@aws/nx-plugin 1.0.0-rc.95 → 1.0.0-rc.97

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 (179) hide show
  1. package/LICENSE-THIRD-PARTY +234 -38
  2. package/migrations.json +65 -2
  3. package/package.json +6 -6
  4. package/src/agentcore-gateway/__snapshots__/generator.spec.ts.snap +1 -1
  5. package/src/agentcore-gateway/generator.js +6 -0
  6. package/src/agentcore-gateway/generator.js.map +1 -1
  7. package/src/agentcore-gateway/react-connection/__snapshots__/generator.spec.ts.snap +4 -1
  8. package/src/agentcore-harness/__snapshots__/generator.spec.ts.snap +68 -4
  9. package/src/agentcore-harness/generator.js +6 -0
  10. package/src/agentcore-harness/generator.js.map +1 -1
  11. package/src/connection/gateway-runtime-config.js +1 -1
  12. package/src/connection/gateway-runtime-config.js.map +1 -1
  13. package/src/infra/app/__snapshots__/generator.spec.ts.snap +10 -16
  14. package/src/infra/app/generator.js +34 -7
  15. package/src/infra/app/generator.js.map +1 -1
  16. package/src/init/generator.d.ts +1 -1
  17. package/src/init/generator.js +8 -6
  18. package/src/init/generator.js.map +1 -1
  19. package/src/init/schema.d.js.map +1 -1
  20. package/src/init/schema.d.ts +1 -0
  21. package/src/init/schema.json +5 -0
  22. package/src/mcp-server/server.js +2 -0
  23. package/src/mcp-server/server.js.map +1 -1
  24. package/src/mcp-server/tools/best-practices.d.ts +28 -0
  25. package/src/mcp-server/tools/best-practices.js +43 -0
  26. package/src/mcp-server/tools/best-practices.js.map +1 -0
  27. package/src/mcp-server/tools/general-guidance.d.ts +1 -1
  28. package/src/mcp-server/tools/general-guidance.js +13 -4
  29. package/src/mcp-server/tools/general-guidance.js.map +1 -1
  30. package/src/migrations/latest/checkov-scan-cache-inputs/metadata.json +3 -0
  31. package/src/migrations/latest/checkov-scan-cache-inputs/migration.d.ts +6 -0
  32. package/src/migrations/latest/checkov-scan-cache-inputs/migration.js +58 -0
  33. package/src/migrations/latest/checkov-scan-cache-inputs/migration.js.map +1 -0
  34. package/src/migrations/latest/gateway-url-accessor/__snapshots__/migration.spec.ts.snap +84 -0
  35. package/src/migrations/latest/gateway-url-accessor/metadata.json +3 -0
  36. package/src/migrations/latest/gateway-url-accessor/migration.d.ts +6 -0
  37. package/src/migrations/latest/gateway-url-accessor/migration.js +94 -0
  38. package/src/migrations/latest/gateway-url-accessor/migration.js.map +1 -0
  39. package/src/migrations/latest/infra-deploy-express-mode/metadata.json +1 -1
  40. package/src/migrations/latest/infra-deploy-express-mode/migration.js +26 -28
  41. package/src/migrations/latest/infra-deploy-express-mode/migration.js.map +1 -1
  42. package/src/migrations/latest/py-lambda-powertools-context/metadata.json +3 -0
  43. package/src/migrations/latest/py-lambda-powertools-context/migration.d.ts +6 -0
  44. package/src/migrations/latest/py-lambda-powertools-context/migration.js +58 -0
  45. package/src/migrations/latest/py-lambda-powertools-context/migration.js.map +1 -0
  46. package/src/migrations/latest/script-project-quality-gates/metadata.json +3 -0
  47. package/src/migrations/latest/script-project-quality-gates/migration.d.ts +6 -0
  48. package/src/migrations/latest/script-project-quality-gates/migration.js +53 -0
  49. package/src/migrations/latest/script-project-quality-gates/migration.js.map +1 -0
  50. package/src/migrations/latest/smithy-extension-trait-aliases/__snapshots__/migration.spec.ts.snap +25 -0
  51. package/src/migrations/latest/smithy-extension-trait-aliases/metadata.json +3 -0
  52. package/src/migrations/latest/smithy-extension-trait-aliases/migration.d.ts +28 -0
  53. package/src/migrations/latest/smithy-extension-trait-aliases/migration.js +75 -0
  54. package/src/migrations/latest/smithy-extension-trait-aliases/migration.js.map +1 -0
  55. package/src/migrations/latest/terraform-validate-without-backend/metadata.json +3 -0
  56. package/src/migrations/latest/terraform-validate-without-backend/migration.d.ts +6 -0
  57. package/src/migrations/latest/terraform-validate-without-backend/migration.js +84 -0
  58. package/src/migrations/latest/terraform-validate-without-backend/migration.js.map +1 -0
  59. package/src/preset/__snapshots__/generator.spec.ts.snap +3 -5
  60. package/src/preset/generator.js +4 -25
  61. package/src/preset/generator.js.map +1 -1
  62. package/src/py/agent/a2a-connection/generator.d.ts +1 -1
  63. package/src/py/agent/gateway-connection/generator.d.ts +1 -1
  64. package/src/py/agent/mcp-connection/generator.d.ts +1 -1
  65. package/src/py/agent/react-connection/__snapshots__/generator.spec.ts.snap +4 -1
  66. package/src/py/agent/react-connection/generator.d.ts +29 -0
  67. package/src/py/dynamodb/__snapshots__/generator.spec.ts.snap +8 -10
  68. package/src/py/dynamodb/generator.js +34 -7
  69. package/src/py/dynamodb/generator.js.map +1 -1
  70. package/src/py/lambda-function/__snapshots__/generator.spec.ts.snap +2 -1
  71. package/src/py/lambda-function/files/handler/__lambdaFunctionSnakeCase__.py.template +2 -1
  72. package/src/py/project/schema.json +3 -1
  73. package/src/py/rdb/__snapshots__/generator.spec.ts.snap +28 -12
  74. package/src/py/rdb/files/Dockerfile.create-db-user.template +7 -3
  75. package/src/py/rdb/files/Dockerfile.migration.template +7 -3
  76. package/src/py/rdb/generator.js +29 -28
  77. package/src/py/rdb/generator.js.map +1 -1
  78. package/src/smithy/react-connection/files/model/extensions.smithy.template +3 -3
  79. package/src/smithy/ts/api/generator.js +7 -2
  80. package/src/smithy/ts/api/generator.js.map +1 -1
  81. package/src/terraform/project/generator.js +34 -10
  82. package/src/terraform/project/generator.js.map +1 -1
  83. package/src/trpc/backend/generator.js +7 -1
  84. package/src/trpc/backend/generator.js.map +1 -1
  85. package/src/trpc/react/generator.js +6 -0
  86. package/src/trpc/react/generator.js.map +1 -1
  87. package/src/ts/agent/generator.js +3 -3
  88. package/src/ts/agent/generator.js.map +1 -1
  89. package/src/ts/agent/react-connection/generator.d.ts +37 -0
  90. package/src/ts/dynamodb/__snapshots__/generator.spec.ts.snap +2 -0
  91. package/src/ts/dynamodb/generator.js +30 -6
  92. package/src/ts/dynamodb/generator.js.map +1 -1
  93. package/src/ts/lib/biome.d.ts +15 -1
  94. package/src/ts/lib/biome.js +79 -63
  95. package/src/ts/lib/biome.js.map +1 -1
  96. package/src/ts/lib/generator.d.ts +13 -0
  97. package/src/ts/lib/generator.js +14 -9
  98. package/src/ts/lib/generator.js.map +1 -1
  99. package/src/ts/lib/ts-project-utils.d.ts +31 -1
  100. package/src/ts/lib/ts-project-utils.js +53 -0
  101. package/src/ts/lib/ts-project-utils.js.map +1 -1
  102. package/src/ts/lib/vitest.d.ts +6 -0
  103. package/src/ts/lib/vitest.js +16 -1
  104. package/src/ts/lib/vitest.js.map +1 -1
  105. package/src/ts/mcp-server/generator.js +3 -3
  106. package/src/ts/mcp-server/generator.js.map +1 -1
  107. package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +5 -0
  108. package/src/ts/rdb/files/Dockerfile.template +5 -0
  109. package/src/ts/rdb/generator.d.ts +8 -0
  110. package/src/ts/rdb/generator.js +28 -24
  111. package/src/ts/rdb/generator.js.map +1 -1
  112. package/src/ts/rdb/trpc-connection/__snapshots__/generator.spec.ts.snap +39 -0
  113. package/src/ts/rdb/trpc-connection/generator.js +13 -0
  114. package/src/ts/rdb/trpc-connection/generator.js.map +1 -1
  115. package/src/ts/react-website/agui/files/common/src/components/__agentNameKebabCase__-chat.tsx.template +9 -0
  116. package/src/ts/react-website/agui/files/common/src/hooks/useAgui__agentNameClassName__.tsx.template +4 -1
  117. package/src/ts/react-website/agui/generator.d.ts +21 -0
  118. package/src/ts/react-website/agui/generator.js +6 -2
  119. package/src/ts/react-website/agui/generator.js.map +1 -1
  120. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +26 -22
  121. package/src/ts/react-website/app/generator.d.ts +42 -0
  122. package/src/ts/react-website/app/generator.js +4 -8
  123. package/src/ts/react-website/app/generator.js.map +1 -1
  124. package/src/utils/agent-connection/agent-connection.d.ts +2 -1
  125. package/src/utils/agent-connection/agent-connection.js +6 -1
  126. package/src/utils/agent-connection/agent-connection.js.map +1 -1
  127. package/src/utils/agent-core-constructs/files/cdk/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.ts.template +11 -7
  128. package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/agentcore-gateway.ts.template +14 -6
  129. package/src/utils/agent-core-packaging.js +5 -5
  130. package/src/utils/agent-core-packaging.js.map +1 -1
  131. package/src/utils/api-constructs/api-constructs.d.ts +5 -0
  132. package/src/utils/api-constructs/api-constructs.js +8 -0
  133. package/src/utils/api-constructs/api-constructs.js.map +1 -1
  134. package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +4 -2
  135. package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +4 -2
  136. package/src/utils/ast.d.ts +10 -0
  137. package/src/utils/ast.js +33 -0
  138. package/src/utils/ast.js.map +1 -1
  139. package/src/utils/dependencies.js +1 -10
  140. package/src/utils/dependencies.js.map +1 -1
  141. package/src/utils/docker.d.ts +11 -0
  142. package/src/utils/docker.js +16 -3
  143. package/src/utils/docker.js.map +1 -1
  144. package/src/utils/dynamodb-config.d.ts +48 -0
  145. package/src/utils/dynamodb-config.js +44 -0
  146. package/src/utils/dynamodb-config.js.map +1 -0
  147. package/src/utils/dynamodb-constructs/files/cdk/app/dynamodb/__nameKebabCase__.ts.template +8 -4
  148. package/src/utils/git-secrets.d.ts +28 -0
  149. package/src/utils/git-secrets.js +66 -0
  150. package/src/utils/git-secrets.js.map +1 -0
  151. package/src/utils/init.js +7 -6
  152. package/src/utils/init.js.map +1 -1
  153. package/src/utils/local-project-dependency.d.ts +28 -0
  154. package/src/utils/local-project-dependency.js +40 -0
  155. package/src/utils/local-project-dependency.js.map +1 -0
  156. package/src/utils/nx.d.ts +14 -0
  157. package/src/utils/nx.js +30 -0
  158. package/src/utils/nx.js.map +1 -1
  159. package/src/utils/rdb-constructs/files/cdk/app/dbs/__nameKebabCase__.ts.template +11 -6
  160. package/src/utils/script-project-targets.d.ts +26 -0
  161. package/src/utils/script-project-targets.js +75 -0
  162. package/src/utils/script-project-targets.js.map +1 -0
  163. package/src/utils/shared-shadcn.d.ts +13 -0
  164. package/src/utils/shared-shadcn.js +3 -2
  165. package/src/utils/shared-shadcn.js.map +1 -1
  166. package/src/utils/test.js +15 -0
  167. package/src/utils/test.js.map +1 -1
  168. package/src/utils/version-upgrade-migration/sync-vended-versions.js +4 -4
  169. package/src/utils/version-upgrade-migration/sync-vended-versions.js.map +1 -1
  170. package/src/utils/versions.d.ts +13 -9
  171. package/src/utils/versions.js +17 -8
  172. package/src/utils/versions.js.map +1 -1
  173. package/src/utils/website-constructs/files/cdk/app/static-websites/__websiteNameKebabCase__.ts.template +8 -4
  174. package/src/py/dynamodb/files/__name__/__init__.py.template +0 -6
  175. package/src/py/dynamodb/files/__name__/entities/__init__.py.template +0 -4
  176. package/src/py/dynamodb/files/config.json.template +0 -24
  177. package/src/ts/dynamodb/files/config.json.template +0 -24
  178. package/src/ts/dynamodb/files/src/entities/index.ts.template +0 -1
  179. package/src/ts/dynamodb/files/src/index.ts.template +0 -2
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../packages/nx-plugin/src/py/rdb/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { relative } from 'node:path';\nimport {\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n readProjectConfiguration,\n type Tree,\n updateProjectConfiguration,\n writeJson,\n} from '@nx/devkit';\nimport {\n addPyDependencies,\n addTsDependencies,\n} from '../../utils/add-dependencies.js';\nimport { addPythonReExport } from '../../utils/agent-connection/agent-connection.js';\nimport { addPythonBundleTarget } from '../../utils/bundle/bundle.js';\nimport { resolveContainers } from '../../utils/containers.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../utils/declared-dependencies.js';\nimport {\n addDockerScanTarget,\n DOCKER_DEPENDENCIES,\n IMAGE_BUILD_CACHE,\n} from '../../utils/docker.js';\nimport { formatFilesInSubtree } from '../../utils/format.js';\nimport { FS_DEPENDENCIES, FsCommands } from '../../utils/fs.js';\nimport { resolveIac } from '../../utils/iac.js';\nimport { installDependencies } from '../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics.js';\nimport { kebabCase, snakeCase, toClassName } from '../../utils/names.js';\nimport { getNpmScope } from '../../utils/npm-scope.js';\nimport {\n addArtifactDependencyToTargets,\n addDependencyToTargetIfNotPresent,\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n projectExists,\n} from '../../utils/nx.js';\nimport { assignPort } from '../../utils/port.js';\nimport { addRdbInfra } from '../../utils/rdb-constructs/rdb-constructs.js';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n sharedConstructsGenerator,\n} from '../../utils/shared-constructs.js';\nimport {\n type IacMetadata,\n PACKAGES_DIR,\n SHARED_SCRIPTS_DIR,\n} from '../../utils/shared-constructs-constants.js';\nimport {\n SHARED_RDB_SCRIPTS_DEPENDENCIES,\n sharedRdbScriptsGenerator,\n} from '../../utils/shared-rdb-scripts.js';\nimport { PY_VERSIONS } from '../../utils/versions.js';\nimport pyProjectGenerator, {\n getPyProjectDetails,\n} from '../project/generator.js';\nimport type { PyRdbGeneratorSchema } from './schema';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface PyRdbMetadata extends IacMetadata {\n readonly engine: PyRdbGeneratorSchema['engine'];\n}\n\n/** The Postgres engine, which MySQL takes none of. */\nconst isPostgres = (m: PyRdbMetadata) => m.engine !== 'mysql';\n\n// Each entry names the engine branch it belongs to, so the same declaration\n// drives both adding and the version sync.\nexport const DEPENDENCIES = declareDependencies<PyRdbMetadata>()({\n ts: [\n // The engine client the local dev script wait-for-*-db.ts imports.\n { name: 'mariadb', when: (m) => m.engine === 'mysql', root: true },\n { name: 'pg', when: isPostgres, root: true },\n { name: '@types/pg', when: isPostgres, dev: true, root: true },\n // Added by the helpers that own the projects they belong to.\n ...ownedElsewhere(FS_DEPENDENCIES),\n ...ownedElsewhere(DOCKER_DEPENDENCIES),\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ...ownedElsewhere(SHARED_RDB_SCRIPTS_DEPENDENCIES),\n ],\n py: [\n { name: 'sqlmodel' },\n { name: 'alembic' },\n // SQLAlchemy's async engine (used by connection.py for both engines)\n // requires greenlet at runtime. Vend it explicitly at a pinned version so\n // the dependency graph is fully determined and doesn't float to an\n // unpublished-wheel release at install time.\n { name: 'greenlet' },\n { name: 'aiomysql', when: (m) => m.engine === 'mysql' },\n { name: 'asyncpg', when: (m) => m.engine !== 'mysql' },\n { name: 'boto3' },\n { name: 'aws-lambda-powertools' },\n ],\n});\n\nexport const PY_RDB_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport const pyRdbGenerator = async (\n tree: Tree,\n options: PyRdbGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const nameClassName = toClassName(options.name);\n const databaseUser = options.databaseUser ?? 'dbadmin';\n const databaseName = snakeCase(options.databaseName ?? options.name);\n const containerEngine = await resolveContainers(tree, 'inherit');\n\n const { fullyQualifiedName, dir, normalizedModuleName } = getPyProjectDetails(\n tree,\n {\n name: options.name,\n directory: options.directory,\n subDirectory: options.subDirectory,\n },\n );\n\n if (!projectExists(tree, fullyQualifiedName)) {\n await pyProjectGenerator(tree, {\n name: options.name,\n directory: options.directory,\n subDirectory: options.subDirectory,\n type: 'library',\n });\n }\n\n const projectConfig = readProjectConfiguration(tree, fullyQualifiedName);\n\n const { engine } = options;\n // Recorded in the metadata below so the version sync can tell a CDK project\n // from a Terraform one; undefined when no infrastructure was generated.\n const iac =\n options.infra !== 'none' ? await resolveIac(tree, options.iac) : undefined;\n\n // Recorded below and read by the declaration's predicates, so the packages\n // added here are exactly the ones the version sync will own.\n const metadata: PyRdbMetadata = { engine, ...(iac ? { iac } : {}) };\n const localDbPort = assignPort(\n tree,\n projectConfig,\n engine === 'mysql' ? 3306 : 5432,\n );\n const localDbHost = 'localhost';\n const localDbUser = engine === 'mysql' ? 'root' : 'dbadmin';\n const localDbPassword = 'password';\n const containerName = `${getNpmScope(tree)}-${databaseName}`;\n const dockerImage =\n engine === 'mysql'\n ? 'public.ecr.aws/docker/library/mysql:8.0.44'\n : 'public.ecr.aws/docker/library/postgres:17.7';\n\n const templateOptions = {\n name: normalizedModuleName,\n runtimeConfigKey: nameClassName,\n engine,\n localDbPort,\n localDbHost,\n localDbName: databaseName,\n localDbUser,\n localDbPassword,\n containerEngine,\n containerName,\n dockerImage,\n sqlmodelVersion: PY_VERSIONS.sqlmodel,\n alembicVersion: PY_VERSIONS.alembic,\n aiomysqlVersion: PY_VERSIONS.aiomysql,\n asyncpgVersion: PY_VERSIONS.asyncpg,\n boto3Version: PY_VERSIONS.boto3,\n awsLambdaPowertoolsVersion: PY_VERSIONS['aws-lambda-powertools'],\n };\n\n // Models, the connection module, the Alembic config and the migration env are\n // user-editable, so a re-run (to add infrastructure, or after a failed run)\n // must not clobber the user's schema and edits.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files'),\n dir,\n templateOptions,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n // The package barrel re-exports connection.py. `pyProjectGenerator` writes a\n // stub __init__.py when it creates the project, so the re-exports are added to\n // whatever is there rather than replacing it — which also leaves a user's own\n // additions to the barrel alone on a re-run.\n const initFilePath = joinPathFragments(\n dir,\n normalizedModuleName,\n '__init__.py',\n );\n for (const importName of ['get_engine', 'is_local_dev', 'session_context']) {\n await addPythonReExport(tree, initFilePath, '.connection', importName);\n }\n\n // config.json is framework-owned: it carries values derived from the\n // generator's options, so it converges on a re-run with changed options.\n writeJson(tree, joinPathFragments(dir, 'config.json'), {\n runtimeConfigKey: nameClassName,\n localDev: {\n containerEngine,\n containerName,\n image: dockerImage,\n port: localDbPort,\n host: localDbHost,\n dbName: databaseName,\n dbUser: localDbUser,\n dbPassword: localDbPassword,\n dbEngine: engine,\n },\n });\n\n await sharedRdbScriptsGenerator(tree, engine, DEPENDENCIES);\n const scriptsDir = relative(\n dir,\n joinPathFragments(PACKAGES_DIR, SHARED_SCRIPTS_DIR, 'src', 'rdb'),\n );\n const fs = new FsCommands(tree, DEPENDENCIES);\n\n const migrationBundleDir = joinPathFragments(\n 'dist',\n projectConfig.root,\n 'docker',\n 'migration',\n );\n const createDbUserBundleDir = joinPathFragments(\n 'dist',\n projectConfig.root,\n 'docker',\n 'create-db-user',\n );\n const migrationDockerImageTag = `${getNpmScope(tree)}-${kebabCase(options.name)}-migration:latest`;\n const createDbUserDockerImageTag = `${getNpmScope(tree)}-${kebabCase(\n options.name,\n )}-create-db-user:latest`;\n\n if (options.infra !== 'none') {\n const { bundleTargetName, bundleOutputDir } = addPythonBundleTarget(\n projectConfig,\n { pythonPlatform: 'aarch64-manylinux_2_28' },\n );\n\n projectConfig.targets['bundle-migration'] = {\n cache: true,\n inputs: ['default'],\n outputs: ['{workspaceRoot}/dist/{projectRoot}/docker/migration'],\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(migrationBundleDir),\n fs.mkdir(migrationBundleDir),\n fs.cpDir(bundleOutputDir, migrationBundleDir),\n fs.cpDir(\n joinPathFragments(dir, 'migrations'),\n joinPathFragments(migrationBundleDir, 'migrations'),\n ),\n fs.cpFile(\n joinPathFragments(dir, 'alembic.ini'),\n joinPathFragments(migrationBundleDir, 'alembic.ini'),\n ),\n fs.cpFile(\n joinPathFragments(dir, 'Dockerfile.migration'),\n joinPathFragments(migrationBundleDir, 'Dockerfile'),\n ),\n ],\n parallel: false,\n },\n dependsOn: [bundleTargetName],\n };\n projectConfig.targets['bundle-create-db-user'] = {\n cache: true,\n inputs: ['default'],\n outputs: ['{workspaceRoot}/dist/{projectRoot}/docker/create-db-user'],\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(createDbUserBundleDir),\n fs.mkdir(createDbUserBundleDir),\n fs.cpDir(bundleOutputDir, createDbUserBundleDir),\n fs.cpFile(\n joinPathFragments(dir, 'Dockerfile.create-db-user'),\n joinPathFragments(createDbUserBundleDir, 'Dockerfile'),\n ),\n ],\n parallel: false,\n },\n dependsOn: [bundleTargetName],\n };\n addDependencyToTargetIfNotPresent(\n projectConfig,\n 'bundle',\n 'bundle-migration',\n );\n addDependencyToTargetIfNotPresent(\n projectConfig,\n 'bundle',\n 'bundle-create-db-user',\n );\n }\n\n projectConfig.targets['pull-image'] = {\n executor: 'nx:run-commands',\n options: {\n command: `tsx ${scriptsDir}/pull-image.ts`,\n cwd: '{projectRoot}',\n },\n };\n projectConfig.targets['dev'] = {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n command: `tsx ${scriptsDir}/start-container.ts`,\n cwd: '{projectRoot}',\n },\n dependsOn: ['pull-image'],\n };\n projectConfig.targets['wait-for-db'] = {\n executor: 'nx:run-commands',\n dependsOn: ['dev'],\n options: {\n command: `tsx ${scriptsDir}/wait-for-${engine}-db.ts`,\n cwd: '{projectRoot}',\n },\n };\n projectConfig.targets.migrate = {\n executor: 'nx:run-commands',\n dependsOn: ['dev', 'wait-for-db'],\n options: {\n command: 'uv run alembic upgrade head',\n cwd: '{projectRoot}',\n env: {\n LOCAL_DEV: 'true',\n },\n },\n };\n projectConfig.targets.alembic = {\n executor: 'nx:run-commands',\n dependsOn: ['dev', 'wait-for-db'],\n options: {\n command: 'uv run alembic',\n cwd: '{projectRoot}',\n env: {\n LOCAL_DEV: 'true',\n },\n },\n };\n\n if (options.infra !== 'none') {\n if (iac === 'terraform') {\n projectConfig.targets.docker = {\n cache: IMAGE_BUILD_CACHE,\n executor: 'nx:run-commands',\n options: {\n commands: [\n `${containerEngine} build --platform linux/arm64 --provenance=false -t ${migrationDockerImageTag} ${migrationBundleDir}`,\n `${containerEngine} build --platform linux/arm64 --provenance=false -t ${createDbUserDockerImageTag} ${createDbUserBundleDir}`,\n ],\n parallel: false,\n },\n dependsOn: ['bundle-migration', 'bundle-create-db-user'],\n };\n addArtifactDependencyToTargets(projectConfig, 'docker');\n\n addDockerScanTarget(\n tree,\n {\n project: projectConfig,\n containerEngine,\n trivyTargetName: 'trivy',\n dockerTargetName: 'docker',\n imageTags: [migrationDockerImageTag, createDbUserDockerImageTag],\n },\n DEPENDENCIES,\n );\n }\n addDependencyToTargetIfNotPresent(\n projectConfig,\n 'build',\n 'bundle-migration',\n );\n addDependencyToTargetIfNotPresent(\n projectConfig,\n 'build',\n 'bundle-create-db-user',\n );\n }\n\n updateProjectConfiguration(tree, fullyQualifiedName, projectConfig);\n addGeneratorMetadata(\n tree,\n fullyQualifiedName,\n PY_RDB_GENERATOR_INFO,\n metadata,\n );\n\n if (options.infra !== 'none') {\n await sharedConstructsGenerator(tree, { iac }, DEPENDENCIES);\n await addRdbInfra(tree, {\n iac,\n projectName: fullyQualifiedName,\n projectRoot: dir,\n nameClassName,\n nameKebabCase: kebabCase(options.name),\n databasePackageAlias: normalizedModuleName,\n databaseName,\n adminUser: databaseUser,\n engine,\n migrationBundleDir,\n createDbUserBundleDir,\n framework: 'sqlmodel',\n createDbUserDockerImageTag,\n migrationDockerImageTag,\n containerEngine,\n });\n }\n\n addPyDependencies(tree, DEPENDENCIES, { metadata, projectRoot: dir });\n addTsDependencies(tree, DEPENDENCIES, { metadata });\n\n await addGeneratorMetricsIfApplicable(tree, [PY_RDB_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript', 'python'],\n });\n};\n\nexport default pyRdbGenerator;\n"],"names":["relative","generateFiles","joinPathFragments","OverwriteStrategy","readProjectConfiguration","updateProjectConfiguration","writeJson","addPyDependencies","addTsDependencies","addPythonReExport","addPythonBundleTarget","resolveContainers","declareDependencies","ownedElsewhere","addDockerScanTarget","DOCKER_DEPENDENCIES","IMAGE_BUILD_CACHE","formatFilesInSubtree","FS_DEPENDENCIES","FsCommands","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","snakeCase","toClassName","getNpmScope","addArtifactDependencyToTargets","addDependencyToTargetIfNotPresent","addGeneratorMetadata","getGeneratorInfo","projectExists","assignPort","addRdbInfra","SHARED_CONSTRUCTS_DEPENDENCIES","sharedConstructsGenerator","PACKAGES_DIR","SHARED_SCRIPTS_DIR","SHARED_RDB_SCRIPTS_DEPENDENCIES","sharedRdbScriptsGenerator","PY_VERSIONS","pyProjectGenerator","getPyProjectDetails","isPostgres","m","engine","DEPENDENCIES","ts","name","when","root","dev","py","PY_RDB_GENERATOR_INFO","filename","pyRdbGenerator","tree","options","nameClassName","databaseUser","databaseName","containerEngine","fullyQualifiedName","dir","normalizedModuleName","directory","subDirectory","type","projectConfig","iac","infra","undefined","metadata","localDbPort","localDbHost","localDbUser","localDbPassword","containerName","dockerImage","templateOptions","runtimeConfigKey","localDbName","sqlmodelVersion","sqlmodel","alembicVersion","alembic","aiomysqlVersion","aiomysql","asyncpgVersion","asyncpg","boto3Version","boto3","awsLambdaPowertoolsVersion","dirname","overwriteStrategy","KeepExisting","initFilePath","importName","localDev","image","port","host","dbName","dbUser","dbPassword","dbEngine","scriptsDir","fs","migrationBundleDir","createDbUserBundleDir","migrationDockerImageTag","createDbUserDockerImageTag","bundleTargetName","bundleOutputDir","pythonPlatform","targets","cache","inputs","outputs","executor","commands","rm","mkdir","cpDir","cpFile","parallel","dependsOn","command","cwd","continuous","migrate","env","LOCAL_DEV","docker","project","trivyTargetName","dockerTargetName","imageTags","projectName","projectRoot","nameKebabCase","databasePackageAlias","adminUser","framework","preferInstallDependencies","languages"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/py/rdb/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { relative } from 'node:path';\nimport {\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n readProjectConfiguration,\n type Tree,\n updateProjectConfiguration,\n writeJson,\n} from '@nx/devkit';\nimport {\n addPyDependencies,\n addTsDependencies,\n} from '../../utils/add-dependencies.js';\nimport { addPythonReExport } from '../../utils/agent-connection/agent-connection.js';\nimport { addPythonBundleTarget } from '../../utils/bundle/bundle.js';\nimport { resolveContainers } from '../../utils/containers.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../utils/declared-dependencies.js';\nimport {\n addDockerScanTarget,\n DOCKER_DEPENDENCIES,\n IMAGE_BUILD_CACHE,\n} from '../../utils/docker.js';\nimport { formatFilesInSubtree } from '../../utils/format.js';\nimport { FS_DEPENDENCIES, FsCommands } from '../../utils/fs.js';\nimport { resolveIac } from '../../utils/iac.js';\nimport { installDependencies } from '../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics.js';\nimport { kebabCase, snakeCase, toClassName } from '../../utils/names.js';\nimport { getNpmScope } from '../../utils/npm-scope.js';\nimport {\n addArtifactDependencyToTargets,\n addDependencyToTargetIfNotPresent,\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n projectExists,\n} from '../../utils/nx.js';\nimport { assignPort } from '../../utils/port.js';\nimport { addRdbInfra } from '../../utils/rdb-constructs/rdb-constructs.js';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n sharedConstructsGenerator,\n} from '../../utils/shared-constructs.js';\nimport {\n type IacMetadata,\n PACKAGES_DIR,\n SHARED_SCRIPTS_DIR,\n} from '../../utils/shared-constructs-constants.js';\nimport {\n SHARED_RDB_SCRIPTS_DEPENDENCIES,\n sharedRdbScriptsGenerator,\n} from '../../utils/shared-rdb-scripts.js';\nimport { PY_VERSIONS } from '../../utils/versions.js';\nimport pyProjectGenerator, {\n getPyProjectDetails,\n} from '../project/generator.js';\nimport type { PyRdbGeneratorSchema } from './schema';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface PyRdbMetadata extends IacMetadata {\n readonly engine: PyRdbGeneratorSchema['engine'];\n}\n\n/** The Postgres engine, which MySQL takes none of. */\nconst isPostgres = (m: PyRdbMetadata) => m.engine !== 'mysql';\n\n// Each entry names the engine branch it belongs to, so the same declaration\n// drives both adding and the version sync.\nexport const DEPENDENCIES = declareDependencies<PyRdbMetadata>()({\n ts: [\n // The engine client the local dev script wait-for-*-db.ts imports.\n { name: 'mariadb', when: (m) => m.engine === 'mysql', root: true },\n { name: 'pg', when: isPostgres, root: true },\n { name: '@types/pg', when: isPostgres, dev: true, root: true },\n // Added by the helpers that own the projects they belong to.\n ...ownedElsewhere(FS_DEPENDENCIES),\n ...ownedElsewhere(DOCKER_DEPENDENCIES),\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ...ownedElsewhere(SHARED_RDB_SCRIPTS_DEPENDENCIES),\n ],\n py: [\n { name: 'sqlmodel' },\n { name: 'alembic' },\n // SQLAlchemy's async engine (used by connection.py for both engines)\n // requires greenlet at runtime. Vend it explicitly at a pinned version so\n // the dependency graph is fully determined and doesn't float to an\n // unpublished-wheel release at install time.\n { name: 'greenlet' },\n { name: 'aiomysql', when: (m) => m.engine === 'mysql' },\n { name: 'asyncpg', when: (m) => m.engine !== 'mysql' },\n { name: 'boto3' },\n { name: 'aws-lambda-powertools' },\n ],\n});\n\nexport const PY_RDB_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport const pyRdbGenerator = async (\n tree: Tree,\n options: PyRdbGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const nameClassName = toClassName(options.name);\n const databaseUser = options.databaseUser ?? 'dbadmin';\n const databaseName = snakeCase(options.databaseName ?? options.name);\n const containerEngine = await resolveContainers(tree, 'inherit');\n\n const { fullyQualifiedName, dir, normalizedModuleName } = getPyProjectDetails(\n tree,\n {\n name: options.name,\n directory: options.directory,\n subDirectory: options.subDirectory,\n },\n );\n\n if (!projectExists(tree, fullyQualifiedName)) {\n await pyProjectGenerator(tree, {\n name: options.name,\n directory: options.directory,\n subDirectory: options.subDirectory,\n type: 'library',\n });\n }\n\n const projectConfig = readProjectConfiguration(tree, fullyQualifiedName);\n\n const { engine } = options;\n // Recorded in the metadata below so the version sync can tell a CDK project\n // from a Terraform one; undefined when no infrastructure was generated.\n const iac =\n options.infra !== 'none' ? await resolveIac(tree, options.iac) : undefined;\n\n // Recorded below and read by the declaration's predicates, so the packages\n // added here are exactly the ones the version sync will own.\n const metadata: PyRdbMetadata = { engine, ...(iac ? { iac } : {}) };\n const localDbPort = assignPort(\n tree,\n projectConfig,\n engine === 'mysql' ? 3306 : 5432,\n );\n const localDbHost = 'localhost';\n const localDbUser = engine === 'mysql' ? 'root' : 'dbadmin';\n const localDbPassword = 'password';\n const containerName = `${getNpmScope(tree)}-${databaseName}`;\n const dockerImage =\n engine === 'mysql'\n ? 'public.ecr.aws/docker/library/mysql:8.0.44'\n : 'public.ecr.aws/docker/library/postgres:17.7';\n\n const templateOptions = {\n name: normalizedModuleName,\n runtimeConfigKey: nameClassName,\n engine,\n localDbPort,\n localDbHost,\n localDbName: databaseName,\n localDbUser,\n localDbPassword,\n containerEngine,\n containerName,\n dockerImage,\n sqlmodelVersion: PY_VERSIONS.sqlmodel,\n alembicVersion: PY_VERSIONS.alembic,\n aiomysqlVersion: PY_VERSIONS.aiomysql,\n asyncpgVersion: PY_VERSIONS.asyncpg,\n boto3Version: PY_VERSIONS.boto3,\n awsLambdaPowertoolsVersion: PY_VERSIONS['aws-lambda-powertools'],\n };\n\n // Models, the connection module, the Alembic config and the migration env are\n // user-editable, so a re-run (to add infrastructure, or after a failed run)\n // must not clobber the user's schema and edits.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files'),\n dir,\n templateOptions,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n // The package barrel re-exports connection.py. `pyProjectGenerator` writes a\n // stub __init__.py when it creates the project, so the re-exports are added to\n // whatever is there rather than replacing it — which also leaves a user's own\n // additions to the barrel alone on a re-run.\n const initFilePath = joinPathFragments(\n dir,\n normalizedModuleName,\n '__init__.py',\n );\n for (const importName of ['get_engine', 'is_local_dev', 'session_context']) {\n await addPythonReExport(tree, initFilePath, '.connection', importName);\n }\n\n // config.json is framework-owned: it carries values derived from the\n // generator's options, so it converges on a re-run with changed options.\n writeJson(tree, joinPathFragments(dir, 'config.json'), {\n runtimeConfigKey: nameClassName,\n localDev: {\n containerEngine,\n containerName,\n image: dockerImage,\n port: localDbPort,\n host: localDbHost,\n dbName: databaseName,\n dbUser: localDbUser,\n dbPassword: localDbPassword,\n dbEngine: engine,\n },\n });\n\n await sharedRdbScriptsGenerator(tree, engine, DEPENDENCIES);\n const scriptsDir = relative(\n dir,\n joinPathFragments(PACKAGES_DIR, SHARED_SCRIPTS_DIR, 'src', 'rdb'),\n );\n const fs = new FsCommands(tree, DEPENDENCIES);\n\n const migrationBundleDir = joinPathFragments(\n 'dist',\n projectConfig.root,\n 'docker',\n 'migration',\n );\n const createDbUserBundleDir = joinPathFragments(\n 'dist',\n projectConfig.root,\n 'docker',\n 'create-db-user',\n );\n const migrationDockerImageTag = `${getNpmScope(tree)}-${kebabCase(options.name)}-migration:latest`;\n const createDbUserDockerImageTag = `${getNpmScope(tree)}-${kebabCase(\n options.name,\n )}-create-db-user:latest`;\n\n if (options.infra !== 'none') {\n const { bundleTargetName, bundleOutputDir } = addPythonBundleTarget(\n projectConfig,\n { pythonPlatform: 'aarch64-manylinux_2_28' },\n );\n\n projectConfig.targets['bundle-migration'] = {\n cache: true,\n inputs: ['default'],\n outputs: ['{workspaceRoot}/dist/{projectRoot}/docker/migration'],\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(migrationBundleDir),\n fs.mkdir(migrationBundleDir),\n fs.cpDir(bundleOutputDir, migrationBundleDir),\n fs.cpDir(\n joinPathFragments(dir, 'migrations'),\n joinPathFragments(migrationBundleDir, 'migrations'),\n ),\n fs.cpFile(\n joinPathFragments(dir, 'alembic.ini'),\n joinPathFragments(migrationBundleDir, 'alembic.ini'),\n ),\n fs.cpFile(\n joinPathFragments(dir, 'Dockerfile.migration'),\n joinPathFragments(migrationBundleDir, 'Dockerfile'),\n ),\n ],\n parallel: false,\n },\n dependsOn: [bundleTargetName],\n };\n projectConfig.targets['bundle-create-db-user'] = {\n cache: true,\n inputs: ['default'],\n outputs: ['{workspaceRoot}/dist/{projectRoot}/docker/create-db-user'],\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(createDbUserBundleDir),\n fs.mkdir(createDbUserBundleDir),\n fs.cpDir(bundleOutputDir, createDbUserBundleDir),\n fs.cpFile(\n joinPathFragments(dir, 'Dockerfile.create-db-user'),\n joinPathFragments(createDbUserBundleDir, 'Dockerfile'),\n ),\n ],\n parallel: false,\n },\n dependsOn: [bundleTargetName],\n };\n addDependencyToTargetIfNotPresent(\n projectConfig,\n 'bundle',\n 'bundle-migration',\n );\n addDependencyToTargetIfNotPresent(\n projectConfig,\n 'bundle',\n 'bundle-create-db-user',\n );\n }\n\n projectConfig.targets['pull-image'] = {\n executor: 'nx:run-commands',\n options: {\n command: `tsx ${scriptsDir}/pull-image.ts`,\n cwd: '{projectRoot}',\n },\n };\n projectConfig.targets['dev'] = {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n command: `tsx ${scriptsDir}/start-container.ts`,\n cwd: '{projectRoot}',\n },\n dependsOn: ['pull-image'],\n };\n projectConfig.targets['wait-for-db'] = {\n executor: 'nx:run-commands',\n dependsOn: ['dev'],\n options: {\n command: `tsx ${scriptsDir}/wait-for-${engine}-db.ts`,\n cwd: '{projectRoot}',\n },\n };\n projectConfig.targets.migrate = {\n executor: 'nx:run-commands',\n dependsOn: ['dev', 'wait-for-db'],\n options: {\n command: 'uv run alembic upgrade head',\n cwd: '{projectRoot}',\n env: {\n LOCAL_DEV: 'true',\n },\n },\n };\n projectConfig.targets.alembic = {\n executor: 'nx:run-commands',\n dependsOn: ['dev', 'wait-for-db'],\n options: {\n command: 'uv run alembic',\n cwd: '{projectRoot}',\n env: {\n LOCAL_DEV: 'true',\n },\n },\n };\n\n if (options.infra !== 'none') {\n // Both images ship under either provider — Terraform pushes the locally\n // built tags, CDK builds the same contexts as image assets — so the build\n // and its scan are wired up for either.\n projectConfig.targets.docker = {\n cache: IMAGE_BUILD_CACHE,\n executor: 'nx:run-commands',\n options: {\n commands: [\n `${containerEngine} build --platform linux/arm64 --provenance=false -t ${migrationDockerImageTag} ${migrationBundleDir}`,\n `${containerEngine} build --platform linux/arm64 --provenance=false -t ${createDbUserDockerImageTag} ${createDbUserBundleDir}`,\n ],\n parallel: false,\n },\n dependsOn: ['bundle-migration', 'bundle-create-db-user'],\n };\n addArtifactDependencyToTargets(projectConfig, 'docker');\n\n addDockerScanTarget(\n tree,\n {\n project: projectConfig,\n containerEngine,\n trivyTargetName: 'trivy',\n dockerTargetName: 'docker',\n imageTags: [migrationDockerImageTag, createDbUserDockerImageTag],\n },\n DEPENDENCIES,\n );\n addDependencyToTargetIfNotPresent(\n projectConfig,\n 'build',\n 'bundle-migration',\n );\n addDependencyToTargetIfNotPresent(\n projectConfig,\n 'build',\n 'bundle-create-db-user',\n );\n }\n\n updateProjectConfiguration(tree, fullyQualifiedName, projectConfig);\n addGeneratorMetadata(\n tree,\n fullyQualifiedName,\n PY_RDB_GENERATOR_INFO,\n metadata,\n );\n\n if (options.infra !== 'none') {\n await sharedConstructsGenerator(tree, { iac }, DEPENDENCIES);\n await addRdbInfra(tree, {\n iac,\n projectName: fullyQualifiedName,\n projectRoot: dir,\n nameClassName,\n nameKebabCase: kebabCase(options.name),\n databasePackageAlias: normalizedModuleName,\n databaseName,\n adminUser: databaseUser,\n engine,\n migrationBundleDir,\n createDbUserBundleDir,\n framework: 'sqlmodel',\n createDbUserDockerImageTag,\n migrationDockerImageTag,\n containerEngine,\n });\n }\n\n addPyDependencies(tree, DEPENDENCIES, { metadata, projectRoot: dir });\n addTsDependencies(tree, DEPENDENCIES, { metadata });\n\n await addGeneratorMetricsIfApplicable(tree, [PY_RDB_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript', 'python'],\n });\n};\n\nexport default pyRdbGenerator;\n"],"names":["relative","generateFiles","joinPathFragments","OverwriteStrategy","readProjectConfiguration","updateProjectConfiguration","writeJson","addPyDependencies","addTsDependencies","addPythonReExport","addPythonBundleTarget","resolveContainers","declareDependencies","ownedElsewhere","addDockerScanTarget","DOCKER_DEPENDENCIES","IMAGE_BUILD_CACHE","formatFilesInSubtree","FS_DEPENDENCIES","FsCommands","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","snakeCase","toClassName","getNpmScope","addArtifactDependencyToTargets","addDependencyToTargetIfNotPresent","addGeneratorMetadata","getGeneratorInfo","projectExists","assignPort","addRdbInfra","SHARED_CONSTRUCTS_DEPENDENCIES","sharedConstructsGenerator","PACKAGES_DIR","SHARED_SCRIPTS_DIR","SHARED_RDB_SCRIPTS_DEPENDENCIES","sharedRdbScriptsGenerator","PY_VERSIONS","pyProjectGenerator","getPyProjectDetails","isPostgres","m","engine","DEPENDENCIES","ts","name","when","root","dev","py","PY_RDB_GENERATOR_INFO","filename","pyRdbGenerator","tree","options","nameClassName","databaseUser","databaseName","containerEngine","fullyQualifiedName","dir","normalizedModuleName","directory","subDirectory","type","projectConfig","iac","infra","undefined","metadata","localDbPort","localDbHost","localDbUser","localDbPassword","containerName","dockerImage","templateOptions","runtimeConfigKey","localDbName","sqlmodelVersion","sqlmodel","alembicVersion","alembic","aiomysqlVersion","aiomysql","asyncpgVersion","asyncpg","boto3Version","boto3","awsLambdaPowertoolsVersion","dirname","overwriteStrategy","KeepExisting","initFilePath","importName","localDev","image","port","host","dbName","dbUser","dbPassword","dbEngine","scriptsDir","fs","migrationBundleDir","createDbUserBundleDir","migrationDockerImageTag","createDbUserDockerImageTag","bundleTargetName","bundleOutputDir","pythonPlatform","targets","cache","inputs","outputs","executor","commands","rm","mkdir","cpDir","cpFile","parallel","dependsOn","command","cwd","continuous","migrate","env","LOCAL_DEV","docker","project","trivyTargetName","dockerTargetName","imageTags","projectName","projectRoot","nameKebabCase","databasePackageAlias","adminUser","framework","preferInstallDependencies","languages"],"mappings":"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"}
@@ -11,19 +11,19 @@ use smithy.openapi#specificationExtension
11
11
  /// Use this trait if you have an operation with an HTTP method typically associated with a mutation (PUT, POST, etc) but
