@jaypie/constructs 1.1.39 → 1.1.41

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,18 @@
1
1
  'use strict';
2
2
 
3
3
  var constructs = require('constructs');
4
- var cdk$1 = require('aws-cdk-lib');
4
+ var cdk = require('aws-cdk-lib');
5
5
  var acm = require('aws-cdk-lib/aws-certificatemanager');
6
6
  var apiGateway = require('aws-cdk-lib/aws-apigateway');
7
7
  var route53 = require('aws-cdk-lib/aws-route53');
8
8
  var route53Targets = require('aws-cdk-lib/aws-route53-targets');
9
- var cdk = require('@jaypie/cdk');
9
+ var cdk$1 = require('@jaypie/cdk');
10
+ var lambda = require('aws-cdk-lib/aws-lambda');
11
+ var secretsmanager = require('aws-cdk-lib/aws-secretsmanager');
10
12
  var s3 = require('aws-cdk-lib/aws-s3');
11
13
  var s3n = require('aws-cdk-lib/aws-s3-notifications');
12
- var lambda = require('aws-cdk-lib/aws-lambda');
13
14
  var sqs = require('aws-cdk-lib/aws-sqs');
14
15
  var lambdaEventSources = require('aws-cdk-lib/aws-lambda-event-sources');
15
- var secretsmanager = require('aws-cdk-lib/aws-secretsmanager');
16
16
  var awsIam = require('aws-cdk-lib/aws-iam');
17
17
  var awsLogs = require('aws-cdk-lib/aws-logs');
18
18
  var sso = require('aws-cdk-lib/aws-sso');
@@ -36,25 +36,118 @@ function _interopNamespaceDefault(e) {
36
36
  return Object.freeze(n);
37
37
  }
38
38
 
39
- var cdk__namespace = /*#__PURE__*/_interopNamespaceDefault(cdk$1);
39
+ var cdk__namespace = /*#__PURE__*/_interopNamespaceDefault(cdk);
40
40
  var acm__namespace = /*#__PURE__*/_interopNamespaceDefault(acm);
41
41
  var apiGateway__namespace = /*#__PURE__*/_interopNamespaceDefault(apiGateway);
42
42
  var route53__namespace = /*#__PURE__*/_interopNamespaceDefault(route53);
43
43
  var route53Targets__namespace = /*#__PURE__*/_interopNamespaceDefault(route53Targets);
44
+ var lambda__namespace = /*#__PURE__*/_interopNamespaceDefault(lambda);
45
+ var secretsmanager__namespace = /*#__PURE__*/_interopNamespaceDefault(secretsmanager);
44
46
  var s3__namespace = /*#__PURE__*/_interopNamespaceDefault(s3);
45
47
  var s3n__namespace = /*#__PURE__*/_interopNamespaceDefault(s3n);
46
- var lambda__namespace = /*#__PURE__*/_interopNamespaceDefault(lambda);
47
48
  var sqs__namespace = /*#__PURE__*/_interopNamespaceDefault(sqs);
48
49
  var lambdaEventSources__namespace = /*#__PURE__*/_interopNamespaceDefault(lambdaEventSources);
49
- var secretsmanager__namespace = /*#__PURE__*/_interopNamespaceDefault(secretsmanager);
50
50
  var sso__namespace = /*#__PURE__*/_interopNamespaceDefault(sso);
51
51
  var cloudfront__namespace = /*#__PURE__*/_interopNamespaceDefault(cloudfront);
52
52
  var origins__namespace = /*#__PURE__*/_interopNamespaceDefault(origins);
53
53
 
54
+ function addDatadogLayer(lambdaFunction, options = {}) {
55
+ const { datadogApiKeyArn } = options;
56
+ // Resolve the Datadog API key ARN from multiple sources
57
+ const resolvedDatadogApiKeyArn = datadogApiKeyArn ||
58
+ process.env.DATADOG_API_KEY_ARN ||
59
+ process.env.CDK_ENV_DATADOG_API_KEY_ARN;
60
+ // Return false if no API key is found
61
+ if (!resolvedDatadogApiKeyArn) {
62
+ return false;
63
+ }
64
+ const stack = cdk.Stack.of(lambdaFunction);
65
+ // Create Datadog Node.js layer
66
+ const datadogNodeLayer = lambda__namespace.LayerVersion.fromLayerVersionArn(stack, `DatadogNodeLayer-${lambdaFunction.node.id}`, `arn:aws:lambda:${stack.region}:464622532012:layer:Datadog-Node20-x:${cdk$1.CDK.DATADOG.LAYER.NODE}`);
67
+ // Create Datadog Extension layer
68
+ const datadogExtensionLayer = lambda__namespace.LayerVersion.fromLayerVersionArn(stack, `DatadogExtensionLayer-${lambdaFunction.node.id}`, `arn:aws:lambda:${stack.region}:464622532012:layer:Datadog-Extension:${cdk$1.CDK.DATADOG.LAYER.EXTENSION}`);
69
+ // Add layers to the lambda function
70
+ lambdaFunction.addLayers(datadogNodeLayer, datadogExtensionLayer);
71
+ // Define Datadog environment variables
72
+ const datadogEnvVars = {
73
+ DD_API_KEY_SECRET_ARN: resolvedDatadogApiKeyArn,
74
+ DD_ENHANCED_METRICS: "true",
75
+ DD_ENV: process.env.PROJECT_ENV || "",
76
+ DD_PROFILING_ENABLED: "false",
77
+ DD_SERVERLESS_APPSEC_ENABLED: "false",
78
+ DD_SERVICE: process.env.PROJECT_SERVICE || "",
79
+ DD_SITE: cdk$1.CDK.DATADOG.SITE,
80
+ DD_TAGS: `${cdk$1.CDK.TAG.SPONSOR}:${process.env.PROJECT_SPONSOR || ""}`,
81
+ DD_TRACE_OTEL_ENABLED: "false",
82
+ };
83
+ // Add environment variables only if they don't already exist
84
+ Object.entries(datadogEnvVars).forEach(([key, value]) => {
85
+ if (lambdaFunction.environment[key] === undefined) {
86
+ lambdaFunction.addEnvironment(key, value);
87
+ }
88
+ });
89
+ // Grant Datadog API key read permission
90
+ const datadogApiKey = secretsmanager__namespace.Secret.fromSecretCompleteArn(stack, `DatadogApiKeyGrant-${lambdaFunction.node.id}`, resolvedDatadogApiKeyArn);
91
+ datadogApiKey.grantRead(lambdaFunction);
92
+ return true;
93
+ }
94
+
95
+ function addParamsAndSecrets(lambdaFunction, options = {}) {
96
+ const { paramsAndSecrets, paramsAndSecretsOptions } = options;
97
+ // Return false if explicitly disabled
98
+ if (paramsAndSecrets === false) {
99
+ return false;
100
+ }
101
+ const stack = cdk.Stack.of(lambdaFunction);
102
+ let resolvedLayer = undefined;
103
+ if (paramsAndSecrets instanceof lambda__namespace.ParamsAndSecretsLayerVersion) {
104
+ // For custom ParamsAndSecretsLayerVersion, we need to extract the ARN
105
+ // This is a workaround since ParamsAndSecretsLayerVersion doesn't implement ILayerVersion
106
+ const layerArn = `arn:aws:lambda:${stack.region}:017000801446:layer:AWSLambdaParametersAndSecrets:${lambda__namespace.ParamsAndSecretsVersions.V1_0_103}`;
107
+ resolvedLayer = lambda__namespace.LayerVersion.fromLayerVersionArn(stack, `ParamsAndSecretsLayer-${lambdaFunction.node.id}`, layerArn);
108
+ // Set environment variables for configuration
109
+ if (paramsAndSecretsOptions?.cacheSize) {
110
+ lambdaFunction.addEnvironment("PARAMETERS_SECRETS_EXTENSION_CACHE_SIZE", paramsAndSecretsOptions.cacheSize.toString());
111
+ }
112
+ if (paramsAndSecretsOptions?.logLevel) {
113
+ lambdaFunction.addEnvironment("PARAMETERS_SECRETS_EXTENSION_LOG_LEVEL", paramsAndSecretsOptions.logLevel);
114
+ }
115
+ if (paramsAndSecretsOptions?.parameterStoreTtl) {
116
+ lambdaFunction.addEnvironment("PARAMETERS_SECRETS_EXTENSION_PARAMETER_STORE_TTL", paramsAndSecretsOptions.parameterStoreTtl.toString());
117
+ }
118
+ if (paramsAndSecretsOptions?.secretsManagerTtl) {
119
+ lambdaFunction.addEnvironment("PARAMETERS_SECRETS_EXTENSION_SECRETS_MANAGER_TTL", paramsAndSecretsOptions.secretsManagerTtl.toString());
120
+ }
121
+ }
122
+ else {
123
+ // Create default ParamsAndSecrets layer using LayerVersion.fromLayerVersionArn
124
+ const layerArn = `arn:aws:lambda:${stack.region}:017000801446:layer:AWSLambdaParametersAndSecrets:${lambda__namespace.ParamsAndSecretsVersions.V1_0_103}`;
125
+ resolvedLayer = lambda__namespace.LayerVersion.fromLayerVersionArn(stack, `ParamsAndSecretsLayer-${lambdaFunction.node.id}`, layerArn);
126
+ // Set default environment variables
127
+ if (paramsAndSecretsOptions?.cacheSize) {
128
+ lambdaFunction.addEnvironment("PARAMETERS_SECRETS_EXTENSION_CACHE_SIZE", paramsAndSecretsOptions.cacheSize.toString());
129
+ }
130
+ const logLevel = paramsAndSecretsOptions?.logLevel || lambda__namespace.ParamsAndSecretsLogLevel.WARN;
131
+ lambdaFunction.addEnvironment("PARAMETERS_SECRETS_EXTENSION_LOG_LEVEL", logLevel);
132
+ if (paramsAndSecretsOptions?.parameterStoreTtl) {
133
+ lambdaFunction.addEnvironment("PARAMETERS_SECRETS_EXTENSION_PARAMETER_STORE_TTL", paramsAndSecretsOptions.parameterStoreTtl.toString());
134
+ }
135
+ if (paramsAndSecretsOptions?.secretsManagerTtl) {
136
+ lambdaFunction.addEnvironment("PARAMETERS_SECRETS_EXTENSION_SECRETS_MANAGER_TTL", paramsAndSecretsOptions.secretsManagerTtl.toString());
137
+ }
138
+ }
139
+ // Add the layer to the lambda function
140
+ if (resolvedLayer) {
141
+ lambdaFunction.addLayers(resolvedLayer);
142
+ return true;
143
+ }
144
+ return false;
145
+ }
146
+
54
147
  function constructEnvName(name, opts) {
55
148
  const env = opts?.env ?? process.env.PROJECT_ENV ?? "build";
56
149
  const key = opts?.key ?? process.env.PROJECT_KEY ?? "project";
57
- const nonce = opts?.nonce ?? process.env.PROJECT_NONCE ?? "cfe2";
150
+ const nonce = opts?.nonce ?? process.env.PROJECT_NONCE ?? "cfe2"; // This default is intentionally short. It is not a special value but should not be changed.
58
151
  return `${env}-${key}-${name}-${nonce}`;
59
152
  }
