diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c4bcc86..10a5f6a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -49,6 +49,6 @@ jobs: tag: v${{ steps.version.outputs.version }} name: Sheetly v${{ steps.version.outputs.version }} artifacts: nupkg/*.nupkg - bodyFile: RELEASE_NOTES.md + bodyFile: docs/RELEASE_NOTES.md token: ${{ secrets.GITHUB_TOKEN }} skipIfReleaseExists: true diff --git a/README.md b/README.md index d699fd9..8c10ed2 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ -
- Sheetly Logo - - # Sheetly - - **Entity Framework Core for Google Sheets** β€” The familiar ORM experience you love, now for spreadsheets. - - [![NuGet](https://img.shields.io/nuget/v/Sheetly.Core.svg)](https://www.nuget.org/packages/Sheetly.Core/) - [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -
+

+ Sheetly Banner +

+ +

+ + + + +

--- diff --git a/assets/banner.svg b/assets/banner.svg new file mode 100644 index 0000000..546175e --- /dev/null +++ b/assets/banner.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + Sheetly + + + + Entity Framework Core for Google Sheets + + + πŸš€ + diff --git a/assets/icon.png b/assets/icon.png new file mode 100644 index 0000000..bc49536 Binary files /dev/null and b/assets/icon.png differ diff --git a/BREAKING_CHANGES.md b/docs/BREAKING_CHANGES.md similarity index 100% rename from BREAKING_CHANGES.md rename to docs/BREAKING_CHANGES.md diff --git a/RELEASE_NOTES.md b/docs/RELEASE_NOTES.md similarity index 79% rename from RELEASE_NOTES.md rename to docs/RELEASE_NOTES.md index 9ca63e9..bf189c1 100644 --- a/RELEASE_NOTES.md +++ b/docs/RELEASE_NOTES.md @@ -1,4 +1,4 @@ -# πŸŽ‰ Sheetly v1.0.0 β€” Release Notes +# πŸŽ‰ Sheetly v1.0.1 β€” Release Notes ## Entity Framework Core for Google Sheets @@ -6,6 +6,17 @@ --- +## πŸ› What's Fixed in v1.0.1 + +- **CLI banner** β€” EF Core-style terminal output with teal rocket art +- **`OnConfiguring` detection** β€” `dotnet sheetly database update` now reads connection settings directly from `OnConfiguring()`, no `appsettings.json` required +- **Build-first behavior** β€” All CLI commands now build the project before executing (like `dotnet ef`) +- **Version output** β€” Removed git commit hash from `--version` output +- **Brand logo** β€” Added official icon to all NuGet packages +- **CI/CD** β€” GitHub Actions workflows for automatic NuGet publishing + +--- + ## ✨ What's New ### Core Features diff --git a/dotnet-tools.json b/dotnet-tools.json deleted file mode 100644 index b0e38ab..0000000 --- a/dotnet-tools.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "version": 1, - "isRoot": true, - "tools": {} -} \ No newline at end of file diff --git a/icon.png b/icon.png deleted file mode 100644 index b1f6ef2..0000000 Binary files a/icon.png and /dev/null differ diff --git a/samples/Sheetly.Sample/MySheetsContext.cs b/samples/Sheetly.Sample/AppDbContext.cs similarity index 100% rename from samples/Sheetly.Sample/MySheetsContext.cs rename to samples/Sheetly.Sample/AppDbContext.cs diff --git a/samples/Sheetly.Sample/Migrations/20260222142948_InitialCreate.cs b/samples/Sheetly.Sample/Migrations/20260222142948_InitialCreate.cs index 36f8398..6c1c7bf 100644 --- a/samples/Sheetly.Sample/Migrations/20260222142948_InitialCreate.cs +++ b/samples/Sheetly.Sample/Migrations/20260222142948_InitialCreate.cs @@ -1,34 +1,33 @@ using Sheetly.Core.Migrations; -using Sheetly.Core.Migrations.Operations; namespace Sheetly.Sample.Migrations; [Migration("20260222142948_InitialCreate")] public partial class InitialCreate : Migration { - public override void Up(MigrationBuilder builder) - { - // ClassName: Category - builder.CreateTable("Categories", table => table - .Column("Id", c => c.IsPrimaryKey().IsUnique()) - .Column("Name") - ); + public override void Up(MigrationBuilder builder) + { + // ClassName: Category + builder.CreateTable("Categories", table => table + .Column("Id", c => c.IsPrimaryKey().IsUnique()) + .Column("Name") + ); - // ClassName: Product - builder.CreateTable("Products", table => table - .Column("Id", c => c.IsPrimaryKey().IsUnique()) - .Column("Title") - .Column("Price", c => c.IsRequired()) - .Column("Description") - .Column("Stock", c => c.IsRequired()) - .Column("CategoryId", c => c.IsRequired().IsForeignKey("Categories")) - ); + // ClassName: Product + builder.CreateTable("Products", table => table + .Column("Id", c => c.IsPrimaryKey().IsUnique()) + .Column("Title") + .Column("Price", c => c.IsRequired()) + .Column("Description") + .Column("Stock", c => c.IsRequired()) + .Column("CategoryId", c => c.IsRequired().IsForeignKey("Categories")) + ); - } + } - public override void Down(MigrationBuilder builder) - { - builder.DropTable("Products"); - builder.DropTable("Categories"); - } + public override void Down(MigrationBuilder builder) + { + builder.DropTable("Products"); + builder.DropTable("Categories"); + } } diff --git a/samples/Sheetly.Sample/Migrations/AppDbModelSnapshot.cs b/samples/Sheetly.Sample/Migrations/AppDbModelSnapshot.cs index 26f6894..8b27cb2 100644 --- a/samples/Sheetly.Sample/Migrations/AppDbModelSnapshot.cs +++ b/samples/Sheetly.Sample/Migrations/AppDbModelSnapshot.cs @@ -1,149 +1,148 @@ -using System; using Sheetly.Core.Migration; namespace Sheetly.Sample.Migrations; public partial class AppDbModelSnapshot : MigrationSnapshot { - public AppDbModelSnapshot() - { - var snapshot = BuildModel(); - this.Entities = snapshot.Entities; - this.ModelHash = snapshot.ModelHash; - this.Version = snapshot.Version; - this.LastUpdated = snapshot.LastUpdated; - } + public AppDbModelSnapshot() + { + var snapshot = BuildModel(); + this.Entities = snapshot.Entities; + this.ModelHash = snapshot.ModelHash; + this.Version = snapshot.Version; + this.LastUpdated = snapshot.LastUpdated; + } - public static MigrationSnapshot BuildModel() - { - var snapshot = new MigrationSnapshot - { - ModelHash = "bwhvOP7ZTBivUrr39R2aR3SRrkfWllxn7VpK5f1bucg=", - Version = "1.0.0", - LastUpdated = DateTime.Parse("2026-02-22T14:29:48.7373255Z") - }; + public static MigrationSnapshot BuildModel() + { + var snapshot = new MigrationSnapshot + { + ModelHash = "bwhvOP7ZTBivUrr39R2aR3SRrkfWllxn7VpK5f1bucg=", + Version = "1.0.0", + LastUpdated = DateTime.Parse("2026-02-22T14:29:48.7373255Z") + }; - // Category - snapshot.Entities["Categories"] = new EntitySchema - { - TableName = "Categories", - ClassName = "Category", - Namespace = "Sheetly.Sample.Models", - Columns = new List - { - new ColumnSchema - { - Name = "Id", - PropertyName = "Id", - DataType = "Int64", - IsPrimaryKey = true, - IsAutoIncrement = true, - IsForeignKey = false, - ForeignKeyColumn = "Id", - IsNullable = false, - IsRequired = false - }, - new ColumnSchema - { - Name = "Name", - PropertyName = "Name", - DataType = "String", - IsPrimaryKey = false, - IsAutoIncrement = false, - IsForeignKey = false, - ForeignKeyColumn = "Id", - IsNullable = true, - IsRequired = false - } - }, - Relationships = new List() - }; + // Category + snapshot.Entities["Categories"] = new EntitySchema + { + TableName = "Categories", + ClassName = "Category", + Namespace = "Sheetly.Sample.Models", + Columns = new List + { + new ColumnSchema + { + Name = "Id", + PropertyName = "Id", + DataType = "Int64", + IsPrimaryKey = true, + IsAutoIncrement = true, + IsForeignKey = false, + ForeignKeyColumn = "Id", + IsNullable = false, + IsRequired = false + }, + new ColumnSchema + { + Name = "Name", + PropertyName = "Name", + DataType = "String", + IsPrimaryKey = false, + IsAutoIncrement = false, + IsForeignKey = false, + ForeignKeyColumn = "Id", + IsNullable = true, + IsRequired = false + } + }, + Relationships = new List() + }; - // Product - snapshot.Entities["Products"] = new EntitySchema - { - TableName = "Products", - ClassName = "Product", - Namespace = "Sheetly.Sample.Models", - Columns = new List - { - new ColumnSchema - { - Name = "Id", - PropertyName = "Id", - DataType = "Int32", - IsPrimaryKey = true, - IsAutoIncrement = true, - IsForeignKey = false, - ForeignKeyColumn = "Id", - IsNullable = false, - IsRequired = false - }, - new ColumnSchema - { - Name = "Title", - PropertyName = "Title", - DataType = "String", - IsPrimaryKey = false, - IsAutoIncrement = false, - IsForeignKey = false, - ForeignKeyColumn = "Id", - IsNullable = true, - IsRequired = false - }, - new ColumnSchema - { - Name = "Price", - PropertyName = "Price", - DataType = "Decimal", - IsPrimaryKey = false, - IsAutoIncrement = false, - IsForeignKey = false, - ForeignKeyColumn = "Id", - IsNullable = false, - IsRequired = false - }, - new ColumnSchema - { - Name = "Description", - PropertyName = "Description", - DataType = "String", - IsPrimaryKey = false, - IsAutoIncrement = false, - IsForeignKey = false, - ForeignKeyColumn = "Id", - IsNullable = true, - IsRequired = false - }, - new ColumnSchema - { - Name = "Stock", - PropertyName = "Stock", - DataType = "Int32", - IsPrimaryKey = false, - IsAutoIncrement = false, - IsForeignKey = false, - ForeignKeyColumn = "Id", - IsNullable = false, - IsRequired = false - }, - new ColumnSchema - { - Name = "CategoryId", - PropertyName = "CategoryId", - DataType = "Int32", - IsPrimaryKey = false, - IsAutoIncrement = false, - IsForeignKey = true, - ForeignKeyTable = "Categories", - ForeignKeyColumn = "Id", - IsNullable = false, - IsRequired = false - } - }, - Relationships = new List() - }; + // Product + snapshot.Entities["Products"] = new EntitySchema + { + TableName = "Products", + ClassName = "Product", + Namespace = "Sheetly.Sample.Models", + Columns = new List + { + new ColumnSchema + { + Name = "Id", + PropertyName = "Id", + DataType = "Int32", + IsPrimaryKey = true, + IsAutoIncrement = true, + IsForeignKey = false, + ForeignKeyColumn = "Id", + IsNullable = false, + IsRequired = false + }, + new ColumnSchema + { + Name = "Title", + PropertyName = "Title", + DataType = "String", + IsPrimaryKey = false, + IsAutoIncrement = false, + IsForeignKey = false, + ForeignKeyColumn = "Id", + IsNullable = true, + IsRequired = false + }, + new ColumnSchema + { + Name = "Price", + PropertyName = "Price", + DataType = "Decimal", + IsPrimaryKey = false, + IsAutoIncrement = false, + IsForeignKey = false, + ForeignKeyColumn = "Id", + IsNullable = false, + IsRequired = false + }, + new ColumnSchema + { + Name = "Description", + PropertyName = "Description", + DataType = "String", + IsPrimaryKey = false, + IsAutoIncrement = false, + IsForeignKey = false, + ForeignKeyColumn = "Id", + IsNullable = true, + IsRequired = false + }, + new ColumnSchema + { + Name = "Stock", + PropertyName = "Stock", + DataType = "Int32", + IsPrimaryKey = false, + IsAutoIncrement = false, + IsForeignKey = false, + ForeignKeyColumn = "Id", + IsNullable = false, + IsRequired = false + }, + new ColumnSchema + { + Name = "CategoryId", + PropertyName = "CategoryId", + DataType = "Int32", + IsPrimaryKey = false, + IsAutoIncrement = false, + IsForeignKey = true, + ForeignKeyTable = "Categories", + ForeignKeyColumn = "Id", + IsNullable = false, + IsRequired = false + } + }, + Relationships = new List() + }; - return snapshot; - } + return snapshot; + } } diff --git a/src/Sheetly.CLI/Commands/AddCommand.cs b/src/Sheetly.CLI/Commands/AddCommand.cs index 4ee4cc0..73877da 100644 --- a/src/Sheetly.CLI/Commands/AddCommand.cs +++ b/src/Sheetly.CLI/Commands/AddCommand.cs @@ -1,4 +1,4 @@ -ο»Ώusing Sheetly.CLI.Helpers; +using Sheetly.CLI.Helpers; using Sheetly.Core; using Sheetly.Core.Migration; using Sheetly.Core.Migrations; @@ -61,7 +61,6 @@ private async Task ExecuteAsync(string? name, bool noBuild, string? projectPath, // Build current snapshot β€” must include fluent API metadata to match SheetsContext.InitializeAsync var currentSnapshot = SnapshotBuilder.BuildFromContext(contextType, modelBuilder.GetMetadata()); - // Load previous snapshot from C# ModelSnapshot class (EF Core style) string finalPath = Path.Combine(contextProjectDir, outputDir); Directory.CreateDirectory(finalPath); @@ -76,7 +75,6 @@ private async Task ExecuteAsync(string? name, bool noBuild, string? projectPath, previousSnapshot = Activator.CreateInstance(snapshotType) as MigrationSnapshot; } - // Get differences var modelDiffer = new ModelDiffer(); var operations = modelDiffer.GetDifferences(previousSnapshot, currentSnapshot); @@ -87,7 +85,6 @@ private async Task ExecuteAsync(string? name, bool noBuild, string? projectPath, } - // Check for duplicate migration name (same class name, different timestamp) var existingMigration = Directory.GetFiles(finalPath, "*.cs") .Where(f => !f.Contains("ModelSnapshot")) .FirstOrDefault(f => Path.GetFileNameWithoutExtension(f).EndsWith($"_{name}", StringComparison.OrdinalIgnoreCase)); @@ -98,7 +95,6 @@ private async Task ExecuteAsync(string? name, bool noBuild, string? projectPath, return; } - // Generate C# migration file string timestamp = DateTime.UtcNow.ToString("yyyyMMddHHmmss"); string migrationId = $"{timestamp}_{name}"; string targetNamespace = $"{contextType.Namespace}.Migrations"; @@ -106,11 +102,9 @@ private async Task ExecuteAsync(string? name, bool noBuild, string? projectPath, var generator = new CSharpMigrationGenerator(); string migrationCode = generator.GenerateMigration(name, migrationId, targetNamespace, operations); - // Write C# migration file string csharpFileName = $"{migrationId}.cs"; await File.WriteAllTextAsync(Path.Combine(finalPath, csharpFileName), migrationCode, ct); - // Generate ModelSnapshot.cs (EF Core style - C# only, no JSON!) var snapshotGenerator = new ModelSnapshotGenerator(); string snapshotCode = snapshotGenerator.GenerateModelSnapshot( currentSnapshot, diff --git a/src/Sheetly.CLI/Commands/RemoveCommand.cs b/src/Sheetly.CLI/Commands/RemoveCommand.cs index ff83882..7f74355 100644 --- a/src/Sheetly.CLI/Commands/RemoveCommand.cs +++ b/src/Sheetly.CLI/Commands/RemoveCommand.cs @@ -1,4 +1,4 @@ -ο»Ώusing Sheetly.CLI.Helpers; +using Sheetly.CLI.Helpers; using Sheetly.Core.Migration; using Sheetly.Core.Migrations; using Sheetly.Core.Migrations.Design; @@ -41,7 +41,6 @@ private async Task ExecuteAsync(string? projectPath, CancellationToken ct) return; } - // Find last migration type by MigrationAttribute ID (sorted descending) var migrationTypes = assembly.GetExportedTypes() .Where(t => t.GetCustomAttribute() != null) .OrderByDescending(t => t.GetCustomAttribute()!.Id) @@ -56,7 +55,6 @@ private async Task ExecuteAsync(string? projectPath, CancellationToken ct) var lastMigrationType = migrationTypes[0]; string migrationId = lastMigrationType.GetCustomAttribute()!.Id; - // Find the corresponding .cs file on disk var migrationFile = Directory.GetFiles(migrationsDir, "*.cs") .FirstOrDefault(f => !f.Contains("ModelSnapshot") && Path.GetFileNameWithoutExtension(f) == migrationId); @@ -67,7 +65,6 @@ private async Task ExecuteAsync(string? projectPath, CancellationToken ct) return; } - // Load the current snapshot from the compiled assembly string contextName = contextType.Name.Replace("Context", ""); string snapshotClassName = $"{contextName}ModelSnapshot"; string targetNamespace = $"{contextType.Namespace}.Migrations"; @@ -79,17 +76,14 @@ private async Task ExecuteAsync(string? projectPath, CancellationToken ct) var currentSnapshot = Activator.CreateInstance(snapshotType) as MigrationSnapshot ?? throw new Exception("Failed to instantiate ModelSnapshot."); - // Get the Down() operations to know what to revert var lastMigration = Activator.CreateInstance(lastMigrationType) as Migration ?? throw new Exception("Failed to instantiate migration."); var downBuilder = new Sheetly.Core.Migrations.MigrationBuilder(); lastMigration.Down(downBuilder); - // Apply Down operations to produce the previous snapshot state var revertedSnapshot = RevertSnapshot(currentSnapshot, downBuilder.GetOperations()); - // Regenerate ModelSnapshot C# file var generator = new ModelSnapshotGenerator(); string snapshotCode = generator.GenerateModelSnapshot(revertedSnapshot, targetNamespace, contextName); string snapshotFilePath = Path.Combine(migrationsDir, $"{snapshotClassName}.cs"); diff --git a/src/Sheetly.CLI/Commands/UpdateCommand.cs b/src/Sheetly.CLI/Commands/UpdateCommand.cs index d44d4ad..9e8935a 100644 --- a/src/Sheetly.CLI/Commands/UpdateCommand.cs +++ b/src/Sheetly.CLI/Commands/UpdateCommand.cs @@ -78,7 +78,6 @@ private async Task ExecuteAsync(bool noBuild, string? projectPath, CancellationT Console.WriteLine($"πŸš€ Found {pendingMigrations.Count} pending migration(s)."); - // Load snapshot to enrich operations with ClassName / IsAutoIncrement var snapshotType = assembly.GetTypes() .FirstOrDefault(t => t.Name.EndsWith("ModelSnapshot") && t.IsSubclassOf(typeof(MigrationSnapshot))); MigrationSnapshot? currentSnapshot = snapshotType != null diff --git a/src/Sheetly.CLI/Program.cs b/src/Sheetly.CLI/Program.cs index d1d3f9d..f9a5e5a 100644 --- a/src/Sheetly.CLI/Program.cs +++ b/src/Sheetly.CLI/Program.cs @@ -3,9 +3,9 @@ using System.Reflection; var version = Assembly - .GetExecutingAssembly() - .GetCustomAttribute()! - .InformationalVersion; + .GetExecutingAssembly() + .GetCustomAttribute()! + .InformationalVersion; // Root Command RootCommand rootCommand = new("Sheetly CLI - Google Sheets ORM Tool"); diff --git a/src/Sheetly.CLI/Sheetly.CLI.csproj b/src/Sheetly.CLI/Sheetly.CLI.csproj index 5aafdb8..1d6b1bc 100644 --- a/src/Sheetly.CLI/Sheetly.CLI.csproj +++ b/src/Sheetly.CLI/Sheetly.CLI.csproj @@ -9,7 +9,7 @@ dotnet-sheetly dotnet-sheetly - 1.0.1 + 1.0.2 Dotnetolog Muqimjon Mamadaliyev Copyright (c) 2025–2026 Muqimjon Mamadaliyev @@ -27,7 +27,7 @@ - + diff --git a/src/Sheetly.CLI/icon.png b/src/Sheetly.CLI/icon.png new file mode 100644 index 0000000..bc49536 Binary files /dev/null and b/src/Sheetly.CLI/icon.png differ diff --git a/src/Sheetly.CLI/tools/Add-SheetlyMigration.ps1 b/src/Sheetly.CLI/tools/Add-SheetlyMigration.ps1 deleted file mode 100644 index dffc49b..0000000 --- a/src/Sheetly.CLI/tools/Add-SheetlyMigration.ps1 +++ /dev/null @@ -1,21 +0,0 @@ -ο»Ώ<# -.SYNOPSIS - Yangi Sheetly migratsiyasini yaratadi. -.PARAMETER Name - Migratsiya nomi. -#> -param( - [Parameter(Mandatory=$true, Position=0)] - [string]$Name -) - -Write-Host "πŸš€ Sheetly: Yangi migratsiya yaratilmoqda: $Name..." -ForegroundColor Cyan - -# dotnet tool orqali asosiy CLI ni chaqiramiz -dotnet sheetly migrations add $Name - -if ($LASTEXITCODE -eq 0) { - Write-Host "βœ… Migratsiya muvaffaqiyatli yaratildi!" -ForegroundColor Green -} else { - Write-Error "❌ Migratsiya yaratishda xatolik yuz berdi." -} \ No newline at end of file diff --git a/src/Sheetly.CLI/tools/init.ps1 b/src/Sheetly.CLI/tools/init.ps1 deleted file mode 100644 index 2d63d7e..0000000 --- a/src/Sheetly.CLI/tools/init.ps1 +++ /dev/null @@ -1,3 +0,0 @@ -# Export functions when package is loaded in PMC -Import-Module "$PSScriptRoot\Add-SheetlyMigration.ps1" -Force -Set-Alias -Name add-sheetly-migration -Value Add-SheetlyMigration -Scope Global \ No newline at end of file diff --git a/src/Sheetly.Core/Migration/MigrationBuilder.cs b/src/Sheetly.Core/Migration/MigrationBuilder.cs index 6b83c97..5e34d13 100644 --- a/src/Sheetly.Core/Migration/MigrationBuilder.cs +++ b/src/Sheetly.Core/Migration/MigrationBuilder.cs @@ -64,12 +64,6 @@ public static MigrationSnapshot BuildFromContext(Type contextType, ModelBuilder MaxLength = prop.GetCustomAttribute()?.Length }; - // Store custom attributes for legacy compatibility (though deprecated) - var attrs = prop.GetCustomAttributes().Select(a => a.GetType().Name.Replace("Attribute", "")).ToList(); -#pragma warning disable CS0618 // Intentional use of deprecated property for backward compatibility - if (attrs.Count != 0) column.Attributes = string.Join(", ", attrs.Select(a => $"[{a}]")); -#pragma warning restore CS0618 - if (prop.Name.EndsWith("Id", StringComparison.OrdinalIgnoreCase) && !column.IsPrimaryKey) { var relatedName = prop.Name.Substring(0, prop.Name.Length - 2); diff --git a/src/Sheetly.Core/Migration/MigrationSnapshot.cs b/src/Sheetly.Core/Migration/MigrationSnapshot.cs index 11c0fa2..fa2f548 100644 --- a/src/Sheetly.Core/Migration/MigrationSnapshot.cs +++ b/src/Sheetly.Core/Migration/MigrationSnapshot.cs @@ -64,18 +64,6 @@ public class ColumnSchema // Additional metadata public string? Comment { get; set; } public string? Collation { get; set; } - - // Legacy support - [Obsolete("Use specific constraint properties instead")] - public string? Attributes { get; set; } - - // Deprecated property name - use ForeignKeyTable - [Obsolete("Use ForeignKeyTable instead")] - public string? RelatedTable - { - get => ForeignKeyTable; - set => ForeignKeyTable = value; - } } /// diff --git a/src/Sheetly.Core/Migrations/MigrationAttribute.cs b/src/Sheetly.Core/Migrations/MigrationAttribute.cs index a5acb3a..2447f21 100644 --- a/src/Sheetly.Core/Migrations/MigrationAttribute.cs +++ b/src/Sheetly.Core/Migrations/MigrationAttribute.cs @@ -1,13 +1,8 @@ namespace Sheetly.Core.Migrations; [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] -public class MigrationAttribute : Attribute +public class MigrationAttribute(string id) : Attribute { /// Format: yyyyMMddHHmmss_MigrationName - public string Id { get; } - - public MigrationAttribute(string id) - { - Id = id ?? throw new ArgumentNullException(nameof(id)); - } + public string Id { get; } = id ?? throw new ArgumentNullException(nameof(id)); } diff --git a/src/Sheetly.Core/Sheetly.Core.csproj b/src/Sheetly.Core/Sheetly.Core.csproj index 44afc69..9d0af79 100644 --- a/src/Sheetly.Core/Sheetly.Core.csproj +++ b/src/Sheetly.Core/Sheetly.Core.csproj @@ -5,7 +5,7 @@ enable Sheetly.Core - 1.0.1 + 1.0.2 Dotnetolog Muqimjon Mamadaliyev Copyright (c) 2025–2026 Muqimjon Mamadaliyev @@ -23,7 +23,7 @@ - + diff --git a/src/Sheetly.Core/SheetsContext.cs b/src/Sheetly.Core/SheetsContext.cs index 2790c96..d9ee563 100644 --- a/src/Sheetly.Core/SheetsContext.cs +++ b/src/Sheetly.Core/SheetsContext.cs @@ -132,7 +132,6 @@ private async Task> GetAppliedMigrationsFromRemoteAsync() var rows = await Provider.GetAllRowsAsync(HistoryTable); - // Skip header row (index 0), get MigrationId from first column return rows.Skip(1) .Where(r => r.Count > 0 && !string.IsNullOrEmpty(r[0]?.ToString())) .Select(r => r[0]!.ToString()!) diff --git a/src/Sheetly.Core/SheetsSet.cs b/src/Sheetly.Core/SheetsSet.cs index 082831f..822758b 100644 --- a/src/Sheetly.Core/SheetsSet.cs +++ b/src/Sheetly.Core/SheetsSet.cs @@ -1,4 +1,4 @@ -ο»Ώusing Sheetly.Core.Abstractions; +using Sheetly.Core.Abstractions; using Sheetly.Core.Mapping; using Sheetly.Core.Migration; using System.Collections; @@ -129,7 +129,6 @@ private async Task ProcessIncludes(List entities) relatedSchema = allSchemas.Values.FirstOrDefault(s => s.ClassName == targetType.Name); if (relatedSchema == null) continue; } - // Always use the schema's actual table name for provider calls var actualTableName = relatedSchema.TableName; if (!loadedTables.TryGetValue(actualTableName, out List? value)) @@ -257,7 +256,7 @@ private async Task GetAndIncrementIdFromCentralSchema(string tableName, int throw new Exception("__SheetlySchema__ table not found."); var rows = await provider.GetAllRowsAsync(SchemaTable); - int schemaIdValue = 0; // Value from __SheetlySchema__ + int schemaIdValue = 0; var pkPropertyName = schema.Columns.First(c => c.IsPrimaryKey).PropertyName; int schemaRowIndex = -1; @@ -293,16 +292,12 @@ private async Task GetAndIncrementIdFromCentralSchema(string tableName, int } } - // Use the maximum of schema value and actual data int currentId = Math.Max(schemaIdValue, maxIdInSheet); - // Next available ID (increment from max) int nextId = currentId + 1; - // Calculate what schema should store after this operation int newSchemaValue = nextId + count - 1; - // Update schema with new value if (schemaRowIndex >= 0) { await provider.UpdateValueAsync(SchemaTable, $"AC{schemaRowIndex + 1}", newSchemaValue); diff --git a/src/Sheetly.DependencyInjection/Sheetly.DependencyInjection.csproj b/src/Sheetly.DependencyInjection/Sheetly.DependencyInjection.csproj index ab5963a..5a7a456 100644 --- a/src/Sheetly.DependencyInjection/Sheetly.DependencyInjection.csproj +++ b/src/Sheetly.DependencyInjection/Sheetly.DependencyInjection.csproj @@ -5,7 +5,7 @@ enable Sheetly.DependencyInjection - 1.0.1 + 1.0.2 Dotnetolog Muqimjon Mamadaliyev Copyright (c) 2025–2026 Muqimjon Mamadaliyev @@ -23,7 +23,7 @@ - + diff --git a/src/Sheetly.Google/Sheetly.Google.csproj b/src/Sheetly.Google/Sheetly.Google.csproj index 3b9c76a..112f8ab 100644 --- a/src/Sheetly.Google/Sheetly.Google.csproj +++ b/src/Sheetly.Google/Sheetly.Google.csproj @@ -5,7 +5,7 @@ enable Sheetly.Google - 1.0.1 + 1.0.2 Dotnetolog Muqimjon Mamadaliyev Copyright (c) 2025–2026 Muqimjon Mamadaliyev @@ -23,7 +23,7 @@ - +