@aws/nx-plugin 1.0.0-rc.50 → 1.0.0-rc.52

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 (32) hide show
  1. package/generators.json +7 -0
  2. package/migrations.json +5 -0
  3. package/package.json +1 -1
  4. package/src/internal/test-matrix/generator.d.ts +29 -0
  5. package/src/internal/test-matrix/generator.js +660 -0
  6. package/src/internal/test-matrix/generator.js.map +1 -0
  7. package/src/internal/test-matrix/schema.d.js +6 -0
  8. package/src/internal/test-matrix/schema.d.js.map +1 -0
  9. package/src/internal/test-matrix/schema.d.ts +12 -0
  10. package/src/internal/test-matrix/schema.json +21 -0
  11. package/src/migrations/latest/user-identity-waf-allow-localhost-callback/migration.d.ts +6 -0
  12. package/src/migrations/latest/user-identity-waf-allow-localhost-callback/migration.js +217 -0
  13. package/src/migrations/latest/user-identity-waf-allow-localhost-callback/migration.js.map +1 -0
  14. package/src/sdk/py.d.ts +2 -0
  15. package/src/sdk/py.js +1 -0
  16. package/src/sdk/py.js.map +1 -1
  17. package/src/sdk/ts.d.ts +2 -0
  18. package/src/sdk/ts.js +2 -0
  19. package/src/sdk/ts.js.map +1 -1
  20. package/src/sdk/utils/format.d.ts +1 -1
  21. package/src/sdk/utils/format.js.map +1 -1
  22. package/src/ts/rdb/generator.js +19 -1
  23. package/src/ts/rdb/generator.js.map +1 -1
  24. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +66 -66
  25. package/src/ts/react-website/app/generator.js +10 -1
  26. package/src/ts/react-website/app/generator.js.map +1 -1
  27. package/src/ts/react-website/cognito-auth/__snapshots__/generator.spec.ts.snap +25 -3
  28. package/src/utils/format.d.ts +11 -1
  29. package/src/utils/format.js +25 -2
  30. package/src/utils/format.js.map +1 -1
  31. package/src/utils/identity-constructs/files/cdk/core/user-identity.ts.template +25 -3
  32. package/src/utils/identity-constructs/files/terraform/core/user-identity/identity/identity.tf.template +25 -8
