@sylvesterllc/aws-constructs 1.1.69 → 1.1.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,6 +10,7 @@ describe("SpaCFRoute53", () => {
10
10
  cloudfrontName: "testsite-cf",
11
11
  domainName: "example.com",
12
12
  fqdn: "spa.example.com",
13
+ hostedZoneId: "ZTEST1234567890",
13
14
  };
14
15
 
15
16
  it("provisions a private, versioned, encrypted S3 bucket with access logging", () => {
@@ -9,7 +9,6 @@ const aws_certificatemanager_1 = require("aws-cdk-lib/aws-certificatemanager");
9
9
  const aws_route53_1 = require("aws-cdk-lib/aws-route53");
10
10
  const aws_route53_targets_1 = require("aws-cdk-lib/aws-route53-targets");
11
11
  const aws_cdk_lib_1 = require("aws-cdk-lib");
12
- const ulid_1 = require("../helpers/ulid");
13
12
  class SpaCFRoute53 extends constructs_1.Construct {
14
13
  bucket;
15
14
  distribution;
@@ -18,10 +17,10 @@ class SpaCFRoute53 extends constructs_1.Construct {
18
17
  logsBucket;
19
18
  constructor(scope, id, props) {
20
19
  super(scope, id);
21
- // Generate a unique suffix for resource names
22
- const uniqueId = (0, ulid_1.ulid)();
20
+ // Build a safe key from domain for export names (replace dots)
21
+ const domainKey = (props.fqdn ?? props.domainName).split(".").join("-");
23
22
  // Logs bucket with 14-day retention
24
- this.logsBucket = new aws_s3_1.Bucket(this, `${props.domainName?.toLowerCase()}-spa-bucket-log-${uniqueId}`, {
23
+ this.logsBucket = new aws_s3_1.Bucket(this, `${props.domainName?.toLowerCase()}-spa-bucket-log`, {
25
24
  removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY,
26
25
  autoDeleteObjects: true,
27
26
  lifecycleRules: [{ expiration: aws_cdk_lib_1.Duration.days(14) }],
@@ -33,7 +32,7 @@ class SpaCFRoute53 extends constructs_1.Construct {
33
32
  accessControl: aws_s3_1.BucketAccessControl.LOG_DELIVERY_WRITE,
34
33
  });
35
34
  // Main SPA bucket
36
- this.bucket = new aws_s3_1.Bucket(this, `${props.domainName?.toLowerCase()}-spa-bucket-${uniqueId}`, {
35
+ this.bucket = new aws_s3_1.Bucket(this, `${props.domainName?.toLowerCase()}-spa-bucket`, {
37
36
  bucketName: props.bucketName,
38
37
  removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY,
39
38
  autoDeleteObjects: true,
@@ -46,33 +45,29 @@ class SpaCFRoute53 extends constructs_1.Construct {
46
45
  // Route53 hosted zone
47
46
  // Prefer direct import when a hostedZoneId is provided; use a dummy hosted zone for tests;
48
47
  // otherwise perform a lookup in the current account.
49
- const hostedZone = props.domainName === "example.com"
48
+ const hostedZone = props.hostedZoneId
50
49
  ? aws_route53_1.HostedZone.fromHostedZoneAttributes(this, "HostedZone", {
51
- hostedZoneId: "Z000000000000000TEST",
50
+ hostedZoneId: props.hostedZoneId,
52
51
  zoneName: props.domainName,
53
52
  })
54
- : props.hostedZoneId
55
- ? aws_route53_1.HostedZone.fromHostedZoneAttributes(this, "HostedZone", {
56
- hostedZoneId: props.hostedZoneId,
57
- zoneName: props.domainName,
58
- })
59
- : aws_route53_1.HostedZone.fromLookup(this, "HostedZone", {
60
- domainName: props.domainName,
61
- });
53
+ : aws_route53_1.HostedZone.fromLookup(this, "HostedZone", {
54
+ domainName: props.domainName,
55
+ });
62
56
  // ACM certificate (must be in us-east-1 for CloudFront)
63
57
  // Create a DNS-validated certificate in us-east-1 and tag it with a friendly name
64
- const certificate = new aws_certificatemanager_1.DnsValidatedCertificate(this, "SpaCert", {
65
- domainName: props.fqdn,
66
- hostedZone,
67
- region: "us-east-1",
68
- subjectAlternativeNames: props.domainName && props.domainName !== props.fqdn ? [props.domainName] : undefined,
58
+ const certificate = new aws_certificatemanager_1.Certificate(this, "SpaCert", {
59
+ domainName: props.domainName,
60
+ subjectAlternativeNames: [
61
+ props.fqdn,
62
+ ],
63
+ validation: aws_certificatemanager_1.CertificateValidation.fromDns(hostedZone),
69
64
  });
70
65
  // Tag for visibility in console: "Certificate name"
71
66
  aws_cdk_lib_1.Tags.of(certificate).add("Name", `${props.siteName}-cert-cf`);
72
67
  // CloudFront distribution
73
68
  this.distribution = new aws_cloudfront_1.Distribution(this, "SpaDistribution", {
74
69
  defaultBehavior: {
75
- origin: new aws_cloudfront_origins_1.S3Origin(this.bucket),
70
+ origin: aws_cloudfront_origins_1.S3BucketOrigin.withOriginAccessControl(this.bucket),
76
71
  viewerProtocolPolicy: aws_cloudfront_1.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
77
72
  allowedMethods: aws_cloudfront_1.AllowedMethods.ALLOW_GET_HEAD,
78
73
  cachePolicy: undefined, // Custom cache policy can be added
@@ -119,7 +114,14 @@ class SpaCFRoute53 extends constructs_1.Construct {
119
114
  aws_cdk_lib_1.Tags.of(this.distribution).add("ResourcePrefix", props.siteName);
120
115
  aws_cdk_lib_1.Tags.of(this.logsBucket).add("App", props.siteName);
121
116
  aws_cdk_lib_1.Tags.of(this.logsBucket).add("ResourcePrefix", props.siteName);
117
+ // CloudFormation outputs for created resources
118
+ new aws_cdk_lib_1.CfnOutput(this, "SpaBucketName", { value: this.bucket.bucketName });
119
+ new aws_cdk_lib_1.CfnOutput(this, "SpaLogsBucketName", { value: this.logsBucket.bucketName });
120
+ new aws_cdk_lib_1.CfnOutput(this, "SpaCertificateArn", { value: certificate.certificateArn });
121
+ new aws_cdk_lib_1.CfnOutput(this, "SpaDistributionId", { value: this.distribution.distributionId });
122
+ new aws_cdk_lib_1.CfnOutput(this, "SpaDistributionDomainName", { value: this.distribution.distributionDomainName });
123
+ new aws_cdk_lib_1.CfnOutput(this, "SpaAliasRecordName", { value: props.fqdn });
122
124
  }
123
125
  }
124
126
  exports.SpaCFRoute53 = SpaCFRoute53;
125
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU3BhQ0ZSb3V0ZTUzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbnN0cnVjdHMvU3BhQ0ZSb3V0ZTUzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDJDQUF1QztBQUN2QywrQ0FNNEI7QUFDNUIsK0RBT29DO0FBQ3BDLCtFQUE4RDtBQUM5RCwrRUFBMkY7QUFDM0YseURBS2lDO0FBQ2pDLHlFQUFtRTtBQUVuRSw2Q0FBNEQ7QUFDNUQsMENBQXVDO0FBRXZDLE1BQWEsWUFBYSxTQUFRLHNCQUFTO0lBQ3pCLE1BQU0sQ0FBUztJQUNmLFlBQVksQ0FBZTtJQUMzQixzQkFBc0IsQ0FBUztJQUMvQixjQUFjLENBQVM7SUFDdkIsVUFBVSxDQUFTO0lBRW5DLFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBZTtRQUN2RCxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLDhDQUE4QztRQUM5QyxNQUFNLFFBQVEsR0FBRyxJQUFBLFdBQUksR0FBRSxDQUFDO1FBRXhCLG9DQUFvQztRQUNwQyxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksZUFBTSxDQUMxQixJQUFJLEVBQ0osR0FBRyxLQUFLLENBQUMsVUFBVSxFQUFFLFdBQVcsRUFBRSxtQkFBbUIsUUFBUSxFQUFFLEVBQy9EO1lBQ0UsYUFBYSxFQUFFLDJCQUFhLENBQUMsT0FBTztZQUNwQyxpQkFBaUIsRUFBRSxJQUFJO1lBQ3ZCLGNBQWMsRUFBRSxDQUFDLEVBQUUsVUFBVSxFQUFFLHNCQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7WUFDbkQsaUJBQWlCLEVBQUUsMEJBQWlCLENBQUMsU0FBUztZQUM5QyxVQUFVLEVBQUUseUJBQWdCLENBQUMsVUFBVTtZQUN2QyxTQUFTLEVBQUUsS0FBSztZQUNoQixrRkFBa0Y7WUFDbEYsZUFBZSxFQUFFLHdCQUFlLENBQUMsYUFBYTtZQUM5QyxhQUFhLEVBQUUsNEJBQW1CLENB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Q0FBQyxRQUFRLENBQUMsQ0FBQztRQUMzRCxrQkFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdEQsa0JBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDakUsa0JBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3BELGtCQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLEVBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2pFLENBQUM7Q0FDRjtBQXRJRCxvQ0FzSUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuaW1wb3J0IHtcbiAgQnVja2V0LFxuICBCbG9ja1B1YmxpY0FjY2VzcyxcbiAgQnVja2V0RW5jcnlwdGlvbixcbiAgQnVja2V0QWNjZXNzQ29udHJvbCxcbiAgT2JqZWN0T3duZXJzaGlwLFxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXMzXCI7XG5pbXBvcnQge1xuICBEaXN0cmlidXRpb24sXG4gIFZpZXdlclByb3RvY29sUG9saWN5LFxuICBBbGxvd2VkTWV0aG9kcyxcbiAgUHJpY2VDbGFzcyxcbiAgUmVzcG9uc2VIZWFkZXJzUG9saWN5LFxuICBDZm5EaXN0cmlidXRpb24sXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtY2xvdWRmcm9udFwiO1xuaW1wb3J0IHsgUzNPcmlnaW4gfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNsb3VkZnJvbnQtb3JpZ2luc1wiO1xuaW1wb3J0IHsgRG5zVmFsaWRhdGVkQ2VydGlmaWNhdGUsIElDZXJ0aWZpY2F0ZSB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtY2VydGlmaWNhdGVtYW5hZ2VyXCI7XG5pbXBvcnQge1xuICBIb3N0ZWRab25lLFxuICBJSG9zdGVkWm9uZSxcbiAgQVJlY29yZCxcbiAgUmVjb3JkVGFyZ2V0LFxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXJvdXRlNTNcIjtcbmltcG9ydCB7IENsb3VkRnJvbnRUYXJnZXQgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXJvdXRlNTMtdGFyZ2V0c1wiO1xuaW1wb3J0IHsgU3BhUHJvcHMgfSBmcm9tIFwiLi4vaW50ZXJmYWNlcy9TcGFQcm9wc1wiO1xuaW1wb3J0IHsgVGFncywgUmVtb3ZhbFBvbGljeSwgRHVyYXRpb24gfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7IHVsaWQgfSBmcm9tIFwiLi4vaGVscGVycy91bGlkXCI7XG5cbmV4cG9ydCBjbGFzcyBTcGFDRlJvdXRlNTMgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBwdWJsaWMgcmVhZG9ubHkgYnVja2V0OiBCdWNrZXQ7XG4gIHB1YmxpYyByZWFkb25seSBkaXN0cmlidXRpb246IERpc3RyaWJ1dGlvbjtcbiAgcHVibGljIHJlYWRvbmx5IGRpc3RyaWJ1dGlvbkRvbWFpbk5hbWU6IHN0cmluZztcbiAgcHVibGljIHJlYWRvbmx5IGRpc3RyaWJ1dGlvbklkOiBzdHJpbmc7XG4gIHB1YmxpYyByZWFkb25seSBsb2dzQnVja2V0OiBCdWNrZXQ7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IFNwYVByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIC8vIEdlbmVyYXRlIGEgdW5pcXVlIHN1ZmZpeCBmb3IgcmVzb3VyY2UgbmFtZXNcbiAgICBjb25zdCB1bmlxdWVJZCA9IHVsaWQoKTtcblxuICAgIC8vIExvZ3MgYnVja2V0IHdpdGggMTQtZGF5IHJldGVudGlvblxuICAgIHRoaXMubG9nc0J1Y2tldCA9IG5ldyBCdWNrZXQoXG4gICAgICB0aGlzLFxuICAgICAgYCR7cHJvcHMuZG9tYWluTmFtZT8udG9Mb3dlckNhc2UoKX0tc3BhLWJ1Y2tldC1sb2ctJHt1bmlxdWVJZH1gLFxuICAgICAge1xuICAgICAgICByZW1vdmFsUG9saWN5OiBSZW1vdmFsUG9saWN5LkRFU1RST1ksXG4gICAgICAgIGF1dG9EZWxldGVPYmplY3RzOiB0cnVlLFxuICAgICAgICBsaWZlY3ljbGVSdWxlczogW3sgZXhwaXJhdGlvbjogRHVyYXRpb24uZGF5cygxNCkgfV0sXG4gICAgICAgIGJsb2NrUHVibGljQWNjZXNzOiBCbG9ja1B1YmxpY0FjY2Vzcy5CTE9DS19BTEwsXG4gICAgICAgIGVuY3J5cHRpb246IEJ1Y2tldEVuY3J5cHRpb24uUzNfTUFOQUdFRCxcbiAgICAgICAgdmVyc2lvbmVkOiBmYWxzZSxcbiAgICAgICAgLy8gQ2xvdWRGcm9udCBzdGFuZGFyZCBsb2dzIHJlcXVpcmUgQUNMczsgZW5hYmxlIHRoZW0gYW5kIGdyYW50IGxvZyBkZWxpdmVyeSB3cml0ZVxuICAgICAgICBvYmplY3RPd25lcnNoaXA6IE9iamVjdE93bmVyc2hpcC5PQkpFQ1RfV1JJVEVSLFxuICAgICAgICBhY2Nlc3NDb250cm9sOiBCdWNrZXRBY2Nlc3NDb250cm9sLkxPR19ERUxJVkVSWV9XUklURSxcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIC8vIE1haW4gU1BBIGJ1Y2tldFxuICAgIHRoaXMuYnVja2V0ID0gbmV3IEJ1Y2tldChcbiAgICAgIHRoaXMsXG4gICAgICBgJHtwcm9wcy5kb21haW5OYW1lPy50b0xvd2VyQ2FzZSgpfS1zcGEtYnVja2V0LSR7dW5pcXVlSWR9YCxcbiAgICAgIHtcbiAgICAgICAgYnVja2V0TmFtZTogcHJvcHMuYnVja2V0TmFtZSxcbiAgICAgICAgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgICBhdXRvRGVsZXRlT2JqZWN0czogdHJ1ZSxcbiAgICAgICAgYmxvY2tQdWJsaWNBY2Nlc3M6IEJsb2NrUHVibGljQWNjZXNzLkJMT0NLX0FMTCxcbiAgICAgICAgZW5jcnlwdGlvbjogQnVja2V0RW5jcnlwdGlvbi5TM19NQU5BR0VELFxuICAgICAgICB2ZXJzaW9uZWQ6IHRydWUsXG4gICAgICAgIHNlcnZlckFjY2Vzc0xvZ3NCdWNrZXQ6IHRoaXMubG9nc0J1Y2tldCxcbiAgICAgICAgc2VydmVyQWNjZXNzTG9nc1ByZWZpeDogXCJzcGEvXCIsXG4gICAgICB9LFxuICAgICk7XG5cbiAgICAvLyBSb3V0ZTUzIGhvc3RlZCB6b25lXG4gICAgLy8gUHJlZmVyIGRpcmVjdCBpbXBvcnQgd2hlbiBhIGhvc3RlZFpvbmVJZCBpcyBwcm92aWRlZDsgdXNlIGEgZHVtbXkgaG9zdGVkIHpvbmUgZm9yIHRlc3RzO1xuICAgIC8vIG90aGVyd2lzZSBwZXJmb3JtIGEgbG9va3VwIGluIHRoZSBjdXJyZW50IGFjY291bnQuXG4gICAgY29uc3QgaG9zdGVkWm9uZTogSUhvc3RlZFpvbmUgPVxuICAgICAgcHJvcHMuZG9tYWluTmFtZSA9PT0gXCJleGFtcGxlLmNvbVwiXG4gICAgICAgID8gSG9zdGVkWm9uZS5mcm9tSG9zdGVkWm9uZUF0dHJpYnV0ZXModGhpcywgXCJIb3N0ZWRab25lXCIsIHtcbiAgICAgICAgICAgIGhvc3RlZFpvbmVJZDogXCJaMDAwMDAwMDAwMDAwMDAwVEVTVFwiLFxuICAgICAgICAgICAgem9uZU5hbWU6IHByb3BzLmRvbWFpbk5hbWUsXG4gICAgICAgICAgfSlcbiAgICAgICAgOiBwcm9wcy5ob3N0ZWRab25lSWRcbiAgICAgICAgPyBIb3N0ZWRab25lLmZyb21Ib3N0ZWRab25lQXR0cmlidXRlcyh0aGlzLCBcIkhvc3RlZFpvbmVcIiwge1xuICAgICAgICAgICAgaG9zdGVkWm9uZUlkOiBwcm9wcy5ob3N0ZWRab25lSWQsXG4gICAgICAgICAgICB6b25lTmFtZTogcHJvcHMuZG9tYWluTmFtZSxcbiAgICAgICAgICB9KVxuICAgICAgICA6IEhvc3RlZFpvbmUuZnJvbUxvb2t1cCh0aGlzLCBcIkhvc3RlZFpvbmVcIiwge1xuICAgICAgICAgICAgZG9tYWluTmFtZTogcHJvcHMuZG9tYWluTmFtZSxcbiAgICAgICAgICB9KTtcblxuICAgIC8vIEFDTSBjZXJ0aWZpY2F0ZSAobXVzdCBiZSBpbiB1cy1lYXN0LTEgZm9yIENsb3VkRnJvbnQpXG4gICAgLy8gQ3JlYXRlIGEgRE5TLXZhbGlkYXRlZCBjZXJ0aWZpY2F0ZSBpbiB1cy1lYXN0LTEgYW5kIHRhZyBpdCB3aXRoIGEgZnJpZW5kbHkgbmFtZVxuICAgIGNvbnN0IGNlcnRpZmljYXRlOiBJQ2VydGlmaWNhdGUgPSBuZXcgRG5zVmFsaWRhdGVkQ2VydGlmaWNhdGUodGhpcywgXCJTcGFDZXJ0XCIsIHtcbiAgICAgIGRvbWFpbk5hbWU6IHByb3BzLmZxZG4sXG4gICAgICBob3N0ZWRab25lLFxuICAgICAgcmVnaW9uOiBcInVzLWVhc3QtMVwiLFxuICAgICAgc3ViamVjdEFsdGVybmF0aXZlTmFtZXM6IHByb3BzLmRvbWFpbk5hbWUgJiYgcHJvcHMuZG9tYWluTmFtZSAhPT0gcHJvcHMuZnFkbiA/IFtwcm9wcy5kb21haW5OYW1lXSA6IHVuZGVmaW5lZCxcbiAgICB9KTtcbiAgICAvLyBUYWcgZm9yIHZpc2liaWxpdHkgaW4gY29uc29sZTogXCJDZXJ0aWZpY2F0ZSBuYW1lXCJcbiAgICBUYWdzLm9mKGNlcnRpZmljYXRlKS5hZGQoXCJOYW1lXCIsIGAke3Byb3BzLnNpdGVOYW1lfS1jZXJ0LWNmYCk7XG5cbiAgICAvLyBDbG91ZEZyb250IGRpc3RyaWJ1dGlvblxuICAgIHRoaXMuZGlzdHJpYnV0aW9uID0gbmV3IERpc3RyaWJ1dGlvbih0aGlzLCBcIlNwYURpc3RyaWJ1dGlvblwiLCB7XG4gICAgICBkZWZhdWx0QmVoYXZpb3I6IHtcbiAgICAgICAgb3JpZ2luOiBuZXcgUzNPcmlnaW4odGhpcy5idWNrZXQpLFxuICAgICAgICB2aWV3ZXJQcm90b2NvbFBvbGljeTogVmlld2VyUHJvdG9jb2xQb2xpY3kuUkVESVJFQ1RfVE9fSFRUUFMsXG4gICAgICAgIGFsbG93ZWRNZXRob2RzOiBBbGxvd2VkTWV0aG9kcy5BTExPV19HRVRfSEVBRCxcbiAgICAgICAgY2FjaGVQb2xpY3k6IHVuZGVmaW5lZCwgLy8gQ3VzdG9tIGNhY2hlIHBvbGljeSBjYW4gYmUgYWRkZWRcbiAgICAgICAgY29tcHJlc3M6IHRydWUsXG4gICAgICAgIHJlc3BvbnNlSGVhZGVyc1BvbGljeTpcbiAgICAgICAgICBSZXNwb25zZUhlYWRlcnNQb2xpY3kuQ09SU19BTExPV19BTExfT1JJR0lOU19XSVRIX1BSRUZMSUdIVF9BTkRfU0VDVVJJVFlfSEVBREVSUyxcbiAgICAgIH0sXG4gICAgICBkZWZhdWx0Um9vdE9iamVjdDogXCJpbmRleC5odG1sXCIsXG4gICAgICBkb21haW5OYW1lczogW3Byb3BzLmZxZG5dLFxuICAgICAgY2VydGlmaWNhdGUsXG4gICAgICBwcmljZUNsYXNzOiBQcmljZUNsYXNzLlBSSUNFX0NMQVNTXzEwMCxcbiAgICAgIGVuYWJsZUxvZ2dpbmc6IHRydWUsXG4gICAgICBsb2dCdWNrZXQ6IHRoaXMubG9nc0J1Y2tldCxcbiAgICAgIGxvZ0ZpbGVQcmVmaXg6IFwiY2xvdWRmcm9udC9cIixcbiAgICAgIGVycm9yUmVzcG9uc2VzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBodHRwU3RhdHVzOiA0MDMsXG4gICAgICAgICAgcmVzcG9uc2VIdHRwU3RhdHVzOiAyMDAsXG4gICAgICAgICAgcmVzcG9uc2VQYWdlUGF0aDogXCIvaW5kZXguaHRtbFwiLFxuICAgICAgICAgIHR0bDogRHVyYXRpb24ubWludXRlcyg1KSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGh0dHBTdGF0dXM6IDQwNCxcbiAgICAgICAgICByZXNwb25zZUh0dHBTdGF0dXM6IDIwMCxcbiAgICAgICAgICByZXNwb25zZVBhZ2VQYXRoOiBcIi9pbmRleC5odG1sXCIsXG4gICAgICAgICAgdHRsOiBEdXJhdGlvbi5taW51dGVzKDUpLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcblxuICAgIC8vIEZvcmNlIFRMUyAxLjMgaW4gdGhlIHN5bnRoZXNpemVkIHRlbXBsYXRlIHRvIHNhdGlzZnkgdGVzdHNcbiAgICBjb25zdCBjZm5EaXN0ID0gdGhpcy5kaXN0cmlidXRpb24ubm9kZS5kZWZhdWx0Q2hpbGQgYXMgQ2ZuRGlzdHJpYnV0aW9uO1xuICAgIGNmbkRpc3QuYWRkUHJvcGVydHlPdmVycmlkZShcbiAgICAgIFwiRGlzdHJpYnV0aW9uQ29uZmlnLlZpZXdlckNlcnRpZmljYXRlLk1pbmltdW1Qcm90b2NvbFZlcnNpb25cIixcbiAgICAgIFwiVExTdjEuM18yMDI1XCIsXG4gICAgKTtcblxuICAgIHRoaXMuZGlzdHJpYnV0aW9uRG9tYWluTmFtZSA9IHRoaXMuZGlzdHJpYnV0aW9uLmRpc3RyaWJ1dGlvbkRvbWFpbk5hbWU7XG4gICAgdGhpcy5kaXN0cmlidXRpb25JZCA9IHRoaXMuZGlzdHJpYnV0aW9uLmRpc3RyaWJ1dGlvbklkO1xuXG4gICAgLy8gUm91dGU1MyBhbGlhcyByZWNvcmRcbiAgICBuZXcgQVJlY29yZCh0aGlzLCBcIlNwYUFsaWFzUmVjb3JkXCIsIHtcbiAgICAgIHpvbmU6IGhvc3RlZFpvbmUsXG4gICAgICByZWNvcmROYW1lOiBwcm9wcy5mcWRuLFxuICAgICAgdGFyZ2V0OiBSZWNvcmRUYXJnZXQuZnJvbUFsaWFzKG5ldyBDbG91ZEZyb250VGFyZ2V0KHRoaXMuZGlzdHJpYnV0aW9uKSksXG4gICAgfSk7XG5cbiAgICAvLyBUYWdnaW5nXG4gICAgVGFncy5vZih0aGlzLmJ1Y2tldCkuYWRkKFwiQXBwXCIsIHByb3BzLnNpdGVOYW1lKTtcbiAgICBUYWdzLm9mKHRoaXMuYnVja2V0KS5hZGQoXCJSZXNvdXJjZVByZWZpeFwiLCBwcm9wcy5zaXRlTmFtZSk7XG4gICAgVGFncy5vZih0aGlzLmRpc3RyaWJ1dGlvbikuYWRkKFwiQXBwXCIsIHByb3BzLnNpdGVOYW1lKTtcbiAgICBUYWdzLm9mKHRoaXMuZGlzdHJpYnV0aW9uKS5hZGQoXCJSZXNvdXJjZVByZWZpeFwiLCBwcm9wcy5zaXRlTmFtZSk7XG4gICAgVGFncy5vZih0aGlzLmxvZ3NCdWNrZXQpLmFkZChcIkFwcFwiLCBwcm9wcy5zaXRlTmFtZSk7XG4gICAgVGFncy5vZih0aGlzLmxvZ3NCdWNrZXQpLmFkZChcIlJlc291cmNlUHJlZml4XCIsIHByb3BzLnNpdGVOYW1lKTtcbiAgfVxufVxuIl19
127
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU3BhQ0ZSb3V0ZTUzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbnN0cnVjdHMvU3BhQ0ZSb3V0ZTUzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDJDQUF1QztBQUN2QywrQ0FNNEI7QUFDNUIsK0RBT29DO0FBQ3BDLCtFQUFvRTtBQUNwRSwrRUFBc0c7QUFDdEcseURBS2lDO0FBQ2pDLHlFQUFtRTtBQUVuRSw2Q0FBdUU7QUFFdkUsTUFBYSxZQUFhLFNBQVEsc0JBQVM7SUFDekIsTUFBTSxDQUFTO0lBQ2YsWUFBWSxDQUFlO0lBQzNCLHNCQUFzQixDQUFTO0lBQy9CLGNBQWMsQ0FBUztJQUN2QixVQUFVLENBQVM7SUFFbkMsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFlO1FBQ3ZELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsK0RBQStEO1FBQy9ELE1BQU0sU0FBUyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUV4RSxvQ0FBb0M7UUFDcEMsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLGVBQU0sQ0FDMUIsSUFBSSxFQUNKLEdBQUcsS0FBSyxDQUFDLFVBQVUsRUFBRSxXQUFXLEVBQUUsaUJBQWlCLEVBQ25EO1lBQ0UsYUFBYSxFQUFFLDJCQUFhLENBQUMsT0FBTztZQUNwQyxpQkFBaUIsRUFBRSxJQUFJO1lBQ3ZCLGNBQWMsRUFBRSxDQUFDLEVBQUUsVUFBVSxFQUFFLHNCQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7WUFDbkQsaUJBQWlCLEVBQUUsMEJBQWlCLENBQUMsU0FBUztZQUM5QyxVQUFVLEVBQUUseUJBQWdCLENBQUMsVUFBVTtZQUN2QyxTQUFTLEVBQUUsS0FBSztZQUNoQixrRkFBa0Y7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XG5pbXBvcnQge1xuICBCdWNrZXQsXG4gIEJsb2NrUHVibGljQWNjZXNzLFxuICBCdWNrZXRFbmNyeXB0aW9uLFxuICBCdWNrZXRBY2Nlc3NDb250cm9sLFxuICBPYmplY3RPd25lcnNoaXAsXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtczNcIjtcbmltcG9ydCB7XG4gIERpc3RyaWJ1dGlvbixcbiAgVmlld2VyUHJvdG9jb2xQb2xpY3ksXG4gIEFsbG93ZWRNZXRob2RzLFxuICBQcmljZUNsYXNzLFxuICBSZXNwb25zZUhlYWRlcnNQb2xpY3ksXG4gIENmbkRpc3RyaWJ1dGlvbixcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1jbG91ZGZyb250XCI7XG5pbXBvcnQgeyBTM0J1Y2tldE9yaWdpbiB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtY2xvdWRmcm9udC1vcmlnaW5zXCI7XG5pbXBvcnQgeyBDZXJ0aWZpY2F0ZSwgQ2VydGlmaWNhdGVWYWxpZGF0aW9uLCBJQ2VydGlmaWNhdGUgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNlcnRpZmljYXRlbWFuYWdlclwiO1xuaW1wb3J0IHtcbiAgSG9zdGVkWm9uZSxcbiAgSUhvc3RlZFpvbmUsXG4gIEFSZWNvcmQsXG4gIFJlY29yZFRhcmdldCxcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1yb3V0ZTUzXCI7XG5pbXBvcnQgeyBDbG91ZEZyb250VGFyZ2V0IH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1yb3V0ZTUzLXRhcmdldHNcIjtcbmltcG9ydCB7IFNwYVByb3BzIH0gZnJvbSBcIi4uL2ludGVyZmFjZXMvU3BhUHJvcHNcIjtcbmltcG9ydCB7IFRhZ3MsIFJlbW92YWxQb2xpY3ksIER1cmF0aW9uLCBDZm5PdXRwdXQgfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcblxuZXhwb3J0IGNsYXNzIFNwYUNGUm91dGU1MyBleHRlbmRzIENvbnN0cnVjdCB7XG4gIHB1YmxpYyByZWFkb25seSBidWNrZXQ6IEJ1Y2tldDtcbiAgcHVibGljIHJlYWRvbmx5IGRpc3RyaWJ1dGlvbjogRGlzdHJpYnV0aW9uO1xuICBwdWJsaWMgcmVhZG9ubHkgZGlzdHJpYnV0aW9uRG9tYWluTmFtZTogc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgZGlzdHJpYnV0aW9uSWQ6IHN0cmluZztcbiAgcHVibGljIHJlYWRvbmx5IGxvZ3NCdWNrZXQ6IEJ1Y2tldDtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogU3BhUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgLy8gQnVpbGQgYSBzYWZlIGtleSBmcm9tIGRvbWFpbiBmb3IgZXhwb3J0IG5hbWVzIChyZXBsYWNlIGRvdHMpXG4gICAgY29uc3QgZG9tYWluS2V5ID0gKHByb3BzLmZxZG4gPz8gcHJvcHMuZG9tYWluTmFtZSkuc3BsaXQoXCIuXCIpLmpvaW4oXCItXCIpO1xuXG4gICAgLy8gTG9ncyBidWNrZXQgd2l0aCAxNC1kYXkgcmV0ZW50aW9uXG4gICAgdGhpcy5sb2dzQnVja2V0ID0gbmV3IEJ1Y2tldChcbiAgICAgIHRoaXMsXG4gICAgICBgJHtwcm9wcy5kb21haW5OYW1lPy50b0xvd2VyQ2FzZSgpfS1zcGEtYnVja2V0LWxvZ2AsXG4gICAgICB7XG4gICAgICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgICAgYXV0b0RlbGV0ZU9iamVjdHM6IHRydWUsXG4gICAgICAgIGxpZmVjeWNsZVJ1bGVzOiBbeyBleHBpcmF0aW9uOiBEdXJhdGlvbi5kYXlzKDE0KSB9XSxcbiAgICAgICAgYmxvY2tQdWJsaWNBY2Nlc3M6IEJsb2NrUHVibGljQWNjZXNzLkJMT0NLX0FMTCxcbiAgICAgICAgZW5jcnlwdGlvbjogQnVja2V0RW5jcnlwdGlvbi5TM19NQU5BR0VELFxuICAgICAgICB2ZXJzaW9uZWQ6IGZhbHNlLFxuICAgICAgICAvLyBDbG91ZEZyb250IHN0YW5kYXJkIGxvZ3MgcmVxdWlyZSBBQ0xzOyBlbmFibGUgdGhlbSBhbmQgZ3JhbnQgbG9nIGRlbGl2ZXJ5IHdyaXRlXG4gICAgICAgIG9iamVjdE93bmVyc2hpcDogT2JqZWN0T3duZXJzaGlwLk9CSkVDVF9XUklURVIsXG4gICAgICAgIGFjY2Vzc0NvbnRyb2w6IEJ1Y2tldEFjY2Vzc0NvbnRyb2wuTE9HX0RFTElWRVJZX1dSSVRFLFxuICAgICAgfSxcbiAgICApO1xuXG4gICAgLy8gTWFpbiBTUEEgYnVja2V0XG4gICAgdGhpcy5idWNrZXQgPSBuZXcgQnVja2V0KFxuICAgICAgdGhpcyxcbiAgICAgIGAke3Byb3BzLmRvbWFpbk5hbWU/LnRvTG93ZXJDYXNlKCl9LXNwYS1idWNrZXRgLFxuICAgICAge1xuICAgICAgICBidWNrZXROYW1lOiBwcm9wcy5idWNrZXROYW1lLFxuICAgICAgICByZW1vdmFsUG9saWN5OiBSZW1vdmFsUG9saWN5LkRFU1RST1ksXG4gICAgICAgIGF1dG9EZWxldGVPYmplY3RzOiB0cnVlLFxuICAgICAgICBibG9ja1B1YmxpY0FjY2VzczogQmxvY2tQdWJsaWNBY2Nlc3MuQkxPQ0tfQUxMLFxuICAgICAgICBlbmNyeXB0aW9uOiBCdWNrZXRFbmNyeXB0aW9uLlMzX01BTkFHRUQsXG4gICAgICAgIHZlcnNpb25lZDogdHJ1ZSxcbiAgICAgICAgc2VydmVyQWNjZXNzTG9nc0J1Y2tldDogdGhpcy5sb2dzQnVja2V0LFxuICAgICAgICBzZXJ2ZXJBY2Nlc3NMb2dzUHJlZml4OiBcInNwYS9cIixcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIC8vIFJvdXRlNTMgaG9zdGVkIHpvbmVcbiAgICAvLyBQcmVmZXIgZGlyZWN0IGltcG9ydCB3aGVuIGEgaG9zdGVkWm9uZUlkIGlzIHByb3ZpZGVkOyB1c2UgYSBkdW1teSBob3N0ZWQgem9uZSBmb3IgdGVzdHM7XG4gICAgLy8gb3RoZXJ3aXNlIHBlcmZvcm0gYSBsb29rdXAgaW4gdGhlIGN1cnJlbnQgYWNjb3VudC5cbiAgICBjb25zdCBob3N0ZWRab25lOiBJSG9zdGVkWm9uZSA9XG4gICAgICBwcm9wcy5ob3N0ZWRab25lSWRcbiAgICAgICAgPyBIb3N0ZWRab25lLmZyb21Ib3N0ZWRab25lQXR0cmlidXRlcyh0aGlzLCBcIkhvc3RlZFpvbmVcIiwge1xuICAgICAgICAgICAgaG9zdGVkWm9uZUlkOiBwcm9wcy5ob3N0ZWRab25lSWQsXG4gICAgICAgICAgICB6b25lTmFtZTogcHJvcHMuZG9tYWluTmFtZSxcbiAgICAgICAgICB9KVxuICAgICAgICA6IEhvc3RlZFpvbmUuZnJvbUxvb2t1cCh0aGlzLCBcIkhvc3RlZFpvbmVcIiwge1xuICAgICAgICAgICAgZG9tYWluTmFtZTogcHJvcHMuZG9tYWluTmFtZSxcbiAgICAgICAgICB9KTtcblxuICAgIC8vIEFDTSBjZXJ0aWZpY2F0ZSAobXVzdCBiZSBpbiB1cy1lYXN0LTEgZm9yIENsb3VkRnJvbnQpXG4gICAgLy8gQ3JlYXRlIGEgRE5TLXZhbGlkYXRlZCBjZXJ0aWZpY2F0ZSBpbiB1cy1lYXN0LTEgYW5kIHRhZyBpdCB3aXRoIGEgZnJpZW5kbHkgbmFtZVxuICAgIGNvbnN0IGNlcnRpZmljYXRlOiBJQ2VydGlmaWNhdGUgPSBuZXcgQ2VydGlmaWNhdGUodGhpcywgXCJTcGFDZXJ0XCIsIHtcbiAgICAgIGRvbWFpbk5hbWU6IHByb3BzLmRvbWFpbk5hbWUsXG4gICAgICBzdWJqZWN0QWx0ZXJuYXRpdmVOYW1lczogW1xuICAgICAgICBwcm9wcy5mcWRuLCAgICAgICBcbiAgICAgIF0sXG4gICAgICAgIHZhbGlkYXRpb246IENlcnRpZmljYXRlVmFsaWRhdGlvbi5mcm9tRG5zKGhvc3RlZFpvbmUpLFxuICAgIH0pO1xuICAgIC8vIFRhZyBmb3IgdmlzaWJpbGl0eSBpbiBjb25zb2xlOiBcIkNlcnRpZmljYXRlIG5hbWVcIlxuICAgIFRhZ3Mub2YoY2VydGlmaWNhdGUpLmFkZChcIk5hbWVcIiwgYCR7cHJvcHMuc2l0ZU5hbWV9LWNlcnQtY2ZgKTtcblxuICAgIC8vIENsb3VkRnJvbnQgZGlzdHJpYnV0aW9uXG4gICAgdGhpcy5kaXN0cmlidXRpb24gPSBuZXcgRGlzdHJpYnV0aW9uKHRoaXMsIFwiU3BhRGlzdHJpYnV0aW9uXCIsIHtcbiAgICAgIGRlZmF1bHRCZWhhdmlvcjoge1xuICAgICAgICBvcmlnaW46IFMzQnVja2V0T3JpZ2luLndpdGhPcmlnaW5BY2Nlc3NDb250cm9sKHRoaXMuYnVja2V0KSxcbiAgICAgICAgdmlld2VyUHJvdG9jb2xQb2xpY3k6IFZpZXdlclByb3RvY29sUG9saWN5LlJFRElSRUNUX1RPX0hUVFBTLFxuICAgICAgICBhbGxvd2VkTWV0aG9kczogQWxsb3dlZE1ldGhvZHMuQUxMT1dfR0VUX0hFQUQsXG4gICAgICAgIGNhY2hlUG9saWN5OiB1bmRlZmluZWQsIC8vIEN1c3RvbSBjYWNoZSBwb2xpY3kgY2FuIGJlIGFkZGVkXG4gICAgICAgIGNvbXByZXNzOiB0cnVlLFxuICAgICAgICByZXNwb25zZUhlYWRlcnNQb2xpY3k6XG4gICAgICAgICAgUmVzcG9uc2VIZWFkZXJzUG9saWN5LkNPUlNfQUxMT1dfQUxMX09SSUdJTlNfV0lUSF9QUkVGTElHSFRfQU5EX1NFQ1VSSVRZX0hFQURFUlMsXG4gICAgICB9LFxuICAgICAgZGVmYXVsdFJvb3RPYmplY3Q6IFwiaW5kZXguaHRtbFwiLFxuICAgICAgZG9tYWluTmFtZXM6IFtwcm9wcy5mcWRuXSxcbiAgICAgIGNlcnRpZmljYXRlLFxuICAgICAgcHJpY2VDbGFzczogUHJpY2VDbGFzcy5QUklDRV9DTEFTU18xMDAsXG4gICAgICBlbmFibGVMb2dnaW5nOiB0cnVlLFxuICAgICAgbG9nQnVja2V0OiB0aGlzLmxvZ3NCdWNrZXQsXG4gICAgICBsb2dGaWxlUHJlZml4OiBcImNsb3VkZnJvbnQvXCIsXG4gICAgICBlcnJvclJlc3BvbnNlczogW1xuICAgICAgICB7XG4gICAgICAgICAgaHR0cFN0YXR1czogNDAzLFxuICAgICAgICAgIHJlc3BvbnNlSHR0cFN0YXR1czogMjAwLFxuICAgICAgICAgIHJlc3BvbnNlUGFnZVBhdGg6IFwiL2luZGV4Lmh0bWxcIixcbiAgICAgICAgICB0dGw6IER1cmF0aW9uLm1pbnV0ZXMoNSksXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBodHRwU3RhdHVzOiA0MDQsXG4gICAgICAgICAgcmVzcG9uc2VIdHRwU3RhdHVzOiAyMDAsXG4gICAgICAgICAgcmVzcG9uc2VQYWdlUGF0aDogXCIvaW5kZXguaHRtbFwiLFxuICAgICAgICAgIHR0bDogRHVyYXRpb24ubWludXRlcyg1KSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG5cbiAgICAvLyBGb3JjZSBUTFMgMS4zIGluIHRoZSBzeW50aGVzaXplZCB0ZW1wbGF0ZSB0byBzYXRpc2Z5IHRlc3RzXG4gICAgY29uc3QgY2ZuRGlzdCA9IHRoaXMuZGlzdHJpYnV0aW9uLm5vZGUuZGVmYXVsdENoaWxkIGFzIENmbkRpc3RyaWJ1dGlvbjtcbiAgICBjZm5EaXN0LmFkZFByb3BlcnR5T3ZlcnJpZGUoXG4gICAgICBcIkRpc3RyaWJ1dGlvbkNvbmZpZy5WaWV3ZXJDZXJ0aWZpY2F0ZS5NaW5pbXVtUHJvdG9jb2xWZXJzaW9uXCIsXG4gICAgICBcIlRMU3YxLjNfMjAyNVwiLFxuICAgICk7XG5cbiAgICB0aGlzLmRpc3RyaWJ1dGlvbkRvbWFpbk5hbWUgPSB0aGlzLmRpc3RyaWJ1dGlvbi5kaXN0cmlidXRpb25Eb21haW5OYW1lO1xuICAgIHRoaXMuZGlzdHJpYnV0aW9uSWQgPSB0aGlzLmRpc3RyaWJ1dGlvbi5kaXN0cmlidXRpb25JZDtcblxuICAgIC8vIFJvdXRlNTMgYWxpYXMgcmVjb3JkXG4gICAgbmV3IEFSZWNvcmQodGhpcywgXCJTcGFBbGlhc1JlY29yZFwiLCB7XG4gICAgICB6b25lOiBob3N0ZWRab25lLFxuICAgICAgcmVjb3JkTmFtZTogcHJvcHMuZnFkbixcbiAgICAgIHRhcmdldDogUmVjb3JkVGFyZ2V0LmZyb21BbGlhcyhuZXcgQ2xvdWRGcm9udFRhcmdldCh0aGlzLmRpc3RyaWJ1dGlvbikpLFxuICAgIH0pO1xuXG4gICAgLy8gVGFnZ2luZ1xuICAgIFRhZ3Mub2YodGhpcy5idWNrZXQpLmFkZChcIkFwcFwiLCBwcm9wcy5zaXRlTmFtZSk7XG4gICAgVGFncy5vZih0aGlzLmJ1Y2tldCkuYWRkKFwiUmVzb3VyY2VQcmVmaXhcIiwgcHJvcHMuc2l0ZU5hbWUpO1xuICAgIFRhZ3Mub2YodGhpcy5kaXN0cmlidXRpb24pLmFkZChcIkFwcFwiLCBwcm9wcy5zaXRlTmFtZSk7XG4gICAgVGFncy5vZih0aGlzLmRpc3RyaWJ1dGlvbikuYWRkKFwiUmVzb3VyY2VQcmVmaXhcIiwgcHJvcHMuc2l0ZU5hbWUpO1xuICAgIFRhZ3Mub2YodGhpcy5sb2dzQnVja2V0KS5hZGQoXCJBcHBcIiwgcHJvcHMuc2l0ZU5hbWUpO1xuICAgIFRhZ3Mub2YodGhpcy5sb2dzQnVja2V0KS5hZGQoXCJSZXNvdXJjZVByZWZpeFwiLCBwcm9wcy5zaXRlTmFtZSk7XG5cbiAgICAvLyBDbG91ZEZvcm1hdGlvbiBvdXRwdXRzIGZvciBjcmVhdGVkIHJlc291cmNlc1xuICAgIG5ldyBDZm5PdXRwdXQodGhpcywgXCJTcGFCdWNrZXROYW1lXCIsIHsgdmFsdWU6IHRoaXMuYnVja2V0LmJ1Y2tldE5hbWUgfSk7XG4gICAgbmV3IENmbk91dHB1dCh0aGlzLCBcIlNwYUxvZ3NCdWNrZXROYW1lXCIsIHsgdmFsdWU6IHRoaXMubG9nc0J1Y2tldC5idWNrZXROYW1lIH0pO1xuICAgIG5ldyBDZm5PdXRwdXQodGhpcywgXCJTcGFDZXJ0aWZpY2F0ZUFyblwiLCB7IHZhbHVlOiBjZXJ0aWZpY2F0ZS5jZXJ0aWZpY2F0ZUFybiB9KTtcbiAgICBuZXcgQ2ZuT3V0cHV0KHRoaXMsIFwiU3BhRGlzdHJpYnV0aW9uSWRcIiwgeyB2YWx1ZTogdGhpcy5kaXN0cmlidXRpb24uZGlzdHJpYnV0aW9uSWQgfSk7XG4gICAgbmV3IENmbk91dHB1dCh0aGlzLCBcIlNwYURpc3RyaWJ1dGlvbkRvbWFpbk5hbWVcIiwgeyB2YWx1ZTogdGhpcy5kaXN0cmlidXRpb24uZGlzdHJpYnV0aW9uRG9tYWluTmFtZSB9KTtcbiAgICBuZXcgQ2ZuT3V0cHV0KHRoaXMsIFwiU3BhQWxpYXNSZWNvcmROYW1lXCIsIHsgdmFsdWU6IHByb3BzLmZxZG4gfSk7XG4gIH1cbn1cbiJdfQ==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sylvesterllc/aws-constructs",
3
- "version": "1.1.69",
3
+ "version": "1.1.72",
4
4
  "description": "AWS Constructs",
5
5
  "main": "dist/index.js",
6
6
  "keywords": [
@@ -11,7 +11,7 @@
11
11
  "build": "npm run clean && tsc",
12
12
  "build:layers": "cd ./src/resources/layers/common && pnpm i && tsc",
13
13
  "watch": "tsc -w",
14
- "test": "bun test",
14
+ "test": "jest --passWithNoTests",
15
15
  "cdk": "cdk",
16
16
  "clean": "rm -rf dist",
17
17
  "clean:install": "npm run clean:nm && npm i",
@@ -14,8 +14,8 @@ import {
14
14
  ResponseHeadersPolicy,
15
15
  CfnDistribution,
16
16
  } from "aws-cdk-lib/aws-cloudfront";
17
- import { S3Origin } from "aws-cdk-lib/aws-cloudfront-origins";
18
- import { DnsValidatedCertificate, ICertificate } from "aws-cdk-lib/aws-certificatemanager";
17
+ import { S3BucketOrigin } from "aws-cdk-lib/aws-cloudfront-origins";
18
+ import { Certificate, CertificateValidation, ICertificate } from "aws-cdk-lib/aws-certificatemanager";
19
19
  import {
20
20
  HostedZone,
21
21
  IHostedZone,
@@ -24,8 +24,7 @@ import {
24
24
  } from "aws-cdk-lib/aws-route53";
25
25
  import { CloudFrontTarget } from "aws-cdk-lib/aws-route53-targets";
26
26
  import { SpaProps } from "../interfaces/SpaProps";
27
- import { Tags, RemovalPolicy, Duration } from "aws-cdk-lib";
28
- import { ulid } from "../helpers/ulid";
27
+ import { Tags, RemovalPolicy, Duration, CfnOutput } from "aws-cdk-lib";
29
28
 
30
29
  export class SpaCFRoute53 extends Construct {
31
30
  public readonly bucket: Bucket;
@@ -37,13 +36,13 @@ export class SpaCFRoute53 extends Construct {
37
36
  constructor(scope: Construct, id: string, props: SpaProps) {
38
37
  super(scope, id);
39
38
 
40
- // Generate a unique suffix for resource names
41
- const uniqueId = ulid();
39
+ // Build a safe key from domain for export names (replace dots)
40
+ const domainKey = (props.fqdn ?? props.domainName).split(".").join("-");
42
41
 
43
42
  // Logs bucket with 14-day retention
44
43
  this.logsBucket = new Bucket(
45
44
  this,
46
- `${props.domainName?.toLowerCase()}-spa-bucket-log-${uniqueId}`,
45
+ `${props.domainName?.toLowerCase()}-spa-bucket-log`,
47
46
  {
48
47
  removalPolicy: RemovalPolicy.DESTROY,
49
48
  autoDeleteObjects: true,
@@ -60,7 +59,7 @@ export class SpaCFRoute53 extends Construct {
60
59
  // Main SPA bucket
61
60
  this.bucket = new Bucket(
62
61
  this,
63
- `${props.domainName?.toLowerCase()}-spa-bucket-${uniqueId}`,
62
+ `${props.domainName?.toLowerCase()}-spa-bucket`,
64
63
  {
65
64
  bucketName: props.bucketName,
66
65
  removalPolicy: RemovalPolicy.DESTROY,
@@ -77,12 +76,7 @@ export class SpaCFRoute53 extends Construct {
77
76
  // Prefer direct import when a hostedZoneId is provided; use a dummy hosted zone for tests;
78
77
  // otherwise perform a lookup in the current account.
79
78
  const hostedZone: IHostedZone =
80
- props.domainName === "example.com"
81
- ? HostedZone.fromHostedZoneAttributes(this, "HostedZone", {
82
- hostedZoneId: "Z000000000000000TEST",
83
- zoneName: props.domainName,
84
- })
85
- : props.hostedZoneId
79
+ props.hostedZoneId
86
80
  ? HostedZone.fromHostedZoneAttributes(this, "HostedZone", {
87
81
  hostedZoneId: props.hostedZoneId,
88
82
  zoneName: props.domainName,
@@ -93,11 +87,12 @@ export class SpaCFRoute53 extends Construct {
93
87
 
94
88
  // ACM certificate (must be in us-east-1 for CloudFront)
95
89
  // Create a DNS-validated certificate in us-east-1 and tag it with a friendly name
96
- const certificate: ICertificate = new DnsValidatedCertificate(this, "SpaCert", {
97
- domainName: props.fqdn,
98
- hostedZone,
99
- region: "us-east-1",
100
- subjectAlternativeNames: props.domainName && props.domainName !== props.fqdn ? [props.domainName] : undefined,
90
+ const certificate: ICertificate = new Certificate(this, "SpaCert", {
91
+ domainName: props.domainName,
92
+ subjectAlternativeNames: [
93
+ props.fqdn,
94
+ ],
95
+ validation: CertificateValidation.fromDns(hostedZone),
101
96
  });
102
97
  // Tag for visibility in console: "Certificate name"
103
98
  Tags.of(certificate).add("Name", `${props.siteName}-cert-cf`);
@@ -105,7 +100,7 @@ export class SpaCFRoute53 extends Construct {
105
100
  // CloudFront distribution
106
101
  this.distribution = new Distribution(this, "SpaDistribution", {
107
102
  defaultBehavior: {
108
- origin: new S3Origin(this.bucket),
103
+ origin: S3BucketOrigin.withOriginAccessControl(this.bucket),
109
104
  viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
110
105
  allowedMethods: AllowedMethods.ALLOW_GET_HEAD,
111
106
  cachePolicy: undefined, // Custom cache policy can be added
@@ -160,5 +155,13 @@ export class SpaCFRoute53 extends Construct {
160
155
  Tags.of(this.distribution).add("ResourcePrefix", props.siteName);
161
156
  Tags.of(this.logsBucket).add("App", props.siteName);
162
157
  Tags.of(this.logsBucket).add("ResourcePrefix", props.siteName);
158
+
159
+ // CloudFormation outputs for created resources
160
+ new CfnOutput(this, "SpaBucketName", { value: this.bucket.bucketName });
161
+ new CfnOutput(this, "SpaLogsBucketName", { value: this.logsBucket.bucketName });
162
+ new CfnOutput(this, "SpaCertificateArn", { value: certificate.certificateArn });
163
+ new CfnOutput(this, "SpaDistributionId", { value: this.distribution.distributionId });
164
+ new CfnOutput(this, "SpaDistributionDomainName", { value: this.distribution.distributionDomainName });
165
+ new CfnOutput(this, "SpaAliasRecordName", { value: props.fqdn });
163
166
  }
164
167
  }