60
153
 
@@ -67,25 +160,6 @@ function constructStackName(key) {
67
160
  }
68
161
  }
69
162
 
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
163
  const CDK$1 = {
90
164
  CREATION: {
91
165
  CDK: "cdk",
@@ -109,39 +183,141 @@ const CDK$1 = {
109
183
  VERSION: "version",
110
184
  },
111
185
  };
112
- function stackTagger(stack, { name } = {}) {
186
+ function constructTagger(construct, { name } = {}) {
113
187
  const stackName = name || constructStackName();
114
188
  const version = process.env.npm_package_version || process.env.PROJECT_VERSION || null;
115
189
  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));
190
+ cdk.Tags.of(construct).add(CDK$1.TAG.BUILD_HEX, process.env.PROJECT_COMMIT.slice(0, 8));
117
191
  }
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());
192
+ cdk.Tags.of(construct).add(CDK$1.TAG.BUILD_DATE, new Date().toISOString());
193
+ cdk.Tags.of(construct).add(CDK$1.TAG.BUILD_TIME, Date.now().toString());
120
194
  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);
195
+ cdk.Tags.of(construct).add(CDK$1.TAG.COMMIT, process.env.PROJECT_COMMIT);
196
+ cdk.Tags.of(construct).add(CDK$1.TAG.CREATION, CDK$1.CREATION.CDK);
123
197
  if (process.env.PROJECT_ENV)
124
- cdk$1.Tags.of(stack).add(CDK$1.TAG.ENV, process.env.PROJECT_ENV);
198
+ cdk.Tags.of(construct).add(CDK$1.TAG.ENV, process.env.PROJECT_ENV);
125
199
  if (process.env.PROJECT_NONCE)
126
- cdk$1.Tags.of(stack).add(CDK$1.TAG.NONCE, process.env.PROJECT_NONCE);
200
+ cdk.Tags.of(construct).add(CDK$1.TAG.NONCE, process.env.PROJECT_NONCE);
127
201
  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);
202
+ cdk.Tags.of(construct).add(CDK$1.TAG.PROJECT, process.env.PROJECT_KEY);
203
+ cdk.Tags.of(construct).add(CDK$1.TAG.ROLE, CDK$1.ROLE.STACK);
130
204
  if (process.env.PROJECT_SERVICE)
131
- cdk$1.Tags.of(stack).add(CDK$1.TAG.SERVICE, process.env.PROJECT_SERVICE);
205
+ cdk.Tags.of(construct).add(CDK$1.TAG.SERVICE, process.env.PROJECT_SERVICE);
132
206
  if (process.env.PROJECT_SPONSOR)
133
- cdk$1.Tags.of(stack).add(CDK$1.TAG.SPONSOR, process.env.PROJECT_SPONSOR);
207
+ cdk.Tags.of(construct).add(CDK$1.TAG.SPONSOR, process.env.PROJECT_SPONSOR);
134
208
  if (stackName)
135
- cdk$1.Tags.of(stack).add(CDK$1.TAG.STACK, stackName);
209
+ cdk.Tags.of(construct).add(CDK$1.TAG.STACK, stackName);
136
210
  if (version)
137
- cdk$1.Tags.of(stack).add(CDK$1.TAG.VERSION, version);
211
+ cdk.Tags.of(construct).add(CDK$1.TAG.VERSION, version);
138
212
  return true;
139
213
  }
140
214
 
