@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.
@@ -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 {};
@@ -16,16 +16,16 @@ var logDestinations = require('aws-cdk-lib/aws-logs-destinations');
16
16
  var s3n = require('aws-cdk-lib/aws-s3-notifications');
17
17
  var sqs = require('aws-cdk-lib/aws-sqs');
18
18
  var lambdaEventSources = require('aws-cdk-lib/aws-lambda-event-sources');
19
+ var logs = require('aws-cdk-lib/aws-logs');
19
20
  var awsEvents = require('aws-cdk-lib/aws-events');
20
21
  var awsEventsTargets = require('aws-cdk-lib/aws-events-targets');
21
- var awsLogs = require('aws-cdk-lib/aws-logs');
22
+ var cloudfront = require('aws-cdk-lib/aws-cloudfront');
23
+ var origins = require('aws-cdk-lib/aws-cloudfront-origins');
22
24
  var cdkNextjsStandalone = require('cdk-nextjs-standalone');
23
25
  var path = require('path');
24
26
  var awsCloudtrail = require('aws-cdk-lib/aws-cloudtrail');
25
27
  var awsSso = require('aws-cdk-lib/aws-sso');
26
28
  var awsSam = require('aws-cdk-lib/aws-sam');
27
- var cloudfront = require('aws-cdk-lib/aws-cloudfront');
28
- var origins = require('aws-cdk-lib/aws-cloudfront-origins');
29
29
 
