@aws/nx-plugin 1.0.0-rc.85 → 1.0.0-rc.87

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.
Files changed (74) hide show
  1. package/migrations.json +11 -1
  2. package/package.json +1 -1
  3. package/src/infra/app/__snapshots__/generator.spec.ts.snap +34 -8
  4. package/src/infra/app/files/app/README.md.template +14 -0
  5. package/src/infra/app/generator.js +15 -2
  6. package/src/infra/app/generator.js.map +1 -1
  7. package/src/mcp-server/tools/general-guidance.js +1 -1
  8. package/src/mcp-server/tools/general-guidance.js.map +1 -1
  9. package/src/migrations/latest/add-destroy-sandbox-target/metadata.json +3 -0
  10. package/src/migrations/latest/add-destroy-sandbox-target/migration.d.ts +6 -0
  11. package/src/migrations/latest/add-destroy-sandbox-target/migration.js +150 -0
  12. package/src/migrations/latest/add-destroy-sandbox-target/migration.js.map +1 -0
  13. package/src/migrations/latest/terraform-rdb-proxy-iam-connect-grant/__snapshots__/migration.spec.ts.snap +23 -0
  14. package/src/migrations/latest/terraform-rdb-proxy-iam-connect-grant/metadata.json +3 -0
  15. package/src/migrations/latest/terraform-rdb-proxy-iam-connect-grant/migration.d.ts +6 -0
  16. package/src/migrations/latest/terraform-rdb-proxy-iam-connect-grant/migration.js +88 -0
  17. package/src/migrations/latest/terraform-rdb-proxy-iam-connect-grant/migration.js.map +1 -0
  18. package/src/open-api/ts-client/generator.js.map +1 -1
  19. package/src/open-api/ts-hooks/generator.spec.tsx +1 -1
  20. package/src/py/project/generator.js +5 -5
  21. package/src/py/project/generator.js.map +1 -1
  22. package/src/py/rdb/__snapshots__/generator.spec.ts.snap +21 -9
  23. package/src/py/rdb/files/__name__/utils.py.template +17 -1
  24. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +8 -8
  25. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +16 -16
  26. package/src/ts/dcr-proxy/__snapshots__/generator.spec.ts.snap +3 -3
  27. package/src/ts/lambda-function/__snapshots__/generator.spec.ts.snap +3 -3
  28. package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +132 -261
  29. package/src/ts/rdb/files/src/utils.ts.template +28 -1
  30. package/src/ts/react-website/cognito-auth/generator.js +1 -1
  31. package/src/ts/react-website/cognito-auth/generator.js.map +1 -1
  32. package/src/ts/react-website/runtime-config/generator.js +1 -1
  33. package/src/ts/react-website/runtime-config/generator.js.map +1 -1
  34. package/src/utils/agent-core-constructs/agent-core-constructs.js +3 -2
  35. package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
  36. package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/agentcore-gateway.ts.template +1 -1
  37. package/src/utils/api-constructs/api-constructs.js +7 -4
  38. package/src/utils/api-constructs/api-constructs.js.map +1 -1
  39. package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +4 -4
  40. package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +4 -4
  41. package/src/utils/api-constructs/files/cdk/core/api/rest/api-gateway-account.ts.template +1 -1
  42. package/src/utils/api-constructs/files/terraform/app/apis/http/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +4 -4
  43. package/src/utils/api-constructs/files/terraform/app/apis/rest/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +4 -4
  44. package/src/utils/ast.d.ts +13 -0
  45. package/src/utils/ast.js +36 -0
  46. package/src/utils/ast.js.map +1 -1
  47. package/src/utils/bundle/bundle.js +5 -2
  48. package/src/utils/bundle/bundle.js.map +1 -1
  49. package/src/utils/dcr-proxy-constructs/dcr-proxy-constructs.js +5 -3
  50. package/src/utils/dcr-proxy-constructs/dcr-proxy-constructs.js.map +1 -1
  51. package/src/utils/dcr-proxy-constructs/files/cdk/app/dcr-proxies/__nameKebabCase__/__nameKebabCase__.ts.template +1 -1
  52. package/src/utils/dcr-proxy-constructs/files/terraform/app/dcr-proxies/__nameKebabCase__/__nameKebabCase__.tf.template +2 -2
  53. package/src/utils/files/common/scripts/src/infra/stage-credentials/cdk-command.ts.template +7 -3
  54. package/src/utils/function-constructs/function-constructs.js +3 -3
  55. package/src/utils/function-constructs/function-constructs.js.map +1 -1
  56. package/src/utils/lambda-runtime-resolution.d.ts +74 -0
  57. package/src/utils/lambda-runtime-resolution.js +97 -0
  58. package/src/utils/lambda-runtime-resolution.js.map +1 -0
  59. package/src/utils/rdb-constructs/files/cdk/app/dbs/__nameKebabCase__.ts.template +3 -3
  60. package/src/utils/rdb-constructs/files/terraform/app/dbs/__nameKebabCase__/__nameKebabCase__.tf.template +10 -29
  61. package/src/utils/rdb-constructs/files/terraform/core/rdb/aurora/aurora.tf.template +28 -116
  62. package/src/utils/rdb-constructs/rdb-constructs.js +5 -3
  63. package/src/utils/rdb-constructs/rdb-constructs.js.map +1 -1
  64. package/src/utils/version-upgrade-migration/sync-lambda-runtimes.d.ts +28 -0
  65. package/src/utils/version-upgrade-migration/sync-lambda-runtimes.js +148 -0
  66. package/src/utils/version-upgrade-migration/sync-lambda-runtimes.js.map +1 -0
  67. package/src/utils/version-upgrade-migration/sync-python-language-version.d.ts +31 -0
  68. package/src/utils/version-upgrade-migration/sync-python-language-version.js +110 -0
  69. package/src/utils/version-upgrade-migration/sync-python-language-version.js.map +1 -0
  70. package/src/utils/version-upgrade-migration/sync-vended-versions.js +36 -7
  71. package/src/utils/version-upgrade-migration/sync-vended-versions.js.map +1 -1
  72. package/src/utils/versions.d.ts +60 -0
  73. package/src/utils/versions.js +51 -0
  74. package/src/utils/versions.js.map +1 -1
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */ import { LAMBDA_RUNTIME_VERSIONS } from "./versions.js";
5
+ /**
6
+ * Resolution of the Lambda runtimes and the CPython patch the version update
7
+ * pins.
8
+ *
9
+ * Lives here rather than beside the script so it is covered by the plugin's test
10
+ * suite; the script supplies the runtime list and the uv output.
11
+ */ /** Compare two dotted numeric versions (`24`, `3.14`) ascending. */ export const compareRuntimeVersions = (a, b)=>{
12
+ const left = a.split('.').map(Number);
13
+ const right = b.split('.').map(Number);
14
+ for(let i = 0; i < Math.max(left.length, right.length); i++){
15
+ const diff = (left[i] ?? 0) - (right[i] ?? 0);
16
+ if (diff !== 0) {
17
+ return diff;
18
+ }
19
+ }
20
+ return 0;
21
+ };
22
+ /**
23
+ * The version a managed runtime identifier names, or undefined for one that isn't
24
+ * a versioned `nodejs`/`python` runtime.
25
+ *
26
+ * `nodejs24.x` -> `24`, `python3.14` -> `3.14`. The bare `nodejs` and
27
+ * `nodejs4.3-edge` style identifiers carry no comparable version and are skipped.
28
+ */ export const runtimeIdentifierVersion = (identifier)=>{
29
+ const node = /^nodejs(\d+)\.x$/.exec(identifier);
30
+ if (node) {
31
+ return {
32
+ language: 'node',
33
+ version: node[1]
34
+ };
35
+ }
36
+ const python = /^python(\d+\.\d+)$/.exec(identifier);
37
+ return python ? {
38
+ language: 'python',
39
+ version: python[1]
40
+ } : undefined;
41
+ };
42
+ /**
43
+ * The latest managed runtime for each language in {@link LAMBDA_RUNTIME_VERSIONS},
44
+ * from the runtime identifiers `aws-cdk-lib` publishes.
45
+ *
46
+ * `Runtime.ALL` is a curated list of the runtimes CDK supports, so a runtime still
47
+ * in public preview does not appear — which is what makes it a usable source for a
48
+ * generally-available runtime. Never moves a runtime backwards: a pin ahead of
49
+ * what CDK offers stays.
50
+ *
51
+ * A language the list says nothing about keeps its current pin and is reported
52
+ * through `unresolved`, so a failure costs this bump alone rather than the whole
53
+ * version update.
54
+ */ export const resolveLambdaRuntimes = (identifiers)=>{
55
+ const unresolved = [];
56
+ const versions = Object.fromEntries(Object.keys(LAMBDA_RUNTIME_VERSIONS).map((language)=>{
57
+ const current = LAMBDA_RUNTIME_VERSIONS[language];
58
+ const available = identifiers.map(runtimeIdentifierVersion).filter((parsed)=>parsed?.language === language).map((parsed)=>parsed.version);
59
+ if (available.length === 0) {
60
+ unresolved.push({
61
+ language,
62
+ kept: current,
63
+ reason: 'no-runtimes-listed'
64
+ });
65
+ return [
66
+ language,
67
+ current
68
+ ];
69
+ }
70
+ const latest = available.reduce((best, version)=>compareRuntimeVersions(version, best) > 0 ? version : best);
71
+ return [
72
+ language,
73
+ compareRuntimeVersions(latest, current) > 0 ? latest : current
74
+ ];
75
+ }));
76
+ return {
77
+ versions,
78
+ unresolved
79
+ };
80
+ };
81
+ /** The warning a language's unresolved runtime reports. */ export const unresolvedRuntimeWarning = (entry)=>`Found no ${entry.language} runtime in the aws-cdk-lib runtime list, so it keeps its pinned runtime (${entry.kept})`;
82
+ /**
83
+ * The latest CPython patch uv can install for a `major.minor`, or undefined when
84
+ * it lists none.
85
+ *
86
+ * Lambda names only `major.minor` and patches the interpreter itself, but uv pins
87
+ * an exact `major.minor.patch`, so the patch is resolved from what uv can actually
88
+ * install for the runtime's minor. Pre-releases and the free-threaded variant are
89
+ * excluded: a generated project needs the default build of a final release.
90
+ */ export const resolveLatestPythonPatch = (entries, minor = LAMBDA_RUNTIME_VERSIONS.python)=>{
91
+ const [major, wanted] = minor.split('.').map(Number);
92
+ const patches = entries.filter((entry)=>entry.implementation === 'cpython' && entry.variant !== 'freethreaded' && entry.version_parts.major === major && entry.version_parts.minor === wanted && // A final release only; `3.15.0rc1` carries a suffix.
93
+ /^\d+\.\d+\.\d+$/.test(entry.version)).map((entry)=>entry.version_parts.patch);
94
+ return patches.length > 0 ? String(Math.max(...patches)) : undefined;
95
+ };
96
+
97
+ //# sourceMappingURL=lambda-runtime-resolution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/lambda-runtime-resolution.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { type ILambdaRuntime, LAMBDA_RUNTIME_VERSIONS } from './versions.js';\n\n/**\n * Resolution of the Lambda runtimes and the CPython patch the version update\n * pins.\n *\n * Lives here rather than beside the script so it is covered by the plugin's test\n * suite; the script supplies the runtime list and the uv output.\n */\n\n/** Compare two dotted numeric versions (`24`, `3.14`) ascending. */\nexport const compareRuntimeVersions = (a: string, b: string): number => {\n const left = a.split('.').map(Number);\n const right = b.split('.').map(Number);\n for (let i = 0; i < Math.max(left.length, right.length); i++) {\n const diff = (left[i] ?? 0) - (right[i] ?? 0);\n if (diff !== 0) {\n return diff;\n }\n }\n return 0;\n};\n\n/**\n * The version a managed runtime identifier names, or undefined for one that isn't\n * a versioned `nodejs`/`python` runtime.\n *\n * `nodejs24.x` -> `24`, `python3.14` -> `3.14`. The bare `nodejs` and\n * `nodejs4.3-edge` style identifiers carry no comparable version and are skipped.\n */\nexport const runtimeIdentifierVersion = (\n identifier: string,\n): { language: ILambdaRuntime; version: string } | undefined => {\n const node = /^nodejs(\\d+)\\.x$/.exec(identifier);\n if (node) {\n return { language: 'node', version: node[1] };\n }\n const python = /^python(\\d+\\.\\d+)$/.exec(identifier);\n return python ? { language: 'python', version: python[1] } : undefined;\n};\n\n/** Why a language's runtime could not be resolved. */\nexport type UnresolvedReason = 'no-runtimes-listed';\n\nexport interface RuntimeResolution {\n /** Runtime version per language, holding the current pin where unresolved. */\n readonly versions: Record<string, string>;\n /** Languages left on their current pin, and why. */\n readonly unresolved: {\n readonly language: string;\n readonly kept: string;\n readonly reason: UnresolvedReason;\n }[];\n}\n\n/**\n * The latest managed runtime for each language in {@link LAMBDA_RUNTIME_VERSIONS},\n * from the runtime identifiers `aws-cdk-lib` publishes.\n *\n * `Runtime.ALL` is a curated list of the runtimes CDK supports, so a runtime still\n * in public preview does not appear — which is what makes it a usable source for a\n * generally-available runtime. Never moves a runtime backwards: a pin ahead of\n * what CDK offers stays.\n *\n * A language the list says nothing about keeps its current pin and is reported\n * through `unresolved`, so a failure costs this bump alone rather than the whole\n * version update.\n */\nexport const resolveLambdaRuntimes = (\n identifiers: readonly string[],\n): RuntimeResolution => {\n const unresolved: RuntimeResolution['unresolved'][number][] = [];\n\n const versions = Object.fromEntries(\n (Object.keys(LAMBDA_RUNTIME_VERSIONS) as ILambdaRuntime[]).map(\n (language) => {\n const current = LAMBDA_RUNTIME_VERSIONS[language];\n const available = identifiers\n .map(runtimeIdentifierVersion)\n .filter((parsed) => parsed?.language === language)\n .map((parsed) => parsed!.version);\n\n if (available.length === 0) {\n unresolved.push({\n language,\n kept: current,\n reason: 'no-runtimes-listed',\n });\n return [language, current];\n }\n\n const latest = available.reduce((best, version) =>\n compareRuntimeVersions(version, best) > 0 ? version : best,\n );\n\n return [\n language,\n compareRuntimeVersions(latest, current) > 0 ? latest : current,\n ];\n },\n ),\n );\n\n return { versions, unresolved };\n};\n\n/** The warning a language's unresolved runtime reports. */\nexport const unresolvedRuntimeWarning = (\n entry: RuntimeResolution['unresolved'][number],\n): string =>\n `Found no ${entry.language} runtime in the aws-cdk-lib runtime list, so it keeps its pinned runtime (${entry.kept})`;\n\n/** A CPython build as `uv python list --output-format json` reports it. */\nexport interface UvPythonEntry {\n readonly version: string;\n readonly version_parts: {\n readonly major: number;\n readonly minor: number;\n readonly patch: number;\n };\n readonly implementation: string;\n readonly variant?: string;\n}\n\n/**\n * The latest CPython patch uv can install for a `major.minor`, or undefined when\n * it lists none.\n *\n * Lambda names only `major.minor` and patches the interpreter itself, but uv pins\n * an exact `major.minor.patch`, so the patch is resolved from what uv can actually\n * install for the runtime's minor. Pre-releases and the free-threaded variant are\n * excluded: a generated project needs the default build of a final release.\n */\nexport const resolveLatestPythonPatch = (\n entries: readonly UvPythonEntry[],\n minor: string = LAMBDA_RUNTIME_VERSIONS.python,\n): string | undefined => {\n const [major, wanted] = minor.split('.').map(Number);\n const patches = entries\n .filter(\n (entry) =>\n entry.implementation === 'cpython' &&\n entry.variant !== 'freethreaded' &&\n entry.version_parts.major === major &&\n entry.version_parts.minor === wanted &&\n // A final release only; `3.15.0rc1` carries a suffix.\n /^\\d+\\.\\d+\\.\\d+$/.test(entry.version),\n )\n .map((entry) => entry.version_parts.patch);\n\n return patches.length > 0 ? String(Math.max(...patches)) : undefined;\n};\n"],"names":["LAMBDA_RUNTIME_VERSIONS","compareRuntimeVersions","a","b","left","split","map","Number","right","i","Math","max","length","diff","runtimeIdentifierVersion","identifier","node","exec","language","version","python","undefined","resolveLambdaRuntimes","identifiers","unresolved","versions","Object","fromEntries","keys","current","available","filter","parsed","push","kept","reason","latest","reduce","best","unresolvedRuntimeWarning","entry","resolveLatestPythonPatch","entries","minor","major","wanted","patches","implementation","variant","version_parts","test","patch","String"],"mappings":"AAAA;;;CAGC,GACD,SAA8BA,uBAAuB,QAAQ,gBAAgB;AAE7E;;;;;;CAMC,GAED,kEAAkE,GAClE,OAAO,MAAMC,yBAAyB,CAACC,GAAWC;IAChD,MAAMC,OAAOF,EAAEG,KAAK,CAAC,KAAKC,GAAG,CAACC;IAC9B,MAAMC,QAAQL,EAAEE,KAAK,CAAC,KAAKC,GAAG,CAACC;IAC/B,IAAK,IAAIE,IAAI,GAAGA,IAAIC,KAAKC,GAAG,CAACP,KAAKQ,MAAM,EAAEJ,MAAMI,MAAM,GAAGH,IAAK;QAC5D,MAAMI,OAAO,AAACT,CAAAA,IAAI,CAACK,EAAE,IAAI,CAAA,IAAMD,CAAAA,KAAK,CAACC,EAAE,IAAI,CAAA;QAC3C,IAAII,SAAS,GAAG;YACd,OAAOA;QACT;IACF;IACA,OAAO;AACT,EAAE;AAEF;;;;;;CAMC,GACD,OAAO,MAAMC,2BAA2B,CACtCC;IAEA,MAAMC,OAAO,mBAAmBC,IAAI,CAACF;IACrC,IAAIC,MAAM;QACR,OAAO;YAAEE,UAAU;YAAQC,SAASH,IAAI,CAAC,EAAE;QAAC;IAC9C;IACA,MAAMI,SAAS,qBAAqBH,IAAI,CAACF;IACzC,OAAOK,SAAS;QAAEF,UAAU;QAAUC,SAASC,MAAM,CAAC,EAAE;IAAC,IAAIC;AAC/D,EAAE;AAgBF;;;;;;;;;;;;CAYC,GACD,OAAO,MAAMC,wBAAwB,CACnCC;IAEA,MAAMC,aAAwD,EAAE;IAEhE,MAAMC,WAAWC,OAAOC,WAAW,CACjC,AAACD,OAAOE,IAAI,CAAC5B,yBAA8CM,GAAG,CAC5D,CAACY;QACC,MAAMW,UAAU7B,uBAAuB,CAACkB,SAAS;QACjD,MAAMY,YAAYP,YACfjB,GAAG,CAACQ,0BACJiB,MAAM,CAAC,CAACC,SAAWA,QAAQd,aAAaA,UACxCZ,GAAG,CAAC,CAAC0B,SAAWA,OAAQb,OAAO;QAElC,IAAIW,UAAUlB,MAAM,KAAK,GAAG;YAC1BY,WAAWS,IAAI,CAAC;gBACdf;gBACAgB,MAAML;gBACNM,QAAQ;YACV;YACA,OAAO;gBAACjB;gBAAUW;aAAQ;QAC5B;QAEA,MAAMO,SAASN,UAAUO,MAAM,CAAC,CAACC,MAAMnB,UACrClB,uBAAuBkB,SAASmB,QAAQ,IAAInB,UAAUmB;QAGxD,OAAO;YACLpB;YACAjB,uBAAuBmC,QAAQP,WAAW,IAAIO,SAASP;SACxD;IACH;IAIJ,OAAO;QAAEJ;QAAUD;IAAW;AAChC,EAAE;AAEF,yDAAyD,GACzD,OAAO,MAAMe,2BAA2B,CACtCC,QAEA,CAAC,SAAS,EAAEA,MAAMtB,QAAQ,CAAC,0EAA0E,EAAEsB,MAAMN,IAAI,CAAC,CAAC,CAAC,CAAC;AAcvH;;;;;;;;CAQC,GACD,OAAO,MAAMO,2BAA2B,CACtCC,SACAC,QAAgB3C,wBAAwBoB,MAAM;IAE9C,MAAM,CAACwB,OAAOC,OAAO,GAAGF,MAAMtC,KAAK,CAAC,KAAKC,GAAG,CAACC;IAC7C,MAAMuC,UAAUJ,QACbX,MAAM,CACL,CAACS,QACCA,MAAMO,cAAc,KAAK,aACzBP,MAAMQ,OAAO,KAAK,kBAClBR,MAAMS,aAAa,CAACL,KAAK,KAAKA,SAC9BJ,MAAMS,aAAa,CAACN,KAAK,KAAKE,UAC9B,sDAAsD;QACtD,kBAAkBK,IAAI,CAACV,MAAMrB,OAAO,GAEvCb,GAAG,CAAC,CAACkC,QAAUA,MAAMS,aAAa,CAACE,KAAK;IAE3C,OAAOL,QAAQlC,MAAM,GAAG,IAAIwC,OAAO1C,KAAKC,GAAG,IAAImC,YAAYzB;AAC7D,EAAE"}
@@ -4,14 +4,14 @@ import { readFileSync } from 'fs';
4
4
  import { Construct } from 'constructs';
