@aws/nx-plugin 1.0.0-rc.45 → 1.0.0-rc.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/LICENSE-THIRD-PARTY +3 -60
  2. package/generators.json +9 -9
  3. package/package.json +7 -3
  4. package/src/agentcore-gateway/generator.js +12 -2
  5. package/src/agentcore-gateway/generator.js.map +1 -1
  6. package/src/infra/app/__snapshots__/generator.spec.ts.snap +25 -31
  7. package/src/infra/app/generator.js +9 -6
  8. package/src/infra/app/generator.js.map +1 -1
  9. package/src/license/config.js +1 -1
  10. package/src/license/config.js.map +1 -1
  11. package/src/mcp-server/schema.d.ts +1 -1
  12. package/src/mcp-server/tools/general-guidance.js +5 -6
  13. package/src/mcp-server/tools/general-guidance.js.map +1 -1
  14. package/src/preset/__snapshots__/generator.spec.ts.snap +38 -7
  15. package/src/preset/generator.d.ts +1 -1
  16. package/src/preset/generator.js +4 -2
  17. package/src/preset/generator.js.map +1 -1
  18. package/src/preset/schema.d.js.map +1 -1
  19. package/src/preset/schema.d.ts +1 -0
  20. package/src/preset/schema.json +5 -0
  21. package/src/py/agent/generator.js +2 -1
  22. package/src/py/agent/generator.js.map +1 -1
  23. package/src/py/mcp-server/generator.js +2 -1
  24. package/src/py/mcp-server/generator.js.map +1 -1
  25. package/src/py/project/generator.js +2 -1
  26. package/src/py/project/generator.js.map +1 -1
  27. package/src/py/rdb/__snapshots__/generator.spec.ts.snap +1 -0
  28. package/src/py/rdb/generator.js +7 -1
  29. package/src/py/rdb/generator.js.map +1 -1
  30. package/src/smithy/ts/api/generator.js +5 -2
  31. package/src/smithy/ts/api/generator.js.map +1 -1
  32. package/src/terraform/project/generator.js +4 -1
  33. package/src/terraform/project/generator.js.map +1 -1
  34. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +6 -6
  35. package/src/trpc/backend/generator.js +7 -5
  36. package/src/trpc/backend/generator.js.map +1 -1
  37. package/src/trpc/react/generator.js +4 -4
  38. package/src/trpc/react/generator.js.map +1 -1
  39. package/src/ts/agent/__snapshots__/generator.spec.ts.snap +2 -2
  40. package/src/ts/agent/a2a-connection/generator.js +3 -2
  41. package/src/ts/agent/a2a-connection/generator.js.map +1 -1
  42. package/src/ts/agent/gateway-connection/generator.js +4 -3
  43. package/src/ts/agent/gateway-connection/generator.js.map +1 -1
  44. package/src/ts/agent/generator.js +8 -5
  45. package/src/ts/agent/generator.js.map +1 -1
  46. package/src/ts/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +1 -1
  47. package/src/ts/agent/mcp-connection/generator.js +4 -3
  48. package/src/ts/agent/mcp-connection/generator.js.map +1 -1
  49. package/src/ts/agent/react-connection/generator.js +10 -19
  50. package/src/ts/agent/react-connection/generator.js.map +1 -1
  51. package/src/ts/astro-docs/generator.js +12 -3
  52. package/src/ts/astro-docs/generator.js.map +1 -1
  53. package/src/ts/dcr-proxy/generator.js +5 -5
  54. package/src/ts/dcr-proxy/generator.js.map +1 -1
  55. package/src/ts/dynamodb/generator.js +5 -2
  56. package/src/ts/dynamodb/generator.js.map +1 -1
  57. package/src/ts/lambda-function/__snapshots__/generator.spec.ts.snap +4 -2
  58. package/src/ts/lambda-function/files/handler/__lambdaFunctionKebabCase__.ts.template +2 -1
  59. package/src/ts/lambda-function/generator.js +3 -2
  60. package/src/ts/lambda-function/generator.js.map +1 -1
  61. package/src/ts/lib/ts-project-utils.js +17 -10
  62. package/src/ts/lib/ts-project-utils.js.map +1 -1
  63. package/src/ts/lib/vitest.js +2 -1
  64. package/src/ts/lib/vitest.js.map +1 -1
  65. package/src/ts/mcp-server/generator.js +11 -11
  66. package/src/ts/mcp-server/generator.js.map +1 -1
  67. package/src/ts/nx-generator/generator.js +5 -0
  68. package/src/ts/nx-generator/generator.js.map +1 -1
  69. package/src/ts/nx-plugin/__snapshots__/generator.spec.ts.snap +5 -6
  70. package/src/ts/nx-plugin/files/mcp-server/resources/GENERAL_GUIDANCE.md.template +5 -6
  71. package/src/ts/nx-plugin/utils.js +2 -1
  72. package/src/ts/nx-plugin/utils.js.map +1 -1
  73. package/src/ts/rdb/agent-connection/generator.js +1 -2
  74. package/src/ts/rdb/agent-connection/generator.js.map +1 -1
  75. package/src/ts/rdb/generator.js +10 -6
  76. package/src/ts/rdb/generator.js.map +1 -1
  77. package/src/ts/rdb/mcp-server-connection/generator.js +1 -2
  78. package/src/ts/rdb/mcp-server-connection/generator.js.map +1 -1
  79. package/src/ts/rdb/smithy-connection/generator.js +1 -2
  80. package/src/ts/rdb/smithy-connection/generator.js.map +1 -1
  81. package/src/ts/rdb/trpc-connection/generator.js +1 -2
  82. package/src/ts/rdb/trpc-connection/generator.js.map +1 -1
  83. package/src/ts/react-website/agui/generator.js +5 -4
  84. package/src/ts/react-website/agui/generator.js.map +1 -1
  85. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +219 -79
  86. package/src/ts/react-website/app/generator.js +34 -14
  87. package/src/ts/react-website/app/generator.js.map +1 -1
  88. package/src/ts/react-website/cognito-auth/__snapshots__/generator.spec.ts.snap +11 -6
  89. package/src/ts/react-website/cognito-auth/__snapshots__/generator.terraform.spec.ts.snap +12 -2
  90. package/src/ts/react-website/cognito-auth/generator.js +3 -2
  91. package/src/ts/react-website/cognito-auth/generator.js.map +1 -1
  92. package/src/ts/react-website/runtime-config/generator.js +2 -2
  93. package/src/ts/react-website/runtime-config/generator.js.map +1 -1
  94. package/src/ts/sync/generator.js +81 -3
  95. package/src/ts/sync/generator.js.map +1 -1
  96. package/src/utils/agent-connection/agent-connection.d.ts +1 -1
  97. package/src/utils/agent-connection/agent-connection.js +50 -1
  98. package/src/utils/agent-connection/agent-connection.js.map +1 -1
  99. package/src/utils/agent-core-constructs/agent-core-constructs.js +10 -1
  100. package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
  101. package/src/utils/api-constructs/api-constructs.js +15 -1
  102. package/src/utils/api-constructs/api-constructs.js.map +1 -1
  103. package/src/utils/bundle/bundle.js +2 -1
  104. package/src/utils/bundle/bundle.js.map +1 -1
  105. package/src/utils/commands.d.ts +5 -3
  106. package/src/utils/commands.js +24 -3
  107. package/src/utils/commands.js.map +1 -1
  108. package/src/utils/config/index.d.ts +16 -0
  109. package/src/utils/config/index.js.map +1 -1
  110. package/src/utils/config/utils.d.ts +3 -2
  111. package/src/utils/config/utils.js +4 -3
  112. package/src/utils/config/utils.js.map +1 -1
  113. package/src/utils/connection/open-api/react.js +3 -2
  114. package/src/utils/connection/open-api/react.js.map +1 -1
  115. package/src/utils/containers.js +1 -1
  116. package/src/utils/containers.js.map +1 -1
  117. package/src/utils/dependencies.d.ts +18 -0
  118. package/src/utils/dependencies.js +206 -0
  119. package/src/utils/dependencies.js.map +1 -0
  120. package/src/utils/files/common/shadcn/readme/README.md.template +3 -3
  121. package/src/utils/files/shadcn/components.json.template +1 -1
  122. package/src/utils/format.d.ts +20 -1
  123. package/src/utils/format.js +83 -49
  124. package/src/utils/format.js.map +1 -1
  125. package/src/utils/fs.d.ts +1 -1
  126. package/src/utils/fs.js +1 -1
  127. package/src/utils/fs.js.map +1 -1
  128. package/src/utils/iac.js +1 -1
  129. package/src/utils/iac.js.map +1 -1
  130. package/src/utils/identity-constructs/files/cdk/core/user-identity.ts.template +11 -6
  131. package/src/utils/identity-constructs/identity-constructs.js +14 -3
  132. package/src/utils/identity-constructs/identity-constructs.js.map +1 -1
  133. package/src/utils/init.d.ts +7 -1
  134. package/src/utils/init.js +38 -17
  135. package/src/utils/init.js.map +1 -1
  136. package/src/utils/install.js +3 -1
  137. package/src/utils/install.js.map +1 -1
  138. package/src/utils/module-format.d.ts +5 -8
  139. package/src/utils/module-format.js +29 -12
  140. package/src/utils/module-format.js.map +1 -1
  141. package/src/utils/npm-scope.d.ts +0 -4
  142. package/src/utils/npm-scope.js +0 -5
  143. package/src/utils/npm-scope.js.map +1 -1
  144. package/src/utils/pnpm-workspace.d.ts +1 -12
  145. package/src/utils/pnpm-workspace.js +3 -30
  146. package/src/utils/pnpm-workspace.js.map +1 -1
  147. package/src/utils/project-package-json.d.ts +39 -0
  148. package/src/utils/project-package-json.js +119 -0
  149. package/src/utils/project-package-json.js.map +1 -0
  150. package/src/utils/shared-constructs.js +6 -5
  151. package/src/utils/shared-constructs.js.map +1 -1
  152. package/src/utils/shared-dynamodb-scripts.js +4 -2
  153. package/src/utils/shared-dynamodb-scripts.js.map +1 -1
  154. package/src/utils/shared-infra-scripts.js +5 -4
  155. package/src/utils/shared-infra-scripts.js.map +1 -1
  156. package/src/utils/shared-rdb-scripts.js +14 -1
  157. package/src/utils/shared-rdb-scripts.js.map +1 -1
  158. package/src/utils/shared-shadcn.js +11 -8
  159. package/src/utils/shared-shadcn.js.map +1 -1
  160. package/src/utils/test.js +8 -3
  161. package/src/utils/test.js.map +1 -1
  162. package/src/utils/versions.d.ts +4 -0
  163. package/src/utils/versions.js +8 -1
  164. package/src/utils/versions.js.map +1 -1
  165. package/src/utils/website-constructs/files/cdk/core/static-website.ts.template +3 -0