12
12
  /// wish for it to be considered as a query by the client
13
13
  @trait
14
- @specificationExtension
14
+ @specificationExtension(as: "x-query")
15
15
  structure query {}
16
16
 
17
17
  /// Use this trait if you have an operation with an HTTP method typically associated with a query (GET, HEAD, etc) but
18
18
  /// wish for it to be considered as a mutation by the client
19
19
  @trait
20
- @specificationExtension
20
+ @specificationExtension(as: "x-mutation")
21
21
  structure mutation {}
22
22
 
23
23
  /// By default, operations which accept a parameter named "cursor" are treated as paginated by the client
24
24
  /// Use this trait if you have an operation where the pagination cursor is named something other than "cursor"
25
25
  @trait
26
- @specificationExtension
26
+ @specificationExtension(as: "x-cursor")
27
27
  structure cursor {
28
28
  // Use inputToken to change the input parameter used for pagination
29
29
  inputToken: String
@@ -131,12 +131,17 @@ export const tsSmithyApiGenerator = async (tree, options)=>{
131
131
  addGeneratorMetadata(tree, backendFullyQualifiedName, TS_SMITHY_API_GENERATOR_INFO, metadata);
132
132
  const backendProjectConfig = readProjectConfigurationUnqualified(tree, backendFullyQualifiedName);
133
133
  const port = assignPort(tree, backendProjectConfig, 3001);
134
- // Delete default index.ts with "hello" function
135
- tree.delete(joinPathFragments(backendProjectConfig.sourceRoot, 'index.ts'));
134
+ if (!projectExists) {
135
+ // Delete default index.ts with "hello" function
136
+ tree.delete(joinPathFragments(backendProjectConfig.sourceRoot, 'index.ts'));
137
+ }
138
+ // The API's source is user-owned, so a re-run leaves existing files alone.
136
139
  generateFiles(tree, joinPathFragments(import.meta.dirname, 'files'), backendProjectConfig.sourceRoot, {
137
140
  apiNameClassName,
138
141
  port,
139
142
  ...esmVars(tree)
143
+ }, {
144
+ overwriteStrategy: OverwriteStrategy.KeepExisting
140
145
  });
141
146
  if (options.infra !== 'none') {
142
147
  if (options.auth === 'custom') {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/smithy/ts/api/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport tsProjectGenerator, {\n getTsLibDetails,\n} from '../../../ts/lib/generator.js';\nimport { addTsDependencies } from '../../../utils/add-dependencies.js';\nimport {\n API_CONSTRUCTS_DEPENDENCIES,\n API_CONSTRUCTS_PY_DEPENDENCIES,\n addApiGatewayInfra,\n} from '../../../utils/api-constructs/api-constructs.js';\nimport { addSharedConstructsOpenApiMetadataGenerateTarget } from '../../../utils/api-constructs/open-api-metadata.js';\nimport {\n addTypeScriptBundleTarget,\n BUNDLE_DEPENDENCIES,\n} from '../../../utils/bundle/bundle.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../../utils/declared-dependencies.js';\nimport { formatFilesInSubtree } from '../../../utils/format.js';\nimport { FS_DEPENDENCIES, FsCommands } from '../../../utils/fs.js';\nimport { updateGitIgnore } from '../../../utils/git.js';\nimport { resolveIac } from '../../../utils/iac.js';\nimport { installDependencies } from '../../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../../utils/metrics.js';\nimport { esmVars } from '../../../utils/module-format.js';\nimport { toClassName, toKebabCase } from '../../../utils/names.js';\nimport {\n addDependencyToTargetIfNotPresent,\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n normalizeTargetKeyOrder,\n readProjectConfigurationUnqualified,\n} from '../../../utils/nx.js';\nimport { assignPort } from '../../../utils/port.js';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n sharedConstructsGenerator,\n} from '../../../utils/shared-constructs.js';\nimport type { IacMetadata } from '../../../utils/shared-constructs-constants.js';\nimport smithyProjectGenerator from '../../project/generator.js';\nimport type { TsSmithyApiGeneratorSchema } from './schema';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface TsSmithyApiMetadata extends IacMetadata {\n readonly apiName: string;\n readonly auth: TsSmithyApiGeneratorSchema['auth'];\n readonly modelProject: string;\n}\n\n// Each entry names the branch it belongs to, so the same declaration drives both\n// adding and the version sync.\nexport const DEPENDENCIES = declareDependencies<TsSmithyApiMetadata>()({\n ts: [\n { name: '@smithy/server-apigateway' },\n { name: '@smithy/server-node' },\n { name: '@middy/core' },\n { name: '@aws-lambda-powertools/logger' },\n { name: '@aws-lambda-powertools/parameters' },\n { name: '@aws-lambda-powertools/tracer' },\n { name: '@aws-lambda-powertools/metrics' },\n { name: '@aws-sdk/client-appconfigdata' },\n // The custom authorizer handler parses its event.\n { name: '@aws-lambda-powertools/parser', when: (m) => m.auth === 'custom' },\n { name: '@types/aws-lambda', dev: true },\n // tsx runs the local server from the workspace root.\n { name: 'tsx', dev: true, root: true },\n ...ownedElsewhere(FS_DEPENDENCIES),\n ...ownedElsewhere(API_CONSTRUCTS_DEPENDENCIES),\n ...ownedElsewhere(BUNDLE_DEPENDENCIES),\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ],\n py: ownedElsewhere(API_CONSTRUCTS_PY_DEPENDENCIES),\n});\n\nexport const TS_SMITHY_API_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport const tsSmithyApiGenerator = async (\n tree: Tree,\n options: TsSmithyApiGeneratorSchema,\n): Promise<GeneratorCallback> => {\n if (\n (options.infra as string) !== 'rest-lambda' &&\n (options.infra as string) !== 'none'\n ) {\n throw new Error(\n `Unsupported infra '${options.infra}' for Smithy TypeScript API. ` +\n `Only 'rest-lambda' (API Gateway REST API) is supported.`,\n );\n }\n\n const integrationPattern = getIntegrationPattern(options);\n const apiNameClassName = toClassName(options.name);\n const apiNameKebabCase = toKebabCase(options.name);\n const { fullyQualifiedName: backendFullyQualifiedName, dir } =\n getTsLibDetails(tree, options);\n const modelProjectName = `${apiNameKebabCase}-model`;\n\n let projectExists: boolean;\n try {\n readProjectConfigurationUnqualified(tree, backendFullyQualifiedName);\n projectExists = true;\n } catch {\n projectExists = false;\n }\n\n if (!projectExists) {\n // Generate the model project\n await smithyProjectGenerator(tree, {\n name: modelProjectName,\n serviceName: apiNameClassName,\n namespace: options.namespace,\n directory: dir,\n subDirectory: 'model',\n preferInstallDependencies: false,\n });\n\n // Generate the backend project\n await tsProjectGenerator(tree, {\n name: options.name,\n directory: dir,\n subDirectory: 'backend',\n preferInstallDependencies: false,\n });\n }\n\n // Add metadata to associate backend project with model project\n const modelProjectConfig = readProjectConfigurationUnqualified(\n tree,\n modelProjectName,\n );\n updateProjectConfiguration(tree, modelProjectConfig.name, {\n ...modelProjectConfig,\n metadata: {\n ...modelProjectConfig.metadata,\n backendProject: backendFullyQualifiedName,\n } as any,\n });\n\n // Recorded in the metadata below so the version sync can tell a CDK\n // project from a Terraform one; undefined when no infrastructure was\n // generated, in which case neither provider's packages were added.\n const iac =\n options.infra !== 'none' ? await resolveIac(tree, options.iac) : undefined;\n\n // Recorded here and read by the declaration's predicates, so the packages\n // added below are exactly the ones the version sync will own.\n const metadata: TsSmithyApiMetadata = {\n apiName: options.name,\n auth: options.auth,\n modelProject: modelProjectConfig.name,\n ...(iac ? { iac } : {}),\n };\n\n addGeneratorMetadata(\n tree,\n backendFullyQualifiedName,\n TS_SMITHY_API_GENERATOR_INFO,\n metadata,\n );\n\n const backendProjectConfig = readProjectConfigurationUnqualified(\n tree,\n backendFullyQualifiedName,\n );\n const port = assignPort(tree, backendProjectConfig, 3001);\n\n // Delete default index.ts with \"hello\" function\n tree.delete(joinPathFragments(backendProjectConfig.sourceRoot, 'index.ts'));\n\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files'),\n backendProjectConfig.sourceRoot,\n {\n apiNameClassName,\n port,\n ...esmVars(tree),\n },\n );\n\n if (options.infra !== 'none') {\n if (options.auth === 'custom') {\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n '..',\n '..',\n '..',\n 'utils',\n 'api-constructs',\n 'files',\n 'cdk',\n 'authorizer',\n 'rest',\n ),\n backendProjectConfig.sourceRoot,\n {},\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n }\n\n // Add infrastructure\n await sharedConstructsGenerator(\n tree,\n {\n iac,\n },\n DEPENDENCIES,\n );\n await addApiGatewayInfra(\n tree,\n {\n iac,\n apiProjectName: backendFullyQualifiedName,\n apiNameClassName,\n apiNameKebabCase,\n auth: options.auth,\n constructType: 'rest',\n backend: {\n type: 'smithy',\n bundleOutputDir: joinPathFragments(\n 'dist',\n backendProjectConfig.root,\n 'bundle',\n ),\n integrationPattern,\n ...(options.auth === 'custom' && {\n authorizerBundleOutputDir: joinPathFragments(\n 'dist',\n backendProjectConfig.root,\n 'bundle',\n 'authorizer',\n ),\n }),\n },\n },\n DEPENDENCIES,\n );\n addSharedConstructsOpenApiMetadataGenerateTarget(tree, {\n iac,\n apiNameKebabCase,\n specPath: joinPathFragments(\n 'dist',\n modelProjectConfig.root,\n 'build',\n 'openapi',\n 'openapi.json',\n ),\n specBuildTargetName: `${modelProjectConfig.name}:build`,\n integrationPattern,\n });\n\n // Add bundle target using rolldown\n await addTypeScriptBundleTarget(\n tree,\n backendProjectConfig,\n {\n targetFilePath: 'src/handler.ts',\n external: [/@aws-sdk\\/.*/], // lambda runtime provides aws sdk\n },\n DEPENDENCIES,\n );\n\n if (options.auth === 'custom') {\n await addTypeScriptBundleTarget(\n tree,\n backendProjectConfig,\n {\n targetFilePath: 'src/authorizer.ts',\n bundleOutputDir: 'authorizer',\n external: [/@aws-sdk\\/.*/],\n },\n DEPENDENCIES,\n );\n }\n }\n\n const cmd = new FsCommands(tree, DEPENDENCIES);\n const generatedSrcDirFromRoot = '{projectRoot}/src/generated';\n\n // Target for copying the ssdk built by the model\n backendProjectConfig.targets['copy-ssdk'] = {\n cache: true,\n inputs: [\n {\n dependentTasksOutputFiles: '**/*',\n },\n ],\n executor: 'nx:run-commands',\n options: {\n commands: [\n cmd.rm(generatedSrcDirFromRoot),\n cmd.mkdir(generatedSrcDirFromRoot),\n cmd.cpDir(\n joinPathFragments('dist', modelProjectConfig.root, 'build', 'ssdk'),\n joinPathFragments(generatedSrcDirFromRoot, 'ssdk'),\n ),\n ],\n parallel: false,\n },\n outputs: ['{projectRoot}/src/generated'],\n dependsOn: [`${modelProjectConfig.name}:build`],\n };\n addDependencyToTargetIfNotPresent(\n backendProjectConfig,\n 'compile',\n 'copy-ssdk',\n );\n\n // Add a project which continuously copies based on changes to the model project\n // This allows the \"serve\" target to hot reload when the smithy model is changed\n backendProjectConfig.targets['watch-copy-ssdk'] = {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n command: `nx watch --projects=${modelProjectConfig.name} --includeDependencies -- nx run ${backendFullyQualifiedName}:copy-ssdk`,\n },\n };\n\n // Add serve target for running the server locally\n backendProjectConfig.targets.serve = normalizeTargetKeyOrder({\n executor: 'nx:run-commands',\n continuous: true,\n dependsOn: ['copy-ssdk', 'watch-copy-ssdk'],\n options: {\n command: 'tsx --watch src/local-server.ts',\n cwd: '{projectRoot}',\n },\n });\n\n const existingDevDependsOn =\n backendProjectConfig.targets['dev']?.dependsOn ?? [];\n\n backendProjectConfig.targets['dev'] = normalizeTargetKeyOrder({\n ...backendProjectConfig.targets.serve,\n // Own copy of dependsOn so adding dev dependencies below doesn't\n // mutate the shared array referenced by the serve target.\n dependsOn: [...(backendProjectConfig.targets.serve.dependsOn ?? [])],\n options: {\n ...backendProjectConfig.targets.serve.options,\n env: {\n LOCAL_DEV: 'true',\n },\n },\n });\n\n // Preserve any dependencies added to dev by connection generators\n for (const dependency of existingDevDependsOn) {\n addDependencyToTargetIfNotPresent(backendProjectConfig, 'dev', dependency);\n }\n\n // Ignore generated code\n updateGitIgnore(tree, backendProjectConfig.root, (patterns) => [\n ...patterns,\n 'src/generated',\n ]);\n\n updateProjectConfiguration(\n tree,\n backendFullyQualifiedName,\n backendProjectConfig,\n );\n\n addTsDependencies(tree, DEPENDENCIES, {\n metadata,\n projectRoot: backendProjectConfig.root,\n });\n\n await addGeneratorMetricsIfApplicable(tree, [TS_SMITHY_API_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\nconst getIntegrationPattern = (\n options: TsSmithyApiGeneratorSchema,\n): 'isolated' | 'shared' => options.integrationPattern ?? 'isolated';\n\nexport default tsSmithyApiGenerator;\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateProjectConfiguration","tsProjectGenerator","getTsLibDetails","addTsDependencies","API_CONSTRUCTS_DEPENDENCIES","API_CONSTRUCTS_PY_DEPENDENCIES","addApiGatewayInfra","addSharedConstructsOpenApiMetadataGenerateTarget","addTypeScriptBundleTarget","BUNDLE_DEPENDENCIES","declareDependencies","ownedElsewhere","formatFilesInSubtree","FS_DEPENDENCIES","FsCommands","updateGitIgnore","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","esmVars","toClassName","toKebabCase","addDependencyToTargetIfNotPresent","addGeneratorMetadata","getGeneratorInfo","normalizeTargetKeyOrder","readProjectConfigurationUnqualified","assignPort","SHARED_CONSTRUCTS_DEPENDENCIES","sharedConstructsGenerator","smithyProjectGenerator","DEPENDENCIES","ts","name","when","m","auth","dev","root","py","TS_SMITHY_API_GENERATOR_INFO","filename","tsSmithyApiGenerator","tree","options","infra","Error","integrationPattern","getIntegrationPattern","apiNameClassName","apiNameKebabCase","fullyQualifiedName","backendFullyQualifiedName","dir","modelProjectName","projectExists","serviceName","namespace","directory","subDirectory","preferInstallDependencies","modelProjectConfig","metadata","backendProject","iac","undefined","apiName","modelProject","backendProjectConfig","port","delete","sourceRoot","dirname","overwriteStrategy","KeepExisting","apiProjectName","constructType","backend","type","bundleOutputDir","authorizerBundleOutputDir","specPath","specBuildTargetName","targetFilePath","external","cmd","generatedSrcDirFromRoot","targets","cache","inputs","dependentTasksOutputFiles","executor","commands","rm","mkdir","cpDir","parallel","outputs","dependsOn","continuous","command","serve","cwd","existingDevDependsOn","env","LOCAL_DEV","dependency","patterns","projectRoot","languages"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/smithy/ts/api/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport tsProjectGenerator, {\n getTsLibDetails,\n} from '../../../ts/lib/generator.js';\nimport { addTsDependencies } from '../../../utils/add-dependencies.js';\nimport {\n API_CONSTRUCTS_DEPENDENCIES,\n API_CONSTRUCTS_PY_DEPENDENCIES,\n addApiGatewayInfra,\n} from '../../../utils/api-constructs/api-constructs.js';\nimport { addSharedConstructsOpenApiMetadataGenerateTarget } from '../../../utils/api-constructs/open-api-metadata.js';\nimport {\n addTypeScriptBundleTarget,\n BUNDLE_DEPENDENCIES,\n} from '../../../utils/bundle/bundle.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../../utils/declared-dependencies.js';\nimport { formatFilesInSubtree } from '../../../utils/format.js';\nimport { FS_DEPENDENCIES, FsCommands } from '../../../utils/fs.js';\nimport { updateGitIgnore } from '../../../utils/git.js';\nimport { resolveIac } from '../../../utils/iac.js';\nimport { installDependencies } from '../../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../../utils/metrics.js';\nimport { esmVars } from '../../../utils/module-format.js';\nimport { toClassName, toKebabCase } from '../../../utils/names.js';\nimport {\n addDependencyToTargetIfNotPresent,\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n normalizeTargetKeyOrder,\n readProjectConfigurationUnqualified,\n} from '../../../utils/nx.js';\nimport { assignPort } from '../../../utils/port.js';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n sharedConstructsGenerator,\n} from '../../../utils/shared-constructs.js';\nimport type { IacMetadata } from '../../../utils/shared-constructs-constants.js';\nimport smithyProjectGenerator from '../../project/generator.js';\nimport type { TsSmithyApiGeneratorSchema } from './schema';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface TsSmithyApiMetadata extends IacMetadata {\n readonly apiName: string;\n readonly auth: TsSmithyApiGeneratorSchema['auth'];\n readonly modelProject: string;\n}\n\n// Each entry names the branch it belongs to, so the same declaration drives both\n// adding and the version sync.\nexport const DEPENDENCIES = declareDependencies<TsSmithyApiMetadata>()({\n ts: [\n { name: '@smithy/server-apigateway' },\n { name: '@smithy/server-node' },\n { name: '@middy/core' },\n { name: '@aws-lambda-powertools/logger' },\n { name: '@aws-lambda-powertools/parameters' },\n { name: '@aws-lambda-powertools/tracer' },\n { name: '@aws-lambda-powertools/metrics' },\n { name: '@aws-sdk/client-appconfigdata' },\n // The custom authorizer handler parses its event.\n { name: '@aws-lambda-powertools/parser', when: (m) => m.auth === 'custom' },\n { name: '@types/aws-lambda', dev: true },\n // tsx runs the local server from the workspace root.\n { name: 'tsx', dev: true, root: true },\n ...ownedElsewhere(FS_DEPENDENCIES),\n ...ownedElsewhere(API_CONSTRUCTS_DEPENDENCIES),\n ...ownedElsewhere(BUNDLE_DEPENDENCIES),\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ],\n py: ownedElsewhere(API_CONSTRUCTS_PY_DEPENDENCIES),\n});\n\nexport const TS_SMITHY_API_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport const tsSmithyApiGenerator = async (\n tree: Tree,\n options: TsSmithyApiGeneratorSchema,\n): Promise<GeneratorCallback> => {\n if (\n (options.infra as string) !== 'rest-lambda' &&\n (options.infra as string) !== 'none'\n ) {\n throw new Error(\n `Unsupported infra '${options.infra}' for Smithy TypeScript API. ` +\n `Only 'rest-lambda' (API Gateway REST API) is supported.`,\n );\n }\n\n const integrationPattern = getIntegrationPattern(options);\n const apiNameClassName = toClassName(options.name);\n const apiNameKebabCase = toKebabCase(options.name);\n const { fullyQualifiedName: backendFullyQualifiedName, dir } =\n getTsLibDetails(tree, options);\n const modelProjectName = `${apiNameKebabCase}-model`;\n\n let projectExists: boolean;\n try {\n readProjectConfigurationUnqualified(tree, backendFullyQualifiedName);\n projectExists = true;\n } catch {\n projectExists = false;\n }\n\n if (!projectExists) {\n // Generate the model project\n await smithyProjectGenerator(tree, {\n name: modelProjectName,\n serviceName: apiNameClassName,\n namespace: options.namespace,\n directory: dir,\n subDirectory: 'model',\n preferInstallDependencies: false,\n });\n\n // Generate the backend project\n await tsProjectGenerator(tree, {\n name: options.name,\n directory: dir,\n subDirectory: 'backend',\n preferInstallDependencies: false,\n });\n }\n\n // Add metadata to associate backend project with model project\n const modelProjectConfig = readProjectConfigurationUnqualified(\n tree,\n modelProjectName,\n );\n updateProjectConfiguration(tree, modelProjectConfig.name, {\n ...modelProjectConfig,\n metadata: {\n ...modelProjectConfig.metadata,\n backendProject: backendFullyQualifiedName,\n } as any,\n });\n\n // Recorded in the metadata below so the version sync can tell a CDK\n // project from a Terraform one; undefined when no infrastructure was\n // generated, in which case neither provider's packages were added.\n const iac =\n options.infra !== 'none' ? await resolveIac(tree, options.iac) : undefined;\n\n // Recorded here and read by the declaration's predicates, so the packages\n // added below are exactly the ones the version sync will own.\n const metadata: TsSmithyApiMetadata = {\n apiName: options.name,\n auth: options.auth,\n modelProject: modelProjectConfig.name,\n ...(iac ? { iac } : {}),\n };\n\n addGeneratorMetadata(\n tree,\n backendFullyQualifiedName,\n TS_SMITHY_API_GENERATOR_INFO,\n metadata,\n );\n\n const backendProjectConfig = readProjectConfigurationUnqualified(\n tree,\n backendFullyQualifiedName,\n );\n const port = assignPort(tree, backendProjectConfig, 3001);\n\n if (!projectExists) {\n // Delete default index.ts with \"hello\" function\n tree.delete(joinPathFragments(backendProjectConfig.sourceRoot, 'index.ts'));\n }\n\n // The API's source is user-owned, so a re-run leaves existing files alone.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files'),\n backendProjectConfig.sourceRoot,\n {\n apiNameClassName,\n port,\n ...esmVars(tree),\n },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n if (options.infra !== 'none') {\n if (options.auth === 'custom') {\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n '..',\n '..',\n '..',\n 'utils',\n 'api-constructs',\n 'files',\n 'cdk',\n 'authorizer',\n 'rest',\n ),\n backendProjectConfig.sourceRoot,\n {},\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n }\n\n // Add infrastructure\n await sharedConstructsGenerator(\n tree,\n {\n iac,\n },\n DEPENDENCIES,\n );\n await addApiGatewayInfra(\n tree,\n {\n iac,\n apiProjectName: backendFullyQualifiedName,\n apiNameClassName,\n apiNameKebabCase,\n auth: options.auth,\n constructType: 'rest',\n backend: {\n type: 'smithy',\n bundleOutputDir: joinPathFragments(\n 'dist',\n backendProjectConfig.root,\n 'bundle',\n ),\n integrationPattern,\n ...(options.auth === 'custom' && {\n authorizerBundleOutputDir: joinPathFragments(\n 'dist',\n backendProjectConfig.root,\n 'bundle',\n 'authorizer',\n ),\n }),\n },\n },\n DEPENDENCIES,\n );\n addSharedConstructsOpenApiMetadataGenerateTarget(tree, {\n iac,\n apiNameKebabCase,\n specPath: joinPathFragments(\n 'dist',\n modelProjectConfig.root,\n 'build',\n 'openapi',\n 'openapi.json',\n ),\n specBuildTargetName: `${modelProjectConfig.name}:build`,\n integrationPattern,\n });\n\n // Add bundle target using rolldown\n await addTypeScriptBundleTarget(\n tree,\n backendProjectConfig,\n {\n targetFilePath: 'src/handler.ts',\n external: [/@aws-sdk\\/.*/], // lambda runtime provides aws sdk\n },\n DEPENDENCIES,\n );\n\n if (options.auth === 'custom') {\n await addTypeScriptBundleTarget(\n tree,\n backendProjectConfig,\n {\n targetFilePath: 'src/authorizer.ts',\n bundleOutputDir: 'authorizer',\n external: [/@aws-sdk\\/.*/],\n },\n DEPENDENCIES,\n );\n }\n }\n\n const cmd = new FsCommands(tree, DEPENDENCIES);\n const generatedSrcDirFromRoot = '{projectRoot}/src/generated';\n\n // Target for copying the ssdk built by the model\n backendProjectConfig.targets['copy-ssdk'] = {\n cache: true,\n inputs: [\n {\n dependentTasksOutputFiles: '**/*',\n },\n ],\n executor: 'nx:run-commands',\n options: {\n commands: [\n cmd.rm(generatedSrcDirFromRoot),\n cmd.mkdir(generatedSrcDirFromRoot),\n cmd.cpDir(\n joinPathFragments('dist', modelProjectConfig.root, 'build', 'ssdk'),\n joinPathFragments(generatedSrcDirFromRoot, 'ssdk'),\n ),\n ],\n parallel: false,\n },\n outputs: ['{projectRoot}/src/generated'],\n dependsOn: [`${modelProjectConfig.name}:build`],\n };\n addDependencyToTargetIfNotPresent(\n backendProjectConfig,\n 'compile',\n 'copy-ssdk',\n );\n\n // Add a project which continuously copies based on changes to the model project\n // This allows the \"serve\" target to hot reload when the smithy model is changed\n backendProjectConfig.targets['watch-copy-ssdk'] = {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n command: `nx watch --projects=${modelProjectConfig.name} --includeDependencies -- nx run ${backendFullyQualifiedName}:copy-ssdk`,\n },\n };\n\n // Add serve target for running the server locally\n backendProjectConfig.targets.serve = normalizeTargetKeyOrder({\n executor: 'nx:run-commands',\n continuous: true,\n dependsOn: ['copy-ssdk', 'watch-copy-ssdk'],\n options: {\n command: 'tsx --watch src/local-server.ts',\n cwd: '{projectRoot}',\n },\n });\n\n const existingDevDependsOn =\n backendProjectConfig.targets['dev']?.dependsOn ?? [];\n\n backendProjectConfig.targets['dev'] = normalizeTargetKeyOrder({\n ...backendProjectConfig.targets.serve,\n // Own copy of dependsOn so adding dev dependencies below doesn't\n // mutate the shared array referenced by the serve target.\n dependsOn: [...(backendProjectConfig.targets.serve.dependsOn ?? [])],\n options: {\n ...backendProjectConfig.targets.serve.options,\n env: {\n LOCAL_DEV: 'true',\n },\n },\n });\n\n // Preserve any dependencies added to dev by connection generators\n for (const dependency of existingDevDependsOn) {\n addDependencyToTargetIfNotPresent(backendProjectConfig, 'dev', dependency);\n }\n\n // Ignore generated code\n updateGitIgnore(tree, backendProjectConfig.root, (patterns) => [\n ...patterns,\n 'src/generated',\n ]);\n\n updateProjectConfiguration(\n tree,\n backendFullyQualifiedName,\n backendProjectConfig,\n );\n\n addTsDependencies(tree, DEPENDENCIES, {\n metadata,\n projectRoot: backendProjectConfig.root,\n });\n\n await addGeneratorMetricsIfApplicable(tree, [TS_SMITHY_API_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\nconst getIntegrationPattern = (\n options: TsSmithyApiGeneratorSchema,\n): 'isolated' | 'shared' => options.integrationPattern ?? 'isolated';\n\nexport default tsSmithyApiGenerator;\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateProjectConfiguration","tsProjectGenerator","getTsLibDetails","addTsDependencies","API_CONSTRUCTS_DEPENDENCIES","API_CONSTRUCTS_PY_DEPENDENCIES","addApiGatewayInfra","addSharedConstructsOpenApiMetadataGenerateTarget","addTypeScriptBundleTarget","BUNDLE_DEPENDENCIES","declareDependencies","ownedElsewhere","formatFilesInSubtree","FS_DEPENDENCIES","FsCommands","updateGitIgnore","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","esmVars","toClassName","toKebabCase","addDependencyToTargetIfNotPresent","addGeneratorMetadata","getGeneratorInfo","normalizeTargetKeyOrder","readProjectConfigurationUnqualified","assignPort","SHARED_CONSTRUCTS_DEPENDENCIES","sharedConstructsGenerator","smithyProjectGenerator","DEPENDENCIES","ts","name","when","m","auth","dev","root","py","TS_SMITHY_API_GENERATOR_INFO","filename","tsSmithyApiGenerator","tree","options","infra","Error","integrationPattern","getIntegrationPattern","apiNameClassName","apiNameKebabCase","fullyQualifiedName","backendFullyQualifiedName","dir","modelProjectName","projectExists","serviceName","namespace","directory","subDirectory","preferInstallDependencies","modelProjectConfig","metadata","backendProject","iac","undefined","apiName","modelProject","backendProjectConfig","port","delete","sourceRoot","dirname","overwriteStrategy","KeepExisting","apiProjectName","constructType","backend","type","bundleOutputDir","authorizerBundleOutputDir","specPath","specBuildTargetName","targetFilePath","external","cmd","generatedSrcDirFromRoot","targets","cache","inputs","dependentTasksOutputFiles","executor","commands","rm","mkdir","cpDir","parallel","outputs","dependsOn","continuous","command","serve","cwd","existingDevDependsOn","env","LOCAL_DEV","dependency","patterns","projectRoot","languages"],"mappings":"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"}
@@ -112,9 +112,11 @@ export async function terraformProjectGenerator(tree, schema) {
112
112
  const distDir = joinPathFragments(outDirToRootRelativePath, 'dist', '{projectRoot}');
113
113
  const tfDistDir = joinPathFragments(distDir, 'terraform');
114
114
  const checkovReportJsonPath = joinPathFragments(distDir, 'checkov', 'checkov_report.json');
115
- // `test` keeps its `.terraform` here rather than in `src`, so initialising it
116
- // never races the backend-configured targets over the shared one.
115
+ // `test` and `validate` each keep their `.terraform` here rather than in
116
+ // `src`, so initialising one never races the backend-configured targets, or
117
+ // the other, over the shared one.
117
118
  const testDataDir = joinPathFragments(distDir, 'terraform-test');
119
+ const validateDataDir = joinPathFragments(distDir, 'terraform-validate');
118
120
  // Provider downloads persist here, so a target whose `.terraform` was cleaned
119
121
  // links the providers it already has rather than re-downloading them. Nx does
120
122
  // not interpolate `{workspaceRoot}` inside `env`, so this is relative to the
@@ -369,20 +371,37 @@ export async function terraformProjectGenerator(tree, schema) {
369
371
  }
370
372
  }
371
373
  },
374
+ // Mirrors `test`: `-backend=false` installs the modules and providers
375
+ // validation needs without configuring the S3 backend, so this runs on a
376
+ // fresh workspace before `bootstrap` and needs no credentials. `TF_DATA_DIR`
377
+ // keeps that `.terraform` out of `src`, so it never races the
378
+ // backend-configured targets over the shared one, and declaring no outputs
379
+ // keeps a cache hit to what it asserts (see `test` above).
372
380
  validate: {
373
381
  executor: 'nx:run-commands',
374
382
  cache: true,
375
383
  inputs: [
376
- 'default'
384
+ 'default',
385
+ '^production'
377
386
  ],
387
+ outputs: [],
378
388
  options: {
379
- command: 'terraform validate',
389
+ commands: [
390
+ {
391
+ command: `shx mkdir -p ${pluginCacheDir}`,
392
+ forwardAllArgs: false
393
+ },
394
+ 'terraform init -backend=false',
395
+ 'terraform validate'
396
+ ],
380
397
  forwardAllArgs: true,
381
- cwd: '{projectRoot}/src'
382
- },
383
- dependsOn: [
384
- 'init'
385
- ]
398
+ cwd: '{projectRoot}/src',
399
+ parallel: false,
400
+ env: {
401
+ TF_DATA_DIR: validateDataDir,
402
+ TF_PLUGIN_CACHE_DIR: pluginCacheDir
403
+ }
404
+ }
386
405
  }
387
406
  };
