@jaypie/constructs 1.1.28 → 1.1.30

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.
@@ -1,18 +1,23 @@
1
1
  'use strict';
2
2
 
3
+ var constructs = require('constructs');
3
4
  var cdk$1 = require('aws-cdk-lib');
5
+ var acm = require('aws-cdk-lib/aws-certificatemanager');
6
+ var apiGateway = require('aws-cdk-lib/aws-apigateway');
7
+ var route53 = require('aws-cdk-lib/aws-route53');
8
+ var route53Targets = require('aws-cdk-lib/aws-route53-targets');
9
+ var cdk = require('@jaypie/cdk');
4
10
  var s3 = require('aws-cdk-lib/aws-s3');
5
11
  var s3n = require('aws-cdk-lib/aws-s3-notifications');
6
- var cdk = require('@jaypie/cdk');
7
- var constructs = require('constructs');
8
12
  var lambda = require('aws-cdk-lib/aws-lambda');
9
13
  var sqs = require('aws-cdk-lib/aws-sqs');
10
14
  var lambdaEventSources = require('aws-cdk-lib/aws-lambda-event-sources');
11
15
  var secretsmanager = require('aws-cdk-lib/aws-secretsmanager');
12
16
  var awsIam = require('aws-cdk-lib/aws-iam');
13
17
  var awsLogs = require('aws-cdk-lib/aws-logs');
14
- var awsRoute53 = require('aws-cdk-lib/aws-route53');
15
18
  var sso = require('aws-cdk-lib/aws-sso');
19
+ var cloudfront = require('aws-cdk-lib/aws-cloudfront');
20
+ var origins = require('aws-cdk-lib/aws-cloudfront-origins');
16
21
 