@@ -1,16 +1,17 @@
1
1
  /**
2
2
  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
- */ import { addDependenciesToPackageJson, generateFiles, joinPathFragments, names, OverwriteStrategy, readProjectConfiguration, updateJson, updateProjectConfiguration } from "@nx/devkit";
4
+ */ import { generateFiles, joinPathFragments, names, OverwriteStrategy, readProjectConfiguration, removeDependenciesFromPackageJson, updateJson, updateProjectConfiguration } from "@nx/devkit";
5
5
  import { applicationGenerator } from "@nx/react";
6
6
  import { relative, sep } from "path";
7
7
  import { addDestructuredImport, addSingleImport, applyGritQL } from "../../../utils/ast.js";
8
+ import { addDependenciesToPackageJson } from "../../../utils/dependencies.js";
8
9
  import { formatFilesInSubtree } from "../../../utils/format.js";
9
10
  import { resolveIac } from "../../../utils/iac.js";
10
11
  import { installDependencies } from "../../../utils/install.js";
11
12
  import { addGeneratorMetricsIfApplicable } from "../../../utils/metrics.js";
12
13
  import { kebabCase, toClassName, toKebabCase } from "../../../utils/names.js";
13
- import { getNpmScopePrefix, toScopeAlias } from "../../../utils/npm-scope.js";
14
+ import { getNpmScopePrefix } from "../../../utils/npm-scope.js";
14
15
  import { addGeneratorMetadata, getGeneratorInfo } from "../../../utils/nx.js";
15
16
  import { sortObjectKeys } from "../../../utils/object.js";
16
17
  import { getRelativePathToRoot } from "../../../utils/paths.js";
@@ -35,7 +36,7 @@ export async function tsReactWebsiteGenerator(tree, schema) {
35
36
  throw new Error('Shadcn requires TailwindCSS to be enabled.');
36
37
  }
37
38
  const npmScopePrefix = getNpmScopePrefix(tree);
38
- const scopeAlias = toScopeAlias(npmScopePrefix);
39
+ const scopeAlias = npmScopePrefix;
39
40
  const websiteNameClassName = toClassName(schema.name);
40
41
  const websiteNameKebabCase = toKebabCase(schema.name);
41
42
  const fullyQualifiedName = `${npmScopePrefix}${websiteNameKebabCase}`;
@@ -264,8 +265,12 @@ export async function tsReactWebsiteGenerator(tree, schema) {
264
265
  if (tailwind) {
265
266
  await applyGritQL(tree, viteConfigPath, '`plugins: [$items]` => `plugins: [$items, tailwindcss()]` where { $items <: within `defineConfig($_)`, $items <: not some `tailwindcss()` }');
266
267
  }
267
- // Use Vite's native tsconfig paths resolution (replaces vite-tsconfig-paths)
268
- await applyGritQL(tree, viteConfigPath, 'or { `defineConfig(() => ({ $props }))` where { $props <: not some `resolve: $_`, $props += `resolve: { tsconfigPaths: true }` }, `defineConfig({ $props })` where { $props <: not some `resolve: $_`, $props += `resolve: { tsconfigPaths: true }` } }');
268
+ // Use Vite's native tsconfig paths resolution (replaces vite-tsconfig-paths).
269
+ // `dedupe` forces a single copy of react/react-dom into the bundle: each
270
+ // project declares its own react dependency, so without this a workspace
271
+ // library's hoisted copy can produce a second React instance and the
272
+ // "Invalid hook call" runtime crash.
273
+ await applyGritQL(tree, viteConfigPath, "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'] }` } }");
269
274
  // Add define: { global: {} } to the config (handles both callback and direct forms)
270
275
  await applyGritQL(tree, viteConfigPath, 'or { `defineConfig(() => ({ $props }))` where { $props <: not contains `define`, $props += `define: { global: {} }` }, `defineConfig({ $props })` where { $props <: not contains `define`, $props += `define: { global: {} }` } }');
271
276
  }
@@ -296,29 +301,44 @@ export async function tsReactWebsiteGenerator(tree, schema) {
296
301
  }
297
302
  ] : tsconfig.references
298
303
  }));
299
- const devDependencies = [
300
- '@nx/react',
301
- '@vitest/ui'
302
- ];
303
304
  const dependencies = [
304
305
  'react',
305
306
  'react-dom'
306
307
  ];
308
+ // Build/test tooling imported only from vite.config.mts stays at the root.
309
+ const rootDevDependencies = [
310
+ '@nx/react',
311
+ '@vitest/ui'
312
+ ];
307
313
  if (ux === 'cloudscape') {
308
314
  dependencies.push('@cloudscape-design/components', '@cloudscape-design/board-components', '@cloudscape-design/global-styles');
309
315
  } else if (ux === 'shadcn') {
310
- // not required to add any dependencies because dependencies are added by the common/shadcn package.
316
+ // Shared shadcn components live in the common/shadcn package, but the
317
+ // website's own generated components (e.g. the tanstack-router sidebar)
318
+ // import lucide-react directly, so the website must declare it.
319
+ if (tanstackRouter) {
320
+ dependencies.push('lucide-react');
321
+ }
311
322
  }
312
- // Add TailwindCSS dependencies if enabled
313
323
  if (tailwind) {
314
324
  dependencies.push('tailwindcss');
315
- devDependencies.push('@tailwindcss/vite');
325
+ rootDevDependencies.push('@tailwindcss/vite');
316
326
  }
317
327
  if (tanstackRouter) {
318
328
  dependencies.push('@tanstack/react-router');
319
- devDependencies.push('@tanstack/router-plugin', '@tanstack/router-generator', '@tanstack/virtual-file-routes', '@tanstack/router-utils');
329
+ rootDevDependencies.push('@tanstack/router-plugin', '@tanstack/router-generator', '@tanstack/virtual-file-routes', '@tanstack/router-utils');
320
330
  }
