@aws/nx-plugin 1.0.0-rc.81 → 1.0.0-rc.83
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/migrations.json +26 -1
- package/package.json +1 -1
- package/src/agentcore-gateway/generator.d.ts +7 -6
- package/src/agentcore-gateway/generator.js +2 -12
- package/src/agentcore-gateway/generator.js.map +1 -1
- package/src/migrations/latest/dynamodb-terraform-app-module-outputs/metadata.json +3 -0
- package/src/migrations/latest/dynamodb-terraform-app-module-outputs/migration.d.ts +6 -0
- package/src/migrations/latest/dynamodb-terraform-app-module-outputs/migration.js +69 -0
- package/src/migrations/latest/dynamodb-terraform-app-module-outputs/migration.js.map +1 -0
- package/src/migrations/latest/runtime-config-namespace-defaults/metadata.json +3 -0
- package/src/migrations/latest/runtime-config-namespace-defaults/migration.d.ts +6 -0
- package/src/migrations/latest/runtime-config-namespace-defaults/migration.js +131 -0
- package/src/migrations/latest/runtime-config-namespace-defaults/migration.js.map +1 -0
- package/src/migrations/latest/terraform-data-resource-destroy-protection/__snapshots__/migration.spec.ts.snap +75 -0
- package/src/migrations/latest/terraform-data-resource-destroy-protection/metadata.json +3 -0
- package/src/migrations/latest/terraform-data-resource-destroy-protection/migration.d.ts +6 -0
- package/src/migrations/latest/terraform-data-resource-destroy-protection/migration.js +78 -0
- package/src/migrations/latest/terraform-data-resource-destroy-protection/migration.js.map +1 -0
- package/src/migrations/latest/terraform-gateway-cedar-render-root-ejs/metadata.json +3 -0
- package/src/migrations/latest/terraform-gateway-cedar-render-root-ejs/migration.d.ts +6 -0
- package/src/migrations/latest/terraform-gateway-cedar-render-root-ejs/migration.js +38 -0
- package/src/migrations/latest/terraform-gateway-cedar-render-root-ejs/migration.js.map +1 -0
- package/src/migrations/latest/terraform-load-runtime-config-src-path/metadata.json +3 -0
- package/src/migrations/latest/terraform-load-runtime-config-src-path/migration.d.ts +6 -0
- package/src/migrations/latest/terraform-load-runtime-config-src-path/migration.js +48 -0
- package/src/migrations/latest/terraform-load-runtime-config-src-path/migration.js.map +1 -0
- package/src/py/dynamodb/__snapshots__/generator.spec.ts.snap +21 -0
- package/src/ts/dynamodb/__snapshots__/generator.spec.ts.snap +21 -0
- package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +12 -0
- package/src/ts/react-website/app/generator.js +2 -2
- package/src/ts/react-website/app/generator.js.map +1 -1
- package/src/utils/agent-core-constructs/agent-core-constructs.d.ts +9 -2
- package/src/utils/agent-core-constructs/agent-core-constructs.js +22 -8
- package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
- package/src/utils/dynamodb-constructs/files/terraform/app/dynamodb/__nameKebabCase__/__nameKebabCase__.tf.template +15 -0
- package/src/utils/dynamodb-constructs/files/terraform/core/dynamodb/dynamodb.tf.template +6 -0
- package/src/utils/files/terraform/src/core/runtime-config/appconfig/appconfig.tf.template +2 -2
- package/src/utils/files/terraform/src/core/runtime-config/appconfig-deployment/appconfig-deployment.tf.template +1 -1
- package/src/utils/rdb-constructs/files/terraform/core/rdb/aurora/aurora.tf.template +6 -0
- package/src/utils/shared-constructs-constants.d.ts +22 -0
- package/src/utils/shared-constructs-constants.js +18 -0
- package/src/utils/shared-constructs-constants.js.map +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/terraform-data-resource-destroy-protection/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { MigrationReturnObject, Tree } from '@nx/devkit';\nimport { applyGritQL, matchGritQL } from '../../../utils/ast.js';\nimport { formatFilesInSubtree } from '../../../utils/format.js';\nimport {\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n} from '../../../utils/shared-constructs-constants.js';\n\n/**\n * Bring existing workspaces up to the destroy protection the generators now\n * vend on the data-bearing Terraform resources:\n *\n * - The DynamoDB table and the Aurora cluster gain\n * `lifecycle { prevent_destroy = true }`. This is a second, independent layer\n * on top of the service-side `deletion_protection_enabled` /\n * `deletion_protection` flags, matching the two guards the CDK constructs\n * already have (`deletionProtection` plus `RemovalPolicy.RETAIN`). Without it,\n * clearing the service-side flag destroys the data in the same apply.\n * `prevent_destroy` cannot reference a variable, so it is vended as a literal\n * and removed to tear down.\n * - Their KMS keys pin `deletion_window_in_days = 30`, the provider maximum and\n * the CDK default. Restoring either resource from a point-in-time backup or\n * snapshot requires its key, so the window in which a scheduled key deletion\n * can still be cancelled matters as much as the backup itself.\n *\n * These files are generated with `KeepExisting`, so without this an upgraded\n * workspace keeps the weaker single-layer protection. Diverged files are left\n * untouched and reported via `nextSteps`.\n */\n\nconst TERRAFORM_DYNAMODB_FILE = `${PACKAGES_DIR}/${SHARED_TERRAFORM_DIR}/src/core/dynamodb/dynamodb.tf`;\nconst TERRAFORM_AURORA_FILE = `${PACKAGES_DIR}/${SHARED_TERRAFORM_DIR}/src/core/rdb/aurora/aurora.tf`;\n\nconst hcl = (pattern: string) => `language hcl\\n${pattern}`;\n\nconst divergedMessage = (filePath: string, resource: string) =>\n `${filePath}: has diverged from the generated shape - left untouched. To protect the ${resource} from being destroyed when the service-side deletion protection flag is cleared, add \\`lifecycle { prevent_destroy = true }\\` to it, and set \\`deletion_window_in_days = 30\\` on its KMS key.`;\n\n/**\n * Add the maximum KMS pending window to a key that omits it, so a scheduled\n * deletion stays cancellable for as long as the provider allows.\n */\nconst migrateKmsKey = async (\n tree: Tree,\n filePath: string,\n keyLabel: string,\n): Promise<void> => {\n const keyBlock = hcl(`\\`resource \"aws_kms_key\" \"${keyLabel}\" { $props }\\``);\n\n // Already pinned - nothing to do.\n if (\n await matchGritQL(\n tree,\n filePath,\n hcl(\n `\\`resource \"aws_kms_key\" \"${keyLabel}\" { $props }\\` where { $props <: contains \\`deletion_window_in_days = $_\\` }`,\n ),\n )\n ) {\n return;\n }\n\n if (!(await matchGritQL(tree, filePath, keyBlock))) {\n return; // Reported by the caller, which matches the data resource too.\n }\n\n await applyGritQL(\n tree,\n filePath,\n hcl(\n `\\`resource \"aws_kms_key\" \"${keyLabel}\" { $props }\\` where { $props <: contains \\`enable_key_rotation = $rotation\\` => \\`enable_key_rotation = $rotation\\n\\n deletion_window_in_days = 30\\` }`,\n ),\n );\n};\n\n/**\n * Add `lifecycle { prevent_destroy = true }` to a data-bearing resource.\n */\nconst migrateDataResource = async (\n tree: Tree,\n filePath: string,\n resourceType: string,\n resourceLabel: string,\n nextSteps: string[],\n description: string,\n): Promise<boolean> => {\n const resourceBlock = hcl(\n `\\`resource \"${resourceType}\" \"${resourceLabel}\" { $props }\\``,\n );\n\n if (!(await matchGritQL(tree, filePath, resourceBlock))) {\n nextSteps.push(divergedMessage(filePath, description));\n return false;\n }\n\n // Already guarded - keep the user's block, whatever it is set to.\n if (\n await matchGritQL(\n tree,\n filePath,\n hcl(\n `\\`resource \"${resourceType}\" \"${resourceLabel}\" { $props }\\` where { $props <: contains \\`prevent_destroy = $_\\` }`,\n ),\n )\n ) {\n return true;\n }\n\n await applyGritQL(\n tree,\n filePath,\n hcl(\n `\\`resource \"${resourceType}\" \"${resourceLabel}\" { $props }\\` => \\`resource \"${resourceType}\" \"${resourceLabel}\" {\\n $props\\n\\n lifecycle {\\n prevent_destroy = true\\n }\\n}\\``,\n ),\n );\n\n return true;\n};\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n if (tree.exists(TERRAFORM_DYNAMODB_FILE)) {\n if (\n await migrateDataResource(\n tree,\n TERRAFORM_DYNAMODB_FILE,\n 'aws_dynamodb_table',\n 'table',\n nextSteps,\n 'DynamoDB table',\n )\n ) {\n await migrateKmsKey(tree, TERRAFORM_DYNAMODB_FILE, 'table');\n }\n }\n\n if (tree.exists(TERRAFORM_AURORA_FILE)) {\n if (\n await migrateDataResource(\n tree,\n TERRAFORM_AURORA_FILE,\n 'aws_rds_cluster',\n 'database',\n nextSteps,\n 'Aurora cluster',\n )\n ) {\n await migrateKmsKey(tree, TERRAFORM_AURORA_FILE, 'database');\n }\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["applyGritQL","matchGritQL","formatFilesInSubtree","PACKAGES_DIR","SHARED_TERRAFORM_DIR","TERRAFORM_DYNAMODB_FILE","TERRAFORM_AURORA_FILE","hcl","pattern","divergedMessage","filePath","resource","migrateKmsKey","tree","keyLabel","keyBlock","migrateDataResource","resourceType","resourceLabel","nextSteps","description","resourceBlock","push","migration","exists"],"mappings":"AAAA;;;CAGC,GAED,SAASA,WAAW,EAAEC,WAAW,QAAQ,wBAAwB;AACjE,SAASC,oBAAoB,QAAQ,2BAA2B;AAChE,SACEC,YAAY,EACZC,oBAAoB,QACf,gDAAgD;AAEvD;;;;;;;;;;;;;;;;;;;;CAoBC,GAED,MAAMC,0BAA0B,GAAGF,aAAa,CAAC,EAAEC,qBAAqB,8BAA8B,CAAC;AACvG,MAAME,wBAAwB,GAAGH,aAAa,CAAC,EAAEC,qBAAqB,8BAA8B,CAAC;AAErG,MAAMG,MAAM,CAACC,UAAoB,CAAC,cAAc,EAAEA,SAAS;AAE3D,MAAMC,kBAAkB,CAACC,UAAkBC,WACzC,GAAGD,SAAS,yEAAyE,EAAEC,SAAS,6LAA6L,CAAC;AAEhS;;;CAGC,GACD,MAAMC,gBAAgB,OACpBC,MACAH,UACAI;IAEA,MAAMC,WAAWR,IAAI,CAAC,0BAA0B,EAAEO,SAAS,cAAc,CAAC;IAE1E,kCAAkC;IAClC,IACE,MAAMb,YACJY,MACAH,UACAH,IACE,CAAC,0BAA0B,EAAEO,SAAS,4EAA4E,CAAC,IAGvH;QACA;IACF;IAEA,IAAI,CAAE,MAAMb,YAAYY,MAAMH,UAAUK,WAAY;QAClD,QAAQ,+DAA+D;IACzE;IAEA,MAAMf,YACJa,MACAH,UACAH,IACE,CAAC,0BAA0B,EAAEO,SAAS,wJAAwJ,CAAC;AAGrM;AAEA;;CAEC,GACD,MAAME,sBAAsB,OAC1BH,MACAH,UACAO,cACAC,eACAC,WACAC;IAEA,MAAMC,gBAAgBd,IACpB,CAAC,YAAY,EAAEU,aAAa,GAAG,EAAEC,cAAc,cAAc,CAAC;IAGhE,IAAI,CAAE,MAAMjB,YAAYY,MAAMH,UAAUW,gBAAiB;QACvDF,UAAUG,IAAI,CAACb,gBAAgBC,UAAUU;QACzC,OAAO;IACT;IAEA,kEAAkE;IAClE,IACE,MAAMnB,YACJY,MACAH,UACAH,IACE,CAAC,YAAY,EAAEU,aAAa,GAAG,EAAEC,cAAc,oEAAoE,CAAC,IAGxH;QACA,OAAO;IACT;IAEA,MAAMlB,YACJa,MACAH,UACAH,IACE,CAAC,YAAY,EAAEU,aAAa,GAAG,EAAEC,cAAc,8BAA8B,EAAED,aAAa,GAAG,EAAEC,cAAc,oEAAoE,CAAC;IAIxL,OAAO;AACT;AAEA,eAAe,eAAeK,UAC5BV,IAAU;IAEV,MAAMM,YAAsB,EAAE;IAE9B,IAAIN,KAAKW,MAAM,CAACnB,0BAA0B;QACxC,IACE,MAAMW,oBACJH,MACAR,yBACA,sBACA,SACAc,WACA,mBAEF;YACA,MAAMP,cAAcC,MAAMR,yBAAyB;QACrD;IACF;IAEA,IAAIQ,KAAKW,MAAM,CAAClB,wBAAwB;QACtC,IACE,MAAMU,oBACJH,MACAP,uBACA,mBACA,YACAa,WACA,mBAEF;YACA,MAAMP,cAAcC,MAAMP,uBAAuB;QACnD;IACF;IAEA,MAAMJ,qBAAqBW;IAE3B,OAAO;QAAEM;IAAU;AACrB"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { type MigrationReturnObject, type Tree } from '@nx/devkit';
|
|
6
|
+
export default function migration(tree: Tree): Promise<MigrationReturnObject>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/ import { getProjects, joinPathFragments } from "@nx/devkit";
|
|
5
|
+
import { AGENTCORE_GATEWAY_GENERATOR_INFO } from "../../../agentcore-gateway/generator.js";
|
|
6
|
+
import { addDependenciesToPackageJson } from "../../../utils/dependencies.js";
|
|
7
|
+
import { formatFilesInSubtree } from "../../../utils/format.js";
|
|
8
|
+
import { PACKAGES_DIR, SHARED_TERRAFORM_DIR } from "../../../utils/shared-constructs-constants.js";
|
|
9
|
+
import { TS_VERSIONS } from "../../../utils/versions.js";
|
|
10
|
+
/**
|
|
11
|
+
* Declare `ejs` at the workspace root for Terraform gateways with Cedar
|
|
12
|
+
* policies, which is where `render-cedar.cjs` resolves it from: the script runs
|
|
13
|
+
* in the shared terraform project, which has no `package.json` of its own.
|
|
14
|
+
*/ const RENDER_SCRIPT = 'render-cedar.cjs';
|
|
15
|
+
export default async function migration(tree) {
|
|
16
|
+
const gatewaysDir = joinPathFragments(PACKAGES_DIR, SHARED_TERRAFORM_DIR, 'src', 'app', 'gateways');
|
|
17
|
+
let needsRootEjs = false;
|
|
18
|
+
for (const project of getProjects(tree).values()){
|
|
19
|
+
const metadata = project.metadata;
|
|
20
|
+
if (metadata?.generator !== AGENTCORE_GATEWAY_GENERATOR_INFO.id) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
// Only a Terraform gateway with Cedar policies vends the render script; a
|
|
24
|
+
// CDK one resolves ejs from the shared constructs project instead.
|
|
25
|
+
if (tree.exists(joinPathFragments(gatewaysDir, metadata.name ?? '', RENDER_SCRIPT))) {
|
|
26
|
+
needsRootEjs = true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (needsRootEjs) {
|
|
30
|
+
addDependenciesToPackageJson(tree, {}, {
|
|
31
|
+
ejs: TS_VERSIONS.ejs
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
await formatFilesInSubtree(tree);
|
|
35
|
+
return {};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/terraform-gateway-cedar-render-root-ejs/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n getProjects,\n joinPathFragments,\n type MigrationReturnObject,\n type Tree,\n} from '@nx/devkit';\nimport { AGENTCORE_GATEWAY_GENERATOR_INFO } from '../../../agentcore-gateway/generator.js';\nimport { addDependenciesToPackageJson } from '../../../utils/dependencies.js';\nimport { formatFilesInSubtree } from '../../../utils/format.js';\nimport {\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n} from '../../../utils/shared-constructs-constants.js';\nimport { TS_VERSIONS } from '../../../utils/versions.js';\n\n/**\n * Declare `ejs` at the workspace root for Terraform gateways with Cedar\n * policies, which is where `render-cedar.cjs` resolves it from: the script runs\n * in the shared terraform project, which has no `package.json` of its own.\n */\n\nconst RENDER_SCRIPT = 'render-cedar.cjs';\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const gatewaysDir = joinPathFragments(\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n 'src',\n 'app',\n 'gateways',\n );\n let needsRootEjs = false;\n\n for (const project of getProjects(tree).values()) {\n const metadata = project.metadata as\n | { generator?: string; name?: string }\n | undefined;\n if (metadata?.generator !== AGENTCORE_GATEWAY_GENERATOR_INFO.id) {\n continue;\n }\n\n // Only a Terraform gateway with Cedar policies vends the render script; a\n // CDK one resolves ejs from the shared constructs project instead.\n if (\n tree.exists(\n joinPathFragments(gatewaysDir, metadata.name ?? '', RENDER_SCRIPT),\n )\n ) {\n needsRootEjs = true;\n }\n }\n\n if (needsRootEjs) {\n addDependenciesToPackageJson(tree, {}, { ejs: TS_VERSIONS.ejs });\n }\n\n await formatFilesInSubtree(tree);\n\n return {};\n}\n"],"names":["getProjects","joinPathFragments","AGENTCORE_GATEWAY_GENERATOR_INFO","addDependenciesToPackageJson","formatFilesInSubtree","PACKAGES_DIR","SHARED_TERRAFORM_DIR","TS_VERSIONS","RENDER_SCRIPT","migration","tree","gatewaysDir","needsRootEjs","project","values","metadata","generator","id","exists","name","ejs"],"mappings":"AAAA;;;CAGC,GACD,SACEA,WAAW,EACXC,iBAAiB,QAGZ,aAAa;AACpB,SAASC,gCAAgC,QAAQ,0CAA0C;AAC3F,SAASC,4BAA4B,QAAQ,iCAAiC;AAC9E,SAASC,oBAAoB,QAAQ,2BAA2B;AAChE,SACEC,YAAY,EACZC,oBAAoB,QACf,gDAAgD;AACvD,SAASC,WAAW,QAAQ,6BAA6B;AAEzD;;;;CAIC,GAED,MAAMC,gBAAgB;AAEtB,eAAe,eAAeC,UAC5BC,IAAU;IAEV,MAAMC,cAAcV,kBAClBI,cACAC,sBACA,OACA,OACA;IAEF,IAAIM,eAAe;IAEnB,KAAK,MAAMC,WAAWb,YAAYU,MAAMI,MAAM,GAAI;QAChD,MAAMC,WAAWF,QAAQE,QAAQ;QAGjC,IAAIA,UAAUC,cAAcd,iCAAiCe,EAAE,EAAE;YAC/D;QACF;QAEA,0EAA0E;QAC1E,mEAAmE;QACnE,IACEP,KAAKQ,MAAM,CACTjB,kBAAkBU,aAAaI,SAASI,IAAI,IAAI,IAAIX,iBAEtD;YACAI,eAAe;QACjB;IACF;IAEA,IAAIA,cAAc;QAChBT,6BAA6BO,MAAM,CAAC,GAAG;YAAEU,KAAKb,YAAYa,GAAG;QAAC;IAChE;IAEA,MAAMhB,qBAAqBM;IAE3B,OAAO,CAAC;AACV"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { type MigrationReturnObject, type Tree } from '@nx/devkit';
|
|
6
|
+
export default function migration(tree: Tree): Promise<MigrationReturnObject>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/ import { getProjects, updateProjectConfiguration } from "@nx/devkit";
|
|
5
|
+
import { formatFilesInSubtree } from "../../../utils/format.js";
|
|
6
|
+
import { TERRAFORM_WEBSITE_RUNTIME_CONFIG_FILE } from "../../../utils/shared-constructs-constants.js";
|
|
7
|
+
/**
|
|
8
|
+
* The Terraform `load-runtime-config` target copied
|
|
9
|
+
* `dist/packages/common/terraform/runtime-config.json`, which nothing writes:
|
|
10
|
+
* the vended runtime-config modules aggregate per namespace into the
|
|
11
|
+
* `runtime-config` *directory*, so the website's config lands at
|
|
12
|
+
* `runtime-config/connection.json`. Copying the directory path always failed
|
|
13
|
+
* with ENOENT, so point it at the file the aggregation actually writes.
|
|
14
|
+
*
|
|
15
|
+
* Both target names are rewritten — `load-runtime-config` and the
|
|
16
|
+
* `load:runtime-config` it was cloned from, which is left in place for
|
|
17
|
+
* workspaces that still reference it.
|
|
18
|
+
*
|
|
19
|
+
* How to write a migration:
|
|
20
|
+
* - https://nx.dev/docs/kb/migration-generators
|
|
21
|
+
* - What `nextSteps` means: https://nx.dev/docs/reference/devkit/MigrationReturnObject
|
|
22
|
+
*/ const TARGETS = [
|
|
23
|
+
'load-runtime-config',
|
|
24
|
+
'load:runtime-config'
|
|
25
|
+
];
|
|
26
|
+
/** The path the target used to name, which never existed on disk. */ const BROKEN_SRC_FILE = 'dist/packages/common/terraform/runtime-config.json';
|
|
27
|
+
export default async function migration(tree) {
|
|
28
|
+
for (const [projectName, project] of getProjects(tree)){
|
|
29
|
+
let updated = false;
|
|
30
|
+
for (const targetName of TARGETS){
|
|
31
|
+
const env = project.targets?.[targetName]?.options?.env;
|
|
32
|
+
// Only the broken path is rewritten, so a workspace that pointed the
|
|
33
|
+
// target somewhere of its own keeps it.
|
|
34
|
+
if (env?.SRC_FILE !== BROKEN_SRC_FILE) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
env.SRC_FILE = TERRAFORM_WEBSITE_RUNTIME_CONFIG_FILE;
|
|
38
|
+
updated = true;
|
|
39
|
+
}
|
|
40
|
+
if (updated) {
|
|
41
|
+
updateProjectConfiguration(tree, projectName, project);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
await formatFilesInSubtree(tree);
|
|
45
|
+
return {};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/terraform-load-runtime-config-src-path/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n getProjects,\n type MigrationReturnObject,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { formatFilesInSubtree } from '../../../utils/format.js';\nimport { TERRAFORM_WEBSITE_RUNTIME_CONFIG_FILE } from '../../../utils/shared-constructs-constants.js';\n\n/**\n * The Terraform `load-runtime-config` target copied\n * `dist/packages/common/terraform/runtime-config.json`, which nothing writes:\n * the vended runtime-config modules aggregate per namespace into the\n * `runtime-config` *directory*, so the website's config lands at\n * `runtime-config/connection.json`. Copying the directory path always failed\n * with ENOENT, so point it at the file the aggregation actually writes.\n *\n * Both target names are rewritten — `load-runtime-config` and the\n * `load:runtime-config` it was cloned from, which is left in place for\n * workspaces that still reference it.\n *\n * How to write a migration:\n * - https://nx.dev/docs/kb/migration-generators\n * - What `nextSteps` means: https://nx.dev/docs/reference/devkit/MigrationReturnObject\n */\n\nconst TARGETS = ['load-runtime-config', 'load:runtime-config'];\n\n/** The path the target used to name, which never existed on disk. */\nconst BROKEN_SRC_FILE = 'dist/packages/common/terraform/runtime-config.json';\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n for (const [projectName, project] of getProjects(tree)) {\n let updated = false;\n\n for (const targetName of TARGETS) {\n const env = project.targets?.[targetName]?.options?.env;\n // Only the broken path is rewritten, so a workspace that pointed the\n // target somewhere of its own keeps it.\n if (env?.SRC_FILE !== BROKEN_SRC_FILE) {\n continue;\n }\n env.SRC_FILE = TERRAFORM_WEBSITE_RUNTIME_CONFIG_FILE;\n updated = true;\n }\n\n if (updated) {\n updateProjectConfiguration(tree, projectName, project);\n }\n }\n\n await formatFilesInSubtree(tree);\n\n return {};\n}\n"],"names":["getProjects","updateProjectConfiguration","formatFilesInSubtree","TERRAFORM_WEBSITE_RUNTIME_CONFIG_FILE","TARGETS","BROKEN_SRC_FILE","migration","tree","projectName","project","updated","targetName","env","targets","options","SRC_FILE"],"mappings":"AAAA;;;CAGC,GACD,SACEA,WAAW,EAGXC,0BAA0B,QACrB,aAAa;AACpB,SAASC,oBAAoB,QAAQ,2BAA2B;AAChE,SAASC,qCAAqC,QAAQ,gDAAgD;AAEtG;;;;;;;;;;;;;;;CAeC,GAED,MAAMC,UAAU;IAAC;IAAuB;CAAsB;AAE9D,mEAAmE,GACnE,MAAMC,kBAAkB;AAExB,eAAe,eAAeC,UAC5BC,IAAU;IAEV,KAAK,MAAM,CAACC,aAAaC,QAAQ,IAAIT,YAAYO,MAAO;QACtD,IAAIG,UAAU;QAEd,KAAK,MAAMC,cAAcP,QAAS;YAChC,MAAMQ,MAAMH,QAAQI,OAAO,EAAE,CAACF,WAAW,EAAEG,SAASF;YACpD,qEAAqE;YACrE,wCAAwC;YACxC,IAAIA,KAAKG,aAAaV,iBAAiB;gBACrC;YACF;YACAO,IAAIG,QAAQ,GAAGZ;YACfO,UAAU;QACZ;QAEA,IAAIA,SAAS;YACXT,2BAA2BM,MAAMC,aAAaC;QAChD;IACF;IAEA,MAAMP,qBAAqBK;IAE3B,OAAO,CAAC;AACV"}
|
|
@@ -126,6 +126,8 @@ resource "aws_kms_key" "table" {
|
|
|
126
126
|
description = "KMS key for DynamoDB table \${var.name}"
|
|
127
127
|
enable_key_rotation = var.enable_key_rotation
|
|
128
128
|
|
|
129
|
+
deletion_window_in_days = 30
|
|
130
|
+
|
|
129
131
|
policy = jsonencode({
|
|
130
132
|
Version = "2012-10-17"
|
|
131
133
|
Statement = [
|
|
@@ -202,6 +204,10 @@ resource "aws_dynamodb_table" "table" {
|
|
|
202
204
|
enabled = var.encryption != "DEFAULT"
|
|
203
205
|
kms_key_arn = local.table_kms_key_arn
|
|
204
206
|
}
|
|
207
|
+
|
|
208
|
+
lifecycle {
|
|
209
|
+
prevent_destroy = true
|
|
210
|
+
}
|
|
205
211
|
}
|
|
206
212
|
|
|
207
213
|
output "table_name" {
|
|
@@ -320,6 +326,21 @@ module "add_to_runtime_config" {
|
|
|
320
326
|
tableName = module.dynamodb_table.table_name
|
|
321
327
|
}
|
|
322
328
|
}
|
|
329
|
+
|
|
330
|
+
output "table_name" {
|
|
331
|
+
description = "Name of the DynamoDB table"
|
|
332
|
+
value = module.dynamodb_table.table_name
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
output "table_arn" {
|
|
336
|
+
description = "ARN of the DynamoDB table, for use in IAM policies granting access to the table. Suffix with /index/* to cover its global secondary indexes."
|
|
337
|
+
value = module.dynamodb_table.table_arn
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
output "kms_key_arn" {
|
|
341
|
+
description = "ARN of the KMS key used to encrypt the DynamoDB table, for use in IAM policies granting access to the table. Null when using the AWS owned key (encryption = DEFAULT)."
|
|
342
|
+
value = module.dynamodb_table.kms_key_arn
|
|
343
|
+
}
|
|
323
344
|
"
|
|
324
345
|
`;
|
|
325
346
|
|
|
@@ -126,6 +126,8 @@ resource "aws_kms_key" "table" {
|
|
|
126
126
|
description = "KMS key for DynamoDB table \${var.name}"
|
|
127
127
|
enable_key_rotation = var.enable_key_rotation
|
|
128
128
|
|
|
129
|
+
deletion_window_in_days = 30
|
|
130
|
+
|
|
129
131
|
policy = jsonencode({
|
|
130
132
|
Version = "2012-10-17"
|
|
131
133
|
Statement = [
|
|
@@ -202,6 +204,10 @@ resource "aws_dynamodb_table" "table" {
|
|
|
202
204
|
enabled = var.encryption != "DEFAULT"
|
|
203
205
|
kms_key_arn = local.table_kms_key_arn
|
|
204
206
|
}
|
|
207
|
+
|
|
208
|
+
lifecycle {
|
|
209
|
+
prevent_destroy = true
|
|
210
|
+
}
|
|
205
211
|
}
|
|
206
212
|
|
|
207
213
|
output "table_name" {
|
|
@@ -320,6 +326,21 @@ module "add_to_runtime_config" {
|
|
|
320
326
|
tableName = module.dynamodb_table.table_name
|
|
321
327
|
}
|
|
322
328
|
}
|
|
329
|
+
|
|
330
|
+
output "table_name" {
|
|
331
|
+
description = "Name of the DynamoDB table"
|
|
332
|
+
value = module.dynamodb_table.table_name
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
output "table_arn" {
|
|
336
|
+
description = "ARN of the DynamoDB table, for use in IAM policies granting access to the table. Suffix with /index/* to cover its global secondary indexes."
|
|
337
|
+
value = module.dynamodb_table.table_arn
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
output "kms_key_arn" {
|
|
341
|
+
description = "ARN of the KMS key used to encrypt the DynamoDB table, for use in IAM policies granting access to the table. Null when using the AWS owned key (encryption = DEFAULT)."
|
|
342
|
+
value = module.dynamodb_table.kms_key_arn
|
|
343
|
+
}
|
|
323
344
|
"
|
|
324
345
|
`;
|
|
325
346
|
|
|
@@ -1008,6 +1008,8 @@ resource "aws_kms_key" "database" {
|
|
|
1008
1008
|
description = "KMS key for Aurora cluster \${var.name}"
|
|
1009
1009
|
enable_key_rotation = var.enable_key_rotation
|
|
1010
1010
|
|
|
1011
|
+
deletion_window_in_days = 30
|
|
1012
|
+
|
|
1011
1013
|
policy = jsonencode({
|
|
1012
1014
|
Version = "2012-10-17"
|
|
1013
1015
|
Statement = [
|
|
@@ -1150,6 +1152,10 @@ resource "aws_rds_cluster" "database" {
|
|
|
1150
1152
|
tags = merge(var.tags, {
|
|
1151
1153
|
Name = "\${var.name}-aurora"
|
|
1152
1154
|
})
|
|
1155
|
+
|
|
1156
|
+
lifecycle {
|
|
1157
|
+
prevent_destroy = true
|
|
1158
|
+
}
|
|
1153
1159
|
}
|
|
1154
1160
|
|
|
1155
1161
|
resource "aws_rds_cluster_instance" "database" {
|
|
@@ -2494,6 +2500,8 @@ resource "aws_kms_key" "database" {
|
|
|
2494
2500
|
description = "KMS key for Aurora cluster \${var.name}"
|
|
2495
2501
|
enable_key_rotation = var.enable_key_rotation
|
|
2496
2502
|
|
|
2503
|
+
deletion_window_in_days = 30
|
|
2504
|
+
|
|
2497
2505
|
policy = jsonencode({
|
|
2498
2506
|
Version = "2012-10-17"
|
|
2499
2507
|
Statement = [
|
|
@@ -2636,6 +2644,10 @@ resource "aws_rds_cluster" "database" {
|
|
|
2636
2644
|
tags = merge(var.tags, {
|
|
2637
2645
|
Name = "\${var.name}-aurora"
|
|
2638
2646
|
})
|
|
2647
|
+
|
|
2648
|
+
lifecycle {
|
|
2649
|
+
prevent_destroy = true
|
|
2650
|
+
}
|
|
2639
2651
|
}
|
|
2640
2652
|
|
|
2641
2653
|
resource "aws_rds_cluster_instance" "database" {
|
|
@@ -18,7 +18,7 @@ import { sortObjectKeys } from "../../../utils/object.js";
|
|
|
18
18
|
import { getRelativePathToRoot } from "../../../utils/paths.js";
|
|
19
19
|
import { getPackageManagerDisplayCommands } from "../../../utils/pkg-manager.js";
|
|
20
20
|
import { SHARED_CONSTRUCTS_DEPENDENCIES, sharedConstructsGenerator } from "../../../utils/shared-constructs.js";
|
|
21
|
-
import { PACKAGES_DIR, SHARED_SHADCN_DIR } from "../../../utils/shared-constructs-constants.js";
|
|
21
|
+
import { PACKAGES_DIR, SHARED_SHADCN_DIR, TERRAFORM_WEBSITE_RUNTIME_CONFIG_FILE } from "../../../utils/shared-constructs-constants.js";
|
|
22
22
|
import { SHADCN_DEPENDENCIES, sharedShadcnGenerator } from "../../../utils/shared-shadcn.js";
|
|
23
23
|
import { addWebsiteInfra, WEBSITE_CONSTRUCTS_PY_DEPENDENCIES } from "../../../utils/website-constructs/website-constructs.js";
|
|
24
24
|
import { configureTsProject } from "../../lib/ts-project-utils.js";
|
|
@@ -202,7 +202,7 @@ export async function tsReactWebsiteGenerator(tree, schema) {
|
|
|
202
202
|
options: {
|
|
203
203
|
command: 'node -e "const fs=require(\'fs\');fs.mkdirSync(process.env.DEST_DIR,{recursive:true});fs.copyFileSync(process.env.SRC_FILE,process.env.DEST_FILE);"',
|
|
204
204
|
env: {
|
|
205
|
-
SRC_FILE:
|
|
205
|
+
SRC_FILE: TERRAFORM_WEBSITE_RUNTIME_CONFIG_FILE,
|
|
206
206
|
DEST_DIR: `{projectRoot}/public`,
|
|
207
207
|
DEST_FILE: `{projectRoot}/public/runtime-config.json`
|
|
208
208
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/ts/react-website/app/generator.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 names,\n OverwriteStrategy,\n readProjectConfiguration,\n removeDependenciesFromPackageJson,\n type Tree,\n updateJson,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { applicationGenerator } from '@nx/react';\nimport { relative, sep } from 'path';\nimport { addTsDependencies } from '../../../utils/add-dependencies.js';\nimport {\n addDestructuredImport,\n addSingleImport,\n appendToArrayViaGritQL,\n applyGritQL,\n} from '../../../utils/ast.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../../utils/declared-dependencies.js';\nimport { formatFilesInSubtree } from '../../../utils/format.js';\nimport { resolveIac } from '../../../utils/iac.js';\nimport { installDependencies } from '../../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../../utils/metrics.js';\nimport { kebabCase, toClassName, toKebabCase } from '../../../utils/names.js';\nimport { getNpmScopePrefix } from '../../../utils/npm-scope.js';\nimport {\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n} from '../../../utils/nx.js';\nimport { sortObjectKeys } from '../../../utils/object.js';\nimport { getRelativePathToRoot } from '../../../utils/paths.js';\nimport { getPackageManagerDisplayCommands } from '../../../utils/pkg-manager.js';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n sharedConstructsGenerator,\n} from '../../../utils/shared-constructs.js';\nimport {\n type IacMetadata,\n PACKAGES_DIR,\n SHARED_SHADCN_DIR,\n} from '../../../utils/shared-constructs-constants.js';\nimport {\n SHADCN_DEPENDENCIES,\n sharedShadcnGenerator,\n} from '../../../utils/shared-shadcn.js';\nimport {\n addWebsiteInfra,\n WEBSITE_CONSTRUCTS_PY_DEPENDENCIES,\n} from '../../../utils/website-constructs/website-constructs.js';\nimport { configureTsProject } from '../../lib/ts-project-utils.js';\nimport { VITEST_DEPENDENCIES } from '../../lib/vitest.js';\n// typescript factory imports removed — now using GritQL for vite config transforms\nimport type {\n TsReactWebsiteGeneratorSchema,\n WebsiteInfraOption,\n} from './schema';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface TsReactWebsiteMetadata extends IacMetadata {\n readonly ux: UxOption;\n readonly framework: string;\n readonly infra: WebsiteInfraOption;\n readonly tailwind: boolean;\n readonly tanstackRouter: boolean;\n}\n\n// Each entry names the branch it belongs to, so the same declaration drives both\n// adding and the version sync.\nexport const DEPENDENCIES = declareDependencies<TsReactWebsiteMetadata>()({\n ts: [\n { name: 'react' },\n { name: 'react-dom' },\n // Build/test tooling imported only from vite.config.mts stays at the root.\n { name: '@nx/react', dev: true, root: true },\n { name: '@vitest/ui', dev: true, root: true },\n {\n name: '@cloudscape-design/components',\n when: (m) => m.ux === 'cloudscape',\n },\n {\n name: '@cloudscape-design/board-components',\n when: (m) => m.ux === 'cloudscape',\n },\n {\n name: '@cloudscape-design/global-styles',\n when: (m) => m.ux === 'cloudscape',\n },\n // Shared shadcn components live in the common/shadcn package, but the\n // website's own generated components (e.g. the tanstack-router sidebar)\n // import lucide-react directly, so the website must declare it.\n {\n name: 'lucide-react',\n when: (m) => m.ux === 'shadcn' && m.tanstackRouter,\n },\n { name: 'tailwindcss', when: (m) => m.tailwind },\n {\n name: '@tailwindcss/vite',\n when: (m) => m.tailwind,\n dev: true,\n root: true,\n },\n { name: '@tanstack/react-router', when: (m) => m.tanstackRouter },\n {\n name: '@tanstack/router-plugin',\n when: (m) => m.tanstackRouter,\n dev: true,\n root: true,\n },\n {\n name: '@tanstack/router-generator',\n when: (m) => m.tanstackRouter,\n dev: true,\n root: true,\n },\n {\n name: '@tanstack/virtual-file-routes',\n when: (m) => m.tanstackRouter,\n dev: true,\n root: true,\n },\n {\n name: '@tanstack/router-utils',\n when: (m) => m.tanstackRouter,\n dev: true,\n root: true,\n },\n ...ownedElsewhere(SHADCN_DEPENDENCIES),\n ...ownedElsewhere(VITEST_DEPENDENCIES),\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ],\n py: ownedElsewhere(WEBSITE_CONSTRUCTS_PY_DEPENDENCIES),\n});\n\nexport const SUPPORTED_UX_PROVIDERS = ['none', 'cloudscape', 'shadcn'] as const;\n\nexport type UxOption = (typeof SUPPORTED_UX_PROVIDERS)[number];\n\nexport type Ux = UxOption;\n\nexport const REACT_WEBSITE_APP_GENERATOR_INFO: NxGeneratorInfo =\n getGeneratorInfo(import.meta.filename);\n\nexport async function tsReactWebsiteGenerator(\n tree: Tree,\n schema: TsReactWebsiteGeneratorSchema,\n) {\n const tailwind = schema.tailwind ?? true;\n const tanstackRouter = schema.tanstackRouter ?? true;\n const ux: Ux = schema.ux ?? 'shadcn';\n if (ux === 'shadcn' && !tailwind) {\n throw new Error('Shadcn requires TailwindCSS to be enabled.');\n }\n const npmScopePrefix = getNpmScopePrefix(tree);\n const scopeAlias = npmScopePrefix;\n const websiteNameClassName = toClassName(schema.name);\n const websiteNameKebabCase = toKebabCase(schema.name);\n const fullyQualifiedName = `${npmScopePrefix}${websiteNameKebabCase}`;\n // NB: interactive nx generator cli can pass empty string\n const websiteContentPath = joinPathFragments(\n schema.directory || '.',\n schema.subDirectory || websiteNameKebabCase,\n );\n\n const projectAlreadyExists = tree.exists(\n joinPathFragments(websiteContentPath, 'project.json'),\n );\n\n // TODO: consider exposing and supporting e2e tests\n const e2eTestRunner = 'none';\n\n if (!projectAlreadyExists) {\n await applicationGenerator(tree, {\n ...schema,\n name: fullyQualifiedName,\n directory: websiteContentPath,\n routing: false,\n e2eTestRunner,\n linter: 'none',\n bundler: 'vite',\n unitTestRunner: 'vitest',\n useProjectJson: true,\n style: 'css',\n // Register the @nx/vite and @nx/vitest plugins so build/serve/test\n // targets are inferred rather than emitting deprecated executor targets.\n addPlugin: true,\n });\n\n // Pin the inferred target names. The vite production build is exposed as\n // `bundle` (which produces the deployable artifact), leaving `build` as an\n // aggregator over lint/compile/test/bundle. vite's own typecheck is dropped\n // in favour of the tsc `compile`.\n updateJson(tree, 'nx.json', (nxJson) => {\n for (const plugin of nxJson.plugins ?? []) {\n if (typeof plugin === 'string') continue;\n if (plugin.plugin === '@nx/vite/plugin') {\n plugin.options = {\n ...plugin.options,\n buildTargetName: 'bundle',\n // Map both of vite's inferred dev-server targets onto `serve` so the\n // plugin doesn't emit a separate `dev`; we author our own `dev`\n // below running the local-dev vite mode.\n serveTargetName: 'serve',\n devTargetName: 'serve',\n previewTargetName: 'preview',\n serveStaticTargetName: 'serve-static',\n typecheckTargetName: 'vite:typecheck',\n };\n } else if (plugin.plugin === '@nx/vitest') {\n plugin.options = {\n ...plugin.options,\n testTargetName: 'test',\n };\n }\n }\n return nxJson;\n });\n\n // Replace with simpler sample source code\n tree.delete(joinPathFragments(websiteContentPath, 'src'));\n }\n\n const projectConfiguration = readProjectConfiguration(\n tree,\n fullyQualifiedName,\n );\n\n const targets = projectConfiguration.targets;\n\n const infra = schema.infra ?? 'cloudfront-s3';\n\n // Configure load-runtime-config target based on IaC provider (only when infra is not none)\n const iac = infra !== 'none' ? await resolveIac(tree, schema.iac) : undefined;\n\n if (iac === 'cdk') {\n targets['load-runtime-config'] = {\n executor: 'nx:run-commands',\n metadata: {\n description: `Load runtime config from your deployed stack for dev purposes. You must set your AWS CLI credentials whilst calling '${getPackageManagerDisplayCommands().exec} nx load-runtime-config ${fullyQualifiedName}'`,\n },\n options: {\n command: `aws s3 cp s3://\\`aws cloudformation describe-stacks --query \"Stacks[?starts_with(StackName, '${kebabCase(npmScopePrefix)}-')][].Outputs[] | [?contains(OutputKey, '${websiteNameClassName}WebsiteBucketName')].OutputValue\" --output text\\`/runtime-config.json \"{projectRoot}/public/runtime-config.json\"`,\n },\n };\n } else if (iac === 'terraform') {\n targets['load-runtime-config'] = {\n executor: 'nx:run-commands',\n metadata: {\n description:\n \"Load runtime config from most recently applied terraform env for dev purposes. Copies the runtime config from the Terraform dist directory to the website's public directory.\",\n },\n options: {\n command:\n 'node -e \"const fs=require(\\'fs\\');fs.mkdirSync(process.env.DEST_DIR,{recursive:true});fs.copyFileSync(process.env.SRC_FILE,process.env.DEST_FILE);\"',\n env: {\n SRC_FILE: 'dist/packages/common/terraform/runtime-config.json',\n DEST_DIR: `{projectRoot}/public`,\n DEST_FILE: `{projectRoot}/public/runtime-config.json`,\n },\n },\n };\n }\n\n if (!projectAlreadyExists) {\n targets['compile'] = {\n dependsOn: ['^build'],\n executor: 'nx:run-commands',\n outputs: ['{workspaceRoot}/dist/{projectRoot}/tsc'],\n options: {\n command: 'tsc --build tsconfig.app.json',\n cwd: '{projectRoot}',\n },\n };\n // bundle is the @nx/vite/plugin inferred `vite build` (writing to the\n // bundle dir configured in vite.config) — it produces the deployable\n // artifact. build aggregates lint/compile/test/bundle.\n targets['build'] = {\n dependsOn: ['lint', 'compile', 'test', 'bundle'],\n };\n\n // Run the website and its connected dependencies locally. Mirrors the\n // inferred `serve` target but with the local-dev vite mode.\n targets['dev'] = {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n command: 'vite --mode local-dev',\n cwd: '{projectRoot}',\n },\n };\n }\n\n projectConfiguration.targets = sortObjectKeys(targets);\n\n updateProjectConfiguration(tree, fullyQualifiedName, projectConfiguration);\n\n // Recorded here and read by the declaration's predicates, so the packages\n // added below are exactly the ones the version sync will own.\n const metadata: TsReactWebsiteMetadata = {\n ux,\n framework: 'react',\n infra,\n tailwind,\n tanstackRouter,\n // Undefined when no infrastructure was generated, so neither provider's\n // packages were added.\n ...(iac ? { iac } : {}),\n };\n addGeneratorMetadata(\n tree,\n projectConfiguration.name,\n REACT_WEBSITE_APP_GENERATOR_INFO,\n metadata,\n );\n\n await configureTsProject(\n tree,\n {\n dir: websiteContentPath,\n fullyQualifiedName,\n },\n DEPENDENCIES,\n );\n\n if (ux === 'shadcn') {\n await sharedShadcnGenerator(tree, DEPENDENCIES);\n }\n\n if (iac) {\n await sharedConstructsGenerator(\n tree,\n {\n iac,\n },\n DEPENDENCIES,\n );\n\n await addWebsiteInfra(tree, {\n iac,\n websiteProjectName: fullyQualifiedName,\n scopeAlias,\n websiteContentPath: joinPathFragments('dist', websiteContentPath),\n websiteNameKebabCase,\n websiteNameClassName,\n });\n }\n\n const projectConfig = readProjectConfiguration(tree, fullyQualifiedName);\n const libraryRoot = projectConfig.root;\n const sharedShadcnStylesImport = relative(\n joinPathFragments(libraryRoot, 'src'),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_SHADCN_DIR,\n 'src',\n 'styles',\n 'globals.css',\n ),\n )\n .split(sep)\n .join('/');\n const sharedShadcnTsconfigRef = relative(\n joinPathFragments(tree.root, websiteContentPath),\n joinPathFragments(\n tree.root,\n PACKAGES_DIR,\n SHARED_SHADCN_DIR,\n 'tsconfig.json',\n ),\n )\n .split(sep)\n .join('/');\n const templateOptions = {\n ...schema,\n fullyQualifiedName,\n pkgMgrCmd: getPackageManagerDisplayCommands().exec,\n tailwind,\n tanstackRouter,\n scopeAlias,\n sharedShadcnStylesImport,\n };\n tree.delete(joinPathFragments(libraryRoot, 'src', 'app'));\n const appCommonTemplatePath = joinPathFragments(\n import.meta.dirname,\n './files/app/common',\n );\n const appTemplatePath = joinPathFragments(\n import.meta.dirname,\n `./files/app/${ux.toLowerCase()}`,\n );\n\n generateFiles(\n tree, // the virtual file system\n appCommonTemplatePath, // path to the file templates\n libraryRoot, // destination path of the files\n templateOptions, // config object to replace variable in file templates\n {\n // User-editable source - preserve any edits on re-run\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n generateFiles(\n tree, // the virtual file system\n appTemplatePath, // path to the file templates\n libraryRoot, // destination path of the files\n templateOptions, // config object to replace variable in file templates\n {\n // User-editable source - preserve any edits on re-run\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n if (tanstackRouter) {\n const routerCommonTemplatePath = joinPathFragments(\n import.meta.dirname,\n './files/tanstack-router/common',\n );\n const routerTemplatePath = joinPathFragments(\n import.meta.dirname,\n `./files/tanstack-router/${ux.toLowerCase()}`,\n );\n\n generateFiles(\n tree,\n routerCommonTemplatePath,\n libraryRoot,\n templateOptions,\n {\n // User-editable source (and the TanStack-managed route tree) - preserve on re-run\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n generateFiles(\n tree,\n routerTemplatePath,\n libraryRoot,\n templateOptions, // config object to replace variable in file templates\n {\n // User-editable source - preserve any edits on re-run\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n tree.delete(joinPathFragments(websiteContentPath, 'src', 'app.tsx'));\n }\n\n if (e2eTestRunner !== 'none') {\n const e2eFullyQualifiedName = `${fullyQualifiedName}-e2e`;\n const e2eRoot = readProjectConfiguration(tree, e2eFullyQualifiedName).root;\n generateFiles(\n tree, // the virtual file system\n joinPathFragments(import.meta.dirname, `./files/e2e/${e2eTestRunner}`), // path to the file templates\n e2eRoot, // destination path of the files\n { ...schema, ...names(fullyQualifiedName) },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n await configureTsProject(\n tree,\n {\n fullyQualifiedName: e2eFullyQualifiedName,\n dir: e2eRoot,\n },\n DEPENDENCIES,\n );\n }\n const viteConfigPath = joinPathFragments(libraryRoot, 'vite.config.mts');\n\n if (tree.exists(viteConfigPath)) {\n // Add Tanstack Router import if enabled\n if (tanstackRouter) {\n await addDestructuredImport(\n tree,\n viteConfigPath,\n ['tanstackRouter'],\n '@tanstack/router-plugin/vite',\n );\n\n await addDestructuredImport(tree, viteConfigPath, ['resolve'], 'path');\n }\n\n // Add TailwindCSS import if enabled\n if (tailwind) {\n await addSingleImport(\n tree,\n viteConfigPath,\n 'tailwindcss',\n '@tailwindcss/vite',\n );\n }\n\n // Update build.outDir. The inferred `vite build` target writes here, so\n // point it at the bundle dir the website infrastructure consumes.\n const outDir = joinPathFragments(\n getRelativePathToRoot(tree, fullyQualifiedName),\n 'dist',\n websiteContentPath,\n 'bundle',\n );\n await applyGritQL(\n tree,\n viteConfigPath,\n `\\`build: { $bprops }\\` where { $bprops <: contains \\`outDir: $_\\` => \\`outDir: '${outDir}'\\` }`,\n );\n\n // Add plugins to the plugins array\n if (tanstackRouter) {\n // Prepend tanstackRouter (must be first plugin) — rewrite works for both single/multi-element\n await applyGritQL(\n tree,\n viteConfigPath,\n \"`plugins: [$items]` => `plugins: [tanstackRouter({ routesDirectory: resolve(import.meta.dirname, 'src/routes'), generatedRouteTree: resolve(import.meta.dirname, 'src/routeTree.gen.ts') }), $items]` where { $items <: within `defineConfig($_)`, $items <: not contains `tanstackRouter` }\",\n );\n }\n\n if (tailwind) {\n await appendToArrayViaGritQL(\n tree,\n viteConfigPath,\n 'plugins:',\n 'tailwindcss()',\n { scope: 'defineConfig($_)' },\n );\n }\n\n // Use Vite's native tsconfig paths resolution (replaces vite-tsconfig-paths).\n // `dedupe` forces a single copy of react/react-dom into the bundle: each\n // project declares its own react dependency, so without this a workspace\n // library's hoisted copy can produce a second React instance and the\n // \"Invalid hook call\" runtime crash.\n await applyGritQL(\n tree,\n viteConfigPath,\n \"or { `defineConfig(() => ({ $props }))` where { $props <: not some `resolve: $_`, $props += `resolve: { tsconfigPaths: true, dedupe: ['react', 'react-dom'] }` }, `defineConfig({ $props })` where { $props <: not some `resolve: $_`, $props += `resolve: { tsconfigPaths: true, dedupe: ['react', 'react-dom'] }` } }\",\n );\n\n // Add define: { global: {} } to the config (handles both callback and direct forms)\n await applyGritQL(\n tree,\n viteConfigPath,\n 'or { `defineConfig(() => ({ $props }))` where { $props <: not contains `define`, $props += `define: { global: {} }` }, `defineConfig({ $props })` where { $props <: not contains `define`, $props += `define: { global: {} }` } }',\n );\n }\n\n updateJson(\n tree,\n joinPathFragments(websiteContentPath, 'tsconfig.json'),\n (tsconfig) => ({\n ...tsconfig,\n compilerOptions: {\n ...tsconfig.compilerOptions,\n moduleResolution: 'Bundler',\n module: 'Preserve',\n },\n }),\n );\n const outDirToRootRelativePath = relative(\n joinPathFragments(tree.root, websiteContentPath),\n tree.root,\n );\n const distDir = joinPathFragments(\n outDirToRootRelativePath,\n 'dist',\n websiteContentPath,\n 'tsc',\n );\n updateJson(\n tree,\n joinPathFragments(websiteContentPath, 'tsconfig.app.json'),\n (tsconfig) => ({\n ...tsconfig,\n compilerOptions: {\n ...tsconfig.compilerOptions,\n outDir: distDir,\n tsBuildInfoFile: joinPathFragments(distDir, 'tsconfig.lib.tsbuildinfo'),\n lib: ['DOM'],\n },\n references:\n ux === 'shadcn'\n ? [\n ...(tsconfig.references ?? []).filter(\n (ref) => ref.path !== sharedShadcnTsconfigRef,\n ),\n {\n path: sharedShadcnTsconfigRef,\n },\n ]\n : tsconfig.references,\n }),\n );\n\n addTsDependencies(tree, DEPENDENCIES, { metadata, projectRoot: libraryRoot });\n\n // @nx/react's applicationGenerator seeds react/react-dom into the root\n // manifest. The website now declares its own pinned versions, so drop the\n // root copies: without catalogs (npm) the root's floating range resolves to\n // a different version than the website's pin, installing a second React and\n // producing the \"Invalid hook call\" runtime crash.\n removeDependenciesFromPackageJson(tree, ['react', 'react-dom'], []);\n\n await addGeneratorMetricsIfApplicable(tree, [\n REACT_WEBSITE_APP_GENERATOR_INFO,\n ]);\n\n // TanStack Router's vite plugin owns this website's route tree and rewrites it\n // in its own (unformatted) shape whenever the config is loaded — including when\n // Nx computes the project graph — so formatting it here would only make\n // generation non-idempotent. The vended biome config excludes `**/*.gen.*`, so\n // the workspace's own `format` target leaves it alone too.\n await formatFilesInSubtree(tree, undefined, {\n ignore: tanstackRouter\n ? [joinPathFragments(libraryRoot, 'src', 'routeTree.gen.ts')]\n : [],\n });\n // The generated vite.config.mts imports these, and Nx's inferred `@nx/vite`\n // plugin loads that config when computing the project graph — so they must be\n // installed even if the caller would otherwise prefer to defer.\n return () =>\n installDependencies(tree, schema.preferInstallDependencies, {\n languages: ['typescript'],\n ensureResolvable: [\n ...(tailwind ? (['@tailwindcss/vite'] as const) : []),\n ...(tanstackRouter ? (['@tanstack/router-plugin'] as const) : []),\n ],\n });\n}\nexport default tsReactWebsiteGenerator;\n"],"names":["generateFiles","joinPathFragments","names","OverwriteStrategy","readProjectConfiguration","removeDependenciesFromPackageJson","updateJson","updateProjectConfiguration","applicationGenerator","relative","sep","addTsDependencies","addDestructuredImport","addSingleImport","appendToArrayViaGritQL","applyGritQL","declareDependencies","ownedElsewhere","formatFilesInSubtree","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","toKebabCase","getNpmScopePrefix","addGeneratorMetadata","getGeneratorInfo","sortObjectKeys","getRelativePathToRoot","getPackageManagerDisplayCommands","SHARED_CONSTRUCTS_DEPENDENCIES","sharedConstructsGenerator","PACKAGES_DIR","SHARED_SHADCN_DIR","SHADCN_DEPENDENCIES","sharedShadcnGenerator","addWebsiteInfra","WEBSITE_CONSTRUCTS_PY_DEPENDENCIES","configureTsProject","VITEST_DEPENDENCIES","DEPENDENCIES","ts","name","dev","root","when","m","ux","tanstackRouter","tailwind","py","SUPPORTED_UX_PROVIDERS","REACT_WEBSITE_APP_GENERATOR_INFO","filename","tsReactWebsiteGenerator","tree","schema","Error","npmScopePrefix","scopeAlias","websiteNameClassName","websiteNameKebabCase","fullyQualifiedName","websiteContentPath","directory","subDirectory","projectAlreadyExists","exists","e2eTestRunner","routing","linter","bundler","unitTestRunner","useProjectJson","style","addPlugin","nxJson","plugin","plugins","options","buildTargetName","serveTargetName","devTargetName","previewTargetName","serveStaticTargetName","typecheckTargetName","testTargetName","delete","projectConfiguration","targets","infra","iac","undefined","executor","metadata","description","exec","command","env","SRC_FILE","DEST_DIR","DEST_FILE","dependsOn","outputs","cwd","continuous","framework","dir","websiteProjectName","projectConfig","libraryRoot","sharedShadcnStylesImport","split","join","sharedShadcnTsconfigRef","templateOptions","pkgMgrCmd","appCommonTemplatePath","dirname","appTemplatePath","toLowerCase","overwriteStrategy","KeepExisting","routerCommonTemplatePath","routerTemplatePath","e2eFullyQualifiedName","e2eRoot","viteConfigPath","outDir","scope","tsconfig","compilerOptions","moduleResolution","module","outDirToRootRelativePath","distDir","tsBuildInfoFile","lib","references","filter","ref","path","projectRoot","ignore","preferInstallDependencies","languages","ensureResolvable"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/ts/react-website/app/generator.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 names,\n OverwriteStrategy,\n readProjectConfiguration,\n removeDependenciesFromPackageJson,\n type Tree,\n updateJson,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { applicationGenerator } from '@nx/react';\nimport { relative, sep } from 'path';\nimport { addTsDependencies } from '../../../utils/add-dependencies.js';\nimport {\n addDestructuredImport,\n addSingleImport,\n appendToArrayViaGritQL,\n applyGritQL,\n} from '../../../utils/ast.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../../utils/declared-dependencies.js';\nimport { formatFilesInSubtree } from '../../../utils/format.js';\nimport { resolveIac } from '../../../utils/iac.js';\nimport { installDependencies } from '../../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../../utils/metrics.js';\nimport { kebabCase, toClassName, toKebabCase } from '../../../utils/names.js';\nimport { getNpmScopePrefix } from '../../../utils/npm-scope.js';\nimport {\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n} from '../../../utils/nx.js';\nimport { sortObjectKeys } from '../../../utils/object.js';\nimport { getRelativePathToRoot } from '../../../utils/paths.js';\nimport { getPackageManagerDisplayCommands } from '../../../utils/pkg-manager.js';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n sharedConstructsGenerator,\n} from '../../../utils/shared-constructs.js';\nimport {\n type IacMetadata,\n PACKAGES_DIR,\n SHARED_SHADCN_DIR,\n TERRAFORM_WEBSITE_RUNTIME_CONFIG_FILE,\n} from '../../../utils/shared-constructs-constants.js';\nimport {\n SHADCN_DEPENDENCIES,\n sharedShadcnGenerator,\n} from '../../../utils/shared-shadcn.js';\nimport {\n addWebsiteInfra,\n WEBSITE_CONSTRUCTS_PY_DEPENDENCIES,\n} from '../../../utils/website-constructs/website-constructs.js';\nimport { configureTsProject } from '../../lib/ts-project-utils.js';\nimport { VITEST_DEPENDENCIES } from '../../lib/vitest.js';\n// typescript factory imports removed — now using GritQL for vite config transforms\nimport type {\n TsReactWebsiteGeneratorSchema,\n WebsiteInfraOption,\n} from './schema';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface TsReactWebsiteMetadata extends IacMetadata {\n readonly ux: UxOption;\n readonly framework: string;\n readonly infra: WebsiteInfraOption;\n readonly tailwind: boolean;\n readonly tanstackRouter: boolean;\n}\n\n// Each entry names the branch it belongs to, so the same declaration drives both\n// adding and the version sync.\nexport const DEPENDENCIES = declareDependencies<TsReactWebsiteMetadata>()({\n ts: [\n { name: 'react' },\n { name: 'react-dom' },\n // Build/test tooling imported only from vite.config.mts stays at the root.\n { name: '@nx/react', dev: true, root: true },\n { name: '@vitest/ui', dev: true, root: true },\n {\n name: '@cloudscape-design/components',\n when: (m) => m.ux === 'cloudscape',\n },\n {\n name: '@cloudscape-design/board-components',\n when: (m) => m.ux === 'cloudscape',\n },\n {\n name: '@cloudscape-design/global-styles',\n when: (m) => m.ux === 'cloudscape',\n },\n // Shared shadcn components live in the common/shadcn package, but the\n // website's own generated components (e.g. the tanstack-router sidebar)\n // import lucide-react directly, so the website must declare it.\n {\n name: 'lucide-react',\n when: (m) => m.ux === 'shadcn' && m.tanstackRouter,\n },\n { name: 'tailwindcss', when: (m) => m.tailwind },\n {\n name: '@tailwindcss/vite',\n when: (m) => m.tailwind,\n dev: true,\n root: true,\n },\n { name: '@tanstack/react-router', when: (m) => m.tanstackRouter },\n {\n name: '@tanstack/router-plugin',\n when: (m) => m.tanstackRouter,\n dev: true,\n root: true,\n },\n {\n name: '@tanstack/router-generator',\n when: (m) => m.tanstackRouter,\n dev: true,\n root: true,\n },\n {\n name: '@tanstack/virtual-file-routes',\n when: (m) => m.tanstackRouter,\n dev: true,\n root: true,\n },\n {\n name: '@tanstack/router-utils',\n when: (m) => m.tanstackRouter,\n dev: true,\n root: true,\n },\n ...ownedElsewhere(SHADCN_DEPENDENCIES),\n ...ownedElsewhere(VITEST_DEPENDENCIES),\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ],\n py: ownedElsewhere(WEBSITE_CONSTRUCTS_PY_DEPENDENCIES),\n});\n\nexport const SUPPORTED_UX_PROVIDERS = ['none', 'cloudscape', 'shadcn'] as const;\n\nexport type UxOption = (typeof SUPPORTED_UX_PROVIDERS)[number];\n\nexport type Ux = UxOption;\n\nexport const REACT_WEBSITE_APP_GENERATOR_INFO: NxGeneratorInfo =\n getGeneratorInfo(import.meta.filename);\n\nexport async function tsReactWebsiteGenerator(\n tree: Tree,\n schema: TsReactWebsiteGeneratorSchema,\n) {\n const tailwind = schema.tailwind ?? true;\n const tanstackRouter = schema.tanstackRouter ?? true;\n const ux: Ux = schema.ux ?? 'shadcn';\n if (ux === 'shadcn' && !tailwind) {\n throw new Error('Shadcn requires TailwindCSS to be enabled.');\n }\n const npmScopePrefix = getNpmScopePrefix(tree);\n const scopeAlias = npmScopePrefix;\n const websiteNameClassName = toClassName(schema.name);\n const websiteNameKebabCase = toKebabCase(schema.name);\n const fullyQualifiedName = `${npmScopePrefix}${websiteNameKebabCase}`;\n // NB: interactive nx generator cli can pass empty string\n const websiteContentPath = joinPathFragments(\n schema.directory || '.',\n schema.subDirectory || websiteNameKebabCase,\n );\n\n const projectAlreadyExists = tree.exists(\n joinPathFragments(websiteContentPath, 'project.json'),\n );\n\n // TODO: consider exposing and supporting e2e tests\n const e2eTestRunner = 'none';\n\n if (!projectAlreadyExists) {\n await applicationGenerator(tree, {\n ...schema,\n name: fullyQualifiedName,\n directory: websiteContentPath,\n routing: false,\n e2eTestRunner,\n linter: 'none',\n bundler: 'vite',\n unitTestRunner: 'vitest',\n useProjectJson: true,\n style: 'css',\n // Register the @nx/vite and @nx/vitest plugins so build/serve/test\n // targets are inferred rather than emitting deprecated executor targets.\n addPlugin: true,\n });\n\n // Pin the inferred target names. The vite production build is exposed as\n // `bundle` (which produces the deployable artifact), leaving `build` as an\n // aggregator over lint/compile/test/bundle. vite's own typecheck is dropped\n // in favour of the tsc `compile`.\n updateJson(tree, 'nx.json', (nxJson) => {\n for (const plugin of nxJson.plugins ?? []) {\n if (typeof plugin === 'string') continue;\n if (plugin.plugin === '@nx/vite/plugin') {\n plugin.options = {\n ...plugin.options,\n buildTargetName: 'bundle',\n // Map both of vite's inferred dev-server targets onto `serve` so the\n // plugin doesn't emit a separate `dev`; we author our own `dev`\n // below running the local-dev vite mode.\n serveTargetName: 'serve',\n devTargetName: 'serve',\n previewTargetName: 'preview',\n serveStaticTargetName: 'serve-static',\n typecheckTargetName: 'vite:typecheck',\n };\n } else if (plugin.plugin === '@nx/vitest') {\n plugin.options = {\n ...plugin.options,\n testTargetName: 'test',\n };\n }\n }\n return nxJson;\n });\n\n // Replace with simpler sample source code\n tree.delete(joinPathFragments(websiteContentPath, 'src'));\n }\n\n const projectConfiguration = readProjectConfiguration(\n tree,\n fullyQualifiedName,\n );\n\n const targets = projectConfiguration.targets;\n\n const infra = schema.infra ?? 'cloudfront-s3';\n\n // Configure load-runtime-config target based on IaC provider (only when infra is not none)\n const iac = infra !== 'none' ? await resolveIac(tree, schema.iac) : undefined;\n\n if (iac === 'cdk') {\n targets['load-runtime-config'] = {\n executor: 'nx:run-commands',\n metadata: {\n description: `Load runtime config from your deployed stack for dev purposes. You must set your AWS CLI credentials whilst calling '${getPackageManagerDisplayCommands().exec} nx load-runtime-config ${fullyQualifiedName}'`,\n },\n options: {\n command: `aws s3 cp s3://\\`aws cloudformation describe-stacks --query \"Stacks[?starts_with(StackName, '${kebabCase(npmScopePrefix)}-')][].Outputs[] | [?contains(OutputKey, '${websiteNameClassName}WebsiteBucketName')].OutputValue\" --output text\\`/runtime-config.json \"{projectRoot}/public/runtime-config.json\"`,\n },\n };\n } else if (iac === 'terraform') {\n targets['load-runtime-config'] = {\n executor: 'nx:run-commands',\n metadata: {\n description:\n \"Load runtime config from most recently applied terraform env for dev purposes. Copies the runtime config from the Terraform dist directory to the website's public directory.\",\n },\n options: {\n command:\n 'node -e \"const fs=require(\\'fs\\');fs.mkdirSync(process.env.DEST_DIR,{recursive:true});fs.copyFileSync(process.env.SRC_FILE,process.env.DEST_FILE);\"',\n env: {\n SRC_FILE: TERRAFORM_WEBSITE_RUNTIME_CONFIG_FILE,\n DEST_DIR: `{projectRoot}/public`,\n DEST_FILE: `{projectRoot}/public/runtime-config.json`,\n },\n },\n };\n }\n\n if (!projectAlreadyExists) {\n targets['compile'] = {\n dependsOn: ['^build'],\n executor: 'nx:run-commands',\n outputs: ['{workspaceRoot}/dist/{projectRoot}/tsc'],\n options: {\n command: 'tsc --build tsconfig.app.json',\n cwd: '{projectRoot}',\n },\n };\n // bundle is the @nx/vite/plugin inferred `vite build` (writing to the\n // bundle dir configured in vite.config) — it produces the deployable\n // artifact. build aggregates lint/compile/test/bundle.\n targets['build'] = {\n dependsOn: ['lint', 'compile', 'test', 'bundle'],\n };\n\n // Run the website and its connected dependencies locally. Mirrors the\n // inferred `serve` target but with the local-dev vite mode.\n targets['dev'] = {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n command: 'vite --mode local-dev',\n cwd: '{projectRoot}',\n },\n };\n }\n\n projectConfiguration.targets = sortObjectKeys(targets);\n\n updateProjectConfiguration(tree, fullyQualifiedName, projectConfiguration);\n\n // Recorded here and read by the declaration's predicates, so the packages\n // added below are exactly the ones the version sync will own.\n const metadata: TsReactWebsiteMetadata = {\n ux,\n framework: 'react',\n infra,\n tailwind,\n tanstackRouter,\n // Undefined when no infrastructure was generated, so neither provider's\n // packages were added.\n ...(iac ? { iac } : {}),\n };\n addGeneratorMetadata(\n tree,\n projectConfiguration.name,\n REACT_WEBSITE_APP_GENERATOR_INFO,\n metadata,\n );\n\n await configureTsProject(\n tree,\n {\n dir: websiteContentPath,\n fullyQualifiedName,\n },\n DEPENDENCIES,\n );\n\n if (ux === 'shadcn') {\n await sharedShadcnGenerator(tree, DEPENDENCIES);\n }\n\n if (iac) {\n await sharedConstructsGenerator(\n tree,\n {\n iac,\n },\n DEPENDENCIES,\n );\n\n await addWebsiteInfra(tree, {\n iac,\n websiteProjectName: fullyQualifiedName,\n scopeAlias,\n websiteContentPath: joinPathFragments('dist', websiteContentPath),\n websiteNameKebabCase,\n websiteNameClassName,\n });\n }\n\n const projectConfig = readProjectConfiguration(tree, fullyQualifiedName);\n const libraryRoot = projectConfig.root;\n const sharedShadcnStylesImport = relative(\n joinPathFragments(libraryRoot, 'src'),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_SHADCN_DIR,\n 'src',\n 'styles',\n 'globals.css',\n ),\n )\n .split(sep)\n .join('/');\n const sharedShadcnTsconfigRef = relative(\n joinPathFragments(tree.root, websiteContentPath),\n joinPathFragments(\n tree.root,\n PACKAGES_DIR,\n SHARED_SHADCN_DIR,\n 'tsconfig.json',\n ),\n )\n .split(sep)\n .join('/');\n const templateOptions = {\n ...schema,\n fullyQualifiedName,\n pkgMgrCmd: getPackageManagerDisplayCommands().exec,\n tailwind,\n tanstackRouter,\n scopeAlias,\n sharedShadcnStylesImport,\n };\n tree.delete(joinPathFragments(libraryRoot, 'src', 'app'));\n const appCommonTemplatePath = joinPathFragments(\n import.meta.dirname,\n './files/app/common',\n );\n const appTemplatePath = joinPathFragments(\n import.meta.dirname,\n `./files/app/${ux.toLowerCase()}`,\n );\n\n generateFiles(\n tree, // the virtual file system\n appCommonTemplatePath, // path to the file templates\n libraryRoot, // destination path of the files\n templateOptions, // config object to replace variable in file templates\n {\n // User-editable source - preserve any edits on re-run\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n generateFiles(\n tree, // the virtual file system\n appTemplatePath, // path to the file templates\n libraryRoot, // destination path of the files\n templateOptions, // config object to replace variable in file templates\n {\n // User-editable source - preserve any edits on re-run\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n if (tanstackRouter) {\n const routerCommonTemplatePath = joinPathFragments(\n import.meta.dirname,\n './files/tanstack-router/common',\n );\n const routerTemplatePath = joinPathFragments(\n import.meta.dirname,\n `./files/tanstack-router/${ux.toLowerCase()}`,\n );\n\n generateFiles(\n tree,\n routerCommonTemplatePath,\n libraryRoot,\n templateOptions,\n {\n // User-editable source (and the TanStack-managed route tree) - preserve on re-run\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n generateFiles(\n tree,\n routerTemplatePath,\n libraryRoot,\n templateOptions, // config object to replace variable in file templates\n {\n // User-editable source - preserve any edits on re-run\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n tree.delete(joinPathFragments(websiteContentPath, 'src', 'app.tsx'));\n }\n\n if (e2eTestRunner !== 'none') {\n const e2eFullyQualifiedName = `${fullyQualifiedName}-e2e`;\n const e2eRoot = readProjectConfiguration(tree, e2eFullyQualifiedName).root;\n generateFiles(\n tree, // the virtual file system\n joinPathFragments(import.meta.dirname, `./files/e2e/${e2eTestRunner}`), // path to the file templates\n e2eRoot, // destination path of the files\n { ...schema, ...names(fullyQualifiedName) },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n await configureTsProject(\n tree,\n {\n fullyQualifiedName: e2eFullyQualifiedName,\n dir: e2eRoot,\n },\n DEPENDENCIES,\n );\n }\n const viteConfigPath = joinPathFragments(libraryRoot, 'vite.config.mts');\n\n if (tree.exists(viteConfigPath)) {\n // Add Tanstack Router import if enabled\n if (tanstackRouter) {\n await addDestructuredImport(\n tree,\n viteConfigPath,\n ['tanstackRouter'],\n '@tanstack/router-plugin/vite',\n );\n\n await addDestructuredImport(tree, viteConfigPath, ['resolve'], 'path');\n }\n\n // Add TailwindCSS import if enabled\n if (tailwind) {\n await addSingleImport(\n tree,\n viteConfigPath,\n 'tailwindcss',\n '@tailwindcss/vite',\n );\n }\n\n // Update build.outDir. The inferred `vite build` target writes here, so\n // point it at the bundle dir the website infrastructure consumes.\n const outDir = joinPathFragments(\n getRelativePathToRoot(tree, fullyQualifiedName),\n 'dist',\n websiteContentPath,\n 'bundle',\n );\n await applyGritQL(\n tree,\n viteConfigPath,\n `\\`build: { $bprops }\\` where { $bprops <: contains \\`outDir: $_\\` => \\`outDir: '${outDir}'\\` }`,\n );\n\n // Add plugins to the plugins array\n if (tanstackRouter) {\n // Prepend tanstackRouter (must be first plugin) — rewrite works for both single/multi-element\n await applyGritQL(\n tree,\n viteConfigPath,\n \"`plugins: [$items]` => `plugins: [tanstackRouter({ routesDirectory: resolve(import.meta.dirname, 'src/routes'), generatedRouteTree: resolve(import.meta.dirname, 'src/routeTree.gen.ts') }), $items]` where { $items <: within `defineConfig($_)`, $items <: not contains `tanstackRouter` }\",\n );\n }\n\n if (tailwind) {\n await appendToArrayViaGritQL(\n tree,\n viteConfigPath,\n 'plugins:',\n 'tailwindcss()',\n { scope: 'defineConfig($_)' },\n );\n }\n\n // Use Vite's native tsconfig paths resolution (replaces vite-tsconfig-paths).\n // `dedupe` forces a single copy of react/react-dom into the bundle: each\n // project declares its own react dependency, so without this a workspace\n // library's hoisted copy can produce a second React instance and the\n // \"Invalid hook call\" runtime crash.\n await applyGritQL(\n tree,\n viteConfigPath,\n \"or { `defineConfig(() => ({ $props }))` where { $props <: not some `resolve: $_`, $props += `resolve: { tsconfigPaths: true, dedupe: ['react', 'react-dom'] }` }, `defineConfig({ $props })` where { $props <: not some `resolve: $_`, $props += `resolve: { tsconfigPaths: true, dedupe: ['react', 'react-dom'] }` } }\",\n );\n\n // Add define: { global: {} } to the config (handles both callback and direct forms)\n await applyGritQL(\n tree,\n viteConfigPath,\n 'or { `defineConfig(() => ({ $props }))` where { $props <: not contains `define`, $props += `define: { global: {} }` }, `defineConfig({ $props })` where { $props <: not contains `define`, $props += `define: { global: {} }` } }',\n );\n }\n\n updateJson(\n tree,\n joinPathFragments(websiteContentPath, 'tsconfig.json'),\n (tsconfig) => ({\n ...tsconfig,\n compilerOptions: {\n ...tsconfig.compilerOptions,\n moduleResolution: 'Bundler',\n module: 'Preserve',\n },\n }),\n );\n const outDirToRootRelativePath = relative(\n joinPathFragments(tree.root, websiteContentPath),\n tree.root,\n );\n const distDir = joinPathFragments(\n outDirToRootRelativePath,\n 'dist',\n websiteContentPath,\n 'tsc',\n );\n updateJson(\n tree,\n joinPathFragments(websiteContentPath, 'tsconfig.app.json'),\n (tsconfig) => ({\n ...tsconfig,\n compilerOptions: {\n ...tsconfig.compilerOptions,\n outDir: distDir,\n tsBuildInfoFile: joinPathFragments(distDir, 'tsconfig.lib.tsbuildinfo'),\n lib: ['DOM'],\n },\n references:\n ux === 'shadcn'\n ? [\n ...(tsconfig.references ?? []).filter(\n (ref) => ref.path !== sharedShadcnTsconfigRef,\n ),\n {\n path: sharedShadcnTsconfigRef,\n },\n ]\n : tsconfig.references,\n }),\n );\n\n addTsDependencies(tree, DEPENDENCIES, { metadata, projectRoot: libraryRoot });\n\n // @nx/react's applicationGenerator seeds react/react-dom into the root\n // manifest. The website now declares its own pinned versions, so drop the\n // root copies: without catalogs (npm) the root's floating range resolves to\n // a different version than the website's pin, installing a second React and\n // producing the \"Invalid hook call\" runtime crash.\n removeDependenciesFromPackageJson(tree, ['react', 'react-dom'], []);\n\n await addGeneratorMetricsIfApplicable(tree, [\n REACT_WEBSITE_APP_GENERATOR_INFO,\n ]);\n\n // TanStack Router's vite plugin owns this website's route tree and rewrites it\n // in its own (unformatted) shape whenever the config is loaded — including when\n // Nx computes the project graph — so formatting it here would only make\n // generation non-idempotent. The vended biome config excludes `**/*.gen.*`, so\n // the workspace's own `format` target leaves it alone too.\n await formatFilesInSubtree(tree, undefined, {\n ignore: tanstackRouter\n ? [joinPathFragments(libraryRoot, 'src', 'routeTree.gen.ts')]\n : [],\n });\n // The generated vite.config.mts imports these, and Nx's inferred `@nx/vite`\n // plugin loads that config when computing the project graph — so they must be\n // installed even if the caller would otherwise prefer to defer.\n return () =>\n installDependencies(tree, schema.preferInstallDependencies, {\n languages: ['typescript'],\n ensureResolvable: [\n ...(tailwind ? (['@tailwindcss/vite'] as const) : []),\n ...(tanstackRouter ? (['@tanstack/router-plugin'] as const) : []),\n ],\n });\n}\nexport default tsReactWebsiteGenerator;\n"],"names":["generateFiles","joinPathFragments","names","OverwriteStrategy","readProjectConfiguration","removeDependenciesFromPackageJson","updateJson","updateProjectConfiguration","applicationGenerator","relative","sep","addTsDependencies","addDestructuredImport","addSingleImport","appendToArrayViaGritQL","applyGritQL","declareDependencies","ownedElsewhere","formatFilesInSubtree","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","toKebabCase","getNpmScopePrefix","addGeneratorMetadata","getGeneratorInfo","sortObjectKeys","getRelativePathToRoot","getPackageManagerDisplayCommands","SHARED_CONSTRUCTS_DEPENDENCIES","sharedConstructsGenerator","PACKAGES_DIR","SHARED_SHADCN_DIR","TERRAFORM_WEBSITE_RUNTIME_CONFIG_FILE","SHADCN_DEPENDENCIES","sharedShadcnGenerator","addWebsiteInfra","WEBSITE_CONSTRUCTS_PY_DEPENDENCIES","configureTsProject","VITEST_DEPENDENCIES","DEPENDENCIES","ts","name","dev","root","when","m","ux","tanstackRouter","tailwind","py","SUPPORTED_UX_PROVIDERS","REACT_WEBSITE_APP_GENERATOR_INFO","filename","tsReactWebsiteGenerator","tree","schema","Error","npmScopePrefix","scopeAlias","websiteNameClassName","websiteNameKebabCase","fullyQualifiedName","websiteContentPath","directory","subDirectory","projectAlreadyExists","exists","e2eTestRunner","routing","linter","bundler","unitTestRunner","useProjectJson","style","addPlugin","nxJson","plugin","plugins","options","buildTargetName","serveTargetName","devTargetName","previewTargetName","serveStaticTargetName","typecheckTargetName","testTargetName","delete","projectConfiguration","targets","infra","iac","undefined","executor","metadata","description","exec","command","env","SRC_FILE","DEST_DIR","DEST_FILE","dependsOn","outputs","cwd","continuous","framework","dir","websiteProjectName","projectConfig","libraryRoot","sharedShadcnStylesImport","split","join","sharedShadcnTsconfigRef","templateOptions","pkgMgrCmd","appCommonTemplatePath","dirname","appTemplatePath","toLowerCase","overwriteStrategy","KeepExisting","routerCommonTemplatePath","routerTemplatePath","e2eFullyQualifiedName","e2eRoot","viteConfigPath","outDir","scope","tsconfig","compilerOptions","moduleResolution","module","outDirToRootRelativePath","distDir","tsBuildInfoFile","lib","references","filter","ref","path","projectRoot","ignore","preferInstallDependencies","languages","ensureResolvable"],"mappings":"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"}
|
|
@@ -13,8 +13,10 @@ type IACProvider = {
|
|
|
13
13
|
/**
|
|
14
14
|
* Dependencies a caller must declare to add an AgentCore Gateway construct.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* Both providers render Cedar policies with `ejs`, each from a different
|
|
17
|
+
* manifest: the CDK construct imports it from the shared constructs project,
|
|
18
|
+
* while Terraform's `render-cedar.cjs` resolves it from the workspace root,
|
|
19
|
+
* since the shared terraform project it runs in has no `package.json`.
|
|
18
20
|
*/
|
|
19
21
|
export declare const AGENT_CORE_CONSTRUCTS_DEPENDENCIES: readonly [{
|
|
20
22
|
readonly name: "ejs";
|
|
@@ -25,6 +27,11 @@ export declare const AGENT_CORE_CONSTRUCTS_DEPENDENCIES: readonly [{
|
|
|
25
27
|
}, {
|
|
26
28
|
readonly name: "@types/ejs";
|
|
27
29
|
readonly when: (m: IacMetadata) => boolean;
|
|
30
|
+
}, {
|
|
31
|
+
readonly name: "ejs";
|
|
32
|
+
readonly when: (m: IacMetadata) => boolean;
|
|
33
|
+
readonly dev: true;
|
|
34
|
+
readonly root: true;
|
|
28
35
|
}];
|
|
29
36
|
/**
|
|
30
37
|
* Python versions the generated Terraform pins in an inline `uv run --with`
|
|
@@ -7,25 +7,33 @@ import { forDependencies } from "../declared-dependencies.js";
|
|
|
7
7
|
import { addDependenciesToPackageJson } from "../dependencies.js";
|
|
8
8
|
import { esmVars } from "../module-format.js";
|
|
9
9
|
import { addDependencyToTargetIfNotPresent } from "../nx.js";
|
|
10
|
-
import {
|
|
10
|
+
import { generatedCdk, generatedTerraform, PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, SHARED_TERRAFORM_DIR } from "../shared-constructs-constants.js";
|
|
11
11
|
import { PY_VERSIONS, terraformProviderVersions, withVersions } from "../versions.js";
|
|
12
12
|
/**
|
|
13
13
|
* Dependencies a caller must declare to add an AgentCore Gateway construct.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* Both providers render Cedar policies with `ejs`, each from a different
|
|
16
|
+
* manifest: the CDK construct imports it from the shared constructs project,
|
|
17
|
+
* while Terraform's `render-cedar.cjs` resolves it from the workspace root,
|
|
18
|
+
* since the shared terraform project it runs in has no `package.json`.
|
|
17
19
|
*/ export const AGENT_CORE_CONSTRUCTS_DEPENDENCIES = [
|
|
18
20
|
{
|
|
19
21
|
name: 'ejs',
|
|
20
|
-
when:
|
|
22
|
+
when: generatedCdk
|
|
21
23
|
},
|
|
22
24
|
{
|
|
23
25
|
name: '@aws-sdk/client-bedrock-agentcore',
|
|
24
|
-
when:
|
|
26
|
+
when: generatedCdk
|
|
25
27
|
},
|
|
26
28
|
{
|
|
27
29
|
name: '@types/ejs',
|
|
28
|
-
when:
|
|
30
|
+
when: generatedCdk
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'ejs',
|
|
34
|
+
when: generatedTerraform,
|
|
35
|
+
dev: true,
|
|
36
|
+
root: true
|
|
29
37
|
}
|
|
30
38
|
];
|
|
31
39
|
/**
|
|
@@ -134,7 +142,7 @@ export const addAgentCoreGatewayInfra = async (tree, options, declaration)=>{
|
|
|
134
142
|
await addAgentCoreGatewayCDKInfra(tree, options, declaration);
|
|
135
143
|
break;
|
|
136
144
|
case 'terraform':
|
|
137
|
-
addAgentCoreGatewayTerraformInfra(tree, options);
|
|
145
|
+
addAgentCoreGatewayTerraformInfra(tree, options, declaration);
|
|
138
146
|
break;
|
|
139
147
|
}
|
|
140
148
|
updateJson(tree, joinPathFragments(PACKAGES_DIR, options.iac === 'cdk' ? SHARED_CONSTRUCTS_DIR : SHARED_TERRAFORM_DIR, 'project.json'), (config)=>{
|
|
@@ -173,7 +181,7 @@ const addAgentCoreGatewayCDKInfra = async (tree, options, declaration)=>{
|
|
|
173
181
|
'@types/ejs'
|
|
174
182
|
]), joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'package.json'));
|
|
175
183
|
};
|
|
176
|
-
const addAgentCoreGatewayTerraformInfra = (tree, options)=>{
|
|
184
|
+
const addAgentCoreGatewayTerraformInfra = (tree, options, declaration)=>{
|
|
177
185
|
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'terraform', 'core', 'agentcore-gateway'), joinPathFragments(PACKAGES_DIR, SHARED_TERRAFORM_DIR, 'src', 'core', 'agentcore-gateway'), {
|
|
178
186
|
...terraformProviderVersions()
|
|
179
187
|
}, {
|
|
@@ -199,7 +207,13 @@ const addAgentCoreGatewayTerraformInfra = (tree, options)=>{
|
|
|
199
207
|
if (tree.exists(renderScript)) {
|
|
200
208
|
tree.delete(renderScript);
|
|
201
209
|
}
|
|
210
|
+
return;
|
|
202
211
|
}
|
|
212
|
+
// render-cedar.cjs resolves ejs from the workspace root, since the shared
|
|
213
|
+
// terraform project it runs in has no package.json.
|
|
214
|
+
addDependenciesToPackageJson(tree, {}, withVersions(forDependencies(declaration), [
|
|
215
|
+
'ejs'
|
|
216
|
+
]));
|
|
203
217
|
};
|
|
204
218
|
/**
|
|
205
219
|
* Add AgentCore Harness infrastructure for the selected IaC provider.
|