-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Dynamic Content Routing and Storage System #140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #140 +/- ##
=======================================
Coverage 76.36% 76.36%
=======================================
Files 16 16
Lines 165 165
Branches 24 24
=======================================
Hits 126 126
Misses 33 33
Partials 6 6 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
32c38c1 to
d7124d1
Compare
Implements TASK-001 to TASK-017 of Phase 1 (Core Interfaces and Abstractions). Added: - ContentDescriptor base class with required Title, Slug, PublishedDate - ResolvedContent<TDescriptor> with init-only properties - Routing interfaces: IRoutingBuilder, IRootConfiguration, ICultureConfiguration, ISegmentConfiguration, IPageConfiguration - Pagination: IPaginationConfiguration with PageSize and UrlFormat - Metadata: IMetadataConfiguration for custom fields - Storage: IContentStorageProvider, IAssetStorageProvider, IContentStorageBuilder, IAssetStorageBuilder, IFileSystemStorageOptions, IPublishingService - Enums: CultureCanonical (WithoutPrefix, WithPrefix), PaginationUrlFormat (Numeric, Prefixed) - Phase 1 unit tests (21 tests) validating all contracts Quality gates: - Build: successful - Tests: 121 tests passed - XML docs: present on all public APIs - CancellationToken parameter standardized: ct -> cancellationToken - Constraints: DateTimeOffset, English, no regions, .NET 10/C#13
…plementation plan
Implements TASK-018, TASK-019, TASK-020, TASK-021, TASK-022, TASK-023, TASK-024, TASK-025, TASK-026, TASK-027
Implemented comprehensive Markdown and YAML frontmatter parsing pipeline: **Package Management:** - Added Markdig 0.41.0 for Markdown rendering with advanced extensions - Added YamlDotNet 16.3.0 for YAML frontmatter parsing (camelCase convention) - Updated Directory.Packages.props and ForgingBlazor.csproj references **Parsing Components:** - FrontmatterParser: Static class extracting YAML between --- delimiters - MarkdownRenderer: Static class with Markdig pipeline (advanced extensions, tables, task lists, auto links, emoji) - ContentParser: Static orchestrator coordinating all parsing steps **Validation & Mapping:** - ContentValidationException: Public exception with parameterless constructor for CA1032 compliance - FrontmatterValidation: Static validation for required fields (title, slug, publishedDate), slug format, DateTimeOffset parsing with InvariantCulture - ContentDescriptorFactory: Static reflection-based factory mapping frontmatter properties with case-insensitive matching, type conversion for DateTimeOffset/bool/enum, nullable handling **Quality Assurance:** - All classes use CultureInfo.InvariantCulture for date/bool parsing (CA1305 compliance) - Static classes for utility methods (CA1822, S1118, S2325 compliance) - Null validation via ArgumentNullException.ThrowIfNull - Build: Successful without warnings or errors - Tests: All 147 tests passing Refs: REQ-CNT-001 through REQ-CNT-005, TASK-028 through TASK-037
Implements TASK-047 to TASK-051: - Add CultureResolver for parsing cultures from two-letter codes, LCIDs, and full formats - Add CultureFallbackChain implementing de-DE → de → en-US → en fallback hierarchy - Add CultureContentLocator for locating content files using culture fallback - Add ContentLookupPath record for content file paths with culture suffixes - Add CultureValidation for startup validation of culture configuration - Refactor all test assertions from ThrowsExactly to Assert.Throws pattern - Use parameterName overload for ArgumentException assertions Refs: TASK-047, TASK-048, TASK-049, TASK-050, TASK-051
Implements TASK-052 to TASK-057: - Add RouteDefinition record for route metadata - Add RouteRegistry for thread-safe route storage - Add RouteResolver for path-to-route matching - Add CanonicalUrlGenerator for culture-aware canonical URLs - Add CanonicalLinkComponent.razor for canonical link tags - Add PaginationSettings record as Phase 7 prerequisite - Add comprehensive unit tests for all components Refs: TASK-052, TASK-053, TASK-054, TASK-056, TASK-057
…unnecessary async/await feat(dependencies): upgrade bunit package to version 1.34.0 refactor(routing): simplify method implementations and improve readability
- Use full culture name (de-DE) instead of two-letter code (de) in CanonicalUrlGenerator - Fix CultureFallbackChain to always include requested culture first - Handle trailing slash correctly for root paths with culture prefix All 306 tests now passing
Implements TASK-044 to TASK-046: - FileSystemWatcherService with 300ms debounced file change detection - ContentCacheService with culture-aware caching (30min sliding, 4h absolute expiration) - ContentCacheInvalidationHandler connecting file system events to cache invalidation All 315 tests passing (+9 new tests for caching and file watching). Refs: TASK-044, TASK-045, TASK-046
Implements TASK-059 to TASK-062: - Add PaginatedResult<T> wrapper class for paginated collections - Add PaginationService for page calculations and URL generation - Add PaginationUrlParser for Numeric and Prefixed format parsing - Add PaginationRouteConstraint for route validation - Comprehensive test coverage for pagination logic (57 new tests) Features: - CreatePaginatedResult handles empty collections, first/middle/last pages - IsValidPageNumber validates page ranges with 404 for out-of-range - GeneratePageUrl supports Numeric (/posts/2) and Prefixed (/posts/page-2) formats - Page 1 canonical at segment root (/posts not /posts/1) - Negative number rejection in URL parsing - Edge case handling: zero pages, exact boundaries, single pages All 372 tests passing. Refs: TASK-059, TASK-060, TASK-061, TASK-062
Implements TASK-076 to TASK-078: - Add ContentComponent<TDescriptor> base class for content components - Add ComponentValidation for @page/@layout directive enforcement - Add ForgingRouteView with ResolvedContent<T> parameter handling - Add ForgingRouter with navigation and routing infrastructure - Comprehensive XML documentation on all public APIs Features: - ContentComponent<TDescriptor> provides typed content component base (REQ-CMP-011) - ComponentValidation ensures no @page/@layout directives (REQ-CMP-009, REQ-CMP-010) - ForgingRouteView handles RouteData binding and ResolvedContent injection - ForgingRouter provides Router-compatible API for future content routing - Implements IComponent, IHandleAfterRender, IDisposable per Blazor patterns - NavigationManager integration with location change subscriptions - RenderFragment handling for Found/NotFound/Navigating states All 372 tests passing. Refs: TASK-076, TASK-077, TASK-078
…, startup validation, and service registration Implements TASK-063 to TASK-075: Phase 8 - Publishing Workflow: - Add PublishingService implementing IPublishingService (TASK-063) - Add PublishingConfirmationService for user confirmation management (TASK-064) - Add ContentExpirationService using TimeProvider for expiration checks (TASK-065) - Add DraftContentFilter for environment-based draft filtering (TASK-066) Phase 9 - Startup Validation: - Add RoutingConfigurationValidation with IValidateOptions (TASK-067) - Add ContentStructureValidation for file existence checks (TASK-068) - Add StorageConfigurationValidation for base path validation (TASK-069) - Add StartupValidationHostedService for aggregated validation (TASK-070) Phase 10 - Service Registration: - Add AddRoutingServices for route registry and resolver (TASK-071) - Add AddContentServices for content infrastructure (TASK-072) - Add AddStorageServices for publishing confirmation (TASK-073) - Add AddValidationServices for validation infrastructure (TASK-074) - Add AddCultureServices for culture fallback and validation (TASK-075) Features: - PublishingService with TODO for segment/culture enumeration - PublishingConfirmationService with concurrent confirmation management - ContentExpirationService using TimeProvider per CON-DEC-002 - DraftContentFilter respecting development/production environments - Comprehensive startup validation with fail-fast error aggregation - Service registration methods excluding static utility classes All 372 tests passing. Refs: TASK-063, TASK-064, TASK-065, TASK-066, TASK-067, TASK-068, TASK-069, TASK-070, TASK-071, TASK-072, TASK-073, TASK-074, TASK-075
All 372 tests passing. Plan document reflects complete status of Phases 1-11.
…ode-only components - Remove ForgingRouter.razor and ForgingRouteView.razor files - Implement BuildRenderTree method for both components - Remove partial class declarations - Add ArgumentNullException.ThrowIfNull for builder parameter - All 372 tests passing
Implements TASK-084 through TASK-092 - Create ForgingBlazor.Storage.AzureBlob project - Add Azure.Storage.Blobs 12.24.0 package - Implement IAzureBlobStorageOptions and AzureBlobStorageOptions - Implement AzureBlobContentStorageProvider with async blob operations - Implement AzureBlobAssetStorageProvider with content-type detection - Create ContentStorageBuilderExtensions and AssetStorageBuilderExtensions - Add comprehensive README.md with usage examples Refs: TASK-084, TASK-085, TASK-086, TASK-087, TASK-088, TASK-089, TASK-090, TASK-091, TASK-092
Implements TASK-095 - Create CheckSlugTests with 24 test cases - Test valid slugs including minimum (3 chars) and maximum (70 chars) boundaries - Test invalid starts/ends (hyphens, digits) - Test consecutive hyphens rejection - Test invalid characters (Unicode, special chars, whitespace) - Test ValidateSlug exception messages and parameter names - All 431 tests passing Refs: TASK-095
Update last_updated timestamp after completing Phase 12 (Azure Blob Storage) and Phase 13 (Core Interface Tests)
- Fixed IContentStorageProvider implementation in AzureBlobContentStorageProvider - Changed methods to use generic TDescriptor instead of string return types - Changed culture parameter from string to CultureInfo - Updated GetContentsAsync to return IReadOnlyList<TDescriptor> - Fixed ExistsAsync signature to accept single path parameter - Integrated ContentParser.Parse for descriptor creation - Fixed IAssetStorageProvider implementation in AzureBlobAssetStorageProvider - Changed GetAssetAsync return type from Task<byte[]?> to Task<Stream> - Changed SaveAssetAsync parameter from byte[] to Stream - Changed GetAssetsAsync parameter from optional prefix to required folder - Updated to use DownloadStreamingAsync for stream-based retrieval - Added project reference to ForgingBlazor in ForgingBlazor.Storage.AzureBlob.csproj to access ContentParser for content parsing - Added InternalsVisibleTo for NetEvolve.ForgingBlazor.Storage.AzureBlob in ForgingBlazor.csproj to allow access to internal ContentParser API - Fixed CA1308 code analysis warning by changing ToLowerInvariant to ToUpperInvariant in GetContentType method All build errors resolved, build succeeds, and all 431 tests pass.
- Removed unnecessary global:: prefix from using directives in multiple files. - Changed List<string> instantiation to use the simpler syntax in ContentStructureValidation.cs and StartupValidationHostedService.cs. - Added unit tests for CanonicalLinkComponent and RouteDefinition to enhance test coverage. - Improved thread safety tests in RouteRegistryTests and RouteResolverTests. - Added new tests for route registration and resolution scenarios.
- Add FrontmatterParserTests.cs with 11 tests covering YAML extraction, edge cases - Add MarkdownRendererTests.cs with 13 tests for HTML rendering validation - Add ContentParserTests.cs with 11 tests for full parsing pipeline - Fix case-insensitive frontmatter validation using ToUpperInvariant (CA1308) - Add array/list conversion support in ContentDescriptorFactory - Fix malformed YAML test to expect InvalidOperationException - Replace obsolete HasCount() with Count() in TUnit assertions Implements TASK-100, TASK-101, TASK-102, TASK-103 Refs: Phase 15 - Unit Tests Content Parsing All tests passing: 538/538 ✅
Implements TASK-096, TASK-097, TASK-098, TASK-099 delivering complete routing unit test coverage: - SlugRouteConstraintTests (40 tests): validates slug pattern matching with comprehensive edge cases including min/max length boundaries, valid/invalid characters, consecutive hyphens, special cases - RoutingBuilderTests (14 tests): verified existing tests for FluentAPI configuration and nested segments - RouteResolverTests (13 tests): verified existing tests for path matching and normalization - CanonicalUrlGeneratorTests (21 tests): verified existing tests for culture-aware URL generation Test results: 573 tests passing (+40 new) Build status: successful with existing warnings Refs: TASK-096, TASK-097, TASK-098, TASK-099
Phase 16 - Unit Tests Culture (GOAL-016): - TASK-096: CultureResolverTests.cs verified (18 tests) * Two-Letter code parsing (en, de, fr) * LCID parsing (1033 for en-US, 1031 for de-DE) * Full culture name parsing (de-DE, fr-FR) * Invalid inputs, null/empty/whitespace handling * Case insensitivity testing - TASK-097: CultureFallbackChainTests.cs verified (11 tests) * Complete fallback hierarchy: de-DE → de → en-US → en → invariant * Custom default culture support * Duplicate elimination in chain * Culture suffix generation (.de-DE, .de, .en-US, .en, empty) - TASK-098: CultureContentLocatorTests.cs verified (6 tests) * Lookup path generation with culture suffixes * Constructor validation * Different culture handling Phase 17 - Unit Tests Pagination (GOAL-017): - TASK-107: PaginationServiceTests.cs verified (30 tests) * Page calculation (first/middle/last pages) * Empty collection handling * Page size boundaries (minimum 1) * Exact page boundaries * Out-of-range page validation * URL generation (Numeric & Prefixed formats) - TASK-108: PaginationUrlParserTests.cs verified (23 tests) * Numeric format parsing (e.g., "2") * Prefixed format parsing (e.g., "page-2") * Invalid inputs (negative, zero, non-numeric) * Case-insensitive prefix matching * Edge cases (empty/whitespace, missing numbers) Total: 88 tests verified passing (35 culture + 53 pagination) All tests: 573/573 ✅ Refs: Phase 16 - Unit Tests Culture, Phase 17 - Unit Tests Pagination
- Add RoutingConfigurationValidationTests with 10 tests for configuration validation - Add ContentStructureValidationTests with 13 tests for content structure validation - Add StorageConfigurationValidationTests with 11 tests for storage configuration validation Validation coverage includes: - Routing: null checks, empty collections, culture validation, component/layout types - Content: constructor validation, missing files, segment/page detection, pagination - Storage: path validation, directory existence, null/empty/whitespace handling Implements TASK-112, TASK-113, TASK-114 Refs: Phase 19 - Unit Tests Validation All tests passing: 609/609 ✅
…d storage - Add AzureBlobContentStorageProviderTests with Azurite emulation (10 tests) - Add ContentRoutingIntegrationTests with route resolution tests (7 tests) - Add PublishingWorkflowIntegrationTests with draft/expiration workflow tests (11 tests) - Add TestContentFixture for sample content generation with multi-culture support - All integration tests pass successfully (627/637 total tests passing) - Azurite tests properly skip when emulator is not running (10 tests) Implements TASK-115, TASK-116, TASK-117, TASK-118, TASK-119 Refs: Phase 20 - Integration Tests All tests passing: 627/637 \u2705 (10 Azurite tests skipped as expected)
- Extract StorageConfiguration into separate file - Extract RoutingConfiguration into separate file - Add Testcontainers.Azurite 4.2.0 for automated integration testing - Configure AzuriteFixture with --skipApiVersionCheck flag Follows one-class-per-file principle for better maintainability. Refs: Phase 20 - Integration Tests
- Move AzuriteFixture from AzureBlobContentStorageProviderTests.cs to AzuriteFixture.cs - Ensures one-class-per-file principle in tests directory Follows architectural decision for better test organization.
- Use [ClassDataSource<AzuriteFixture>] attribute for dependency injection - Implement IAsyncInitializer and IAsyncDisposable in AzuriteFixture - Convert static methods to instance methods using fixture parameter - Change AzuriteFixture visibility from internal to public - Fix invalid slugs in test data (post-1 → post-one, post-2 → post-two) This follows TUnit best practices for shared test fixtures and enables proper lifecycle management through the framework. All 10 tests passing.
…polation in various files
dc64572 to
7957500
Compare
…om Directory.Packages.props
- Add ForgingRouteView unit tests (7 tests) - Add ForgingRouter unit tests (8 tests) - Add ForgingRouterSmokeTests integration tests (7 tests) - Verify all 652 tests passing Implements TASK-081, TASK-082, TASK-083 Completes Phase 11 and Phase 18 testing requirements Refs: TASK-081, TASK-082, TASK-083, TASK-109, TASK-110, TASK-111
- Mark TASK-081 through TASK-083 as completed (2026-01-28) - Mark TASK-109 through TASK-111 as completed (2026-01-28) - Add Phase 18 completion report with test summary - Update Phase 11 report with new test details All 652 tests passing
… improve exception handling in ForgingRouter tests
No description provided.