Import from internal git

This commit is contained in:
2025-10-11 13:08:09 +02:00
commit 97aaa715dc
175 changed files with 7014 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
using Core.Dto.Settings;
using Core.Interfaces;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Generator.DataSource;
/// <summary>
/// Provides some methods to load json objects from a json data source
/// </summary>
public class JsonLoader : IDataSourceLoader
{
private readonly IServiceCollection _services;
private readonly IConfiguration _configuration;
public JsonLoader(IServiceCollection services, IConfiguration configuration)
{
_services = services;
_configuration = configuration;
}
/// <summary>
/// Load data that can be found in appsettings.json
/// </summary>
public void LoadAppsettings()
{
_services.AddOptions<EnvironmentConfigDto>().Bind(_configuration.GetSection("Environment"));
_services.AddOptions<DefaultArgumentsConfigDto>().Bind(_configuration.GetSection("DefaultArguments"));
_services.AddOptions<GeneralConfigDto>().Bind(_configuration.GetSection("General"));
_services.AddOptions<PublishConfigDto>().Bind(_configuration.GetSection("Publish"));
_services.AddOptions<CredentialsConfigDto>().Bind(_configuration.GetSection("Credentials"));
_services.AddOptions<DockerImagesConfigDto>().Bind(_configuration.GetSection("DockerImages"));
_services.AddOptions<JavaConfigDto>().Bind(_configuration.GetSection("Java"));
_services.AddOptions<DotnetConfigDto>().Bind(_configuration.GetSection("Dotnet"));
_services.AddOptions<JavascriptConfigDto>().Bind(_configuration.GetSection("Javascript"));
_services.AddOptions<OpenApiConfigDto>().Bind(_configuration.GetSection("OpenApi"));
_services.AddOptions<TemplatesConfigDto>().Bind(_configuration.GetSection("Templates"));
}
}

View File

@@ -0,0 +1,64 @@
using Core;
using Core.Dto;
using Core.Dto.Settings;
using Core.Settings;
using Generator.Mappers;
using Microsoft.Extensions.Options;
namespace Generator.DataSource.Settings;
/// <summary>
/// This class is intended to encapsulate configurations objects
/// </summary>
public class ConfigManager
{
private readonly ArgumentsDto _args;
private readonly EnvironmentConfigDto _env;
private readonly DefaultArgumentsConfigDto _defArgs;
private readonly GeneralConfigDto _general;
public readonly DockerImagesConfigDto DockerImages;
public readonly TemplatesConfigDto Templates;
public readonly PublishConfigDto Publish;
public readonly CredentialsConfigDto Credentials;
public readonly DotnetConfigDto Dotnet;
public readonly JavaConfigDto Java;
public readonly JavascriptConfigDto Javascript;
public readonly OpenApiConfigDto OpenApi;
public ConfigManager(
ArgumentsDto args,
IOptions<EnvironmentConfigDto> env,
IOptions<DefaultArgumentsConfigDto> defArgs,
IOptions<GeneralConfigDto> general,
IOptions<PublishConfigDto> publish,
IOptions<CredentialsConfigDto> creds,
IOptions<DockerImagesConfigDto> images,
IOptions<DotnetConfigDto> dotnet,
IOptions<JavaConfigDto> java,
IOptions<JavascriptConfigDto> javascript,
IOptions<OpenApiConfigDto> openapi,
IOptions<TemplatesConfigDto> templates)
{
_args = args;
_env = env.Value;
Publish = publish.Value;
Credentials = creds.Value;
_defArgs = defArgs.Value;
_general = general.Value;
DockerImages = images.Value;
Templates = templates.Value;
Dotnet = dotnet.Value;
Java = java.Value;
Javascript = javascript.Value;
OpenApi = openapi.Value;
}
public BaseConfig GetBase() => _env.Map();
public DefaultArgumentsConfig GetDefArgs() => _defArgs.Map(_args);
public GeneralConfig GetGeneral() => _general.Map();
public Location GetRoot(bool isLocal) => isLocal ? GetBase().LocalRoot : GetBase().DockerRoot;
}

View File

