@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.
- package/generators.json +7 -0
- package/migrations.json +5 -0
- package/package.json +1 -1
- package/src/internal/test-matrix/generator.d.ts +29 -0
- package/src/internal/test-matrix/generator.js +660 -0
- package/src/internal/test-matrix/generator.js.map +1 -0
- package/src/internal/test-matrix/schema.d.js +6 -0
- package/src/internal/test-matrix/schema.d.js.map +1 -0
- package/src/internal/test-matrix/schema.d.ts +12 -0
- package/src/internal/test-matrix/schema.json +21 -0
- package/src/migrations/latest/user-identity-waf-allow-localhost-callback/migration.d.ts +6 -0
- package/src/migrations/latest/user-identity-waf-allow-localhost-callback/migration.js +217 -0
- package/src/migrations/latest/user-identity-waf-allow-localhost-callback/migration.js.map +1 -0
- package/src/sdk/py.d.ts +2 -0
- package/src/sdk/py.js +1 -0
- package/src/sdk/py.js.map +1 -1
- package/src/sdk/ts.d.ts +2 -0
- package/src/sdk/ts.js +2 -0
- package/src/sdk/ts.js.map +1 -1
- package/src/sdk/utils/format.d.ts +1 -1
- package/src/sdk/utils/format.js.map +1 -1
- package/src/ts/rdb/generator.js +19 -1
- package/src/ts/rdb/generator.js.map +1 -1
- package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +66 -66
- package/src/ts/react-website/app/generator.js +10 -1
- package/src/ts/react-website/app/generator.js.map +1 -1
- package/src/ts/react-website/cognito-auth/__snapshots__/generator.spec.ts.snap +25 -3
- package/src/utils/format.d.ts +11 -1
- package/src/utils/format.js +25 -2
- package/src/utils/format.js.map +1 -1
- package/src/utils/identity-constructs/files/cdk/core/user-identity.ts.template +25 -3
- 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
|
-
|
|
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(
|
|
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 = (
|
|
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
|
-
|
|
360
|
+
LOCAL_CALLBACK_URLS.concat(
|
|
339
361
|
Stack.of(this)
|
|
340
362
|
.node.findAll()
|
|
341
363
|
.filter(
|
package/src/utils/format.d.ts
CHANGED
|
@@ -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
|
package/src/utils/format.js
CHANGED
|
@@ -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
|
-
|
|
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),
|