215
+ function envHostname({ component, domain, env, subdomain, }) {
216
+ const resolvedDomain = domain || process.env.CDK_ENV_DOMAIN || process.env.CDK_ENV_HOSTED_ZONE;
217
+ if (!resolvedDomain) {
218
+ throw new cdk$1.ConfigurationError("No hostname `domain` provided. Set CDK_ENV_DOMAIN or CDK_ENV_HOSTED_ZONE to use environment domain");
219
+ }
220
+ const resolvedComponent = component === "@" || component === "" ? undefined : component;
221
+ const resolvedSubdomain = subdomain || process.env.CDK_ENV_SUBDOMAIN;
222
+ const resolvedEnv = env || process.env.PROJECT_ENV;
223
+ const parts = [
224
+ resolvedComponent,
225
+ resolvedSubdomain,
226
+ resolvedEnv,
227
+ resolvedDomain,
228
+ ].filter((part) => part);
229
+ return parts.join(".");
230
+ }
231
+
232
+ /**
233
+ * Check if the current environment matches the given environment
234
+ */
235
+ function isEnv(env) {
236
+ return process.env.PROJECT_ENV === env;
237
+ }
238
+ /**
239
+ * Check if the current environment is production
240
+ */
241
+ function isProductionEnv() {
242
+ return isEnv(cdk$1.CDK.ENV.PRODUCTION);
243
+ }
244
+ /**
245
+ * Check if the current environment is sandbox
246
+ */
247
+ function isSandboxEnv() {
248
+ return isEnv(cdk$1.CDK.ENV.SANDBOX);
249
+ }
250
+
251
+ function jaypieLambdaEnv(options = {}) {
252
+ const { initialEnvironment = {} } = options;
253
+ // Start with empty environment - we'll only add valid values
254
+ let environment = {};
255
+ // First, add all valid string values from initialEnvironment
256
+ Object.entries(initialEnvironment).forEach(([key, value]) => {
257
+ if (typeof value === "string") {
258
+ environment[key] = value;
259
+ }
260
+ });
261
+ // Default environment values
262
+ const defaultEnvValues = {
263
+ AWS_LAMBDA_NODEJS_DISABLE_CALLBACK_WARNING: "true",
264
+ };
265
+ // Apply default environment values with user overrides
266
+ Object.entries(defaultEnvValues).forEach(([key, defaultValue]) => {
267
+ if (key in initialEnvironment) {
268
+ const userValue = initialEnvironment[key];
269
+ // If user passes a string, it's already added above
270
+ // If user passes non-string falsy value, omit the key
271
+ if (!userValue) {
272
+ delete environment[key];
273
+ }
274
+ // Ignore non-string truthy values (key not added)
275
+ }
276
+ else {
277
+ // No user override, use default value
278
+ environment[key] = defaultValue;
279
+ }
280
+ });
281
+ // Default environment variables from process.env if present
282
+ const defaultEnvVars = [
283
+ "DATADOG_API_KEY_ARN",
284
+ "LOG_LEVEL",
285
+ "MODULE_LOGGER",
286
+ "MODULE_LOG_LEVEL",
287
+ "PROJECT_CHAOS",
288
+ "PROJECT_COMMIT",
289
+ "PROJECT_ENV",
290
+ "PROJECT_KEY",
291
+ "PROJECT_SECRET",
292
+ "PROJECT_SERVICE",
293
+ "PROJECT_SPONSOR",
294
+ "PROJECT_VERSION",
295
+ ];
296
+ // Add default environment variables if they exist in process.env
297
+ defaultEnvVars.forEach((envVar) => {
298
+ if (process.env[envVar] && !environment[envVar]) {
299
+ environment[envVar] = process.env[envVar];
300
+ }
301
+ });
302
+ return environment;
303
+ }
304
+
305
+ function resolveHostedZone(scope, { name = "HostedZone", zone = process.env.CDK_ENV_HOSTED_ZONE, }) {
306
+ if (!zone) {
307
+ throw new cdk$1.ConfigurationError("No `zone` provided. Set CDK_ENV_HOSTED_ZONE to use environment zone");
308
+ }
309
+ if (typeof zone === "string") {
310
+ return route53__namespace.HostedZone.fromLookup(scope, name, {
311
+ domainName: zone,
312
+ });
313
+ }
314
+ return zone;
315
+ }
316
+
141
317
  class JaypieApiGateway extends constructs.Construct {
142
318
  constructor(scope, id, props) {
143
319
  super(scope, id);
144
- const { certificate = true, handler, host: propsHost, name, roleTag = cdk.CDK.ROLE.API, zone: propsZone, } = props;
320
+ const { certificate = true, handler, host: propsHost, name, roleTag = cdk$1.CDK.ROLE.API, zone: propsZone, } = props;
145
321
  // Determine zone from props or environment
146
322
  let zone = propsZone;
147
323
  if (!zone && process.env.CDK_ENV_API_HOSTED_ZONE) {
@@ -155,7 +331,7 @@ class JaypieApiGateway extends constructs.Construct {
155
331
  }
156
332
  else if (process.env.CDK_ENV_API_SUBDOMAIN &&
157
333
  process.env.CDK_ENV_API_HOSTED_ZONE) {
158
- host = cdk.mergeDomain(process.env.CDK_ENV_API_SUBDOMAIN, process.env.CDK_ENV_API_HOSTED_ZONE);
334
+ host = cdk$1.mergeDomain(process.env.CDK_ENV_API_SUBDOMAIN, process.env.CDK_ENV_API_HOSTED_ZONE);
159
335
  }
160
336
  }
161
337
  const apiGatewayName = name || constructEnvName("ApiGateway");
@@ -164,20 +340,13 @@ class JaypieApiGateway extends constructs.Construct {
164
340
  let hostedZone;
165
341
  let certificateToUse;
166
342
  if (host && zone) {
167
- if (typeof zone === "string") {
168
- hostedZone = route53__namespace.HostedZone.fromLookup(this, "HostedZone", {
169
- domainName: zone,
170
- });
171
- }
172
- else {
173
- hostedZone = zone;
174
- }
343
+ hostedZone = resolveHostedZone(this, { zone });
175
344
  if (certificate === true) {
176
345
  certificateToUse = new acm__namespace.Certificate(this, certificateName, {
177
346
  domainName: host,
178
347
  validation: acm__namespace.CertificateValidation.fromDns(hostedZone),
179
348
  });
180
- cdk$1.Tags.of(certificateToUse).add(cdk.CDK.TAG.ROLE, cdk.CDK.ROLE.HOSTING);
349
+ cdk.Tags.of(certificateToUse).add(cdk$1.CDK.TAG.ROLE, cdk$1.CDK.ROLE.HOSTING);
181
350
  }
182
351
  else if (typeof certificate === "object") {
183
352
  certificateToUse = certificate;
@@ -196,19 +365,19 @@ class JaypieApiGateway extends constructs.Construct {
196
365
  handler,
197
366
  ...lambdaRestApiProps,
198
367
  });
199
- cdk$1.Tags.of(this._api).add(cdk.CDK.TAG.ROLE, roleTag);
368
+ cdk.Tags.of(this._api).add(cdk$1.CDK.TAG.ROLE, roleTag);
200
369
  if (host && certificateToUse && hostedZone) {
201
370
  this._domainName = this._api.addDomainName(apiDomainName, {
202
371
  domainName: host,
203
372
  certificate: certificateToUse,
204
373
  });
205
- cdk$1.Tags.of(this._domainName).add(cdk.CDK.TAG.ROLE, roleTag);
374
+ cdk.Tags.of(this._domainName).add(cdk$1.CDK.TAG.ROLE, roleTag);
206
375
  const record = new route53__namespace.ARecord(this, "AliasRecord", {
207
376
  recordName: host,
208
377
  target: route53__namespace.RecordTarget.fromAlias(new route53Targets__namespace.ApiGatewayDomain(this._domainName)),
209
378
  zone: hostedZone,
210
379
  });
211
- cdk$1.Tags.of(record).add(cdk.CDK.TAG.ROLE, cdk.CDK.ROLE.NETWORKING);
380
+ cdk.Tags.of(record).add(cdk$1.CDK.TAG.ROLE, cdk$1.CDK.ROLE.NETWORKING);
212
381
  }
213
382
  }
214
383
  get api() {
@@ -249,8 +418,8 @@ class JaypieApiGateway extends constructs.Construct {
249
418
  }
250
419
  get env() {
251
420
  return {
252
- account: cdk$1.Stack.of(this).account,
253
- region: cdk$1.Stack.of(this).region,
421
+ account: cdk.Stack.of(this).account,
422
+ region: cdk.Stack.of(this).region,
254
423
  };
255
424
  }
256
425
  get stack() {
@@ -288,7 +457,7 @@ class JaypieApiGateway extends constructs.Construct {
288
457
  }
289
458
  }
290
459
 
291
- class JaypieStack extends cdk$1.Stack {
460
+ class JaypieStack extends cdk.Stack {
292
461
  constructor(scope, id, props = {}) {
293
462
  const { key, ...stackProps } = props;
294
463
  // Handle stackName
@@ -303,7 +472,7 @@ class JaypieStack extends cdk$1.Stack {
303
472
  };
304
473
  super(scope, id, stackProps);
305
474
  // Apply tags
306
- stackTagger(this, { name: stackProps.stackName });
475
+ constructTagger(this, { name: stackProps.stackName });
307
476
  }
308
477
  }
309
478
 
@@ -321,103 +490,12 @@ class JaypieAppStack extends JaypieStack {
321
490
  class JaypieLambda extends constructs.Construct {
322
491
  constructor(scope, id, props) {
323
492
  super(scope, id);
324
- const { allowAllOutbound, allowPublicSubnet, architecture = lambda__namespace.Architecture.X86_64, code, codeSigningConfig, datadogApiKeyArn, deadLetterQueue, deadLetterQueueEnabled, deadLetterTopic, description, environment: initialEnvironment = {}, environmentEncryption, envSecrets = {}, ephemeralStorageSize, filesystem, handler = "index.handler", initialPolicy, layers = [], logRetention = cdk.CDK.LAMBDA.LOG_RETENTION, logRetentionRole, logRetentionRetryOptions, maxEventAge, memorySize = cdk.CDK.LAMBDA.MEMORY_SIZE, paramsAndSecrets, paramsAndSecretsOptions, profiling, profilingGroup, provisionedConcurrentExecutions, reservedConcurrentExecutions, retryAttempts, roleTag = cdk.CDK.ROLE.PROCESSING, runtime = lambda__namespace.Runtime.NODEJS_22_X, runtimeManagementMode, secrets = [], securityGroups, timeout = cdk$1.Duration.seconds(cdk.CDK.DURATION.LAMBDA_WORKER), tracing, vendorTag, vpc, vpcSubnets, } = props;
325
- // Create a mutable copy of the environment variables
326
- let environment = { ...initialEnvironment };
327
- // Default environment values
328
- const defaultEnvValues = {
329
- AWS_LAMBDA_NODEJS_DISABLE_CALLBACK_WARNING: "true",
330
- };
331
- // Apply default environment values with user overrides
332
- Object.entries(defaultEnvValues).forEach(([key, defaultValue]) => {
333
- if (key in initialEnvironment) {
334
- const userValue = initialEnvironment[key];
335
- // If user passes a string, use that value
336
- if (typeof userValue === "string") {
337
- environment[key] = userValue;
338
- }
339
- // If user passes non-string falsy value, omit the key
340
- else if (!userValue) {
341
- delete environment[key];
342
- }
343
- // Ignore non-string truthy values (key already not present)
344
- }
345
- else {
346
- // No user override, use default value
347
- environment[key] = defaultValue;
348
- }
349
- });
350
- // Default environment variables from process.env if present
351
- const defaultEnvVars = [
352
- "DATADOG_API_KEY_ARN",
353
- "LOG_LEVEL",
354
- "MODULE_LOGGER",
355
- "MODULE_LOG_LEVEL",
356
- "PROJECT_COMMIT",
357
- "PROJECT_ENV",
358
- "PROJECT_KEY",
359
- "PROJECT_SECRET",
360
- "PROJECT_SERVICE",
361
- "PROJECT_SPONSOR",
362
- "PROJECT_VERSION",
363
- ];
364
- // Add default environment variables if they exist in process.env
365
- defaultEnvVars.forEach((envVar) => {
366
- if (process.env[envVar] && !environment[envVar]) {
367
- environment[envVar] = process.env[envVar];
368
- }
369
- });
493
+ const { allowAllOutbound, allowPublicSubnet, architecture = lambda__namespace.Architecture.X86_64, code, codeSigningConfig, datadogApiKeyArn, deadLetterQueue, deadLetterQueueEnabled, deadLetterTopic, description, environment: initialEnvironment = {}, environmentEncryption, envSecrets = {}, ephemeralStorageSize, filesystem, handler = "index.handler", initialPolicy, layers = [], logRetention = cdk$1.CDK.LAMBDA.LOG_RETENTION, logRetentionRole, logRetentionRetryOptions, maxEventAge, memorySize = cdk$1.CDK.LAMBDA.MEMORY_SIZE, paramsAndSecrets, paramsAndSecretsOptions, profiling, profilingGroup, provisionedConcurrentExecutions, reservedConcurrentExecutions, retryAttempts, roleTag = cdk$1.CDK.ROLE.PROCESSING, runtime = lambda__namespace.Runtime.NODEJS_22_X, runtimeManagementMode, secrets = [], securityGroups, timeout = cdk.Duration.seconds(cdk$1.CDK.DURATION.LAMBDA_WORKER), tracing, vendorTag, vpc, vpcSubnets, } = props;
494
+ // Get base environment with defaults
495
+ const environment = jaypieLambdaEnv({ initialEnvironment });
370
496
  const codeAsset = typeof code === "string" ? lambda__namespace.Code.fromAsset(code) : code;
371
497
  // Create a working copy of layers
372
498
  const resolvedLayers = [...layers];
373
- // Determine if we should add Datadog integration
374
- // Check for datadog API key ARN in different sources
375
- const resolvedDatadogApiKeyArn = datadogApiKeyArn ||
376
- process.env.DATADOG_API_KEY_ARN ||
377
- process.env.CDK_ENV_DATADOG_API_KEY_ARN;
378
- // Add Datadog integration if API key is available
379
- if (resolvedDatadogApiKeyArn) {
380
- // Add Datadog Node.js layer
381
- const datadogNodeLayer = lambda__namespace.LayerVersion.fromLayerVersionArn(this, "DatadogNodeLayer", `arn:aws:lambda:${cdk$1.Stack.of(this).region}:464622532012:layer:Datadog-Node20-x:${cdk.CDK.DATADOG.LAYER.NODE}`);
382
- resolvedLayers.push(datadogNodeLayer);
383
- // Add Datadog Extension layer
384
- const datadogExtensionLayer = lambda__namespace.LayerVersion.fromLayerVersionArn(this, "DatadogExtensionLayer", `arn:aws:lambda:${cdk$1.Stack.of(this).region}:464622532012:layer:Datadog-Extension:${cdk.CDK.DATADOG.LAYER.EXTENSION}`);
385
- resolvedLayers.push(datadogExtensionLayer);
386
- // Set Datadog environment variables
387
- Object.assign(environment, {
388
- DD_API_KEY_SECRET_ARN: resolvedDatadogApiKeyArn,
389
- DD_ENHANCED_METRICS: "true",
390
- DD_ENV: process.env.PROJECT_ENV || "",
391
- DD_PROFILING_ENABLED: "false",
392
- DD_SERVERLESS_APPSEC_ENABLED: "false",
393
- DD_SERVICE: process.env.PROJECT_SERVICE || "",
394
- DD_SITE: cdk.CDK.DATADOG.SITE,
395
- DD_TAGS: `${cdk.CDK.TAG.SPONSOR}:${process.env.PROJECT_SPONSOR || ""}`,
396
- DD_TRACE_OTEL_ENABLED: "false",
397
- });
398
- }
399
- // Configure ParamsAndSecrets layer
400
- let resolvedParamsAndSecrets = undefined;
401
- if (paramsAndSecrets !== false) {
402
- if (paramsAndSecrets instanceof lambda__namespace.ParamsAndSecretsLayerVersion) {
403
- resolvedParamsAndSecrets = paramsAndSecrets;
404
- }
405
- else {
406
- // Create default ParamsAndSecrets layer
407
- resolvedParamsAndSecrets =
408
- lambda__namespace.ParamsAndSecretsLayerVersion.fromVersion(lambda__namespace.ParamsAndSecretsVersions.V1_0_103, {
409
- cacheSize: paramsAndSecretsOptions?.cacheSize,
410
- logLevel: paramsAndSecretsOptions?.logLevel ||
411
- lambda__namespace.ParamsAndSecretsLogLevel.WARN,
412
- parameterStoreTtl: paramsAndSecretsOptions?.parameterStoreTtl
413
- ? cdk$1.Duration.seconds(paramsAndSecretsOptions.parameterStoreTtl)
414
- : undefined,
415
- secretsManagerTtl: paramsAndSecretsOptions?.secretsManagerTtl
416
- ? cdk$1.Duration.seconds(paramsAndSecretsOptions.secretsManagerTtl)
417
- : undefined,
418
- });
419
- }
420
- }
421
499
  // Process secrets environment variables
422
500
  const secretsEnvironment = Object.entries(envSecrets).reduce((acc, [key, secret]) => ({
423
501
  ...acc,
@@ -460,7 +538,6 @@ class JaypieLambda extends constructs.Construct {
460
538
  logRetentionRetryOptions,
461
539
  maxEventAge,
462
540
  memorySize,
463
- paramsAndSecrets: resolvedParamsAndSecrets,
464
541
  profiling,
465
542
  profilingGroup,
466
543
  reservedConcurrentExecutions,
@@ -468,19 +545,26 @@ class JaypieLambda extends constructs.Construct {
468
545
  runtime,
469
546
  runtimeManagementMode,
470
547
  securityGroups,
471
- timeout: typeof timeout === "number" ? cdk$1.Duration.seconds(timeout) : timeout,
548
+ timeout: typeof timeout === "number" ? cdk.Duration.seconds(timeout) : timeout,
472
549
  tracing,
473
550
  vpc,
474
551
  vpcSubnets,
475
552
  // Enable auto-publishing of versions when using provisioned concurrency
476
553
  currentVersionOptions: provisionedConcurrentExecutions !== undefined
477
554
  ? {
478
- removalPolicy: cdk$1.RemovalPolicy.RETAIN,
555
+ removalPolicy: cdk.RemovalPolicy.RETAIN,
479
556
  description: "Auto-published version for provisioned concurrency",
480
557
  // Don't set provisioned concurrency here - it will be set on the alias
481
558
  }
482
559
  : undefined,
483
560
  });
561
+ // Add ParamsAndSecrets layer if configured
562
+ addParamsAndSecrets(this._lambda, {
563
+ paramsAndSecrets,
564
+ paramsAndSecretsOptions,
565
+ });
566
+ // Add Datadog layers and environment variables if configured
567
+ addDatadogLayer(this._lambda, { datadogApiKeyArn });
484
568
  // Grant secret read permissions
485
569
  Object.values(envSecrets).forEach((secret) => {
486
570
  secret.grantRead(this._lambda);
@@ -489,11 +573,6 @@ class JaypieLambda extends constructs.Construct {
489
573
  secrets.forEach((secret) => {
490
574
  secret.grantRead(this._lambda);
491
575
  });
492
- // Grant Datadog API key read permission if applicable
493
- if (resolvedDatadogApiKeyArn) {
494
- const datadogApiKey = secretsmanager__namespace.Secret.fromSecretCompleteArn(this, "DatadogApiKeyGrant", resolvedDatadogApiKeyArn);
495
- datadogApiKey.grantRead(this._lambda);
496
- }
497
576
  // Configure provisioned concurrency if specified
498
577
  if (provisionedConcurrentExecutions !== undefined) {
499
578
  // Use currentVersion which is auto-published with proper configuration
@@ -508,10 +587,10 @@ class JaypieLambda extends constructs.Construct {
508
587
  this._provisioned.node.addDependency(version);
509
588
  }
510
589
  if (roleTag) {
511
- cdk$1.Tags.of(this._lambda).add(cdk.CDK.TAG.ROLE, roleTag);
590
+ cdk.Tags.of(this._lambda).add(cdk$1.CDK.TAG.ROLE, roleTag);
512
591
  }
513
592
  if (vendorTag) {
514
- cdk$1.Tags.of(this._lambda).add(cdk.CDK.TAG.VENDOR, vendorTag);
593
+ cdk.Tags.of(this._lambda).add(cdk$1.CDK.TAG.VENDOR, vendorTag);
515
594
  }
516
595
  // Assign _reference based on provisioned state
517
596
  this._reference =
@@ -608,8 +687,8 @@ class JaypieLambda extends constructs.Construct {
608
687
  }
609
688
  get env() {
610
689
  return {
611
- account: cdk$1.Stack.of(this).account,
612
- region: cdk$1.Stack.of(this).region,
690
+ account: cdk.Stack.of(this).account,
691
+ region: cdk.Stack.of(this).region,
613
692
  };
614
693
  }
615
694
  get stack() {
@@ -623,19 +702,19 @@ class JaypieLambda extends constructs.Construct {
623
702
  class JaypieQueuedLambda extends constructs.Construct {
624
703
  constructor(scope, id, props) {
625
704
  super(scope, id);
626
- const { batchSize = 1, code, environment = {}, envSecrets = {}, fifo = true, handler = "index.handler", layers = [], logRetention = cdk.CDK.LAMBDA.LOG_RETENTION, memorySize = cdk.CDK.LAMBDA.MEMORY_SIZE, paramsAndSecrets, reservedConcurrentExecutions, roleTag, runtime = lambda__namespace.Runtime.NODEJS_22_X, secrets = [], timeout = cdk$1.Duration.seconds(cdk.CDK.DURATION.LAMBDA_WORKER), vendorTag, visibilityTimeout = cdk$1.Duration.seconds(cdk.CDK.DURATION.LAMBDA_WORKER), } = props;
705
+ const { batchSize = 1, code, environment = {}, envSecrets = {}, fifo = true, handler = "index.handler", layers = [], logRetention = cdk$1.CDK.LAMBDA.LOG_RETENTION, memorySize = cdk$1.CDK.LAMBDA.MEMORY_SIZE, paramsAndSecrets, reservedConcurrentExecutions, roleTag, runtime = lambda__namespace.Runtime.NODEJS_22_X, secrets = [], timeout = cdk.Duration.seconds(cdk$1.CDK.DURATION.LAMBDA_WORKER), vendorTag, visibilityTimeout = cdk.Duration.seconds(cdk$1.CDK.DURATION.LAMBDA_WORKER), } = props;
627
706
  // Create SQS Queue
628
707
  this._queue = new sqs__namespace.Queue(this, "Queue", {
629
708
  fifo,
630
709
  visibilityTimeout: typeof visibilityTimeout === "number"
631
- ? cdk$1.Duration.seconds(visibilityTimeout)
710
+ ? cdk.Duration.seconds(visibilityTimeout)
632
711
  : visibilityTimeout,
633
712
  });
634
713
  if (roleTag) {
635
- cdk$1.Tags.of(this._queue).add(cdk.CDK.TAG.ROLE, roleTag);
714
+ cdk.Tags.of(this._queue).add(cdk$1.CDK.TAG.ROLE, roleTag);
636
715
  }
637
716
  if (vendorTag) {
638
- cdk$1.Tags.of(this._queue).add(cdk.CDK.TAG.VENDOR, vendorTag);
717
+ cdk.Tags.of(this._queue).add(cdk$1.CDK.TAG.VENDOR, vendorTag);
639
718
  }
640
719
  // Create Lambda with JaypieLambda
641
720
  this._lambdaConstruct = new JaypieLambda(this, "Function", {
@@ -756,12 +835,12 @@ class JaypieQueuedLambda extends constructs.Construct {
756
835
  }
757
836
  get env() {
758
837
  return {
759
- account: cdk$1.Stack.of(this).account,
760
- region: cdk$1.Stack.of(this).region,
838
+ account: cdk.Stack.of(this).account,
839
+ region: cdk.Stack.of(this).region,
761
840
  };
762
841
  }
763
842
  get stack() {
764
- return cdk$1.Stack.of(this);
843
+ return cdk.Stack.of(this);
765
844
  }
766
845
  applyRemovalPolicy(policy) {
767
846
  this._lambdaConstruct.applyRemovalPolicy(policy);
@@ -836,15 +915,15 @@ class JaypieBucketQueuedLambda extends JaypieQueuedLambda {
836
915
  // Create S3 Bucket
837
916
  this._bucket = new s3__namespace.Bucket(this, "Bucket", {
838
917
  bucketName: bucketOptions.bucketName || bucketName,
839
- removalPolicy: bucketOptions.removalPolicy || cdk$1.RemovalPolicy.RETAIN,
918
+ removalPolicy: bucketOptions.removalPolicy || cdk.RemovalPolicy.RETAIN,
840
919
  ...bucketOptions,
841
920
  });
842
921
  // Add tags to bucket
843
922
  if (roleTag) {
844
- cdk$1.Tags.of(this._bucket).add(cdk.CDK.TAG.ROLE, roleTag);
923
+ cdk.Tags.of(this._bucket).add(cdk$1.CDK.TAG.ROLE, roleTag);
845
924
  }
846
925
  if (vendorTag) {
847
- cdk$1.Tags.of(this._bucket).add(cdk.CDK.TAG.VENDOR, vendorTag);
926
+ cdk.Tags.of(this._bucket).add(cdk$1.CDK.TAG.VENDOR, vendorTag);
848
927
  }
849
928
  // Add an event notification from the bucket to the queue
850
929
  this._bucket.addEventNotification(s3__namespace.EventType.OBJECT_CREATED, new s3n__namespace.SqsDestination(this.queue));
@@ -1009,13 +1088,13 @@ class JaypieBucketQueuedLambda extends JaypieQueuedLambda {
1009
1088
 
1010
1089
  // It is a consumer if the environment is ephemeral
1011
1090
  function checkEnvIsConsumer(env = process.env) {
1012
- return (env.PROJECT_ENV === cdk.CDK.ENV.PERSONAL ||
1091
+ return (env.PROJECT_ENV === cdk$1.CDK.ENV.PERSONAL ||
1013
1092
  !!env.CDK_ENV_PERSONAL ||
1014
1093
  /** @deprecated */ env.PROJECT_ENV === "ephemeral" ||
1015
1094
  /** @deprecated */ !!env.CDK_ENV_EPHEMERAL);
1016
1095
  }
1017
1096
  function checkEnvIsProvider(env = process.env) {
1018
- return env.PROJECT_ENV === cdk.CDK.ENV.SANDBOX;
1097
+ return env.PROJECT_ENV === cdk$1.CDK.ENV.SANDBOX;
1019
1098
  }
1020
1099
  function cleanName(name) {
1021
1100
  return name.replace(/[^a-zA-Z0-9:-]/g, "");
@@ -1029,7 +1108,7 @@ function exportEnvName(name, env = process.env) {
1029
1108
  }
1030
1109
  else {
1031
1110
  if (checkEnvIsConsumer(env)) {
1032
- rawName = `env-${cdk.CDK.ENV.SANDBOX}-${env.PROJECT_KEY}-${name}`;
1111
+ rawName = `env-${cdk$1.CDK.ENV.SANDBOX}-${env.PROJECT_KEY}-${name}`;
1033
1112
  }
1034
1113
  else {
1035
1114
  rawName = `env-${env.PROJECT_ENV}-${env.PROJECT_KEY}-${name}`;
@@ -1050,10 +1129,10 @@ class JaypieEnvSecret extends constructs.Construct {
1050
1129
  exportName = cleanName(exportParam);
1051
1130
  }
1052
1131
  if (consumer) {
1053
- const secretName = cdk$1.Fn.importValue(exportName);
1132
+ const secretName = cdk.Fn.importValue(exportName);
1054
1133
  this._secret = secretsmanager__namespace.Secret.fromSecretNameV2(this, id, secretName);
1055
1134
  // Add CfnOutput for consumer secrets
1056
- new cdk$1.CfnOutput(this, `ConsumedName`, {
1135
+ new cdk.CfnOutput(this, `ConsumedName`, {
1057
1136
  value: this._secret.secretName,
1058
1137
  });
1059
1138
  }
@@ -1062,24 +1141,24 @@ class JaypieEnvSecret extends constructs.Construct {
1062
1141
  const secretProps = {
1063
1142
  generateSecretString,
1064
1143
  secretStringValue: !generateSecretString && secretValue
1065
- ? cdk$1.SecretValue.unsafePlainText(secretValue)
1144
+ ? cdk.SecretValue.unsafePlainText(secretValue)
1066
1145
  : undefined,
1067
1146
  };
1068
1147
  this._secret = new secretsmanager__namespace.Secret(this, id, secretProps);
1069
1148
  if (roleTag) {
1070
- cdk$1.Tags.of(this._secret).add(cdk.CDK.TAG.ROLE, roleTag);
1149
+ cdk.Tags.of(this._secret).add(cdk$1.CDK.TAG.ROLE, roleTag);
1071
1150
  }
1072
1151
  if (vendorTag) {
1073
- cdk$1.Tags.of(this._secret).add(cdk.CDK.TAG.VENDOR, vendorTag);
1152
+ cdk.Tags.of(this._secret).add(cdk$1.CDK.TAG.VENDOR, vendorTag);
1074
1153
  }
1075
1154
  if (provider) {
1076
- new cdk$1.CfnOutput(this, `ProvidedName`, {
1155
+ new cdk.CfnOutput(this, `ProvidedName`, {
1077
1156
  value: this._secret.secretName,
1078
1157
  exportName,
1079
1158
  });
1080
1159
  }
1081
1160
  else {
1082
- new cdk$1.CfnOutput(this, `CreatedName`, {
1161
+ new cdk.CfnOutput(this, `CreatedName`, {
1083
1162
  value: this._secret.secretName,
1084
1163
  });
1085
1164
  }
@@ -1087,12 +1166,12 @@ class JaypieEnvSecret extends constructs.Construct {
1087
1166
  }
1088
1167
  // IResource implementation
1089
1168
  get stack() {
1090
- return cdk$1.Stack.of(this);
1169
+ return cdk.Stack.of(this);
1091
1170
  }
1092
1171
  get env() {
1093
1172
  return {
1094
- account: cdk$1.Stack.of(this).account,
1095
- region: cdk$1.Stack.of(this).region,
1173
+ account: cdk.Stack.of(this).account,
1174
+ region: cdk.Stack.of(this).region,
1096
1175
  };
1097
1176
  }
1098
1177
  applyRemovalPolicy(policy) {
@@ -1144,8 +1223,8 @@ class JaypieDatadogSecret extends JaypieEnvSecret {
1144
1223
  constructor(scope, id = "MongoConnectionString", props) {
1145
1224
  const defaultProps = {
1146
1225
  envKey: "DATADOG_API_KEY",
1147
- roleTag: cdk.CDK.ROLE.MONITORING,
1148
- vendorTag: cdk.CDK.VENDOR.DATADOG,
1226
+ roleTag: cdk$1.CDK.ROLE.MONITORING,
1227
+ vendorTag: cdk$1.CDK.VENDOR.DATADOG,
1149
1228
  ...props,
1150
1229
  };
1151
1230
  super(scope, id, defaultProps);
@@ -1155,8 +1234,8 @@ class JaypieDatadogSecret extends JaypieEnvSecret {
1155
1234
  class JaypieExpressLambda extends JaypieLambda {
1156
1235
  constructor(scope, id, props) {
1157
1236
  super(scope, id, {
1158
- timeout: cdk$1.Duration.seconds(cdk.CDK.DURATION.EXPRESS_API),
1159
- roleTag: cdk.CDK.ROLE.API,
1237
+ timeout: cdk.Duration.seconds(cdk$1.CDK.DURATION.EXPRESS_API),
1238
+ roleTag: cdk$1.CDK.ROLE.API,
1160
1239
  ...props,
1161
1240
  });
1162
1241
  }
@@ -1172,7 +1251,7 @@ class JaypieHostedZone extends constructs.Construct {
1172
1251
  constructor(scope, id, props) {
1173
1252
  super(scope, id);
1174
1253
  const { destination, zoneName, project } = props;
1175
- const service = props.service || cdk.CDK.SERVICE.INFRASTRUCTURE;
1254
+ const service = props.service || cdk$1.CDK.SERVICE.INFRASTRUCTURE;
1176
1255
  // Create the log group
1177
1256
  this.logGroup = new awsLogs.LogGroup(this, "LogGroup", {
1178
1257
  logGroupName: process.env.PROJECT_NONCE
@@ -1181,10 +1260,10 @@ class JaypieHostedZone extends constructs.Construct {
1181
1260
  retention: awsLogs.RetentionDays.ONE_WEEK,
1182
1261
  });
1183
1262
  // Add tags
1184
- cdk__namespace.Tags.of(this.logGroup).add(cdk.CDK.TAG.SERVICE, service);
1185
- cdk__namespace.Tags.of(this.logGroup).add(cdk.CDK.TAG.ROLE, cdk.CDK.ROLE.NETWORKING);
1263
+ cdk__namespace.Tags.of(this.logGroup).add(cdk$1.CDK.TAG.SERVICE, service);
1264
+ cdk__namespace.Tags.of(this.logGroup).add(cdk$1.CDK.TAG.ROLE, cdk$1.CDK.ROLE.NETWORKING);
1186
1265
  if (project) {
1187
- cdk__namespace.Tags.of(this.logGroup).add(cdk.CDK.TAG.PROJECT, project);
1266
+ cdk__namespace.Tags.of(this.logGroup).add(cdk$1.CDK.TAG.PROJECT, project);
1188
1267
  }
1189
1268
  // Grant Route 53 permissions to write to the log group
1190
1269
  this.logGroup.grantWrite(new awsIam.ServicePrincipal(SERVICE.ROUTE53));
@@ -1201,10 +1280,10 @@ class JaypieHostedZone extends constructs.Construct {
1201
1280
  zoneName,
1202
1281
  });
1203
1282
  // Add tags
1204
- cdk__namespace.Tags.of(this.hostedZone).add(cdk.CDK.TAG.SERVICE, service);
1205
- cdk__namespace.Tags.of(this.hostedZone).add(cdk.CDK.TAG.ROLE, cdk.CDK.ROLE.NETWORKING);
1283
+ cdk__namespace.Tags.of(this.hostedZone).add(cdk$1.CDK.TAG.SERVICE, service);
1284
+ cdk__namespace.Tags.of(this.hostedZone).add(cdk$1.CDK.TAG.ROLE, cdk$1.CDK.ROLE.NETWORKING);
1206
1285
  if (project) {
1207
- cdk__namespace.Tags.of(this.hostedZone).add(cdk.CDK.TAG.PROJECT, project);
1286
+ cdk__namespace.Tags.of(this.hostedZone).add(cdk$1.CDK.TAG.PROJECT, project);
1208
1287
  }
1209
1288
  }
1210
1289
  }
@@ -1224,7 +1303,7 @@ class JaypieInfrastructureStack extends JaypieStack {
1224
1303
  super(scope, id, { key, ...stackProps });
1225
1304
  // Add infrastructure-specific tag
1226
1305
  if (process.env.CDK_ENV_INFRASTRUCTURE_STACK_SHA) {
1227
- cdk$1.Tags.of(this).add(CDK.TAG.STACK_SHA, process.env.CDK_ENV_INFRASTRUCTURE_STACK_SHA);
1306
+ cdk.Tags.of(this).add(CDK.TAG.STACK_SHA, process.env.CDK_ENV_INFRASTRUCTURE_STACK_SHA);
1228
1307
  }
1229
1308
  }
1230
1309
  }
@@ -1233,8 +1312,8 @@ class JaypieMongoDbSecret extends JaypieEnvSecret {
1233
1312
  constructor(scope, id = "MongoConnectionString", props) {
1234
1313
  const defaultProps = {
1235
1314
  envKey: "MONGODB_URI",
1236
- roleTag: cdk.CDK.ROLE.STORAGE,
1237
- vendorTag: cdk.CDK.VENDOR.MONGODB,
1315
+ roleTag: cdk$1.CDK.ROLE.STORAGE,
1316
+ vendorTag: cdk$1.CDK.VENDOR.MONGODB,
1238
1317
  ...props,
1239
1318
  };
1240
1319
  super(scope, id, defaultProps);
@@ -1245,8 +1324,8 @@ class JaypieOpenAiSecret extends JaypieEnvSecret {
1245
1324
  constructor(scope, id = "OpenAiApiKey", props) {
1246
1325
  const defaultProps = {
1247
1326
  envKey: "OPENAI_API_KEY",
1248
- roleTag: cdk.CDK.ROLE.PROCESSING,
1249
- vendorTag: cdk.CDK.VENDOR.OPENAI,
1327
+ roleTag: cdk$1.CDK.ROLE.PROCESSING,
1328
+ vendorTag: cdk$1.CDK.VENDOR.OPENAI,
1250
1329
  ...props,
1251
1330
  };
1252
1331
  super(scope, id, defaultProps);
@@ -1306,11 +1385,11 @@ class JaypieSsoGroups extends constructs.Construct {
1306
1385
  instanceArn: this.instanceArn,
1307
1386
  name: exports.PermissionSetType.ADMINISTRATOR,
1308
1387
  description: "Full administrative access to all AWS services and resources",
1309
- sessionDuration: cdk$1.Duration.hours(8).toIsoString(),
1388
+ sessionDuration: cdk.Duration.hours(8).toIsoString(),
1310
1389
  managedPolicies: ["arn:aws:iam::aws:policy/AdministratorAccess"],
1311
1390
  inlinePolicy: mergedPolicy,
1312
1391
  });
1313
- cdk$1.Tags.of(permissionSet).add(cdk.CDK.TAG.SERVICE, cdk.CDK.SERVICE.SSO);
1392
+ cdk.Tags.of(permissionSet).add(cdk$1.CDK.TAG.SERVICE, cdk$1.CDK.SERVICE.SSO);
1314
1393
  this.permissionSets[exports.PermissionSetType.ADMINISTRATOR] = permissionSet;
1315
1394
  }
1316
1395
  /**
@@ -1343,11 +1422,11 @@ class JaypieSsoGroups extends constructs.Construct {
1343
1422
  instanceArn: this.instanceArn,
1344
1423
  name: exports.PermissionSetType.ANALYST,
1345
1424
  description: "Read-only access with billing visibility and limited write access",
1346
- sessionDuration: cdk$1.Duration.hours(4).toIsoString(),
1425
+ sessionDuration: cdk.Duration.hours(4).toIsoString(),
1347
1426
  managedPolicies: ["arn:aws:iam::aws:policy/ReadOnlyAccess"],
1348
1427
  inlinePolicy: mergedPolicy,
1349
1428
  });
1350
- cdk$1.Tags.of(permissionSet).add(cdk.CDK.TAG.SERVICE, cdk.CDK.SERVICE.SSO);
1429
+ cdk.Tags.of(permissionSet).add(cdk$1.CDK.TAG.SERVICE, cdk$1.CDK.SERVICE.SSO);
1351
1430
  this.permissionSets[exports.PermissionSetType.ANALYST] = permissionSet;
1352
1431
  }
1353
1432
  /**
@@ -1395,13 +1474,13 @@ class JaypieSsoGroups extends constructs.Construct {
1395
1474
  instanceArn: this.instanceArn,
1396
1475
  name: exports.PermissionSetType.DEVELOPER,
1397
1476
  description: "System administrator access with expanded write permissions",
1398
- sessionDuration: cdk$1.Duration.hours(8).toIsoString(),
1477
+ sessionDuration: cdk.Duration.hours(8).toIsoString(),
1399
1478
  managedPolicies: [
1400
1479
  "arn:aws:iam::aws:policy/job-function/SystemAdministrator",
1401
1480
  ],
1402
1481
  inlinePolicy: mergedPolicy,
1403
1482
  });
1404
- cdk$1.Tags.of(permissionSet).add(cdk.CDK.TAG.SERVICE, cdk.CDK.SERVICE.SSO);
1483
+ cdk.Tags.of(permissionSet).add(cdk$1.CDK.TAG.SERVICE, cdk$1.CDK.SERVICE.SSO);
1405
1484
  this.permissionSets[exports.PermissionSetType.DEVELOPER] = permissionSet;
1406
1485
  }
1407
1486
  /**
@@ -1468,8 +1547,8 @@ class JaypieSsoGroups extends constructs.Construct {
1468
1547
  targetId: accountId,
1469
1548
  targetType: "AWS_ACCOUNT",
1470
1549
  });
1471
- cdk$1.Tags.of(assignment).add(cdk.CDK.TAG.SERVICE, cdk.CDK.SERVICE.SSO);
1472
- cdk$1.Tags.of(assignment).add("Group", "administrators");
1550
+ cdk.Tags.of(assignment).add(cdk$1.CDK.TAG.SERVICE, cdk$1.CDK.SERVICE.SSO);
1551
+ cdk.Tags.of(assignment).add("Group", "administrators");
1473
1552
  });
1474
1553
  }
1475
1554
  /**
@@ -1495,8 +1574,8 @@ class JaypieSsoGroups extends constructs.Construct {
1495
1574
  targetId: accountId,
1496
1575
  targetType: "AWS_ACCOUNT",
1497
1576
  });
1498
- cdk$1.Tags.of(assignment).add(cdk.CDK.TAG.SERVICE, cdk.CDK.SERVICE.SSO);
1499
- cdk$1.Tags.of(assignment).add("Group", "analysts");
1577
+ cdk.Tags.of(assignment).add(cdk$1.CDK.TAG.SERVICE, cdk$1.CDK.SERVICE.SSO);
1578
+ cdk.Tags.of(assignment).add("Group", "analysts");
1500
1579
  });
1501
1580
  }
1502
1581
  /**
@@ -1521,8 +1600,8 @@ class JaypieSsoGroups extends constructs.Construct {
1521
1600
  targetId: accountId,
1522
1601
  targetType: "AWS_ACCOUNT",
1523
1602
  });
1524
- cdk$1.Tags.of(assignment).add(cdk.CDK.TAG.SERVICE, cdk.CDK.SERVICE.SSO);
1525
- cdk$1.Tags.of(assignment).add("Group", "developers");
1603
+ cdk.Tags.of(assignment).add(cdk$1.CDK.TAG.SERVICE, cdk$1.CDK.SERVICE.SSO);
1604
+ cdk.Tags.of(assignment).add("Group", "developers");
1526
1605
  });
1527
1606
  }
1528
1607
  }
@@ -1531,8 +1610,8 @@ class JaypieTraceSigningKeySecret extends JaypieEnvSecret {
1531
1610
  constructor(scope, id = "TraceSigningKey", props) {
1532
1611
  const defaultProps = {
1533
1612
  envKey: "TRACE_SIGNING_KEY",
1534
- roleTag: cdk.CDK.ROLE.API,
1535
- vendorTag: cdk.CDK.VENDOR.KNOWTRACE,
1613
+ roleTag: cdk$1.CDK.ROLE.API,
1614
+ vendorTag: cdk$1.CDK.VENDOR.KNOWTRACE,
1536
1615
  ...props,
1537
1616
  };
1538
1617
  super(scope, id, defaultProps);
@@ -1542,19 +1621,19 @@ class JaypieTraceSigningKeySecret extends JaypieEnvSecret {
1542
1621
  class JaypieWebDeploymentBucket extends constructs.Construct {
1543
1622
  constructor(scope, id, props = {}) {
1544
1623
  super(scope, id);
1545
- const roleTag = props.roleTag || cdk.CDK.ROLE.HOSTING;
1624
+ const roleTag = props.roleTag || cdk$1.CDK.ROLE.HOSTING;
1546
1625
  // Environment variable validation
1547
1626
  if (process.env.CDK_ENV_WEB_SUBDOMAIN &&
1548
- !cdk.isValidSubdomain(process.env.CDK_ENV_WEB_SUBDOMAIN)) {
1549
- throw new cdk.ConfigurationError("CDK_ENV_WEB_SUBDOMAIN is not a valid subdomain");
1627
+ !cdk$1.isValidSubdomain(process.env.CDK_ENV_WEB_SUBDOMAIN)) {
1628
+ throw new cdk$1.ConfigurationError("CDK_ENV_WEB_SUBDOMAIN is not a valid subdomain");
1550
1629
  }
1551
1630
  if (process.env.CDK_ENV_WEB_HOSTED_ZONE &&
1552
- !cdk.isValidHostname(process.env.CDK_ENV_WEB_HOSTED_ZONE)) {
1553
- throw new cdk.ConfigurationError("CDK_ENV_WEB_HOSTED_ZONE is not a valid hostname");
1631
+ !cdk$1.isValidHostname(process.env.CDK_ENV_WEB_HOSTED_ZONE)) {
1632
+ throw new cdk$1.ConfigurationError("CDK_ENV_WEB_HOSTED_ZONE is not a valid hostname");
1554
1633
  }
1555
1634
  if (process.env.CDK_ENV_HOSTED_ZONE &&
1556
- !cdk.isValidHostname(process.env.CDK_ENV_HOSTED_ZONE)) {
1557
- throw new cdk.ConfigurationError("CDK_ENV_HOSTED_ZONE is not a valid hostname");
1635
+ !cdk$1.isValidHostname(process.env.CDK_ENV_HOSTED_ZONE)) {
1636
+ throw new cdk$1.ConfigurationError("CDK_ENV_HOSTED_ZONE is not a valid hostname");
1558
1637
  }
1559
1638
  // Determine host from props or environment
1560
1639
  let host = props.host;
@@ -1562,7 +1641,7 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
1562
1641
  try {
1563
1642
  host =
1564
1643
  process.env.CDK_ENV_WEB_HOST ||
1565
- cdk.mergeDomain(process.env.CDK_ENV_WEB_SUBDOMAIN || "", process.env.CDK_ENV_WEB_HOSTED_ZONE ||
1644
+ cdk$1.mergeDomain(process.env.CDK_ENV_WEB_SUBDOMAIN || "", process.env.CDK_ENV_WEB_HOSTED_ZONE ||
1566
1645
  process.env.CDK_ENV_HOSTED_ZONE ||
1567
1646
  "");
1568
1647
  }
@@ -1570,8 +1649,8 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
1570
1649
  host = undefined;
1571
1650
  }
1572
1651
  }
1573
- if (host && !cdk.isValidHostname(host)) {
1574
- throw new cdk.ConfigurationError("Host is not a valid hostname");
1652
+ if (host && !cdk$1.isValidHostname(host)) {
1653
+ throw new cdk$1.ConfigurationError("Host is not a valid hostname");
1575
1654
  }
1576
1655
  // Determine zone from props or environment
1577
1656
  const zone = props.zone ||
@@ -1584,7 +1663,7 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
1584
1663
  blockPublicAccess: s3__namespace.BlockPublicAccess.BLOCK_ACLS,
1585
1664
  bucketName: props.name || constructEnvName("web"),
1586
1665
  publicReadAccess: true,
1587
- removalPolicy: cdk$1.RemovalPolicy.DESTROY,
1666
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
1588
1667
  versioned: false,
1589
1668
  websiteErrorDocument: "index.html",
1590
1669
  websiteIndexDocument: "index.html",
@@ -1602,7 +1681,7 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
1602
1681
  this.isWebsite = this.bucket.isWebsite;
1603
1682
  this.notificationsHandlerRole = undefined;
1604
1683
  this.policy = this.bucket.policy;
1605
- cdk$1.Tags.of(this.bucket).add(cdk.CDK.TAG.ROLE, roleTag);
1684
+ cdk.Tags.of(this.bucket).add(cdk$1.CDK.TAG.ROLE, roleTag);
1606
1685
  // Create deployment role if repository is configured
1607
1686
  let repo;
1608
1687
  if (process.env.CDK_ENV_REPO) {
@@ -1610,14 +1689,14 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
1610
1689
  }
1611
1690
  if (repo) {
1612
1691
  const bucketDeployRole = new awsIam.Role(this, "DestinationBucketDeployRole", {
1613
- assumedBy: new awsIam.FederatedPrincipal(cdk$1.Fn.importValue(cdk.CDK.IMPORT.OIDC_PROVIDER), {
1692
+ assumedBy: new awsIam.FederatedPrincipal(cdk.Fn.importValue(cdk$1.CDK.IMPORT.OIDC_PROVIDER), {
1614
1693
  StringLike: {
1615
1694
  "token.actions.githubusercontent.com:sub": repo,
1616
1695
  },
1617
1696
  }, "sts:AssumeRoleWithWebIdentity"),
1618
- maxSessionDuration: cdk$1.Duration.hours(1),
1697
+ maxSessionDuration: cdk.Duration.hours(1),
1619
1698
  });
1620
- cdk$1.Tags.of(bucketDeployRole).add(cdk.CDK.TAG.ROLE, cdk.CDK.ROLE.DEPLOY);
1699
+ cdk.Tags.of(bucketDeployRole).add(cdk$1.CDK.TAG.ROLE, cdk$1.CDK.ROLE.DEPLOY);
1621
1700
  // Allow the role to write to the bucket
1622
1701
  bucketDeployRole.addToPolicy(new awsIam.PolicyStatement({
1623
1702
  effect: awsIam.Effect.ALLOW,
@@ -1642,7 +1721,7 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
1642
1721
  }));
1643
1722
  this.deployRoleArn = bucketDeployRole.roleArn;
1644
1723
  // Output the deploy role ARN
1645
- new cdk$1.CfnOutput(this, "DestinationBucketDeployRoleArn", {
1724
+ new cdk.CfnOutput(this, "DestinationBucketDeployRoleArn", {
1646
1725
  value: bucketDeployRole.roleArn,
1647
1726
  });
1648
1727
  }
@@ -1662,10 +1741,10 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
1662
1741
  domainName: host,
1663
1742
  validation: acm__namespace.CertificateValidation.fromDns(hostedZone),
1664
1743
  });
1665
- new cdk$1.CfnOutput(this, "CertificateArn", {
1744
+ new cdk.CfnOutput(this, "CertificateArn", {
1666
1745
  value: this.certificate.certificateArn,
1667
1746
  });
1668
- cdk$1.Tags.of(this.certificate).add(cdk.CDK.TAG.ROLE, roleTag);
1747
+ cdk.Tags.of(this.certificate).add(cdk$1.CDK.TAG.ROLE, roleTag);
1669
1748
  }
1670
1749
  // Create CloudFront distribution
1671
1750
  this.distribution = new cloudfront__namespace.Distribution(this, "Distribution", {
@@ -1677,7 +1756,7 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
1677
1756
  certificate: this.certificate,
1678
1757
  domainNames: [host],
1679
1758
  });
1680
- cdk$1.Tags.of(this.distribution).add(cdk.CDK.TAG.ROLE, roleTag);
1759
+ cdk.Tags.of(this.distribution).add(cdk$1.CDK.TAG.ROLE, roleTag);
1681
1760
  // If this is production, enable caching on everything but index.html
1682
1761
  if (isProductionEnv()) {
1683
1762
  this.distribution.addBehavior("/*", new origins__namespace.S3Origin(this.bucket), {
@@ -1691,7 +1770,7 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
1691
1770
  target: route53__namespace.RecordTarget.fromAlias(new route53Targets__namespace.CloudFrontTarget(this.distribution)),
1692
1771
  zone: hostedZone,
1693
1772
  });
1694
- cdk$1.Tags.of(record).add(cdk.CDK.TAG.ROLE, cdk.CDK.ROLE.NETWORKING);
1773
+ cdk.Tags.of(record).add(cdk$1.CDK.TAG.ROLE, cdk$1.CDK.ROLE.NETWORKING);
1695
1774
  this.distributionDomainName = this.distribution.distributionDomainName;
1696
1775
  }
1697
1776
  }
@@ -1734,6 +1813,9 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
1734
1813
  grantWrite(identity, objectsKeyPattern) {
1735
1814
  return this.bucket.grantWrite(identity, objectsKeyPattern);
1736
1815
  }
1816
+ grantReplicationPermission(identity, props) {
1817
+ return this.bucket.grantReplicationPermission(identity, props);
1818
+ }
1737
1819
  s3UrlForObject(key) {
1738
1820
  return this.bucket.s3UrlForObject(key);
1739
1821
  }
@@ -1800,10 +1882,15 @@ exports.JaypieSsoGroups = JaypieSsoGroups;
1800
1882
  exports.JaypieStack = JaypieStack;
1801
1883
  exports.JaypieTraceSigningKeySecret = JaypieTraceSigningKeySecret;
1802
1884
  exports.JaypieWebDeploymentBucket = JaypieWebDeploymentBucket;
1885
+ exports.addDatadogLayer = addDatadogLayer;
1886
+ exports.addParamsAndSecrets = addParamsAndSecrets;
1803
1887
  exports.constructEnvName = constructEnvName;
1804
1888
  exports.constructStackName = constructStackName;
1889
+ exports.constructTagger = constructTagger;
1890
+ exports.envHostname = envHostname;
1805
1891
  exports.isEnv = isEnv;
1806
1892
  exports.isProductionEnv = isProductionEnv;
1807
1893
  exports.isSandboxEnv = isSandboxEnv;
1808
- exports.stackTagger = stackTagger;
1894
+ exports.jaypieLambdaEnv = jaypieLambdaEnv;
1895
+ exports.resolveHostedZone = resolveHostedZone;
1809
1896
  //# sourceMappingURL=index.cjs.map