@@ -4455,55 +4455,55 @@ exports[`react-website generator > Tanstack router integration > should generate
4455
4455
  // You should NOT make any changes in this file as it will be overwritten.
4456
4456
  // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
4457
4457
 
4458
- import { Route as rootRouteImport } from './routes/__root';
4459
- import { Route as IndexRouteImport } from './routes/index';
4458
+ import { Route as rootRouteImport } from './routes/__root'
4459
+ import { Route as IndexRouteImport } from './routes/index'
4460
4460
 
4461
4461
  const IndexRoute = IndexRouteImport.update({
4462
4462
  id: '/',
4463
4463
  path: '/',
4464
4464
  getParentRoute: () => rootRouteImport,
4465
- } as any);
4465
+ } as any)
4466
4466
 
4467
4467
  export interface FileRoutesByFullPath {
4468
- '/': typeof IndexRoute;
4468
+ '/': typeof IndexRoute
4469
4469
  }
4470
4470
  export interface FileRoutesByTo {
4471
- '/': typeof IndexRoute;
4471
+ '/': typeof IndexRoute
4472
4472
  }
4473
4473
  export interface FileRoutesById {
4474
- __root__: typeof rootRouteImport;
4475
- '/': typeof IndexRoute;
4474
+ __root__: typeof rootRouteImport
4475
+ '/': typeof IndexRoute
4476
4476
  }
4477
4477
  export interface FileRouteTypes {
4478
- fileRoutesByFullPath: FileRoutesByFullPath;
4479
- fullPaths: '/';
4480
- fileRoutesByTo: FileRoutesByTo;
4481
- to: '/';
4482
- id: '__root__' | '/';
4483
- fileRoutesById: FileRoutesById;
4478
+ fileRoutesByFullPath: FileRoutesByFullPath
4479
+ fullPaths: '/'
4480
+ fileRoutesByTo: FileRoutesByTo
4481
+ to: '/'
4482
+ id: '__root__' | '/'
4483
+ fileRoutesById: FileRoutesById
4484
4484
  }
4485
4485
  export interface RootRouteChildren {
4486
- IndexRoute: typeof IndexRoute;
4486
+ IndexRoute: typeof IndexRoute
4487
4487
  }
4488
4488
 
4489
4489
  declare module '@tanstack/react-router' {
4490
4490
  interface FileRoutesByPath {
4491
4491
  '/': {
4492
- id: '/';
4493
- path: '/';
4494
- fullPath: '/';
4495
- preLoaderRoute: typeof IndexRouteImport;
4496
- parentRoute: typeof rootRouteImport;
4497
- };
4492
+ id: '/'
4493
+ path: '/'
4494
+ fullPath: '/'
4495
+ preLoaderRoute: typeof IndexRouteImport
4496
+ parentRoute: typeof rootRouteImport
4497
+ }
4498
4498
  }
4499
4499
  }
4500
4500
 
4501
4501
  const rootRouteChildren: RootRouteChildren = {
4502
4502
  IndexRoute: IndexRoute,
4503
- };
4503
+ }
4504
4504
  export const routeTree = rootRouteImport
4505
4505
  ._addFileChildren(rootRouteChildren)
4506
- ._addFileTypes<FileRouteTypes>();
4506
+ ._addFileTypes<FileRouteTypes>()
4507
4507
  "
4508
4508
  `;
4509
4509
 
@@ -5801,55 +5801,55 @@ exports[`react-website generator ux tests > Cloudscape > should update package.j
5801
5801
  // You should NOT make any changes in this file as it will be overwritten.
5802
5802
  // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
5803
5803
 
5804
- import { Route as rootRouteImport } from './routes/__root';
5805
- import { Route as IndexRouteImport } from './routes/index';
5804
+ import { Route as rootRouteImport } from './routes/__root'
5805
+ import { Route as IndexRouteImport } from './routes/index'
5806
5806
 
5807
5807
  const IndexRoute = IndexRouteImport.update({
5808
5808
  id: '/',
5809
5809
  path: '/',
5810
5810
  getParentRoute: () => rootRouteImport,
5811
- } as any);
5811
+ } as any)
5812
5812
 
5813
5813
  export interface FileRoutesByFullPath {
5814
- '/': typeof IndexRoute;
5814
+ '/': typeof IndexRoute
5815
5815
  }
5816
5816
  export interface FileRoutesByTo {
5817
- '/': typeof IndexRoute;
5817
+ '/': typeof IndexRoute
5818
5818
  }
5819
5819
  export interface FileRoutesById {
5820
- __root__: typeof rootRouteImport;
5821
- '/': typeof IndexRoute;
5820
+ __root__: typeof rootRouteImport
5821
+ '/': typeof IndexRoute
5822
5822
  }
5823
5823
  export interface FileRouteTypes {
5824
- fileRoutesByFullPath: FileRoutesByFullPath;
5825
- fullPaths: '/';
5826
- fileRoutesByTo: FileRoutesByTo;
5827
- to: '/';
5828
- id: '__root__' | '/';
5829
- fileRoutesById: FileRoutesById;
5824
+ fileRoutesByFullPath: FileRoutesByFullPath
5825
+ fullPaths: '/'
5826
+ fileRoutesByTo: FileRoutesByTo
5827
+ to: '/'
5828
+ id: '__root__' | '/'
5829
+ fileRoutesById: FileRoutesById
5830
5830
  }
5831
5831
  export interface RootRouteChildren {
5832
- IndexRoute: typeof IndexRoute;
5832
+ IndexRoute: typeof IndexRoute
5833
5833
  }
5834
5834
 
5835
5835
  declare module '@tanstack/react-router' {
5836
5836
  interface FileRoutesByPath {
5837
5837
  '/': {
5838
- id: '/';
5839
- path: '/';
5840
- fullPath: '/';
5841
- preLoaderRoute: typeof IndexRouteImport;
5842
- parentRoute: typeof rootRouteImport;
5843
- };
5838
+ id: '/'
5839
+ path: '/'
5840
+ fullPath: '/'
5841
+ preLoaderRoute: typeof IndexRouteImport
5842
+ parentRoute: typeof rootRouteImport
5843
+ }
5844
5844
  }
5845
5845
  }
5846
5846
 
5847
5847
  const rootRouteChildren: RootRouteChildren = {
5848
5848
  IndexRoute: IndexRoute,
5849
- };
5849
+ }
5850
5850
  export const routeTree = rootRouteImport
5851
5851
  ._addFileChildren(rootRouteChildren)
5852
- ._addFileTypes<FileRouteTypes>();
5852
+ ._addFileTypes<FileRouteTypes>()
5853
5853
  "
5854
5854
  `;
5855
5855
 
@@ -6172,55 +6172,55 @@ exports[`react-website generator ux tests > Shadcn > should update package.json
6172
6172
  // You should NOT make any changes in this file as it will be overwritten.
6173
6173
  // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
6174
6174
 
6175
- import { Route as rootRouteImport } from './routes/__root';
6176
- import { Route as IndexRouteImport } from './routes/index';
6175
+ import { Route as rootRouteImport } from './routes/__root'
6176
+ import { Route as IndexRouteImport } from './routes/index'
6177
6177
 
6178
6178
  const IndexRoute = IndexRouteImport.update({
6179
6179
  id: '/',
6180
6180
  path: '/',
6181
6181
  getParentRoute: () => rootRouteImport,
6182
- } as any);
6182
+ } as any)
6183
6183
 
6184
6184
  export interface FileRoutesByFullPath {
6185
- '/': typeof IndexRoute;
6185
+ '/': typeof IndexRoute
6186
6186
  }
6187
6187
  export interface FileRoutesByTo {
6188
- '/': typeof IndexRoute;
6188
+ '/': typeof IndexRoute
6189
6189
  }
6190
6190
  export interface FileRoutesById {
6191
- __root__: typeof rootRouteImport;
6192
- '/': typeof IndexRoute;
6191
+ __root__: typeof rootRouteImport
6192
+ '/': typeof IndexRoute
6193
6193
  }
6194
6194
  export interface FileRouteTypes {
6195
- fileRoutesByFullPath: FileRoutesByFullPath;
6196
- fullPaths: '/';
6197
- fileRoutesByTo: FileRoutesByTo;
6198
- to: '/';
6199
- id: '__root__' | '/';
6200
- fileRoutesById: FileRoutesById;
6195
+ fileRoutesByFullPath: FileRoutesByFullPath
6196
+ fullPaths: '/'
6197
+ fileRoutesByTo: FileRoutesByTo
6198
+ to: '/'
6199
+ id: '__root__' | '/'
6200
+ fileRoutesById: FileRoutesById
6201
6201
  }
6202
6202
  export interface RootRouteChildren {
6203
- IndexRoute: typeof IndexRoute;
6203
+ IndexRoute: typeof IndexRoute
6204
6204
  }
6205
6205
 
6206
6206
  declare module '@tanstack/react-router' {
6207
6207
  interface FileRoutesByPath {
6208
6208
  '/': {
6209
- id: '/';
6210
- path: '/';
6211
- fullPath: '/';
6212
- preLoaderRoute: typeof IndexRouteImport;
6213
- parentRoute: typeof rootRouteImport;
6214
- };
6209
+ id: '/'
6210
+ path: '/'
6211
+ fullPath: '/'
6212
+ preLoaderRoute: typeof IndexRouteImport
6213
+ parentRoute: typeof rootRouteImport
6214
+ }
6215
6215
  }
6216
6216
  }
6217
6217
 
6218
6218
  const rootRouteChildren: RootRouteChildren = {
6219
6219
  IndexRoute: IndexRoute,
6220
- };
6220
+ }
6221
6221
  export const routeTree = rootRouteImport
6222
6222
  ._addFileChildren(rootRouteChildren)
6223
- ._addFileTypes<FileRouteTypes>();
6223
+ ._addFileTypes<FileRouteTypes>()
6224
6224
  "
6225
6225
  `;
6226
6226
 
@@ -342,7 +342,16 @@ export async function tsReactWebsiteGenerator(tree, schema) {
342
342
  await addGeneratorMetricsIfApplicable(tree, [
343
343
  REACT_WEBSITE_APP_GENERATOR_INFO
344
344
  ]);
345
- await formatFilesInSubtree(tree);
345
+ // TanStack Router's vite plugin owns this website's route tree and rewrites it
346
+ // in its own (unformatted) shape whenever the config is loaded — including when
347
+ // Nx computes the project graph — so formatting it here would only make
348
+ // generation non-idempotent. The vended biome config excludes `**/*.gen.*`, so
349
+ // the workspace's own `format` target leaves it alone too.
350
+ await formatFilesInSubtree(tree, undefined, {
351
+ ignore: tanstackRouter ? [
352
+ joinPathFragments(libraryRoot, 'src', 'routeTree.gen.ts')
353
+ ] : []
354
+ });
346
355
  // The generated vite.config.mts imports these, and Nx's inferred `@nx/vite`
347
356
  // plugin loads that config when computing the project graph — so they must be
348
357
  // installed even if the caller would otherwise prefer to defer.
@@ -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 {\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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"}
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 // 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","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","ignore","preferInstallDependencies","languages","ensureResolvable"],"mappings":"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"}
@@ -125,6 +125,9 @@ import { suppressRules } from './checkov.js';
125
125
 
126
126
  const WEB_CLIENT_ID = 'WebClient';
127
127
 
128
+ /** Local dev server origins permitted to complete the sign-in redirect */
129
+ const LOCAL_CALLBACK_URLS = ['http://localhost:4200', 'http://localhost:4300'];
130
+
128
131
  export interface UserIdentityProps {
129
132
  /**
130
133
  * Whether to enable AWS WAFv2 with the default managed ruleset
@@ -160,7 +163,11 @@ export class UserIdentity extends Construct {
160
163
  this.userPool = this.createUserPool();
161
164
 
162
165
  if (enableWaf) {
163
- this.webAcl = this.createWebAcl(id, this.userPool);
166
+ this.webAcl = this.createWebAcl(
167
+ id,
168
+ this.userPool,
169
+ LOCAL_CALLBACK_URLS.length > 0,
170
+ );
164
171
  }
165
172
  this.userPoolDomain = this.createUserPoolDomain(this.userPool);
166
173
  this.userPoolClient = this.createUserPoolClient(this.userPool);
@@ -248,7 +255,11 @@ export class UserIdentity extends Construct {
248
255
  return userPool;
249
256
  };
250
257
 
251
- private createWebAcl = (id: string, userPool: UserPool) => {
258
+ private createWebAcl = (
259
+ id: string,
260
+ userPool: UserPool,
261
+ allowsLocalCallback: boolean,
262
+ ) => {
252
263
  const webAcl = new CfnWebACL(this, 'WebAcl', {
253
264
  defaultAction: { allow: {} },
254
265
  scope: 'REGIONAL',
@@ -265,6 +276,17 @@ export class UserIdentity extends Construct {
265
276
  managedRuleGroupStatement: {
266
277
  name: 'AWSManagedRulesCommonRuleSet',
267
278
  vendorName: 'AWS',
279
+ // EC2MetaDataSSRF_QUERYARGUMENTS treats the loopback redirect_uri the
280
+ // Hosted UI receives during local sign-in as an SSRF attempt. Counted
281
+ // only while a local callback URL is allowed; every other rule blocks.
282
+ ruleActionOverrides: allowsLocalCallback
283
+ ? [
284
+ {
285
+ name: 'EC2MetaDataSSRF_QUERYARGUMENTS',
286
+ actionToUse: { count: {} },
287
+ },
288
+ ]
289
+ : undefined,
268
290
  },
269
291
  },
270
292
  visibilityConfig: {
@@ -335,7 +357,7 @@ export class UserIdentity extends Construct {
335
357
  private createUserPoolClient = (userPool: UserPool) => {
336
358
  const lazilyComputedCallbackUrls = Lazy.list({
337
359
  produce: () =>
338
- ['http://localhost:4200', 'http://localhost:4300'].concat(
360
+ LOCAL_CALLBACK_URLS.concat(
339
361
  Stack.of(this)
340
362
  .node.findAll()
341
363
  .filter(
@@ -65,12 +65,22 @@ export declare const getDefaultBiomeConfig: (tree: Tree) => {
65
65
  };
66
66
  }[];
67
67
  };
68
+ export interface FormatFilesInSubtreeOptions {
69
+ /**
70
+ * Paths, relative to the workspace root, to leave untouched.
71
+ *
72
+ * For files another tool owns the formatting of: formatting them here makes
73
+ * generation non-idempotent, since the tool rewrites them in its own shape on
74
+ * the next run and the workspace flips between the two forms.
75
+ */
76
+ readonly ignore?: readonly string[];
77
+ }
68
78
  /**
69
79
  * Format files in the given directory within the tree.
70
80
  * Handles both TypeScript/JavaScript/JSON (via biome) and Python (via ruff) files.
71
81
  * See https://github.com/nrwl/nx/blob/4cd640a9187954505d12de5b6d76a90d8ce4c2eb/packages/devkit/src/generators/format-files.ts#L11
72
82
  */
73
- export declare function formatFilesInSubtree(tree: Tree, dir?: string): Promise<void>;
83
+ export declare function formatFilesInSubtree(tree: Tree, dir?: string, options?: FormatFilesInSubtreeOptions): Promise<void>;
74
84
  /**
75
85
  * Derive ruff's `target-version` (eg `py314`) from a PEP 508
76
86
  * `requires-python` specifier (eg `>=3.14`). Ruff targets the minimum
@@ -109,12 +109,35 @@ const BIOME_FORMATTABLE_EXTENSIONS = new Set([
109
109
  '.css'
110
110
  ]);
111
111
  /** Matches `tsconfig.json` and variants like `tsconfig.lib.json`. */ const isTsConfig = (filePath)=>/(^|\/)tsconfig[^/]*\.json$/.test(filePath);
112
+ /**
113
+ * Paths declared ignored for a tree, which stay ignored for every later call.
114
+ *
115
+ * A call formats every change pending in the tree, not only the ones its caller
116
+ * made, so the list cannot be scoped to the call that passes it: generators
117
+ * composing on one tree would reformat a file an earlier generator had excluded.
118
+ * Once the generator that owns a file declares it ignored, it stays ignored for
119
+ * the rest of the run.
120
+ */ const treeIgnoredPaths = new WeakMap();
121
+ /**
122
+ * Tree paths are workspace-relative and forward-slash separated. Normalise so a
123
+ * caller building a path with `path.join` on Windows still matches.
124
+ */ const normalizeTreePath = (filePath)=>filePath.split(path.sep).join('/').replace(/^\.\//, '');
112
125
  /**
113
126
  * Format files in the given directory within the tree.
114
127
  * Handles both TypeScript/JavaScript/JSON (via biome) and Python (via ruff) files.
115
128
  * See https://github.com/nrwl/nx/blob/4cd640a9187954505d12de5b6d76a90d8ce4c2eb/packages/devkit/src/generators/format-files.ts#L11
116
- */ export async function formatFilesInSubtree(tree, dir) {
117
- const changedFiles = tree.listChanges().filter((file)=>file.type !== 'DELETE').filter((file)=>dir ? file.path.startsWith(dir) : true);
129
+ */ export async function formatFilesInSubtree(tree, dir, options) {
130
+ let ignored = treeIgnoredPaths.get(tree);
131
+ if (options?.ignore?.length) {
132
+ if (!ignored) {
133
+ ignored = new Set();
134
+ treeIgnoredPaths.set(tree, ignored);
135
+ }
136
+ for (const filePath of options.ignore){
137
+ ignored.add(normalizeTreePath(filePath));
138
+ }
139
+ }
140
+ const changedFiles = tree.listChanges().filter((file)=>file.type !== 'DELETE').filter((file)=>dir ? file.path.startsWith(dir) : true).filter((file)=>!ignored?.has(normalizeTreePath(file.path)));
118
141
  const pyFiles = changedFiles.filter((file)=>file.path.endsWith('.py'));
119
142
  const otherFiles = changedFiles.filter((file)=>BIOME_FORMATTABLE_EXTENSIONS.has(path.extname(file.path)) && // tsconfigs are not biome-managed: they're excluded from the vended
120
143
  // format target (Nx's typescript-sync rewrites them without formatting),