@jaypie/constructs 1.2.0-rc.0 → 1.2.0-rc.10

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.
package/dist/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as cdk from 'aws-cdk-lib';
2
- import { Tags, Stack, Duration, RemovalPolicy, CfnStack, Fn, CfnOutput, SecretValue } from 'aws-cdk-lib';
2
+ import { Tags, Stack, Fn, CfnOutput, SecretValue, Duration, RemovalPolicy, CfnStack } from 'aws-cdk-lib';
3
3
  import * as s3 from 'aws-cdk-lib/aws-s3';
4
4
  import { Bucket, StorageClass, BucketAccessControl, EventType } from 'aws-cdk-lib/aws-s3';
5
5
  import { Construct } from 'constructs';
@@ -285,6 +285,23 @@ function addDatadogLayers(lambdaFunction, options = {}) {
285
285
  return true;
286
286
  }
287
287
 
288
+ /**
289
+ * Conditional logging for CDK constructs.
290
+ * Only logs when CDK_ENV_LOG=true is set.
291
+ */
292
+ /* eslint-disable no-console */
293
+ function cdkLog(message, data) {
294
+ if (process.env.CDK_ENV_LOG === "true") {
295
+ if (data !== undefined) {
296
+ console.log(`[CDK] ${message}`, JSON.stringify(data, null, 2));
297
+ }
298
+ else {
299
+ console.log(`[CDK] ${message}`);
300
+ }
301
+ }
302
+ }
303
+ /* eslint-enable no-console */
304
+
288
305
  function constructEnvName(name, opts) {
289
306
  const env = opts?.env ?? process.env.PROJECT_ENV ?? "build";
290
307
  const key = opts?.key ?? process.env.PROJECT_KEY ?? "project";
@@ -354,6 +371,15 @@ function constructTagger(construct, { name } = {}) {
354
371
  }
355
372
 
356
373
  function envHostname({ component, domain, env, subdomain, } = {}) {
374
+ cdkLog("envHostname called", {
375
+ params: { component, domain, env, subdomain },
376
+ envVars: {
377
+ CDK_ENV_DOMAIN: process.env.CDK_ENV_DOMAIN,
378
+ CDK_ENV_HOSTED_ZONE: process.env.CDK_ENV_HOSTED_ZONE,
379
+ CDK_ENV_SUBDOMAIN: process.env.CDK_ENV_SUBDOMAIN,
380
+ PROJECT_ENV: process.env.PROJECT_ENV,
381
+ },
382
+ });
357
383
  const resolvedDomain = domain || process.env.CDK_ENV_DOMAIN || process.env.CDK_ENV_HOSTED_ZONE;
358
384
  if (!resolvedDomain) {
359
385
  throw new ConfigurationError("No hostname `domain` provided. Set CDK_ENV_DOMAIN or CDK_ENV_HOSTED_ZONE to use environment domain");
@@ -368,7 +394,9 @@ function envHostname({ component, domain, env, subdomain, } = {}) {
368
394
  filteredEnv,
369
395
  resolvedDomain,
370
396
  ].filter((part) => part);
371
- return parts.join(".");
397
+ const hostname = parts.join(".");
398
+ cdkLog("envHostname resolved", { hostname });
399
+ return hostname;
372
400
  }
373
401
 
374
402
  /**
@@ -656,15 +684,84 @@ function resolveDatadogLoggingDestination(scope, options) {
656
684
  return datadogLoggingDestination;
657
685
  }
658
686
 
687
+ /**
688
+ * Resolves environment input to a plain object.
689
+ *
690
+ * When environment is an object (legacy syntax), returns it as-is.
691
+ * When environment is an array:
692
+ * - Strings are treated as keys to lookup in process.env
693
+ * - Objects have their key-value pairs merged in
694
+ *
695
+ * @example
696
+ * // Legacy object syntax
697
+ * resolveEnvironment({ FOO: "bar" })
698
+ * // => { FOO: "bar" }
699
+ *
700
+ * @example
701
+ * // Array syntax with process.env lookup
702
+ * // Given process.env.MY_VAR = "hello"
703
+ * resolveEnvironment(["MY_VAR"])
704
+ * // => { MY_VAR: "hello" }
705
+ *
706
+ * @example
707
+ * // Array syntax with objects
708
+ * resolveEnvironment([{ FOO: "bar", BAZ: "qux" }])
709
+ * // => { FOO: "bar", BAZ: "qux" }
710
+ *
711
+ * @example
712
+ * // Mixed array syntax
713
+ * // Given process.env.MY_VAR = "hello"
714
+ * resolveEnvironment(["MY_VAR", { FOO: "bar" }])
715
+ * // => { MY_VAR: "hello", FOO: "bar" }
716
+ */
717
+ function resolveEnvironment(environment, env = process.env) {
718
+ if (!environment) {
719
+ return {};
720
+ }
721
+ // Legacy object syntax - return as-is
722
+ if (!Array.isArray(environment)) {
723
+ return environment;
724
+ }
725
+ // Array syntax - process each item
726
+ return environment.reduce((acc, item) => {
727
+ if (typeof item === "string") {
728
+ // String: lookup in process.env
729
+ const value = env[item];
730
+ if (value !== undefined) {
731
+ return {
732
+ ...acc,
733
+ [item]: value,
734
+ };
735
+ }
736
+ // Skip if not found in process.env
737
+ return acc;
738
+ }
739
+ // Object: merge key-value pairs
740
+ return {
741
+ ...acc,
742
+ ...item,
743
+ };
744
+ }, {});
745
+ }
746
+
659
747
  function resolveHostedZone(scope, { name = "HostedZone", zone = process.env.CDK_ENV_HOSTED_ZONE, } = {}) {
748
+ cdkLog("resolveHostedZone called", {
749
+ name,
750
+ zone: typeof zone === "string" ? zone : "(IHostedZone object)",
751
+ CDK_ENV_HOSTED_ZONE: process.env.CDK_ENV_HOSTED_ZONE,
752
+ });
660
753
  if (!zone) {
661
754
  throw new ConfigurationError("No `zone` provided. Set CDK_ENV_HOSTED_ZONE to use environment zone");
662
755
  }
663
756
  if (typeof zone === "string") {
757
+ cdkLog("resolveHostedZone: looking up zone by domain name", {
758
+ domainName: zone,
759
+ });
664
760
  return route53.HostedZone.fromLookup(scope, name, {
665
761
  domainName: zone,
666
762
  });
667
763
  }
764
+ cdkLog("resolveHostedZone: using provided IHostedZone object");
668
765
  return zone;
669
766
  }
670
767
 
@@ -688,6 +785,246 @@ const resolveParamsAndSecrets = ({ paramsAndSecrets, options, } = {}) => {
688
785
  return resolvedParamsAndSecrets;
689
786
  };
690
787
 
788
+ // It is a consumer if the environment is ephemeral
789
+ function checkEnvIsConsumer(env = process.env) {
790
+ return (env.PROJECT_ENV === CDK$2.ENV.PERSONAL ||
791
+ !!env.CDK_ENV_PERSONAL ||
792
+ /** @deprecated */ env.PROJECT_ENV === "ephemeral" ||
793
+ /** @deprecated */ !!env.CDK_ENV_EPHEMERAL);
794
+ }
795
+ function checkEnvIsProvider(env = process.env) {
796
+ return env.PROJECT_ENV === CDK$2.ENV.SANDBOX;
797
+ }
798
+ function cleanName(name) {
799
+ return name.replace(/[^a-zA-Z0-9:-]/g, "");
800
+ }
801
+ function exportEnvName(name, env = process.env) {
802
+ let rawName;
803
+ if (checkEnvIsProvider(env)) {
804
+ rawName = `env-${env.PROJECT_ENV}-${env.PROJECT_KEY}-${name}`;
805
+ // Clean the entire name to only allow alphanumeric, colons, and hyphens
806
+ return cleanName(rawName);
807
+ }
808
+ else {
809
+ if (checkEnvIsConsumer(env)) {
810
+ rawName = `env-${CDK$2.ENV.SANDBOX}-${env.PROJECT_KEY}-${name}`;
811
+ }
812
+ else {
813
+ rawName = `env-${env.PROJECT_ENV}-${env.PROJECT_KEY}-${name}`;
814
+ }
815
+ }
816
+ return cleanName(rawName);
817
+ }
818
+ class JaypieEnvSecret extends Construct {
819
+ constructor(scope, idOrEnvKey, props) {
820
+ // Check if idOrEnvKey should be treated as envKey:
821
+ // - No props provided OR props.envKey is not set
822
+ // - AND idOrEnvKey exists as a non-empty string in process.env
823
+ const treatAsEnvKey = (!props || props.envKey === undefined) &&
824
+ typeof process.env[idOrEnvKey] === "string" &&
825
+ process.env[idOrEnvKey] !== "";
826
+ const id = treatAsEnvKey ? `EnvSecret_${idOrEnvKey}` : idOrEnvKey;
827
+ super(scope, id);
828
+ const { consumer = checkEnvIsConsumer(), envKey: envKeyProp, export: exportParam, generateSecretString, provider = checkEnvIsProvider(), roleTag, vendorTag, value, } = props || {};
829
+ const envKey = treatAsEnvKey ? idOrEnvKey : envKeyProp;
830
+ this._envKey = envKey;
831
+ let exportName;
832
+ if (!exportParam) {
833
+ exportName = exportEnvName(id);
834
+ }
835
+ else {
836
+ exportName = cleanName(exportParam);
837
+ }
838
+ if (consumer) {
839
+ const secretName = Fn.importValue(exportName);
840
+ this._secret = secretsmanager.Secret.fromSecretNameV2(this, id, secretName);
841
+ // Add CfnOutput for consumer secrets
842
+ new CfnOutput(this, `ConsumedName`, {
843
+ value: this._secret.secretName,
844
+ });
845
+ }
846
+ else {
847
+ const secretValue = envKey && process.env[envKey] ? process.env[envKey] : value;
848
+ const secretProps = {
849
+ generateSecretString,
850
+ secretStringValue: !generateSecretString && secretValue
851
+ ? SecretValue.unsafePlainText(secretValue)
852
+ : undefined,
853
+ };
854
+ this._secret = new secretsmanager.Secret(this, id, secretProps);
855
+ if (roleTag) {
856
+ Tags.of(this._secret).add(CDK$2.TAG.ROLE, roleTag);
857
+ }
858
+ if (vendorTag) {
859
+ Tags.of(this._secret).add(CDK$2.TAG.VENDOR, vendorTag);
860
+ }
861
+ if (provider) {
862
+ new CfnOutput(this, `ProvidedName`, {
863
+ value: this._secret.secretName,
864
+ exportName,
865
+ });
866
+ }
867
+ else {
868
+ new CfnOutput(this, `CreatedName`, {
869
+ value: this._secret.secretName,
870
+ });
871
+ }
872
+ }
873
+ }
874
+ // IResource implementation
875
+ get stack() {
876
+ return Stack.of(this);
877
+ }
878
+ get env() {
879
+ return {
880
+ account: Stack.of(this).account,
881
+ region: Stack.of(this).region,
882
+ };
883
+ }
884
+ applyRemovalPolicy(policy) {
885
+ this._secret.applyRemovalPolicy(policy);
886
+ }
887
+ // ISecret implementation
888
+ get secretArn() {
889
+ return this._secret.secretArn;
890
+ }
891
+ get secretName() {
892
+ return this._secret.secretName;
893
+ }
894
+ get secretFullArn() {
895
+ return this._secret.secretFullArn;
896
+ }
897
+ get encryptionKey() {
898
+ return this._secret.encryptionKey;
899
+ }
900
+ get secretValue() {
901
+ return this._secret.secretValue;
902
+ }
903
+ secretValueFromJson(key) {
904
+ return this._secret.secretValueFromJson(key);
905
+ }
906
+ grantRead(grantee, versionStages) {
907
+ return this._secret.grantRead(grantee, versionStages);
908
+ }
909
+ grantWrite(grantee) {
910
+ return this._secret.grantWrite(grantee);
911
+ }
912
+ addRotationSchedule(id, options) {
913
+ return this._secret.addRotationSchedule(id, options);
914
+ }
915
+ addToResourcePolicy(statement) {
916
+ return this._secret.addToResourcePolicy(statement);
917
+ }
918
+ denyAccountRootDelete() {
919
+ this._secret.denyAccountRootDelete();
920
+ }
921
+ attach(target) {
922
+ return this._secret.attach(target);
923
+ }
924
+ cfnDynamicReferenceKey(options) {
925
+ return this._secret.cfnDynamicReferenceKey(options);
926
+ }
927
+ get envKey() {
928
+ return this._envKey;
929
+ }
930
+ }
931
+
932
+ /**
933
+ * Cache for secrets by scope to avoid creating duplicates.
934
+ * Uses WeakMap to allow garbage collection when scopes are no longer referenced.
935
+ */
936
+ const secretsByScope = new WeakMap();
937
+ /**
938
+ * Gets or creates the secrets cache for a given scope.
939
+ */
940
+ function getSecretsCache(scope) {
941
+ let cache = secretsByScope.get(scope);
942
+ if (!cache) {
943
+ cache = new Map();
944
+ secretsByScope.set(scope, cache);
945
+ }
946
+ return cache;
947
+ }
948
+ /**
949
+ * Gets an existing secret from the cache or creates a new one.
950
+ * This ensures that multiple constructs within the same scope share secrets.
951
+ */
952
+ function getOrCreateSecret(scope, envKey, props) {
953
+ const cache = getSecretsCache(scope);
954
+ const existingSecret = cache.get(envKey);
955
+ if (existingSecret) {
956
+ return existingSecret;
957
+ }
958
+ // Create new secret - JaypieEnvSecret's smart constructor handles envKey detection
959
+ const secret = new JaypieEnvSecret(scope, envKey, {
960
+ ...props,
961
+ envKey,
962
+ });
963
+ cache.set(envKey, secret);
964
+ return secret;
965
+ }
966
+ /**
967
+ * Resolves secrets input to an array of JaypieEnvSecret instances.
968
+ *
969
+ * When an item is already a JaypieEnvSecret, it's passed through as-is.
970
+ * When an item is a string, a JaypieEnvSecret is created (or reused from cache)
971
+ * with the string as the envKey.
972
+ *
973
+ * Secrets are cached per scope to avoid creating duplicate secrets when
974
+ * multiple constructs in the same scope reference the same secret.
975
+ *
976
+ * @example
977
+ * // JaypieEnvSecret instances pass through
978
+ * const secret = new JaypieEnvSecret(scope, "MySecret", { envKey: "MY_KEY" });
979
+ * resolveSecrets(scope, [secret])
980
+ * // => [secret]
981
+ *
982
+ * @example
983
+ * // Strings create JaypieEnvSecret instances
984
+ * resolveSecrets(scope, ["AUTH0_SECRET", "MONGODB_URI"])
985
+ * // => [JaypieEnvSecret(envKey: "AUTH0_SECRET"), JaypieEnvSecret(envKey: "MONGODB_URI")]
986
+ *
987
+ * @example
988
+ * // Mixed input
989
+ * const existingSecret = new JaypieEnvSecret(scope, "Existing", { envKey: "EXISTING" });
990
+ * resolveSecrets(scope, [existingSecret, "NEW_SECRET"])
991
+ * // => [existingSecret, JaypieEnvSecret(envKey: "NEW_SECRET")]
992
+ *
993
+ * @example
994
+ * // Secrets are shared across calls with the same scope
995
+ * const secrets1 = resolveSecrets(scope, ["SHARED_SECRET"]);
996
+ * const secrets2 = resolveSecrets(scope, ["SHARED_SECRET"]);
997
+ * // secrets1[0] === secrets2[0] (same instance)
998
+ */
999
+ function resolveSecrets(scope, secrets) {
1000
+ if (!secrets || secrets.length === 0) {
1001
+ return [];
1002
+ }
1003
+ return secrets.map((item) => {
1004
+ if (typeof item === "string") {
1005
+ return getOrCreateSecret(scope, item);
1006
+ }
1007
+ // Already a JaypieEnvSecret instance
1008
+ return item;
1009
+ });
1010
+ }
1011
+ /**
1012
+ * Clears the secrets cache for a given scope.
1013
+ * Primarily useful for testing.
1014
+ */
1015
+ function clearSecretsCache(scope) {
1016
+ secretsByScope.delete(scope);
1017
+ }
1018
+ /**
1019
+ * Clears all secrets caches.
1020
+ * Primarily useful for testing.
1021
+ */
1022
+ function clearAllSecretsCaches() {
1023
+ // WeakMap doesn't have a clear() method, so we create a new one
1024
+ // This relies on the module being reloaded or the function being called
1025
+ // between test runs. For testing, use clearSecretsCache(scope) instead.
1026
+ }
1027
+
691
1028
  class JaypieApiGateway extends Construct {
692
1029
  constructor(scope, id, props) {
693
1030
  super(scope, id);
@@ -869,11 +1206,15 @@ class JaypieAppStack extends JaypieStack {
869
1206
  class JaypieLambda extends Construct {
870
1207
  constructor(scope, id, props) {
871
1208
  super(scope, id);
872
- const { allowAllOutbound, allowPublicSubnet, architecture = lambda.Architecture.X86_64, code, datadogApiKeyArn, deadLetterQueue, deadLetterQueueEnabled, deadLetterTopic, description, environment: initialEnvironment = {}, envSecrets = {}, ephemeralStorageSize, filesystem, handler = "index.handler", initialPolicy, layers = [], 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 = new lambda.Runtime("nodejs24.x", lambda.RuntimeFamily.NODEJS, {
1209
+ const { allowAllOutbound, allowPublicSubnet, architecture = lambda.Architecture.X86_64, code, datadogApiKeyArn, deadLetterQueue, deadLetterQueueEnabled, deadLetterTopic, description, environment: environmentInput, 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 = new lambda.Runtime("nodejs24.x", lambda.RuntimeFamily.NODEJS, {
873
1210
  supportsInlineCode: true,
874
- }), runtimeManagementMode, secrets = [], securityGroups, timeout = Duration.seconds(CDK$2.DURATION.LAMBDA_WORKER), tracing, vendorTag, vpc, vpcSubnets, } = props;
1211
+ }), runtimeManagementMode, secrets: secretsInput = [], securityGroups, timeout = Duration.seconds(CDK$2.DURATION.LAMBDA_WORKER), tracing, vendorTag, vpc, vpcSubnets, } = props;
1212
+ // Resolve environment from array or object syntax
1213
+ const initialEnvironment = resolveEnvironment(environmentInput);
875
1214
  // Get base environment with defaults
876
1215
  const environment = jaypieLambdaEnv({ initialEnvironment });
1216
+ // Resolve secrets from mixed array (strings and JaypieEnvSecret instances)
1217
+ const secrets = resolveSecrets(scope, secretsInput);
877
1218
  const codeAsset = typeof code === "string" ? lambda.Code.fromAsset(code) : code;
878
1219
  // Create a working copy of layers
879
1220
  const resolvedLayers = [...layers];
@@ -1854,150 +2195,6 @@ class JaypieDistribution extends Construct {
1854
2195
  }
1855
2196
  }
1856
2197
 
1857
- // It is a consumer if the environment is ephemeral
1858
- function checkEnvIsConsumer(env = process.env) {
1859
- return (env.PROJECT_ENV === CDK$2.ENV.PERSONAL ||
1860
- !!env.CDK_ENV_PERSONAL ||
1861
- /** @deprecated */ env.PROJECT_ENV === "ephemeral" ||
1862
- /** @deprecated */ !!env.CDK_ENV_EPHEMERAL);
1863
- }
1864
- function checkEnvIsProvider(env = process.env) {
1865
- return env.PROJECT_ENV === CDK$2.ENV.SANDBOX;
1866
- }
1867
- function cleanName(name) {
1868
- return name.replace(/[^a-zA-Z0-9:-]/g, "");
1869
- }
1870
- function exportEnvName(name, env = process.env) {
1871
- let rawName;
1872
- if (checkEnvIsProvider(env)) {
1873
- rawName = `env-${env.PROJECT_ENV}-${env.PROJECT_KEY}-${name}`;
1874
- // Clean the entire name to only allow alphanumeric, colons, and hyphens
1875
- return cleanName(rawName);
1876
- }
1877
- else {
1878
- if (checkEnvIsConsumer(env)) {
1879
- rawName = `env-${CDK$2.ENV.SANDBOX}-${env.PROJECT_KEY}-${name}`;
1880
- }
1881
- else {
1882
- rawName = `env-${env.PROJECT_ENV}-${env.PROJECT_KEY}-${name}`;
1883
- }
1884
- }
1885
- return cleanName(rawName);
1886
- }
1887
- class JaypieEnvSecret extends Construct {
1888
- constructor(scope, idOrEnvKey, props) {
1889
- // Check if idOrEnvKey should be treated as envKey:
1890
- // - No props provided OR props.envKey is not set
1891
- // - AND idOrEnvKey exists as a non-empty string in process.env
1892
- const treatAsEnvKey = (!props || props.envKey === undefined) &&
1893
- typeof process.env[idOrEnvKey] === "string" &&
1894
- process.env[idOrEnvKey] !== "";
1895
- const id = treatAsEnvKey ? `EnvSecret_${idOrEnvKey}` : idOrEnvKey;
1896
- super(scope, id);
1897
- const { consumer = checkEnvIsConsumer(), envKey: envKeyProp, export: exportParam, generateSecretString, provider = checkEnvIsProvider(), roleTag, vendorTag, value, } = props || {};
1898
- const envKey = treatAsEnvKey ? idOrEnvKey : envKeyProp;
1899
- this._envKey = envKey;
1900
- let exportName;
1901
- if (!exportParam) {
1902
- exportName = exportEnvName(id);
1903
- }
1904
- else {
1905
- exportName = cleanName(exportParam);
1906
- }
1907
- if (consumer) {
1908
- const secretName = Fn.importValue(exportName);
1909
- this._secret = secretsmanager.Secret.fromSecretNameV2(this, id, secretName);
1910
- // Add CfnOutput for consumer secrets
1911
- new CfnOutput(this, `ConsumedName`, {
1912
- value: this._secret.secretName,
1913
- });
1914
- }
1915
- else {
1916
- const secretValue = envKey && process.env[envKey] ? process.env[envKey] : value;
1917
- const secretProps = {
1918
- generateSecretString,
1919
- secretStringValue: !generateSecretString && secretValue
1920
- ? SecretValue.unsafePlainText(secretValue)
1921
- : undefined,
1922
- };
1923
- this._secret = new secretsmanager.Secret(this, id, secretProps);
1924
- if (roleTag) {
1925
- Tags.of(this._secret).add(CDK$2.TAG.ROLE, roleTag);
1926
- }
1927
- if (vendorTag) {
1928
- Tags.of(this._secret).add(CDK$2.TAG.VENDOR, vendorTag);
1929
- }
1930
- if (provider) {
1931
- new CfnOutput(this, `ProvidedName`, {
1932
- value: this._secret.secretName,
1933
- exportName,
1934
- });
1935
- }
1936
- else {
1937
- new CfnOutput(this, `CreatedName`, {
1938
- value: this._secret.secretName,
1939
- });
1940
- }
1941
- }
1942
- }
1943
- // IResource implementation
1944
- get stack() {
1945
- return Stack.of(this);
1946
- }
1947
- get env() {
1948
- return {
1949
- account: Stack.of(this).account,
1950
- region: Stack.of(this).region,
1951
- };
1952
- }
1953
- applyRemovalPolicy(policy) {
1954
- this._secret.applyRemovalPolicy(policy);
1955
- }
1956
- // ISecret implementation
1957
- get secretArn() {
1958
- return this._secret.secretArn;
1959
- }
1960
- get secretName() {
1961
- return this._secret.secretName;
1962
- }
1963
- get secretFullArn() {
1964
- return this._secret.secretFullArn;
1965
- }
1966
- get encryptionKey() {
1967
- return this._secret.encryptionKey;
1968
- }
1969
- get secretValue() {
1970
- return this._secret.secretValue;
1971
- }
1972
- secretValueFromJson(key) {
1973
- return this._secret.secretValueFromJson(key);
1974
- }
1975
- grantRead(grantee, versionStages) {
1976
- return this._secret.grantRead(grantee, versionStages);
1977
- }
1978
- grantWrite(grantee) {
1979
- return this._secret.grantWrite(grantee);
1980
- }
1981
- addRotationSchedule(id, options) {
1982
- return this._secret.addRotationSchedule(id, options);
1983
- }
1984
- addToResourcePolicy(statement) {
1985
- return this._secret.addToResourcePolicy(statement);
1986
- }
1987
- denyAccountRootDelete() {
1988
- this._secret.denyAccountRootDelete();
1989
- }
1990
- attach(target) {
1991
- return this._secret.attach(target);
1992
- }
1993
- cfnDynamicReferenceKey(options) {
1994
- return this._secret.cfnDynamicReferenceKey(options);
1995
- }
1996
- get envKey() {
1997
- return this._envKey;
1998
- }
1999
- }
2000
-
2001
2198
  class JaypieDatadogSecret extends JaypieEnvSecret {
2002
2199
  constructor(scope, id = "MongoConnectionString", props) {
2003
2200
  const defaultProps = {
@@ -2404,17 +2601,45 @@ class JaypieMongoDbSecret extends JaypieEnvSecret {
2404
2601
  class JaypieNextJs extends Construct {
2405
2602
  constructor(scope, id, props) {
2406
2603
  super(scope, id);
2604
+ cdkLog("JaypieNextJs constructor called", {
2605
+ id,
2606
+ props: {
2607
+ domainName: props?.domainName,
2608
+ hostedZone: typeof props?.hostedZone === "string"
2609
+ ? props.hostedZone
2610
+ : props?.hostedZone
2611
+ ? "(IHostedZone object)"
2612
+ : undefined,
2613
+ nextjsPath: props?.nextjsPath,
2614
+ hasEnvironment: !!props?.environment,
2615
+ hasEnvSecrets: !!props?.envSecrets,
2616
+ hasSecrets: !!props?.secrets,
2617
+ },
2618
+ cwd: process.cwd(),
2619
+ });
2407
2620
  const domainName = props?.domainName || envHostname();
2408
2621
  this.domainName = domainName;
2409
2622
  const domainNameSanitized = domainName
2410
2623
  .replace(/\./g, "-")
2411
2624
  .replace(/[^a-zA-Z0-9]/g, "_");
2625
+ cdkLog("JaypieNextJs domain resolved", {
2626
+ domainName,
2627
+ domainNameSanitized,
2628
+ });
2629
+ // Resolve environment from array or object syntax
2630
+ const environment = resolveEnvironment(props?.environment);
2412
2631
  const envSecrets = props?.envSecrets || {};
2413
2632
  const nextjsPath = props?.nextjsPath?.startsWith("..")
2414
2633
  ? path.join(process.cwd(), props.nextjsPath)
2415
2634
  : props?.nextjsPath || path.join(process.cwd(), "..", "nextjs");
2416
2635
  const paramsAndSecrets = resolveParamsAndSecrets();
2417
- const secrets = props?.secrets || [];
2636
+ cdkLog("JaypieNextJs paths resolved", {
2637
+ nextjsPath,
2638
+ propsNextjsPath: props?.nextjsPath,
2639
+ cwd: process.cwd(),
2640
+ });
2641
+ // Resolve secrets from mixed array (strings and JaypieEnvSecret instances)
2642
+ const secrets = resolveSecrets(scope, props?.secrets);
2418
2643
  // Process secrets environment variables
2419
2644
  const secretsEnvironment = Object.entries(envSecrets).reduce((acc, [key, secret]) => ({
2420
2645
  ...acc,
@@ -2440,6 +2665,17 @@ class JaypieNextJs extends Construct {
2440
2665
  }
2441
2666
  return acc;
2442
2667
  }, {});
2668
+ cdkLog("JaypieNextJs creating Nextjs construct", {
2669
+ nextjsPath,
2670
+ domainName,
2671
+ environmentKeys: Object.keys({
2672
+ ...jaypieLambdaEnv(),
2673
+ ...environment,
2674
+ ...secretsEnvironment,
2675
+ ...jaypieSecretsEnvironment,
2676
+ ...nextPublicEnv,
2677
+ }),
2678
+ });
2443
2679
  const nextjs = new Nextjs(this, "NextJsApp", {
2444
2680
  nextjsPath,
2445
2681
  domainProps: {
@@ -2450,6 +2686,7 @@ class JaypieNextJs extends Construct {
2450
2686
  },
2451
2687
  environment: {
2452
2688
  ...jaypieLambdaEnv(),
2689
+ ...environment,
2453
2690
  ...secretsEnvironment,
2454
2691
  ...jaypieSecretsEnvironment,
2455
2692
  ...nextPublicEnv,
@@ -2476,8 +2713,10 @@ class JaypieNextJs extends Construct {
2476
2713
  },
2477
2714
  },
2478
2715
  });
2716
+ cdkLog("JaypieNextJs Nextjs construct created successfully");
2479
2717
  addDatadogLayers(nextjs.imageOptimizationFunction);
2480
2718
  addDatadogLayers(nextjs.serverFunction.lambdaFunction);
2719
+ cdkLog("JaypieNextJs Datadog layers added");
2481
2720
  // Grant secret read permissions
2482
2721
  Object.values(envSecrets).forEach((secret) => {
2483
2722
  secret.grantRead(nextjs.serverFunction.lambdaFunction);
@@ -3254,5 +3493,5 @@ class JaypieTraceSigningKeySecret extends JaypieEnvSecret {
3254
3493
  }
3255
3494
  }
3256
3495
 
3257
- export { CDK$2 as CDK, JaypieAccountLoggingBucket, JaypieApiGateway, JaypieAppStack, JaypieBucketQueuedLambda, JaypieDatadogBucket, JaypieDatadogForwarder, JaypieDatadogSecret, JaypieDistribution, JaypieDnsRecord, JaypieEnvSecret, JaypieEventsRule, JaypieExpressLambda, JaypieGitHubDeployRole, JaypieHostedZone, JaypieInfrastructureStack, JaypieLambda, JaypieMongoDbSecret, JaypieNextJs, JaypieOpenAiSecret, JaypieOrganizationTrail, JaypieQueuedLambda, JaypieSsoPermissions, JaypieSsoSyncApplication, JaypieStack, JaypieStaticWebBucket, JaypieTraceSigningKeySecret, JaypieWebDeploymentBucket, addDatadogLayers, constructEnvName, constructStackName, constructTagger, envHostname, extendDatadogRole, isEnv, isProductionEnv, isSandboxEnv, isValidHostname$1 as isValidHostname, isValidSubdomain, jaypieLambdaEnv, mergeDomain, resolveDatadogForwarderFunction, resolveDatadogLayers, resolveDatadogLoggingDestination, resolveHostedZone, resolveParamsAndSecrets };
3496
+ export { CDK$2 as CDK, JaypieAccountLoggingBucket, JaypieApiGateway, JaypieAppStack, JaypieBucketQueuedLambda, JaypieDatadogBucket, JaypieDatadogForwarder, JaypieDatadogSecret, JaypieDistribution, JaypieDnsRecord, JaypieEnvSecret, JaypieEventsRule, JaypieExpressLambda, JaypieGitHubDeployRole, JaypieHostedZone, JaypieInfrastructureStack, JaypieLambda, JaypieMongoDbSecret, JaypieNextJs, JaypieOpenAiSecret, JaypieOrganizationTrail, JaypieQueuedLambda, JaypieSsoPermissions, JaypieSsoSyncApplication, JaypieStack, JaypieStaticWebBucket, JaypieTraceSigningKeySecret, JaypieWebDeploymentBucket, addDatadogLayers, cdkLog, clearAllSecretsCaches, clearSecretsCache, constructEnvName, constructStackName, constructTagger, envHostname, extendDatadogRole, isEnv, isProductionEnv, isSandboxEnv, isValidHostname$1 as isValidHostname, isValidSubdomain, jaypieLambdaEnv, mergeDomain, resolveDatadogForwarderFunction, resolveDatadogLayers, resolveDatadogLoggingDestination, resolveEnvironment, resolveHostedZone, resolveParamsAndSecrets, resolveSecrets };
3258
3497
  //# sourceMappingURL=index.js.map