5
5
  import { Platform } from 'aws-cdk-lib/aws-ecr-assets';
6
6
  import {
7
- <%_ if (framework !== 'sqlmodel') { _%>
7
+ <%_ if (framework === 'prisma') { _%>
8
8
  Code,
9
9
  <%_ } _%>
10
10
  DockerImageCode,
11
11
  DockerImageFunction,
12
12
  Function,
13
13
  FunctionOptions,
14
- <%_ if (framework !== 'sqlmodel') { _%>
14
+ <%_ if (framework === 'prisma') { _%>
15
15
  Runtime,
16
16
  <%_ } _%>
17
17
  } from 'aws-cdk-lib/aws-lambda';
@@ -76,7 +76,7 @@ export class <%= nameClassName %> extends AuroraDatabase {
76
76
  ...baseProps,
77
77
  code: Code.fromAsset(createDbUserBundleDir),
78
78
  handler: 'index.handler',
79
- runtime: Runtime.NODEJS_LATEST,
79
+ runtime: <%- nodeRuntime %>,
80
80
  environment: {
81
81
  NODE_EXTRA_CA_CERTS: '/var/runtime/ca-cert.pem',
82
82
  },
@@ -88,12 +88,6 @@ variable "enable_rds_proxy" {
88
88
  default = true
89
89
  }
90
90
 
91
- variable "enable_credential_rotation" {
92
- description = "Whether to enable automatic credential rotation for the admin secret."
93
- type = bool
94
- default = true
95
- }
96
-
97
91
  variable "enable_cloudwatch_logs" {
98
92
  description = "Whether to export Aurora engine logs to CloudWatch. PostgreSQL logs DDL statements only (log_statement=ddl); MySQL enables Advanced Auditing scoped to connections and DDL (server_audit_events=CONNECT,QUERY_DDL). Neither logs statement parameter values, to avoid leaking PII into log data."
99
93
  type = bool
@@ -144,7 +138,7 @@ variable "create_db_user_docker_image_tag" {
144
138
  }
145
139
  <%_ } _%>
146
140
 
147
- <%_ if (framework !== 'sqlmodel') { _%>
141
+ <%_ if (framework === 'prisma') { _%>
148
142
  variable "asset_bucket_name" {
149
143
  description = "Name of the shared asset S3 bucket used to stage the Lambda deployment zip. Instantiate the `core/asset-bucket` module once per deployment and pass its `bucket_name` output here."
150
144
  type = string
@@ -163,7 +157,7 @@ resource "random_string" "suffix" {
163
157
  locals {
164
158
  config = jsondecode(file("${path.module}/../../../../../../../<%= projectRoot %>/config.json"))
165
159
  runtime_config_key = local.config.runtimeConfigKey
166
- <%_ if (framework !== 'sqlmodel') { _%>
160
+ <%_ if (framework === 'prisma') { _%>
167
161
  create_db_user_bundle_path = "${path.module}/../../../../../../../<%- createDbUserBundleDir %>"
168
162
  <%_ } _%>
169
163
  migration_function_name = "<%= nameKebabCase %>-migration-${random_string.suffix.result}"
@@ -177,7 +171,6 @@ module "aurora" {
177
171
  name = "<%= nameKebabCase %>"
178
172
  vpc_id = var.vpc_id
179
173
  subnet_ids = var.database_subnet_ids
180
- lambda_subnet_ids = var.lambda_subnet_ids
181
174
  engine = "<%= engine === 'mysql' ? 'aurora-mysql' : 'aurora-postgresql' %>"
182
175
  engine_version = var.engine_version
183
176
  database_name = "<%= databaseName %>"
@@ -189,7 +182,6 @@ module "aurora" {
189
182
  deletion_protection = var.deletion_protection
190
183
  skip_final_snapshot = var.skip_final_snapshot
191
184
  enable_rds_proxy = var.enable_rds_proxy
192
- enable_credential_rotation = var.enable_credential_rotation
193
185
  enable_cloudwatch_logs = var.enable_cloudwatch_logs
194
186
  enable_performance_insights = var.enable_performance_insights
195
187
  performance_insights_retention_period = var.performance_insights_retention_period
@@ -206,22 +198,6 @@ resource "aws_iam_role_policy" "proxy_db_user_connect" {
206
198
  policy = jsonencode({
207
199
  Version = "2012-10-17"
208
200
  Statement = [
209
- <%_ if (engine === 'mysql' && framework !== 'sqlmodel') { _%>
210
- {
211
- Effect = "Allow"
212
- Action = [
213
- "secretsmanager:GetSecretValue"
214
- ]
215
- Resource = [module.aurora.secret_arn]
216
- },
217
- {
218
- Effect = "Allow"
219
- Action = [
220
- "kms:Decrypt"
221
- ]
222
- Resource = [module.aurora.kms_key_arn]
223
- }
224
- <%_ } else { _%>
225
201
  {
226
202
  Effect = "Allow"
227
203
  Action = ["rds-db:connect"]
@@ -229,12 +205,11 @@ resource "aws_iam_role_policy" "proxy_db_user_connect" {
229
205
  "arn:aws:rds-db:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:dbuser:${module.aurora.cluster_resource_id}/${local.database_runtime_user}"
230
206
  ]
231
207
  }
232
- <%_ } _%>
233
208
  ]
234
209
  })
235
210
  }
236
211
 
237
- <%_ if (framework !== 'sqlmodel') { _%>
212
+ <%_ if (framework === 'prisma') { _%>
238
213
  data "archive_file" "create_db_user_zip" {
239
214
  type = "zip"
240
215
  source_dir = local.create_db_user_bundle_path
@@ -595,7 +570,7 @@ resource "aws_lambda_function" "create_db_user" {
595
570
  role = aws_iam_role.create_db_user.arn
596
571
  handler = "index.handler"
597
572
  source_code_hash = data.archive_file.create_db_user_zip.output_base64sha256
598
- runtime = "nodejs24.x"
573
+ runtime = "<%- nodeRuntime %>"
599
574
  timeout = 300
600
575
  architectures = ["arm64"]
601
576
  <%_ } _%>
@@ -612,6 +587,9 @@ resource "aws_lambda_function" "create_db_user" {
612
587
  environment {
613
588
  variables = {
614
589
  DATABASE_SECRET_ARN = module.aurora.secret_arn
590
+ DATABASE_HOST = module.aurora.writer_endpoint
591
+ DATABASE_PORT = module.aurora.cluster_port
592
+ DATABASE_NAME = module.aurora.database_name
615
593
  <%_ if (framework === 'prisma') { _%>
616
594
  NODE_EXTRA_CA_CERTS = "/var/runtime/ca-cert.pem"
617
595
  <%_ } _%>
@@ -699,6 +677,9 @@ resource "aws_lambda_function" "migration_handler" {
699
677
  environment {
700
678
  variables = {
701
679
  DATABASE_SECRET_ARN = module.aurora.secret_arn
680
+ DATABASE_HOST = module.aurora.writer_endpoint
681
+ DATABASE_PORT = module.aurora.cluster_port
682
+ DATABASE_NAME = module.aurora.database_name
702
683
  }
703
684
  }
704
685
 
@@ -1,5 +1,6 @@
1
1
  # Core Aurora module
2
- # This module creates an Aurora cluster and a generated admin secret.
2
+ # This module creates an Aurora cluster whose admin credentials are generated
3
+ # and rotated by RDS in Secrets Manager.
3
4
 
4
5
  terraform {
5
6
  required_version = ">= 1.0"
@@ -43,11 +44,6 @@ variable "subnet_ids" {
43
44
  type = list(string)
44
45
  }
45
46
 
46
- variable "lambda_subnet_ids" {
47
- description = "Subnet IDs for the credential-rotation Lambda. Must have outbound egress to AWS service endpoints (e.g. Secrets Manager) — use private subnets with a NAT gateway."
48
- type = list(string)
49
- }
50
-
51
47
  variable "engine" {
52
48
  description = "Aurora engine to use."
53
49
  type = string
@@ -117,12 +113,6 @@ variable "enable_rds_proxy" {
117
113
  default = true
118
114
  }
119
115
 
120
- variable "enable_credential_rotation" {
121
- description = "Whether to enable automatic credential rotation for the admin secret."
122
- type = bool
123
- default = true
124
- }
125
-
126
116
  variable "enable_cloudwatch_logs" {
127
117
  description = "Whether to export Aurora engine logs to CloudWatch. PostgreSQL logs DDL statements only (log_statement=ddl); MySQL enables Advanced Auditing scoped to connections and DDL (server_audit_events=CONNECT,QUERY_DDL). Neither logs statement parameter values, to avoid leaking PII into log data."
128
118
  type = bool
@@ -244,6 +234,20 @@ resource "aws_kms_key" "database" {
244
234
  "kms:CreateGrant"
245
235
  ]
246
236
  Resource = "*"
237
+ },
238
+ {
239
+ Sid = "AllowSecretsManagerService"
240
+ Effect = "Allow"
241
+ Principal = {
242
+ Service = "secretsmanager.amazonaws.com"
243
+ }
244
+ Action = [
245
+ "kms:Encrypt",
246
+ "kms:Decrypt",
247
+ "kms:GenerateDataKey*",
248
+ "kms:DescribeKey"
249
+ ]
250
+ Resource = "*"
247
251
  }
248
252
  ]
249
253
  })
@@ -298,35 +302,6 @@ resource "aws_db_subnet_group" "database" {
298
302
  })
299
303
  }
300
304
 
301
- resource "random_password" "master_password" {
302
- length = 32
303
- special = true
304
- override_special = "!#$%&*()-_=+[]{}<>:?"
305
- }
306
-
307
- resource "aws_secretsmanager_secret" "credentials" {
308
- #checkov:skip=CKV2_AWS_57:Rotation is configured via aws_cloudformation_stack.credentials_rotation using the AWS::SecretsManager-2024-09-16 transform; Checkov cannot resolve rotation schedules created by CloudFormation transforms
309
- name_prefix = "${var.name}-aurora-credentials-"
310
- kms_key_id = aws_kms_key.database.arn
311
-
312
- tags = merge(var.tags, {
313
- Name = "${var.name}-aurora-credentials"
314
- })
315
- }
316
-
317
- resource "aws_secretsmanager_secret_version" "credentials" {
318
- secret_id = aws_secretsmanager_secret.credentials.id
319
- secret_string = jsonencode({
320
- engine = var.engine == "aurora-mysql" ? "mysql" : "postgres"
321
- username = var.admin_user
322
- password = random_password.master_password.result
323
- host = aws_rds_cluster.database.endpoint
324
- port = aws_rds_cluster.database.port
325
- dbname = var.database_name
326
- dbClusterIdentifier = aws_rds_cluster.database.cluster_identifier
327
- })
328
- }
329
-
330
305
  resource "aws_rds_cluster" "database" {
331
306
  #checkov:skip=CKV2_AWS_27:Query logging is enabled by default via enable_cloudwatch_logs; checkov cannot resolve the conditional count expression on aws_rds_cluster_parameter_group.database
332
307
  #checkov:skip=CKV_AWS_139:Deletion protection is enabled but checkov is unable to detect it correctly
@@ -335,7 +310,8 @@ resource "aws_rds_cluster" "database" {
335
310
  engine_version = coalesce(var.engine_version, local.default_engine_version)
336
311
  database_name = var.database_name
337
312
  master_username = var.admin_user
338
- master_password = random_password.master_password.result
313
+ manage_master_user_password = true
314
+ master_user_secret_kms_key_id = aws_kms_key.database.arn
339
315
  db_subnet_group_name = aws_db_subnet_group.database.name
340
316
  db_cluster_parameter_group_name = var.enable_cloudwatch_logs ? aws_rds_cluster_parameter_group.database[0].name : null
341
317
  vpc_security_group_ids = [aws_security_group.database.id]
@@ -387,75 +363,6 @@ resource "aws_rds_cluster_instance" "database" {
387
363
  })
388
364
  }
389
365
 
390
- resource "aws_security_group" "rotation" {
391
- #checkov:skip=CKV2_AWS_5:Security group is attached to the hosted rotation Lambda created by AWS::SecretsManager::RotationSchedule; Checkov cannot resolve resources created by the CloudFormation transform
392
- count = var.enable_credential_rotation ? 1 : 0
393
- name_prefix = "${var.name}-aurora-rotation-"
394
- description = "Security group for Aurora secret rotation ${var.name}"
395
- vpc_id = var.vpc_id
396
-
397
- tags = merge(var.tags, {
398
- Name = "${var.name}-aurora-rotation"
399
- })
400
- }
401
-
402
- resource "aws_vpc_security_group_egress_rule" "rotation_to_database" {
403
- count = var.enable_credential_rotation ? 1 : 0
404
- security_group_id = aws_security_group.rotation[0].id
405
- referenced_security_group_id = aws_security_group.database.id
406
- from_port = coalesce(var.port, local.default_port)
407
- to_port = coalesce(var.port, local.default_port)
408
- ip_protocol = "tcp"
409
- description = "Allow outbound database traffic from secret rotation Lambda"
410
- }
411
-
412
- resource "aws_vpc_security_group_ingress_rule" "rotation_to_database" {
413
- count = var.enable_credential_rotation ? 1 : 0
414
- security_group_id = aws_security_group.database.id
415
- referenced_security_group_id = aws_security_group.rotation[0].id
416
- from_port = coalesce(var.port, local.default_port)
417
- to_port = coalesce(var.port, local.default_port)
418
- ip_protocol = "tcp"
419
- description = "Allow inbound database traffic from secret rotation Lambda"
420
- }
421
-
422
- resource "aws_cloudformation_stack" "credentials_rotation" {
423
- #checkov:skip=CKV_AWS_124:SNS event notifications are not required for the credentials rotation stack
424
- count = var.enable_credential_rotation ? 1 : 0
425
- name = "${local.cluster_name}-credentials-rotation"
426
-
427
- capabilities = ["CAPABILITY_IAM", "CAPABILITY_AUTO_EXPAND"]
428
-
429
- template_body = jsonencode({
430
- AWSTemplateFormatVersion = "2010-09-09"
431
- Transform = "AWS::SecretsManager-2024-09-16"
432
- Resources = {
433
- CredentialsRotationSchedule = {
434
- Type = "AWS::SecretsManager::RotationSchedule"
435
- Properties = {
436
- SecretId = aws_secretsmanager_secret.credentials.arn
437
- HostedRotationLambda = {
438
- RotationType = var.engine == "aurora-mysql" ? "MySQLSingleUser" : "PostgreSQLSingleUser"
439
- RotationLambdaName = "${local.cluster_name}-credentials-rotation"
440
- VpcSecurityGroupIds = aws_security_group.rotation[0].id
441
- VpcSubnetIds = join(",", var.lambda_subnet_ids)
442
- }
443
- RotationRules = {
444
- AutomaticallyAfterDays = 30
445
- }
446
- }
447
- }
448
- }
449
- })
450
-
451
- depends_on = [
452
- aws_secretsmanager_secret_version.credentials,
453
- aws_rds_cluster_instance.database,
454
- aws_vpc_security_group_egress_rule.rotation_to_database,
455
- aws_vpc_security_group_ingress_rule.rotation_to_database,
456
- ]
457
- }
458
-
459
366
  resource "aws_iam_role" "proxy" {
460
367
  count = var.enable_rds_proxy ? 1 : 0
461
368
 
@@ -694,6 +601,11 @@ output "cluster_endpoint" {
694
601
  value = var.enable_rds_proxy ? aws_db_proxy.aurora[0].endpoint : aws_rds_cluster.database.endpoint
695
602
  }
696
603
 
604
+ output "writer_endpoint" {
605
+ description = "Writer endpoint of the Aurora cluster itself, bypassing the RDS Proxy. Used by the admin-credentialled handlers, which connect directly to the cluster."
606
+ value = aws_rds_cluster.database.endpoint
607
+ }
608
+
697
609
  output "reader_endpoint" {
698
610
  description = "Reader endpoint of the Aurora cluster."
699
611
  value = aws_rds_cluster.database.reader_endpoint
@@ -720,12 +632,12 @@ output "proxy_role_name" {
720
632
  }
721
633
 
722
634
  output "secret_arn" {
723
- description = "ARN of the generated admin credentials secret."
724
- value = aws_secretsmanager_secret.credentials.arn
635
+ description = "ARN of the RDS-managed admin credentials secret. Its value is a JSON object with username and password only — connection details come from this module's other outputs."
636
+ value = one(aws_rds_cluster.database.master_user_secret[*].secret_arn)
725
637
  }
726
638
 
727
639
  output "kms_key_arn" {
728
- description = "ARN of the KMS key protecting Aurora and the generated secret."
640
+ description = "ARN of the KMS key protecting Aurora and its admin credentials secret."
729
641
  value = aws_kms_key.database.arn
730
642
  }
731
643
 
@@ -750,6 +662,6 @@ output "database_name" {
750
662
  }
751
663
 
752
664
  output "admin_user" {
753
- description = "Admin username stored in the generated secret."
754
- value = jsondecode(aws_secretsmanager_secret_version.credentials.secret_string).username
665
+ description = "Admin username stored in the RDS-managed credentials secret."
666
+ value = aws_rds_cluster.database.master_username
755
667
  }
@@ -6,7 +6,7 @@ import { addStarExport } from "../ast.js";
6
6
  import { esmVars } from "../module-format.js";
7
7
  import { addDependencyToTargetIfNotPresent } from "../nx.js";
8
8
  import { PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, SHARED_TERRAFORM_DIR } from "../shared-constructs-constants.js";
9
- import { terraformProviderVersions } from "../versions.js";
9
+ import { cdkLambdaRuntimeVars, terraformLambdaRuntimeVars, terraformProviderVersions } from "../versions.js";
10
10
  /**
11
11
  * Aurora Serverless v2 scaling bounds, in ACUs, that both IaC providers derive
12
12
  * from so the same generator options vend the same ceiling regardless of `--iac`.
@@ -48,7 +48,8 @@ export const addRdbCdkConstructs = async (tree, options)=>{
48
48
  });
49
49
  generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'cdk', 'app', 'dbs'), joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'src', 'app', 'dbs'), {
50
50
  ...options,
51
- ...esmVars(tree)
51
+ ...esmVars(tree),
52
+ ...cdkLambdaRuntimeVars()
52
53
  }, {
53
54
  overwriteStrategy: OverwriteStrategy.KeepExisting
54
55
  });
@@ -66,7 +67,8 @@ export const addRdbTerraformModules = (tree, options)=>{
66
67
  generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'terraform', 'app', 'dbs'), joinPathFragments(PACKAGES_DIR, SHARED_TERRAFORM_DIR, 'src', 'app', 'dbs'), {
67
68
  ...options,
68
69
  ...terraformProviderVersions(),
69
- ...auroraServerlessV2Capacity()
70
+ ...auroraServerlessV2Capacity(),
71
+ ...terraformLambdaRuntimeVars()
70
72
  }, {
71
73
  overwriteStrategy: OverwriteStrategy.KeepExisting
72
74
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../packages/nx-plugin/src/utils/rdb-constructs/rdb-constructs.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type ProjectConfiguration,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { addStarExport } from '../ast.js';\nimport type { Containers } from '../containers.js';\nimport type { Iac } from '../iac.js';\nimport { esmVars } from '../module-format.js';\nimport { addDependencyToTargetIfNotPresent } from '../nx.js';\nimport {\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n SHARED_TERRAFORM_DIR,\n} from '../shared-constructs-constants.js';\nimport { terraformProviderVersions } from '../versions.js';\n\n/**\n * Aurora Serverless v2 scaling bounds, in ACUs, that both IaC providers derive\n * from so the same generator options vend the same ceiling regardless of `--iac`.\n *\n * Set explicitly on CDK rather than inheriting `DatabaseClusterProps`, whose\n * default moves with `aws-cdk-lib`. Serverless v2 bills on ACUs consumed, not on\n * the ceiling, so the maximum is headroom rather than a cost commitment.\n */\nexport const AURORA_SERVERLESS_V2_CAPACITY = {\n min: 0.5,\n max: 4,\n} as const;\n\n/**\n * Substitution variables exposing the Aurora Serverless v2 scaling bounds to\n * generated CDK and Terraform templates.\n */\nconst auroraServerlessV2Capacity = () => ({\n serverlessMinCapacity: AURORA_SERVERLESS_V2_CAPACITY.min,\n serverlessMaxCapacity: AURORA_SERVERLESS_V2_CAPACITY.max,\n});\n\nexport interface AddRdbConstructOptions {\n projectName: string;\n projectRoot: string;\n nameClassName: string;\n nameKebabCase: string;\n databasePackageAlias: string;\n databaseName: string;\n adminUser: string;\n engine: 'postgres' | 'mysql';\n migrationBundleDir: string;\n /**\n * Node.js zip bundle directory for the create-db-user Lambda (ts#rdb).\n * When absent the migration Docker image is reused with the\n * `create_db_user_handler.handler` command (py#rdb).\n */\n createDbUserBundleDir: string;\n /** ORM framework used by the create-db-user Lambda. */\n framework: 'prisma' | 'sqlmodel';\n /** Local Docker tag for the Python create-db-user Lambda image. */\n createDbUserDockerImageTag?: string;\n /** Local Docker tag for the migration Lambda image. */\n migrationDockerImageTag: string;\n containerEngine: Containers;\n}\n\nexport const addRdbInfra = async (\n tree: Tree,\n options: AddRdbConstructOptions & { iac: Iac },\n) => {\n if (options.iac === 'cdk') {\n await addRdbCdkConstructs(tree, options);\n } else if (options.iac === 'terraform') {\n addRdbTerraformModules(tree, options);\n } else {\n throw new Error(`Unsupported iac ${options.iac}`);\n }\n\n updateJson(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n options.iac === 'cdk' ? SHARED_CONSTRUCTS_DIR : SHARED_TERRAFORM_DIR,\n 'project.json',\n ),\n (config: ProjectConfiguration) => {\n addDependencyToTargetIfNotPresent(\n config,\n 'build',\n `${options.projectName}:build`,\n );\n return config;\n },\n );\n};\n\nexport const addRdbCdkConstructs = async (\n tree: Tree,\n options: AddRdbConstructOptions,\n) => {\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'cdk', 'core', 'rdb'),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'core',\n 'rdb',\n ),\n { ...options, ...esmVars(tree), ...auroraServerlessV2Capacity() },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'cdk', 'app', 'dbs'),\n joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'src', 'app', 'dbs'),\n { ...options, ...esmVars(tree) },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'core',\n 'index.ts',\n ),\n './rdb/aurora.js',\n );\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'dbs',\n 'index.ts',\n ),\n `./${options.nameKebabCase}.js`,\n );\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'index.ts',\n ),\n './dbs/index.js',\n );\n};\n\nexport const addRdbTerraformModules = (\n tree: Tree,\n options: AddRdbConstructOptions,\n) => {\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'terraform', 'core', 'rdb'),\n joinPathFragments(PACKAGES_DIR, SHARED_TERRAFORM_DIR, 'src', 'core', 'rdb'),\n { ...terraformProviderVersions(), ...auroraServerlessV2Capacity() },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'terraform', 'app', 'dbs'),\n joinPathFragments(PACKAGES_DIR, SHARED_TERRAFORM_DIR, 'src', 'app', 'dbs'),\n {\n ...options,\n ...terraformProviderVersions(),\n ...auroraServerlessV2Capacity(),\n },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n};\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateJson","addStarExport","esmVars","addDependencyToTargetIfNotPresent","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","SHARED_TERRAFORM_DIR","terraformProviderVersions","AURORA_SERVERLESS_V2_CAPACITY","min","max","auroraServerlessV2Capacity","serverlessMinCapacity","serverlessMaxCapacity","addRdbInfra","tree","options","iac","addRdbCdkConstructs","addRdbTerraformModules","Error","config","projectName","dirname","overwriteStrategy","KeepExisting","nameKebabCase"],"mappings":"AAAA;;;CAGC,GACD,SACEA,aAAa,EACbC,iBAAiB,EACjBC,iBAAiB,EAGjBC,UAAU,QACL,aAAa;AACpB,SAASC,aAAa,QAAQ,YAAY;AAG1C,SAASC,OAAO,QAAQ,sBAAsB;AAC9C,SAASC,iCAAiC,QAAQ,WAAW;AAC7D,SACEC,YAAY,EACZC,qBAAqB,EACrBC,oBAAoB,QACf,oCAAoC;AAC3C,SAASC,yBAAyB,QAAQ,iBAAiB;AAE3D;;;;;;;CAOC,GACD,OAAO,MAAMC,gCAAgC;IAC3CC,KAAK;IACLC,KAAK;AACP,EAAW;AAEX;;;CAGC,GACD,MAAMC,6BAA6B,IAAO,CAAA;QACxCC,uBAAuBJ,8BAA8BC,GAAG;QACxDI,uBAAuBL,8BAA8BE,GAAG;IAC1D,CAAA;AA2BA,OAAO,MAAMI,cAAc,OACzBC,MACAC;IAEA,IAAIA,QAAQC,GAAG,KAAK,OAAO;QACzB,MAAMC,oBAAoBH,MAAMC;IAClC,OAAO,IAAIA,QAAQC,GAAG,KAAK,aAAa;QACtCE,uBAAuBJ,MAAMC;IAC/B,OAAO;QACL,MAAM,IAAII,MAAM,CAAC,gBAAgB,EAAEJ,QAAQC,GAAG,EAAE;IAClD;IAEAjB,WACEe,MACAjB,kBACEM,cACAY,QAAQC,GAAG,KAAK,QAAQZ,wBAAwBC,sBAChD,iBAEF,CAACe;QACClB,kCACEkB,QACA,SACA,GAAGL,QAAQM,WAAW,CAAC,MAAM,CAAC;QAEhC,OAAOD;IACT;AAEJ,EAAE;AAEF,OAAO,MAAMH,sBAAsB,OACjCH,MACAC;IAEAnB,cACEkB,MACAjB,kBAAkB,YAAYyB,OAAO,EAAE,SAAS,OAAO,QAAQ,QAC/DzB,kBACEM,cACAC,uBACA,OACA,QACA,QAEF;QAAE,GAAGW,OAAO;QAAE,GAAGd,QAAQa,KAAK;QAAE,GAAGJ,4BAA4B;IAAC,GAChE;QACEa,mBAAmBzB,kBAAkB0B,YAAY;IACnD;IAGF5B,cACEkB,MACAjB,kBAAkB,YAAYyB,OAAO,EAAE,SAAS,OAAO,OAAO,QAC9DzB,kBAAkBM,cAAcC,uBAAuB,OAAO,OAAO,QACrE;QAAE,GAAGW,OAAO;QAAE,GAAGd,QAAQa,KAAK;IAAC,GAC/B;QACES,mBAAmBzB,kBAAkB0B,YAAY;IACnD;IAGF,MAAMxB,cACJc,MACAjB,kBACEM,cACAC,uBACA,OACA,QACA,aAEF;IAEF,MAAMJ,cACJc,MACAjB,kBACEM,cACAC,uBACA,OACA,OACA,OACA,aAEF,CAAC,EAAE,EAAEW,QAAQU,aAAa,CAAC,GAAG,CAAC;IAEjC,MAAMzB,cACJc,MACAjB,kBACEM,cACAC,uBACA,OACA,OACA,aAEF;AAEJ,EAAE;AAEF,OAAO,MAAMc,yBAAyB,CACpCJ,MACAC;IAEAnB,cACEkB,MACAjB,kBAAkB,YAAYyB,OAAO,EAAE,SAAS,aAAa,QAAQ,QACrEzB,kBAAkBM,cAAcE,sBAAsB,OAAO,QAAQ,QACrE;QAAE,GAAGC,2BAA2B;QAAE,GAAGI,4BAA4B;IAAC,GAClE;QACEa,mBAAmBzB,kBAAkB0B,YAAY;IACnD;IAGF5B,cACEkB,MACAjB,kBAAkB,YAAYyB,OAAO,EAAE,SAAS,aAAa,OAAO,QACpEzB,kBAAkBM,cAAcE,sBAAsB,OAAO,OAAO,QACpE;QACE,GAAGU,OAAO;QACV,GAAGT,2BAA2B;QAC9B,GAAGI,4BAA4B;IACjC,GACA;QACEa,mBAAmBzB,kBAAkB0B,YAAY;IACnD;AAEJ,EAAE"}
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/utils/rdb-constructs/rdb-constructs.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type ProjectConfiguration,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { addStarExport } from '../ast.js';\nimport type { Containers } from '../containers.js';\nimport type { Iac } from '../iac.js';\nimport { esmVars } from '../module-format.js';\nimport { addDependencyToTargetIfNotPresent } from '../nx.js';\nimport {\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n SHARED_TERRAFORM_DIR,\n} from '../shared-constructs-constants.js';\nimport {\n cdkLambdaRuntimeVars,\n terraformLambdaRuntimeVars,\n terraformProviderVersions,\n} from '../versions.js';\n\n/**\n * Aurora Serverless v2 scaling bounds, in ACUs, that both IaC providers derive\n * from so the same generator options vend the same ceiling regardless of `--iac`.\n *\n * Set explicitly on CDK rather than inheriting `DatabaseClusterProps`, whose\n * default moves with `aws-cdk-lib`. Serverless v2 bills on ACUs consumed, not on\n * the ceiling, so the maximum is headroom rather than a cost commitment.\n */\nexport const AURORA_SERVERLESS_V2_CAPACITY = {\n min: 0.5,\n max: 4,\n} as const;\n\n/**\n * Substitution variables exposing the Aurora Serverless v2 scaling bounds to\n * generated CDK and Terraform templates.\n */\nconst auroraServerlessV2Capacity = () => ({\n serverlessMinCapacity: AURORA_SERVERLESS_V2_CAPACITY.min,\n serverlessMaxCapacity: AURORA_SERVERLESS_V2_CAPACITY.max,\n});\n\nexport interface AddRdbConstructOptions {\n projectName: string;\n projectRoot: string;\n nameClassName: string;\n nameKebabCase: string;\n databasePackageAlias: string;\n databaseName: string;\n adminUser: string;\n engine: 'postgres' | 'mysql';\n migrationBundleDir: string;\n /**\n * Node.js zip bundle directory for the create-db-user Lambda (ts#rdb).\n * When absent the migration Docker image is reused with the\n * `create_db_user_handler.handler` command (py#rdb).\n */\n createDbUserBundleDir: string;\n /** ORM framework used by the create-db-user Lambda. */\n framework: 'prisma' | 'sqlmodel';\n /** Local Docker tag for the Python create-db-user Lambda image. */\n createDbUserDockerImageTag?: string;\n /** Local Docker tag for the migration Lambda image. */\n migrationDockerImageTag: string;\n containerEngine: Containers;\n}\n\nexport const addRdbInfra = async (\n tree: Tree,\n options: AddRdbConstructOptions & { iac: Iac },\n) => {\n if (options.iac === 'cdk') {\n await addRdbCdkConstructs(tree, options);\n } else if (options.iac === 'terraform') {\n addRdbTerraformModules(tree, options);\n } else {\n throw new Error(`Unsupported iac ${options.iac}`);\n }\n\n updateJson(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n options.iac === 'cdk' ? SHARED_CONSTRUCTS_DIR : SHARED_TERRAFORM_DIR,\n 'project.json',\n ),\n (config: ProjectConfiguration) => {\n addDependencyToTargetIfNotPresent(\n config,\n 'build',\n `${options.projectName}:build`,\n );\n return config;\n },\n );\n};\n\nexport const addRdbCdkConstructs = async (\n tree: Tree,\n options: AddRdbConstructOptions,\n) => {\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'cdk', 'core', 'rdb'),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'core',\n 'rdb',\n ),\n { ...options, ...esmVars(tree), ...auroraServerlessV2Capacity() },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'cdk', 'app', 'dbs'),\n joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'src', 'app', 'dbs'),\n { ...options, ...esmVars(tree), ...cdkLambdaRuntimeVars() },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'core',\n 'index.ts',\n ),\n './rdb/aurora.js',\n );\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'dbs',\n 'index.ts',\n ),\n `./${options.nameKebabCase}.js`,\n );\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'index.ts',\n ),\n './dbs/index.js',\n );\n};\n\nexport const addRdbTerraformModules = (\n tree: Tree,\n options: AddRdbConstructOptions,\n) => {\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'terraform', 'core', 'rdb'),\n joinPathFragments(PACKAGES_DIR, SHARED_TERRAFORM_DIR, 'src', 'core', 'rdb'),\n { ...terraformProviderVersions(), ...auroraServerlessV2Capacity() },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'terraform', 'app', 'dbs'),\n joinPathFragments(PACKAGES_DIR, SHARED_TERRAFORM_DIR, 'src', 'app', 'dbs'),\n {\n ...options,\n ...terraformProviderVersions(),\n ...auroraServerlessV2Capacity(),\n ...terraformLambdaRuntimeVars(),\n },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n};\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateJson","addStarExport","esmVars","addDependencyToTargetIfNotPresent","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","SHARED_TERRAFORM_DIR","cdkLambdaRuntimeVars","terraformLambdaRuntimeVars","terraformProviderVersions","AURORA_SERVERLESS_V2_CAPACITY","min","max","auroraServerlessV2Capacity","serverlessMinCapacity","serverlessMaxCapacity","addRdbInfra","tree","options","iac","addRdbCdkConstructs","addRdbTerraformModules","Error","config","projectName","dirname","overwriteStrategy","KeepExisting","nameKebabCase"],"mappings":"AAAA;;;CAGC,GACD,SACEA,aAAa,EACbC,iBAAiB,EACjBC,iBAAiB,EAGjBC,UAAU,QACL,aAAa;AACpB,SAASC,aAAa,QAAQ,YAAY;AAG1C,SAASC,OAAO,QAAQ,sBAAsB;AAC9C,SAASC,iCAAiC,QAAQ,WAAW;AAC7D,SACEC,YAAY,EACZC,qBAAqB,EACrBC,oBAAoB,QACf,oCAAoC;AAC3C,SACEC,oBAAoB,EACpBC,0BAA0B,EAC1BC,yBAAyB,QACpB,iBAAiB;AAExB;;;;;;;CAOC,GACD,OAAO,MAAMC,gCAAgC;IAC3CC,KAAK;IACLC,KAAK;AACP,EAAW;AAEX;;;CAGC,GACD,MAAMC,6BAA6B,IAAO,CAAA;QACxCC,uBAAuBJ,8BAA8BC,GAAG;QACxDI,uBAAuBL,8BAA8BE,GAAG;IAC1D,CAAA;AA2BA,OAAO,MAAMI,cAAc,OACzBC,MACAC;IAEA,IAAIA,QAAQC,GAAG,KAAK,OAAO;QACzB,MAAMC,oBAAoBH,MAAMC;IAClC,OAAO,IAAIA,QAAQC,GAAG,KAAK,aAAa;QACtCE,uBAAuBJ,MAAMC;IAC/B,OAAO;QACL,MAAM,IAAII,MAAM,CAAC,gBAAgB,EAAEJ,QAAQC,GAAG,EAAE;IAClD;IAEAnB,WACEiB,MACAnB,kBACEM,cACAc,QAAQC,GAAG,KAAK,QAAQd,wBAAwBC,sBAChD,iBAEF,CAACiB;QACCpB,kCACEoB,QACA,SACA,GAAGL,QAAQM,WAAW,CAAC,MAAM,CAAC;QAEhC,OAAOD;IACT;AAEJ,EAAE;AAEF,OAAO,MAAMH,sBAAsB,OACjCH,MACAC;IAEArB,cACEoB,MACAnB,kBAAkB,YAAY2B,OAAO,EAAE,SAAS,OAAO,QAAQ,QAC/D3B,kBACEM,cACAC,uBACA,OACA,QACA,QAEF;QAAE,GAAGa,OAAO;QAAE,GAAGhB,QAAQe,KAAK;QAAE,GAAGJ,4BAA4B;IAAC,GAChE;QACEa,mBAAmB3B,kBAAkB4B,YAAY;IACnD;IAGF9B,cACEoB,MACAnB,kBAAkB,YAAY2B,OAAO,EAAE,SAAS,OAAO,OAAO,QAC9D3B,kBAAkBM,cAAcC,uBAAuB,OAAO,OAAO,QACrE;QAAE,GAAGa,OAAO;QAAE,GAAGhB,QAAQe,KAAK;QAAE,GAAGV,sBAAsB;IAAC,GAC1D;QACEmB,mBAAmB3B,kBAAkB4B,YAAY;IACnD;IAGF,MAAM1B,cACJgB,MACAnB,kBACEM,cACAC,uBACA,OACA,QACA,aAEF;IAEF,MAAMJ,cACJgB,MACAnB,kBACEM,cACAC,uBACA,OACA,OACA,OACA,aAEF,CAAC,EAAE,EAAEa,QAAQU,aAAa,CAAC,GAAG,CAAC;IAEjC,MAAM3B,cACJgB,MACAnB,kBACEM,cACAC,uBACA,OACA,OACA,aAEF;AAEJ,EAAE;AAEF,OAAO,MAAMgB,yBAAyB,CACpCJ,MACAC;IAEArB,cACEoB,MACAnB,kBAAkB,YAAY2B,OAAO,EAAE,SAAS,aAAa,QAAQ,QACrE3B,kBAAkBM,cAAcE,sBAAsB,OAAO,QAAQ,QACrE;QAAE,GAAGG,2BAA2B;QAAE,GAAGI,4BAA4B;IAAC,GAClE;QACEa,mBAAmB3B,kBAAkB4B,YAAY;IACnD;IAGF9B,cACEoB,MACAnB,kBAAkB,YAAY2B,OAAO,EAAE,SAAS,aAAa,OAAO,QACpE3B,kBAAkBM,cAAcE,sBAAsB,OAAO,OAAO,QACpE;QACE,GAAGY,OAAO;QACV,GAAGT,2BAA2B;QAC9B,GAAGI,4BAA4B;QAC/B,GAAGL,4BAA4B;IACjC,GACA;QACEkB,mBAAmB3B,kBAAkB4B,YAAY;IACnD;AAEJ,EAAE"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { type Tree } from '@nx/devkit';
6
+ /**
7
+ * Sync the Lambda runtimes vended into the projects this plugin owns.
8
+ *
9
+ * The runtimes present are read from each file rather than compared against a
10
+ * list of what past releases vended, which would need maintaining by hand for the
11
+ * same reason the pin itself does.
12
+ */
13
+ /** The IaC provider a vended file belongs to, decided by the directory it sits in. */
14
+ export type VendedIac = 'cdk' | 'terraform';
15
+ /**
16
+ * Sync the Lambda runtimes in the directories this plugin owns.
17
+ *
18
+ * A runtime below the pin is ours to move, as is a `_LATEST` alias — its value is
19
+ * decided by `aws-cdk-lib`, which is the drift this closes. A runtime at or ahead
20
+ * of the pin is the user's and is left, as is any Lambda outside these
21
+ * directories. One the rewrite cannot reach is reported instead.
22
+ *
23
+ * @returns the files changed, and the owned files still holding an older runtime
24
+ */
25
+ export declare const syncLambdaRuntimes: (tree: Tree, dirs: Readonly<Record<VendedIac, string>>) => Promise<{
26
+ updated: string[];
27
+ diverged: string[];
28
+ }>;