388
407
  const projectConfiguration = {
@@ -406,12 +425,17 @@ export async function terraformProjectGenerator(tree, schema) {
406
425
  addGeneratorMetadata(tree, lib.fullyQualifiedName, TERRAFORM_PROJECT_GENERATOR_INFO, {
407
426
  iac: 'terraform'
408
427
  });
428
+ // The guides tell the reader to declare resources in `main.tf`, add variables
429
+ // and outputs, and configure environments in `env/*.tfvars`, so everything
430
+ // here is scaffolded once and then left alone. Provider version bumps reach
431
+ // `providers.tf` through the vended version sync, which rewrites the pin in
432
+ // place rather than the whole file.
409
433
  generateFiles(tree, joinPathFragments(import.meta.dirname, `./files/${schema.type}`), lib.dir, {
410
434
  metricsModulePath,
411
435
  stateKeyPrefix: kebabCase(lib.fullyQualifiedName),
412
436
  ...terraformProviderVersions()
413
437
  }, {
414
- overwriteStrategy: OverwriteStrategy.Overwrite
438
+ overwriteStrategy: OverwriteStrategy.KeepExisting
415
439
  });
416
440
  // Checkov skips are the user's to curate, so preserve any they have added.
417
441
  generateFiles(tree, joinPathFragments(import.meta.dirname, './files/checkov'), lib.dir, {}, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../packages/nx-plugin/src/terraform/project/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n addProjectConfiguration,\n detectPackageManager,\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n readNxJson,\n type TargetConfiguration,\n type Tree,\n updateJson,\n updateNxJson,\n} from '@nx/devkit';\nimport { join, relative } from 'path';\nimport { addLicenseCheckToLintTarget } from '../../license/config.js';\nimport { getTsLibDetails } from '../../ts/lib/generator.js';\nimport { addTsDependencies } from '../../utils/add-dependencies.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../utils/declared-dependencies.js';\nimport { formatFilesInSubtree } from '../../utils/format.js';\nimport { updateGitIgnore } from '../../utils/git.js';\nimport { installDependencies } from '../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics.js';\nimport { kebabCase } from '../../utils/names.js';\nimport {\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n projectExists,\n} from '../../utils/nx.js';\nimport { sortObjectKeys } from '../../utils/object.js';\nimport { uvxCommand } from '../../utils/py.js';\nimport { sharedConstructsGenerator } from '../../utils/shared-constructs.js';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n SHARED_TERRAFORM_DIR,\n SHARED_TERRAFORM_NAME,\n} from '../../utils/shared-constructs-constants.js';\nimport {\n terraformProviderVersions,\n withVersions,\n} from '../../utils/versions.js';\nimport type { TerraformProjectGeneratorSchema } from './schema';\n\n// Terraform projects carry no package.json, so their build tooling and the AWS\n// SDK the vended deploy scripts import are declared at the workspace root. This\n// generator records no metadata, so nothing a predicate could read.\nexport const DEPENDENCIES = declareDependencies()({\n ts: [\n { name: '@nx-extend/terraform', dev: true, root: true },\n { name: 'shx', dev: true, root: true },\n { name: 'tsx', dev: true, root: true },\n { name: '@aws-sdk/client-s3', dev: true, root: true },\n { name: '@aws-sdk/client-sts', dev: true, root: true },\n { name: '@aws-sdk/credential-providers', dev: true, root: true },\n { name: '@smithy/config-resolver', dev: true, root: true },\n { name: '@smithy/node-config-provider', dev: true, root: true },\n // Declared for its pinned version, which goes into npm's `overrides` below.\n { name: '@nx/devkit', versionOnly: true },\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ],\n});\n\nconst NX_EXTEND_PLUGIN = '@nx-extend/terraform';\nexport const TERRAFORM_PROJECT_GENERATOR_INFO: NxGeneratorInfo =\n getGeneratorInfo(import.meta.filename);\n\n/**\n * Checks formatting, mirroring the TypeScript and Python `format` targets: the\n * base target fails on an unformatted file and the `fix` configuration rewrites\n * it. Writing from the base target would rewrite the `default` input the hash is\n * computed over, so the target could never cache-hit.\n *\n * Scoped to the project's own `src` rather than `-recursive`, so it checks the\n * files the vended templates cover. `-diff` names what to fix when it fails.\n */\nexport const TERRAFORM_FORMAT_TARGET: TargetConfiguration = {\n executor: 'nx:run-commands',\n cache: true,\n inputs: ['default'],\n options: {\n command: 'terraform fmt -check -diff',\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n },\n configurations: {\n fix: {\n command: 'terraform fmt',\n },\n 'skip-lint': {\n // Cross-platform no-op (`true` is not available on Windows cmd).\n command: 'node -e \"\"',\n },\n },\n};\n\nexport async function terraformProjectGenerator(\n tree: Tree,\n schema: TerraformProjectGeneratorSchema,\n): Promise<GeneratorCallback> {\n // Just use getTsLibDetails as it isn't specific to TS\n const lib = getTsLibDetails(tree, schema);\n const { fullyQualifiedName: sharedTfProjectName } = getTsLibDetails(tree, {\n name: SHARED_TERRAFORM_NAME,\n });\n\n const outDirToRootRelativePath = relative(\n join(tree.root, lib.dir, 'src'),\n tree.root,\n ).replace(/\\\\/g, '/');\n const distDir = joinPathFragments(\n outDirToRootRelativePath,\n 'dist',\n '{projectRoot}',\n );\n const tfDistDir = joinPathFragments(distDir, 'terraform');\n const checkovReportJsonPath = joinPathFragments(\n distDir,\n 'checkov',\n 'checkov_report.json',\n );\n // `test` keeps its `.terraform` here rather than in `src`, so initialising it\n // never races the backend-configured targets over the shared one.\n const testDataDir = joinPathFragments(distDir, 'terraform-test');\n\n // Provider downloads persist here, so a target whose `.terraform` was cleaned\n // links the providers it already has rather than re-downloading them. Nx does\n // not interpolate `{workspaceRoot}` inside `env`, so this is relative to the\n // target's `cwd`. It sits under `.terraform`, which this generator gitignores\n // — that is also what keeps the providers out of Nx's file walk — and unlike\n // `.nx/cache` it survives `nx reset`.\n //\n // One cache per project rather than one for the workspace: two `terraform\n // init` runs filling a shared cache concurrently each compute a different hash\n // for the same provider, because the hash covers a directory the other is\n // still writing, and terraform then rejects the mismatch against the lock\n // file. Per project, no two writers ever meet, so the targets stay parallel.\n const pluginCacheDir = joinPathFragments(\n outDirToRootRelativePath,\n '.terraform',\n 'plugin-cache',\n '{projectRoot}',\n );\n\n // Calculate relative path from current project to common/terraform/metrics\n // Use forward slashes for terraform module source paths (even on Windows)\n const metricsModulePath = relative(\n join(tree.root, lib.dir, 'src'),\n join(tree.root, 'packages', SHARED_TERRAFORM_DIR, 'src', 'metrics'),\n ).replace(/\\\\/g, '/');\n\n updateGitIgnore(tree, '.', (patterns) => [...patterns, '.terraform']);\n\n const applicationTargets: {\n [targetName: string]: TargetConfiguration;\n } = {\n apply: {\n executor: 'nx:run-commands',\n defaultConfiguration: 'dev',\n configurations: {\n dev: {\n command: `terraform apply ${tfDistDir}/dev.tfplan`,\n },\n },\n options: {\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n },\n dependsOn: ['plan'],\n },\n bootstrap: {\n executor: 'nx:run-commands',\n options: {\n forwardAllArgs: true,\n commands: ['tsx {projectRoot}/scripts/bootstrap.ts {projectRoot}'],\n cwd: '{workspaceRoot}',\n },\n },\n 'bootstrap-destroy': {\n executor: 'nx:run-commands',\n options: {\n forwardAllArgs: true,\n commands: [\n 'tsx {projectRoot}/scripts/bootstrap-destroy.ts {projectRoot}',\n ],\n cwd: '{workspaceRoot}',\n },\n },\n build: {\n dependsOn: ['format', 'checkov', 'test', `${sharedTfProjectName}:build`],\n },\n deploy: {\n dependsOn: ['apply'],\n },\n // The artifact-only sibling of build, which `plan` depends on.\n assemble: {\n dependsOn: [`${sharedTfProjectName}:assemble`],\n },\n destroy: {\n executor: 'nx:run-commands',\n defaultConfiguration: 'dev',\n configurations: {\n dev: {\n command: 'terraform destroy -var-file=env/dev.tfvars',\n },\n },\n options: {\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n },\n dependsOn: ['init'],\n },\n init: {\n executor: 'nx:run-commands',\n defaultConfiguration: 'dev',\n configurations: {\n dev: {\n env: { TF_ENV: 'dev' },\n },\n },\n options: {\n forwardAllArgs: true,\n commands: ['tsx {projectRoot}/scripts/init.ts {projectRoot}'],\n cwd: '{workspaceRoot}',\n },\n dependsOn: ['^init'],\n },\n output: {\n executor: 'nx:run-commands',\n cache: true,\n inputs: ['default'],\n options: {\n command: 'terraform output -json',\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n },\n },\n plan: {\n executor: 'nx:run-commands',\n defaultConfiguration: 'dev',\n configurations: {\n dev: {\n commands: [\n `shx mkdir -p ${tfDistDir}`,\n `terraform plan -var-file=env/dev.tfvars -out=${tfDistDir}/dev.tfplan`,\n ],\n },\n },\n options: {\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n parallel: false,\n },\n dependsOn: ['init', 'validate', '^validate', 'assemble'],\n },\n };\n\n const libTargets: {\n [targetName: string]: TargetConfiguration;\n } = {\n build: {\n dependsOn: ['format', 'checkov', 'test'],\n },\n // A Terraform library vends modules rather than a deployable artifact, so\n // its `assemble` carries only whatever the consuming projects register on it.\n assemble: {\n executor: 'nx:noop',\n },\n format: TERRAFORM_FORMAT_TARGET,\n // Terraform has no linter of its own, so `lint` orchestrates the format\n // check. It exists so `nx run-many --target lint` reaches terraform\n // projects, and so `--configuration=fix` and `--configuration=skip-lint`\n // propagate to `format` the way they do for TypeScript and Python projects.\n lint: {\n dependsOn: ['format'],\n },\n init: {\n executor: 'nx:run-commands',\n defaultConfiguration: 'dev',\n configurations: {\n dev: {\n commands: [\n {\n command: `shx mkdir -p ${pluginCacheDir}`,\n forwardAllArgs: false,\n },\n 'terraform init',\n ],\n },\n },\n options: {\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n parallel: false,\n env: { TF_PLUGIN_CACHE_DIR: pluginCacheDir },\n },\n },\n // `^production` mirrors `test`: checkov resolves the relative modules a\n // project consumes, so a change in one must invalidate the scan.\n checkov: {\n executor: 'nx:run-commands',\n cache: true,\n inputs: ['default', '^production'],\n outputs: ['{workspaceRoot}/dist/{projectRoot}/checkov'],\n options: {\n command: uvxCommand(\n 'checkov',\n `--config-file ../checkov.yml --directory . -o cli -o json --output-file-path console,${checkovReportJsonPath}`,\n ),\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n },\n },\n // Terraform's native test framework, which runs any `.tftest.hcl` files.\n // A project with none is a no-op success.\n //\n // `-backend=false` installs the modules and providers the tests need\n // without configuring the S3 backend, so this runs before `bootstrap` and\n // needs no credentials. `TF_DATA_DIR` keeps that `.terraform` out of `src`,\n // so it never races the backend-configured targets over the shared one.\n // `^production` is what invalidates the cache when a consumed module\n // changes; `{projectRoot}/**/*` alone would serve a stale pass.\n //\n // `TF_DATA_DIR` is terraform's working directory, not an artifact: its\n // provider entries are symlinks into the shared plugin cache, so restoring\n // it on another machine would yield dangling links while the commands that\n // repopulate them are skipped. Declaring no outputs keeps a cache hit to\n // what it actually asserts — that the tests passed for these inputs.\n test: {\n executor: 'nx:run-commands',\n cache: true,\n inputs: ['default', '^production'],\n outputs: [],\n options: {\n commands: [\n { command: `shx mkdir -p ${pluginCacheDir}`, forwardAllArgs: false },\n 'terraform init -backend=false',\n 'terraform test',\n ],\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n parallel: false,\n env: { TF_DATA_DIR: testDataDir, TF_PLUGIN_CACHE_DIR: pluginCacheDir },\n },\n },\n validate: {\n executor: 'nx:run-commands',\n cache: true,\n inputs: ['default'],\n options: {\n command: 'terraform validate',\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n },\n dependsOn: ['init'],\n },\n };\n\n const projectConfiguration = {\n root: lib.dir,\n projectType: schema.type,\n sourceRoot: joinPathFragments(lib.dir, 'src'),\n targets: sortObjectKeys({\n ...libTargets,\n ...(schema.type === 'application' ? applicationTargets : {}),\n }),\n };\n\n // Only create the project configuration on first run; skip it on re-run so\n // existing project.json customisations are preserved.\n if (!projectExists(tree, lib.fullyQualifiedName)) {\n addProjectConfiguration(tree, lib.fullyQualifiedName, projectConfiguration);\n }\n\n // The `lint` target checks licenses alongside formatting, as it does for\n // TypeScript and Python projects.\n addLicenseCheckToLintTarget(tree, lib.fullyQualifiedName);\n\n // This generator IS the Terraform project, so the provider is fixed.\n addGeneratorMetadata(\n tree,\n lib.fullyQualifiedName,\n TERRAFORM_PROJECT_GENERATOR_INFO,\n { iac: 'terraform' },\n );\n\n generateFiles(\n tree, // the virtual file system\n joinPathFragments(import.meta.dirname, `./files/${schema.type}`), // path to the file templates\n lib.dir, // destination path of the files\n {\n metricsModulePath,\n stateKeyPrefix: kebabCase(lib.fullyQualifiedName),\n ...terraformProviderVersions(),\n },\n {\n overwriteStrategy: OverwriteStrategy.Overwrite,\n },\n );\n\n // Checkov skips are the user's to curate, so preserve any they have added.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, './files/checkov'),\n lib.dir,\n {},\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n const nxJson = readNxJson(tree);\n\n if (\n !nxJson.plugins?.find((p) =>\n typeof p === 'string'\n ? p === NX_EXTEND_PLUGIN\n : p.plugin === NX_EXTEND_PLUGIN,\n )\n ) {\n nxJson.plugins = [...(nxJson.plugins ?? []), NX_EXTEND_PLUGIN];\n updateNxJson(tree, nxJson);\n }\n\n // Ensure shared constructs for Terraform are created\n await sharedConstructsGenerator(tree, { iac: 'terraform' }, DEPENDENCIES);\n\n // Add Terraform metrics\n await addGeneratorMetricsIfApplicable(tree, [\n TERRAFORM_PROJECT_GENERATOR_INFO,\n ]);\n\n addTsDependencies(tree, DEPENDENCIES);\n\n // @nx-extend/terraform has a peer dependency on @nx/devkit ^21.0.0 which causes\n // npm install to fail, so for NPM we add a resolution\n // Can remove when https://github.com/TriPSs/nx-extend/issues/407 is addressed\n if (detectPackageManager() === 'npm') {\n updateJson(tree, 'package.json', (packageJson) => {\n packageJson.overrides = {\n ...packageJson.overrides,\n ...withVersions(DEPENDENCIES, ['@nx/devkit']),\n };\n return packageJson;\n });\n }\n\n // `updateProjectConfiguration` re-serialises project.json with every inline\n // array expanded, which the vended `format` target rejects.\n await formatFilesInSubtree(tree);\n\n // `@nx-extend/terraform` is registered as an Nx plugin in nx.json, so Nx\n // loads it when computing the project graph — it must resolve even if the\n // caller would otherwise prefer to defer installing.\n return () =>\n installDependencies(tree, schema.preferInstallDependencies, {\n languages: ['typescript'],\n ensureResolvable: [NX_EXTEND_PLUGIN],\n });\n}\nexport default terraformProjectGenerator;\n"],"names":["addProjectConfiguration","detectPackageManager","generateFiles","joinPathFragments","OverwriteStrategy","readNxJson","updateJson","updateNxJson","join","relative","addLicenseCheckToLintTarget","getTsLibDetails","addTsDependencies","declareDependencies","ownedElsewhere","formatFilesInSubtree","updateGitIgnore","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","addGeneratorMetadata","getGeneratorInfo","projectExists","sortObjectKeys","uvxCommand","sharedConstructsGenerator","SHARED_CONSTRUCTS_DEPENDENCIES","SHARED_TERRAFORM_DIR","SHARED_TERRAFORM_NAME","terraformProviderVersions","withVersions","DEPENDENCIES","ts","name","dev","root","versionOnly","NX_EXTEND_PLUGIN","TERRAFORM_PROJECT_GENERATOR_INFO","filename","TERRAFORM_FORMAT_TARGET","executor","cache","inputs","options","command","forwardAllArgs","cwd","configurations","fix","terraformProjectGenerator","tree","schema","lib","fullyQualifiedName","sharedTfProjectName","outDirToRootRelativePath","dir","replace","distDir","tfDistDir","checkovReportJsonPath","testDataDir","pluginCacheDir","metricsModulePath","patterns","applicationTargets","apply","defaultConfiguration","dependsOn","bootstrap","commands","build","deploy","assemble","destroy","init","env","TF_ENV","output","plan","parallel","libTargets","format","lint","TF_PLUGIN_CACHE_DIR","checkov","outputs","test","TF_DATA_DIR","validate","projectConfiguration","projectType","type","sourceRoot","targets","iac","dirname","stateKeyPrefix","overwriteStrategy","Overwrite","KeepExisting","nxJson","plugins","find","p","plugin","packageJson","overrides","preferInstallDependencies","languages","ensureResolvable"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/terraform/project/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n addProjectConfiguration,\n detectPackageManager,\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n readNxJson,\n type TargetConfiguration,\n type Tree,\n updateJson,\n updateNxJson,\n} from '@nx/devkit';\nimport { join, relative } from 'path';\nimport { addLicenseCheckToLintTarget } from '../../license/config.js';\nimport { getTsLibDetails } from '../../ts/lib/generator.js';\nimport { addTsDependencies } from '../../utils/add-dependencies.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../utils/declared-dependencies.js';\nimport { formatFilesInSubtree } from '../../utils/format.js';\nimport { updateGitIgnore } from '../../utils/git.js';\nimport { installDependencies } from '../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics.js';\nimport { kebabCase } from '../../utils/names.js';\nimport {\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n projectExists,\n} from '../../utils/nx.js';\nimport { sortObjectKeys } from '../../utils/object.js';\nimport { uvxCommand } from '../../utils/py.js';\nimport { sharedConstructsGenerator } from '../../utils/shared-constructs.js';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n SHARED_TERRAFORM_DIR,\n SHARED_TERRAFORM_NAME,\n} from '../../utils/shared-constructs-constants.js';\nimport {\n terraformProviderVersions,\n withVersions,\n} from '../../utils/versions.js';\nimport type { TerraformProjectGeneratorSchema } from './schema';\n\n// Terraform projects carry no package.json, so their build tooling and the AWS\n// SDK the vended deploy scripts import are declared at the workspace root. This\n// generator records no metadata, so nothing a predicate could read.\nexport const DEPENDENCIES = declareDependencies()({\n ts: [\n { name: '@nx-extend/terraform', dev: true, root: true },\n { name: 'shx', dev: true, root: true },\n { name: 'tsx', dev: true, root: true },\n { name: '@aws-sdk/client-s3', dev: true, root: true },\n { name: '@aws-sdk/client-sts', dev: true, root: true },\n { name: '@aws-sdk/credential-providers', dev: true, root: true },\n { name: '@smithy/config-resolver', dev: true, root: true },\n { name: '@smithy/node-config-provider', dev: true, root: true },\n // Declared for its pinned version, which goes into npm's `overrides` below.\n { name: '@nx/devkit', versionOnly: true },\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ],\n});\n\nconst NX_EXTEND_PLUGIN = '@nx-extend/terraform';\nexport const TERRAFORM_PROJECT_GENERATOR_INFO: NxGeneratorInfo =\n getGeneratorInfo(import.meta.filename);\n\n/**\n * Checks formatting, mirroring the TypeScript and Python `format` targets: the\n * base target fails on an unformatted file and the `fix` configuration rewrites\n * it. Writing from the base target would rewrite the `default` input the hash is\n * computed over, so the target could never cache-hit.\n *\n * Scoped to the project's own `src` rather than `-recursive`, so it checks the\n * files the vended templates cover. `-diff` names what to fix when it fails.\n */\nexport const TERRAFORM_FORMAT_TARGET: TargetConfiguration = {\n executor: 'nx:run-commands',\n cache: true,\n inputs: ['default'],\n options: {\n command: 'terraform fmt -check -diff',\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n },\n configurations: {\n fix: {\n command: 'terraform fmt',\n },\n 'skip-lint': {\n // Cross-platform no-op (`true` is not available on Windows cmd).\n command: 'node -e \"\"',\n },\n },\n};\n\nexport async function terraformProjectGenerator(\n tree: Tree,\n schema: TerraformProjectGeneratorSchema,\n): Promise<GeneratorCallback> {\n // Just use getTsLibDetails as it isn't specific to TS\n const lib = getTsLibDetails(tree, schema);\n const { fullyQualifiedName: sharedTfProjectName } = getTsLibDetails(tree, {\n name: SHARED_TERRAFORM_NAME,\n });\n\n const outDirToRootRelativePath = relative(\n join(tree.root, lib.dir, 'src'),\n tree.root,\n ).replace(/\\\\/g, '/');\n const distDir = joinPathFragments(\n outDirToRootRelativePath,\n 'dist',\n '{projectRoot}',\n );\n const tfDistDir = joinPathFragments(distDir, 'terraform');\n const checkovReportJsonPath = joinPathFragments(\n distDir,\n 'checkov',\n 'checkov_report.json',\n );\n // `test` and `validate` each keep their `.terraform` here rather than in\n // `src`, so initialising one never races the backend-configured targets, or\n // the other, over the shared one.\n const testDataDir = joinPathFragments(distDir, 'terraform-test');\n const validateDataDir = joinPathFragments(distDir, 'terraform-validate');\n\n // Provider downloads persist here, so a target whose `.terraform` was cleaned\n // links the providers it already has rather than re-downloading them. Nx does\n // not interpolate `{workspaceRoot}` inside `env`, so this is relative to the\n // target's `cwd`. It sits under `.terraform`, which this generator gitignores\n // — that is also what keeps the providers out of Nx's file walk — and unlike\n // `.nx/cache` it survives `nx reset`.\n //\n // One cache per project rather than one for the workspace: two `terraform\n // init` runs filling a shared cache concurrently each compute a different hash\n // for the same provider, because the hash covers a directory the other is\n // still writing, and terraform then rejects the mismatch against the lock\n // file. Per project, no two writers ever meet, so the targets stay parallel.\n const pluginCacheDir = joinPathFragments(\n outDirToRootRelativePath,\n '.terraform',\n 'plugin-cache',\n '{projectRoot}',\n );\n\n // Calculate relative path from current project to common/terraform/metrics\n // Use forward slashes for terraform module source paths (even on Windows)\n const metricsModulePath = relative(\n join(tree.root, lib.dir, 'src'),\n join(tree.root, 'packages', SHARED_TERRAFORM_DIR, 'src', 'metrics'),\n ).replace(/\\\\/g, '/');\n\n updateGitIgnore(tree, '.', (patterns) => [...patterns, '.terraform']);\n\n const applicationTargets: {\n [targetName: string]: TargetConfiguration;\n } = {\n apply: {\n executor: 'nx:run-commands',\n defaultConfiguration: 'dev',\n configurations: {\n dev: {\n command: `terraform apply ${tfDistDir}/dev.tfplan`,\n },\n },\n options: {\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n },\n dependsOn: ['plan'],\n },\n bootstrap: {\n executor: 'nx:run-commands',\n options: {\n forwardAllArgs: true,\n commands: ['tsx {projectRoot}/scripts/bootstrap.ts {projectRoot}'],\n cwd: '{workspaceRoot}',\n },\n },\n 'bootstrap-destroy': {\n executor: 'nx:run-commands',\n options: {\n forwardAllArgs: true,\n commands: [\n 'tsx {projectRoot}/scripts/bootstrap-destroy.ts {projectRoot}',\n ],\n cwd: '{workspaceRoot}',\n },\n },\n build: {\n dependsOn: ['format', 'checkov', 'test', `${sharedTfProjectName}:build`],\n },\n deploy: {\n dependsOn: ['apply'],\n },\n // The artifact-only sibling of build, which `plan` depends on.\n assemble: {\n dependsOn: [`${sharedTfProjectName}:assemble`],\n },\n destroy: {\n executor: 'nx:run-commands',\n defaultConfiguration: 'dev',\n configurations: {\n dev: {\n command: 'terraform destroy -var-file=env/dev.tfvars',\n },\n },\n options: {\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n },\n dependsOn: ['init'],\n },\n init: {\n executor: 'nx:run-commands',\n defaultConfiguration: 'dev',\n configurations: {\n dev: {\n env: { TF_ENV: 'dev' },\n },\n },\n options: {\n forwardAllArgs: true,\n commands: ['tsx {projectRoot}/scripts/init.ts {projectRoot}'],\n cwd: '{workspaceRoot}',\n },\n dependsOn: ['^init'],\n },\n output: {\n executor: 'nx:run-commands',\n cache: true,\n inputs: ['default'],\n options: {\n command: 'terraform output -json',\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n },\n },\n plan: {\n executor: 'nx:run-commands',\n defaultConfiguration: 'dev',\n configurations: {\n dev: {\n commands: [\n `shx mkdir -p ${tfDistDir}`,\n `terraform plan -var-file=env/dev.tfvars -out=${tfDistDir}/dev.tfplan`,\n ],\n },\n },\n options: {\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n parallel: false,\n },\n dependsOn: ['init', 'validate', '^validate', 'assemble'],\n },\n };\n\n const libTargets: {\n [targetName: string]: TargetConfiguration;\n } = {\n build: {\n dependsOn: ['format', 'checkov', 'test'],\n },\n // A Terraform library vends modules rather than a deployable artifact, so\n // its `assemble` carries only whatever the consuming projects register on it.\n assemble: {\n executor: 'nx:noop',\n },\n format: TERRAFORM_FORMAT_TARGET,\n // Terraform has no linter of its own, so `lint` orchestrates the format\n // check. It exists so `nx run-many --target lint` reaches terraform\n // projects, and so `--configuration=fix` and `--configuration=skip-lint`\n // propagate to `format` the way they do for TypeScript and Python projects.\n lint: {\n dependsOn: ['format'],\n },\n init: {\n executor: 'nx:run-commands',\n defaultConfiguration: 'dev',\n configurations: {\n dev: {\n commands: [\n {\n command: `shx mkdir -p ${pluginCacheDir}`,\n forwardAllArgs: false,\n },\n 'terraform init',\n ],\n },\n },\n options: {\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n parallel: false,\n env: { TF_PLUGIN_CACHE_DIR: pluginCacheDir },\n },\n },\n // `^production` mirrors `test`: checkov resolves the relative modules a\n // project consumes, so a change in one must invalidate the scan.\n checkov: {\n executor: 'nx:run-commands',\n cache: true,\n inputs: ['default', '^production'],\n outputs: ['{workspaceRoot}/dist/{projectRoot}/checkov'],\n options: {\n command: uvxCommand(\n 'checkov',\n `--config-file ../checkov.yml --directory . -o cli -o json --output-file-path console,${checkovReportJsonPath}`,\n ),\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n },\n },\n // Terraform's native test framework, which runs any `.tftest.hcl` files.\n // A project with none is a no-op success.\n //\n // `-backend=false` installs the modules and providers the tests need\n // without configuring the S3 backend, so this runs before `bootstrap` and\n // needs no credentials. `TF_DATA_DIR` keeps that `.terraform` out of `src`,\n // so it never races the backend-configured targets over the shared one.\n // `^production` is what invalidates the cache when a consumed module\n // changes; `{projectRoot}/**/*` alone would serve a stale pass.\n //\n // `TF_DATA_DIR` is terraform's working directory, not an artifact: its\n // provider entries are symlinks into the shared plugin cache, so restoring\n // it on another machine would yield dangling links while the commands that\n // repopulate them are skipped. Declaring no outputs keeps a cache hit to\n // what it actually asserts — that the tests passed for these inputs.\n test: {\n executor: 'nx:run-commands',\n cache: true,\n inputs: ['default', '^production'],\n outputs: [],\n options: {\n commands: [\n { command: `shx mkdir -p ${pluginCacheDir}`, forwardAllArgs: false },\n 'terraform init -backend=false',\n 'terraform test',\n ],\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n parallel: false,\n env: { TF_DATA_DIR: testDataDir, TF_PLUGIN_CACHE_DIR: pluginCacheDir },\n },\n },\n // Mirrors `test`: `-backend=false` installs the modules and providers\n // validation needs without configuring the S3 backend, so this runs on a\n // fresh workspace before `bootstrap` and needs no credentials. `TF_DATA_DIR`\n // keeps that `.terraform` out of `src`, so it never races the\n // backend-configured targets over the shared one, and declaring no outputs\n // keeps a cache hit to what it asserts (see `test` above).\n validate: {\n executor: 'nx:run-commands',\n cache: true,\n inputs: ['default', '^production'],\n outputs: [],\n options: {\n commands: [\n { command: `shx mkdir -p ${pluginCacheDir}`, forwardAllArgs: false },\n 'terraform init -backend=false',\n 'terraform validate',\n ],\n forwardAllArgs: true,\n cwd: '{projectRoot}/src',\n parallel: false,\n env: {\n TF_DATA_DIR: validateDataDir,\n TF_PLUGIN_CACHE_DIR: pluginCacheDir,\n },\n },\n },\n };\n\n const projectConfiguration = {\n root: lib.dir,\n projectType: schema.type,\n sourceRoot: joinPathFragments(lib.dir, 'src'),\n targets: sortObjectKeys({\n ...libTargets,\n ...(schema.type === 'application' ? applicationTargets : {}),\n }),\n };\n\n // Only create the project configuration on first run; skip it on re-run so\n // existing project.json customisations are preserved.\n if (!projectExists(tree, lib.fullyQualifiedName)) {\n addProjectConfiguration(tree, lib.fullyQualifiedName, projectConfiguration);\n }\n\n // The `lint` target checks licenses alongside formatting, as it does for\n // TypeScript and Python projects.\n addLicenseCheckToLintTarget(tree, lib.fullyQualifiedName);\n\n // This generator IS the Terraform project, so the provider is fixed.\n addGeneratorMetadata(\n tree,\n lib.fullyQualifiedName,\n TERRAFORM_PROJECT_GENERATOR_INFO,\n { iac: 'terraform' },\n );\n\n // The guides tell the reader to declare resources in `main.tf`, add variables\n // and outputs, and configure environments in `env/*.tfvars`, so everything\n // here is scaffolded once and then left alone. Provider version bumps reach\n // `providers.tf` through the vended version sync, which rewrites the pin in\n // place rather than the whole file.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, `./files/${schema.type}`),\n lib.dir,\n {\n metricsModulePath,\n stateKeyPrefix: kebabCase(lib.fullyQualifiedName),\n ...terraformProviderVersions(),\n },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // Checkov skips are the user's to curate, so preserve any they have added.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, './files/checkov'),\n lib.dir,\n {},\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n const nxJson = readNxJson(tree);\n\n if (\n !nxJson.plugins?.find((p) =>\n typeof p === 'string'\n ? p === NX_EXTEND_PLUGIN\n : p.plugin === NX_EXTEND_PLUGIN,\n )\n ) {\n nxJson.plugins = [...(nxJson.plugins ?? []), NX_EXTEND_PLUGIN];\n updateNxJson(tree, nxJson);\n }\n\n // Ensure shared constructs for Terraform are created\n await sharedConstructsGenerator(tree, { iac: 'terraform' }, DEPENDENCIES);\n\n // Add Terraform metrics\n await addGeneratorMetricsIfApplicable(tree, [\n TERRAFORM_PROJECT_GENERATOR_INFO,\n ]);\n\n addTsDependencies(tree, DEPENDENCIES);\n\n // @nx-extend/terraform has a peer dependency on @nx/devkit ^21.0.0 which causes\n // npm install to fail, so for NPM we add a resolution\n // Can remove when https://github.com/TriPSs/nx-extend/issues/407 is addressed\n if (detectPackageManager() === 'npm') {\n updateJson(tree, 'package.json', (packageJson) => {\n packageJson.overrides = {\n ...packageJson.overrides,\n ...withVersions(DEPENDENCIES, ['@nx/devkit']),\n };\n return packageJson;\n });\n }\n\n // `updateProjectConfiguration` re-serialises project.json with every inline\n // array expanded, which the vended `format` target rejects.\n await formatFilesInSubtree(tree);\n\n // `@nx-extend/terraform` is registered as an Nx plugin in nx.json, so Nx\n // loads it when computing the project graph — it must resolve even if the\n // caller would otherwise prefer to defer installing.\n return () =>\n installDependencies(tree, schema.preferInstallDependencies, {\n languages: ['typescript'],\n ensureResolvable: [NX_EXTEND_PLUGIN],\n });\n}\nexport default terraformProjectGenerator;\n"],"names":["addProjectConfiguration","detectPackageManager","generateFiles","joinPathFragments","OverwriteStrategy","readNxJson","updateJson","updateNxJson","join","relative","addLicenseCheckToLintTarget","getTsLibDetails","addTsDependencies","declareDependencies","ownedElsewhere","formatFilesInSubtree","updateGitIgnore","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","addGeneratorMetadata","getGeneratorInfo","projectExists","sortObjectKeys","uvxCommand","sharedConstructsGenerator","SHARED_CONSTRUCTS_DEPENDENCIES","SHARED_TERRAFORM_DIR","SHARED_TERRAFORM_NAME","terraformProviderVersions","withVersions","DEPENDENCIES","ts","name","dev","root","versionOnly","NX_EXTEND_PLUGIN","TERRAFORM_PROJECT_GENERATOR_INFO","filename","TERRAFORM_FORMAT_TARGET","executor","cache","inputs","options","command","forwardAllArgs","cwd","configurations","fix","terraformProjectGenerator","tree","schema","lib","fullyQualifiedName","sharedTfProjectName","outDirToRootRelativePath","dir","replace","distDir","tfDistDir","checkovReportJsonPath","testDataDir","validateDataDir","pluginCacheDir","metricsModulePath","patterns","applicationTargets","apply","defaultConfiguration","dependsOn","bootstrap","commands","build","deploy","assemble","destroy","init","env","TF_ENV","output","plan","parallel","libTargets","format","lint","TF_PLUGIN_CACHE_DIR","checkov","outputs","test","TF_DATA_DIR","validate","projectConfiguration","projectType","type","sourceRoot","targets","iac","dirname","stateKeyPrefix","overwriteStrategy","KeepExisting","nxJson","plugins","find","p","plugin","packageJson","overrides","preferInstallDependencies","languages","ensureResolvable"],"mappings":"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"}
@@ -129,6 +129,10 @@ export async function tsTrpcApiGenerator(tree, options) {
129
129
  }
130
130
  const projectConfig = readProjectConfigurationUnqualified(tree, backendProjectName);
131
131
  const backendRoot = projectConfig.root;
132
+ if (!projectExists) {
133
+ // Clear the placeholder barrel from ts#project so the API's own is written.
134
+ tree.delete(joinPathFragments(backendRoot, 'src', 'index.ts'));
135
+ }
132
136
  const port = assignPort(tree, projectConfig, 2022);
133
137
  const enhancedOptions = {
134
138
  backendProjectName,
@@ -154,6 +158,7 @@ export async function tsTrpcApiGenerator(tree, options) {
154
158
  backend: {
155
159
  type: 'trpc',
156
160
  projectAlias: enhancedOptions.backendProjectAlias,
161
+ projectRoot: backendRoot,
157
162
  bundleOutputDir: joinPathFragments('dist', backendRoot, 'bundle'),
158
163
  integrationPattern: getIntegrationPattern(options),
159
164
  ...options.auth === 'custom' && {
@@ -229,8 +234,9 @@ export async function tsTrpcApiGenerator(tree, options) {
229
234
  }
230
235
  projectConfig.targets = sortObjectKeys(projectConfig.targets);
231
236
  updateProjectConfiguration(tree, projectConfig.name, projectConfig);
237
+ // The API's source is user-owned, so a re-run leaves existing files alone.
232
238
  generateFiles(tree, joinPathFragments(import.meta.dirname, 'files'), backendRoot, enhancedOptions, {
233
- overwriteStrategy: OverwriteStrategy.Overwrite
239
+ overwriteStrategy: OverwriteStrategy.KeepExisting
234
240
  });
235
241
  tree.delete(joinPathFragments(backendRoot, 'src', 'lib'));
236
242
  if (options.infra !== 'none' && options.auth === 'custom') {