/// <inheritdoc /> public async Task MigrateAsync(IDatabaseContext ctx) { var dbFolder = GetDatabaseMigrationsFolder(); var migrationsRootFolder = Path.Combine(_assemblyService.GetExecutingAssemblyRootPath(), "SqlScripts/Migrations", dbFolder); var migrationFiles = _fileService.GetFiles(migrationsRootFolder, "*.migration.sql").OrderBy(f => f); foreach (var file in migrationFiles) { var fileBaseName = Path.GetFileName(file).Split('.').First(); var checkFileName = $"{fileBaseName}.check.sql"; var checkFilePath = Path.Combine(migrationsRootFolder, checkFileName); if (!_fileService.FileExists(checkFilePath)) { throw new InvalidOperationException($"Could not find file {checkFilePath}"); } // The check script will be loaded. It is expected that the script returns an 1 or higher if the migration should NOT be executed and a "0" if the migration SHOULD be executed. var checkScript = _fileService.ReadAllText(checkFilePath); _logger.LogDebug($"Checking file {checkFileName}."); var checkResult = await ctx.ExecuteScalarAsync <int>(checkScript); if (checkResult > 0) { _logger.LogDebug($"Result of {checkFileName} is {checkResult}, so migration will not be executed."); } else { _logger.LogDebug($"Result of {checkFileName} is {checkResult}, so migration {file} will be executed."); var migrationScript = _fileService.ReadAllText(file); await ctx.ExecuteAsync(migrationScript); } } }
/// <inheritdoc /> public async Task <StubResponseWriterResultModel> WriteToResponseAsync(StubModel stub, ResponseModel response) { var imgDefinition = stub.Response?.Image; if (imgDefinition == null || imgDefinition.Type == ResponseImageType.NotSet) { return(StubResponseWriterResultModel.IsNotExecuted(GetType().Name)); } var stubImage = stub.Response.Image; response.Headers.AddOrReplaceCaseInsensitive("Content-Type", stubImage.ContentTypeHeaderValue); var cacheFilePath = Path.Combine(_fileService.GetTempPath(), $"{stubImage.Hash}.bin"); byte[] bytes; if (_fileService.FileExists(cacheFilePath)) { bytes = _fileService.ReadAllBytes(cacheFilePath); } else { var collection = new FontCollection(); collection.Install(Path.Combine(_assemblyService.GetExecutingAssemblyRootPath(), "Manrope-Regular.ttf")); const string fontFamilyName = "Manrope"; if (!collection.TryFind(fontFamilyName, out var family)) { throw new RequestValidationException($"Font family '{fontFamilyName}' not found!"); } using var image = new Image <Rgba32>(stubImage.Width, stubImage.Height); var font = new Font(family, stubImage.FontSize); var parsedColor = Color.ParseHex(stubImage.BackgroundColor); var polygon = new Rectangle(0, 0, stubImage.Width, stubImage.Height); var fontColor = !string.IsNullOrWhiteSpace(stubImage.FontColor) ? Color.ParseHex(stubImage.FontColor) : parsedColor.InvertColor(); image.Mutate(i => i .Fill(parsedColor, polygon) .ApplyScalingWaterMark(font, stubImage.Text, fontColor, 5, stubImage.WordWrap)); using var ms = new MemoryStream(); switch (stubImage.Type) { case ResponseImageType.Bmp: await image.SaveAsBmpAsync(ms); break; case ResponseImageType.Gif: await image.SaveAsGifAsync(ms); break; case ResponseImageType.Jpeg: await image.SaveAsJpegAsync(ms, new JpegEncoder { Quality = stubImage.JpegQuality }); break; default: await image.SaveAsPngAsync(ms); break; } bytes = ms.ToArray(); _fileService.WriteAllBytes(cacheFilePath, bytes); } response.Body = bytes; return(StubResponseWriterResultModel.IsExecuted(GetType().Name)); }