diff --git a/CLAUDE.md b/CLAUDE.md index b0026c6..8d1a30c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -58,6 +58,7 @@ dotnet add test/LayeredCraft.Cdk.Constructs.Tests/ package PackageName - Configures Route53 DNS records for primary domain and alternates - Supports optional API proxying via CloudFront behaviors for `/api/*` paths - Includes automatic asset deployment with cache invalidation +- Exposes `SiteDomain` property containing the fully qualified domain name **DynamoDbTableConstruct** (`src/LayeredCraft.Cdk.Constructs/DynamoDbTableConstruct.cs`) - Comprehensive CDK construct for DynamoDB table creation and configuration @@ -88,7 +89,7 @@ dotnet add test/LayeredCraft.Cdk.Constructs.Tests/ package PackageName ### Target Frameworks - .NET 8.0 and .NET 9.0 -- Uses AWS CDK v2 (Amazon.CDK.Lib 2.203.1) +- Uses AWS CDK v2 (Amazon.CDK.Lib 2.213.0) ### OpenTelemetry Configuration (v2.0.0+) Starting with version 2.0.0, the OpenTelemetry layer configuration has been updated: diff --git a/Directory.Build.props b/Directory.Build.props index 62b6559..7b38a93 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,6 @@ - 2.0.0 + 2.0.1 MIT diff --git a/docs/constructs/static-site.md b/docs/constructs/static-site.md index 8e3cbfa..5be705e 100644 --- a/docs/constructs/static-site.md +++ b/docs/constructs/static-site.md @@ -51,6 +51,29 @@ public class MyStack : Stack | `ApiDomain` | `string?` | `null` | API domain for proxy behavior | | `AlternateDomains` | `string[]` | `[]` | Additional domains to include in certificate | +## Construct Properties + +The `StaticSiteConstruct` exposes the following properties after instantiation: + +| Property | Type | Description | +|----------|------|-------------| +| `SiteDomain` | `string` | Fully qualified domain name of the site (e.g., "www.example.com") | + +### Accessing Site Domain + +```csharp +var site = new StaticSiteConstruct(this, "MySite", new StaticSiteConstructProps +{ + SiteBucketName = "my-website-bucket", + DomainName = "example.com", + SiteSubDomain = "www", + AssetPath = "./website-build" +}); + +// Access the computed site domain +var domain = site.SiteDomain; // "www.example.com" +``` + ## Advanced Examples ### Website with Subdomain diff --git a/src/LayeredCraft.Cdk.Constructs/LayeredCraft.Cdk.Constructs.csproj b/src/LayeredCraft.Cdk.Constructs/LayeredCraft.Cdk.Constructs.csproj index 1dbeadd..e85b4b1 100644 --- a/src/LayeredCraft.Cdk.Constructs/LayeredCraft.Cdk.Constructs.csproj +++ b/src/LayeredCraft.Cdk.Constructs/LayeredCraft.Cdk.Constructs.csproj @@ -15,7 +15,7 @@ - + diff --git a/src/LayeredCraft.Cdk.Constructs/StaticSiteConstruct.cs b/src/LayeredCraft.Cdk.Constructs/StaticSiteConstruct.cs index 0774043..16c3d46 100644 --- a/src/LayeredCraft.Cdk.Constructs/StaticSiteConstruct.cs +++ b/src/LayeredCraft.Cdk.Constructs/StaticSiteConstruct.cs @@ -19,6 +19,11 @@ namespace LayeredCraft.Cdk.Constructs; /// public class StaticSiteConstruct : Construct { + /// + /// Gets the fully qualified domain name of the static site (e.g., "www.example.com"). + /// This property is set during construct initialization and combines the site subdomain with the domain name. + /// + public string SiteDomain { get; private set; } /// /// Initializes a new instance of the StaticSiteConstruct class. /// @@ -33,12 +38,12 @@ public StaticSiteConstruct(Construct scope, string id, IStaticSiteConstructProps DomainName = props.DomainName }); - var siteDomain = $"{props.SiteSubDomain}.{props.DomainName}"; + SiteDomain = $"{props.SiteSubDomain}.{props.DomainName}"; // Create S3 bucket for static website hosting var siteBucket = new Bucket(this, $"{id}-bucket", new BucketProps { - BucketName = siteDomain, + BucketName = SiteDomain, WebsiteIndexDocument = "index.html", WebsiteErrorDocument = "index.html", PublicReadAccess = true, @@ -62,7 +67,7 @@ public StaticSiteConstruct(Construct scope, string id, IStaticSiteConstructProps // Create SSL certificate for HTTPS with DNS validation var certificate = new Certificate(this, $"{id}-certificate", new CertificateProps { - DomainName = siteDomain, + DomainName = SiteDomain, Validation = CertificateValidation.FromDns(zone), SubjectAlternativeNames = props.AlternateDomains, }); @@ -70,7 +75,7 @@ public StaticSiteConstruct(Construct scope, string id, IStaticSiteConstructProps // Create CloudFront distribution for global content delivery var distribution = new Distribution(this, $"{id}-cdn", new DistributionProps { - DomainNames = [siteDomain, ..props.AlternateDomains], + DomainNames = [SiteDomain, ..props.AlternateDomains], DefaultBehavior = new BehaviorOptions { Origin = new S3StaticWebsiteOrigin(siteBucket, new S3StaticWebsiteOriginProps @@ -112,7 +117,7 @@ public StaticSiteConstruct(Construct scope, string id, IStaticSiteConstructProps _ = new ARecord(this, $"{id}-alias-record", new ARecordProps { Zone = zone, - RecordName = siteDomain, + RecordName = SiteDomain, Target = RecordTarget.FromAlias(new CloudFrontTarget(distribution)), }); diff --git a/test/LayeredCraft.Cdk.Constructs.Tests/LayeredCraft.Cdk.Constructs.Tests.csproj b/test/LayeredCraft.Cdk.Constructs.Tests/LayeredCraft.Cdk.Constructs.Tests.csproj index 4d382d9..4292168 100644 --- a/test/LayeredCraft.Cdk.Constructs.Tests/LayeredCraft.Cdk.Constructs.Tests.csproj +++ b/test/LayeredCraft.Cdk.Constructs.Tests/LayeredCraft.Cdk.Constructs.Tests.csproj @@ -36,8 +36,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive