@aws/nx-plugin 1.0.0-rc.81 → 1.0.0-rc.82
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 +11 -1
- package/package.json +1 -1
- 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-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/ts/react-website/app/generator.js +2 -2
- package/src/ts/react-website/app/generator.js.map +1 -1
- 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/shared-constructs-constants.d.ts +17 -0
- package/src/utils/shared-constructs-constants.js +14 -0
- package/src/utils/shared-constructs-constants.js.map +1 -1
package/migrations.json
CHANGED
|
@@ -22,6 +22,16 @@
|
|
|
22
22
|
"description": "Forward the py#agent Strands hooks to the AG-UI adapter so model and tool errors are reported",
|
|
23
23
|
"implementation": "./src/migrations/latest/py-agent-ag-ui-hooks/migration"
|
|
24
24
|
},
|
|
25
|
+
"latest-terraform-load-runtime-config-src-path": {
|
|
26
|
+
"version": "1.0.0-rc.82",
|
|
27
|
+
"description": "Point the react website's terraform load-runtime-config target at the runtime-config file the terraform aggregation actually writes",
|
|
28
|
+
"implementation": "./src/migrations/latest/terraform-load-runtime-config-src-path/migration"
|
|
29
|
+
},
|
|
30
|
+
"latest-runtime-config-namespace-defaults": {
|
|
31
|
+
"version": "1.0.0-rc.82",
|
|
32
|
+
"description": "Provision AppConfig configuration profiles for every namespace the vended terraform modules write to",
|
|
33
|
+
"implementation": "./src/migrations/latest/runtime-config-namespace-defaults/migration"
|
|
34
|
+
},
|
|
25
35
|
"v1.0.0-rc.50-0001-modernize-function-props-cast": {
|
|
26
36
|
"version": "1.0.0-rc.50",
|
|
27
37
|
"description": "Replace the legacy angle-bracket FunctionProps type assertion with the modern as syntax in generated API constructs",
|
|
@@ -163,7 +173,7 @@
|
|
|
163
173
|
"implementation": "./src/migrations/v1.0.0-rc.75/0001-ts-agent-session-id-middleware-extraction/migration"
|
|
164
174
|
},
|
|
165
175
|
"sync-vended-versions": {
|
|
166
|
-
"version": "1.0.0-rc.
|
|
176
|
+
"version": "1.0.0-rc.82",
|
|
167
177
|
"description": "Sync vended dependency versions and the tracked plugin version to those vended by this release",
|
|
168
178
|
"implementation": "./src/utils/version-upgrade-migration/migration"
|
|
169
179
|
}
|
package/package.json
CHANGED
|
@@ -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,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/ import { visitNotIgnoredFiles } from "@nx/devkit";
|
|
5
|
+
import { applyGritQL, matchGritQL } from "../../../utils/ast.js";
|
|
6
|
+
import { formatFilesInSubtree } from "../../../utils/format.js";
|
|
7
|
+
import { PACKAGES_DIR, SHARED_TERRAFORM_DIR } from "../../../utils/shared-constructs-constants.js";
|
|
8
|
+
/**
|
|
9
|
+
* Provision AppConfig configuration profiles for every namespace the vended terraform modules write to
|
|
10
|
+
*
|
|
11
|
+
* `core/runtime-config/appconfig` creates one configuration profile per entry in
|
|
12
|
+
* its `namespaces` list, and `appconfig-deployment` aggregates and deploys the
|
|
13
|
+
* same list. A module contributing an entry to a namespace outside that list
|
|
14
|
+
* writes its entry file to disk and nothing more — the value never reaches
|
|
15
|
+
* AppConfig, so a consumer reading it back fails at runtime. The vended defaults
|
|
16
|
+
* now cover `dynamodb` and `database` alongside `connection` and `agentcore`.
|
|
17
|
+
*
|
|
18
|
+
* Root modules that pass `namespaces` explicitly are updated too, since an
|
|
19
|
+
* explicit list overrides the vended default.
|
|
20
|
+
*
|
|
21
|
+
* How to write a migration:
|
|
22
|
+
* - https://nx.dev/docs/kb/migration-generators
|
|
23
|
+
* - What `nextSteps` means: https://nx.dev/docs/reference/devkit/MigrationReturnObject
|
|
24
|
+
*
|
|
25
|
+
* Guardrails:
|
|
26
|
+
* - Transform source with GritQL (`applyGritQL`, `matchGritQL`), not regexes or
|
|
27
|
+
* string replacements: it matches the AST, so it holds up against however the
|
|
28
|
+
* user's copy has been formatted. Use `updateJson` for JSON.
|
|
29
|
+
* - Pattern-match before writing: skip files that have diverged from the shape
|
|
30
|
+
* your generators produce and report them via `nextSteps`, or consider a
|
|
31
|
+
* hybrid migration, rather than clobbering the user's changes.
|
|
32
|
+
* - `nextSteps` is for work left for the user to do by hand, not a log of the
|
|
33
|
+
* edits you made: an edit that applied cleanly needs no entry.
|
|
34
|
+
* - Idempotent: re-running must be a no-op.
|
|
35
|
+
* - Format what you write: finish with `formatFilesInSubtree` so the files your
|
|
36
|
+
* migration wrote are formatted correctly.
|
|
37
|
+
*/ /** Namespaces the vended modules write to that the old defaults omitted. */ const ADDED_NAMESPACES = [
|
|
38
|
+
'database',
|
|
39
|
+
'dynamodb'
|
|
40
|
+
];
|
|
41
|
+
const RUNTIME_CONFIG_DIR = `${PACKAGES_DIR}/${SHARED_TERRAFORM_DIR}/src/core/runtime-config`;
|
|
42
|
+
const APPCONFIG_FILE = `${RUNTIME_CONFIG_DIR}/appconfig/appconfig.tf`;
|
|
43
|
+
const APPCONFIG_DEPLOYMENT_FILE = `${RUNTIME_CONFIG_DIR}/appconfig-deployment/appconfig-deployment.tf`;
|
|
44
|
+
const hcl = (pattern)=>`language hcl\n${pattern}`;
|
|
45
|
+
/** The `namespaces` variable declaration in a vended appconfig module. */ const VENDED_DEFAULT = {
|
|
46
|
+
block: 'variable "namespaces" { $body }',
|
|
47
|
+
attribute: 'default'
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* A call to the vended appconfig module that passes `namespaces` explicitly.
|
|
51
|
+
* `$src` binds the quoted string, so the regex ends at the closing quote — that
|
|
52
|
+
* anchor is what keeps the sibling `appconfig-deployment` call, which takes its
|
|
53
|
+
* namespaces from this module's output, out of scope.
|
|
54
|
+
*/ const ROOT_MODULE_ARGUMENT = {
|
|
55
|
+
block: 'module $name { $body }',
|
|
56
|
+
attribute: 'namespaces',
|
|
57
|
+
clauses: '$body <: contains `source = $src`, $src <: r".*runtime-config/appconfig\\"", $body <: contains `namespaces = $_`'
|
|
58
|
+
};
|
|
59
|
+
/** A GritQL pattern matching the enclosing block, plus any extra clauses. */ const scopePattern = (list, extraClauses)=>{
|
|
60
|
+
const clauses = [
|
|
61
|
+
list.clauses,
|
|
62
|
+
extraClauses
|
|
63
|
+
].filter(Boolean).join(', ');
|
|
64
|
+
return hcl(`\`${list.block}\`${clauses ? ` where { ${clauses} }` : ''}`);
|
|
65
|
+
};
|
|
66
|
+
/** Whether a namespace already appears in the list. */ const listsNamespace = (tree, filePath, list, namespace)=>matchGritQL(tree, filePath, scopePattern(list, `$body <: contains \`"${namespace}"\``));
|
|
67
|
+
/**
|
|
68
|
+
* Append a namespace to the list. Appended within the list rather than
|
|
69
|
+
* re-emitting it, so no trailing hole is introduced.
|
|
70
|
+
*/ const appendNamespace = (tree, filePath, list, namespace)=>applyGritQL(tree, filePath, scopePattern(list, `$body <: contains bubble \`${list.attribute} = [$items]\` where { $items <: [$..., $last], $last += \`, "${namespace}"\` }`));
|
|
71
|
+
/**
|
|
72
|
+
* Add every missing namespace to a list, returning false when one could not be
|
|
73
|
+
* added. Already-listed namespaces are skipped, which is what makes a re-run a
|
|
74
|
+
* no-op.
|
|
75
|
+
*/ const addMissingNamespaces = async (tree, filePath, list)=>{
|
|
76
|
+
for (const namespace of ADDED_NAMESPACES){
|
|
77
|
+
if (await listsNamespace(tree, filePath, list, namespace)) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (!await appendNamespace(tree, filePath, list, namespace)) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return true;
|
|
85
|
+
};
|
|
86
|
+
/** The vended module's own description, updated to document the new defaults. */ const DESCRIPTION_REWRITE = scopePattern(VENDED_DEFAULT, '$body <: contains bubble `description = $desc` where { $desc <: r".*one Configuration Profile is created per namespace.*", $desc => `"List of runtime-config namespaces this AppConfig application should expose (one Configuration Profile is created per namespace). The default covers every namespace the generated modules write to, and a namespace with no contributions deploys an empty profile — when adding namespaces of your own, keep the defaults alongside them."` }');
|
|
87
|
+
const missing = ADDED_NAMESPACES.map((n)=>`"${n}"`).join(' and ');
|
|
88
|
+
const divergedNextStep = (filePath)=>`${filePath}: the \`namespaces\` variable has diverged from the generated shape - left untouched. Add ${missing} to its \`default\` list, otherwise no configuration profile is created for them and the entries the vended dynamodb/database modules contribute are never deployed.`;
|
|
89
|
+
const rootModuleNextStep = (filePath)=>`${filePath}: passes \`namespaces\` to the runtime-config appconfig module in a shape this migration could not update - left untouched. Add ${missing} to that list, or drop the argument to take the module's defaults, otherwise the entries the vended dynamodb/database modules contribute are never deployed.`;
|
|
90
|
+
/** Bring one vended appconfig module's `namespaces` default up to date. */ const migrateVendedModule = async (tree, filePath, nextSteps)=>{
|
|
91
|
+
if (!tree.exists(filePath)) {
|
|
92
|
+
return; // This workspace has no Terraform runtime config.
|
|
93
|
+
}
|
|
94
|
+
if (!await addMissingNamespaces(tree, filePath, VENDED_DEFAULT)) {
|
|
95
|
+
nextSteps.push(divergedNextStep(filePath));
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Root modules that pass `namespaces` explicitly override the vended default, so
|
|
100
|
+
* they need the same additions.
|
|
101
|
+
*/ const migrateRootModules = async (tree, nextSteps)=>{
|
|
102
|
+
const terraformFiles = [];
|
|
103
|
+
visitNotIgnoredFiles(tree, '', (filePath)=>{
|
|
104
|
+
if (filePath.endsWith('.tf') && !filePath.startsWith(RUNTIME_CONFIG_DIR)) {
|
|
105
|
+
terraformFiles.push(filePath);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
for (const filePath of terraformFiles){
|
|
109
|
+
if (!await matchGritQL(tree, filePath, scopePattern(ROOT_MODULE_ARGUMENT))) {
|
|
110
|
+
continue; // Takes the module's defaults, so nothing to update.
|
|
111
|
+
}
|
|
112
|
+
if (!await addMissingNamespaces(tree, filePath, ROOT_MODULE_ARGUMENT)) {
|
|
113
|
+
nextSteps.push(rootModuleNextStep(filePath));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
export default async function migration(tree) {
|
|
118
|
+
const nextSteps = [];
|
|
119
|
+
await migrateVendedModule(tree, APPCONFIG_FILE, nextSteps);
|
|
120
|
+
await migrateVendedModule(tree, APPCONFIG_DEPLOYMENT_FILE, nextSteps);
|
|
121
|
+
if (tree.exists(APPCONFIG_FILE)) {
|
|
122
|
+
await applyGritQL(tree, APPCONFIG_FILE, DESCRIPTION_REWRITE);
|
|
123
|
+
}
|
|
124
|
+
await migrateRootModules(tree, nextSteps);
|
|
125
|
+
await formatFilesInSubtree(tree);
|
|
126
|
+
return {
|
|
127
|
+
nextSteps
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/runtime-config-namespace-defaults/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n type MigrationReturnObject,\n type Tree,\n visitNotIgnoredFiles,\n} 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 * Provision AppConfig configuration profiles for every namespace the vended terraform modules write to\n *\n * `core/runtime-config/appconfig` creates one configuration profile per entry in\n * its `namespaces` list, and `appconfig-deployment` aggregates and deploys the\n * same list. A module contributing an entry to a namespace outside that list\n * writes its entry file to disk and nothing more — the value never reaches\n * AppConfig, so a consumer reading it back fails at runtime. The vended defaults\n * now cover `dynamodb` and `database` alongside `connection` and `agentcore`.\n *\n * Root modules that pass `namespaces` explicitly are updated too, since an\n * explicit list overrides the vended default.\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 * Guardrails:\n * - Transform source with GritQL (`applyGritQL`, `matchGritQL`), not regexes or\n * string replacements: it matches the AST, so it holds up against however the\n * user's copy has been formatted. Use `updateJson` for JSON.\n * - Pattern-match before writing: skip files that have diverged from the shape\n * your generators produce and report them via `nextSteps`, or consider a\n * hybrid migration, rather than clobbering the user's changes.\n * - `nextSteps` is for work left for the user to do by hand, not a log of the\n * edits you made: an edit that applied cleanly needs no entry.\n * - Idempotent: re-running must be a no-op.\n * - Format what you write: finish with `formatFilesInSubtree` so the files your\n * migration wrote are formatted correctly.\n */\n\n/** Namespaces the vended modules write to that the old defaults omitted. */\nconst ADDED_NAMESPACES = ['database', 'dynamodb'];\n\nconst RUNTIME_CONFIG_DIR = `${PACKAGES_DIR}/${SHARED_TERRAFORM_DIR}/src/core/runtime-config`;\nconst APPCONFIG_FILE = `${RUNTIME_CONFIG_DIR}/appconfig/appconfig.tf`;\nconst APPCONFIG_DEPLOYMENT_FILE = `${RUNTIME_CONFIG_DIR}/appconfig-deployment/appconfig-deployment.tf`;\n\nconst hcl = (pattern: string) => `language hcl\\n${pattern}`;\n\n/**\n * Where a `namespaces` list lives, as the block that encloses it and the\n * attribute holding the list. `clauses` narrows the block further, keeping an\n * unrelated list elsewhere in the file out of scope; `$body` is the block's body\n * in every case, so the clauses below can all be written against it.\n */\ninterface NamespaceList {\n readonly block: string;\n readonly attribute: string;\n readonly clauses?: string;\n}\n\n/** The `namespaces` variable declaration in a vended appconfig module. */\nconst VENDED_DEFAULT: NamespaceList = {\n block: 'variable \"namespaces\" { $body }',\n attribute: 'default',\n};\n\n/**\n * A call to the vended appconfig module that passes `namespaces` explicitly.\n * `$src` binds the quoted string, so the regex ends at the closing quote — that\n * anchor is what keeps the sibling `appconfig-deployment` call, which takes its\n * namespaces from this module's output, out of scope.\n */\nconst ROOT_MODULE_ARGUMENT: NamespaceList = {\n block: 'module $name { $body }',\n attribute: 'namespaces',\n clauses:\n '$body <: contains `source = $src`, $src <: r\".*runtime-config/appconfig\\\\\"\", $body <: contains `namespaces = $_`',\n};\n\n/** A GritQL pattern matching the enclosing block, plus any extra clauses. */\nconst scopePattern = (list: NamespaceList, extraClauses?: string) => {\n const clauses = [list.clauses, extraClauses].filter(Boolean).join(', ');\n return hcl(`\\`${list.block}\\`${clauses ? ` where { ${clauses} }` : ''}`);\n};\n\n/** Whether a namespace already appears in the list. */\nconst listsNamespace = (\n tree: Tree,\n filePath: string,\n list: NamespaceList,\n namespace: string,\n) =>\n matchGritQL(\n tree,\n filePath,\n scopePattern(list, `$body <: contains \\`\"${namespace}\"\\``),\n );\n\n/**\n * Append a namespace to the list. Appended within the list rather than\n * re-emitting it, so no trailing hole is introduced.\n */\nconst appendNamespace = (\n tree: Tree,\n filePath: string,\n list: NamespaceList,\n namespace: string,\n) =>\n applyGritQL(\n tree,\n filePath,\n scopePattern(\n list,\n `$body <: contains bubble \\`${list.attribute} = [$items]\\` where { $items <: [$..., $last], $last += \\`, \"${namespace}\"\\` }`,\n ),\n );\n\n/**\n * Add every missing namespace to a list, returning false when one could not be\n * added. Already-listed namespaces are skipped, which is what makes a re-run a\n * no-op.\n */\nconst addMissingNamespaces = async (\n tree: Tree,\n filePath: string,\n list: NamespaceList,\n): Promise<boolean> => {\n for (const namespace of ADDED_NAMESPACES) {\n if (await listsNamespace(tree, filePath, list, namespace)) {\n continue;\n }\n if (!(await appendNamespace(tree, filePath, list, namespace))) {\n return false;\n }\n }\n return true;\n};\n\n/** The vended module's own description, updated to document the new defaults. */\nconst DESCRIPTION_REWRITE = scopePattern(\n VENDED_DEFAULT,\n '$body <: contains bubble `description = $desc` where { $desc <: r\".*one Configuration Profile is created per namespace.*\", $desc => `\"List of runtime-config namespaces this AppConfig application should expose (one Configuration Profile is created per namespace). The default covers every namespace the generated modules write to, and a namespace with no contributions deploys an empty profile — when adding namespaces of your own, keep the defaults alongside them.\"` }',\n);\n\nconst missing = ADDED_NAMESPACES.map((n) => `\"${n}\"`).join(' and ');\n\nconst divergedNextStep = (filePath: string) =>\n `${filePath}: the \\`namespaces\\` variable has diverged from the generated shape - left untouched. Add ${missing} to its \\`default\\` list, otherwise no configuration profile is created for them and the entries the vended dynamodb/database modules contribute are never deployed.`;\n\nconst rootModuleNextStep = (filePath: string) =>\n `${filePath}: passes \\`namespaces\\` to the runtime-config appconfig module in a shape this migration could not update - left untouched. Add ${missing} to that list, or drop the argument to take the module's defaults, otherwise the entries the vended dynamodb/database modules contribute are never deployed.`;\n\n/** Bring one vended appconfig module's `namespaces` default up to date. */\nconst migrateVendedModule = async (\n tree: Tree,\n filePath: string,\n nextSteps: string[],\n): Promise<void> => {\n if (!tree.exists(filePath)) {\n return; // This workspace has no Terraform runtime config.\n }\n\n if (!(await addMissingNamespaces(tree, filePath, VENDED_DEFAULT))) {\n nextSteps.push(divergedNextStep(filePath));\n }\n};\n\n/**\n * Root modules that pass `namespaces` explicitly override the vended default, so\n * they need the same additions.\n */\nconst migrateRootModules = async (\n tree: Tree,\n nextSteps: string[],\n): Promise<void> => {\n const terraformFiles: string[] = [];\n visitNotIgnoredFiles(tree, '', (filePath) => {\n if (filePath.endsWith('.tf') && !filePath.startsWith(RUNTIME_CONFIG_DIR)) {\n terraformFiles.push(filePath);\n }\n });\n\n for (const filePath of terraformFiles) {\n if (\n !(await matchGritQL(tree, filePath, scopePattern(ROOT_MODULE_ARGUMENT)))\n ) {\n continue; // Takes the module's defaults, so nothing to update.\n }\n\n if (!(await addMissingNamespaces(tree, filePath, ROOT_MODULE_ARGUMENT))) {\n nextSteps.push(rootModuleNextStep(filePath));\n }\n }\n};\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n await migrateVendedModule(tree, APPCONFIG_FILE, nextSteps);\n await migrateVendedModule(tree, APPCONFIG_DEPLOYMENT_FILE, nextSteps);\n\n if (tree.exists(APPCONFIG_FILE)) {\n await applyGritQL(tree, APPCONFIG_FILE, DESCRIPTION_REWRITE);\n }\n\n await migrateRootModules(tree, nextSteps);\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["visitNotIgnoredFiles","applyGritQL","matchGritQL","formatFilesInSubtree","PACKAGES_DIR","SHARED_TERRAFORM_DIR","ADDED_NAMESPACES","RUNTIME_CONFIG_DIR","APPCONFIG_FILE","APPCONFIG_DEPLOYMENT_FILE","hcl","pattern","VENDED_DEFAULT","block","attribute","ROOT_MODULE_ARGUMENT","clauses","scopePattern","list","extraClauses","filter","Boolean","join","listsNamespace","tree","filePath","namespace","appendNamespace","addMissingNamespaces","DESCRIPTION_REWRITE","missing","map","n","divergedNextStep","rootModuleNextStep","migrateVendedModule","nextSteps","exists","push","migrateRootModules","terraformFiles","endsWith","startsWith","migration"],"mappings":"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"}
|
|
@@ -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"}
|
|
@@ -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":"AAAA;;;CAGC,GACD,SACEA,aAAa,EACbC,iBAAiB,EACjBC,KAAK,EACLC,iBAAiB,EACjBC,wBAAwB,EACxBC,iCAAiC,EAEjCC,UAAU,EACVC,0BAA0B,QACrB,aAAa;AACpB,SAASC,oBAAoB,QAAQ,YAAY;AACjD,SAASC,QAAQ,EAAEC,GAAG,QAAQ,OAAO;AACrC,SAASC,iBAAiB,QAAQ,qCAAqC;AACvE,SACEC,qBAAqB,EACrBC,eAAe,EACfC,sBAAsB,EACtBC,WAAW,QACN,wBAAwB;AAC/B,SACEC,mBAAmB,EACnBC,cAAc,QACT,0CAA0C;AACjD,SAASC,oBAAoB,QAAQ,2BAA2B;AAChE,SAASC,UAAU,QAAQ,wBAAwB;AACnD,SAASC,mBAAmB,QAAQ,4BAA4B;AAChE,SAASC,+BAA+B,QAAQ,4BAA4B;AAC5E,SAASC,SAAS,EAAEC,WAAW,EAAEC,WAAW,QAAQ,0BAA0B;AAC9E,SAASC,iBAAiB,QAAQ,8BAA8B;AAChE,SACEC,oBAAoB,EACpBC,gBAAgB,QAEX,uBAAuB;AAC9B,SAASC,cAAc,QAAQ,2BAA2B;AAC1D,SAASC,qBAAqB,QAAQ,0BAA0B;AAChE,SAASC,gCAAgC,QAAQ,gCAAgC;AACjF,SACEC,8BAA8B,EAC9BC,yBAAyB,QACpB,sCAAsC;AAC7C,SAEEC,YAAY,EACZC,iBAAiB,QACZ,gDAAgD;AACvD,SACEC,mBAAmB,EACnBC,qBAAqB,QAChB,kCAAkC;AACzC,SACEC,eAAe,EACfC,kCAAkC,QAC7B,0DAA0D;AACjE,SAASC,kBAAkB,QAAQ,gCAAgC;AACnE,SAASC,mBAAmB,QAAQ,sBAAsB;AAgB1D,iFAAiF;AACjF,+BAA+B;AAC/B,OAAO,MAAMC,eAAezB,sBAA8C;IACxE0B,IAAI;QACF;YAAEC,MAAM;QAAQ;QAChB;YAAEA,MAAM;QAAY;QACpB,2EAA2E;QAC3E;YAAEA,MAAM;YAAaC,KAAK;YAAMC,MAAM;QAAK;QAC3C;YAAEF,MAAM;YAAcC,KAAK;YAAMC,MAAM;QAAK;QAC5C;YACEF,MAAM;YACNG,MAAM,CAACC,IAAMA,EAAEC,EAAE,KAAK;QACxB;QACA;YACEL,MAAM;YACNG,MAAM,CAACC,IAAMA,EAAEC,EAAE,KAAK;QACxB;QACA;YACEL,MAAM;YACNG,MAAM,CAACC,IAAMA,EAAEC,EAAE,KAAK;QACxB;QACA,sEAAsE;QACtE,wEAAwE;QACxE,gEAAgE;QAChE;YACEL,MAAM;YACNG,MAAM,CAACC,IAAMA,EAAEC,EAAE,KAAK,YAAYD,EAAEE,cAAc;QACpD;QACA;YAAEN,MAAM;YAAeG,MAAM,CAACC,IAAMA,EAAEG,QAAQ;QAAC;QAC/C;YACEP,MAAM;YACNG,MAAM,CAACC,IAAMA,EAAEG,QAAQ;YACvBN,KAAK;YACLC,MAAM;QACR;QACA;YAAEF,MAAM;YAA0BG,MAAM,CAACC,IAAMA,EAAEE,cAAc;QAAC;QAChE;YACEN,MAAM;YACNG,MAAM,CAACC,IAAMA,EAAEE,cAAc;YAC7BL,KAAK;YACLC,MAAM;QACR;QACA;YACEF,MAAM;YACNG,MAAM,CAACC,IAAMA,EAAEE,cAAc;YAC7BL,KAAK;YACLC,MAAM;QACR;QACA;YACEF,MAAM;YACNG,MAAM,CAACC,IAAMA,EAAEE,cAAc;YAC7BL,KAAK;YACLC,MAAM;QACR;QACA;YACEF,MAAM;YACNG,MAAM,CAACC,IAAMA,EAAEE,cAAc;YAC7BL,KAAK;YACLC,MAAM;QACR;WACG5B,eAAekB;WACflB,eAAeuB;WACfvB,eAAec;KACnB;IACDoB,IAAIlC,eAAeqB;AACrB,GAAG;AAEH,OAAO,MAAMc,yBAAyB;IAAC;IAAQ;IAAc;CAAS,CAAU;AAMhF,OAAO,MAAMC,mCACX1B,iBAAiB,YAAY2B,QAAQ,EAAE;AAEzC,OAAO,eAAeC,wBACpBC,IAAU,EACVC,MAAqC;IAErC,MAAMP,WAAWO,OAAOP,QAAQ,IAAI;IACpC,MAAMD,iBAAiBQ,OAAOR,cAAc,IAAI;IAChD,MAAMD,KAASS,OAAOT,EAAE,IAAI;IAC5B,IAAIA,OAAO,YAAY,CAACE,UAAU;QAChC,MAAM,IAAIQ,MAAM;IAClB;IACA,MAAMC,iBAAiBlC,kBAAkB+B;IACzC,MAAMI,aAAaD;IACnB,MAAME,uBAAuBtC,YAAYkC,OAAOd,IAAI;IACpD,MAAMmB,uBAAuBtC,YAAYiC,OAAOd,IAAI;IACpD,MAAMoB,qBAAqB,GAAGJ,iBAAiBG,sBAAsB;IACrE,yDAAyD;IACzD,MAAME,qBAAqB/D,kBACzBwD,OAAOQ,SAAS,IAAI,KACpBR,OAAOS,YAAY,IAAIJ;IAGzB,MAAMK,uBAAuBX,KAAKY,MAAM,CACtCnE,kBAAkB+D,oBAAoB;IAGxC,mDAAmD;IACnD,MAAMK,gBAAgB;IAEtB,IAAI,CAACF,sBAAsB;QACzB,MAAM3D,qBAAqBgD,MAAM;YAC/B,GAAGC,MAAM;YACTd,MAAMoB;YACNE,WAAWD;YACXM,SAAS;YACTD;YACAE,QAAQ;YACRC,SAAS;YACTC,gBAAgB;YAChBC,gBAAgB;YAChBC,OAAO;YACP,mEAAmE;YACnE,yEAAyE;YACzEC,WAAW;QACb;QAEA,yEAAyE;QACzE,2EAA2E;QAC3E,4EAA4E;QAC5E,kCAAkC;QAClCtE,WAAWkD,MAAM,WAAW,CAACqB;YAC3B,KAAK,MAAMC,UAAUD,OAAOE,OAAO,IAAI,EAAE,CAAE;gBACzC,IAAI,OAAOD,WAAW,UAAU;gBAChC,IAAIA,OAAOA,MAAM,KAAK,mBAAmB;oBACvCA,OAAOE,OAAO,GAAG;wBACf,GAAGF,OAAOE,OAAO;wBACjBC,iBAAiB;wBACjB,qEAAqE;wBACrE,gEAAgE;wBAChE,yCAAyC;wBACzCC,iBAAiB;wBACjBC,eAAe;wBACfC,mBAAmB;wBACnBC,uBAAuB;wBACvBC,qBAAqB;oBACvB;gBACF,OAAO,IAAIR,OAAOA,MAAM,KAAK,cAAc;oBACzCA,OAAOE,OAAO,GAAG;wBACf,GAAGF,OAAOE,OAAO;wBACjBO,gBAAgB;oBAClB;gBACF;YACF;YACA,OAAOV;QACT;QAEA,0CAA0C;QAC1CrB,KAAKgC,MAAM,CAACvF,kBAAkB+D,oBAAoB;IACpD;IAEA,MAAMyB,uBAAuBrF,yBAC3BoD,MACAO;IAGF,MAAM2B,UAAUD,qBAAqBC,OAAO;IAE5C,MAAMC,QAAQlC,OAAOkC,KAAK,IAAI;IAE9B,2FAA2F;IAC3F,MAAMC,MAAMD,UAAU,SAAS,MAAMxE,WAAWqC,MAAMC,OAAOmC,GAAG,IAAIC;IAEpE,IAAID,QAAQ,OAAO;QACjBF,OAAO,CAAC,sBAAsB,GAAG;YAC/BI,UAAU;YACVC,UAAU;gBACRC,aAAa,CAAC,qHAAqH,EAAElE,mCAAmCmE,IAAI,CAAC,wBAAwB,EAAElC,mBAAmB,CAAC,CAAC;YAC9N;YACAiB,SAAS;gBACPkB,SAAS,CAAC,6FAA6F,EAAE5E,UAAUqC,gBAAgB,0CAA0C,EAAEE,qBAAqB,gHAAgH,CAAC;YACvT;QACF;IACF,OAAO,IAAI+B,QAAQ,aAAa;QAC9BF,OAAO,CAAC,sBAAsB,GAAG;YAC/BI,UAAU;YACVC,UAAU;gBACRC,aACE;YACJ;YACAhB,SAAS;gBACPkB,SACE;gBACFC,KAAK;oBACHC,UAAU;oBACVC,UAAU,CAAC,oBAAoB,CAAC;oBAChCC,WAAW,CAAC,wCAAwC,CAAC;gBACvD;YACF;QACF;IACF;IAEA,IAAI,CAACnC,sBAAsB;QACzBuB,OAAO,CAAC,UAAU,GAAG;YACnBa,WAAW;gBAAC;aAAS;YACrBT,UAAU;YACVU,SAAS;gBAAC;aAAyC;YACnDxB,SAAS;gBACPkB,SAAS;gBACTO,KAAK;YACP;QACF;QACA,sEAAsE;QACtE,qEAAqE;QACrE,uDAAuD;QACvDf,OAAO,CAAC,QAAQ,GAAG;YACjBa,WAAW;gBAAC;gBAAQ;gBAAW;gBAAQ;aAAS;QAClD;QAEA,sEAAsE;QACtE,4DAA4D;QAC5Db,OAAO,CAAC,MAAM,GAAG;YACfI,UAAU;YACVY,YAAY;YACZ1B,SAAS;gBACPkB,SAAS;gBACTO,KAAK;YACP;QACF;IACF;IAEAhB,qBAAqBC,OAAO,GAAG9D,eAAe8D;IAE9CnF,2BAA2BiD,MAAMO,oBAAoB0B;IAErD,0EAA0E;IAC1E,8DAA8D;IAC9D,MAAMM,WAAmC;QACvC/C;QACA2D,WAAW;QACXhB;QACAzC;QACAD;QACA,wEAAwE;QACxE,uBAAuB;QACvB,GAAI2C,MAAM;YAAEA;QAAI,IAAI,CAAC,CAAC;IACxB;IACAlE,qBACE8B,MACAiC,qBAAqB9C,IAAI,EACzBU,kCACA0C;IAGF,MAAMxD,mBACJiB,MACA;QACEoD,KAAK5C;QACLD;IACF,GACAtB;IAGF,IAAIO,OAAO,UAAU;QACnB,MAAMZ,sBAAsBoB,MAAMf;IACpC;IAEA,IAAImD,KAAK;QACP,MAAM5D,0BACJwB,MACA;YACEoC;QACF,GACAnD;QAGF,MAAMJ,gBAAgBmB,MAAM;YAC1BoC;YACAiB,oBAAoB9C;YACpBH;YACAI,oBAAoB/D,kBAAkB,QAAQ+D;YAC9CF;YACAD;QACF;IACF;IAEA,MAAMiD,gBAAgB1G,yBAAyBoD,MAAMO;IACrD,MAAMgD,cAAcD,cAAcjE,IAAI;IACtC,MAAMmE,2BAA2BvG,SAC/BR,kBAAkB8G,aAAa,QAC/B9G,kBACEgC,cACAC,mBACA,OACA,UACA,gBAGD+E,KAAK,CAACvG,KACNwG,IAAI,CAAC;IACR,MAAMC,0BAA0B1G,SAC9BR,kBAAkBuD,KAAKX,IAAI,EAAEmB,qBAC7B/D,kBACEuD,KAAKX,IAAI,EACTZ,cACAC,mBACA,kBAGD+E,KAAK,CAACvG,KACNwG,IAAI,CAAC;IACR,MAAME,kBAAkB;QACtB,GAAG3D,MAAM;QACTM;QACAsD,WAAWvF,mCAAmCmE,IAAI;QAClD/C;QACAD;QACAW;QACAoD;IACF;IACAxD,KAAKgC,MAAM,CAACvF,kBAAkB8G,aAAa,OAAO;IAClD,MAAMO,wBAAwBrH,kBAC5B,YAAYsH,OAAO,EACnB;IAEF,MAAMC,kBAAkBvH,kBACtB,YAAYsH,OAAO,EACnB,CAAC,YAAY,EAAEvE,GAAGyE,WAAW,IAAI;IAGnCzH,cACEwD,MACA8D,uBACAP,aACAK,iBACA;QACE,sDAAsD;QACtDM,mBAAmBvH,kBAAkBwH,YAAY;IACnD;IAGF3H,cACEwD,MACAgE,iBACAT,aACAK,iBACA;QACE,sDAAsD;QACtDM,mBAAmBvH,kBAAkBwH,YAAY;IACnD;IAGF,IAAI1E,gBAAgB;QAClB,MAAM2E,2BAA2B3H,kBAC/B,YAAYsH,OAAO,EACnB;QAEF,MAAMM,qBAAqB5H,kBACzB,YAAYsH,OAAO,EACnB,CAAC,wBAAwB,EAAEvE,GAAGyE,WAAW,IAAI;QAG/CzH,cACEwD,MACAoE,0BACAb,aACAK,iBACA;YACE,kFAAkF;YAClFM,mBAAmBvH,kBAAkBwH,YAAY;QACnD;QAGF3H,cACEwD,MACAqE,oBACAd,aACAK,iBACA;YACE,sDAAsD;YACtDM,mBAAmBvH,kBAAkBwH,YAAY;QACnD;QAEFnE,KAAKgC,MAAM,CAACvF,kBAAkB+D,oBAAoB,OAAO;IAC3D;IAEA,IAAIK,kBAAkB,QAAQ;QAC5B,MAAMyD,wBAAwB,GAAG/D,mBAAmB,IAAI,CAAC;QACzD,MAAMgE,UAAU3H,yBAAyBoD,MAAMsE,uBAAuBjF,IAAI;QAC1E7C,cACEwD,MACAvD,kBAAkB,YAAYsH,OAAO,EAAE,CAAC,YAAY,EAAElD,eAAe,GACrE0D,SACA;YAAE,GAAGtE,MAAM;YAAE,GAAGvD,MAAM6D,mBAAmB;QAAC,GAC1C;YACE2D,mBAAmBvH,kBAAkBwH,YAAY;QACnD;QAEF,MAAMpF,mBACJiB,MACA;YACEO,oBAAoB+D;YACpBlB,KAAKmB;QACP,GACAtF;IAEJ;IACA,MAAMuF,iBAAiB/H,kBAAkB8G,aAAa;IAEtD,IAAIvD,KAAKY,MAAM,CAAC4D,iBAAiB;QAC/B,wCAAwC;QACxC,IAAI/E,gBAAgB;YAClB,MAAMrC,sBACJ4C,MACAwE,gBACA;gBAAC;aAAiB,EAClB;YAGF,MAAMpH,sBAAsB4C,MAAMwE,gBAAgB;gBAAC;aAAU,EAAE;QACjE;QAEA,oCAAoC;QACpC,IAAI9E,UAAU;YACZ,MAAMrC,gBACJ2C,MACAwE,gBACA,eACA;QAEJ;QAEA,wEAAwE;QACxE,kEAAkE;QAClE,MAAMC,SAAShI,kBACb4B,sBAAsB2B,MAAMO,qBAC5B,QACAC,oBACA;QAEF,MAAMjD,YACJyC,MACAwE,gBACA,CAAC,gFAAgF,EAAEC,OAAO,KAAK,CAAC;QAGlG,mCAAmC;QACnC,IAAIhF,gBAAgB;YAClB,8FAA8F;YAC9F,MAAMlC,YACJyC,MACAwE,gBACA;QAEJ;QAEA,IAAI9E,UAAU;YACZ,MAAMpC,uBACJ0C,MACAwE,gBACA,YACA,iBACA;gBAAEE,OAAO;YAAmB;QAEhC;QAEA,8EAA8E;QAC9E,yEAAyE;QACzE,yEAAyE;QACzE,qEAAqE;QACrE,qCAAqC;QACrC,MAAMnH,YACJyC,MACAwE,gBACA;QAGF,oFAAoF;QACpF,MAAMjH,YACJyC,MACAwE,gBACA;IAEJ;IAEA1H,WACEkD,MACAvD,kBAAkB+D,oBAAoB,kBACtC,CAACmE,WAAc,CAAA;YACb,GAAGA,QAAQ;YACXC,iBAAiB;gBACf,GAAGD,SAASC,eAAe;gBAC3BC,kBAAkB;gBAClBC,QAAQ;YACV;QACF,CAAA;IAEF,MAAMC,2BAA2B9H,SAC/BR,kBAAkBuD,KAAKX,IAAI,EAAEmB,qBAC7BR,KAAKX,IAAI;IAEX,MAAM2F,UAAUvI,kBACdsI,0BACA,QACAvE,oBACA;IAEF1D,WACEkD,MACAvD,kBAAkB+D,oBAAoB,sBACtC,CAACmE,WAAc,CAAA;YACb,GAAGA,QAAQ;YACXC,iBAAiB;gBACf,GAAGD,SAASC,eAAe;gBAC3BH,QAAQO;gBACRC,iBAAiBxI,kBAAkBuI,SAAS;gBAC5CE,KAAK;oBAAC;iBAAM;YACd;YACAC,YACE3F,OAAO,WACH;mBACK,AAACmF,CAAAA,SAASQ,UAAU,IAAI,EAAE,AAAD,EAAGC,MAAM,CACnC,CAACC,MAAQA,IAAIC,IAAI,KAAK3B;gBAExB;oBACE2B,MAAM3B;gBACR;aACD,GACDgB,SAASQ,UAAU;QAC3B,CAAA;IAGFhI,kBAAkB6C,MAAMf,cAAc;QAAEsD;QAAUgD,aAAahC;IAAY;IAE3E,uEAAuE;IACvE,0EAA0E;IAC1E,4EAA4E;IAC5E,4EAA4E;IAC5E,mDAAmD;IACnD1G,kCAAkCmD,MAAM;QAAC;QAAS;KAAY,EAAE,EAAE;IAElE,MAAMnC,gCAAgCmC,MAAM;QAC1CH;KACD;IAED,+EAA+E;IAC/E,gFAAgF;IAChF,wEAAwE;IACxE,+EAA+E;IAC/E,2DAA2D;IAC3D,MAAMnC,qBAAqBsC,MAAMqC,WAAW;QAC1CmD,QAAQ/F,iBACJ;YAAChD,kBAAkB8G,aAAa,OAAO;SAAoB,GAC3D,EAAE;IACR;IACA,4EAA4E;IAC5E,8EAA8E;IAC9E,gEAAgE;IAChE,OAAO,IACL3F,oBAAoBoC,MAAMC,OAAOwF,yBAAyB,EAAE;YAC1DC,WAAW;gBAAC;aAAa;YACzBC,kBAAkB;mBACZjG,WAAY;oBAAC;iBAAoB,GAAa,EAAE;mBAChDD,iBAAkB;oBAAC;iBAA0B,GAAa,EAAE;aACjE;QACH;AACJ;AACA,eAAeM,wBAAwB"}
|
|
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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"}
|
|
@@ -22,9 +22,9 @@ variable "application_name" {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
variable "namespaces" {
|
|
25
|
-
description = "List of runtime-config namespaces this AppConfig application should expose (one Configuration Profile is created per namespace)."
|
|
25
|
+
description = "List of runtime-config namespaces this AppConfig application should expose (one Configuration Profile is created per namespace). The default covers every namespace the generated modules write to, and a namespace with no contributions deploys an empty profile — when adding namespaces of your own, keep the defaults alongside them."
|
|
26
26
|
type = list(string)
|
|
27
|
-
default = ["connection", "agentcore"]
|
|
27
|
+
default = ["connection", "agentcore", "database", "dynamodb"]
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
variable "deployment_strategy_id" {
|
|
@@ -40,7 +40,7 @@ variable "configuration_profile_ids" {
|
|
|
40
40
|
variable "namespaces" {
|
|
41
41
|
description = "List of namespaces to aggregate + deploy. Must match the keys of `configuration_profile_ids`."
|
|
42
42
|
type = list(string)
|
|
43
|
-
default = ["connection", "agentcore"]
|
|
43
|
+
default = ["connection", "agentcore", "database", "dynamodb"]
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
locals {
|
|
@@ -10,6 +10,23 @@ export declare const SHARED_INFRA_CONFIG_DIR = "common/infra-config";
|
|
|
10
10
|
export declare const SHARED_SCRIPTS_NAME = "common-scripts";
|
|
11
11
|
export declare const SHARED_SCRIPTS_DIR = "common/scripts";
|
|
12
12
|
export declare const DYNAMODB_GENERATOR_IDS: string[];
|
|
13
|
+
/**
|
|
14
|
+
* Directory the vended Terraform runtime-config modules aggregate into at apply
|
|
15
|
+
* time, relative to the workspace root. The `entry` module writes leaf files
|
|
16
|
+
* under `entries/<namespace>/`, and the `read` / `appconfig-deployment` modules
|
|
17
|
+
* merge those into one `<namespace>.json` here.
|
|
18
|
+
*/
|
|
19
|
+
export declare const TERRAFORM_RUNTIME_CONFIG_DIR = "dist/packages/common/terraform/runtime-config";
|
|
20
|
+
/**
|
|
21
|
+
* Runtime-config namespace the static website publishes to and reads back, as
|
|
22
|
+
* passed to the `read` module by the vended static-website Terraform module.
|
|
23
|
+
*/
|
|
24
|
+
export declare const WEBSITE_RUNTIME_CONFIG_NAMESPACE = "connection";
|
|
25
|
+
/**
|
|
26
|
+
* File the Terraform aggregation writes the website's runtime config to,
|
|
27
|
+
* relative to the workspace root.
|
|
28
|
+
*/
|
|
29
|
+
export declare const TERRAFORM_WEBSITE_RUNTIME_CONFIG_FILE = "dist/packages/common/terraform/runtime-config/connection.json";
|
|
13
30
|
/**
|
|
14
31
|
* What a generator records about the infrastructure it generated.
|
|
15
32
|
*
|
|
@@ -16,6 +16,20 @@ export const DYNAMODB_GENERATOR_IDS = [
|
|
|
16
16
|
'ts#dynamodb',
|
|
17
17
|
'py#dynamodb'
|
|
18
18
|
];
|
|
19
|
+
/**
|
|
20
|
+
* Directory the vended Terraform runtime-config modules aggregate into at apply
|
|
21
|
+
* time, relative to the workspace root. The `entry` module writes leaf files
|
|
22
|
+
* under `entries/<namespace>/`, and the `read` / `appconfig-deployment` modules
|
|
23
|
+
* merge those into one `<namespace>.json` here.
|
|
24
|
+
*/ export const TERRAFORM_RUNTIME_CONFIG_DIR = `dist/${PACKAGES_DIR}/${SHARED_TERRAFORM_DIR}/runtime-config`;
|
|
25
|
+
/**
|
|
26
|
+
* Runtime-config namespace the static website publishes to and reads back, as
|
|
27
|
+
* passed to the `read` module by the vended static-website Terraform module.
|
|
28
|
+
*/ export const WEBSITE_RUNTIME_CONFIG_NAMESPACE = 'connection';
|
|
29
|
+
/**
|
|
30
|
+
* File the Terraform aggregation writes the website's runtime config to,
|
|
31
|
+
* relative to the workspace root.
|
|
32
|
+
*/ export const TERRAFORM_WEBSITE_RUNTIME_CONFIG_FILE = `${TERRAFORM_RUNTIME_CONFIG_DIR}/${WEBSITE_RUNTIME_CONFIG_NAMESPACE}.json`;
|
|
19
33
|
/**
|
|
20
34
|
* Whether infrastructure was generated at all, so the packages an infra helper
|
|
21
35
|
* adds are only claimed where that helper ran.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/shared-constructs-constants.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { DeclaredTsDependency } from './declared-dependencies.js';\nimport type { ITsDepVersion } from './versions.js';\n\nexport const PACKAGES_DIR = 'packages';\nexport const SHARED_CONSTRUCTS_NAME = 'common-constructs';\nexport const SHARED_CONSTRUCTS_DIR = 'common/constructs';\nexport const SHARED_TERRAFORM_NAME = 'terraform';\nexport const SHARED_TERRAFORM_DIR = 'common/terraform';\nexport const SHARED_SHADCN_NAME = 'common-shadcn';\nexport const SHARED_SHADCN_DIR = 'common/shadcn';\nexport const SHARED_INFRA_CONFIG_NAME = 'common-infra-config';\nexport const SHARED_INFRA_CONFIG_DIR = 'common/infra-config';\nexport const SHARED_SCRIPTS_NAME = 'common-scripts';\nexport const SHARED_SCRIPTS_DIR = 'common/scripts';\n\nexport const DYNAMODB_GENERATOR_IDS = ['ts#dynamodb', 'py#dynamodb'];\n\n/**\n * What a generator records about the infrastructure it generated.\n *\n * Every generator that creates infrastructure records the `iac` it used, so a\n * predicate can tell a CDK project from a Terraform one at upgrade time. Absent\n * when the generator was run with no infrastructure, so its presence doubles as\n * \"infrastructure was generated\" — which is what gates the packages an infra\n * helper adds.\n */\nexport interface IacMetadata {\n readonly iac?: string;\n}\n\n/**\n * Whether infrastructure was generated at all, so the packages an infra helper\n * adds are only claimed where that helper ran.\n *\n * Reads `iac` rather than the generator's own `infra` option: every generator\n * resolves `iac` only on the infra branch, so one recorded field answers both\n * questions and no generator needs a second one.\n */\nexport const generatedInfrastructure = (m: IacMetadata): boolean =>\n m.iac !== undefined;\n\n/**\n * Whether Terraform infrastructure was generated, for the versions only a `.tf`\n * module pins — a Terraform inline script's `uv run --with` pins, which the CDK\n * branch never writes.\n */\nexport const generatedTerraform = (m: IacMetadata): boolean =>\n m.iac === 'terraform';\n\n/**\n * Dependencies a caller must declare to use the shared constructs project.\n * Lives here so generators can spread it without importing the generator.\n *\n * `constructs` and `aws-cdk-lib` are gated on CDK because\n * `sharedConstructsGenerator` creates the TypeScript constructs project on that\n * branch alone — a Terraform workspace gets the shared Terraform project and\n * never receives them.\n */\nexport const SHARED_CONSTRUCTS_DEPENDENCIES = [\n { name: 'constructs', when: (m: IacMetadata) => m.iac === 'cdk' },\n { name: 'aws-cdk-lib', when: (m: IacMetadata) => m.iac === 'cdk' },\n { name: '@types/node' },\n] as const satisfies readonly DeclaredTsDependency<\n ITsDepVersion,\n IacMetadata\n>[];\n"],"names":["PACKAGES_DIR","SHARED_CONSTRUCTS_NAME","SHARED_CONSTRUCTS_DIR","SHARED_TERRAFORM_NAME","SHARED_TERRAFORM_DIR","SHARED_SHADCN_NAME","SHARED_SHADCN_DIR","SHARED_INFRA_CONFIG_NAME","SHARED_INFRA_CONFIG_DIR","SHARED_SCRIPTS_NAME","SHARED_SCRIPTS_DIR","DYNAMODB_GENERATOR_IDS","generatedInfrastructure","m","iac","undefined","generatedTerraform","SHARED_CONSTRUCTS_DEPENDENCIES","name","when"],"mappings":"AAAA;;;CAGC,GAID,OAAO,MAAMA,eAAe,WAAW;AACvC,OAAO,MAAMC,yBAAyB,oBAAoB;AAC1D,OAAO,MAAMC,wBAAwB,oBAAoB;AACzD,OAAO,MAAMC,wBAAwB,YAAY;AACjD,OAAO,MAAMC,uBAAuB,mBAAmB;AACvD,OAAO,MAAMC,qBAAqB,gBAAgB;AAClD,OAAO,MAAMC,oBAAoB,gBAAgB;AACjD,OAAO,MAAMC,2BAA2B,sBAAsB;AAC9D,OAAO,MAAMC,0BAA0B,sBAAsB;AAC7D,OAAO,MAAMC,sBAAsB,iBAAiB;AACpD,OAAO,MAAMC,qBAAqB,iBAAiB;AAEnD,OAAO,MAAMC,yBAAyB;IAAC;IAAe;CAAc,CAAC;
|
|
1
|
+
{"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/shared-constructs-constants.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { DeclaredTsDependency } from './declared-dependencies.js';\nimport type { ITsDepVersion } from './versions.js';\n\nexport const PACKAGES_DIR = 'packages';\nexport const SHARED_CONSTRUCTS_NAME = 'common-constructs';\nexport const SHARED_CONSTRUCTS_DIR = 'common/constructs';\nexport const SHARED_TERRAFORM_NAME = 'terraform';\nexport const SHARED_TERRAFORM_DIR = 'common/terraform';\nexport const SHARED_SHADCN_NAME = 'common-shadcn';\nexport const SHARED_SHADCN_DIR = 'common/shadcn';\nexport const SHARED_INFRA_CONFIG_NAME = 'common-infra-config';\nexport const SHARED_INFRA_CONFIG_DIR = 'common/infra-config';\nexport const SHARED_SCRIPTS_NAME = 'common-scripts';\nexport const SHARED_SCRIPTS_DIR = 'common/scripts';\n\nexport const DYNAMODB_GENERATOR_IDS = ['ts#dynamodb', 'py#dynamodb'];\n\n/**\n * Directory the vended Terraform runtime-config modules aggregate into at apply\n * time, relative to the workspace root. The `entry` module writes leaf files\n * under `entries/<namespace>/`, and the `read` / `appconfig-deployment` modules\n * merge those into one `<namespace>.json` here.\n */\nexport const TERRAFORM_RUNTIME_CONFIG_DIR = `dist/${PACKAGES_DIR}/${SHARED_TERRAFORM_DIR}/runtime-config`;\n\n/**\n * Runtime-config namespace the static website publishes to and reads back, as\n * passed to the `read` module by the vended static-website Terraform module.\n */\nexport const WEBSITE_RUNTIME_CONFIG_NAMESPACE = 'connection';\n\n/**\n * File the Terraform aggregation writes the website's runtime config to,\n * relative to the workspace root.\n */\nexport const TERRAFORM_WEBSITE_RUNTIME_CONFIG_FILE = `${TERRAFORM_RUNTIME_CONFIG_DIR}/${WEBSITE_RUNTIME_CONFIG_NAMESPACE}.json`;\n\n/**\n * What a generator records about the infrastructure it generated.\n *\n * Every generator that creates infrastructure records the `iac` it used, so a\n * predicate can tell a CDK project from a Terraform one at upgrade time. Absent\n * when the generator was run with no infrastructure, so its presence doubles as\n * \"infrastructure was generated\" — which is what gates the packages an infra\n * helper adds.\n */\nexport interface IacMetadata {\n readonly iac?: string;\n}\n\n/**\n * Whether infrastructure was generated at all, so the packages an infra helper\n * adds are only claimed where that helper ran.\n *\n * Reads `iac` rather than the generator's own `infra` option: every generator\n * resolves `iac` only on the infra branch, so one recorded field answers both\n * questions and no generator needs a second one.\n */\nexport const generatedInfrastructure = (m: IacMetadata): boolean =>\n m.iac !== undefined;\n\n/**\n * Whether Terraform infrastructure was generated, for the versions only a `.tf`\n * module pins — a Terraform inline script's `uv run --with` pins, which the CDK\n * branch never writes.\n */\nexport const generatedTerraform = (m: IacMetadata): boolean =>\n m.iac === 'terraform';\n\n/**\n * Dependencies a caller must declare to use the shared constructs project.\n * Lives here so generators can spread it without importing the generator.\n *\n * `constructs` and `aws-cdk-lib` are gated on CDK because\n * `sharedConstructsGenerator` creates the TypeScript constructs project on that\n * branch alone — a Terraform workspace gets the shared Terraform project and\n * never receives them.\n */\nexport const SHARED_CONSTRUCTS_DEPENDENCIES = [\n { name: 'constructs', when: (m: IacMetadata) => m.iac === 'cdk' },\n { name: 'aws-cdk-lib', when: (m: IacMetadata) => m.iac === 'cdk' },\n { name: '@types/node' },\n] as const satisfies readonly DeclaredTsDependency<\n ITsDepVersion,\n IacMetadata\n>[];\n"],"names":["PACKAGES_DIR","SHARED_CONSTRUCTS_NAME","SHARED_CONSTRUCTS_DIR","SHARED_TERRAFORM_NAME","SHARED_TERRAFORM_DIR","SHARED_SHADCN_NAME","SHARED_SHADCN_DIR","SHARED_INFRA_CONFIG_NAME","SHARED_INFRA_CONFIG_DIR","SHARED_SCRIPTS_NAME","SHARED_SCRIPTS_DIR","DYNAMODB_GENERATOR_IDS","TERRAFORM_RUNTIME_CONFIG_DIR","WEBSITE_RUNTIME_CONFIG_NAMESPACE","TERRAFORM_WEBSITE_RUNTIME_CONFIG_FILE","generatedInfrastructure","m","iac","undefined","generatedTerraform","SHARED_CONSTRUCTS_DEPENDENCIES","name","when"],"mappings":"AAAA;;;CAGC,GAID,OAAO,MAAMA,eAAe,WAAW;AACvC,OAAO,MAAMC,yBAAyB,oBAAoB;AAC1D,OAAO,MAAMC,wBAAwB,oBAAoB;AACzD,OAAO,MAAMC,wBAAwB,YAAY;AACjD,OAAO,MAAMC,uBAAuB,mBAAmB;AACvD,OAAO,MAAMC,qBAAqB,gBAAgB;AAClD,OAAO,MAAMC,oBAAoB,gBAAgB;AACjD,OAAO,MAAMC,2BAA2B,sBAAsB;AAC9D,OAAO,MAAMC,0BAA0B,sBAAsB;AAC7D,OAAO,MAAMC,sBAAsB,iBAAiB;AACpD,OAAO,MAAMC,qBAAqB,iBAAiB;AAEnD,OAAO,MAAMC,yBAAyB;IAAC;IAAe;CAAc,CAAC;AAErE;;;;;CAKC,GACD,OAAO,MAAMC,+BAA+B,CAAC,KAAK,EAAEZ,aAAa,CAAC,EAAEI,qBAAqB,eAAe,CAAC,CAAC;AAE1G;;;CAGC,GACD,OAAO,MAAMS,mCAAmC,aAAa;AAE7D;;;CAGC,GACD,OAAO,MAAMC,wCAAwC,GAAGF,6BAA6B,CAAC,EAAEC,iCAAiC,KAAK,CAAC,CAAC;AAehI;;;;;;;CAOC,GACD,OAAO,MAAME,0BAA0B,CAACC,IACtCA,EAAEC,GAAG,KAAKC,UAAU;AAEtB;;;;CAIC,GACD,OAAO,MAAMC,qBAAqB,CAACH,IACjCA,EAAEC,GAAG,KAAK,YAAY;AAExB;;;;;;;;CAQC,GACD,OAAO,MAAMG,iCAAiC;IAC5C;QAAEC,MAAM;QAAcC,MAAM,CAACN,IAAmBA,EAAEC,GAAG,KAAK;IAAM;IAChE;QAAEI,MAAM;QAAeC,MAAM,CAACN,IAAmBA,EAAEC,GAAG,KAAK;IAAM;IACjE;QAAEI,MAAM;IAAc;CACvB,CAGG"}
|