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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/LICENSE-THIRD-PARTY +3 -60
  2. package/generators.json +1 -1
  3. package/package.json +7 -3
  4. package/src/agentcore-gateway/generator.js +12 -2
  5. package/src/agentcore-gateway/generator.js.map +1 -1
  6. package/src/infra/app/__snapshots__/generator.spec.ts.snap +25 -31
  7. package/src/infra/app/generator.js +9 -6
  8. package/src/infra/app/generator.js.map +1 -1
  9. package/src/license/config.js +1 -1
  10. package/src/license/config.js.map +1 -1
  11. package/src/mcp-server/schema.d.ts +1 -1
  12. package/src/mcp-server/tools/general-guidance.js +5 -6
  13. package/src/mcp-server/tools/general-guidance.js.map +1 -1
  14. package/src/preset/__snapshots__/generator.spec.ts.snap +38 -7
  15. package/src/preset/generator.d.ts +1 -1
  16. package/src/preset/generator.js +4 -2
  17. package/src/preset/generator.js.map +1 -1
  18. package/src/preset/schema.d.js.map +1 -1
  19. package/src/preset/schema.d.ts +1 -0
  20. package/src/preset/schema.json +5 -0
  21. package/src/py/agent/generator.js +2 -1
  22. package/src/py/agent/generator.js.map +1 -1
  23. package/src/py/mcp-server/generator.js +2 -1
  24. package/src/py/mcp-server/generator.js.map +1 -1
  25. package/src/py/project/generator.js +2 -1
  26. package/src/py/project/generator.js.map +1 -1
  27. package/src/py/rdb/generator.js +2 -1
  28. package/src/py/rdb/generator.js.map +1 -1
  29. package/src/smithy/ts/api/generator.js +5 -2
  30. package/src/smithy/ts/api/generator.js.map +1 -1
  31. package/src/terraform/project/generator.js +4 -1
  32. package/src/terraform/project/generator.js.map +1 -1
  33. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +6 -6
  34. package/src/trpc/backend/generator.js +7 -5
  35. package/src/trpc/backend/generator.js.map +1 -1
  36. package/src/trpc/react/generator.js +4 -4
  37. package/src/trpc/react/generator.js.map +1 -1
  38. package/src/ts/agent/__snapshots__/generator.spec.ts.snap +2 -2
  39. package/src/ts/agent/a2a-connection/generator.js +3 -2
  40. package/src/ts/agent/a2a-connection/generator.js.map +1 -1
  41. package/src/ts/agent/gateway-connection/generator.js +4 -3
  42. package/src/ts/agent/gateway-connection/generator.js.map +1 -1
  43. package/src/ts/agent/generator.js +8 -5
  44. package/src/ts/agent/generator.js.map +1 -1
  45. package/src/ts/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +1 -1
  46. package/src/ts/agent/mcp-connection/generator.js +4 -3
  47. package/src/ts/agent/mcp-connection/generator.js.map +1 -1
  48. package/src/ts/agent/react-connection/generator.js +10 -19
  49. package/src/ts/agent/react-connection/generator.js.map +1 -1
  50. package/src/ts/astro-docs/generator.js +12 -3
  51. package/src/ts/astro-docs/generator.js.map +1 -1
  52. package/src/ts/dcr-proxy/generator.js +5 -5
  53. package/src/ts/dcr-proxy/generator.js.map +1 -1
  54. package/src/ts/dynamodb/generator.js +5 -2
  55. package/src/ts/dynamodb/generator.js.map +1 -1
  56. package/src/ts/lambda-function/__snapshots__/generator.spec.ts.snap +4 -2
  57. package/src/ts/lambda-function/files/handler/__lambdaFunctionKebabCase__.ts.template +2 -1
  58. package/src/ts/lambda-function/generator.js +3 -2
  59. package/src/ts/lambda-function/generator.js.map +1 -1
  60. package/src/ts/lib/ts-project-utils.js +17 -10
  61. package/src/ts/lib/ts-project-utils.js.map +1 -1
  62. package/src/ts/lib/vitest.js +2 -1
  63. package/src/ts/lib/vitest.js.map +1 -1
  64. package/src/ts/mcp-server/generator.js +11 -11
  65. package/src/ts/mcp-server/generator.js.map +1 -1
  66. package/src/ts/nx-generator/generator.js +5 -0
  67. package/src/ts/nx-generator/generator.js.map +1 -1
  68. package/src/ts/nx-plugin/__snapshots__/generator.spec.ts.snap +5 -6
  69. package/src/ts/nx-plugin/files/mcp-server/resources/GENERAL_GUIDANCE.md.template +5 -6
  70. package/src/ts/nx-plugin/utils.js +2 -1
  71. package/src/ts/nx-plugin/utils.js.map +1 -1
  72. package/src/ts/rdb/agent-connection/generator.js +1 -2
  73. package/src/ts/rdb/agent-connection/generator.js.map +1 -1
  74. package/src/ts/rdb/generator.js +10 -6
  75. package/src/ts/rdb/generator.js.map +1 -1
  76. package/src/ts/rdb/mcp-server-connection/generator.js +1 -2
  77. package/src/ts/rdb/mcp-server-connection/generator.js.map +1 -1
  78. package/src/ts/rdb/smithy-connection/generator.js +1 -2
  79. package/src/ts/rdb/smithy-connection/generator.js.map +1 -1
  80. package/src/ts/rdb/trpc-connection/generator.js +1 -2
  81. package/src/ts/rdb/trpc-connection/generator.js.map +1 -1
  82. package/src/ts/react-website/agui/generator.js +5 -4
  83. package/src/ts/react-website/agui/generator.js.map +1 -1
  84. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +210 -79
  85. package/src/ts/react-website/app/generator.js +34 -14
  86. package/src/ts/react-website/app/generator.js.map +1 -1
  87. package/src/ts/react-website/cognito-auth/generator.js +3 -2
  88. package/src/ts/react-website/cognito-auth/generator.js.map +1 -1
  89. package/src/ts/react-website/runtime-config/generator.js +2 -2
  90. package/src/ts/react-website/runtime-config/generator.js.map +1 -1
  91. package/src/ts/sync/generator.js +81 -3
  92. package/src/ts/sync/generator.js.map +1 -1
  93. package/src/utils/agent-connection/agent-connection.d.ts +1 -1
  94. package/src/utils/agent-connection/agent-connection.js +50 -1
  95. package/src/utils/agent-connection/agent-connection.js.map +1 -1
  96. package/src/utils/agent-core-constructs/agent-core-constructs.js +10 -1
  97. package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
  98. package/src/utils/api-constructs/api-constructs.js +15 -1
  99. package/src/utils/api-constructs/api-constructs.js.map +1 -1
  100. package/src/utils/bundle/bundle.js +2 -1
  101. package/src/utils/bundle/bundle.js.map +1 -1
  102. package/src/utils/commands.d.ts +5 -3
  103. package/src/utils/commands.js +24 -3
  104. package/src/utils/commands.js.map +1 -1
  105. package/src/utils/config/index.d.ts +16 -0
  106. package/src/utils/config/index.js.map +1 -1
  107. package/src/utils/config/utils.d.ts +3 -2
  108. package/src/utils/config/utils.js +4 -3
  109. package/src/utils/config/utils.js.map +1 -1
  110. package/src/utils/connection/open-api/react.js +3 -2
  111. package/src/utils/connection/open-api/react.js.map +1 -1
  112. package/src/utils/containers.js +1 -1
  113. package/src/utils/containers.js.map +1 -1
  114. package/src/utils/dependencies.d.ts +18 -0
  115. package/src/utils/dependencies.js +206 -0
  116. package/src/utils/dependencies.js.map +1 -0
  117. package/src/utils/files/common/shadcn/readme/README.md.template +3 -3
  118. package/src/utils/files/shadcn/components.json.template +1 -1
  119. package/src/utils/format.d.ts +20 -1
  120. package/src/utils/format.js +83 -49
  121. package/src/utils/format.js.map +1 -1
  122. package/src/utils/fs.d.ts +1 -1
  123. package/src/utils/fs.js +1 -1
  124. package/src/utils/fs.js.map +1 -1
  125. package/src/utils/iac.js +1 -1
  126. package/src/utils/iac.js.map +1 -1
  127. package/src/utils/init.d.ts +7 -1
  128. package/src/utils/init.js +38 -17
  129. package/src/utils/init.js.map +1 -1
  130. package/src/utils/install.js +3 -1
  131. package/src/utils/install.js.map +1 -1
  132. package/src/utils/module-format.d.ts +5 -8
  133. package/src/utils/module-format.js +29 -12
  134. package/src/utils/module-format.js.map +1 -1
  135. package/src/utils/npm-scope.d.ts +0 -4
  136. package/src/utils/npm-scope.js +0 -5
  137. package/src/utils/npm-scope.js.map +1 -1
  138. package/src/utils/pnpm-workspace.d.ts +1 -12
  139. package/src/utils/pnpm-workspace.js +3 -30
  140. package/src/utils/pnpm-workspace.js.map +1 -1
  141. package/src/utils/project-package-json.d.ts +39 -0
  142. package/src/utils/project-package-json.js +119 -0
  143. package/src/utils/project-package-json.js.map +1 -0
  144. package/src/utils/shared-constructs.js +6 -5
  145. package/src/utils/shared-constructs.js.map +1 -1
  146. package/src/utils/shared-dynamodb-scripts.js +4 -2
  147. package/src/utils/shared-dynamodb-scripts.js.map +1 -1
  148. package/src/utils/shared-infra-scripts.js +5 -4
  149. package/src/utils/shared-infra-scripts.js.map +1 -1
  150. package/src/utils/shared-rdb-scripts.js +14 -1
  151. package/src/utils/shared-rdb-scripts.js.map +1 -1
  152. package/src/utils/shared-shadcn.js +11 -8
  153. package/src/utils/shared-shadcn.js.map +1 -1
  154. package/src/utils/test.js +8 -3
  155. package/src/utils/test.js.map +1 -1
  156. package/src/utils/versions.d.ts +3 -0
  157. package/src/utils/versions.js +3 -0
  158. package/src/utils/versions.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/license/config.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n getProjects,\n type ProjectConfiguration,\n readProjectConfiguration,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport {\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n readAwsNxPluginConfig,\n updateAwsNxPluginConfig,\n} from '../utils/config/utils';\nimport { formatFilesInSubtree } from '../utils/format';\nimport { addDependencyToTargetIfNotPresent } from '../utils/nx';\nimport type {\n CommentSyntax,\n LicenseConfig,\n LicenseSourceConfig,\n} from './config-types';\nimport type { DependencyCheckException } from './dependency-check/types';\nimport type { SPDXLicenseIdentifier } from './schema';\n\n/**\n * Licenses containing a placeholder for the copyright year.\n */\nconst LICENSES_WITH_YEAR: Set<SPDXLicenseIdentifier> = new Set(['MIT']);\n\n/**\n * Defines the comment syntax for popular programming languages\n */\nexport const LANGUAGE_COMMENT_SYNTAX: { [ext: string]: CommentSyntax } = {\n // C++ style comments\n ...Object.fromEntries(\n [\n // Node\n 'js',\n 'ts',\n 'cjs',\n 'mjs',\n 'cts',\n 'mts',\n // React\n 'jsx',\n 'tsx',\n // Web\n 'sass',\n 'scss',\n 'php',\n // Java\n 'java',\n // TypeSpec\n 'tsp',\n // Golang\n 'go',\n // Rust\n 'rs',\n // C and C++\n 'c',\n 'cpp',\n 'cxx',\n 'cc',\n 'h',\n 'hpp',\n // C#\n 'cs',\n // Scala\n 'scala',\n 'sc',\n 'sbt',\n // Kotlin\n 'kt',\n // Swift\n 'swift',\n ].map((ext) => [ext, { line: '//', block: { start: '/*', end: '*/' } }]),\n ),\n // Bash style comments\n ...Object.fromEntries(\n [\n // Bash\n 'sh',\n // Perl\n 'pl',\n // YAML\n 'yaml',\n 'yml',\n // R\n 'r',\n ].map((ext) => [ext, { line: '#' }]),\n ),\n // Docker\n Dockerfile: { line: '#' },\n // Python\n py: { line: '#', block: { start: '\"\"\"', end: '\"\"\"' } },\n // Web\n html: { block: { start: '<!--', end: '-->' } },\n css: { block: { start: '/*', end: '*/' } },\n // Ruby\n rb: { line: '#', block: { start: '=begin', end: '=end' } },\n // F#\n ...Object.fromEntries(\n ['fs', 'fsx'].map((ext) => [\n ext,\n { line: '//', block: { start: '(*', end: '*)' } },\n ]),\n ),\n // Visual Basic\n vb: { line: \"' \" },\n // Lua\n lua: { line: '--', block: { start: '--[[', end: ']]' } },\n // PowerShell\n ps1: { line: '#', block: { start: '<#', end: '#>' } },\n psm1: { line: '#', block: { start: '<#', end: '#>' } },\n // Markdown\n md: { block: { start: '<!--', end: '-->' } },\n // Terraform\n tf: { line: '#', block: { start: '/*', end: '*/' } },\n // Smithy\n smithy: { line: '//' },\n};\n\n/**\n * Module specifier for the license helpers exported by this package, used by\n * imports written into the user's config file.\n */\nconst LICENSE_SDK_MODULE = '@aws/nx-plugin/sdk/license';\n\n/**\n * Build the object literal source for a dependency check exception.\n * `JSON.stringify` produces valid string literals for arbitrary text (quotes,\n * backslashes, newlines all escaped); prettier later normalises quote style.\n */\nconst exceptionLiteral = (exception: DependencyCheckException): string => {\n const parts = [`package: ${JSON.stringify(exception.package)}`];\n if (exception.version !== undefined) {\n parts.push(`version: ${JSON.stringify(exception.version)}`);\n }\n parts.push(`reason: ${JSON.stringify(exception.reason)}`);\n if (exception.spdx !== undefined) {\n parts.push(`spdx: ${JSON.stringify(exception.spdx)}`);\n }\n return `{ ${parts.join(', ')} }`;\n};\n\n/**\n * GritQL `or` block that appends `$ins` (the insert placeholder) to the named\n * array inside the matched `$scope`, without ever producing an array hole:\n * - empty `key: []` → `key: [$ins]` (a list-append `+=` does not match an\n * empty array, so the empty case is rewritten directly)\n * - otherwise → list-append `+=` of `, $ins`; the leading comma is the\n * element separator and `+=` places it correctly for single inline,\n * single-with-trailing-comma and multi-element arrays alike\n */\nconst appendToArray = (key: string, ins: string) =>\n `or {\n $scope <: contains \\`${key}: []\\` => \\`${key}: [${ins}]\\`,\n $scope <: contains \\`${key}: [$items]\\` where { $items += \\`, ${ins}\\` }\n }`;\n\n/**\n * Insert `property` (TypeScript source like `dependencies: { ... }`) as the\n * first property of the `license` object literal.\n *\n * Prepending is comma-safe for every shape — empty `{}`, single- or multi-line.\n * `+=` appending is not: it omits the separator when the last property's value\n * is an object/array literal (e.g. `source: { ... }`), corrupting the file. The\n * property text is routed through a placeholder so its content never enters the\n * GritQL pattern. Returns true if the file changed (a `license` object existed).\n */\nconst prependLicenseProperty = async (\n tree: Tree,\n property: string,\n): Promise<boolean> => {\n const { insertViaGritQL, GRIT_INSERT_PLACEHOLDER } = await import(\n '../utils/ast'\n );\n\n // Non-empty license object: insert before the first existing property.\n const intoNonEmpty = await insertViaGritQL(\n tree,\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n `\\`license: { $props }\\` where { $props => \\`${GRIT_INSERT_PLACEHOLDER}, $props\\` }`,\n property,\n );\n if (intoNonEmpty) return true;\n\n // Empty license object: `{ $props }` doesn't match `{}`, so fill it directly.\n return insertViaGritQL(\n tree,\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n `\\`license: {}\\` => \\`license: { ${GRIT_INSERT_PLACEHOLDER} }\\``,\n property,\n );\n};\n\n/**\n * Whether `license.dependencies` (the dependency-check block) is configured.\n * Scoped within `license` so a `dependencies`-shaped object elsewhere in the\n * file isn't mistaken for it.\n */\nconst hasDependenciesBlock = async (tree: Tree): Promise<boolean> => {\n if (!tree.exists(AWS_NX_PLUGIN_CONFIG_FILE_NAME)) return false;\n const { matchGritQL } = await import('../utils/ast');\n return matchGritQL(\n tree,\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n '`license: { $l }` where { $l <: contains `dependencies: $_` }',\n );\n};\n\n/**\n * Workspace-root npm-ecosystem lockfiles. Each is added to the license-check\n * cache inputs only when present, so the cache invalidates on dependency\n * changes without listing lockfiles for package managers the workspace doesn't\n * use.\n */\nconst NPM_LOCKFILES = [\n 'pnpm-lock.yaml',\n 'yarn.lock',\n 'package-lock.json',\n 'bun.lockb',\n];\n\n/**\n * Recompute the `inputs` of the root `license-check` target from what's\n * currently in the workspace: the present npm lockfiles, the config file, and\n * a recursive uv.lock glob when the dependency check uses a Python collector.\n *\n * The uv lockfile is keyed off the collector (not file presence) because it is\n * created by `uv` *after* the generator runs, and may live in a subdirectory of\n * a uv workspace. Callers run this whenever they change the relevant state, so\n * the inputs stay correct regardless of generator order. No-op if the\n * license-check target doesn't exist yet.\n */\nexport const updateLicenseCheckTargetInputs = async (\n tree: Tree,\n): Promise<void> => {\n const rootProjectJsonPath = 'project.json';\n if (!tree.exists(rootProjectJsonPath)) return;\n\n const rootProject = JSON.parse(tree.read(rootProjectJsonPath, 'utf-8')!);\n const target = rootProject.targets?.['license-check'];\n if (!target) return;\n\n const inputs = NPM_LOCKFILES.filter((f) => tree.exists(f)).map(\n (f) => `{workspaceRoot}/${f}`,\n );\n\n if (await hasPythonCollector(tree)) {\n inputs.push('{workspaceRoot}/**/uv.lock');\n }\n\n inputs.push('{workspaceRoot}/aws-nx-plugin.config.mts');\n\n target.inputs = inputs;\n tree.write(rootProjectJsonPath, JSON.stringify(rootProject, null, 2));\n};\n\n/**\n * Whether the dependency check config has a `pythonCollector` configured.\n */\nconst hasPythonCollector = async (tree: Tree): Promise<boolean> => {\n if (!tree.exists(AWS_NX_PLUGIN_CONFIG_FILE_NAME)) return false;\n const { matchGritQL } = await import('../utils/ast');\n return matchGritQL(tree, AWS_NX_PLUGIN_CONFIG_FILE_NAME, '`pythonCollector`');\n};\n\n/**\n * The name of the project that owns the root `license-check` target, or\n * undefined if no project defines it.\n */\nconst findLicenseCheckProjectName = (tree: Tree): string | undefined => {\n for (const [name, config] of getProjects(tree)) {\n if (config.targets?.['license-check']) return name;\n }\n return undefined;\n};\n\n/**\n * Make a project's `lint` target depend on the root `license-check` target, so\n * license checking runs as part of lint/build. No-op when the project has no\n * `lint` target or there's no license-check target to depend on. Idempotent.\n *\n * Callers format afterwards (generators call `formatFilesInSubtree` at the end),\n * so the rewritten project.json matches prettier.\n */\nexport const addLicenseCheckToLintTarget = (\n tree: Tree,\n projectName: string,\n): void => {\n const licenseCheckProject = findLicenseCheckProjectName(tree);\n if (!licenseCheckProject) return;\n\n let project: ProjectConfiguration;\n try {\n project = readProjectConfiguration(tree, projectName);\n } catch {\n return;\n }\n\n // Only wire projects that actually lint, and never the license-check project\n // itself (a target can't depend on its own project's target).\n if (!project.targets?.lint || projectName === licenseCheckProject) return;\n\n addDependencyToTargetIfNotPresent(project, 'lint', {\n projects: [licenseCheckProject],\n target: 'license-check',\n });\n updateProjectConfiguration(tree, projectName, project);\n};\n\n/**\n * Wire every project's `lint` target to the root `license-check` target.\n * Called by the license generator so existing projects pick up the dependency\n * regardless of the order generators ran in.\n */\nexport const addLicenseCheckToAllLintTargets = (tree: Tree): void => {\n for (const [name] of getProjects(tree)) {\n addLicenseCheckToLintTarget(tree, name);\n }\n};\n\nexport interface EnsureDependencyCheckBlockOptions {\n includeCollectors?: 'npm' | 'npm+python';\n}\n\n/**\n * Ensure the `dependencies` block (dependency license checking) exists within\n * the `license` config. If one already exists it is left untouched, so user\n * customizations survive.\n */\nexport const ensureDependencyCheckBlock = async (\n tree: Tree,\n options?: EnsureDependencyCheckBlockOptions,\n): Promise<void> => {\n if (!tree.exists(AWS_NX_PLUGIN_CONFIG_FILE_NAME)) return;\n\n const { addDestructuredImport } = await import('../utils/ast');\n\n if (await hasDependenciesBlock(tree)) {\n return;\n }\n\n const withPython = options?.includeCollectors === 'npm+python';\n const collectors = withPython\n ? 'collectors: [npmCollector(), pythonCollector()]'\n : 'collectors: [npmCollector()]';\n\n const block = `dependencies: { allow: DEFAULT_LICENSE_ALLOWLIST, ${collectors}, exceptions: [] }`;\n\n // Prepend the block as the first property of the license object. Prepending\n // (rather than `+=` appending) is comma-safe for every shape: GritQL's `+=`\n // omits the separator when the last existing property's value is an object\n // literal (e.g. `source: { ... }`), which would corrupt the file.\n const added = await prependLicenseProperty(tree, block);\n\n // Only add the imports if the block was actually written (i.e. a license\n // object literal existed to attach it to).\n if (added) {\n await addDestructuredImport(\n tree,\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n withPython\n ? ['DEFAULT_LICENSE_ALLOWLIST', 'npmCollector', 'pythonCollector']\n : ['DEFAULT_LICENSE_ALLOWLIST', 'npmCollector'],\n LICENSE_SDK_MODULE,\n );\n await formatFilesInSubtree(tree, AWS_NX_PLUGIN_CONFIG_FILE_NAME);\n }\n};\n\n/**\n * Ensure license exceptions are present in `license.dependencies.exceptions`.\n * An exception whose package is already listed is skipped (so existing reasons\n * are never overwritten). Other exceptions, collectors and the allowlist are\n * left untouched.\n *\n * The `dependencies: { $scope }` scope keeps edits within the dependency-check\n * block, so an `exceptions` array elsewhere in the file isn't matched.\n */\nexport const ensureLicenseExceptions = async (\n tree: Tree,\n exceptions: DependencyCheckException[],\n): Promise<void> => {\n if (!tree.exists(AWS_NX_PLUGIN_CONFIG_FILE_NAME)) return;\n\n const { insertViaGritQL, GRIT_INSERT_PLACEHOLDER } = await import(\n '../utils/ast'\n );\n\n if (!(await hasDependenciesBlock(tree))) {\n return;\n }\n\n let modified = false;\n for (const exception of exceptions) {\n const pkg = JSON.stringify(exception.package);\n const inserted = await insertViaGritQL(\n tree,\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n `\\`dependencies: { $scope }\\` where {\n $scope <: not contains \\`package: ${pkg}\\`,\n ${appendToArray('exceptions', GRIT_INSERT_PLACEHOLDER)}\n }`,\n exceptionLiteral(exception),\n );\n modified ||= inserted;\n }\n\n if (modified) {\n await formatFilesInSubtree(tree, AWS_NX_PLUGIN_CONFIG_FILE_NAME);\n }\n};\n\n/**\n * Add `pythonCollector()` to `license.dependencies.collectors`, unless one is\n * already configured.\n */\nexport const ensurePythonLicenseCollector = async (\n tree: Tree,\n): Promise<void> => {\n if (!tree.exists(AWS_NX_PLUGIN_CONFIG_FILE_NAME)) return;\n\n const { addDestructuredImport, insertViaGritQL, GRIT_INSERT_PLACEHOLDER } =\n await import('../utils/ast');\n\n if (!(await hasDependenciesBlock(tree))) {\n return;\n }\n\n const added = await insertViaGritQL(\n tree,\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n `\\`dependencies: { $scope }\\` where {\n $scope <: not contains \\`pythonCollector\\`,\n ${appendToArray('collectors', GRIT_INSERT_PLACEHOLDER)}\n }`,\n 'pythonCollector()',\n );\n\n if (added) {\n await addDestructuredImport(\n tree,\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n ['pythonCollector'],\n LICENSE_SDK_MODULE,\n );\n await formatFilesInSubtree(tree, AWS_NX_PLUGIN_CONFIG_FILE_NAME);\n // Now that a Python collector is configured, ensure uv.lock is a cache\n // input. Runs here (not only in the license generator) so it's added\n // whenever the collector is — e.g. when py#project runs after license.\n await updateLicenseCheckTargetInputs(tree);\n }\n};\n\n/**\n * Build the default `license.source` config for a given license\n */\nexport const defaultLicenseConfig = (\n spdx: SPDXLicenseIdentifier,\n copyrightHolder: string,\n): LicenseSourceConfig => {\n switch (spdx) {\n case 'ASL': {\n // For ASL, we use a \"box\" style license header\n const rawContent = [\n `Copyright ${copyrightHolder}. All Rights Reserved.`,\n '',\n 'Licensed under the Amazon Software License (the \"License\"). You may not use this file except in compliance',\n 'with the License. A copy of the License is located at',\n '',\n ' https://aws.amazon.com/asl/',\n '',\n 'or in the \"license\" file accompanying this file. This file is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES',\n 'OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions',\n 'and limitations under the License.',\n ];\n const maxLen = Math.max(...rawContent.map((line) => line.length));\n const lines = rawContent.map(\n (line) => `${line}${' '.repeat(maxLen - line.length)}`,\n );\n return {\n spdx,\n copyrightHolder,\n header: {\n content: { lines },\n format: {\n '**/*.{js,ts,jsx,tsx,mjs,mts}': {\n blockStart: `/***${'*'.repeat(maxLen)}**`,\n lineStart: ' * ',\n lineEnd: ' *',\n blockEnd: ` ***${'*'.repeat(maxLen)}**/`,\n },\n '**/*.{py,sh,tf}': {\n blockStart: `###${'#'.repeat(maxLen)}##`,\n lineStart: '# ',\n lineEnd: ' #',\n blockEnd: `###${'#'.repeat(maxLen)}##`,\n },\n },\n exclude: ['**/*.gen.*'],\n },\n };\n }\n default: {\n return {\n spdx,\n copyrightHolder,\n ...(LICENSES_WITH_YEAR.has(spdx)\n ? {\n copyrightYear: new Date().getFullYear(),\n }\n : {}),\n header: {\n content: {\n lines: [\n `Copyright ${copyrightHolder}. All Rights Reserved.`,\n `SPDX-License-Identifier: ${spdx}`,\n ],\n },\n format: {\n '**/*.{js,ts,jsx,tsx,mjs,mts}': {\n blockStart: '/**',\n lineStart: ' * ',\n blockEnd: ' */',\n },\n '**/*.{py,sh,tf}': {\n blockStart: '#',\n lineStart: '# ',\n blockEnd: '#',\n },\n },\n exclude: ['**/*.gen.*'],\n },\n };\n }\n }\n};\n\n/**\n * Write the `license.source` config (headers + LICENSE files) to the aws nx\n * plugin config.\n *\n * The `source` block is (re)written, but any existing `license.dependencies`\n * block — a user-customized allowlist, collectors and exceptions — is\n * preserved, so re-running the license generator (e.g. to change the copyright\n * holder) never clobbers dependency-check customizations.\n */\nexport const writeLicenseConfig = async (\n tree: Tree,\n source: LicenseSourceConfig,\n) => {\n const { captureGritQL } = await import('../utils/ast');\n\n // Capture the existing `dependencies: { ... }` block before overwriting the\n // license value, so we can re-attach it afterwards. It's managed by the\n // ensure* helpers, never written from here.\n const preserved = tree.exists(AWS_NX_PLUGIN_CONFIG_FILE_NAME)\n ? await captureGritQL(\n tree,\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n '`dependencies: $_`',\n )\n : undefined;\n\n await updateAwsNxPluginConfig(tree, { license: { source } });\n\n // Re-attach the preserved block. The captured text may contain backticks,\n // `${...}` or quotes — prependLicenseProperty routes it through a placeholder\n // so it never enters the GritQL pattern.\n if (preserved) {\n await prependLicenseProperty(tree, preserved);\n await formatFilesInSubtree(tree, AWS_NX_PLUGIN_CONFIG_FILE_NAME);\n }\n};\n\n/**\n * Read license configuration\n */\nexport const readLicenseConfig = async (\n tree: Tree,\n): Promise<LicenseConfig | undefined> => {\n return (await readAwsNxPluginConfig(tree))?.license;\n};\n"],"names":["getProjects","readProjectConfiguration","updateProjectConfiguration","AWS_NX_PLUGIN_CONFIG_FILE_NAME","readAwsNxPluginConfig","updateAwsNxPluginConfig","formatFilesInSubtree","addDependencyToTargetIfNotPresent","LICENSES_WITH_YEAR","Set","LANGUAGE_COMMENT_SYNTAX","Object","fromEntries","map","ext","line","block","start","end","Dockerfile","py","html","css","rb","vb","lua","ps1","psm1","md","tf","smithy","LICENSE_SDK_MODULE","exceptionLiteral","exception","parts","JSON","stringify","package","version","undefined","push","reason","spdx","join","appendToArray","key","ins","prependLicenseProperty","tree","property","insertViaGritQL","GRIT_INSERT_PLACEHOLDER","intoNonEmpty","hasDependenciesBlock","exists","matchGritQL","NPM_LOCKFILES","updateLicenseCheckTargetInputs","rootProjectJsonPath","rootProject","parse","read","target","targets","inputs","filter","f","hasPythonCollector","write","findLicenseCheckProjectName","name","config","addLicenseCheckToLintTarget","projectName","licenseCheckProject","project","lint","projects","addLicenseCheckToAllLintTargets","ensureDependencyCheckBlock","options","addDestructuredImport","withPython","includeCollectors","collectors","added","ensureLicenseExceptions","exceptions","modified","pkg","inserted","ensurePythonLicenseCollector","defaultLicenseConfig","copyrightHolder","rawContent","maxLen","Math","max","length","lines","repeat","header","content","format","blockStart","lineStart","lineEnd","blockEnd","exclude","has","copyrightYear","Date","getFullYear","writeLicenseConfig","source","captureGritQL","preserved","license","readLicenseConfig"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/license/config.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n getProjects,\n type ProjectConfiguration,\n readProjectConfiguration,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport {\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n readAwsNxPluginConfig,\n updateAwsNxPluginConfig,\n} from '../utils/config/utils';\nimport { formatFilesInSubtree } from '../utils/format';\nimport { addDependencyToTargetIfNotPresent } from '../utils/nx';\nimport type {\n CommentSyntax,\n LicenseConfig,\n LicenseSourceConfig,\n} from './config-types';\nimport type { DependencyCheckException } from './dependency-check/types';\nimport type { SPDXLicenseIdentifier } from './schema';\n\n/**\n * Licenses containing a placeholder for the copyright year.\n */\nconst LICENSES_WITH_YEAR: Set<SPDXLicenseIdentifier> = new Set(['MIT']);\n\n/**\n * Defines the comment syntax for popular programming languages\n */\nexport const LANGUAGE_COMMENT_SYNTAX: { [ext: string]: CommentSyntax } = {\n // C++ style comments\n ...Object.fromEntries(\n [\n // Node\n 'js',\n 'ts',\n 'cjs',\n 'mjs',\n 'cts',\n 'mts',\n // React\n 'jsx',\n 'tsx',\n // Web\n 'sass',\n 'scss',\n 'php',\n // Java\n 'java',\n // TypeSpec\n 'tsp',\n // Golang\n 'go',\n // Rust\n 'rs',\n // C and C++\n 'c',\n 'cpp',\n 'cxx',\n 'cc',\n 'h',\n 'hpp',\n // C#\n 'cs',\n // Scala\n 'scala',\n 'sc',\n 'sbt',\n // Kotlin\n 'kt',\n // Swift\n 'swift',\n ].map((ext) => [ext, { line: '//', block: { start: '/*', end: '*/' } }]),\n ),\n // Bash style comments\n ...Object.fromEntries(\n [\n // Bash\n 'sh',\n // Perl\n 'pl',\n // YAML\n 'yaml',\n 'yml',\n // R\n 'r',\n ].map((ext) => [ext, { line: '#' }]),\n ),\n // Docker\n Dockerfile: { line: '#' },\n // Python\n py: { line: '#', block: { start: '\"\"\"', end: '\"\"\"' } },\n // Web\n html: { block: { start: '<!--', end: '-->' } },\n css: { block: { start: '/*', end: '*/' } },\n // Ruby\n rb: { line: '#', block: { start: '=begin', end: '=end' } },\n // F#\n ...Object.fromEntries(\n ['fs', 'fsx'].map((ext) => [\n ext,\n { line: '//', block: { start: '(*', end: '*)' } },\n ]),\n ),\n // Visual Basic\n vb: { line: \"' \" },\n // Lua\n lua: { line: '--', block: { start: '--[[', end: ']]' } },\n // PowerShell\n ps1: { line: '#', block: { start: '<#', end: '#>' } },\n psm1: { line: '#', block: { start: '<#', end: '#>' } },\n // Markdown\n md: { block: { start: '<!--', end: '-->' } },\n // Terraform\n tf: { line: '#', block: { start: '/*', end: '*/' } },\n // Smithy\n smithy: { line: '//' },\n};\n\n/**\n * Module specifier for the license helpers exported by this package, used by\n * imports written into the user's config file.\n */\nconst LICENSE_SDK_MODULE = '@aws/nx-plugin/sdk/license';\n\n/**\n * Build the object literal source for a dependency check exception.\n * `JSON.stringify` produces valid string literals for arbitrary text (quotes,\n * backslashes, newlines all escaped); prettier later normalises quote style.\n */\nconst exceptionLiteral = (exception: DependencyCheckException): string => {\n const parts = [`package: ${JSON.stringify(exception.package)}`];\n if (exception.version !== undefined) {\n parts.push(`version: ${JSON.stringify(exception.version)}`);\n }\n parts.push(`reason: ${JSON.stringify(exception.reason)}`);\n if (exception.spdx !== undefined) {\n parts.push(`spdx: ${JSON.stringify(exception.spdx)}`);\n }\n return `{ ${parts.join(', ')} }`;\n};\n\n/**\n * GritQL `or` block that appends `$ins` (the insert placeholder) to the named\n * array inside the matched `$scope`, without ever producing an array hole:\n * - empty `key: []` → `key: [$ins]` (a list-append `+=` does not match an\n * empty array, so the empty case is rewritten directly)\n * - otherwise → list-append `+=` of `, $ins`; the leading comma is the\n * element separator and `+=` places it correctly for single inline,\n * single-with-trailing-comma and multi-element arrays alike\n */\nconst appendToArray = (key: string, ins: string) =>\n `or {\n $scope <: contains \\`${key}: []\\` => \\`${key}: [${ins}]\\`,\n $scope <: contains \\`${key}: [$items]\\` where { $items += \\`, ${ins}\\` }\n }`;\n\n/**\n * Insert `property` (TypeScript source like `dependencies: { ... }`) as the\n * first property of the `license` object literal.\n *\n * Prepending is comma-safe for every shape — empty `{}`, single- or multi-line.\n * `+=` appending is not: it omits the separator when the last property's value\n * is an object/array literal (e.g. `source: { ... }`), corrupting the file. The\n * property text is routed through a placeholder so its content never enters the\n * GritQL pattern. Returns true if the file changed (a `license` object existed).\n */\nconst prependLicenseProperty = async (\n tree: Tree,\n property: string,\n): Promise<boolean> => {\n const { insertViaGritQL, GRIT_INSERT_PLACEHOLDER } = await import(\n '../utils/ast'\n );\n\n // Non-empty license object: insert before the first existing property.\n const intoNonEmpty = await insertViaGritQL(\n tree,\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n `\\`license: { $props }\\` where { $props => \\`${GRIT_INSERT_PLACEHOLDER}, $props\\` }`,\n property,\n );\n if (intoNonEmpty) return true;\n\n // Empty license object: `{ $props }` doesn't match `{}`, so fill it directly.\n return insertViaGritQL(\n tree,\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n `\\`license: {}\\` => \\`license: { ${GRIT_INSERT_PLACEHOLDER} }\\``,\n property,\n );\n};\n\n/**\n * Whether `license.dependencies` (the dependency-check block) is configured.\n * Scoped within `license` so a `dependencies`-shaped object elsewhere in the\n * file isn't mistaken for it.\n */\nconst hasDependenciesBlock = async (tree: Tree): Promise<boolean> => {\n if (!tree.exists(AWS_NX_PLUGIN_CONFIG_FILE_NAME)) return false;\n const { matchGritQL } = await import('../utils/ast');\n return matchGritQL(\n tree,\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n '`license: { $l }` where { $l <: contains `dependencies: $_` }',\n );\n};\n\n/**\n * Workspace-root npm-ecosystem lockfiles. Each is added to the license-check\n * cache inputs only when present, so the cache invalidates on dependency\n * changes without listing lockfiles for package managers the workspace doesn't\n * use.\n */\nconst NPM_LOCKFILES = [\n 'pnpm-lock.yaml',\n 'yarn.lock',\n 'package-lock.json',\n 'bun.lockb',\n];\n\n/**\n * Recompute the `inputs` of the root `license-check` target from what's\n * currently in the workspace: the present npm lockfiles, the config file, and\n * a recursive uv.lock glob when the dependency check uses a Python collector.\n *\n * The uv lockfile is keyed off the collector (not file presence) because it is\n * created by `uv` *after* the generator runs, and may live in a subdirectory of\n * a uv workspace. Callers run this whenever they change the relevant state, so\n * the inputs stay correct regardless of generator order. No-op if the\n * license-check target doesn't exist yet.\n */\nexport const updateLicenseCheckTargetInputs = async (\n tree: Tree,\n): Promise<void> => {\n const rootProjectJsonPath = 'project.json';\n if (!tree.exists(rootProjectJsonPath)) return;\n\n const rootProject = JSON.parse(tree.read(rootProjectJsonPath, 'utf-8')!);\n const target = rootProject.targets?.['license-check'];\n if (!target) return;\n\n const inputs = NPM_LOCKFILES.filter((f) => tree.exists(f)).map(\n (f) => `{workspaceRoot}/${f}`,\n );\n\n if (await hasPythonCollector(tree)) {\n inputs.push('{workspaceRoot}/**/uv.lock');\n }\n\n inputs.push('{workspaceRoot}/aws-nx-plugin.config.mts');\n\n target.inputs = inputs;\n tree.write(rootProjectJsonPath, JSON.stringify(rootProject, null, 2));\n};\n\n/**\n * Whether the dependency check config has a `pythonCollector` configured.\n */\nconst hasPythonCollector = async (tree: Tree): Promise<boolean> => {\n if (!tree.exists(AWS_NX_PLUGIN_CONFIG_FILE_NAME)) return false;\n const { matchGritQL } = await import('../utils/ast');\n return matchGritQL(tree, AWS_NX_PLUGIN_CONFIG_FILE_NAME, '`pythonCollector`');\n};\n\n/**\n * The name of the project that owns the root `license-check` target, or\n * undefined if no project defines it.\n */\nconst findLicenseCheckProjectName = (tree: Tree): string | undefined => {\n for (const [name, config] of getProjects(tree)) {\n if (config.targets?.['license-check']) return name;\n }\n return undefined;\n};\n\n/**\n * Make a project's `lint` target depend on the root `license-check` target, so\n * license checking runs as part of lint/build. No-op when the project has no\n * `lint` target or there's no license-check target to depend on. Idempotent.\n *\n * Callers format afterwards (generators call `formatFilesInSubtree` at the end),\n * so the rewritten project.json matches prettier.\n */\nexport const addLicenseCheckToLintTarget = (\n tree: Tree,\n projectName: string,\n): void => {\n const licenseCheckProject = findLicenseCheckProjectName(tree);\n if (!licenseCheckProject) return;\n\n let project: ProjectConfiguration;\n try {\n project = readProjectConfiguration(tree, projectName);\n } catch {\n return;\n }\n\n // Only wire projects that actually lint, and never the license-check project\n // itself (a target can't depend on its own project's target).\n if (!project.targets?.lint || projectName === licenseCheckProject) return;\n\n addDependencyToTargetIfNotPresent(project, 'lint', {\n projects: [licenseCheckProject],\n target: 'license-check',\n });\n updateProjectConfiguration(tree, projectName, project);\n};\n\n/**\n * Wire every project's `lint` target to the root `license-check` target.\n * Called by the license generator so existing projects pick up the dependency\n * regardless of the order generators ran in.\n */\nexport const addLicenseCheckToAllLintTargets = (tree: Tree): void => {\n for (const [name] of getProjects(tree)) {\n addLicenseCheckToLintTarget(tree, name);\n }\n};\n\nexport interface EnsureDependencyCheckBlockOptions {\n includeCollectors?: 'npm' | 'npm+python';\n}\n\n/**\n * Ensure the `dependencies` block (dependency license checking) exists within\n * the `license` config. If one already exists it is left untouched, so user\n * customizations survive.\n */\nexport const ensureDependencyCheckBlock = async (\n tree: Tree,\n options?: EnsureDependencyCheckBlockOptions,\n): Promise<void> => {\n if (!tree.exists(AWS_NX_PLUGIN_CONFIG_FILE_NAME)) return;\n\n const { addDestructuredImport } = await import('../utils/ast');\n\n if (await hasDependenciesBlock(tree)) {\n return;\n }\n\n const withPython = options?.includeCollectors === 'npm+python';\n const collectors = withPython\n ? 'collectors: [npmCollector(), pythonCollector()]'\n : 'collectors: [npmCollector()]';\n\n const block = `dependencies: { allow: DEFAULT_LICENSE_ALLOWLIST, ${collectors}, exceptions: [] }`;\n\n // Prepend the block as the first property of the license object. Prepending\n // (rather than `+=` appending) is comma-safe for every shape: GritQL's `+=`\n // omits the separator when the last existing property's value is an object\n // literal (e.g. `source: { ... }`), which would corrupt the file.\n const added = await prependLicenseProperty(tree, block);\n\n // Only add the imports if the block was actually written (i.e. a license\n // object literal existed to attach it to).\n if (added) {\n await addDestructuredImport(\n tree,\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n withPython\n ? ['DEFAULT_LICENSE_ALLOWLIST', 'npmCollector', 'pythonCollector']\n : ['DEFAULT_LICENSE_ALLOWLIST', 'npmCollector'],\n LICENSE_SDK_MODULE,\n );\n await formatFilesInSubtree(tree, AWS_NX_PLUGIN_CONFIG_FILE_NAME);\n }\n};\n\n/**\n * Ensure license exceptions are present in `license.dependencies.exceptions`.\n * An exception whose package is already listed is skipped (so existing reasons\n * are never overwritten). Other exceptions, collectors and the allowlist are\n * left untouched.\n *\n * The `dependencies: { $scope }` scope keeps edits within the dependency-check\n * block, so an `exceptions` array elsewhere in the file isn't matched.\n */\nexport const ensureLicenseExceptions = async (\n tree: Tree,\n exceptions: DependencyCheckException[],\n): Promise<void> => {\n if (!tree.exists(AWS_NX_PLUGIN_CONFIG_FILE_NAME)) return;\n\n const { insertViaGritQL, GRIT_INSERT_PLACEHOLDER } = await import(\n '../utils/ast'\n );\n\n if (!(await hasDependenciesBlock(tree))) {\n return;\n }\n\n let modified = false;\n for (const exception of exceptions) {\n const pkg = JSON.stringify(exception.package);\n const inserted = await insertViaGritQL(\n tree,\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n `\\`dependencies: { $scope }\\` where {\n $scope <: not contains \\`package: ${pkg}\\`,\n ${appendToArray('exceptions', GRIT_INSERT_PLACEHOLDER)}\n }`,\n exceptionLiteral(exception),\n );\n modified ||= inserted;\n }\n\n if (modified) {\n await formatFilesInSubtree(tree, AWS_NX_PLUGIN_CONFIG_FILE_NAME);\n }\n};\n\n/**\n * Add `pythonCollector()` to `license.dependencies.collectors`, unless one is\n * already configured.\n */\nexport const ensurePythonLicenseCollector = async (\n tree: Tree,\n): Promise<void> => {\n if (!tree.exists(AWS_NX_PLUGIN_CONFIG_FILE_NAME)) return;\n\n const { addDestructuredImport, insertViaGritQL, GRIT_INSERT_PLACEHOLDER } =\n await import('../utils/ast');\n\n if (!(await hasDependenciesBlock(tree))) {\n return;\n }\n\n const added = await insertViaGritQL(\n tree,\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n `\\`dependencies: { $scope }\\` where {\n $scope <: not contains \\`pythonCollector\\`,\n ${appendToArray('collectors', GRIT_INSERT_PLACEHOLDER)}\n }`,\n 'pythonCollector()',\n );\n\n if (added) {\n await addDestructuredImport(\n tree,\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n ['pythonCollector'],\n LICENSE_SDK_MODULE,\n );\n await formatFilesInSubtree(tree, AWS_NX_PLUGIN_CONFIG_FILE_NAME);\n // Now that a Python collector is configured, ensure uv.lock is a cache\n // input. Runs here (not only in the license generator) so it's added\n // whenever the collector is — e.g. when py#project runs after license.\n await updateLicenseCheckTargetInputs(tree);\n }\n};\n\n/**\n * Build the default `license.source` config for a given license\n */\nexport const defaultLicenseConfig = (\n spdx: SPDXLicenseIdentifier,\n copyrightHolder: string,\n): LicenseSourceConfig => {\n switch (spdx) {\n case 'ASL': {\n // For ASL, we use a \"box\" style license header\n const rawContent = [\n `Copyright ${copyrightHolder}. All Rights Reserved.`,\n '',\n 'Licensed under the Amazon Software License (the \"License\"). You may not use this file except in compliance',\n 'with the License. A copy of the License is located at',\n '',\n ' https://aws.amazon.com/asl/',\n '',\n 'or in the \"license\" file accompanying this file. This file is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES',\n 'OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions',\n 'and limitations under the License.',\n ];\n const maxLen = Math.max(...rawContent.map((line) => line.length));\n const lines = rawContent.map(\n (line) => `${line}${' '.repeat(maxLen - line.length)}`,\n );\n return {\n spdx,\n copyrightHolder,\n header: {\n content: { lines },\n format: {\n '**/*.{js,ts,jsx,tsx,mjs,mts}': {\n blockStart: `/***${'*'.repeat(maxLen)}**`,\n lineStart: ' * ',\n lineEnd: ' *',\n blockEnd: ` ***${'*'.repeat(maxLen)}**/`,\n },\n '**/*.{py,sh,tf}': {\n blockStart: `###${'#'.repeat(maxLen)}##`,\n lineStart: '# ',\n lineEnd: ' #',\n blockEnd: `###${'#'.repeat(maxLen)}##`,\n },\n },\n exclude: ['**/*.gen.*'],\n },\n };\n }\n default: {\n return {\n spdx,\n copyrightHolder,\n ...(LICENSES_WITH_YEAR.has(spdx)\n ? {\n copyrightYear: new Date().getFullYear(),\n }\n : {}),\n header: {\n content: {\n lines: [\n `Copyright ${copyrightHolder}. All Rights Reserved.`,\n `SPDX-License-Identifier: ${spdx}`,\n ],\n },\n format: {\n '**/*.{js,ts,jsx,tsx,mjs,mts}': {\n blockStart: '/**',\n lineStart: ' * ',\n blockEnd: ' */',\n },\n '**/*.{py,sh,tf}': {\n blockStart: '#',\n lineStart: '# ',\n blockEnd: '#',\n },\n },\n exclude: ['**/*.gen.*'],\n },\n };\n }\n }\n};\n\n/**\n * Write the `license.source` config (headers + LICENSE files) to the aws nx\n * plugin config.\n *\n * The `source` block is (re)written, but any existing `license.dependencies`\n * block — a user-customized allowlist, collectors and exceptions — is\n * preserved, so re-running the license generator (e.g. to change the copyright\n * holder) never clobbers dependency-check customizations.\n */\nexport const writeLicenseConfig = async (\n tree: Tree,\n source: LicenseSourceConfig,\n) => {\n const { captureGritQL } = await import('../utils/ast');\n\n // Capture the existing `dependencies: { ... }` block before overwriting the\n // license value, so we can re-attach it afterwards. It's managed by the\n // ensure* helpers, never written from here.\n const preserved = tree.exists(AWS_NX_PLUGIN_CONFIG_FILE_NAME)\n ? await captureGritQL(\n tree,\n AWS_NX_PLUGIN_CONFIG_FILE_NAME,\n '`dependencies: $_`',\n )\n : undefined;\n\n await updateAwsNxPluginConfig(tree, { license: { source } });\n\n // Re-attach the preserved block. The captured text may contain backticks,\n // `${...}` or quotes — prependLicenseProperty routes it through a placeholder\n // so it never enters the GritQL pattern.\n if (preserved) {\n await prependLicenseProperty(tree, preserved);\n await formatFilesInSubtree(tree, AWS_NX_PLUGIN_CONFIG_FILE_NAME);\n }\n};\n\n/**\n * Read license configuration\n */\nexport const readLicenseConfig = async (\n tree: Tree,\n): Promise<LicenseConfig | undefined> => {\n return readAwsNxPluginConfig(tree)?.license;\n};\n"],"names":["getProjects","readProjectConfiguration","updateProjectConfiguration","AWS_NX_PLUGIN_CONFIG_FILE_NAME","readAwsNxPluginConfig","updateAwsNxPluginConfig","formatFilesInSubtree","addDependencyToTargetIfNotPresent","LICENSES_WITH_YEAR","Set","LANGUAGE_COMMENT_SYNTAX","Object","fromEntries","map","ext","line","block","start","end","Dockerfile","py","html","css","rb","vb","lua","ps1","psm1","md","tf","smithy","LICENSE_SDK_MODULE","exceptionLiteral","exception","parts","JSON","stringify","package","version","undefined","push","reason","spdx","join","appendToArray","key","ins","prependLicenseProperty","tree","property","insertViaGritQL","GRIT_INSERT_PLACEHOLDER","intoNonEmpty","hasDependenciesBlock","exists","matchGritQL","NPM_LOCKFILES","updateLicenseCheckTargetInputs","rootProjectJsonPath","rootProject","parse","read","target","targets","inputs","filter","f","hasPythonCollector","write","findLicenseCheckProjectName","name","config","addLicenseCheckToLintTarget","projectName","licenseCheckProject","project","lint","projects","addLicenseCheckToAllLintTargets","ensureDependencyCheckBlock","options","addDestructuredImport","withPython","includeCollectors","collectors","added","ensureLicenseExceptions","exceptions","modified","pkg","inserted","ensurePythonLicenseCollector","defaultLicenseConfig","copyrightHolder","rawContent","maxLen","Math","max","length","lines","repeat","header","content","format","blockStart","lineStart","lineEnd","blockEnd","exclude","has","copyrightYear","Date","getFullYear","writeLicenseConfig","source","captureGritQL","preserved","license","readLicenseConfig"],"mappings":"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"}
@@ -6,7 +6,7 @@ import { z } from 'zod';
6
6
  export declare const PACKAGE_MANAGERS: readonly ["pnpm", "yarn", "npm", "bun"];
7
7
  export declare const PackageManagerSchema: z.ZodEnum<{
8
8
  npm: "npm";
9
- pnpm: "pnpm";
10
9
  yarn: "yarn";
10
+ pnpm: "pnpm";
11
11
  bun: "bun";
12
12
  }>;
@@ -42,12 +42,11 @@ ${PACKAGE_MANAGERS.map((pm)=>buildNxCommand('<options>', pm)).join(' - \n')}
42
42
 
43
43
  ## General Instructions
44
44
 
45
- - Workspaces contain a single \`package.json\` file at the root which defines the dependencies for all projects. Therefore when installing dependencies, you must add these to the root workspace using the appropriate command for your package manager:
46
- - pnpm add -w -D <package>
47
- - yarn add -D <package>
48
- - npm install --legacy-peer-deps -D <package>
49
- - bun add -D <package>
50
- - (Omit -D for production dependencies)
45
+ - Each project declares the third-party runtime dependencies its source imports in its own \`package.json\`; shared build/test tooling (test runners, bundlers, etc.) is declared in the root \`package.json\` \`devDependencies\`. Versions follow a single version policy, recorded in the package manager's dependency catalog where supported (referenced as \`catalog:\`). Install with the appropriate command for your package manager:
46
+ - Add a project runtime dependency: \`pnpm add <package> --filter <project>\` / \`yarn workspace <project> add <package>\` / \`npm install <package> -w <project>\` / \`bun add <package> --cwd <project-directory>\`
47
+ - Add a shared dev tool at the root: \`pnpm add -Dw <package>\` / \`yarn add -D <package>\` / \`npm install --legacy-peer-deps -D <package>\` / \`bun install -D <package>\`
48
+ - The \`noUndeclaredDependencies\` lint rule enforces that a project's source only imports packages declared in its own \`package.json\`
49
+ - Projects in the same workspace can import one another directly by package name (eg \`@workspace-name/project-name\`) without declaring a dependency in \`package.json\` — TypeScript path aliases in \`tsconfig.base.json\` resolve these imports
51
50
  - When specifying project names as arguments to generators, prefer the _fully qualified_ project name, for example \`@workspace-name/project-name\`. Check the \`project.json\` file for the specific package to find its fully qualified name
52
51
  - When no generator exists for a specific framework required, use the base \`ts#project\` and \`py#project\` generators and build on top.
53
52
  - Leave the \`--infra\` option at its default value unless the user has explicitly instructed otherwise. Generators choose a sensible default type of infrastructure to deploy the project with, so only override \`--infra\` when the user has specified a particular requirement.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../packages/nx-plugin/src/mcp-server/tools/general-guidance.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { NxGeneratorInfo } from '../../utils/generators';\nimport { IAC_PROVIDERS } from '../../utils/iac-providers';\nimport { buildNxCommand, fetchGuidePages } from '../generator-info';\nimport { PACKAGE_MANAGERS } from '../schema';\n\nexport const TOOL_SELECTION_GUIDE = `## Tool Selection Guide\n\n- Use the \\`general-guidance\\` tool for guidance and best practices for working with Nx and the Nx Plugin for AWS.\n- Use the \\`create-workspace-command\\` tool to discover how to create a workspace to start a new project.\n- Use the \\`add-to-existing-project\\` tool when adding the plugin to an existing Nx workspace or non-Nx monorepo, or when troubleshooting configuration errors in such a workspace.\n- Use the \\`list-generators\\` tool to discover the available generators and how to run them.\n- Use the \\`generator-guide\\` tool to retrieve detailed information about a specific generator.`;\n\n/**\n * Add a tool which provides general guidance for using Nx and the Nx Plugin for AWS\n */\nexport const addGeneralGuidanceTool = (\n server: McpServer,\n generators: NxGeneratorInfo[],\n) => {\n server.registerTool(\n 'general-guidance',\n {\n title: 'General Guidance',\n description:\n 'Tool for guidance and best practices for working with Nx and the Nx Plugin for AWS',\n },\n async () => ({\n content: [\n {\n type: 'text' as const,\n text: `# Nx Plugin for AWS Guidance\n\n${TOOL_SELECTION_GUIDE}\n\n## Getting Started\n\n- Choose a package manager first. You can choose between ${PACKAGE_MANAGERS.join(', ')}. It's recommended to use \"pnpm\" if the user has no preference\n- Choose an infrastructure as code (IaC) provider next. You can choose between ${IAC_PROVIDERS.join(', ')}. It's recommended to use CDK if the user has no preference\n- Next, you must create an Nx workspace. Use the \\`create-workspace-command\\` tool for more details, and provide it with your chosen package manager\n- After this, you can start scaffolding the main components of your application using generators. Use the \\`list-generators\\` tool to discover available generators, and the \\`generator-guide\\` tool for more detailed information about a specific generator\n\n## Nx Primer\n\n- Prefix nx commands with the appropriate prefix for your package manager, for example:\n${PACKAGE_MANAGERS.map((pm) => buildNxCommand('<options>', pm)).join(' - \\n')}\n- Each project in your workspace has a file named \\`project.json\\` which contains important project information such as its name, and defines the \"targets\" which can be run for that project, for example building or testing the project\n- Use the command \\`nx reset\\` to reset the Nx daemon when unexpected issues arise\n- After adding dependencies between TypeScript projects, use \\`nx sync\\` to ensure project references are set up correctly\n\n## General Instructions\n\n- Workspaces contain a single \\`package.json\\` file at the root which defines the dependencies for all projects. Therefore when installing dependencies, you must add these to the root workspace using the appropriate command for your package manager:\n - pnpm add -w -D <package>\n - yarn add -D <package>\n - npm install --legacy-peer-deps -D <package>\n - bun add -D <package>\n - (Omit -D for production dependencies)\n- When specifying project names as arguments to generators, prefer the _fully qualified_ project name, for example \\`@workspace-name/project-name\\`. Check the \\`project.json\\` file for the specific package to find its fully qualified name\n- When no generator exists for a specific framework required, use the base \\`ts#project\\` and \\`py#project\\` generators and build on top.\n- Leave the \\`--infra\\` option at its default value unless the user has explicitly instructed otherwise. Generators choose a sensible default type of infrastructure to deploy the project with, so only override \\`--infra\\` when the user has specified a particular requirement.\n\n## Useful Commands\n\n- Fix lint issues with \\`nx run-many --target lint --configuration=fix --all --output-style=stream\\`\n- Build all projects with \\`nx run-many --target build --all --output-style=stream\\`\n- Prefer importing the CDK constructs vended by generators in \\`packages/common/constructs\\` over writing your own\n\n## Best Practices\n\n- After running a generator, use the \\`nx show projects\\` command to check which projects have been added (if any)\n- Carefully examine the files that have been generated and always refer back to the generator guide when working in a generated project\n- Generate all projects into the \\`packages/\\` directory\n- After making changes to your projects, fix linting issues, then run a full build\n- When it's time to start testing a project, suggest to the user that infrastructure is deployed to AWS. For websites, if a runtime-config.json is needed, use the load:runtime-config target after a deployment to point a local website at a sandbox stack.\n\n## Batching Generators\n\nWhen scaffolding several projects in one go, chain generators to avoid a slow dependency install after every generator:\n\n- **Chain generators** with \\`&&\\` in a single command. Pass \\`--prefer-install-dependencies=false\\` on each generator except the last so dependencies install once at the end, for example:\n\n${PACKAGE_MANAGERS.map(\n (pm) => ` \\`\\`\\`bash\n ${buildNxCommand('g @aws/nx-plugin:ts#trpc-api --no-interactive --name=my-app-api --auth=IAM --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:ts#react-website --no-interactive --name=my-app-website --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:connection --no-interactive --sourceProject=@my-app/my-app-website --targetProject=@my-app/my-app-api --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:ts#infra --no-interactive --name=infra', pm)} && \\\\\n ${buildNxCommand('sync', pm)}\n \\`\\`\\``,\n).join('\\n')}\n\n- **\\`--prefer-install-dependencies=false\\`** asks a generator to defer its dependency install so the batch installs once at the end (the final generator above omits the flag and installs everything).\n- **\\`nx sync\\`** is required before building — generators modify TypeScript project references.\n\n## Detailed Guides\n\nPlease refer to the below documentation for important details regarding workspaces and working with TypeScript or Python projects.\n\n${await fetchGuidePages(['workspace', 'typescript-project', 'python-project'], generators)}\n\n `,\n },\n ],\n }),\n );\n};\n"],"names":["IAC_PROVIDERS","buildNxCommand","fetchGuidePages","PACKAGE_MANAGERS","TOOL_SELECTION_GUIDE","addGeneralGuidanceTool","server","generators","registerTool","title","description","content","type","text","join","map","pm"],"mappings":"AAAA;;;CAGC,GAGD,SAASA,aAAa,QAAQ,+BAA4B;AAC1D,SAASC,cAAc,EAAEC,eAAe,QAAQ,uBAAoB;AACpE,SAASC,gBAAgB,QAAQ,eAAY;AAE7C,OAAO,MAAMC,uBAAuB,CAAC;;;;;;+FAM0D,CAAC,CAAC;AAEjG;;CAEC,GACD,OAAO,MAAMC,yBAAyB,CACpCC,QACAC;IAEAD,OAAOE,YAAY,CACjB,oBACA;QACEC,OAAO;QACPC,aACE;IACJ,GACA,UAAa,CAAA;YACXC,SAAS;gBACP;oBACEC,MAAM;oBACNC,MAAM,CAAC;;AAEjB,EAAET,qBAAqB;;;;yDAIkC,EAAED,iBAAiBW,IAAI,CAAC,MAAM;+EACR,EAAEd,cAAcc,IAAI,CAAC,MAAM;;;;;;;AAO1G,EAAEX,iBAAiBY,GAAG,CAAC,CAACC,KAAOf,eAAe,aAAae,KAAKF,IAAI,CAAC,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqC9E,EAAEX,iBAAiBY,GAAG,CACpB,CAACC,KAAO,CAAC;EACT,EAAEf,eAAe,kHAAkHe,IAAI;IACrI,EAAEf,eAAe,gHAAgHe,IAAI;IACrI,EAAEf,eAAe,8JAA8Je,IAAI;IACnL,EAAEf,eAAe,2DAA2De,IAAI;IAChF,EAAEf,eAAe,QAAQe,IAAI;QACzB,CAAC,EACPF,IAAI,CAAC,MAAM;;;;;;;;;AASb,EAAE,MAAMZ,gBAAgB;wBAAC;wBAAa;wBAAsB;qBAAiB,EAAEK,YAAY;;IAEvF,CAAC;gBACG;aACD;QACH,CAAA;AAEJ,EAAE"}
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/mcp-server/tools/general-guidance.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { NxGeneratorInfo } from '../../utils/generators';\nimport { IAC_PROVIDERS } from '../../utils/iac-providers';\nimport { buildNxCommand, fetchGuidePages } from '../generator-info';\nimport { PACKAGE_MANAGERS } from '../schema';\n\nexport const TOOL_SELECTION_GUIDE = `## Tool Selection Guide\n\n- Use the \\`general-guidance\\` tool for guidance and best practices for working with Nx and the Nx Plugin for AWS.\n- Use the \\`create-workspace-command\\` tool to discover how to create a workspace to start a new project.\n- Use the \\`add-to-existing-project\\` tool when adding the plugin to an existing Nx workspace or non-Nx monorepo, or when troubleshooting configuration errors in such a workspace.\n- Use the \\`list-generators\\` tool to discover the available generators and how to run them.\n- Use the \\`generator-guide\\` tool to retrieve detailed information about a specific generator.`;\n\n/**\n * Add a tool which provides general guidance for using Nx and the Nx Plugin for AWS\n */\nexport const addGeneralGuidanceTool = (\n server: McpServer,\n generators: NxGeneratorInfo[],\n) => {\n server.registerTool(\n 'general-guidance',\n {\n title: 'General Guidance',\n description:\n 'Tool for guidance and best practices for working with Nx and the Nx Plugin for AWS',\n },\n async () => ({\n content: [\n {\n type: 'text' as const,\n text: `# Nx Plugin for AWS Guidance\n\n${TOOL_SELECTION_GUIDE}\n\n## Getting Started\n\n- Choose a package manager first. You can choose between ${PACKAGE_MANAGERS.join(', ')}. It's recommended to use \"pnpm\" if the user has no preference\n- Choose an infrastructure as code (IaC) provider next. You can choose between ${IAC_PROVIDERS.join(', ')}. It's recommended to use CDK if the user has no preference\n- Next, you must create an Nx workspace. Use the \\`create-workspace-command\\` tool for more details, and provide it with your chosen package manager\n- After this, you can start scaffolding the main components of your application using generators. Use the \\`list-generators\\` tool to discover available generators, and the \\`generator-guide\\` tool for more detailed information about a specific generator\n\n## Nx Primer\n\n- Prefix nx commands with the appropriate prefix for your package manager, for example:\n${PACKAGE_MANAGERS.map((pm) => buildNxCommand('<options>', pm)).join(' - \\n')}\n- Each project in your workspace has a file named \\`project.json\\` which contains important project information such as its name, and defines the \"targets\" which can be run for that project, for example building or testing the project\n- Use the command \\`nx reset\\` to reset the Nx daemon when unexpected issues arise\n- After adding dependencies between TypeScript projects, use \\`nx sync\\` to ensure project references are set up correctly\n\n## General Instructions\n\n- Each project declares the third-party runtime dependencies its source imports in its own \\`package.json\\`; shared build/test tooling (test runners, bundlers, etc.) is declared in the root \\`package.json\\` \\`devDependencies\\`. Versions follow a single version policy, recorded in the package manager's dependency catalog where supported (referenced as \\`catalog:\\`). Install with the appropriate command for your package manager:\n - Add a project runtime dependency: \\`pnpm add <package> --filter <project>\\` / \\`yarn workspace <project> add <package>\\` / \\`npm install <package> -w <project>\\` / \\`bun add <package> --cwd <project-directory>\\`\n - Add a shared dev tool at the root: \\`pnpm add -Dw <package>\\` / \\`yarn add -D <package>\\` / \\`npm install --legacy-peer-deps -D <package>\\` / \\`bun install -D <package>\\`\n- The \\`noUndeclaredDependencies\\` lint rule enforces that a project's source only imports packages declared in its own \\`package.json\\`\n- Projects in the same workspace can import one another directly by package name (eg \\`@workspace-name/project-name\\`) without declaring a dependency in \\`package.json\\` — TypeScript path aliases in \\`tsconfig.base.json\\` resolve these imports\n- When specifying project names as arguments to generators, prefer the _fully qualified_ project name, for example \\`@workspace-name/project-name\\`. Check the \\`project.json\\` file for the specific package to find its fully qualified name\n- When no generator exists for a specific framework required, use the base \\`ts#project\\` and \\`py#project\\` generators and build on top.\n- Leave the \\`--infra\\` option at its default value unless the user has explicitly instructed otherwise. Generators choose a sensible default type of infrastructure to deploy the project with, so only override \\`--infra\\` when the user has specified a particular requirement.\n\n## Useful Commands\n\n- Fix lint issues with \\`nx run-many --target lint --configuration=fix --all --output-style=stream\\`\n- Build all projects with \\`nx run-many --target build --all --output-style=stream\\`\n- Prefer importing the CDK constructs vended by generators in \\`packages/common/constructs\\` over writing your own\n\n## Best Practices\n\n- After running a generator, use the \\`nx show projects\\` command to check which projects have been added (if any)\n- Carefully examine the files that have been generated and always refer back to the generator guide when working in a generated project\n- Generate all projects into the \\`packages/\\` directory\n- After making changes to your projects, fix linting issues, then run a full build\n- When it's time to start testing a project, suggest to the user that infrastructure is deployed to AWS. For websites, if a runtime-config.json is needed, use the load:runtime-config target after a deployment to point a local website at a sandbox stack.\n\n## Batching Generators\n\nWhen scaffolding several projects in one go, chain generators to avoid a slow dependency install after every generator:\n\n- **Chain generators** with \\`&&\\` in a single command. Pass \\`--prefer-install-dependencies=false\\` on each generator except the last so dependencies install once at the end, for example:\n\n${PACKAGE_MANAGERS.map(\n (pm) => ` \\`\\`\\`bash\n ${buildNxCommand('g @aws/nx-plugin:ts#trpc-api --no-interactive --name=my-app-api --auth=IAM --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:ts#react-website --no-interactive --name=my-app-website --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:connection --no-interactive --sourceProject=@my-app/my-app-website --targetProject=@my-app/my-app-api --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:ts#infra --no-interactive --name=infra', pm)} && \\\\\n ${buildNxCommand('sync', pm)}\n \\`\\`\\``,\n).join('\\n')}\n\n- **\\`--prefer-install-dependencies=false\\`** asks a generator to defer its dependency install so the batch installs once at the end (the final generator above omits the flag and installs everything).\n- **\\`nx sync\\`** is required before building — generators modify TypeScript project references.\n\n## Detailed Guides\n\nPlease refer to the below documentation for important details regarding workspaces and working with TypeScript or Python projects.\n\n${await fetchGuidePages(['workspace', 'typescript-project', 'python-project'], generators)}\n\n `,\n },\n ],\n }),\n );\n};\n"],"names":["IAC_PROVIDERS","buildNxCommand","fetchGuidePages","PACKAGE_MANAGERS","TOOL_SELECTION_GUIDE","addGeneralGuidanceTool","server","generators","registerTool","title","description","content","type","text","join","map","pm"],"mappings":"AAAA;;;CAGC,GAGD,SAASA,aAAa,QAAQ,+BAA4B;AAC1D,SAASC,cAAc,EAAEC,eAAe,QAAQ,uBAAoB;AACpE,SAASC,gBAAgB,QAAQ,eAAY;AAE7C,OAAO,MAAMC,uBAAuB,CAAC;;;;;;+FAM0D,CAAC,CAAC;AAEjG;;CAEC,GACD,OAAO,MAAMC,yBAAyB,CACpCC,QACAC;IAEAD,OAAOE,YAAY,CACjB,oBACA;QACEC,OAAO;QACPC,aACE;IACJ,GACA,UAAa,CAAA;YACXC,SAAS;gBACP;oBACEC,MAAM;oBACNC,MAAM,CAAC;;AAEjB,EAAET,qBAAqB;;;;yDAIkC,EAAED,iBAAiBW,IAAI,CAAC,MAAM;+EACR,EAAEd,cAAcc,IAAI,CAAC,MAAM;;;;;;;AAO1G,EAAEX,iBAAiBY,GAAG,CAAC,CAACC,KAAOf,eAAe,aAAae,KAAKF,IAAI,CAAC,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoC9E,EAAEX,iBAAiBY,GAAG,CACpB,CAACC,KAAO,CAAC;EACT,EAAEf,eAAe,kHAAkHe,IAAI;IACrI,EAAEf,eAAe,gHAAgHe,IAAI;IACrI,EAAEf,eAAe,8JAA8Je,IAAI;IACnL,EAAEf,eAAe,2DAA2De,IAAI;IAChF,EAAEf,eAAe,QAAQe,IAAI;QACzB,CAAC,EACPF,IAAI,CAAC,MAAM;;;;;;;;;AASb,EAAE,MAAMZ,gBAAgB;wBAAC;wBAAa;wBAAsB;qBAAiB,EAAEK,YAAY;;IAEvF,CAAC;gBACG;aACD;QACH,CAAA;AAEJ,EAAE"}
@@ -239,6 +239,7 @@ exports[`preset generator > should run successfully > aws-nx-plugin.config.mts 1
239
239
  export default {
240
240
  iac: { provider: 'cdk' },
241
241
  containers: { engine: 'docker' },
242
+ packageManager: { catalogs: true },
242
243
  } satisfies AwsNxPluginConfig;
243
244
  "
244
245
  `;
@@ -257,6 +258,9 @@ exports[`preset generator > should run successfully > biome.json 1`] = `
257
258
  "formatter": {
258
259
  "quoteStyle": "single",
259
260
  "trailingCommas": "all"
261
+ },
262
+ "resolver": {
263
+ "experimentalPnpmCatalogs": true
260
264
  }
261
265
  },
262
266
  "css": {
@@ -272,7 +276,7 @@ exports[`preset generator > should run successfully > biome.json 1`] = `
272
276
  "rules": {
273
277
  "preset": "none",
274
278
  "correctness": {
275
- "noUndeclaredDependencies": "warn"
279
+ "noUndeclaredDependencies": "error"
276
280
  }
277
281
  }
278
282
  },
@@ -291,12 +295,29 @@ exports[`preset generator > should run successfully > biome.json 1`] = `
291
295
  "!**/node_modules",
292
296
  "!**/.nx",
293
297
  "!**/.venv",
298
+ "!**/.grit",
294
299
  "!**/*.css",
295
300
  "!**/*.gen.*",
296
301
  "!**/generated/**",
297
302
  "!**/tsconfig*.json"
298
303
  ]
299
- }
304
+ },
305
+ "overrides": [
306
+ {
307
+ "includes": [
308
+ "**/*.config.{ts,mts,cts,js,mjs,cjs}",
309
+ "**/*.{spec,test}.{ts,tsx,mts,cts,js,jsx,mjs,cjs}",
310
+ "**/*.stories.{ts,tsx}"
311
+ ],
312
+ "linter": {
313
+ "rules": {
314
+ "correctness": {
315
+ "noUndeclaredDependencies": "off"
316
+ }
317
+ }
318
+ }
319
+ }
320
+ ]
300
321
  }
301
322
  "
302
323
  `;
@@ -343,14 +364,17 @@ exports[`preset generator > should run successfully > package.json 1`] = `
343
364
  "name": "@proj/source",
344
365
  "dependencies": {},
345
366
  "devDependencies": {
346
- "@biomejs/biome": "2.5.4",
347
- "@nx/js": "23.1.0",
348
- "@nx/workspace": "23.1.0",
367
+ "@biomejs/biome": "catalog:",
368
+ "@nx/js": "catalog:",
369
+ "@nx/workspace": "catalog:",
349
370
  "@swc/helpers": "~0.5.18",
350
- "nx": "23.1.0",
351
- "typescript": "~6.0.3"
371
+ "nx": "catalog:",
372
+ "typescript": "catalog:"
352
373
  },
353
374
  "type": "module",
375
+ "workspaces": [
376
+ "packages/*"
377
+ ],
354
378
  "scripts": {
355
379
  "dev": "nx run-many --target dev",
356
380
  "build": "nx run-many --target build",
@@ -380,6 +404,13 @@ onlyBuiltDependencies:
380
404
  - esbuild
381
405
  - nx
382
406
  - sharp
407
+ catalogMode: strict
408
+ catalog:
409
+ nx: 23.1.0
410
+ '@nx/js': 23.1.0
411
+ '@nx/workspace': 23.1.0
412
+ typescript: ~6.0.3
413
+ '@biomejs/biome': 2.5.4
383
414
  "
384
415
  `;
385
416
 
@@ -29,5 +29,5 @@ export declare const PRESET_GENERATOR_INFO: NxGeneratorInfo;
29
29
  * isAmazonian(); // false
30
30
  */
31
31
  export declare function isAmazonian(): boolean;
32
- export declare const presetGenerator: (tree: Tree, { iac, gitSecrets, mcp, containers, module, preferInstallDependencies, }: PresetGeneratorSchema) => Promise<GeneratorCallback>;
32
+ export declare const presetGenerator: (tree: Tree, { iac, gitSecrets, mcp, containers, module, catalog, preferInstallDependencies, }: PresetGeneratorSchema) => Promise<GeneratorCallback>;
33
33
  export default presetGenerator;
@@ -1,11 +1,12 @@
1
1
  /**
2
2
  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
- */ import { addDependenciesToPackageJson, joinPathFragments, OverwriteStrategy, updateJson } from "@nx/devkit";
4
+ */ import { joinPathFragments, OverwriteStrategy, updateJson } from "@nx/devkit";
5
5
  import { execSync } from "child_process";
6
6
  import enquirer from "enquirer";
7
7
  import { readFileSync } from "fs";
8
8
  import { ensureAwsNxPluginConfig, updateAwsNxPluginConfig } from "../utils/config/utils.js";
9
+ import { addDependenciesToPackageJson } from "../utils/dependencies.js";
9
10
  import { formatFilesInSubtree } from "../utils/format.js";
10
11
  import { applyWorkspaceInit } from "../utils/init.js";
11
12
  import { installDependencies } from "../utils/install.js";
@@ -75,7 +76,7 @@ const setUpGitSecrets = (tree)=>{
75
76
  'husky'
76
77
  ]));
77
78
  };
78
- export const presetGenerator = async (tree, { iac, gitSecrets, mcp, containers, module, preferInstallDependencies })=>{
79
+ export const presetGenerator = async (tree, { iac, gitSecrets, mcp, containers, module, catalog, preferInstallDependencies })=>{
79
80
  if (isAmazonian() && !process.env.VITEST && !process.env.CI && process.env.NX_DRY_RUN !== 'true' && process.env.NX_INTERACTIVE !== 'false') {
80
81
  const { engagementId } = await enquirer.prompt([
81
82
  {
@@ -108,6 +109,7 @@ export const presetGenerator = async (tree, { iac, gitSecrets, mcp, containers,
108
109
  iac,
109
110
  containers,
110
111
  mcp,
112
+ catalogs: catalog ?? true,
111
113
  readmeOverwriteStrategy: OverwriteStrategy.Overwrite,
112
114
  overwriteScripts: true
113
115
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/preset/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n addDependenciesToPackageJson,\n type GeneratorCallback,\n joinPathFragments,\n OverwriteStrategy,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { execSync } from 'child_process';\nimport enquirer from 'enquirer';\nimport { readFileSync } from 'fs';\nimport {\n ensureAwsNxPluginConfig,\n updateAwsNxPluginConfig,\n} from '../utils/config/utils';\nimport { formatFilesInSubtree } from '../utils/format';\nimport { applyWorkspaceInit } from '../utils/init';\nimport { installDependencies } from '../utils/install';\nimport { getGeneratorInfo, type NxGeneratorInfo } from '../utils/nx';\nimport { withVersions } from '../utils/versions';\nimport type { PresetGeneratorSchema } from './schema';\n\nexport const PRESET_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\n/**\n * Determines if the current user is an Amazon employee based on their git configuration.\n *\n * This function checks the git user email configuration to identify Amazon employees\n * by looking for email addresses with Amazon domains (e.g., @amazon.com, @amazon.co.uk).\n *\n * @returns {boolean} True if the user's git email has an Amazon domain, false otherwise\n *\n * @example\n * // Returns true for Amazon employee emails\n * // git config user.email = \"john.doe@amazon.com\"\n * isAmazonian(); // true\n *\n * @example\n * // Returns false for non-Amazon emails\n * // git config user.email = \"user@example.com\"\n * isAmazonian(); // false\n *\n * @example\n * // Returns false when git config is not available or throws an error\n * isAmazonian(); // false\n */\nexport function isAmazonian(): boolean {\n try {\n // Execute git command to retrieve the user's configured email address\n const gitEmail = execSync('git config user.email', {\n encoding: 'utf8',\n }).trim();\n\n // Return false if no email is configured\n if (!gitEmail) {\n return false;\n }\n\n // Split email address to extract domain part\n const emailParts = gitEmail.split('@');\n if (emailParts.length < 2) {\n return false;\n }\n\n // Extract domain and normalize to lowercase for comparison\n const domain = emailParts[1].toLowerCase();\n\n // Check if domain starts with 'amazon.' (covers amazon.com, amazon.co.uk, etc.)\n return domain.startsWith('amazon.');\n } catch (error) {\n // Return false if git command fails or any other error occurs\n // This handles cases where git is not installed or configured\n return false;\n }\n}\n\nconst setUpGitSecrets = (tree: Tree) => {\n const gitSecretsDir = joinPathFragments(\n import.meta.dirname,\n 'git-secrets-files',\n 'git-secrets-dir',\n );\n const huskyDir = joinPathFragments(\n import.meta.dirname,\n 'git-secrets-files',\n 'husky-dir',\n );\n\n tree.write(\n '.git-secrets/git-secrets',\n readFileSync(joinPathFragments(gitSecretsDir, 'git-secrets'), 'utf-8'),\n );\n tree.write(\n '.husky/pre-commit',\n readFileSync(joinPathFragments(huskyDir, 'pre-commit'), 'utf-8'),\n );\n tree.write('.gitallowed', '\\\\.git-secrets/git-secrets:\\n');\n\n updateJson(tree, 'package.json', (json) => ({\n ...json,\n scripts: {\n ...json.scripts,\n prepare: 'husky',\n },\n }));\n\n addDependenciesToPackageJson(tree, {}, withVersions(['husky']));\n};\n\nexport const presetGenerator = async (\n tree: Tree,\n {\n iac,\n gitSecrets,\n mcp,\n containers,\n module,\n preferInstallDependencies,\n }: PresetGeneratorSchema,\n): Promise<GeneratorCallback> => {\n if (\n isAmazonian() &&\n !process.env.VITEST &&\n !process.env.CI &&\n process.env.NX_DRY_RUN !== 'true' &&\n process.env.NX_INTERACTIVE !== 'false'\n ) {\n const { engagementId } = await enquirer.prompt<{ engagementId?: string }>([\n {\n name: 'engagementId',\n message: 'Please enter your engagementId (if known)',\n type: 'input',\n initial: 'None',\n },\n ]);\n\n if (engagementId != 'None') {\n await ensureAwsNxPluginConfig(tree);\n await updateAwsNxPluginConfig(tree, { tags: [engagementId] });\n }\n }\n\n // The preset owns the greenfield workspace's module format: write the root\n // `type` explicitly from the chosen `--module` so later generators can\n // infer it. The `init` generator never touches an existing workspace's\n // `type` field.\n updateJson(tree, 'package.json', (packageJson) => ({\n ...packageJson,\n type: (module ?? 'esm') === 'esm' ? 'module' : 'commonjs',\n }));\n\n // Apply the deterministic workspace configuration shared with the `init`\n // generator. The preset owns the README of a greenfield workspace.\n await applyWorkspaceInit(tree, {\n iac,\n containers,\n mcp,\n readmeOverwriteStrategy: OverwriteStrategy.Overwrite,\n overwriteScripts: true,\n });\n\n tree.delete('apps/.gitkeep');\n tree.delete('libs/.gitkeep');\n tree.write('packages/.gitkeep', '');\n\n if (gitSecrets !== false) {\n setUpGitSecrets(tree);\n }\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\nexport default presetGenerator;\n"],"names":["addDependenciesToPackageJson","joinPathFragments","OverwriteStrategy","updateJson","execSync","enquirer","readFileSync","ensureAwsNxPluginConfig","updateAwsNxPluginConfig","formatFilesInSubtree","applyWorkspaceInit","installDependencies","getGeneratorInfo","withVersions","PRESET_GENERATOR_INFO","filename","isAmazonian","gitEmail","encoding","trim","emailParts","split","length","domain","toLowerCase","startsWith","error","setUpGitSecrets","tree","gitSecretsDir","dirname","huskyDir","write","json","scripts","prepare","presetGenerator","iac","gitSecrets","mcp","containers","module","preferInstallDependencies","process","env","VITEST","CI","NX_DRY_RUN","NX_INTERACTIVE","engagementId","prompt","name","message","type","initial","tags","packageJson","readmeOverwriteStrategy","Overwrite","overwriteScripts","delete","languages"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/preset/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 joinPathFragments,\n OverwriteStrategy,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { execSync } from 'child_process';\nimport enquirer from 'enquirer';\nimport { readFileSync } from 'fs';\nimport {\n ensureAwsNxPluginConfig,\n updateAwsNxPluginConfig,\n} from '../utils/config/utils';\nimport { addDependenciesToPackageJson } from '../utils/dependencies';\nimport { formatFilesInSubtree } from '../utils/format';\nimport { applyWorkspaceInit } from '../utils/init';\nimport { installDependencies } from '../utils/install';\nimport { getGeneratorInfo, type NxGeneratorInfo } from '../utils/nx';\nimport { withVersions } from '../utils/versions';\nimport type { PresetGeneratorSchema } from './schema';\n\nexport const PRESET_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\n/**\n * Determines if the current user is an Amazon employee based on their git configuration.\n *\n * This function checks the git user email configuration to identify Amazon employees\n * by looking for email addresses with Amazon domains (e.g., @amazon.com, @amazon.co.uk).\n *\n * @returns {boolean} True if the user's git email has an Amazon domain, false otherwise\n *\n * @example\n * // Returns true for Amazon employee emails\n * // git config user.email = \"john.doe@amazon.com\"\n * isAmazonian(); // true\n *\n * @example\n * // Returns false for non-Amazon emails\n * // git config user.email = \"user@example.com\"\n * isAmazonian(); // false\n *\n * @example\n * // Returns false when git config is not available or throws an error\n * isAmazonian(); // false\n */\nexport function isAmazonian(): boolean {\n try {\n // Execute git command to retrieve the user's configured email address\n const gitEmail = execSync('git config user.email', {\n encoding: 'utf8',\n }).trim();\n\n // Return false if no email is configured\n if (!gitEmail) {\n return false;\n }\n\n // Split email address to extract domain part\n const emailParts = gitEmail.split('@');\n if (emailParts.length < 2) {\n return false;\n }\n\n // Extract domain and normalize to lowercase for comparison\n const domain = emailParts[1].toLowerCase();\n\n // Check if domain starts with 'amazon.' (covers amazon.com, amazon.co.uk, etc.)\n return domain.startsWith('amazon.');\n } catch (error) {\n // Return false if git command fails or any other error occurs\n // This handles cases where git is not installed or configured\n return false;\n }\n}\n\nconst setUpGitSecrets = (tree: Tree) => {\n const gitSecretsDir = joinPathFragments(\n import.meta.dirname,\n 'git-secrets-files',\n 'git-secrets-dir',\n );\n const huskyDir = joinPathFragments(\n import.meta.dirname,\n 'git-secrets-files',\n 'husky-dir',\n );\n\n tree.write(\n '.git-secrets/git-secrets',\n readFileSync(joinPathFragments(gitSecretsDir, 'git-secrets'), 'utf-8'),\n );\n tree.write(\n '.husky/pre-commit',\n readFileSync(joinPathFragments(huskyDir, 'pre-commit'), 'utf-8'),\n );\n tree.write('.gitallowed', '\\\\.git-secrets/git-secrets:\\n');\n\n updateJson(tree, 'package.json', (json) => ({\n ...json,\n scripts: {\n ...json.scripts,\n prepare: 'husky',\n },\n }));\n\n addDependenciesToPackageJson(tree, {}, withVersions(['husky']));\n};\n\nexport const presetGenerator = async (\n tree: Tree,\n {\n iac,\n gitSecrets,\n mcp,\n containers,\n module,\n catalog,\n preferInstallDependencies,\n }: PresetGeneratorSchema,\n): Promise<GeneratorCallback> => {\n if (\n isAmazonian() &&\n !process.env.VITEST &&\n !process.env.CI &&\n process.env.NX_DRY_RUN !== 'true' &&\n process.env.NX_INTERACTIVE !== 'false'\n ) {\n const { engagementId } = await enquirer.prompt<{ engagementId?: string }>([\n {\n name: 'engagementId',\n message: 'Please enter your engagementId (if known)',\n type: 'input',\n initial: 'None',\n },\n ]);\n\n if (engagementId != 'None') {\n await ensureAwsNxPluginConfig(tree);\n await updateAwsNxPluginConfig(tree, { tags: [engagementId] });\n }\n }\n\n // The preset owns the greenfield workspace's module format: write the root\n // `type` explicitly from the chosen `--module` so later generators can\n // infer it. The `init` generator never touches an existing workspace's\n // `type` field.\n updateJson(tree, 'package.json', (packageJson) => ({\n ...packageJson,\n type: (module ?? 'esm') === 'esm' ? 'module' : 'commonjs',\n }));\n\n // Apply the deterministic workspace configuration shared with the `init`\n // generator. The preset owns the README of a greenfield workspace.\n await applyWorkspaceInit(tree, {\n iac,\n containers,\n mcp,\n catalogs: catalog ?? true,\n readmeOverwriteStrategy: OverwriteStrategy.Overwrite,\n overwriteScripts: true,\n });\n\n tree.delete('apps/.gitkeep');\n tree.delete('libs/.gitkeep');\n tree.write('packages/.gitkeep', '');\n\n if (gitSecrets !== false) {\n setUpGitSecrets(tree);\n }\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\nexport default presetGenerator;\n"],"names":["joinPathFragments","OverwriteStrategy","updateJson","execSync","enquirer","readFileSync","ensureAwsNxPluginConfig","updateAwsNxPluginConfig","addDependenciesToPackageJson","formatFilesInSubtree","applyWorkspaceInit","installDependencies","getGeneratorInfo","withVersions","PRESET_GENERATOR_INFO","filename","isAmazonian","gitEmail","encoding","trim","emailParts","split","length","domain","toLowerCase","startsWith","error","setUpGitSecrets","tree","gitSecretsDir","dirname","huskyDir","write","json","scripts","prepare","presetGenerator","iac","gitSecrets","mcp","containers","module","catalog","preferInstallDependencies","process","env","VITEST","CI","NX_DRY_RUN","NX_INTERACTIVE","engagementId","prompt","name","message","type","initial","tags","packageJson","catalogs","readmeOverwriteStrategy","Overwrite","overwriteScripts","delete","languages"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/preset/schema.d.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { Containers } from '../utils/containers';\nimport { Iac } from '../utils/iac';\nimport type { ModuleFormat } from '../utils/module-format';\n\nexport type PresetContainersOption = Containers | 'infer';\n\nexport interface PresetGeneratorSchema {\n readonly iac: Iac;\n readonly gitSecrets?: boolean;\n readonly mcp?: boolean;\n readonly containers?: PresetContainersOption;\n readonly module?: ModuleFormat;\n readonly preferInstallDependencies?: boolean;\n}\n"],"names":[],"mappings":"AAAA;;;CAGC,GAQD,WAOC"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/preset/schema.d.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { Containers } from '../utils/containers';\nimport { Iac } from '../utils/iac';\nimport type { ModuleFormat } from '../utils/module-format';\n\nexport type PresetContainersOption = Containers | 'infer';\n\nexport interface PresetGeneratorSchema {\n readonly iac: Iac;\n readonly gitSecrets?: boolean;\n readonly mcp?: boolean;\n readonly containers?: PresetContainersOption;\n readonly module?: ModuleFormat;\n readonly catalog?: boolean;\n readonly preferInstallDependencies?: boolean;\n}\n"],"names":[],"mappings":"AAAA;;;CAGC,GAQD,WAQC"}
@@ -15,5 +15,6 @@ export interface PresetGeneratorSchema {
15
15
  readonly mcp?: boolean;
16
16
  readonly containers?: PresetContainersOption;
17
17
  readonly module?: ModuleFormat;
18
+ readonly catalog?: boolean;
18
19
  readonly preferInstallDependencies?: boolean;
19
20
  }
@@ -37,6 +37,11 @@
37
37
  "enum": ["esm", "cjs"],
38
38
  "default": "esm"
39
39
  },
40
+ "catalog": {
41
+ "type": "boolean",
42
+ "description": "Whether generators record dependency versions in the package manager's catalog (pnpm/yarn/bun), keeping a single source of truth for versions. When false, dependencies are written directly to each project's package.json and keeping versions aligned is your responsibility.",
43
+ "default": true
44
+ },
40
45
  "preferInstallDependencies": {
41
46
  "type": "boolean",
42
47
  "description": "Whether to prefer installing dependencies after the generator runs. Set to false to defer installing when batching multiple generators (an install still runs if needed so subsequent generators can compute the Nx project graph); install once at the end.",
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
- */ import { addDependenciesToPackageJson, generateFiles, joinPathFragments, OverwriteStrategy, updateProjectConfiguration } from "@nx/devkit";
4
+ */ import { generateFiles, joinPathFragments, OverwriteStrategy, updateProjectConfiguration } from "@nx/devkit";
5
5
  import { ensureLicenseExceptions } from "../../license/config.js";
6
6
  import { AG_UI_LANGGRAPH_EXCEPTIONS } from "../../license/known-exceptions.js";
7
7
  import { addAgentChatScripts } from "../../utils/agent-chat/agent-chat.js";
@@ -9,6 +9,7 @@ import { addPythonFrameworkBase, ensurePythonAgentConnectionProject, getPythonAg
9
9
  import { addAgentInfra } from "../../utils/agent-core-constructs/agent-core-constructs.js";
10
10
  import { addPythonBundleTarget } from "../../utils/bundle/bundle.js";
11
11
  import { resolveContainers } from "../../utils/containers.js";
12
+ import { addDependenciesToPackageJson } from "../../utils/dependencies.js";
12
13
  import { addDockerScanTarget } from "../../utils/docker.js";
13
14
  import { formatFilesInSubtree } from "../../utils/format.js";
14
15
  import { FsCommands } from "../../utils/fs.js";