30
30
  function _interopNamespaceDefault(e) {
31
31
  var n = Object.create(null);
@@ -56,9 +56,10 @@ var logDestinations__namespace = /*#__PURE__*/_interopNamespaceDefault(logDestin
56
56
  var s3n__namespace = /*#__PURE__*/_interopNamespaceDefault(s3n);
57
57
  var sqs__namespace = /*#__PURE__*/_interopNamespaceDefault(sqs);
58
58
  var lambdaEventSources__namespace = /*#__PURE__*/_interopNamespaceDefault(lambdaEventSources);
59
- var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
59
+ var logs__namespace = /*#__PURE__*/_interopNamespaceDefault(logs);
60
60
  var cloudfront__namespace = /*#__PURE__*/_interopNamespaceDefault(cloudfront);
61
61
  var origins__namespace = /*#__PURE__*/_interopNamespaceDefault(origins);
62
+ var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
62
63
 
63
64
  const CDK$2 = {
64
65
  ACCOUNT: {
@@ -900,7 +901,7 @@ class JaypieAppStack extends JaypieStack {
900
901
  class JaypieLambda extends constructs.Construct {
901
902
  constructor(scope, id, props) {
902
903
  super(scope, id);
903
- const { allowAllOutbound, allowPublicSubnet, architecture = lambda__namespace.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__namespace.Runtime.NODEJS_22_X, runtimeManagementMode, secrets = [], securityGroups, timeout = cdk.Duration.seconds(CDK$2.DURATION.LAMBDA_WORKER), tracing, vendorTag, vpc, vpcSubnets, } = props;
904
+ const { allowAllOutbound, allowPublicSubnet, architecture = lambda__namespace.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__namespace.Runtime.NODEJS_22_X, runtimeManagementMode, secrets = [], securityGroups, timeout = cdk.Duration.seconds(CDK$2.DURATION.LAMBDA_WORKER), tracing, vendorTag, vpc, vpcSubnets, } = props;
904
905
  // Get base environment with defaults
905
906
  const environment = jaypieLambdaEnv({ initialEnvironment });
906
907
  const codeAsset = typeof code === "string" ? lambda__namespace.Code.fromAsset(code) : code;
@@ -926,6 +927,12 @@ class JaypieLambda extends constructs.Construct {
926
927
  paramsAndSecrets,
927
928
  options: paramsAndSecretsOptions,
928
929
  });
930
+ // Create LogGroup if not provided
931
+ const resolvedLogGroup = logGroup ??
932
+ new logs__namespace.LogGroup(this, "LogGroup", {
933
+ retention: logRetention,
934
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
935
+ });
929
936
  // Create Lambda Function
930
937
  this._lambda = new lambda__namespace.Function(this, "Function", {
931
938
  allowAllOutbound,
@@ -946,9 +953,7 @@ class JaypieLambda extends constructs.Construct {
946
953
  handler,
947
954
  initialPolicy,
948
955
  layers: resolvedLayers,
949
- logRetention,
950
- logRetentionRole,
951
- logRetentionRetryOptions,
956
+ logGroup: resolvedLogGroup,
952
957
  maxEventAge,
953
958
  memorySize,
954
959
  paramsAndSecrets: resolvedParamsAndSecrets,
@@ -1119,7 +1124,7 @@ class JaypieLambda extends constructs.Construct {
1119
1124
  class JaypieQueuedLambda extends constructs.Construct {
1120
1125
  constructor(scope, id, props) {
1121
1126
  super(scope, id);
1122
- 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__namespace.Runtime.NODEJS_22_X, runtimeManagementMode, secrets = [], securityGroups, timeout = cdk.Duration.seconds(CDK$2.DURATION.LAMBDA_WORKER), tracing, vendorTag, visibilityTimeout = cdk.Duration.seconds(CDK$2.DURATION.LAMBDA_WORKER), vpc, vpcSubnets, } = props;
1127
+ 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__namespace.Runtime.NODEJS_22_X, runtimeManagementMode, secrets = [], securityGroups, timeout = cdk.Duration.seconds(CDK$2.DURATION.LAMBDA_WORKER), tracing, vendorTag, visibilityTimeout = cdk.Duration.seconds(CDK$2.DURATION.LAMBDA_WORKER), vpc, vpcSubnets, } = props;
1123
1128
  // Create SQS Queue
1124
1129
  this._queue = new sqs__namespace.Queue(this, "Queue", {
1125
1130
  fifo,
@@ -1154,9 +1159,8 @@ class JaypieQueuedLambda extends constructs.Construct {
1154
1159
  handler,
1155
1160
  initialPolicy,
1156
1161
  layers,
1162
+ logGroup,
1157
1163
  logRetention,
1158
- logRetentionRole,
1159
- logRetentionRetryOptions,
1160
1164
  maxEventAge,
1161
1165
  memorySize,
1162
1166
  paramsAndSecrets,
@@ -1659,6 +1663,178 @@ class JaypieDatadogForwarder extends constructs.Construct {
1659
1663
  }
1660
1664
  }
1661
1665
 
1666
+ class JaypieDistribution extends constructs.Construct {
1667
+ constructor(scope, id, props) {
1668
+ super(scope, id);
1669
+ const { certificate: certificateProp = true, handler, host: propsHost, invokeMode = lambda__namespace.InvokeMode.BUFFERED, roleTag = CDK$2.ROLE.API, zone: propsZone, defaultBehavior: propsDefaultBehavior, ...distributionProps } = props;
1670
+ // Validate environment variables
1671
+ if (process.env.CDK_ENV_API_SUBDOMAIN &&
1672
+ !isValidSubdomain(process.env.CDK_ENV_API_SUBDOMAIN)) {
1673
+ throw new Error("CDK_ENV_API_SUBDOMAIN is not a valid subdomain");
1674
+ }
1675
+ if (process.env.CDK_ENV_API_HOSTED_ZONE &&
1676
+ !isValidHostname$1(process.env.CDK_ENV_API_HOSTED_ZONE)) {
1677
+ throw new Error("CDK_ENV_API_HOSTED_ZONE is not a valid hostname");
1678
+ }
1679
+ if (process.env.CDK_ENV_HOSTED_ZONE &&
1680
+ !isValidHostname$1(process.env.CDK_ENV_HOSTED_ZONE)) {
1681
+ throw new Error("CDK_ENV_HOSTED_ZONE is not a valid hostname");
1682
+ }
1683
+ // Determine host from props or environment
1684
+ let host = propsHost;
1685
+ if (!host) {
1686
+ try {
1687
+ if (process.env.CDK_ENV_API_HOST_NAME) {
1688
+ host = process.env.CDK_ENV_API_HOST_NAME;
1689
+ }
1690
+ else if (process.env.CDK_ENV_API_SUBDOMAIN) {
1691
+ host = mergeDomain(process.env.CDK_ENV_API_SUBDOMAIN, process.env.CDK_ENV_API_HOSTED_ZONE ||
1692
+ process.env.CDK_ENV_HOSTED_ZONE ||
1693
+ "");
1694
+ }
1695
+ }
1696
+ catch {
1697
+ host = undefined;
1698
+ }
1699
+ }
1700
+ if (host && !isValidHostname$1(host)) {
1701
+ throw new Error("Host is not a valid hostname");
1702
+ }
1703
+ this.host = host;
1704
+ // Determine zone from props or environment
1705
+ const zone = propsZone || process.env.CDK_ENV_HOSTED_ZONE;
1706
+ // Resolve the origin from handler
1707
+ // Check order matters: IFunctionUrl before IOrigin (FunctionUrl also has bind method)
1708
+ // IFunction before IFunctionUrl (IFunction doesn't have functionUrlId)
1709
+ let origin;
1710
+ if (handler) {
1711
+ if (this.isIFunction(handler)) {
1712
+ // Create FunctionUrl for the Lambda function
1713
+ const functionUrl = new lambda__namespace.FunctionUrl(this, "FunctionUrl", {
1714
+ function: handler,
1715
+ authType: lambda__namespace.FunctionUrlAuthType.NONE,
1716
+ invokeMode,
1717
+ });
1718
+ this.functionUrl = functionUrl;
1719
+ origin = new origins__namespace.FunctionUrlOrigin(functionUrl);
1720
+ }
1721
+ else if (this.isIFunctionUrl(handler)) {
1722
+ origin = new origins__namespace.FunctionUrlOrigin(handler);
1723
+ }
1724
+ else if (this.isIOrigin(handler)) {
1725
+ origin = handler;
1726
+ }
1727
+ }
1728
+ // Build default behavior
1729
+ let defaultBehavior;
1730
+ if (propsDefaultBehavior) {
1731
+ defaultBehavior = propsDefaultBehavior;
1732
+ }
1733
+ else if (origin) {
1734
+ defaultBehavior = {
1735
+ cachePolicy: cloudfront__namespace.CachePolicy.CACHING_DISABLED,
1736
+ origin,
1737
+ originRequestPolicy: cloudfront__namespace.OriginRequestPolicy.ALL_VIEWER,
1738
+ viewerProtocolPolicy: cloudfront__namespace.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
1739
+ };
1740
+ }
1741
+ else {
1742
+ throw new Error("Either handler or defaultBehavior must be provided to JaypieDistribution");
1743
+ }
1744
+ // Resolve hosted zone and certificate
1745
+ // Only resolve zone when we need it (for certificate or DNS)
1746
+ let hostedZone;
1747
+ let certificateToUse;
1748
+ if (host && zone && certificateProp !== false) {
1749
+ hostedZone = resolveHostedZone(this, { zone });
1750
+ if (certificateProp === true) {
1751
+ certificateToUse = new acm__namespace.Certificate(this, constructEnvName("Certificate"), {
1752
+ domainName: host,
1753
+ validation: acm__namespace.CertificateValidation.fromDns(hostedZone),
1754
+ });
1755
+ cdk.Tags.of(certificateToUse).add(CDK$2.TAG.ROLE, roleTag);
1756
+ }
1757
+ else if (typeof certificateProp === "object") {
1758
+ certificateToUse = certificateProp;
1759
+ }
1760
+ this.certificate = certificateToUse;
1761
+ }
1762
+ // Create the CloudFront distribution
1763
+ this.distribution = new cloudfront__namespace.Distribution(this, constructEnvName("Distribution"), {
1764
+ defaultBehavior,
1765
+ ...(host && certificateToUse
1766
+ ? {
1767
+ certificate: certificateToUse,
1768
+ domainNames: [host],
1769
+ }
1770
+ : {}),
1771
+ ...distributionProps,
1772
+ });
1773
+ cdk.Tags.of(this.distribution).add(CDK$2.TAG.ROLE, roleTag);
1774
+ this.distributionArn = `arn:aws:cloudfront::${cdk.Stack.of(this).account}:distribution/${this.distribution.distributionId}`;
1775
+ this.distributionDomainName = this.distribution.distributionDomainName;
1776
+ this.distributionId = this.distribution.distributionId;
1777
+ this.domainName = this.distribution.domainName;
1778
+ // Create DNS record if we have host and zone
1779
+ if (host && hostedZone) {
1780
+ const record = new route53__namespace.ARecord(this, "AliasRecord", {
1781
+ recordName: host,
1782
+ target: route53__namespace.RecordTarget.fromAlias(new route53Targets__namespace.CloudFrontTarget(this.distribution)),
1783
+ zone: hostedZone,
1784
+ });
1785
+ cdk.Tags.of(record).add(CDK$2.TAG.ROLE, CDK$2.ROLE.NETWORKING);
1786
+ }
1787
+ }
1788
+ // Type guards for handler types
1789
+ isIOrigin(handler) {
1790
+ return (typeof handler === "object" &&
1791
+ handler !== null &&
1792
+ "bind" in handler &&
1793
+ typeof handler.bind === "function");
1794
+ }
1795
+ isIFunctionUrl(handler) {
1796
+ // FunctionUrl has 'url' property which is the function URL string
1797
+ // IFunction does not have 'url' property
1798
+ return (typeof handler === "object" &&
1799
+ handler !== null &&
1800
+ "url" in handler &&
1801
+ "functionArn" in handler);
1802
+ }
1803
+ isIFunction(handler) {
1804
+ // IFunction has functionArn and functionName but NOT 'url'
1805
+ // (FunctionUrl also has functionArn but also has 'url')
1806
+ return (typeof handler === "object" &&
1807
+ handler !== null &&
1808
+ "functionArn" in handler &&
1809
+ "functionName" in handler &&
1810
+ !("url" in handler));
1811
+ }
1812
+ // Implement IDistribution interface
1813
+ get env() {
1814
+ return {
1815
+ account: cdk.Stack.of(this).account,
1816
+ region: cdk.Stack.of(this).region,
1817
+ };
1818
+ }
1819
+ get stack() {
1820
+ return this.distribution.stack;
1821
+ }
1822
+ applyRemovalPolicy(policy) {
1823
+ this.distribution.applyRemovalPolicy(policy);
1824
+ }
1825
+ grant(identity, ...actions) {
1826
+ return this.distribution.grant(identity, ...actions);
1827
+ }
1828
+ grantCreateInvalidation(identity) {
1829
+ return this.distribution.grantCreateInvalidation(identity);
1830
+ }
1831
+ get distributionRef() {
1832
+ return {
1833
+ distributionId: this.distribution.distributionId,
1834
+ };
1835
+ }
1836
+ }
1837
+
1662
1838
  // It is a consumer if the environment is ephemeral
1663
1839
  function checkEnvIsConsumer(env = process.env) {
1664
1840
  return (env.PROJECT_ENV === CDK$2.ENV.PERSONAL ||
@@ -2118,11 +2294,11 @@ class JaypieHostedZone extends constructs.Construct {
2118
2294
  const destination = props.destination ?? true;
2119
2295
  const service = props.service || CDK$2.SERVICE.INFRASTRUCTURE;
2120
2296
  // Create the log group
2121
- this.logGroup = new awsLogs.LogGroup(this, "LogGroup", {
2297
+ this.logGroup = new logs.LogGroup(this, "LogGroup", {
2122
2298
  logGroupName: process.env.PROJECT_NONCE
2123
2299
  ? `/aws/route53/${zoneName}-${process.env.PROJECT_NONCE}`
2124
2300
  : `/aws/route53/${zoneName}`,
2125
- retention: awsLogs.RetentionDays.ONE_WEEK,
2301
+ retention: logs.RetentionDays.ONE_WEEK,
2126
2302
  });
2127
2303
  // Add tags
2128
2304
  cdk__namespace.Tags.of(this.logGroup).add(CDK$2.TAG.SERVICE, service);
@@ -2139,7 +2315,7 @@ class JaypieHostedZone extends constructs.Construct {
2139
2315
  : destination;
2140
2316
  this.logGroup.addSubscriptionFilter("DatadogLambdaDestination", {
2141
2317
  destination: lambdaDestination,
2142
- filterPattern: awsLogs.FilterPattern.allEvents(),
2318
+ filterPattern: logs.FilterPattern.allEvents(),
2143
2319
  });
2144
2320
  }
2145
2321
  // Create the hosted zone
@@ -2800,7 +2976,7 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
2800
2976
  this.bucket = new s3__namespace.Bucket(this, "DestinationBucket", {
2801
2977
  accessControl: s3__namespace.BucketAccessControl.BUCKET_OWNER_FULL_CONTROL,
2802
2978
  autoDeleteObjects: true,
2803
- blockPublicAccess: s3__namespace.BlockPublicAccess.BLOCK_ACLS,
2979
+ blockPublicAccess: s3__namespace.BlockPublicAccess.BLOCK_ACLS_ONLY,
2804
2980
  bucketName: props.name || constructEnvName("web"),
2805
2981
  publicReadAccess: true,
2806
2982
  removalPolicy: cdk.RemovalPolicy.DESTROY,
@@ -2853,11 +3029,14 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
2853
3029
  actions: ["s3:ListBucket"],
2854
3030
  resources: [this.bucket.bucketArn],
2855
3031
  }));
2856
- // Allow the role to deploy CDK apps
3032
+ // Allow the role to describe the current stack
3033
+ const stack = cdk.Stack.of(this);
2857
3034
  bucketDeployRole.addToPolicy(new awsIam.PolicyStatement({
2858
3035
  actions: ["cloudformation:DescribeStacks"],
2859
3036
  effect: awsIam.Effect.ALLOW,
2860
- resources: ["*"], // TODO: restrict to this stack
3037
+ resources: [
3038
+ `arn:aws:cloudformation:${stack.region}:${stack.account}:stack/${stack.stackName}/*`,
3039
+ ],
2861
3040
  }));
2862
3041
  this.deployRoleArn = bucketDeployRole.roleArn;
2863
3042
  // Output the deploy role ARN
@@ -2890,7 +3069,7 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
2890
3069
  this.distribution = new cloudfront__namespace.Distribution(this, "Distribution", {
2891
3070
  defaultBehavior: {
2892
3071
  cachePolicy: cloudfront__namespace.CachePolicy.CACHING_DISABLED,
2893
- origin: new origins__namespace.S3Origin(this.bucket),
3072
+ origin: new origins__namespace.S3StaticWebsiteOrigin(this.bucket),
2894
3073
  viewerProtocolPolicy: cloudfront__namespace.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
2895
3074
  },
2896
3075
  certificate: this.certificate,
@@ -2899,7 +3078,7 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
2899
3078
  cdk.Tags.of(this.distribution).add(CDK$2.TAG.ROLE, roleTag);
2900
3079
  // If this is production, enable caching on everything but index.html
2901
3080
  if (isProductionEnv()) {
2902
- this.distribution.addBehavior("/*", new origins__namespace.S3Origin(this.bucket), {
3081
+ this.distribution.addBehavior("/*", new origins__namespace.S3StaticWebsiteOrigin(this.bucket), {
2903
3082
  viewerProtocolPolicy: cloudfront__namespace.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
2904
3083
  cachePolicy: cloudfront__namespace.CachePolicy.CACHING_OPTIMIZED,
2905
3084
  });
@@ -3020,6 +3199,7 @@ exports.JaypieBucketQueuedLambda = JaypieBucketQueuedLambda;
3020
3199
  exports.JaypieDatadogBucket = JaypieDatadogBucket;
3021
3200
  exports.JaypieDatadogForwarder = JaypieDatadogForwarder;
3022
3201
  exports.JaypieDatadogSecret = JaypieDatadogSecret;
3202
+ exports.JaypieDistribution = JaypieDistribution;
3023
3203
  exports.JaypieDnsRecord = JaypieDnsRecord;
3024
3204
  exports.JaypieEnvSecret = JaypieEnvSecret;
3025
3205
  exports.JaypieEventsRule = JaypieEventsRule;