109 lines
3.8 KiB
C#
109 lines
3.8 KiB
C#
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");
|
|
}
|
|
|
|
} |