@@ -0,0 +1,109 @@
using System.Text.RegularExpressions;
using Core;
using Core.Dto.Yaml;
using Core.Exceptions;
using Core.Helpers;
using Core.Yaml;
using Generator.Mappers;
using Newtonsoft.Json;
using YamlDotNet.Serialization;
namespace Generator.DataSource.Yaml;
public class OpenApiYamlExtractor
{
/// <summary>
/// Retrieves an openapi-formatted yaml at a specific location
/// </summary>
/// <param name="path">file location</param>
/// <returns></returns>
public OpenApiYaml ExtractNode(string path)
{
var text = PathHelper.TextFrom(path);
var deserializer = new DeserializerBuilder()
.IgnoreUnmatchedProperties()
.Build();
var dto = deserializer.Deserialize<OpenApiYamlDto>(text);
return dto.ToModel(path);
}
/// <summary>
/// Loads all configs that can be found in the config file located at the given path
/// </summary>
/// <param name="configPath">Given path</param>
/// <returns></returns>
/// <exception cref="InvalidOperationException">When config file couldn't has been deserialize</exception>
/// <exception cref="ConfigException">When the given path does not exists</exception>
public Dictionary<string, YamlConfig> LoadConfigs(string configPath)
{
try
{
var json = PathHelper.TextFrom(configPath);
var configDto = JsonConvert.DeserializeObject<SpecConfigDto>(json);
return (configDto ?? throw new InvalidOperationException()).Map();
}
catch (FileNotFoundException)
{
throw new ConfigException($"No config file found at {configPath}. Fix it or i'll never generate anything for you");
}
}
/// <summary>
/// Extract all scoped references of a specification file. In other words, this will extracts all references
/// between the given spec file and the closer reference-related schemas, including paths and params files
/// </summary>
/// <param name="filePath">Given file path</param>
/// <returns></returns>
public ISet<string> ExtractScopedRefs(string filePath) => ExtractRefs(filePath, false, new HashSet<string>());
/// <summary>
/// Extract all possibles references from a given specification file
/// </summary>
/// <param name="filePath">Given file path</param>
/// <returns></returns>
public ISet<string> ExtractAllRefs(string filePath) => ExtractRefs(filePath, true, new HashSet<string>());
private ISet<string> ExtractRefs(string filePath, bool deepSearch, ISet<string> refs)
{
const string pattern = """(\$ref):\s{1}['|"](.+)['|"]""";
var text = PathHelper.TextFrom(filePath);
var matches = Regex.Matches(text, pattern);
foreach (Match m in matches)
{
var rawReference = m.Groups[2].Value;
var absolutePath = AbsolutePathFromRef(filePath, rawReference);
//If path references itself or circular dependency is detected
if (absolutePath == string.Empty || refs.Contains(absolutePath)) continue;
if (!deepSearch && IsSchema(absolutePath))
{
refs.Add(absolutePath);
continue;
}
var subRefs = ExtractRefs(absolutePath, deepSearch, refs);
refs.UnionWith(subRefs);
refs.Add(absolutePath);
}
return refs;
}
private string AbsolutePathFromRef(string relative, string reference)
{
var result = PathHelper.GetFolder(relative) + reference;
var r = result.Split("#")[0];
return r[^1].Equals('/') ? string.Empty : PathHelper.AbsolutePath(r);
}
private bool IsSchema(string path)
{
var l = new Location(path);
return l.LastElement().Contains("schemas");
}
}

View File