321
- addDependenciesToPackageJson(tree, withVersions(dependencies), withVersions(devDependencies));
331
+ addDependenciesToPackageJson(tree, withVersions(dependencies), {}, joinPathFragments(libraryRoot, 'package.json'));
332
+ addDependenciesToPackageJson(tree, {}, withVersions(rootDevDependencies));
333
+ // @nx/react's applicationGenerator seeds react/react-dom into the root
334
+ // manifest. The website now declares its own pinned versions, so drop the
335
+ // root copies: without catalogs (npm) the root's floating range resolves to
336
+ // a different version than the website's pin, installing a second React and
337
+ // producing the "Invalid hook call" runtime crash.
338
+ removeDependenciesFromPackageJson(tree, [
339
+ 'react',
340
+ 'react-dom'
341
+ ], []);
322
342
  await addGeneratorMetricsIfApplicable(tree, [
323
343
  REACT_WEBSITE_APP_GENERATOR_INFO
324
344
  ]);
@@ -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 addDependenciesToPackageJson,\n generateFiles,\n joinPathFragments,\n names,\n OverwriteStrategy,\n readProjectConfiguration,\n type Tree,\n updateJson,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { applicationGenerator } from '@nx/react';\nimport { relative, sep } from 'path';\nimport {\n addDestructuredImport,\n addSingleImport,\n applyGritQL,\n} from '../../../utils/ast';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport { resolveIac } from '../../../utils/iac';\nimport { installDependencies } from '../../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../../utils/metrics';\nimport { kebabCase, toClassName, toKebabCase } from '../../../utils/names';\nimport { getNpmScopePrefix, toScopeAlias } from '../../../utils/npm-scope';\nimport {\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n} from '../../../utils/nx';\nimport { sortObjectKeys } from '../../../utils/object';\nimport { getRelativePathToRoot } from '../../../utils/paths';\nimport { getPackageManagerDisplayCommands } from '../../../utils/pkg-manager';\nimport { sharedConstructsGenerator } from '../../../utils/shared-constructs';\nimport {\n PACKAGES_DIR,\n SHARED_SHADCN_DIR,\n} from '../../../utils/shared-constructs-constants';\nimport { sharedShadcnGenerator } from '../../../utils/shared-shadcn';\nimport { type ITsDepVersion, withVersions } from '../../../utils/versions';\nimport { addWebsiteInfra } from '../../../utils/website-constructs/website-constructs';\nimport { configureTsProject } from '../../lib/ts-project-utils';\n// typescript factory imports removed — now using GritQL for vite config transforms\nimport type { TsReactWebsiteGeneratorSchema } from './schema';\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 = toScopeAlias(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 run ${fullyQualifiedName}:load:runtime-config'`,\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 addGeneratorMetadata(\n tree,\n projectConfiguration.name,\n REACT_WEBSITE_APP_GENERATOR_INFO,\n {\n ux,\n framework: 'react',\n infra,\n },\n );\n\n await configureTsProject(tree, {\n dir: websiteContentPath,\n fullyQualifiedName,\n });\n\n if (ux === 'shadcn') {\n await sharedShadcnGenerator(tree);\n }\n\n if (iac) {\n await sharedConstructsGenerator(tree, {\n iac,\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(tree, {\n fullyQualifiedName: e2eFullyQualifiedName,\n dir: e2eRoot,\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(__dirname, 'src/routes'), generatedRouteTree: resolve(__dirname, 'src/routeTree.gen.ts') }), $items]` where { $items <: within `defineConfig($_)`, $items <: not contains `tanstackRouter` }\",\n );\n }\n\n if (tailwind) {\n await applyGritQL(\n tree,\n viteConfigPath,\n '`plugins: [$items]` => `plugins: [$items, tailwindcss()]` where { $items <: within `defineConfig($_)`, $items <: not some `tailwindcss()` }',\n );\n }\n\n // Use Vite's native tsconfig paths resolution (replaces vite-tsconfig-paths)\n await applyGritQL(\n tree,\n viteConfigPath,\n 'or { `defineConfig(() => ({ $props }))` where { $props <: not some `resolve: $_`, $props += `resolve: { tsconfigPaths: true }` }, `defineConfig({ $props })` where { $props <: not some `resolve: $_`, $props += `resolve: { tsconfigPaths: true }` } }',\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 const devDependencies: ITsDepVersion[] = ['@nx/react', '@vitest/ui'];\n\n const dependencies: ITsDepVersion[] = ['react', 'react-dom'];\n\n if (ux === 'cloudscape') {\n dependencies.push(\n '@cloudscape-design/components',\n '@cloudscape-design/board-components',\n '@cloudscape-design/global-styles',\n );\n } else if (ux === 'shadcn') {\n // not required to add any dependencies because dependencies are added by the common/shadcn package.\n }\n\n // Add TailwindCSS dependencies if enabled\n if (tailwind) {\n dependencies.push('tailwindcss');\n devDependencies.push('@tailwindcss/vite');\n }\n if (tanstackRouter) {\n dependencies.push('@tanstack/react-router');\n devDependencies.push(\n '@tanstack/router-plugin',\n '@tanstack/router-generator',\n '@tanstack/virtual-file-routes',\n '@tanstack/router-utils',\n );\n }\n\n addDependenciesToPackageJson(\n tree,\n withVersions(dependencies),\n withVersions(devDependencies),\n );\n\n await addGeneratorMetricsIfApplicable(tree, [\n REACT_WEBSITE_APP_GENERATOR_INFO,\n ]);\n\n await formatFilesInSubtree(tree);\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":["addDependenciesToPackageJson","generateFiles","joinPathFragments","names","OverwriteStrategy","readProjectConfiguration","updateJson","updateProjectConfiguration","applicationGenerator","relative","sep","addDestructuredImport","addSingleImport","applyGritQL","formatFilesInSubtree","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","toKebabCase","getNpmScopePrefix","toScopeAlias","addGeneratorMetadata","getGeneratorInfo","sortObjectKeys","getRelativePathToRoot","getPackageManagerDisplayCommands","sharedConstructsGenerator","PACKAGES_DIR","SHARED_SHADCN_DIR","sharedShadcnGenerator","withVersions","addWebsiteInfra","configureTsProject","SUPPORTED_UX_PROVIDERS","REACT_WEBSITE_APP_GENERATOR_INFO","filename","tsReactWebsiteGenerator","tree","schema","tailwind","tanstackRouter","ux","Error","npmScopePrefix","scopeAlias","websiteNameClassName","name","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","root","sharedShadcnStylesImport","split","join","sharedShadcnTsconfigRef","templateOptions","pkgMgrCmd","appCommonTemplatePath","dirname","appTemplatePath","toLowerCase","overwriteStrategy","KeepExisting","routerCommonTemplatePath","routerTemplatePath","e2eFullyQualifiedName","e2eRoot","viteConfigPath","outDir","tsconfig","compilerOptions","moduleResolution","module","outDirToRootRelativePath","distDir","tsBuildInfoFile","lib","references","filter","ref","path","devDependencies","dependencies","push","preferInstallDependencies","languages","ensureResolvable"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/ts/react-website/app/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n joinPathFragments,\n names,\n OverwriteStrategy,\n readProjectConfiguration,\n removeDependenciesFromPackageJson,\n type Tree,\n updateJson,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { applicationGenerator } from '@nx/react';\nimport { relative, sep } from 'path';\nimport {\n addDestructuredImport,\n addSingleImport,\n applyGritQL,\n} from '../../../utils/ast';\nimport { addDependenciesToPackageJson } from '../../../utils/dependencies';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport { resolveIac } from '../../../utils/iac';\nimport { installDependencies } from '../../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../../utils/metrics';\nimport { kebabCase, toClassName, toKebabCase } from '../../../utils/names';\nimport { getNpmScopePrefix } from '../../../utils/npm-scope';\nimport {\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n} from '../../../utils/nx';\nimport { sortObjectKeys } from '../../../utils/object';\nimport { getRelativePathToRoot } from '../../../utils/paths';\nimport { getPackageManagerDisplayCommands } from '../../../utils/pkg-manager';\nimport { sharedConstructsGenerator } from '../../../utils/shared-constructs';\nimport {\n PACKAGES_DIR,\n SHARED_SHADCN_DIR,\n} from '../../../utils/shared-constructs-constants';\nimport { sharedShadcnGenerator } from '../../../utils/shared-shadcn';\nimport { type ITsDepVersion, withVersions } from '../../../utils/versions';\nimport { addWebsiteInfra } from '../../../utils/website-constructs/website-constructs';\nimport { configureTsProject } from '../../lib/ts-project-utils';\n// typescript factory imports removed — now using GritQL for vite config transforms\nimport type { TsReactWebsiteGeneratorSchema } from './schema';\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 run ${fullyQualifiedName}:load:runtime-config'`,\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 addGeneratorMetadata(\n tree,\n projectConfiguration.name,\n REACT_WEBSITE_APP_GENERATOR_INFO,\n {\n ux,\n framework: 'react',\n infra,\n },\n );\n\n await configureTsProject(tree, {\n dir: websiteContentPath,\n fullyQualifiedName,\n });\n\n if (ux === 'shadcn') {\n await sharedShadcnGenerator(tree);\n }\n\n if (iac) {\n await sharedConstructsGenerator(tree, {\n iac,\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(tree, {\n fullyQualifiedName: e2eFullyQualifiedName,\n dir: e2eRoot,\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(__dirname, 'src/routes'), generatedRouteTree: resolve(__dirname, 'src/routeTree.gen.ts') }), $items]` where { $items <: within `defineConfig($_)`, $items <: not contains `tanstackRouter` }\",\n );\n }\n\n if (tailwind) {\n await applyGritQL(\n tree,\n viteConfigPath,\n '`plugins: [$items]` => `plugins: [$items, tailwindcss()]` where { $items <: within `defineConfig($_)`, $items <: not some `tailwindcss()` }',\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 const dependencies: ITsDepVersion[] = ['react', 'react-dom'];\n // Build/test tooling imported only from vite.config.mts stays at the root.\n const rootDevDependencies: ITsDepVersion[] = ['@nx/react', '@vitest/ui'];\n\n if (ux === 'cloudscape') {\n dependencies.push(\n '@cloudscape-design/components',\n '@cloudscape-design/board-components',\n '@cloudscape-design/global-styles',\n );\n } else if (ux === 'shadcn') {\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 if (tanstackRouter) {\n dependencies.push('lucide-react');\n }\n }\n\n if (tailwind) {\n dependencies.push('tailwindcss');\n rootDevDependencies.push('@tailwindcss/vite');\n }\n if (tanstackRouter) {\n dependencies.push('@tanstack/react-router');\n rootDevDependencies.push(\n '@tanstack/router-plugin',\n '@tanstack/router-generator',\n '@tanstack/virtual-file-routes',\n '@tanstack/router-utils',\n );\n }\n\n addDependenciesToPackageJson(\n tree,\n withVersions(dependencies),\n {},\n joinPathFragments(libraryRoot, 'package.json'),\n );\n addDependenciesToPackageJson(tree, {}, withVersions(rootDevDependencies));\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 await formatFilesInSubtree(tree);\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","addDestructuredImport","addSingleImport","applyGritQL","addDependenciesToPackageJson","formatFilesInSubtree","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","toKebabCase","getNpmScopePrefix","addGeneratorMetadata","getGeneratorInfo","sortObjectKeys","getRelativePathToRoot","getPackageManagerDisplayCommands","sharedConstructsGenerator","PACKAGES_DIR","SHARED_SHADCN_DIR","sharedShadcnGenerator","withVersions","addWebsiteInfra","configureTsProject","SUPPORTED_UX_PROVIDERS","REACT_WEBSITE_APP_GENERATOR_INFO","filename","tsReactWebsiteGenerator","tree","schema","tailwind","tanstackRouter","ux","Error","npmScopePrefix","scopeAlias","websiteNameClassName","name","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","root","sharedShadcnStylesImport","split","join","sharedShadcnTsconfigRef","templateOptions","pkgMgrCmd","appCommonTemplatePath","dirname","appTemplatePath","toLowerCase","overwriteStrategy","KeepExisting","routerCommonTemplatePath","routerTemplatePath","e2eFullyQualifiedName","e2eRoot","viteConfigPath","outDir","tsconfig","compilerOptions","moduleResolution","module","outDirToRootRelativePath","distDir","tsBuildInfoFile","lib","references","filter","ref","path","dependencies","rootDevDependencies","push","preferInstallDependencies","languages","ensureResolvable"],"mappings":"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"}
@@ -118,7 +118,7 @@ import {
118
118
  import { LogGroup, RetentionDays } from 'aws-cdk-lib/aws-logs';
119
119
  import { Construct } from 'constructs';
120
120
  import { RuntimeConfig } from './runtime-config.js';
121
- import { Distribution } from 'aws-cdk-lib/aws-cloudfront';
121
+ import { CfnDistribution, Distribution } from 'aws-cdk-lib/aws-cloudfront';
122
122
  import { suppressRules } from './checkov.js';
123
123
 
124
124
  const WEB_CLIENT_ID = 'WebClient';
@@ -334,9 +334,7 @@ export class UserIdentity extends Construct {
334
334
  const lazilyComputedCallbackUrls = Lazy.list({
335
335
  produce: () =>
336
336
  ['http://localhost:4200', 'http://localhost:4300'].concat(
337
- this.findCloudFrontDistributions().map(
338
- (d) => \`https://\${d.domainName}\`,
339
- ),
337
+ this.findCloudFrontDomainNames().map((domain) => \`https://\${domain}\`),
340
338
  ),
341
339
  });
342
340
 
@@ -386,10 +384,17 @@ export class UserIdentity extends Construct {
386
384
  }).node.addDependency(userPoolClient, userPool, userPoolDomain);
387
385
  };
388
386
 
389
- private findCloudFrontDistributions = (): Distribution[] =>
387
+ // Includes each distribution's default domain name plus any custom domain names (aliases) configured on it.
388
+ private findCloudFrontDomainNames = (): string[] =>
390
389
  Stack.of(this)
391
390
  .node.findAll()
392
- .filter((child) => child instanceof Distribution);
391
+ .filter((child): child is Distribution => child instanceof Distribution)
392
+ .flatMap((d) => {
393
+ const cfnDistribution = d.node.defaultChild as CfnDistribution;
394
+ const distributionConfig =
395
+ cfnDistribution.distributionConfig as CfnDistribution.DistributionConfigProperty;
396
+ return [d.domainName, ...(distributionConfig.aliases ?? [])];
397
+ });
393
398
  }
394
399
  "
395
400
  `;
@@ -241,11 +241,21 @@ resource "aws_cloudfront_distribution" "website" {
241
241
  }
242
242
  }
243
243
 
244
- # Add CloudFront domain to user pool client callback URLs
244
+ # Add CloudFront domain and any custom domain names to user pool client callback URLs.
245
+ # Keyed by statically-known values so for_each keys are resolvable at plan time; the
246
+ # CloudFront domain is only known at apply time, so it appears in the value, not the key.
247
+ locals {
248
+ callback_urls = merge(
249
+ { cloudfront = "https://\${aws_cloudfront_distribution.website.domain_name}" },
250
+ { for domain in var.custom_domain_names : domain => "https://\${domain}" },
251
+ )
252
+ }
253
+
245
254
  module "add_callback_url" {
246
255
  source = "../user-identity/add-callback-url"
256
+ for_each = local.callback_urls
247
257
 
248
- callback_url = "https://\${aws_cloudfront_distribution.website.domain_name}"
258
+ callback_url = each.value
249
259
 
250
260
  depends_on = [aws_cloudfront_distribution.website]
251
261
  }
@@ -1,11 +1,12 @@
1
1
  /**
2
2
  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
- */ import { addDependenciesToPackageJson, generateFiles, joinPathFragments, OverwriteStrategy } from "@nx/devkit";
4
+ */ import { generateFiles, joinPathFragments, OverwriteStrategy } from "@nx/devkit";
5
5
  import { readFileSync } from "fs";
6
6
  import { join } from "path";
7
7
  import { addDestructuredImport, addSingleImport, applyGritQL } from "../../../utils/ast.js";
8
8
  import { addHookResultToRouterProviderContext } from "../../../utils/ast/website.js";
9
+ import { addDependenciesToPackageJson } from "../../../utils/dependencies.js";
9
10
  import { formatFilesInSubtree } from "../../../utils/format.js";
10
11
  import { resolveIac } from "../../../utils/iac.js";
11
12
  import { addIdentityInfra } from "../../../utils/identity-constructs/identity-constructs.js";
@@ -43,7 +44,7 @@ export async function tsReactWebsiteAuthGenerator(tree, options) {
43
44
  addDependenciesToPackageJson(tree, withVersions([
44
45
  'oidc-client-ts',
45
46
  'react-oidc-context'
46
- ]), {});
47
+ ]), {}, joinPathFragments(projectConfig.root, 'package.json'));
47
48
  const mainTsxPath = joinPathFragments(srcRoot, 'main.tsx');
48
49
  await addSingleImport(tree, mainTsxPath, 'CognitoAuth', './components/CognitoAuth');
49
50
  await addHookResultToRouterProviderContext(tree, mainTsxPath, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/ts/react-website/cognito-auth/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n addDependenciesToPackageJson,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type Tree,\n} from '@nx/devkit';\nimport { readFileSync } from 'fs';\nimport { join } from 'path';\nimport {\n addDestructuredImport,\n addSingleImport,\n applyGritQL,\n} from '../../../utils/ast';\nimport { addHookResultToRouterProviderContext } from '../../../utils/ast/website';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport { resolveIac } from '../../../utils/iac';\nimport { addIdentityInfra } from '../../../utils/identity-constructs/identity-constructs';\nimport { installDependencies } from '../../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../../utils/metrics';\nimport { getNpmScope } from '../../../utils/npm-scope';\nimport {\n addComponentGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n readProjectConfigurationUnqualified,\n} from '../../../utils/nx';\nimport { toProjectRelativePath } from '../../../utils/paths';\nimport { sharedConstructsGenerator } from '../../../utils/shared-constructs';\nimport { withVersions } from '../../../utils/versions';\nimport { runtimeConfigGenerator } from '../runtime-config/generator';\nimport type { TsReactWebsiteAuthGeneratorSchema } from './schema';\nimport {\n addCloudscapeAuthMenu,\n addNoneAuthMenu,\n addShadcnAuthMenu,\n deriveCognitoDomainPrefix,\n} from './utils';\n\nconst readGritPattern = (name: string): string =>\n readFileSync(\n join(import.meta.dirname, 'grit', `${name}.grit`),\n 'utf-8',\n ).trim();\n\nexport const COGNITO_AUTH_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport async function tsReactWebsiteAuthGenerator(\n tree: Tree,\n options: TsReactWebsiteAuthGeneratorSchema,\n) {\n const projectConfig = readProjectConfigurationUnqualified(\n tree,\n options.project,\n );\n const srcRoot = projectConfig.sourceRoot;\n\n const cognitoDomain =\n options.cognitoDomain && options.cognitoDomain.length > 0\n ? options.cognitoDomain\n : deriveCognitoDomainPrefix(getNpmScope(tree), projectConfig.name!);\n\n await runtimeConfigGenerator(tree, {\n project: options.project,\n preferInstallDependencies: false,\n });\n\n const iac = await resolveIac(tree, options.iac);\n\n await sharedConstructsGenerator(tree, {\n iac,\n });\n\n await addIdentityInfra(tree, {\n iac,\n allowSignup: options.allowSignup,\n cognitoDomain,\n });\n\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'app'),\n srcRoot,\n options,\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n addDependenciesToPackageJson(\n tree,\n withVersions(['oidc-client-ts', 'react-oidc-context']),\n {},\n );\n\n const mainTsxPath = joinPathFragments(srcRoot, 'main.tsx');\n\n await addSingleImport(\n tree,\n mainTsxPath,\n 'CognitoAuth',\n './components/CognitoAuth',\n );\n\n await addHookResultToRouterProviderContext(tree, mainTsxPath, {\n hook: 'useAuth',\n module: 'react-oidc-context',\n contextProp: 'auth',\n });\n\n const projectConfiguration = readProjectConfigurationUnqualified(\n tree,\n options.project,\n );\n\n const ux = (\n (projectConfiguration.metadata as any)?.ux ?? 'shadcn'\n ).toLowerCase();\n\n await applyGritQL(tree, mainTsxPath, readGritPattern('cognito-auth-wrapper'));\n // Update App Layout\n const appLayoutTsxPath = joinPathFragments(\n srcRoot,\n 'components',\n 'AppLayout',\n 'index.tsx',\n );\n if (tree.exists(appLayoutTsxPath)) {\n await addDestructuredImport(\n tree,\n appLayoutTsxPath,\n ['useAuth'],\n 'react-oidc-context',\n );\n await applyGritQL(\n tree,\n appLayoutTsxPath,\n readGritPattern('app-layout-use-auth'),\n );\n // TODO: update utils if they exist by appending to the array\n // Add a top-level navigation menu that shows the signed-in user's profile and actions\n switch (ux) {\n case 'cloudscape':\n await addCloudscapeAuthMenu(tree, appLayoutTsxPath);\n break;\n case 'shadcn':\n await addShadcnAuthMenu(tree, appLayoutTsxPath);\n break;\n case 'none':\n await addNoneAuthMenu(tree, appLayoutTsxPath);\n break;\n default:\n throw new Error(\n `Top-level navigation menu to show the signed-in user for ux \"${ux}\" is not implemented.`,\n );\n }\n } else {\n console.info(\n `Skipping update to ${appLayoutTsxPath} as it does not exist.`,\n );\n }\n // End update App Layout\n\n addComponentGeneratorMetadata(\n tree,\n options.project,\n COGNITO_AUTH_GENERATOR_INFO,\n toProjectRelativePath(\n projectConfig,\n joinPathFragments(srcRoot, 'components', 'CognitoAuth'),\n ),\n );\n\n await addGeneratorMetricsIfApplicable(tree, [COGNITO_AUTH_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n}\nexport default tsReactWebsiteAuthGenerator;\n"],"names":["addDependenciesToPackageJson","generateFiles","joinPathFragments","OverwriteStrategy","readFileSync","join","addDestructuredImport","addSingleImport","applyGritQL","addHookResultToRouterProviderContext","formatFilesInSubtree","resolveIac","addIdentityInfra","installDependencies","addGeneratorMetricsIfApplicable","getNpmScope","addComponentGeneratorMetadata","getGeneratorInfo","readProjectConfigurationUnqualified","toProjectRelativePath","sharedConstructsGenerator","withVersions","runtimeConfigGenerator","addCloudscapeAuthMenu","addNoneAuthMenu","addShadcnAuthMenu","deriveCognitoDomainPrefix","readGritPattern","name","dirname","trim","COGNITO_AUTH_GENERATOR_INFO","filename","tsReactWebsiteAuthGenerator","tree","options","projectConfig","project","srcRoot","sourceRoot","cognitoDomain","length","preferInstallDependencies","iac","allowSignup","overwriteStrategy","KeepExisting","mainTsxPath","hook","module","contextProp","projectConfiguration","ux","metadata","toLowerCase","appLayoutTsxPath","exists","Error","console","info","languages"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/ts/react-website/cognito-auth/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 OverwriteStrategy,\n type Tree,\n} from '@nx/devkit';\nimport { readFileSync } from 'fs';\nimport { join } from 'path';\nimport {\n addDestructuredImport,\n addSingleImport,\n applyGritQL,\n} from '../../../utils/ast';\nimport { addHookResultToRouterProviderContext } from '../../../utils/ast/website';\nimport { addDependenciesToPackageJson } from '../../../utils/dependencies';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport { resolveIac } from '../../../utils/iac';\nimport { addIdentityInfra } from '../../../utils/identity-constructs/identity-constructs';\nimport { installDependencies } from '../../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../../utils/metrics';\nimport { getNpmScope } from '../../../utils/npm-scope';\nimport {\n addComponentGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n readProjectConfigurationUnqualified,\n} from '../../../utils/nx';\nimport { toProjectRelativePath } from '../../../utils/paths';\nimport { sharedConstructsGenerator } from '../../../utils/shared-constructs';\nimport { withVersions } from '../../../utils/versions';\nimport { runtimeConfigGenerator } from '../runtime-config/generator';\nimport type { TsReactWebsiteAuthGeneratorSchema } from './schema';\nimport {\n addCloudscapeAuthMenu,\n addNoneAuthMenu,\n addShadcnAuthMenu,\n deriveCognitoDomainPrefix,\n} from './utils';\n\nconst readGritPattern = (name: string): string =>\n readFileSync(\n join(import.meta.dirname, 'grit', `${name}.grit`),\n 'utf-8',\n ).trim();\n\nexport const COGNITO_AUTH_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport async function tsReactWebsiteAuthGenerator(\n tree: Tree,\n options: TsReactWebsiteAuthGeneratorSchema,\n) {\n const projectConfig = readProjectConfigurationUnqualified(\n tree,\n options.project,\n );\n const srcRoot = projectConfig.sourceRoot;\n\n const cognitoDomain =\n options.cognitoDomain && options.cognitoDomain.length > 0\n ? options.cognitoDomain\n : deriveCognitoDomainPrefix(getNpmScope(tree), projectConfig.name!);\n\n await runtimeConfigGenerator(tree, {\n project: options.project,\n preferInstallDependencies: false,\n });\n\n const iac = await resolveIac(tree, options.iac);\n\n await sharedConstructsGenerator(tree, {\n iac,\n });\n\n await addIdentityInfra(tree, {\n iac,\n allowSignup: options.allowSignup,\n cognitoDomain,\n });\n\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'app'),\n srcRoot,\n options,\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n addDependenciesToPackageJson(\n tree,\n withVersions(['oidc-client-ts', 'react-oidc-context']),\n {},\n joinPathFragments(projectConfig.root, 'package.json'),\n );\n\n const mainTsxPath = joinPathFragments(srcRoot, 'main.tsx');\n\n await addSingleImport(\n tree,\n mainTsxPath,\n 'CognitoAuth',\n './components/CognitoAuth',\n );\n\n await addHookResultToRouterProviderContext(tree, mainTsxPath, {\n hook: 'useAuth',\n module: 'react-oidc-context',\n contextProp: 'auth',\n });\n\n const projectConfiguration = readProjectConfigurationUnqualified(\n tree,\n options.project,\n );\n\n const ux = (\n (projectConfiguration.metadata as any)?.ux ?? 'shadcn'\n ).toLowerCase();\n\n await applyGritQL(tree, mainTsxPath, readGritPattern('cognito-auth-wrapper'));\n // Update App Layout\n const appLayoutTsxPath = joinPathFragments(\n srcRoot,\n 'components',\n 'AppLayout',\n 'index.tsx',\n );\n if (tree.exists(appLayoutTsxPath)) {\n await addDestructuredImport(\n tree,\n appLayoutTsxPath,\n ['useAuth'],\n 'react-oidc-context',\n );\n await applyGritQL(\n tree,\n appLayoutTsxPath,\n readGritPattern('app-layout-use-auth'),\n );\n // TODO: update utils if they exist by appending to the array\n // Add a top-level navigation menu that shows the signed-in user's profile and actions\n switch (ux) {\n case 'cloudscape':\n await addCloudscapeAuthMenu(tree, appLayoutTsxPath);\n break;\n case 'shadcn':\n await addShadcnAuthMenu(tree, appLayoutTsxPath);\n break;\n case 'none':\n await addNoneAuthMenu(tree, appLayoutTsxPath);\n break;\n default:\n throw new Error(\n `Top-level navigation menu to show the signed-in user for ux \"${ux}\" is not implemented.`,\n );\n }\n } else {\n console.info(\n `Skipping update to ${appLayoutTsxPath} as it does not exist.`,\n );\n }\n // End update App Layout\n\n addComponentGeneratorMetadata(\n tree,\n options.project,\n COGNITO_AUTH_GENERATOR_INFO,\n toProjectRelativePath(\n projectConfig,\n joinPathFragments(srcRoot, 'components', 'CognitoAuth'),\n ),\n );\n\n await addGeneratorMetricsIfApplicable(tree, [COGNITO_AUTH_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n}\nexport default tsReactWebsiteAuthGenerator;\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","readFileSync","join","addDestructuredImport","addSingleImport","applyGritQL","addHookResultToRouterProviderContext","addDependenciesToPackageJson","formatFilesInSubtree","resolveIac","addIdentityInfra","installDependencies","addGeneratorMetricsIfApplicable","getNpmScope","addComponentGeneratorMetadata","getGeneratorInfo","readProjectConfigurationUnqualified","toProjectRelativePath","sharedConstructsGenerator","withVersions","runtimeConfigGenerator","addCloudscapeAuthMenu","addNoneAuthMenu","addShadcnAuthMenu","deriveCognitoDomainPrefix","readGritPattern","name","dirname","trim","COGNITO_AUTH_GENERATOR_INFO","filename","tsReactWebsiteAuthGenerator","tree","options","projectConfig","project","srcRoot","sourceRoot","cognitoDomain","length","preferInstallDependencies","iac","allowSignup","overwriteStrategy","KeepExisting","root","mainTsxPath","hook","module","contextProp","projectConfiguration","ux","metadata","toLowerCase","appLayoutTsxPath","exists","Error","console","info","languages"],"mappings":"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"}
@@ -6,7 +6,7 @@ import { addSingleImport, applyGritQL, matchGritQL } from "../../../utils/ast.js
6
6
  import { addHookResultToRouterProviderContext } from "../../../utils/ast/website.js";
7
7
  import { formatFilesInSubtree } from "../../../utils/format.js";
8
8
  import { addGeneratorMetricsIfApplicable } from "../../../utils/metrics.js";
9
- import { getNpmScopePrefix, toScopeAlias } from "../../../utils/npm-scope.js";
9
+ import { getNpmScopePrefix } from "../../../utils/npm-scope.js";
10
10
  import { addComponentGeneratorMetadata, getGeneratorInfo, readProjectConfigurationUnqualified } from "../../../utils/nx.js";
11
11
  import { toProjectRelativePath } from "../../../utils/paths.js";
12
12
  export const RUNTIME_CONFIG_GENERATOR_INFO = getGeneratorInfo(import.meta.filename);
@@ -26,7 +26,7 @@ export async function runtimeConfigGenerator(tree, options) {
26
26
  generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'app'), srcRoot, {
27
27
  ...options,
28
28
  npmScopePrefix,
29
- scopeAlias: toScopeAlias(npmScopePrefix)
29
+ scopeAlias: npmScopePrefix
30
30
  }, {
31
31
  overwriteStrategy: OverwriteStrategy.KeepExisting
32
32
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/ts/react-website/runtime-config/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 OverwriteStrategy,\n type Tree,\n} from '@nx/devkit';\nimport { addSingleImport, applyGritQL, matchGritQL } from '../../../utils/ast';\nimport { addHookResultToRouterProviderContext } from '../../../utils/ast/website';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport { addGeneratorMetricsIfApplicable } from '../../../utils/metrics';\nimport { getNpmScopePrefix, toScopeAlias } from '../../../utils/npm-scope';\nimport {\n addComponentGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n readProjectConfigurationUnqualified,\n} from '../../../utils/nx';\nimport { toProjectRelativePath } from '../../../utils/paths';\nimport type { RuntimeConfigGeneratorSchema } from './schema';\n\nexport const RUNTIME_CONFIG_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport async function runtimeConfigGenerator(\n tree: Tree,\n options: RuntimeConfigGeneratorSchema,\n) {\n const projectConfig = readProjectConfigurationUnqualified(\n tree,\n options.project,\n );\n const srcRoot = projectConfig.sourceRoot;\n const mainTsxPath = joinPathFragments(srcRoot, 'main.tsx');\n if (!tree.exists(mainTsxPath)) {\n throw new Error(\n `Can only run this generator on a project which contains ${mainTsxPath}`,\n );\n }\n\n const runtimeConfigPath = joinPathFragments(\n srcRoot,\n 'components',\n 'RuntimeConfig',\n 'index.tsx',\n );\n if (tree.exists(runtimeConfigPath)) {\n console.debug('Runtime config already exists, skipping generation');\n return;\n }\n\n const npmScopePrefix = getNpmScopePrefix(tree);\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'app'),\n srcRoot,\n {\n ...options,\n npmScopePrefix,\n scopeAlias: toScopeAlias(npmScopePrefix),\n },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // Only add RuntimeConfigProvider wrapper and import if not already present in JSX\n const alreadyWrapped = await matchGritQL(\n tree,\n mainTsxPath,\n '`<RuntimeConfigProvider>$_</RuntimeConfigProvider>`',\n );\n if (!alreadyWrapped) {\n await addSingleImport(\n tree,\n mainTsxPath,\n 'RuntimeConfigProvider',\n './components/RuntimeConfig',\n );\n\n const wrapped = await applyGritQL(\n tree,\n mainTsxPath,\n '`<App />` => `<RuntimeConfigProvider><App /></RuntimeConfigProvider>`',\n );\n\n if (!wrapped) {\n throw new Error('Could not locate the App element in main.tsx');\n }\n }\n\n await addHookResultToRouterProviderContext(tree, mainTsxPath, {\n hook: 'useRuntimeConfig',\n module: './hooks/useRuntimeConfig',\n contextProp: 'runtimeConfig',\n });\n\n addComponentGeneratorMetadata(\n tree,\n options.project,\n RUNTIME_CONFIG_GENERATOR_INFO,\n toProjectRelativePath(\n projectConfig,\n joinPathFragments(srcRoot, 'components', 'RuntimeConfig'),\n ),\n );\n\n await addGeneratorMetricsIfApplicable(tree, [RUNTIME_CONFIG_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n}\nexport default runtimeConfigGenerator;\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","addSingleImport","applyGritQL","matchGritQL","addHookResultToRouterProviderContext","formatFilesInSubtree","addGeneratorMetricsIfApplicable","getNpmScopePrefix","toScopeAlias","addComponentGeneratorMetadata","getGeneratorInfo","readProjectConfigurationUnqualified","toProjectRelativePath","RUNTIME_CONFIG_GENERATOR_INFO","filename","runtimeConfigGenerator","tree","options","projectConfig","project","srcRoot","sourceRoot","mainTsxPath","exists","Error","runtimeConfigPath","console","debug","npmScopePrefix","dirname","scopeAlias","overwriteStrategy","KeepExisting","alreadyWrapped","wrapped","hook","module","contextProp"],"mappings":"AAAA;;;CAGC,GACD,SACEA,aAAa,EACbC,iBAAiB,EACjBC,iBAAiB,QAEZ,aAAa;AACpB,SAASC,eAAe,EAAEC,WAAW,EAAEC,WAAW,QAAQ,wBAAqB;AAC/E,SAASC,oCAAoC,QAAQ,gCAA6B;AAClF,SAASC,oBAAoB,QAAQ,2BAAwB;AAC7D,SAASC,+BAA+B,QAAQ,4BAAyB;AACzE,SAASC,iBAAiB,EAAEC,YAAY,QAAQ,8BAA2B;AAC3E,SACEC,6BAA6B,EAC7BC,gBAAgB,EAEhBC,mCAAmC,QAC9B,uBAAoB;AAC3B,SAASC,qBAAqB,QAAQ,0BAAuB;AAG7D,OAAO,MAAMC,gCAAiDH,iBAC5D,YAAYI,QAAQ,EACpB;AAEF,OAAO,eAAeC,uBACpBC,IAAU,EACVC,OAAqC;IAErC,MAAMC,gBAAgBP,oCACpBK,MACAC,QAAQE,OAAO;IAEjB,MAAMC,UAAUF,cAAcG,UAAU;IACxC,MAAMC,cAAcvB,kBAAkBqB,SAAS;IAC/C,IAAI,CAACJ,KAAKO,MAAM,CAACD,cAAc;QAC7B,MAAM,IAAIE,MACR,CAAC,wDAAwD,EAAEF,aAAa;IAE5E;IAEA,MAAMG,oBAAoB1B,kBACxBqB,SACA,cACA,iBACA;IAEF,IAAIJ,KAAKO,MAAM,CAACE,oBAAoB;QAClCC,QAAQC,KAAK,CAAC;QACd;IACF;IAEA,MAAMC,iBAAiBrB,kBAAkBS;IACzClB,cACEkB,MACAjB,kBAAkB,YAAY8B,OAAO,EAAE,SAAS,QAChDT,SACA;QACE,GAAGH,OAAO;QACVW;QACAE,YAAYtB,aAAaoB;IAC3B,GACA;QACEG,mBAAmB/B,kBAAkBgC,YAAY;IACnD;IAGF,kFAAkF;IAClF,MAAMC,iBAAiB,MAAM9B,YAC3Ba,MACAM,aACA;IAEF,IAAI,CAACW,gBAAgB;QACnB,MAAMhC,gBACJe,MACAM,aACA,yBACA;QAGF,MAAMY,UAAU,MAAMhC,YACpBc,MACAM,aACA;QAGF,IAAI,CAACY,SAAS;YACZ,MAAM,IAAIV,MAAM;QAClB;IACF;IAEA,MAAMpB,qCAAqCY,MAAMM,aAAa;QAC5Da,MAAM;QACNC,QAAQ;QACRC,aAAa;IACf;IAEA5B,8BACEO,MACAC,QAAQE,OAAO,EACfN,+BACAD,sBACEM,eACAnB,kBAAkBqB,SAAS,cAAc;IAI7C,MAAMd,gCAAgCU,MAAM;QAACH;KAA8B;IAE3E,MAAMR,qBAAqBW;AAC7B;AACA,eAAeD,uBAAuB"}
1
+ {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/ts/react-website/runtime-config/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 OverwriteStrategy,\n type Tree,\n} from '@nx/devkit';\nimport { addSingleImport, applyGritQL, matchGritQL } from '../../../utils/ast';\nimport { addHookResultToRouterProviderContext } from '../../../utils/ast/website';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport { addGeneratorMetricsIfApplicable } from '../../../utils/metrics';\nimport { getNpmScopePrefix } from '../../../utils/npm-scope';\nimport {\n addComponentGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n readProjectConfigurationUnqualified,\n} from '../../../utils/nx';\nimport { toProjectRelativePath } from '../../../utils/paths';\nimport type { RuntimeConfigGeneratorSchema } from './schema';\n\nexport const RUNTIME_CONFIG_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport async function runtimeConfigGenerator(\n tree: Tree,\n options: RuntimeConfigGeneratorSchema,\n) {\n const projectConfig = readProjectConfigurationUnqualified(\n tree,\n options.project,\n );\n const srcRoot = projectConfig.sourceRoot;\n const mainTsxPath = joinPathFragments(srcRoot, 'main.tsx');\n if (!tree.exists(mainTsxPath)) {\n throw new Error(\n `Can only run this generator on a project which contains ${mainTsxPath}`,\n );\n }\n\n const runtimeConfigPath = joinPathFragments(\n srcRoot,\n 'components',\n 'RuntimeConfig',\n 'index.tsx',\n );\n if (tree.exists(runtimeConfigPath)) {\n console.debug('Runtime config already exists, skipping generation');\n return;\n }\n\n const npmScopePrefix = getNpmScopePrefix(tree);\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'app'),\n srcRoot,\n {\n ...options,\n npmScopePrefix,\n scopeAlias: npmScopePrefix,\n },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // Only add RuntimeConfigProvider wrapper and import if not already present in JSX\n const alreadyWrapped = await matchGritQL(\n tree,\n mainTsxPath,\n '`<RuntimeConfigProvider>$_</RuntimeConfigProvider>`',\n );\n if (!alreadyWrapped) {\n await addSingleImport(\n tree,\n mainTsxPath,\n 'RuntimeConfigProvider',\n './components/RuntimeConfig',\n );\n\n const wrapped = await applyGritQL(\n tree,\n mainTsxPath,\n '`<App />` => `<RuntimeConfigProvider><App /></RuntimeConfigProvider>`',\n );\n\n if (!wrapped) {\n throw new Error('Could not locate the App element in main.tsx');\n }\n }\n\n await addHookResultToRouterProviderContext(tree, mainTsxPath, {\n hook: 'useRuntimeConfig',\n module: './hooks/useRuntimeConfig',\n contextProp: 'runtimeConfig',\n });\n\n addComponentGeneratorMetadata(\n tree,\n options.project,\n RUNTIME_CONFIG_GENERATOR_INFO,\n toProjectRelativePath(\n projectConfig,\n joinPathFragments(srcRoot, 'components', 'RuntimeConfig'),\n ),\n );\n\n await addGeneratorMetricsIfApplicable(tree, [RUNTIME_CONFIG_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n}\nexport default runtimeConfigGenerator;\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","addSingleImport","applyGritQL","matchGritQL","addHookResultToRouterProviderContext","formatFilesInSubtree","addGeneratorMetricsIfApplicable","getNpmScopePrefix","addComponentGeneratorMetadata","getGeneratorInfo","readProjectConfigurationUnqualified","toProjectRelativePath","RUNTIME_CONFIG_GENERATOR_INFO","filename","runtimeConfigGenerator","tree","options","projectConfig","project","srcRoot","sourceRoot","mainTsxPath","exists","Error","runtimeConfigPath","console","debug","npmScopePrefix","dirname","scopeAlias","overwriteStrategy","KeepExisting","alreadyWrapped","wrapped","hook","module","contextProp"],"mappings":"AAAA;;;CAGC,GACD,SACEA,aAAa,EACbC,iBAAiB,EACjBC,iBAAiB,QAEZ,aAAa;AACpB,SAASC,eAAe,EAAEC,WAAW,EAAEC,WAAW,QAAQ,wBAAqB;AAC/E,SAASC,oCAAoC,QAAQ,gCAA6B;AAClF,SAASC,oBAAoB,QAAQ,2BAAwB;AAC7D,SAASC,+BAA+B,QAAQ,4BAAyB;AACzE,SAASC,iBAAiB,QAAQ,8BAA2B;AAC7D,SACEC,6BAA6B,EAC7BC,gBAAgB,EAEhBC,mCAAmC,QAC9B,uBAAoB;AAC3B,SAASC,qBAAqB,QAAQ,0BAAuB;AAG7D,OAAO,MAAMC,gCAAiDH,iBAC5D,YAAYI,QAAQ,EACpB;AAEF,OAAO,eAAeC,uBACpBC,IAAU,EACVC,OAAqC;IAErC,MAAMC,gBAAgBP,oCACpBK,MACAC,QAAQE,OAAO;IAEjB,MAAMC,UAAUF,cAAcG,UAAU;IACxC,MAAMC,cAActB,kBAAkBoB,SAAS;IAC/C,IAAI,CAACJ,KAAKO,MAAM,CAACD,cAAc;QAC7B,MAAM,IAAIE,MACR,CAAC,wDAAwD,EAAEF,aAAa;IAE5E;IAEA,MAAMG,oBAAoBzB,kBACxBoB,SACA,cACA,iBACA;IAEF,IAAIJ,KAAKO,MAAM,CAACE,oBAAoB;QAClCC,QAAQC,KAAK,CAAC;QACd;IACF;IAEA,MAAMC,iBAAiBpB,kBAAkBQ;IACzCjB,cACEiB,MACAhB,kBAAkB,YAAY6B,OAAO,EAAE,SAAS,QAChDT,SACA;QACE,GAAGH,OAAO;QACVW;QACAE,YAAYF;IACd,GACA;QACEG,mBAAmB9B,kBAAkB+B,YAAY;IACnD;IAGF,kFAAkF;IAClF,MAAMC,iBAAiB,MAAM7B,YAC3BY,MACAM,aACA;IAEF,IAAI,CAACW,gBAAgB;QACnB,MAAM/B,gBACJc,MACAM,aACA,yBACA;QAGF,MAAMY,UAAU,MAAM/B,YACpBa,MACAM,aACA;QAGF,IAAI,CAACY,SAAS;YACZ,MAAM,IAAIV,MAAM;QAClB;IACF;IAEA,MAAMnB,qCAAqCW,MAAMM,aAAa;QAC5Da,MAAM;QACNC,QAAQ;QACRC,aAAa;IACf;IAEA5B,8BACEO,MACAC,QAAQE,OAAO,EACfN,+BACAD,sBACEM,eACAlB,kBAAkBoB,SAAS,cAAc;IAI7C,MAAMb,gCAAgCS,MAAM;QAACH;KAA8B;IAE3E,MAAMP,qBAAqBU;AAC7B;AACA,eAAeD,uBAAuB"}
@@ -1,11 +1,12 @@
1
1
  /**
2
2
  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
- */ import { getProjects, joinPathFragments, readJson, updateJson } from "@nx/devkit";
4
+ */ import { createProjectGraphAsync, getProjects, joinPathFragments, readJson, updateJson } from "@nx/devkit";
5
5
  import { relative } from "path";
6
6
  import PackageJson from "../../../package.json" with {
7
7
  type: 'json'
8
8
  };
9
+ import { getLocalDependencySpecifier } from "../../utils/dependencies.js";
9
10
  import { getGeneratorInfo } from "../../utils/nx.js";
10
11
  export const TS_SYNC_GENERATOR_INFO = getGeneratorInfo(import.meta.filename);
11
12
  export const SYNC_GENERATOR_NAME = `${PackageJson.name}:${TS_SYNC_GENERATOR_INFO.id}`;
@@ -31,13 +32,90 @@ export const tsSyncGeneratorGenerator = async (tree)=>{
31
32
  }
32
33
  }
33
34
  }
34
- if (Object.keys(changesByConfigFile).length === 0) {
35
+ const localSpecifier = getLocalDependencySpecifier(tree);
36
+ const localDepChanges = await syncLocalProjectDependencies(tree, localSpecifier);
37
+ const messages = [];
38
+ if (Object.keys(changesByConfigFile).length > 0) {
39
+ messages.push(buildOutOfSyncMessage(changesByConfigFile));
40
+ }
41
+ if (Object.keys(localDepChanges).length > 0) {
42
+ messages.push(buildLocalDepOutOfSyncMessage(localDepChanges, localSpecifier));
43
+ }
44
+ if (messages.length === 0) {
35
45
  return {};
36
46
  }
37
47
  return {
38
- outOfSyncMessage: buildOutOfSyncMessage(changesByConfigFile)
48
+ outOfSyncMessage: messages.join('\n\n')
39
49
  };
40
50
  };
51
+ /**
52
+ * Declare each project's local workspace dependencies in its own package.json
53
+ * so `noUndeclaredDependencies` passes. Edges come from the Nx project graph
54
+ * (the same import analysis `@nx/js:typescript-sync` uses). Returns the
55
+ * packages added per project manifest.
56
+ */ const syncLocalProjectDependencies = async (tree, localSpecifier)=>{
57
+ const projectGraph = await createProjectGraphAsync();
58
+ const projectInfoByName = collectProjectInfo(tree, projectGraph);
59
+ const addedByManifest = {};
60
+ for (const [projectName, info] of projectInfoByName){
61
+ // Local workspace projects this one depends on (excludes external packages
62
+ // and implicit edges).
63
+ const dependencyNames = (projectGraph.dependencies[projectName] ?? []).filter((dep)=>dep.type !== 'implicit' && projectInfoByName.has(dep.target) && dep.target !== projectName).map((dep)=>projectInfoByName.get(dep.target).packageName);
64
+ if (dependencyNames.length === 0) {
65
+ continue;
66
+ }
67
+ const added = [];
68
+ updateJson(tree, info.packageJsonPath, (json)=>{
69
+ const dependencies = {
70
+ ...json.dependencies ?? {}
71
+ };
72
+ const devDependencies = json.devDependencies ?? {};
73
+ for (const name of [
74
+ ...new Set(dependencyNames)
75
+ ].sort()){
76
+ // Already declared in either list — leave as-is.
77
+ if (dependencies[name] || devDependencies[name]) {
78
+ continue;
79
+ }
80
+ dependencies[name] = localSpecifier;
81
+ added.push(name);
82
+ }
83
+ return added.length > 0 ? {
84
+ ...json,
85
+ dependencies
86
+ } : json;
87
+ });
88
+ if (added.length > 0) {
89
+ addedByManifest[info.packageJsonPath] = added;
90
+ }
91
+ }
92
+ return addedByManifest;
93
+ };
94
+ /**
95
+ * Index workspace projects with a named package.json by project name, so graph
96
+ * edges (keyed by project name) resolve to the manifest to declare the dep in.
97
+ */ const collectProjectInfo = (tree, projectGraph)=>{
98
+ const infoByName = new Map();
99
+ for (const [name, node] of Object.entries(projectGraph.nodes)){
100
+ const root = node.data.root;
101
+ if (!root) {
102
+ continue;
103
+ }
104
+ const packageJsonPath = joinPathFragments(root, 'package.json');
105
+ if (!tree.exists(packageJsonPath)) {
106
+ continue;
107
+ }
108
+ const packageName = readJson(tree, packageJsonPath).name;
109
+ if (packageName) {
110
+ infoByName.set(name, {
111
+ packageName,
112
+ packageJsonPath
113
+ });
114
+ }
115
+ }
116
+ return infoByName;
117
+ };
118
+ const buildLocalDepOutOfSyncMessage = (addedByManifest, localSpecifier)=>`Local project dependencies are out of sync. The following workspace dependencies will be declared:\n${Object.entries(addedByManifest).map(([manifest, names])=>`${manifest}:\n${names.map((name)=>`- ${name}: ${localSpecifier}`).join('\n')}`).join('\n\n')}`;
41
119
  export default tsSyncGeneratorGenerator;
42
120
  const readBaseTsConfigPaths = (tree)=>{
43
121
  const baseConfigPath = [