168 lines
6.2 KiB
C#
168 lines
6.2 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using Microsoft.Extensions.Configuration;
|
|
|
|
namespace Sozsoft.Platform.Data.Seeds;
|
|
|
|
/// <summary>
|
|
/// Runtime'da duzenlenebilen seed dosyalarinin klasorunu cozer.
|
|
/// <para>
|
|
/// Kod ile birlikte versiyonlanan sabit seed'ler (DbMigrator projesindeki *Data.json dosyalari)
|
|
/// buraya dahil degildir; onlar kendi projelerinin ciktisinda kalir.
|
|
/// </para>
|
|
/// <para>
|
|
/// Klasor bilincli olarak hicbir projenin icinde degildir: depoda <c>configs/seeds</c> altinda durur ve
|
|
/// konteynere bind mount ile baglanir. Boylece bir seed dosyasi degistiginde ne api ne de migrator
|
|
/// imaji yeniden derlenir; deploy sirasindaki <c>git pull</c> yeterlidir. Ayni klasor File Manager
|
|
/// uzerinden de duzenlenebildigi icin yapilan degisiklik dogrudan host diskinde kalici olur.
|
|
/// </para>
|
|
/// <para>
|
|
/// Klasor duzeni CDN ile ayni kapsam mantigini izler — once kapsam, sonra icerik turu:
|
|
/// <code>
|
|
/// seeds/
|
|
/// host/ → host (varsayilan) veritabani kapsami
|
|
/// crud/
|
|
/// wizard/
|
|
/// data/
|
|
/// sql/ → SQL Server saglayicisi
|
|
/// object/ → nesne olusturulur/guncellenir
|
|
/// execute/ → nesne olusturulur, ayrica tum migration'lar bitince calistirilir
|
|
/// postgres/ → PostgreSQL saglayicisi
|
|
/// object/
|
|
/// execute/
|
|
/// tenants/
|
|
/// {tenantId}/ → her tenant kendi klasorunde
|
|
/// crud/ wizard/ data/ sql/{object,execute}/ postgres/{object,execute}/
|
|
/// </code>
|
|
/// </para>
|
|
/// <para>
|
|
/// Cozum sirasi:
|
|
/// 1) <c>App:SeedsPath</c> ayari (konteynerde mount noktasi),
|
|
/// 2) calisma dizininden yukari dogru <c>configs/seeds</c> aramasi (local gelistirme),
|
|
/// 3) calisma dizininin altindaki <c>Seeds</c> klasoru (son care).
|
|
/// </para>
|
|
/// </summary>
|
|
public static class SeedPathResolver
|
|
{
|
|
public const string ConfigurationKey = "App:SeedsPath";
|
|
|
|
/// <summary>Host veritabani kapsamindaki seed'lerin kok klasoru.</summary>
|
|
public const string HostFolder = "host";
|
|
|
|
/// <summary>Tenant kapsamindaki seed'lerin kok klasoru; altinda tenant Id'si ile klasorler bulunur.</summary>
|
|
public const string TenantsFolder = "tenants";
|
|
|
|
/// <summary>SQL Server saglayicisinin script klasoru.</summary>
|
|
public const string SqlFolder = "sql";
|
|
|
|
/// <summary>PostgreSQL saglayicisinin script klasoru.</summary>
|
|
public const string PostgresFolder = "postgres";
|
|
|
|
/// <summary>Yalnizca olusturulan/guncellenen nesne scriptleri.</summary>
|
|
public const string ObjectFolder = "object";
|
|
|
|
/// <summary>Olusturulan, ayrica tum migration'lar bittikten sonra calistirilan scriptler.</summary>
|
|
public const string ExecuteFolder = "execute";
|
|
|
|
/// <summary>Wizard'in urettigi konfigurasyon dosyalari.</summary>
|
|
public const string WizardFolder = "wizard";
|
|
|
|
/// <summary>Crud endpoint konfigurasyon dosyalari.</summary>
|
|
public const string CrudFolder = "crud";
|
|
|
|
/// <summary>Liste verisinin aynalandigi seed dosyalari (<c>data/{ListFormCode}.json</c>).</summary>
|
|
public const string DataFolder = "data";
|
|
|
|
/// <summary>Bir ListForm icin varsayilan veri seed dosyasinin kapsam klasorune gore goreli yolu.</summary>
|
|
public static string GetDataFilePath(string listFormCode)
|
|
{
|
|
return $"{DataFolder}/{listFormCode}.json";
|
|
}
|
|
|
|
private const string RepositorySeedsFolder = "seeds";
|
|
private const string RepositoryConfigsFolder = "configs";
|
|
private const string FallbackFolderName = "Seeds";
|
|
|
|
/// <summary>Seed kok klasorunun tam yolunu dondurur. Klasorun var olmasi garanti edilmez.</summary>
|
|
public static string GetRootPath(IConfiguration? configuration)
|
|
{
|
|
var configuredPath = configuration?[ConfigurationKey];
|
|
if (!string.IsNullOrWhiteSpace(configuredPath))
|
|
{
|
|
return Path.GetFullPath(configuredPath);
|
|
}
|
|
|
|
var repositoryPath = FindRepositorySeedsPath();
|
|
if (repositoryPath != null)
|
|
{
|
|
return repositoryPath;
|
|
}
|
|
|
|
return Path.Combine(Directory.GetCurrentDirectory(), FallbackFolderName);
|
|
}
|
|
|
|
/// <summary>Seed kok klasorunun altindaki bir alt yolu dondurur.</summary>
|
|
public static string GetPath(IConfiguration? configuration, params string[] subPaths)
|
|
{
|
|
var path = GetRootPath(configuration);
|
|
|
|
foreach (var subPath in subPaths)
|
|
{
|
|
path = Path.Combine(path, subPath);
|
|
}
|
|
|
|
return path;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Kapsam klasorunun (host ya da ilgili tenant) altindaki yolu dondurur.
|
|
/// <paramref name="tenantId"/> null ise <c>host/</c>, aksi halde <c>tenants/{tenantId}/</c> kullanilir.
|
|
/// </summary>
|
|
public static string GetScopePath(IConfiguration? configuration, Guid? tenantId, params string[] subPaths)
|
|
{
|
|
return GetPath(configuration, BuildScopeSubPaths(tenantId, subPaths));
|
|
}
|
|
|
|
/// <summary>Kapsam klasorunun seed koküne gore goreli adi (<c>host</c> ya da <c>tenants/{tenantId}</c>).</summary>
|
|
public static string GetScopeFolderName(Guid? tenantId)
|
|
{
|
|
return tenantId == null
|
|
? HostFolder
|
|
: $"{TenantsFolder}/{tenantId.Value}";
|
|
}
|
|
|
|
/// <summary>Aktif veritabani saglayicisina karsilik gelen script klasorunun adi.</summary>
|
|
public static string GetProviderFolderName(bool isPostgreSql)
|
|
{
|
|
return isPostgreSql ? PostgresFolder : SqlFolder;
|
|
}
|
|
|
|
private static string[] BuildScopeSubPaths(Guid? tenantId, string[] subPaths)
|
|
{
|
|
var scopeSegments = tenantId == null
|
|
? new[] { HostFolder }
|
|
: new[] { TenantsFolder, tenantId.Value.ToString() };
|
|
|
|
return scopeSegments.Concat(subPaths ?? Array.Empty<string>()).ToArray();
|
|
}
|
|
|
|
/// <summary>Calisma dizininden yukari dogru cikarak depodaki configs/seeds klasorunu arar.</summary>
|
|
private static string? FindRepositorySeedsPath()
|
|
{
|
|
var dir = new DirectoryInfo(Directory.GetCurrentDirectory());
|
|
|
|
while (dir != null)
|
|
{
|
|
var candidate = Path.Combine(dir.FullName, RepositoryConfigsFolder, RepositorySeedsFolder);
|
|
if (Directory.Exists(candidate))
|
|
{
|
|
return candidate;
|
|
}
|
|
|
|
dir = dir.Parent;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|