@jaypie/constructs 1.1.61 → 1.1.62-rc.1

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.
@@ -5,6 +5,7 @@ export { JaypieAppStack } from "./JaypieAppStack";
5
5
  export { JaypieBucketQueuedLambda } from "./JaypieBucketQueuedLambda";
6
6
  export { JaypieDatadogBucket, JaypieDatadogBucketProps, } from "./JaypieDatadogBucket";
7
7
  export { JaypieDatadogForwarder, JaypieDatadogForwarderProps, } from "./JaypieDatadogForwarder";
8
+ export { JaypieDistribution, JaypieDistributionProps, } from "./JaypieDistribution";
8
9
  export { JaypieDatadogSecret } from "./JaypieDatadogSecret";
9
10
  export { JaypieDnsRecord, JaypieDnsRecordProps } from "./JaypieDnsRecord";
10
11
  export { JaypieEnvSecret } from "./JaypieEnvSecret";
@@ -0,0 +1,65 @@
1
+ import { RemovalPolicy, Stack } from "aws-cdk-lib";
2
+ import * as acm from "aws-cdk-lib/aws-certificatemanager";
3
+ import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
4
+ import * as lambda from "aws-cdk-lib/aws-lambda";
5
+ import * as route53 from "aws-cdk-lib/aws-route53";
6
+ import { Construct } from "constructs";
7
+ export interface JaypieDistributionProps extends Omit<cloudfront.DistributionProps, "certificate" | "defaultBehavior"> {
8
+ /**
9
+ * SSL certificate for the CloudFront distribution
10
+ * @default true (creates a new certificate)
11
+ */
12
+ certificate?: boolean | acm.ICertificate;
13
+ /**
14
+ * Override default behavior (optional if handler is provided)
15
+ */
16
+ defaultBehavior?: cloudfront.BehaviorOptions;
17
+ /**
18
+ * The origin handler - can be an IOrigin, IFunctionUrl, or IFunction
19
+ * If IFunction, a FunctionUrl will be created with auth NONE
20
+ */
21
+ handler?: cloudfront.IOrigin | lambda.IFunctionUrl | lambda.IFunction;
22
+ /**
23
+ * The domain name for the distribution
24
+ * @default mergeDomain(CDK_ENV_API_SUBDOMAIN, CDK_ENV_API_HOSTED_ZONE || CDK_ENV_HOSTED_ZONE)
25
+ */
26
+ host?: string;
27
+ /**
28
+ * Invoke mode for Lambda Function URLs
29
+ * @default InvokeMode.BUFFERED
30
+ */
31
+ invokeMode?: lambda.InvokeMode;
32
+ /**
33
+ * Role tag for tagging resources
34
+ * @default CDK.ROLE.HOSTING
35
+ */
36
+ roleTag?: string;
37
+ /**
38
+ * The hosted zone for DNS records
39
+ * @default CDK_ENV_API_HOSTED_ZONE || CDK_ENV_HOSTED_ZONE
40
+ */
41
+ zone?: string | route53.IHostedZone;
42
+ }
43
+ export declare class JaypieDistribution extends Construct implements cloudfront.IDistribution {
44
+ readonly certificate?: acm.ICertificate;
45
+ readonly distribution: cloudfront.Distribution;
46
+ readonly distributionArn: string;
47
+ readonly distributionDomainName: string;
48
+ readonly distributionId: string;
49
+ readonly domainName: string;
50
+ readonly functionUrl?: lambda.FunctionUrl;
51
+ readonly host?: string;
52
+ constructor(scope: Construct, id: string, props: JaypieDistributionProps);
53
+ private isIOrigin;
54
+ private isIFunctionUrl;
55
+ private isIFunction;
56
+ get env(): {
57
+ account: string;
58
+ region: string;
59
+ };
60
+ get stack(): Stack;
61
+ applyRemovalPolicy(policy: RemovalPolicy): void;
62
+ grant(identity: import("aws-cdk-lib/aws-iam").IGrantable, ...actions: string[]): import("aws-cdk-lib/aws-iam").Grant;
63
+ grantCreateInvalidation(identity: import("aws-cdk-lib/aws-iam").IGrantable): import("aws-cdk-lib/aws-iam").Grant;
64
+ get distributionRef(): cloudfront.DistributionReference;
65
+ }
@@ -1,9 +1,10 @@
1
1
  import { Construct } from "constructs";