@@ -0,0 +1,164 @@
using System.Text;
using Core;
using Core.Helpers;
using Core.Yaml;
using MoreLinq;
namespace Generator.DataSource.Yaml;
public class YamlBuilder
{
private OpenApiYaml _file;
private bool _isSubNode;
private readonly string _configIdentifier;
private readonly Dictionary<string, YamlConfig> _configs;
private readonly OpenApiYamlExtractor _extractor;
public YamlBuilder(string filePath, string configIdentifier)
{
_isSubNode = false;
_configIdentifier = configIdentifier;
_file = new OpenApiYaml(filePath);
_configs = new Dictionary<string, YamlConfig>();
_extractor = new OpenApiYamlExtractor();
}
/// <summary>
/// Adds all raw references to the object to build
/// </summary>
public void AddReferences()
{
var scopedRefs = _extractor.ExtractScopedRefs(_file.Location.ToString());
var allRefs = _extractor.ExtractAllRefs(_file.Location.ToString());
_file.ScopedRefs = scopedRefs;
_file.OutScopedRefs = allRefs;
_file.OutScopedRefs.ExceptWith(scopedRefs);
}
/// <summary>
/// Attributes the dedicated config file to the object to build
/// </summary>
public void SelectConfig()
{
if (_configs.ContainsKey(_file.Location.GetFileName()))
{
_file.Config = _configs[_file.Location.GetFileName()];
}
else
{
throw new Exception($"{_file.Location} cannot be generated. You either made a typo " +
$"or forgot to register file in {GetConfig(_file.Location)}");
}
}
/// <summary>
/// Adds all built schemas to the object to build
/// </summary>
public void AddSchema()
{
using var enumerator = _file.ScopedRefs.GetEnumerator();
while (enumerator.MoveNext())
{
var loc = new Location(enumerator.Current);
var fileName = loc.GetFileName();
if(!_configs.ContainsKey(fileName)) continue;
var schema = _isSubNode ?
_extractor.ExtractNode(loc.ToString())
: CreateSubNode(loc.ToString());
schema.Config = _configs[fileName];
_file.ReferencedSchemas.Add(schema);
}
}
/// <summary>
/// Adds the models that will be ignored to the object to build
/// </summary>
public void AddIgnoredModels()
{
foreach (var reference in _file.Refs)
{
var loc = new Location(reference);
var schema = _extractor.ExtractNode(loc.ToString());
_file.IgnoredModels.UnionWith(schema.Models);
}
}
/// <summary>
/// Simply output the object to build
/// </summary>
/// <returns></returns>
public OpenApiYaml Create() => _file;
/// <summary>
/// Loads the object to build
/// </summary>
public void LoadSpec()
{
_file = _extractor.ExtractNode(_file.Location.ToString());
_file.Openapi = _file.Openapi;
if (_file.Info != null) _file.Info = new Dictionary<string, object>(_file.Info);
_file.Tags = _file.Tags == null ? new List<object>() : [.._file.Tags];
}
/// <summary>
/// Load all the found config files into the builder
/// </summary>
public void LoadConfigs()
{
LoadConfig(_file.Location);
foreach (var reference in _file.Refs) LoadConfig(new Location(reference));
}
private void LoadConfig(Location path)
{
var configPath = GetConfig(path)?.ToString();
if (configPath == null || _configs.ContainsKey(path.GetFileName())) return;
_extractor.LoadConfigs(configPath)
.ForEach(c => _configs.TryAdd(c.Key, c.Value));
}
private void SetForSubNode() => _isSubNode = true;
private OpenApiYaml CreateSubNode(string path)
{
var yamlBuilder = new YamlBuilder(path, _configIdentifier);
yamlBuilder.SetForSubNode();
yamlBuilder.LoadSpec();
yamlBuilder.AddReferences();
yamlBuilder.LoadConfigs();
yamlBuilder.AddSchema();
yamlBuilder.AddIgnoredModels();
return yamlBuilder.Create();
}
private Location? GetConfig(Location loc)
{
var spec = loc.GetFolder();
var pathItems = loc.Path.Split(['/', '\\']);
pathItems[^1] = spec + _configIdentifier;
var builder = new StringBuilder();
builder.AppendJoin("/", pathItems);
var configPath = builder.ToString();
try
{
PathHelper.CheckPathValidity(configPath);
}
catch (FileNotFoundException)
{
return null;
}
return new Location(configPath);
}
}

View File

@@ -0,0 +1,36 @@
using Core;
using Core.Yaml;
using Generator.Daos;
namespace Generator.DataSource.Yaml;
public class YamlDirector
{
private readonly OpenApiDao _openApiDao;
public YamlDirector(OpenApiDao openApiDao)
{
_openApiDao = openApiDao;
}
/// <summary>
/// Build a yaml object lmao what do you want me to say ? All the information's are in the method signature
/// </summary>
/// <param name="specPath"></param>
/// <returns></returns>
public OpenApiYaml BuildYaml(string specPath)
{
var openApiConfig = _openApiDao.GetOpenApi(true, specPath);
var yamlBuilder = new YamlBuilder(openApiConfig.SpecFile.ToString(), openApiConfig.ConfigIdentifier);
yamlBuilder.LoadSpec();
yamlBuilder.AddReferences();
yamlBuilder.LoadConfigs();
yamlBuilder.SelectConfig();
yamlBuilder.AddSchema();
yamlBuilder.AddIgnoredModels();
return yamlBuilder.Create();
}
}