17
22
  function _interopNamespaceDefault(e) {
18
23
  var n = Object.create(null);
@@ -32,6 +37,10 @@ function _interopNamespaceDefault(e) {
32
37
  }
33
38
 
34
39
  var cdk__namespace = /*#__PURE__*/_interopNamespaceDefault(cdk$1);
40
+ var acm__namespace = /*#__PURE__*/_interopNamespaceDefault(acm);
41
+ var apiGateway__namespace = /*#__PURE__*/_interopNamespaceDefault(apiGateway);
42
+ var route53__namespace = /*#__PURE__*/_interopNamespaceDefault(route53);
43
+ var route53Targets__namespace = /*#__PURE__*/_interopNamespaceDefault(route53Targets);
35
44
  var s3__namespace = /*#__PURE__*/_interopNamespaceDefault(s3);
36
45
  var s3n__namespace = /*#__PURE__*/_interopNamespaceDefault(s3n);
37
46
  var lambda__namespace = /*#__PURE__*/_interopNamespaceDefault(lambda);
@@ -39,11 +48,264 @@ var sqs__namespace = /*#__PURE__*/_interopNamespaceDefault(sqs);
39
48
  var lambdaEventSources__namespace = /*#__PURE__*/_interopNamespaceDefault(lambdaEventSources);
40
49
  var secretsmanager__namespace = /*#__PURE__*/_interopNamespaceDefault(secretsmanager);
41
50
  var sso__namespace = /*#__PURE__*/_interopNamespaceDefault(sso);
51
+ var cloudfront__namespace = /*#__PURE__*/_interopNamespaceDefault(cloudfront);
52
+ var origins__namespace = /*#__PURE__*/_interopNamespaceDefault(origins);
53
+
54
+ function constructEnvName(name, opts) {
55
+ const env = opts?.env ?? process.env.PROJECT_ENV ?? "build";
56
+ const key = opts?.key ?? process.env.PROJECT_KEY ?? "project";
57
+ const nonce = opts?.nonce ?? process.env.PROJECT_NONCE ?? "cfe2";
58
+ return `${env}-${key}-${name}-${nonce}`;
59
+ }
60
+
61
+ function constructStackName(key) {
62
+ if (!key) {
63
+ return `cdk-${process.env.PROJECT_SPONSOR}-${process.env.PROJECT_KEY}-${process.env.PROJECT_ENV}-${process.env.PROJECT_NONCE}`;
64
+ }
65
+ else {
66
+ return `cdk-${process.env.PROJECT_SPONSOR}-${process.env.PROJECT_KEY}-${process.env.PROJECT_ENV}-${process.env.PROJECT_NONCE}-${key}`;
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Check if the current environment matches the given environment
72
+ */
73
+ function isEnv(env) {
74
+ return process.env.PROJECT_ENV === env;
75
+ }
76
+ /**
77
+ * Check if the current environment is production
78
+ */
79
+ function isProductionEnv() {
80
+ return isEnv(cdk.CDK.ENV.PRODUCTION);
81
+ }
82
+ /**
83
+ * Check if the current environment is sandbox
84
+ */
85
+ function isSandboxEnv() {
86
+ return isEnv(cdk.CDK.ENV.SANDBOX);
87
+ }
88
+
89
+ const CDK$1 = {
90
+ CREATION: {
91
+ CDK: "cdk",
92
+ },
93
+ ROLE: {
94
+ STACK: "stack",
95
+ },
96
+ TAG: {
97
+ BUILD_DATE: "buildDate",
98
+ BUILD_HEX: "buildHex",
99
+ BUILD_TIME: "buildTime",
100
+ COMMIT: "commit",
101
+ CREATION: "creation",
102
+ ENV: "env",
103
+ NONCE: "nonce",
104
+ PROJECT: "project",
105
+ ROLE: "role",
106
+ SERVICE: "service",
107
+ SPONSOR: "sponsor",
108
+ STACK: "stack",
109
+ VERSION: "version",
110
+ },
111
+ };
112
+ function stackTagger(stack, { name } = {}) {
113
+ const stackName = name || constructStackName();
114
+ const version = process.env.npm_package_version || process.env.PROJECT_VERSION || null;
115
+ if (process.env.PROJECT_COMMIT && process.env.PROJECT_COMMIT.length > 8) {
116
+ cdk$1.Tags.of(stack).add(CDK$1.TAG.BUILD_HEX, process.env.PROJECT_COMMIT.slice(0, 8));
117
+ }
118
+ cdk$1.Tags.of(stack).add(CDK$1.TAG.BUILD_DATE, new Date().toISOString());
119
+ cdk$1.Tags.of(stack).add(CDK$1.TAG.BUILD_TIME, Date.now().toString());
120
+ if (process.env.PROJECT_COMMIT)
121
+ cdk$1.Tags.of(stack).add(CDK$1.TAG.COMMIT, process.env.PROJECT_COMMIT);
122
+ cdk$1.Tags.of(stack).add(CDK$1.TAG.CREATION, CDK$1.CREATION.CDK);
123
+ if (process.env.PROJECT_ENV)
124
+ cdk$1.Tags.of(stack).add(CDK$1.TAG.ENV, process.env.PROJECT_ENV);
125
+ if (process.env.PROJECT_NONCE)
126
+ cdk$1.Tags.of(stack).add(CDK$1.TAG.NONCE, process.env.PROJECT_NONCE);
127
+ if (process.env.PROJECT_KEY)
128
+ cdk$1.Tags.of(stack).add(CDK$1.TAG.PROJECT, process.env.PROJECT_KEY);
129
+ cdk$1.Tags.of(stack).add(CDK$1.TAG.ROLE, CDK$1.ROLE.STACK);
130
+ if (process.env.PROJECT_SERVICE)
131
+ cdk$1.Tags.of(stack).add(CDK$1.TAG.SERVICE, process.env.PROJECT_SERVICE);
132
+ if (process.env.PROJECT_SPONSOR)
133
+ cdk$1.Tags.of(stack).add(CDK$1.TAG.SPONSOR, process.env.PROJECT_SPONSOR);
134
+ if (stackName)
135
+ cdk$1.Tags.of(stack).add(CDK$1.TAG.STACK, stackName);
136
+ if (version)
137
+ cdk$1.Tags.of(stack).add(CDK$1.TAG.VERSION, version);
138
+ return true;
139
+ }
140
+
141
+ class JaypieApiGateway extends constructs.Construct {
142
+ constructor(scope, id, props) {
143
+ super(scope, id);
144
+ const { certificate = true, handler, host, name, roleTag = cdk.CDK.ROLE.API, zone, } = props;
145
+ const apiGatewayName = name || constructEnvName("ApiGateway");
146
+ const certificateName = constructEnvName("Certificate");
147
+ const apiDomainName = constructEnvName("ApiDomainName");
148
+ let hostedZone;
149
+ let certificateToUse;
150
+ if (host && zone) {
151
+ if (typeof zone === "string") {
152
+ hostedZone = route53__namespace.HostedZone.fromLookup(this, "HostedZone", {
153
+ domainName: zone,
154
+ });
155
+ }
156
+ else {
157
+ hostedZone = zone;
158
+ }
159
+ if (certificate === true) {
160
+ certificateToUse = new acm__namespace.Certificate(this, certificateName, {
161
+ domainName: host,
162
+ validation: acm__namespace.CertificateValidation.fromDns(hostedZone),
163
+ });
164
+ cdk$1.Tags.of(certificateToUse).add(cdk.CDK.TAG.ROLE, cdk.CDK.ROLE.HOSTING);
165
+ }
166
+ else if (typeof certificate === "object") {
167
+ certificateToUse = certificate;
168
+ }
169
+ this._certificate = certificateToUse;
170
+ this._host = host;
171
+ }
172
+ const {
173
+ // * `...lambdaRestApiProps` cannot be moved to the first const destructuring because it needs to exclude the custom properties first.
174
+ // Ignore the variables we already assigned to other properties
175
+ /* eslint-disable @typescript-eslint/no-unused-vars */
176
+ certificate: _certificate, host: _host, name: _name, roleTag: _roleTag, zone: _zone, handler: _handler,
177
+ /* eslint-enable @typescript-eslint/no-unused-vars */
178
+ ...lambdaRestApiProps } = props;
179
+ this._api = new apiGateway__namespace.LambdaRestApi(this, apiGatewayName, {
180
+ handler,
181
+ ...lambdaRestApiProps,
182
+ });
183
+ cdk$1.Tags.of(this._api).add(cdk.CDK.TAG.ROLE, roleTag);
184
+ if (host && certificateToUse && hostedZone) {
185
+ this._domainName = this._api.addDomainName(apiDomainName, {
186
+ domainName: host,
187
+ certificate: certificateToUse,
188
+ });
189
+ cdk$1.Tags.of(this._domainName).add(cdk.CDK.TAG.ROLE, roleTag);
190
+ const record = new route53__namespace.ARecord(this, "AliasRecord", {
191
+ recordName: host,
192
+ target: route53__namespace.RecordTarget.fromAlias(new route53Targets__namespace.ApiGatewayDomain(this._domainName)),
193
+ zone: hostedZone,
194
+ });
195
+ cdk$1.Tags.of(record).add(cdk.CDK.TAG.ROLE, cdk.CDK.ROLE.NETWORKING);
196
+ }
197
+ }
198
+ get api() {
199
+ return this._api;
200
+ }
201
+ get url() {
202
+ return this._api.url;
203
+ }
204
+ get certificateArn() {
205
+ return this._certificate?.certificateArn;
206
+ }
207
+ get domainName() {
208
+ return this._domainName?.domainName;
209
+ }
210
+ get host() {
211
+ return this._host;
212
+ }
213
+ get restApiId() {
214
+ return this._api.restApiId;
215
+ }
216
+ get restApiName() {
217
+ return this._api.restApiName;
218
+ }
219
+ get restApiRootResourceId() {
220
+ return this._api.restApiRootResourceId;
221
+ }
222
+ get deploymentStage() {
223
+ return this._api.deploymentStage;
224
+ }
225
+ get domainNameAliasDomainName() {
226
+ return this._domainName?.domainNameAliasDomainName;
227
+ }
228
+ get domainNameAliasHostedZoneId() {
229
+ return this._domainName?.domainNameAliasHostedZoneId;
230
+ }
231
+ get root() {
232
+ return this._api.root;
233
+ }
234
+ get env() {
235
+ return {
236
+ account: cdk$1.Stack.of(this).account,
237
+ region: cdk$1.Stack.of(this).region,
238
+ };
239
+ }
240
+ get stack() {
241
+ return this._api.stack;
242
+ }
243
+ arnForExecuteApi(method, path, stage) {
244
+ return this._api.arnForExecuteApi(method, path, stage);
245
+ }
246
+ metric(metricName, props) {
247
+ return this._api.metric(metricName, props);
248
+ }
249
+ metricCacheHitCount(props) {
250
+ return this._api.metricCacheHitCount(props);
251
+ }
252
+ metricCacheMissCount(props) {
253
+ return this._api.metricCacheMissCount(props);
254
+ }
255
+ metricClientError(props) {
256
+ return this._api.metricClientError(props);
257
+ }
258
+ metricCount(props) {
259
+ return this._api.metricCount(props);
260
+ }
261
+ metricIntegrationLatency(props) {
262
+ return this._api.metricIntegrationLatency(props);
263
+ }
264
+ metricLatency(props) {
265
+ return this._api.metricLatency(props);
266
+ }
267
+ metricServerError(props) {
268
+ return this._api.metricServerError(props);
269
+ }
270
+ applyRemovalPolicy(policy) {
271
+ this._api.applyRemovalPolicy(policy);
272
+ }
273
+ }
274
+
275
+ class JaypieStack extends cdk$1.Stack {
276
+ constructor(scope, id, props = {}) {
277
+ const { key, ...stackProps } = props;
278
+ // Handle stackName
279
+ if (!stackProps.stackName) {
280
+ stackProps.stackName = constructStackName(key);
281
+ }
282
+ // Handle env
283
+ stackProps.env = {
284
+ account: process.env.CDK_DEFAULT_ACCOUNT,
285
+ region: process.env.CDK_DEFAULT_REGION,
286
+ ...stackProps.env,
287
+ };
288
+ super(scope, id, stackProps);
289
+ // Apply tags
290
+ stackTagger(this, { name: stackProps.stackName });
291
+ }
292
+ }
293
+
294
+ class JaypieAppStack extends JaypieStack {
295
+ constructor(scope, id, props = {}) {
296
+ const { key = "app", ...stackProps } = props;
297
+ // Handle stackName
298
+ if (!stackProps.stackName) {
299
+ stackProps.stackName = constructStackName(key);
300
+ }
301
+ super(scope, id, { key, ...stackProps });
302
+ }
303
+ }
42
304
 
43
305
  class JaypieLambda extends constructs.Construct {
44
306
  constructor(scope, id, props) {
45
307
  super(scope, id);
46
- const { code, datadogApiKeyArn, environment: initialEnvironment = {}, envSecrets = {}, handler = "index.handler", layers = [], logRetention = cdk.CDK.LAMBDA.LOG_RETENTION, memorySize = cdk.CDK.LAMBDA.MEMORY_SIZE, paramsAndSecrets, paramsAndSecretsOptions, reservedConcurrentExecutions, roleTag, runtime = lambda__namespace.Runtime.NODEJS_22_X, secrets = [], timeout = cdk$1.Duration.seconds(cdk.CDK.DURATION.LAMBDA_WORKER), vendorTag, } = props;
308
+ const { code, datadogApiKeyArn, environment: initialEnvironment = {}, envSecrets = {}, handler = "index.handler", layers = [], logRetention = cdk.CDK.LAMBDA.LOG_RETENTION, memorySize = cdk.CDK.LAMBDA.MEMORY_SIZE, paramsAndSecrets, paramsAndSecretsOptions, provisionedConcurrentExecutions, reservedConcurrentExecutions, roleTag = cdk.CDK.ROLE.PROCESSING, runtime = lambda__namespace.Runtime.NODEJS_22_X, secrets = [], timeout = cdk$1.Duration.seconds(cdk.CDK.DURATION.LAMBDA_WORKER), vendorTag, } = props;
47
309
  // Create a mutable copy of the environment variables
48
310
  let environment = { ...initialEnvironment };
49
311
  // Default environment variables from process.env if present
@@ -159,6 +421,14 @@ class JaypieLambda extends constructs.Construct {
159
421
  const datadogApiKey = secretsmanager__namespace.Secret.fromSecretCompleteArn(this, "DatadogApiKeyGrant", resolvedDatadogApiKeyArn);
160
422
  datadogApiKey.grantRead(this._lambda);
161
423
  }
424
+ // Configure provisioned concurrency if specified
425
+ if (provisionedConcurrentExecutions !== undefined) {
426
+ new lambda__namespace.Alias(this, "ProvisionedAlias", {
427
+ aliasName: "provisioned",
428
+ version: this._lambda.currentVersion,
429
+ provisionedConcurrentExecutions,
430
+ });
431
+ }
162
432
  if (roleTag) {
163
433
  cdk$1.Tags.of(this._lambda).add(cdk.CDK.TAG.ROLE, roleTag);
164
434
  }
@@ -845,7 +1115,7 @@ class JaypieHostedZone extends constructs.Construct {
845
1115
  });
846
1116
  }
847
1117
  // Create the hosted zone
848
- this.hostedZone = new awsRoute53.HostedZone(this, "HostedZone", {
1118
+ this.hostedZone = new route53.HostedZone(this, "HostedZone", {
849
1119
  queryLogsLogGroupArn: this.logGroup.logGroupArn,
850
1120
  zoneName,
851
1121
  });
@@ -858,6 +1128,26 @@ class JaypieHostedZone extends constructs.Construct {
858
1128
  }
859
1129
  }
860
1130
 
1131
+ const CDK = {
1132
+ TAG: {
1133
+ STACK_SHA: "stackSha",
1134
+ },
1135
+ };
1136
+ class JaypieInfrastructureStack extends JaypieStack {
1137
+ constructor(scope, id, props = {}) {
1138
+ const { key = "infra", ...stackProps } = props;
1139
+ // Handle stackName
1140
+ if (!stackProps.stackName) {
1141
+ stackProps.stackName = constructStackName(key);
1142
+ }
1143
+ super(scope, id, { key, ...stackProps });
1144
+ // Add infrastructure-specific tag
1145
+ if (process.env.CDK_ENV_INFRASTRUCTURE_STACK_SHA) {
1146
+ cdk$1.Tags.of(this).add(CDK.TAG.STACK_SHA, process.env.CDK_ENV_INFRASTRUCTURE_STACK_SHA);
1147
+ }
1148
+ }
1149
+ }
1150
+
861
1151
  class JaypieMongoDbSecret extends JaypieEnvSecret {
862
1152
  constructor(scope, id = "MongoConnectionString", props) {
863
1153
  const defaultProps = {
@@ -1168,15 +1458,271 @@ class JaypieTraceSigningKeySecret extends JaypieEnvSecret {
1168
1458
  }
1169
1459
  }
1170
1460
 
1461
+ class JaypieWebDeploymentBucket extends constructs.Construct {
1462
+ constructor(scope, id, props = {}) {
1463
+ super(scope, id);
1464
+ const roleTag = props.roleTag || cdk.CDK.ROLE.HOSTING;
1465
+ // Environment variable validation
1466
+ if (process.env.CDK_ENV_WEB_SUBDOMAIN &&
1467
+ !cdk.isValidSubdomain(process.env.CDK_ENV_WEB_SUBDOMAIN)) {
1468
+ throw new cdk.ConfigurationError("CDK_ENV_WEB_SUBDOMAIN is not a valid subdomain");
1469
+ }
1470
+ if (process.env.CDK_ENV_WEB_HOSTED_ZONE &&
1471
+ !cdk.isValidHostname(process.env.CDK_ENV_WEB_HOSTED_ZONE)) {
1472
+ throw new cdk.ConfigurationError("CDK_ENV_WEB_HOSTED_ZONE is not a valid hostname");
1473
+ }
1474
+ if (process.env.CDK_ENV_HOSTED_ZONE &&
1475
+ !cdk.isValidHostname(process.env.CDK_ENV_HOSTED_ZONE)) {
1476
+ throw new cdk.ConfigurationError("CDK_ENV_HOSTED_ZONE is not a valid hostname");
1477
+ }
1478
+ // Determine host from props or environment
1479
+ let host = props.host;
1480
+ if (!host) {
1481
+ try {
1482
+ host =
1483
+ process.env.CDK_ENV_WEB_HOST ||
1484
+ cdk.mergeDomain(process.env.CDK_ENV_WEB_SUBDOMAIN || "", process.env.CDK_ENV_WEB_HOSTED_ZONE ||
1485
+ process.env.CDK_ENV_HOSTED_ZONE ||
1486
+ "");
1487
+ }
1488
+ catch {
1489
+ host = undefined;
1490
+ }
1491
+ }
1492
+ if (host && !cdk.isValidHostname(host)) {
1493
+ throw new cdk.ConfigurationError("Host is not a valid hostname");
1494
+ }
1495
+ // Determine zone from props or environment
1496
+ const zone = props.zone ||
1497
+ process.env.CDK_ENV_WEB_HOSTED_ZONE ||
1498
+ process.env.CDK_ENV_HOSTED_ZONE;
1499
+ // Create the S3 bucket
1500
+ this.bucket = new s3__namespace.Bucket(this, "DestinationBucket", {
1501
+ accessControl: s3__namespace.BucketAccessControl.BUCKET_OWNER_FULL_CONTROL,
1502
+ autoDeleteObjects: true,
1503
+ blockPublicAccess: s3__namespace.BlockPublicAccess.BLOCK_ACLS,
1504
+ bucketName: props.name || constructEnvName("web"),
1505
+ publicReadAccess: true,
1506
+ removalPolicy: cdk$1.RemovalPolicy.DESTROY,
1507
+ versioned: false,
1508
+ websiteErrorDocument: "index.html",
1509
+ websiteIndexDocument: "index.html",
1510
+ ...props,
1511
+ });
1512
+ // Delegate IBucket properties to the bucket
1513
+ this.bucketArn = this.bucket.bucketArn;
1514
+ this.bucketDomainName = this.bucket.bucketDomainName;
1515
+ this.bucketDualStackDomainName = this.bucket.bucketDualStackDomainName;
1516
+ this.bucketName = this.bucket.bucketName;
1517
+ this.bucketRegionalDomainName = this.bucket.bucketRegionalDomainName;
1518
+ this.bucketWebsiteDomainName = this.bucket.bucketWebsiteDomainName;
1519
+ this.bucketWebsiteUrl = this.bucket.bucketWebsiteUrl;
1520
+ this.encryptionKey = this.bucket.encryptionKey;
1521
+ this.isWebsite = this.bucket.isWebsite;
1522
+ this.notificationsHandlerRole = undefined;
1523
+ this.policy = this.bucket.policy;
1524
+ cdk$1.Tags.of(this.bucket).add(cdk.CDK.TAG.ROLE, roleTag);
1525
+ // Create deployment role if repository is configured
1526
+ let repo;
1527
+ if (process.env.CDK_ENV_REPO) {
1528
+ repo = `repo:${process.env.CDK_ENV_REPO}:*`;
1529
+ }
1530
+ if (repo) {
1531
+ const bucketDeployRole = new awsIam.Role(this, "DestinationBucketDeployRole", {
1532
+ assumedBy: new awsIam.FederatedPrincipal(cdk$1.Fn.importValue(cdk.CDK.IMPORT.OIDC_PROVIDER), {
1533
+ StringLike: {
1534
+ "token.actions.githubusercontent.com:sub": repo,
1535
+ },
1536
+ }, "sts:AssumeRoleWithWebIdentity"),
1537
+ maxSessionDuration: cdk$1.Duration.hours(1),
1538
+ });
1539
+ cdk$1.Tags.of(bucketDeployRole).add(cdk.CDK.TAG.ROLE, cdk.CDK.ROLE.DEPLOY);
1540
+ // Allow the role to write to the bucket
1541
+ bucketDeployRole.addToPolicy(new awsIam.PolicyStatement({
1542
+ effect: awsIam.Effect.ALLOW,
1543
+ actions: [
1544
+ "s3:DeleteObject",
1545
+ "s3:GetObject",
1546
+ "s3:ListObjectsV2",
1547
+ "s3:PutObject",
1548
+ ],
1549
+ resources: [`${this.bucket.bucketArn}/*`],
1550
+ }));
1551
+ bucketDeployRole.addToPolicy(new awsIam.PolicyStatement({
1552
+ effect: awsIam.Effect.ALLOW,
1553
+ actions: ["s3:ListBucket"],
1554
+ resources: [this.bucket.bucketArn],
1555
+ }));
1556
+ // Allow the role to deploy CDK apps
1557
+ bucketDeployRole.addToPolicy(new awsIam.PolicyStatement({
1558
+ actions: ["cloudformation:DescribeStacks"],
1559
+ effect: awsIam.Effect.ALLOW,
1560
+ resources: ["*"], // TODO: restrict to this stack
1561
+ }));
1562
+ this.deployRoleArn = bucketDeployRole.roleArn;
1563
+ // Output the deploy role ARN
1564
+ new cdk$1.CfnOutput(this, "DestinationBucketDeployRoleArn", {
1565
+ value: bucketDeployRole.roleArn,
1566
+ });
1567
+ }
1568
+ // Create CloudFront distribution and certificate if host and zone are provided
1569
+ if (host && zone) {
1570
+ const hostedZone = typeof zone === "string"
1571
+ ? route53__namespace.HostedZone.fromLookup(this, "HostedZone", {
1572
+ domainName: zone,
1573
+ })
1574
+ : zone;
1575
+ // Create certificate if not provided
1576
+ if (props.certificate !== false) {
1577
+ this.certificate =
1578
+ typeof props.certificate === "object"
1579
+ ? props.certificate
1580
+ : new acm__namespace.Certificate(this, "Certificate", {
1581
+ domainName: host,
1582
+ validation: acm__namespace.CertificateValidation.fromDns(hostedZone),
1583
+ });
1584
+ new cdk$1.CfnOutput(this, "CertificateArn", {
1585
+ value: this.certificate.certificateArn,
1586
+ });
1587
+ cdk$1.Tags.of(this.certificate).add(cdk.CDK.TAG.ROLE, roleTag);
1588
+ }
1589
+ // Create CloudFront distribution
1590
+ this.distribution = new cloudfront__namespace.Distribution(this, "Distribution", {
1591
+ defaultBehavior: {
1592
+ cachePolicy: cloudfront__namespace.CachePolicy.CACHING_DISABLED,
1593
+ origin: new origins__namespace.S3Origin(this.bucket),
1594
+ viewerProtocolPolicy: cloudfront__namespace.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
1595
+ },
1596
+ certificate: this.certificate,
1597
+ domainNames: [host],
1598
+ });
1599
+ cdk$1.Tags.of(this.distribution).add(cdk.CDK.TAG.ROLE, roleTag);
1600
+ // If this is production, enable caching on everything but index.html
1601
+ if (isProductionEnv()) {
1602
+ this.distribution.addBehavior("/*", new origins__namespace.S3Origin(this.bucket), {
1603
+ viewerProtocolPolicy: cloudfront__namespace.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
1604
+ cachePolicy: cloudfront__namespace.CachePolicy.CACHING_OPTIMIZED,
1605
+ });
1606
+ }
1607
+ // Create DNS record
1608
+ const record = new route53__namespace.ARecord(this, "AliasRecord", {
1609
+ recordName: host,
1610
+ target: route53__namespace.RecordTarget.fromAlias(new route53Targets__namespace.CloudFrontTarget(this.distribution)),
1611
+ zone: hostedZone,
1612
+ });
1613
+ cdk$1.Tags.of(record).add(cdk.CDK.TAG.ROLE, cdk.CDK.ROLE.NETWORKING);
1614
+ this.distributionDomainName = this.distribution.distributionDomainName;
1615
+ }
1616
+ }
1617
+ // Implement remaining IBucket methods by delegating to the bucket
1618
+ addEventNotification(event, dest, ...filters) {
1619
+ this.bucket.addEventNotification(event, dest, ...filters);
1620
+ }
1621
+ addObjectCreatedNotification(dest, ...filters) {
1622
+ this.bucket.addObjectCreatedNotification(dest, ...filters);
1623
+ }
1624
+ addObjectRemovedNotification(dest, ...filters) {
1625
+ this.bucket.addObjectRemovedNotification(dest, ...filters);
1626
+ }
1627
+ addToResourcePolicy(permission) {
1628
+ return this.bucket.addToResourcePolicy(permission);
1629
+ }
1630
+ arnForObjects(keyPattern) {
1631
+ return this.bucket.arnForObjects(keyPattern);
1632
+ }
1633
+ grantDelete(identity, objectsKeyPattern) {
1634
+ return this.bucket.grantDelete(identity, objectsKeyPattern);
1635
+ }
1636
+ grantPublicAccess(allowedActions, keyPrefix) {
1637
+ return keyPrefix
1638
+ ? this.bucket.grantPublicAccess(allowedActions, keyPrefix)
1639
+ : this.bucket.grantPublicAccess(allowedActions);
1640
+ }
1641
+ grantPut(identity, objectsKeyPattern) {
1642
+ return this.bucket.grantPut(identity, objectsKeyPattern);
1643
+ }
1644
+ grantPutAcl(identity, objectsKeyPattern) {
1645
+ return this.bucket.grantPutAcl(identity, objectsKeyPattern);
1646
+ }
1647
+ grantRead(identity, objectsKeyPattern) {
1648
+ return this.bucket.grantRead(identity, objectsKeyPattern);
1649
+ }
1650
+ grantReadWrite(identity, objectsKeyPattern) {
1651
+ return this.bucket.grantReadWrite(identity, objectsKeyPattern);
1652
+ }
1653
+ grantWrite(identity, objectsKeyPattern) {
1654
+ return this.bucket.grantWrite(identity, objectsKeyPattern);
1655
+ }
1656
+ s3UrlForObject(key) {
1657
+ return this.bucket.s3UrlForObject(key);
1658
+ }
1659
+ urlForObject(key) {
1660
+ return this.bucket.urlForObject(key);
1661
+ }
1662
+ virtualHostedUrlForObject(key, options) {
1663
+ return this.bucket.virtualHostedUrlForObject(key, options);
1664
+ }
1665
+ transferAccelerationUrlForObject(key) {
1666
+ return this.bucket.transferAccelerationUrlForObject(key);
1667
+ }
1668
+ onCloudTrailEvent(id, options) {
1669
+ return this.bucket.onCloudTrailEvent(id, options);
1670
+ }
1671
+ onCloudTrailPutObject(id, options) {
1672
+ return this.bucket.onCloudTrailPutObject(id, options);
1673
+ }
1674
+ onCloudTrailWriteObject(id, options) {
1675
+ return this.bucket.onCloudTrailWriteObject(id, options);
1676
+ }
1677
+ addCorsRule(rule) {
1678
+ this.bucket.addCorsRule(rule);
1679
+ }
1680
+ addInventory(inventory) {
1681
+ this.bucket.addInventory(inventory);
1682
+ }
1683
+ addLifecycleRule(rule) {
1684
+ this.bucket.addLifecycleRule(rule);
1685
+ }
1686
+ addMetric(metric) {
1687
+ this.bucket.addMetric(metric);
1688
+ }
1689
+ enableEventBridgeNotification() {
1690
+ this.bucket.enableEventBridgeNotification();
1691
+ }
1692
+ addReplicationPolicy(policy) {
1693
+ this.bucket.addReplicationPolicy(policy);
1694
+ }
1695
+ get stack() {
1696
+ return this.bucket.stack;
1697
+ }
1698
+ get env() {
1699
+ return this.bucket.env;
1700
+ }
1701
+ applyRemovalPolicy(policy) {
1702
+ this.bucket.applyRemovalPolicy(policy);
1703
+ }
1704
+ }
1705
+
1706
+ exports.JaypieApiGateway = JaypieApiGateway;
1707
+ exports.JaypieAppStack = JaypieAppStack;
1171
1708
  exports.JaypieBucketQueuedLambda = JaypieBucketQueuedLambda;
1172
1709
  exports.JaypieDatadogSecret = JaypieDatadogSecret;
1173
1710
  exports.JaypieEnvSecret = JaypieEnvSecret;
1174
1711
  exports.JaypieExpressLambda = JaypieExpressLambda;
1175
1712
  exports.JaypieHostedZone = JaypieHostedZone;
1713
+ exports.JaypieInfrastructureStack = JaypieInfrastructureStack;
1176
1714
  exports.JaypieLambda = JaypieLambda;
1177
1715
  exports.JaypieMongoDbSecret = JaypieMongoDbSecret;
1178
1716
  exports.JaypieOpenAiSecret = JaypieOpenAiSecret;
1179
1717
  exports.JaypieQueuedLambda = JaypieQueuedLambda;
1180
1718
  exports.JaypieSsoGroups = JaypieSsoGroups;
1719
+ exports.JaypieStack = JaypieStack;
1181
1720
  exports.JaypieTraceSigningKeySecret = JaypieTraceSigningKeySecret;
1721
+ exports.JaypieWebDeploymentBucket = JaypieWebDeploymentBucket;
1722
+ exports.constructEnvName = constructEnvName;
1723
+ exports.constructStackName = constructStackName;
1724
+ exports.isEnv = isEnv;
1725
+ exports.isProductionEnv = isProductionEnv;
1726
+ exports.isSandboxEnv = isSandboxEnv;
1727
+ exports.stackTagger = stackTagger;
1182
1728
  //# sourceMappingURL=index.cjs.map