2
2
  import { Duration, Stack, RemovalPolicy } from "aws-cdk-lib";
3
3
  import * as lambda from "aws-cdk-lib/aws-lambda";
4
- import * as iam from "aws-cdk-lib/aws-iam";
5
4
  import * as cloudwatch from "aws-cdk-lib/aws-cloudwatch";
6
5
  import * as ec2 from "aws-cdk-lib/aws-ec2";
6
+ import * as iam from "aws-cdk-lib/aws-iam";
7
+ import * as logs from "aws-cdk-lib/aws-logs";
7
8
  import * as secretsmanager from "aws-cdk-lib/aws-secretsmanager";
8
9
  import { JaypieEnvSecret } from "./JaypieEnvSecret.js";
9
10
  export interface JaypieLambdaProps {
@@ -27,9 +28,8 @@ export interface JaypieLambdaProps {
27
28
  handler: string;
28
29
  initialPolicy?: iam.PolicyStatement[];
29
30
  layers?: lambda.ILayerVersion[];
30
- logRetention?: number;
31
- logRetentionRole?: iam.IRole;
32
- logRetentionRetryOptions?: lambda.LogRetentionRetryOptions;
31
+ logGroup?: logs.ILogGroup;
32
+ logRetention?: logs.RetentionDays | number;
33
33
  maxEventAge?: Duration;
34
34
  memorySize?: number;
35
35
  paramsAndSecrets?: lambda.ParamsAndSecretsLayerVersion | boolean;
@@ -0,0 +1 @@
1
+ export {};
@@ -5,6 +5,7 @@ export { JaypieAppStack } from "./JaypieAppStack";
5
5
  export { JaypieBucketQueuedLambda } from "./JaypieBucketQueuedLambda";
6
6
  export { JaypieDatadogBucket, JaypieDatadogBucketProps, } from "./JaypieDatadogBucket";
7
7
  export { JaypieDatadogForwarder, JaypieDatadogForwarderProps, } from "./JaypieDatadogForwarder";
8
+ export { JaypieDistribution, JaypieDistributionProps, } from "./JaypieDistribution";
8
9
  export { JaypieDatadogSecret } from "./JaypieDatadogSecret";
9
10
  export { JaypieDnsRecord, JaypieDnsRecordProps } from "./JaypieDnsRecord";
10
11
  export { JaypieEnvSecret } from "./JaypieEnvSecret";
package/dist/esm/index.js CHANGED
@@ -18,16 +18,17 @@ import * as s3n from 'aws-cdk-lib/aws-s3-notifications';
18
18
  import { LambdaDestination } from 'aws-cdk-lib/aws-s3-notifications';
19
19
  import * as sqs from 'aws-cdk-lib/aws-sqs';
20
20
  import * as lambdaEventSources from 'aws-cdk-lib/aws-lambda-event-sources';
21
+ import * as logs from 'aws-cdk-lib/aws-logs';
22
+ import { LogGroup, RetentionDays, FilterPattern } from 'aws-cdk-lib/aws-logs';
21
23
  import { Rule, RuleTargetInput } from 'aws-cdk-lib/aws-events';
22
24
  import { LambdaFunction } from 'aws-cdk-lib/aws-events-targets';
23
- import { LogGroup, RetentionDays, FilterPattern } from 'aws-cdk-lib/aws-logs';
25
+ import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
26
+ import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';
24
27
  import { Nextjs } from 'cdk-nextjs-standalone';
25
28
  import * as path from 'path';
26
29
  import { Trail, ReadWriteType } from 'aws-cdk-lib/aws-cloudtrail';
27
30
  import { CfnPermissionSet, CfnAssignment } from 'aws-cdk-lib/aws-sso';
28
31
  import { CfnApplication } from 'aws-cdk-lib/aws-sam';
29
- import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
30
- import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';
31
32
 
32
33
  const CDK$2 = {
33
34
  ACCOUNT: {
@@ -869,7 +870,7 @@ class JaypieAppStack extends JaypieStack {
869
870
  class JaypieLambda extends Construct {
870
871
  constructor(scope, id, props) {
871
872
  super(scope, id);
872
- const { allowAllOutbound, allowPublicSubnet, architecture = lambda.Architecture.X86_64, code, datadogApiKeyArn, deadLetterQueue, deadLetterQueueEnabled, deadLetterTopic, description, environment: initialEnvironment = {}, envSecrets = {}, ephemeralStorageSize, filesystem, handler = "index.handler", initialPolicy, layers = [], logRetention = CDK$2.LAMBDA.LOG_RETENTION, logRetentionRole, logRetentionRetryOptions, maxEventAge, memorySize = CDK$2.LAMBDA.MEMORY_SIZE, paramsAndSecrets, paramsAndSecretsOptions, profiling, profilingGroup, provisionedConcurrentExecutions, reservedConcurrentExecutions, retryAttempts, roleTag = CDK$2.ROLE.PROCESSING, runtime = lambda.Runtime.NODEJS_22_X, runtimeManagementMode, secrets = [], securityGroups, timeout = Duration.seconds(CDK$2.DURATION.LAMBDA_WORKER), tracing, vendorTag, vpc, vpcSubnets, } = props;
873
+ const { allowAllOutbound, allowPublicSubnet, architecture = lambda.Architecture.X86_64, code, datadogApiKeyArn, deadLetterQueue, deadLetterQueueEnabled, deadLetterTopic, description, environment: initialEnvironment = {}, envSecrets = {}, ephemeralStorageSize, filesystem, handler = "index.handler", initialPolicy, layers = [], logGroup, logRetention = CDK$2.LAMBDA.LOG_RETENTION, maxEventAge, memorySize = CDK$2.LAMBDA.MEMORY_SIZE, paramsAndSecrets, paramsAndSecretsOptions, profiling, profilingGroup, provisionedConcurrentExecutions, reservedConcurrentExecutions, retryAttempts, roleTag = CDK$2.ROLE.PROCESSING, runtime = lambda.Runtime.NODEJS_22_X, runtimeManagementMode, secrets = [], securityGroups, timeout = Duration.seconds(CDK$2.DURATION.LAMBDA_WORKER), tracing, vendorTag, vpc, vpcSubnets, } = props;
873
874
  // Get base environment with defaults
874
875
  const environment = jaypieLambdaEnv({ initialEnvironment });
875
876
  const codeAsset = typeof code === "string" ? lambda.Code.fromAsset(code) : code;
@@ -895,6 +896,12 @@ class JaypieLambda extends Construct {
895
896
  paramsAndSecrets,
896
897
  options: paramsAndSecretsOptions,
897
898
  });
899
+ // Create LogGroup if not provided
900
+ const resolvedLogGroup = logGroup ??
901
+ new logs.LogGroup(this, "LogGroup", {
902
+ retention: logRetention,
903
+ removalPolicy: RemovalPolicy.DESTROY,
904
+ });
898
905
  // Create Lambda Function
899
906
  this._lambda = new lambda.Function(this, "Function", {
900
907
  allowAllOutbound,
@@ -915,9 +922,7 @@ class JaypieLambda extends Construct {
915
922
  handler,
916
923
  initialPolicy,
917
924
  layers: resolvedLayers,
918
- logRetention,
919
- logRetentionRole,
920
- logRetentionRetryOptions,
925
+ logGroup: resolvedLogGroup,
921
926
  maxEventAge,
922
927
  memorySize,
923
928
  paramsAndSecrets: resolvedParamsAndSecrets,
@@ -1088,7 +1093,7 @@ class JaypieLambda extends Construct {
1088
1093
  class JaypieQueuedLambda extends Construct {
1089
1094
  constructor(scope, id, props) {
1090
1095
  super(scope, id);
1091
- const { allowAllOutbound, allowPublicSubnet, architecture, batchSize = 1, code, datadogApiKeyArn, deadLetterQueue, deadLetterQueueEnabled, deadLetterTopic, description, environment = {}, envSecrets = {}, ephemeralStorageSize, fifo = true, filesystem, handler = "index.handler", initialPolicy, layers = [], logRetention = CDK$2.LAMBDA.LOG_RETENTION, logRetentionRole, logRetentionRetryOptions, maxEventAge, memorySize = CDK$2.LAMBDA.MEMORY_SIZE, paramsAndSecrets, paramsAndSecretsOptions, profiling, profilingGroup, provisionedConcurrentExecutions, reservedConcurrentExecutions, retryAttempts, roleTag, runtime = lambda.Runtime.NODEJS_22_X, runtimeManagementMode, secrets = [], securityGroups, timeout = Duration.seconds(CDK$2.DURATION.LAMBDA_WORKER), tracing, vendorTag, visibilityTimeout = Duration.seconds(CDK$2.DURATION.LAMBDA_WORKER), vpc, vpcSubnets, } = props;
1096
+ const { allowAllOutbound, allowPublicSubnet, architecture, batchSize = 1, code, datadogApiKeyArn, deadLetterQueue, deadLetterQueueEnabled, deadLetterTopic, description, environment = {}, envSecrets = {}, ephemeralStorageSize, fifo = true, filesystem, handler = "index.handler", initialPolicy, layers = [], logGroup, logRetention = CDK$2.LAMBDA.LOG_RETENTION, maxEventAge, memorySize = CDK$2.LAMBDA.MEMORY_SIZE, paramsAndSecrets, paramsAndSecretsOptions, profiling, profilingGroup, provisionedConcurrentExecutions, reservedConcurrentExecutions, retryAttempts, roleTag, runtime = lambda.Runtime.NODEJS_22_X, runtimeManagementMode, secrets = [], securityGroups, timeout = Duration.seconds(CDK$2.DURATION.LAMBDA_WORKER), tracing, vendorTag, visibilityTimeout = Duration.seconds(CDK$2.DURATION.LAMBDA_WORKER), vpc, vpcSubnets, } = props;
1092
1097
  // Create SQS Queue
1093
1098
  this._queue = new sqs.Queue(this, "Queue", {
1094
1099
  fifo,
@@ -1123,9 +1128,8 @@ class JaypieQueuedLambda extends Construct {
1123
1128
  handler,
1124
1129
  initialPolicy,
1125
1130
  layers,
1131
+ logGroup,
1126
1132
  logRetention,
1127
- logRetentionRole,
1128
- logRetentionRetryOptions,
1129
1133
  maxEventAge,
1130
1134
  memorySize,
1131
1135
  paramsAndSecrets,
@@ -1628,6 +1632,178 @@ class JaypieDatadogForwarder extends Construct {
1628
1632
  }
1629
1633
  }
1630
1634
 
1635
+ class JaypieDistribution extends Construct {
1636
+ constructor(scope, id, props) {
1637
+ super(scope, id);
1638
+ const { certificate: certificateProp = true, handler, host: propsHost, invokeMode = lambda.InvokeMode.BUFFERED, roleTag = CDK$2.ROLE.API, zone: propsZone, defaultBehavior: propsDefaultBehavior, ...distributionProps } = props;
1639
+ // Validate environment variables
1640
+ if (process.env.CDK_ENV_API_SUBDOMAIN &&
1641
+ !isValidSubdomain(process.env.CDK_ENV_API_SUBDOMAIN)) {
1642
+ throw new Error("CDK_ENV_API_SUBDOMAIN is not a valid subdomain");
1643
+ }
1644
+ if (process.env.CDK_ENV_API_HOSTED_ZONE &&
1645
+ !isValidHostname$1(process.env.CDK_ENV_API_HOSTED_ZONE)) {
1646
+ throw new Error("CDK_ENV_API_HOSTED_ZONE is not a valid hostname");
1647
+ }
1648
+ if (process.env.CDK_ENV_HOSTED_ZONE &&
1649
+ !isValidHostname$1(process.env.CDK_ENV_HOSTED_ZONE)) {
1650
+ throw new Error("CDK_ENV_HOSTED_ZONE is not a valid hostname");
1651
+ }
1652
+ // Determine host from props or environment
1653
+ let host = propsHost;
1654
+ if (!host) {
1655
+ try {
1656
+ if (process.env.CDK_ENV_API_HOST_NAME) {
1657
+ host = process.env.CDK_ENV_API_HOST_NAME;
1658
+ }
1659
+ else if (process.env.CDK_ENV_API_SUBDOMAIN) {
1660
+ host = mergeDomain(process.env.CDK_ENV_API_SUBDOMAIN, process.env.CDK_ENV_API_HOSTED_ZONE ||
1661
+ process.env.CDK_ENV_HOSTED_ZONE ||
1662
+ "");
1663
+ }
1664
+ }
1665
+ catch {
1666
+ host = undefined;
1667
+ }
1668
+ }
1669
+ if (host && !isValidHostname$1(host)) {
1670
+ throw new Error("Host is not a valid hostname");
1671
+ }
1672
+ this.host = host;
1673
+ // Determine zone from props or environment
1674
+ const zone = propsZone || process.env.CDK_ENV_HOSTED_ZONE;
1675
+ // Resolve the origin from handler
1676
+ // Check order matters: IFunctionUrl before IOrigin (FunctionUrl also has bind method)
1677
+ // IFunction before IFunctionUrl (IFunction doesn't have functionUrlId)
1678
+ let origin;
1679
+ if (handler) {
1680
+ if (this.isIFunction(handler)) {
1681
+ // Create FunctionUrl for the Lambda function
1682
+ const functionUrl = new lambda.FunctionUrl(this, "FunctionUrl", {
1683
+ function: handler,
1684
+ authType: lambda.FunctionUrlAuthType.NONE,
1685
+ invokeMode,
1686
+ });
1687
+ this.functionUrl = functionUrl;
1688
+ origin = new origins.FunctionUrlOrigin(functionUrl);
1689
+ }
1690
+ else if (this.isIFunctionUrl(handler)) {
1691
+ origin = new origins.FunctionUrlOrigin(handler);
1692
+ }
1693
+ else if (this.isIOrigin(handler)) {
1694
+ origin = handler;
1695
+ }
1696
+ }
1697
+ // Build default behavior
1698
+ let defaultBehavior;
1699
+ if (propsDefaultBehavior) {
1700
+ defaultBehavior = propsDefaultBehavior;
1701
+ }
1702
+ else if (origin) {
1703
+ defaultBehavior = {
1704
+ cachePolicy: cloudfront.CachePolicy.CACHING_DISABLED,
1705
+ origin,
1706
+ originRequestPolicy: cloudfront.OriginRequestPolicy.ALL_VIEWER,
1707
+ viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
1708
+ };
1709
+ }
1710
+ else {
1711
+ throw new Error("Either handler or defaultBehavior must be provided to JaypieDistribution");
1712
+ }
1713
+ // Resolve hosted zone and certificate
1714
+ // Only resolve zone when we need it (for certificate or DNS)
1715
+ let hostedZone;
1716
+ let certificateToUse;
1717
+ if (host && zone && certificateProp !== false) {
1718
+ hostedZone = resolveHostedZone(this, { zone });
1719
+ if (certificateProp === true) {
1720
+ certificateToUse = new acm.Certificate(this, constructEnvName("Certificate"), {
1721
+ domainName: host,
1722
+ validation: acm.CertificateValidation.fromDns(hostedZone),
1723
+ });
1724
+ Tags.of(certificateToUse).add(CDK$2.TAG.ROLE, roleTag);
1725
+ }
1726
+ else if (typeof certificateProp === "object") {
1727
+ certificateToUse = certificateProp;
1728
+ }
1729
+ this.certificate = certificateToUse;
1730
+ }
1731
+ // Create the CloudFront distribution
1732
+ this.distribution = new cloudfront.Distribution(this, constructEnvName("Distribution"), {
1733
+ defaultBehavior,
1734
+ ...(host && certificateToUse
1735
+ ? {
1736
+ certificate: certificateToUse,
1737
+ domainNames: [host],
1738
+ }
1739
+ : {}),
1740
+ ...distributionProps,
1741
+ });
1742
+ Tags.of(this.distribution).add(CDK$2.TAG.ROLE, roleTag);
1743
+ this.distributionArn = `arn:aws:cloudfront::${Stack.of(this).account}:distribution/${this.distribution.distributionId}`;
1744
+ this.distributionDomainName = this.distribution.distributionDomainName;
1745
+ this.distributionId = this.distribution.distributionId;
1746
+ this.domainName = this.distribution.domainName;
1747
+ // Create DNS record if we have host and zone
1748
+ if (host && hostedZone) {
1749
+ const record = new route53.ARecord(this, "AliasRecord", {
1750
+ recordName: host,
1751
+ target: route53.RecordTarget.fromAlias(new route53Targets.CloudFrontTarget(this.distribution)),
1752
+ zone: hostedZone,
1753
+ });
1754
+ Tags.of(record).add(CDK$2.TAG.ROLE, CDK$2.ROLE.NETWORKING);
1755
+ }
1756
+ }
1757
+ // Type guards for handler types
1758
+ isIOrigin(handler) {
1759
+ return (typeof handler === "object" &&
1760
+ handler !== null &&
1761
+ "bind" in handler &&
1762
+ typeof handler.bind === "function");
1763
+ }
1764
+ isIFunctionUrl(handler) {
1765
+ // FunctionUrl has 'url' property which is the function URL string
1766
+ // IFunction does not have 'url' property
1767
+ return (typeof handler === "object" &&
1768
+ handler !== null &&
1769
+ "url" in handler &&
1770
+ "functionArn" in handler);
1771
+ }
1772
+ isIFunction(handler) {
1773
+ // IFunction has functionArn and functionName but NOT 'url'
1774
+ // (FunctionUrl also has functionArn but also has 'url')
1775
+ return (typeof handler === "object" &&
1776
+ handler !== null &&
1777
+ "functionArn" in handler &&
1778
+ "functionName" in handler &&
1779
+ !("url" in handler));
1780
+ }
1781
+ // Implement IDistribution interface
1782
+ get env() {
1783
+ return {
1784
+ account: Stack.of(this).account,
1785
+ region: Stack.of(this).region,
1786
+ };
1787
+ }
1788
+ get stack() {
1789
+ return this.distribution.stack;
1790
+ }
1791
+ applyRemovalPolicy(policy) {
1792
+ this.distribution.applyRemovalPolicy(policy);
1793
+ }
1794
+ grant(identity, ...actions) {
1795
+ return this.distribution.grant(identity, ...actions);
1796
+ }
1797
+ grantCreateInvalidation(identity) {
1798
+ return this.distribution.grantCreateInvalidation(identity);
1799
+ }
1800
+ get distributionRef() {
1801
+ return {
1802
+ distributionId: this.distribution.distributionId,
1803
+ };
1804
+ }
1805
+ }
1806
+
1631
1807
  // It is a consumer if the environment is ephemeral
1632
1808
  function checkEnvIsConsumer(env = process.env) {
1633
1809
  return (env.PROJECT_ENV === CDK$2.ENV.PERSONAL ||
@@ -2769,7 +2945,7 @@ class JaypieWebDeploymentBucket extends Construct {
2769
2945
  this.bucket = new s3.Bucket(this, "DestinationBucket", {
2770
2946
  accessControl: s3.BucketAccessControl.BUCKET_OWNER_FULL_CONTROL,
2771
2947
  autoDeleteObjects: true,
2772
- blockPublicAccess: s3.BlockPublicAccess.BLOCK_ACLS,
2948
+ blockPublicAccess: s3.BlockPublicAccess.BLOCK_ACLS_ONLY,
2773
2949
  bucketName: props.name || constructEnvName("web"),
2774
2950
  publicReadAccess: true,
2775
2951
  removalPolicy: RemovalPolicy.DESTROY,
@@ -2822,11 +2998,14 @@ class JaypieWebDeploymentBucket extends Construct {
2822
2998
  actions: ["s3:ListBucket"],
2823
2999
  resources: [this.bucket.bucketArn],
2824
3000
  }));
2825
- // Allow the role to deploy CDK apps
3001
+ // Allow the role to describe the current stack
3002
+ const stack = Stack.of(this);
2826
3003
  bucketDeployRole.addToPolicy(new PolicyStatement({
2827
3004
  actions: ["cloudformation:DescribeStacks"],
2828
3005
  effect: Effect.ALLOW,
2829
- resources: ["*"], // TODO: restrict to this stack
3006
+ resources: [
3007
+ `arn:aws:cloudformation:${stack.region}:${stack.account}:stack/${stack.stackName}/*`,
3008
+ ],
2830
3009
  }));
2831
3010
  this.deployRoleArn = bucketDeployRole.roleArn;
2832
3011
  // Output the deploy role ARN
@@ -2859,7 +3038,7 @@ class JaypieWebDeploymentBucket extends Construct {
2859
3038
  this.distribution = new cloudfront.Distribution(this, "Distribution", {
2860
3039
  defaultBehavior: {
2861
3040
  cachePolicy: cloudfront.CachePolicy.CACHING_DISABLED,
2862
- origin: new origins.S3Origin(this.bucket),
3041
+ origin: new origins.S3StaticWebsiteOrigin(this.bucket),
2863
3042
  viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
2864
3043
  },
2865
3044
  certificate: this.certificate,
@@ -2868,7 +3047,7 @@ class JaypieWebDeploymentBucket extends Construct {
2868
3047
  Tags.of(this.distribution).add(CDK$2.TAG.ROLE, roleTag);
2869
3048
  // If this is production, enable caching on everything but index.html
2870
3049
  if (isProductionEnv()) {
2871
- this.distribution.addBehavior("/*", new origins.S3Origin(this.bucket), {
3050
+ this.distribution.addBehavior("/*", new origins.S3StaticWebsiteOrigin(this.bucket), {
2872
3051
  viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
2873
3052
  cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
2874
3053
  });
@@ -2981,5 +3160,5 @@ class JaypieWebDeploymentBucket extends Construct {
2981
3160
  }
2982
3161
  }
2983
3162
 
2984
- export { CDK$2 as CDK, JaypieAccountLoggingBucket, JaypieApiGateway, JaypieAppStack, JaypieBucketQueuedLambda, JaypieDatadogBucket, JaypieDatadogForwarder, JaypieDatadogSecret, JaypieDnsRecord, JaypieEnvSecret, JaypieEventsRule, JaypieExpressLambda, JaypieGitHubDeployRole, JaypieHostedZone, JaypieInfrastructureStack, JaypieLambda, JaypieMongoDbSecret, JaypieNextJs, JaypieOpenAiSecret, JaypieOrganizationTrail, JaypieQueuedLambda, JaypieSsoPermissions, JaypieSsoSyncApplication, JaypieStack, JaypieTraceSigningKeySecret, JaypieWebDeploymentBucket, addDatadogLayers, constructEnvName, constructStackName, constructTagger, envHostname, extendDatadogRole, isEnv, isProductionEnv, isSandboxEnv, isValidHostname$1 as isValidHostname, isValidSubdomain, jaypieLambdaEnv, mergeDomain, resolveDatadogForwarderFunction, resolveDatadogLayers, resolveDatadogLoggingDestination, resolveHostedZone, resolveParamsAndSecrets };
3163
+ export { CDK$2 as CDK, JaypieAccountLoggingBucket, JaypieApiGateway, JaypieAppStack, JaypieBucketQueuedLambda, JaypieDatadogBucket, JaypieDatadogForwarder, JaypieDatadogSecret, JaypieDistribution, JaypieDnsRecord, JaypieEnvSecret, JaypieEventsRule, JaypieExpressLambda, JaypieGitHubDeployRole, JaypieHostedZone, JaypieInfrastructureStack, JaypieLambda, JaypieMongoDbSecret, JaypieNextJs, JaypieOpenAiSecret, JaypieOrganizationTrail, JaypieQueuedLambda, JaypieSsoPermissions, JaypieSsoSyncApplication, JaypieStack, JaypieTraceSigningKeySecret, JaypieWebDeploymentBucket, addDatadogLayers, constructEnvName, constructStackName, constructTagger, envHostname, extendDatadogRole, isEnv, isProductionEnv, isSandboxEnv, isValidHostname$1 as isValidHostname, isValidSubdomain, jaypieLambdaEnv, mergeDomain, resolveDatadogForwarderFunction, resolveDatadogLayers, resolveDatadogLoggingDestination, resolveHostedZone, resolveParamsAndSecrets };
2985
3164
  //# sourceMappingURL=index.js.map