@aws/nx-plugin 1.0.0-rc.62 → 1.0.0-rc.64

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 (57) hide show
  1. package/migrations.json +12 -2
  2. package/package.json +1 -1
  3. package/src/agentcore-gateway/__snapshots__/generator.spec.ts.snap +22 -0
  4. package/src/infra/app/__snapshots__/generator.spec.ts.snap +28 -0
  5. package/src/infra/app/files/app/README.md.template +8 -4
  6. package/src/infra/app/files/app/src/main.ts.template +4 -0
  7. package/src/infra/app/generator.js +17 -1
  8. package/src/infra/app/generator.js.map +1 -1
  9. package/src/mcp-server/tools/general-guidance.js +1 -0
  10. package/src/mcp-server/tools/general-guidance.js.map +1 -1
  11. package/src/migrations/latest/add-deploy-sandbox-target/metadata.json +3 -0
  12. package/src/migrations/latest/add-deploy-sandbox-target/migration.d.ts +6 -0
  13. package/src/migrations/latest/add-deploy-sandbox-target/migration.js +83 -0
  14. package/src/migrations/latest/add-deploy-sandbox-target/migration.js.map +1 -0
  15. package/src/{smithy/project/files/service/build.Dockerfile.template → migrations/latest/smithy-build-without-docker/legacy-service.Dockerfile.fixture} +2 -2
  16. package/src/migrations/latest/smithy-build-without-docker/metadata.json +3 -0
  17. package/src/migrations/latest/smithy-build-without-docker/migration.d.ts +6 -0
  18. package/src/migrations/latest/smithy-build-without-docker/migration.js +154 -0
  19. package/src/migrations/latest/smithy-build-without-docker/migration.js.map +1 -0
  20. package/src/migrations/latest/smithy-ssdk-bundle-pins/rc57-service.Dockerfile.fixture +95 -0
  21. package/src/py/agent/a2a-connection/generator.d.ts +1 -1
  22. package/src/py/agent/gateway-connection/generator.d.ts +1 -1
  23. package/src/py/agent/generator.d.ts +8 -0
  24. package/src/py/agent/mcp-connection/generator.d.ts +1 -1
  25. package/src/py/fast-api/generator.d.ts +4 -0
  26. package/src/py/mcp-server/generator.d.ts +8 -0
  27. package/src/py/rdb/generator.d.ts +8 -0
  28. package/src/smithy/project/__snapshots__/generator.spec.ts.snap +163 -260
  29. package/src/smithy/project/files/service/smithy-build.json.template +5 -5
  30. package/src/smithy/project/files/shapes/smithy-build.json.template +1 -1
  31. package/src/smithy/project/files/ssdk-bundle/ssdk.rolldown.config.mjs.template +52 -0
  32. package/src/smithy/project/generator.d.ts +76 -18
  33. package/src/smithy/project/generator.js +160 -38
  34. package/src/smithy/project/generator.js.map +1 -1
  35. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +22 -3
  36. package/src/smithy/ts/api/generator.d.ts +4 -0
  37. package/src/ts/agent/generator.d.ts +8 -0
  38. package/src/ts/astro-docs/__snapshots__/generator.spec.ts.snap +14 -0
  39. package/src/ts/astro-docs/files/base/src/content/docs/en/index.mdx.template +2 -2
  40. package/src/ts/astro-docs/files/base/src/content.config.ts.template +4 -4
  41. package/src/ts/mcp-server/generator.d.ts +8 -0
  42. package/src/ts/rdb/generator.d.ts +8 -0
  43. package/src/utils/agent-core-constructs/files/terraform/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.tf.template +18 -2
  44. package/src/utils/docker.d.ts +2 -0
  45. package/src/utils/fs.d.ts +8 -0
  46. package/src/utils/fs.js +11 -0
  47. package/src/utils/fs.js.map +1 -1
  48. package/src/utils/smithy.d.ts +59 -0
  49. package/src/utils/smithy.js +73 -0
  50. package/src/utils/smithy.js.map +1 -0
  51. package/src/utils/version-upgrade-migration/sync-embedded-versions.d.ts +2 -2
  52. package/src/utils/version-upgrade-migration/sync-embedded-versions.js +53 -5
  53. package/src/utils/version-upgrade-migration/sync-embedded-versions.js.map +1 -1
  54. package/src/utils/versions.d.ts +33 -1
  55. package/src/utils/versions.js +26 -1
  56. package/src/utils/versions.js.map +1 -1
  57. package/src/smithy/project/files/shapes/build.Dockerfile.template +0 -33
@@ -11,11 +11,11 @@ terraform {
11
11
  source = "hashicorp/external"
12
12
  version = "<%- externalProviderVersion %>"
13
13
  }
14
+ <%_ } _%>
14
15
  time = {
15
16
  source = "hashicorp/time"
16
17
  version = "<%- timeProviderVersion %>"
17
18
  }
18
- <%_ } _%>
19
19
  random = {
20
20
  source = "hashicorp/random"
21
21
  version = "<%- randomProviderVersion %>"
@@ -168,6 +168,22 @@ resource "aws_iam_role_policy" "gateway_role_policy" {
168
168
  Statement = var.additional_iam_policy_statements
169
169
  })
170
170
  }
171
+
172
+ # IAM is eventually consistent, and the gateway assumes this role to reach its
173
+ # targets — an MCP target fetches tools at creation time. Without this wait the
174
+ # fetch intermittently runs before the policy above has propagated and the
175
+ # target lands in FAILED with an authorization error.
176
+ resource "time_sleep" "gateway_role_policy_propagation" {
177
+ count = length(var.additional_iam_policy_statements) > 0 ? 1 : 0
178
+
179
+ depends_on = [aws_iam_role_policy.gateway_role_policy]
180
+
181
+ create_duration = "30s"
182
+
183
+ triggers = {
184
+ policy = aws_iam_role_policy.gateway_role_policy[0].policy
185
+ }
186
+ }
171
187
  <%_ } _%>
172
188
  <%_ if (cedarPolicy) { _%>
173
189
 
@@ -215,9 +231,9 @@ resource "aws_bedrockagentcore_gateway" "this" {
215
231
  arn = aws_bedrockagentcore_policy_engine.this.policy_engine_arn
216
232
  mode = "ENFORCE"
217
233
  }
234
+ <%_ } _%>
218
235
 
219
236
  depends_on = [time_sleep.gateway_role_policy_propagation]
220
- <%_ } _%>
221
237
  }
222
238
 
223
239
  # WAFv2 protection for the gateway. AgentCore Gateway requires a REGIONAL web
@@ -11,6 +11,8 @@ export declare const DOCKER_DEPENDENCIES: readonly [{
11
11
  readonly name: "rimraf";
12
12
  }, {
13
13
  readonly name: "make-dir-cli";
14
+ }, {
15
+ readonly name: "cpy-cli";
14
16
  }];
15
17
  /**
16
18
  * Substitution variables for the vended Node `Dockerfile` templates: the npm
package/src/utils/fs.d.ts CHANGED
@@ -11,6 +11,8 @@ export declare const FS_DEPENDENCIES: readonly [{
11
11
  readonly name: "rimraf";
12
12
  }, {
13
13
  readonly name: "make-dir-cli";
14
+ }, {
15
+ readonly name: "cpy-cli";
14
16
  }];
15
17
  /**
16
18
  * Platform agnostic commands for filesystem operations, adding the CLIs they
@@ -23,5 +25,11 @@ export declare class FsCommands<D extends DependencyDeclaration> {
23
25
  cp(src: string, dst: string): string;
24
26
  rm(dir: string): string;
25
27
  mkdir(dir: string): string;
28
+ /**
29
+ * Copy the single file a glob matches to `dst`, for an artifact whose producer
30
+ * names it — the Smithy OpenAPI plugin writes `<ServiceShape>.openapi.json`.
31
+ * Fails rather than silently doing nothing when the glob matches nothing.
32
+ */
33
+ cpGlobToFile(srcGlob: string, dstDir: string, dstFileName: string): string;
26
34
  private add;
27
35
  }
package/src/utils/fs.js CHANGED
@@ -13,6 +13,9 @@ import { withVersions } from "./versions.js";
13
13
  },
14
14
  {
15
15
  name: 'make-dir-cli'
16
+ },
17
+ {
18
+ name: 'cpy-cli'
16
19
  }
17
20
  ];
18
21
  /**
@@ -37,6 +40,14 @@ import { withVersions } from "./versions.js";
37
40
  this.add('make-dir-cli');
38
41
  return `make-dir ${dir}`;
39
42
  }
43
+ /**
44
+ * Copy the single file a glob matches to `dst`, for an artifact whose producer
45
+ * names it — the Smithy OpenAPI plugin writes `<ServiceShape>.openapi.json`.
46
+ * Fails rather than silently doing nothing when the glob matches nothing.
47
+ */ cpGlobToFile(srcGlob, dstDir, dstFileName) {
48
+ this.add('cpy-cli');
49
+ return `cpy "${srcGlob}" ${dstDir} --flat --rename=${dstFileName}`;
50
+ }
40
51
  add(dep) {
41
52
  addDependenciesToPackageJson(this.tree, {}, withVersions(forDependencies(this.declaration), [
42
53
  dep
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/fs.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { Tree } from '@nx/devkit';\nimport {\n type DependencyDeclaration,\n forDependencies,\n type MustDeclare,\n} from './declared-dependencies';\nimport { addDependenciesToPackageJson } from './dependencies';\nimport { type ITsDepVersion, withVersions } from './versions';\n\n/** Dependencies a caller must declare to use `FsCommands`. */\nexport const FS_DEPENDENCIES = [\n { name: 'ncp' },\n { name: 'rimraf' },\n { name: 'make-dir-cli' },\n] as const satisfies readonly { name: ITsDepVersion }[];\n\n/**\n * Platform agnostic commands for filesystem operations, adding the CLIs they\n * need to the root package.json.\n */\nexport class FsCommands<D extends DependencyDeclaration> {\n private tree: Tree;\n private declaration: D;\n\n constructor(\n tree: Tree,\n declaration: D & MustDeclare<typeof FS_DEPENDENCIES, D>,\n ) {\n this.tree = tree;\n this.declaration = declaration;\n }\n\n public cp(src: string, dst: string) {\n this.add('ncp');\n return `ncp ${src} ${dst}`;\n }\n\n public rm(dir: string) {\n this.add('rimraf');\n return `rimraf ${dir}`;\n }\n\n public mkdir(dir: string) {\n this.add('make-dir-cli');\n return `make-dir ${dir}`;\n }\n\n private add(dep: (typeof FS_DEPENDENCIES)[number]['name']) {\n addDependenciesToPackageJson(\n this.tree,\n {},\n withVersions(forDependencies<typeof FS_DEPENDENCIES>(this.declaration), [\n dep,\n ]),\n );\n }\n}\n"],"names":["forDependencies","addDependenciesToPackageJson","withVersions","FS_DEPENDENCIES","name","FsCommands","tree","declaration","cp","src","dst","add","rm","dir","mkdir","dep"],"mappings":"AAAA;;;CAGC,GAED,SAEEA,eAAe,QAEV,6BAA0B;AACjC,SAASC,4BAA4B,QAAQ,oBAAiB;AAC9D,SAA6BC,YAAY,QAAQ,gBAAa;AAE9D,4DAA4D,GAC5D,OAAO,MAAMC,kBAAkB;IAC7B;QAAEC,MAAM;IAAM;IACd;QAAEA,MAAM;IAAS;IACjB;QAAEA,MAAM;IAAe;CACxB,CAAuD;AAExD;;;CAGC,GACD,OAAO,MAAMC;IACHC,KAAW;IACXC,YAAe;IAEvB,YACED,IAAU,EACVC,WAAuD,CACvD;QACA,IAAI,CAACD,IAAI,GAAGA;QACZ,IAAI,CAACC,WAAW,GAAGA;IACrB;IAEOC,GAAGC,GAAW,EAAEC,GAAW,EAAE;QAClC,IAAI,CAACC,GAAG,CAAC;QACT,OAAO,CAAC,IAAI,EAAEF,IAAI,CAAC,EAAEC,KAAK;IAC5B;IAEOE,GAAGC,GAAW,EAAE;QACrB,IAAI,CAACF,GAAG,CAAC;QACT,OAAO,CAAC,OAAO,EAAEE,KAAK;IACxB;IAEOC,MAAMD,GAAW,EAAE;QACxB,IAAI,CAACF,GAAG,CAAC;QACT,OAAO,CAAC,SAAS,EAAEE,KAAK;IAC1B;IAEQF,IAAII,GAA6C,EAAE;QACzDd,6BACE,IAAI,CAACK,IAAI,EACT,CAAC,GACDJ,aAAaF,gBAAwC,IAAI,CAACO,WAAW,GAAG;YACtEQ;SACD;IAEL;AACF"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/fs.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { Tree } from '@nx/devkit';\nimport {\n type DependencyDeclaration,\n forDependencies,\n type MustDeclare,\n} from './declared-dependencies';\nimport { addDependenciesToPackageJson } from './dependencies';\nimport { type ITsDepVersion, withVersions } from './versions';\n\n/** Dependencies a caller must declare to use `FsCommands`. */\nexport const FS_DEPENDENCIES = [\n { name: 'ncp' },\n { name: 'rimraf' },\n { name: 'make-dir-cli' },\n { name: 'cpy-cli' },\n] as const satisfies readonly { name: ITsDepVersion }[];\n\n/**\n * Platform agnostic commands for filesystem operations, adding the CLIs they\n * need to the root package.json.\n */\nexport class FsCommands<D extends DependencyDeclaration> {\n private tree: Tree;\n private declaration: D;\n\n constructor(\n tree: Tree,\n declaration: D & MustDeclare<typeof FS_DEPENDENCIES, D>,\n ) {\n this.tree = tree;\n this.declaration = declaration;\n }\n\n public cp(src: string, dst: string) {\n this.add('ncp');\n return `ncp ${src} ${dst}`;\n }\n\n public rm(dir: string) {\n this.add('rimraf');\n return `rimraf ${dir}`;\n }\n\n public mkdir(dir: string) {\n this.add('make-dir-cli');\n return `make-dir ${dir}`;\n }\n\n /**\n * Copy the single file a glob matches to `dst`, for an artifact whose producer\n * names it — the Smithy OpenAPI plugin writes `<ServiceShape>.openapi.json`.\n * Fails rather than silently doing nothing when the glob matches nothing.\n */\n public cpGlobToFile(srcGlob: string, dstDir: string, dstFileName: string) {\n this.add('cpy-cli');\n return `cpy \"${srcGlob}\" ${dstDir} --flat --rename=${dstFileName}`;\n }\n\n private add(dep: (typeof FS_DEPENDENCIES)[number]['name']) {\n addDependenciesToPackageJson(\n this.tree,\n {},\n withVersions(forDependencies<typeof FS_DEPENDENCIES>(this.declaration), [\n dep,\n ]),\n );\n }\n}\n"],"names":["forDependencies","addDependenciesToPackageJson","withVersions","FS_DEPENDENCIES","name","FsCommands","tree","declaration","cp","src","dst","add","rm","dir","mkdir","cpGlobToFile","srcGlob","dstDir","dstFileName","dep"],"mappings":"AAAA;;;CAGC,GAED,SAEEA,eAAe,QAEV,6BAA0B;AACjC,SAASC,4BAA4B,QAAQ,oBAAiB;AAC9D,SAA6BC,YAAY,QAAQ,gBAAa;AAE9D,4DAA4D,GAC5D,OAAO,MAAMC,kBAAkB;IAC7B;QAAEC,MAAM;IAAM;IACd;QAAEA,MAAM;IAAS;IACjB;QAAEA,MAAM;IAAe;IACvB;QAAEA,MAAM;IAAU;CACnB,CAAuD;AAExD;;;CAGC,GACD,OAAO,MAAMC;IACHC,KAAW;IACXC,YAAe;IAEvB,YACED,IAAU,EACVC,WAAuD,CACvD;QACA,IAAI,CAACD,IAAI,GAAGA;QACZ,IAAI,CAACC,WAAW,GAAGA;IACrB;IAEOC,GAAGC,GAAW,EAAEC,GAAW,EAAE;QAClC,IAAI,CAACC,GAAG,CAAC;QACT,OAAO,CAAC,IAAI,EAAEF,IAAI,CAAC,EAAEC,KAAK;IAC5B;IAEOE,GAAGC,GAAW,EAAE;QACrB,IAAI,CAACF,GAAG,CAAC;QACT,OAAO,CAAC,OAAO,EAAEE,KAAK;IACxB;IAEOC,MAAMD,GAAW,EAAE;QACxB,IAAI,CAACF,GAAG,CAAC;QACT,OAAO,CAAC,SAAS,EAAEE,KAAK;IAC1B;IAEA;;;;GAIC,GACD,AAAOE,aAAaC,OAAe,EAAEC,MAAc,EAAEC,WAAmB,EAAE;QACxE,IAAI,CAACP,GAAG,CAAC;QACT,OAAO,CAAC,KAAK,EAAEK,QAAQ,EAAE,EAAEC,OAAO,iBAAiB,EAAEC,aAAa;IACpE;IAEQP,IAAIQ,GAA6C,EAAE;QACzDlB,6BACE,IAAI,CAACK,IAAI,EACT,CAAC,GACDJ,aAAaF,gBAAwC,IAAI,CAACO,WAAW,GAAG;YACtEY;SACD;IAEL;AACF"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ /**
6
+ * How a generated Smithy project runs the Smithy CLI.
7
+ *
8
+ * Off Windows `mise` resolves the pinned CLI, downloading and caching it on first
9
+ * use, so a Smithy build needs no tool installed on the machine.
10
+ *
11
+ * mise itself is fetched by `npx` rather than added as a workspace dependency. The
12
+ * `mise` npm package is a stub that fetches its real binary in a `preinstall`, and
13
+ * every package manager gates install scripts differently: pnpm, bun and yarn
14
+ * Berry each need their own allowlist entry, bun and yarn fail silently when it is
15
+ * missing, and `nx migrate` installs with `--ignore-scripts` — so a migrated
16
+ * workspace ends up with the package present and no binary. `npx` sidesteps all of
17
+ * it: it runs the package's own bin, resolving from `node_modules` when it happens
18
+ * to be there and fetching it otherwise. A warm cache costs about a second.
19
+ *
20
+ * On Windows mise publishes no platform package to npm, so there the Smithy CLI is
21
+ * a documented prerequisite and the target invokes `smithy` directly.
22
+ */
23
+ /**
24
+ * The prefix a target command runs the Smithy CLI through.
25
+ *
26
+ * Off Windows both mise and the CLI are pinned in the command, so the version sync
27
+ * can move them forward. On Windows the CLI comes from the user's PATH, so there is
28
+ * no version to pin — {@link warnIfSmithyMissing} checks it is there.
29
+ */
30
+ export declare const smithyCliCommand: () => string;
31
+ /**
32
+ * Whether the workspace this generator runs in targets Windows, where the Smithy
33
+ * CLI is a user-installed prerequisite.
34
+ *
35
+ * Read at generate time rather than build time: the resolved command is baked
36
+ * into `project.json`, matching how `containers.engine` is resolved.
37
+ */
38
+ export declare const isWindows: () => boolean;
39
+ /**
40
+ * Warn when generating a Smithy project on Windows without the CLI installed.
41
+ *
42
+ * A warning rather than an error: the project is still generated correctly, and
43
+ * the CLI can be installed before the first build.
44
+ *
45
+ * @param onPath overrides the PATH probe, so a test can cover the Windows branch
46
+ * from any runner — ESM module namespaces cannot be spied on.
47
+ */
48
+ export declare const warnIfSmithyMissing: (onPath?: () => boolean) => void;
49
+ /**
50
+ * Substitution variables exposing the Smithy Maven pins to the generated
51
+ * `smithy-build.json` templates.
52
+ */
53
+ export declare const smithyMavenVersions: () => {
54
+ smithyModelDependency: string;
55
+ smithyAwsTraitsDependency: string;
56
+ smithyValidationModelDependency: string;
57
+ smithyOpenApiDependency: string;
58
+ smithyTypeScriptCodegenDependency: string;
59
+ };
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */ import * as childProcess from "node:child_process";
5
+ import { logger } from "@nx/devkit";
6
+ import { javaMavenDependency, MISE_VERSIONS, TS_VERSIONS } from "./versions.js";
7
+ /**
8
+ * How a generated Smithy project runs the Smithy CLI.
9
+ *
10
+ * Off Windows `mise` resolves the pinned CLI, downloading and caching it on first
11
+ * use, so a Smithy build needs no tool installed on the machine.
12
+ *
13
+ * mise itself is fetched by `npx` rather than added as a workspace dependency. The
14
+ * `mise` npm package is a stub that fetches its real binary in a `preinstall`, and
15
+ * every package manager gates install scripts differently: pnpm, bun and yarn
16
+ * Berry each need their own allowlist entry, bun and yarn fail silently when it is
17
+ * missing, and `nx migrate` installs with `--ignore-scripts` — so a migrated
18
+ * workspace ends up with the package present and no binary. `npx` sidesteps all of
19
+ * it: it runs the package's own bin, resolving from `node_modules` when it happens
20
+ * to be there and fetching it otherwise. A warm cache costs about a second.
21
+ *
22
+ * On Windows mise publishes no platform package to npm, so there the Smithy CLI is
23
+ * a documented prerequisite and the target invokes `smithy` directly.
24
+ */ /**
25
+ * The prefix a target command runs the Smithy CLI through.
26
+ *
27
+ * Off Windows both mise and the CLI are pinned in the command, so the version sync
28
+ * can move them forward. On Windows the CLI comes from the user's PATH, so there is
29
+ * no version to pin — {@link warnIfSmithyMissing} checks it is there.
30
+ */ export const smithyCliCommand = ()=>isWindows() ? 'smithy' : `npx -y mise@${TS_VERSIONS.mise} exec smithy@${MISE_VERSIONS.smithy} -- smithy`;
31
+ /**
32
+ * Whether the workspace this generator runs in targets Windows, where the Smithy
33
+ * CLI is a user-installed prerequisite.
34
+ *
35
+ * Read at generate time rather than build time: the resolved command is baked
36
+ * into `project.json`, matching how `containers.engine` is resolved.
37
+ */ export const isWindows = ()=>process.platform === 'win32';
38
+ /** Whether a Smithy CLI is resolvable on the PATH. */ const isSmithyOnPath = ()=>{
39
+ try {
40
+ childProcess.execSync('where smithy', {
41
+ stdio: 'ignore'
42
+ });
43
+ return true;
44
+ } catch {
45
+ return false;
46
+ }
47
+ };
48
+ /**
49
+ * Warn when generating a Smithy project on Windows without the CLI installed.
50
+ *
51
+ * A warning rather than an error: the project is still generated correctly, and
52
+ * the CLI can be installed before the first build.
53
+ *
54
+ * @param onPath overrides the PATH probe, so a test can cover the Windows branch
55
+ * from any runner — ESM module namespaces cannot be spied on.
56
+ */ export const warnIfSmithyMissing = (onPath = isSmithyOnPath)=>{
57
+ if (!isWindows() || onPath()) {
58
+ return;
59
+ }
60
+ logger.warn(`The Smithy CLI was not found on your PATH. Smithy projects build with it directly on Windows, so install it before building: https://smithy.io/2.0/guides/smithy-cli/cli_installation.html`);
61
+ };
62
+ /**
63
+ * Substitution variables exposing the Smithy Maven pins to the generated
64
+ * `smithy-build.json` templates.
65
+ */ export const smithyMavenVersions = ()=>({
66
+ smithyModelDependency: javaMavenDependency('software.amazon.smithy:smithy-model'),
67
+ smithyAwsTraitsDependency: javaMavenDependency('software.amazon.smithy:smithy-aws-traits'),
68
+ smithyValidationModelDependency: javaMavenDependency('software.amazon.smithy:smithy-validation-model'),
69
+ smithyOpenApiDependency: javaMavenDependency('software.amazon.smithy:smithy-openapi'),
70
+ smithyTypeScriptCodegenDependency: javaMavenDependency('software.amazon.smithy.typescript:smithy-aws-typescript-codegen')
71
+ });
72
+
73
+ //# sourceMappingURL=smithy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/smithy.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport * as childProcess from 'node:child_process';\nimport { logger } from '@nx/devkit';\nimport { javaMavenDependency, MISE_VERSIONS, TS_VERSIONS } from './versions';\n\n/**\n * How a generated Smithy project runs the Smithy CLI.\n *\n * Off Windows `mise` resolves the pinned CLI, downloading and caching it on first\n * use, so a Smithy build needs no tool installed on the machine.\n *\n * mise itself is fetched by `npx` rather than added as a workspace dependency. The\n * `mise` npm package is a stub that fetches its real binary in a `preinstall`, and\n * every package manager gates install scripts differently: pnpm, bun and yarn\n * Berry each need their own allowlist entry, bun and yarn fail silently when it is\n * missing, and `nx migrate` installs with `--ignore-scripts` — so a migrated\n * workspace ends up with the package present and no binary. `npx` sidesteps all of\n * it: it runs the package's own bin, resolving from `node_modules` when it happens\n * to be there and fetching it otherwise. A warm cache costs about a second.\n *\n * On Windows mise publishes no platform package to npm, so there the Smithy CLI is\n * a documented prerequisite and the target invokes `smithy` directly.\n */\n\n/**\n * The prefix a target command runs the Smithy CLI through.\n *\n * Off Windows both mise and the CLI are pinned in the command, so the version sync\n * can move them forward. On Windows the CLI comes from the user's PATH, so there is\n * no version to pin — {@link warnIfSmithyMissing} checks it is there.\n */\nexport const smithyCliCommand = (): string =>\n isWindows()\n ? 'smithy'\n : `npx -y mise@${TS_VERSIONS.mise} exec smithy@${MISE_VERSIONS.smithy} -- smithy`;\n\n/**\n * Whether the workspace this generator runs in targets Windows, where the Smithy\n * CLI is a user-installed prerequisite.\n *\n * Read at generate time rather than build time: the resolved command is baked\n * into `project.json`, matching how `containers.engine` is resolved.\n */\nexport const isWindows = (): boolean => process.platform === 'win32';\n\n/** Whether a Smithy CLI is resolvable on the PATH. */\nconst isSmithyOnPath = (): boolean => {\n try {\n childProcess.execSync('where smithy', { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n};\n\n/**\n * Warn when generating a Smithy project on Windows without the CLI installed.\n *\n * A warning rather than an error: the project is still generated correctly, and\n * the CLI can be installed before the first build.\n *\n * @param onPath overrides the PATH probe, so a test can cover the Windows branch\n * from any runner — ESM module namespaces cannot be spied on.\n */\nexport const warnIfSmithyMissing = (\n onPath: () => boolean = isSmithyOnPath,\n): void => {\n if (!isWindows() || onPath()) {\n return;\n }\n logger.warn(\n `The Smithy CLI was not found on your PATH. Smithy projects build with it directly on Windows, so install it before building: https://smithy.io/2.0/guides/smithy-cli/cli_installation.html`,\n );\n};\n\n/**\n * Substitution variables exposing the Smithy Maven pins to the generated\n * `smithy-build.json` templates.\n */\nexport const smithyMavenVersions = () => ({\n smithyModelDependency: javaMavenDependency(\n 'software.amazon.smithy:smithy-model',\n ),\n smithyAwsTraitsDependency: javaMavenDependency(\n 'software.amazon.smithy:smithy-aws-traits',\n ),\n smithyValidationModelDependency: javaMavenDependency(\n 'software.amazon.smithy:smithy-validation-model',\n ),\n smithyOpenApiDependency: javaMavenDependency(\n 'software.amazon.smithy:smithy-openapi',\n ),\n smithyTypeScriptCodegenDependency: javaMavenDependency(\n 'software.amazon.smithy.typescript:smithy-aws-typescript-codegen',\n ),\n});\n"],"names":["childProcess","logger","javaMavenDependency","MISE_VERSIONS","TS_VERSIONS","smithyCliCommand","isWindows","mise","smithy","process","platform","isSmithyOnPath","execSync","stdio","warnIfSmithyMissing","onPath","warn","smithyMavenVersions","smithyModelDependency","smithyAwsTraitsDependency","smithyValidationModelDependency","smithyOpenApiDependency","smithyTypeScriptCodegenDependency"],"mappings":"AAAA;;;CAGC,GAED,YAAYA,kBAAkB,qBAAqB;AACnD,SAASC,MAAM,QAAQ,aAAa;AACpC,SAASC,mBAAmB,EAAEC,aAAa,EAAEC,WAAW,QAAQ,gBAAa;AAE7E;;;;;;;;;;;;;;;;;CAiBC,GAED;;;;;;CAMC,GACD,OAAO,MAAMC,mBAAmB,IAC9BC,cACI,WACA,CAAC,YAAY,EAAEF,YAAYG,IAAI,CAAC,aAAa,EAAEJ,cAAcK,MAAM,CAAC,UAAU,CAAC,CAAC;AAEtF;;;;;;CAMC,GACD,OAAO,MAAMF,YAAY,IAAeG,QAAQC,QAAQ,KAAK,QAAQ;AAErE,oDAAoD,GACpD,MAAMC,iBAAiB;IACrB,IAAI;QACFX,aAAaY,QAAQ,CAAC,gBAAgB;YAAEC,OAAO;QAAS;QACxD,OAAO;IACT,EAAE,OAAM;QACN,OAAO;IACT;AACF;AAEA;;;;;;;;CAQC,GACD,OAAO,MAAMC,sBAAsB,CACjCC,SAAwBJ,cAAc;IAEtC,IAAI,CAACL,eAAeS,UAAU;QAC5B;IACF;IACAd,OAAOe,IAAI,CACT,CAAC,0LAA0L,CAAC;AAEhM,EAAE;AAEF;;;CAGC,GACD,OAAO,MAAMC,sBAAsB,IAAO,CAAA;QACxCC,uBAAuBhB,oBACrB;QAEFiB,2BAA2BjB,oBACzB;QAEFkB,iCAAiClB,oBAC/B;QAEFmB,yBAAyBnB,oBACvB;QAEFoB,mCAAmCpB,oBACjC;IAEJ,CAAA,EAAG"}
@@ -14,8 +14,8 @@ import { type OwnedDependencies } from './owned-dependencies';
14
14
  export declare const isDockerfile: (filePath: string) => boolean;
15
15
  /**
16
16
  * Sync the vended versions baked into generated file bodies: `Dockerfile` pins,
17
- * the Python pins in Terraform inline scripts, and the tooling images
18
- * `project.json` target commands run.
17
+ * the Python pins in Terraform inline scripts, the tooling `project.json` target
18
+ * commands run, and the Maven coordinates a `smithy-build.json` resolves.
19
19
  *
20
20
  * Reports only the files left for the user: a pin that takes effect the next time
21
21
  * the thing holding it runs needs no follow-up, but one this skipped for holding
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
- */ import { visitNotIgnoredFiles } from "@nx/devkit";
4
+ */ import { getProjects, joinPathFragments, visitNotIgnoredFiles } from "@nx/devkit";
5
+ import { SMITHY_PROJECT_GENERATOR_INFO } from "../../smithy/project/generator.js";
5
6
  import { applyGritQL } from "../ast.js";
6
- import { BASE_IMAGES, CONTAINER_REPOSITORIES, CONTAINER_VERSIONS, PY_VERSIONS, TS_VERSIONS } from "../versions.js";
7
+ import { BASE_IMAGES, CONTAINER_REPOSITORIES, CONTAINER_VERSIONS, JAVA_ARTIFACTS, JAVA_VERSIONS, MISE_VERSIONS, PY_VERSIONS, TS_VERSIONS } from "../versions.js";
7
8
  import { ownedForFile } from "./owned-dependencies.js";
8
9
  import { isVendedUpgrade } from "./vended-upgrade.js";
9
10
  /** Escape a package name or image reference for use inside a regex. */ const escapeRegExp = (value)=>value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
@@ -269,6 +270,17 @@ import { isVendedUpgrade } from "./vended-upgrade.js";
269
270
  pattern: `${escapeRegExp(repository)}:([^${VERSION_TERMINATORS}']+)`,
270
271
  vended: CONTAINER_VERSIONS[tool]
271
272
  })),
273
+ // The Smithy CLI a Smithy project's compile target runs, and the `mise` that
274
+ // resolves it. Neither is installed into the workspace — the target fetches
275
+ // mise with `npx` — so this command is the only place either version sits.
276
+ {
277
+ pattern: `exec smithy@([^${VERSION_TERMINATORS}']+)`,
278
+ vended: MISE_VERSIONS.smithy
279
+ },
280
+ {
281
+ pattern: `npx -y mise@([^${VERSION_TERMINATORS}']+)`,
282
+ vended: TS_VERSIONS.mise
283
+ },
272
284
  ...Object.keys(PY_VERSIONS).flatMap((name)=>{
273
285
  const vended = vendedPyVersion(name);
274
286
  return vended ? UVX_PIN_SHAPES.map((shape)=>({
@@ -285,10 +297,45 @@ import { isVendedUpgrade } from "./vended-upgrade.js";
285
297
  }
286
298
  return skipped;
287
299
  };
300
+ /**
301
+ * Sync the Maven coordinates a generated `smithy-build.json` resolves.
302
+ *
303
+ * These are Java artifacts the Smithy CLI downloads, so they appear in no
304
+ * manifest the dependency sync reads — this file is the only place they sit. Each
305
+ * is matched by its `group:artifact` prefix so only the version is rewritten,
306
+ * leaving any coordinate the user added alone.
307
+ *
308
+ * Scoped to the projects `smithy#project` generated: a `smithy-build.json` a user
309
+ * wrote themselves keeps the versions they chose.
310
+ */ const syncSmithyMavenPins = async (tree)=>{
311
+ const isGeneratedSmithyProject = (project)=>project.metadata?.generator === SMITHY_PROJECT_GENERATOR_INFO.id;
312
+ const smithyBuilds = [];
313
+ for (const [, project] of getProjects(tree)){
314
+ if (!isGeneratedSmithyProject(project)) {
315
+ continue;
316
+ }
317
+ const path = joinPathFragments(project.root, 'smithy-build.json');
318
+ if (tree.exists(path)) {
319
+ smithyBuilds.push(path);
320
+ }
321
+ }
322
+ const pins = JAVA_ARTIFACTS.map((artifact)=>({
323
+ // A coordinate is a JSON string here, so a quote ends the version.
324
+ pattern: `${escapeRegExp(artifact)}:([^${VERSION_TERMINATORS}']+)`,
325
+ vended: JAVA_VERSIONS[artifact]
326
+ }));
327
+ const skipped = [];
328
+ for (const path of smithyBuilds){
329
+ if ((await applyPins(tree, path, pins)).skipped) {
330
+ skipped.push(path);
331
+ }
332
+ }
333
+ return skipped;
334
+ };
288
335
  /**
289
336
  * Sync the vended versions baked into generated file bodies: `Dockerfile` pins,
290
- * the Python pins in Terraform inline scripts, and the tooling images
291
- * `project.json` target commands run.
337
+ * the Python pins in Terraform inline scripts, the tooling `project.json` target
338
+ * commands run, and the Maven coordinates a `smithy-build.json` resolves.
292
339
  *
293
340
  * Reports only the files left for the user: a pin that takes effect the next time
294
341
  * the thing holding it runs needs no follow-up, but one this skipped for holding
@@ -298,7 +345,8 @@ import { isVendedUpgrade } from "./vended-upgrade.js";
298
345
  */ export const syncEmbeddedVersions = async (tree, owned)=>[
299
346
  ...await syncDockerfiles(tree, owned),
300
347
  ...await syncTerraformScriptPins(tree, owned),
301
- ...await syncTargetToolPins(tree)
348
+ ...await syncTargetToolPins(tree),
349
+ ...await syncSmithyMavenPins(tree)
302
350
  ];
303
351
 
304
352
  //# sourceMappingURL=sync-embedded-versions.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../packages/nx-plugin/src/utils/version-upgrade-migration/sync-embedded-versions.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { Tree } from '@nx/devkit';\nimport { visitNotIgnoredFiles } from '@nx/devkit';\nimport { applyGritQL } from '../ast';\nimport {\n BASE_IMAGES,\n CONTAINER_REPOSITORIES,\n CONTAINER_VERSIONS,\n PY_VERSIONS,\n TS_VERSIONS,\n} from '../versions';\nimport { type OwnedDependencies, ownedForFile } from './owned-dependencies';\nimport { isVendedUpgrade } from './vended-upgrade';\n\n/**\n * Sync the vended versions generators bake into the body of a file rather than\n * into a manifest: the container image pins in a `Dockerfile`, the Python pins\n * in a Terraform inline script, and the tooling images a `project.json` target\n * command runs.\n *\n * Every version here is pinned to clear a known HIGH/CRITICAL vulnerability, or\n * to keep a generated image reproducible, so leaving them behind strands a\n * workspace on exactly the versions most in need of an upgrade.\n *\n * These sit inside shell commands, which GritQL has no grammar for — so instead\n * of pattern-matching the surrounding syntax, each pin is located by an anchored\n * regex whose single capture group is the version, and only that capture is\n * rewritten. The file's own text around it is never reconstructed, so a\n * reformatted or hand-edited file syncs the same way a freshly generated one\n * does.\n */\n\n/** A pin found in a file body, and the version this release vends for it. */\ninterface EmbeddedPin {\n /** Regex matching the pin, with the version as its only capture group. */\n readonly pattern: string;\n readonly vended: string;\n /**\n * Whether the declared value is a version to move forward, or a tag to replace\n * whenever it differs. A tag — `lts-slim`, say — has no ordering to compare, so\n * one that isn't what this release vends is simply out of date.\n */\n readonly kind?: 'version' | 'tag';\n}\n\n/** Escape a package name or image reference for use inside a regex. */\nconst escapeRegExp = (value: string): string =>\n value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/**\n * Characters that end a pinned version: whitespace, the backslash continuing a\n * shell line, and the quote closing the string the pin sits in.\n *\n * The quote is escaped because the pattern is itself a double-quoted GritQL\n * regex literal, which a bare quote would terminate.\n */\nconst VERSION_TERMINATORS = '\\\\s\\\\\\\\\\\\\"';\n\n/**\n * Rewrite the capture group of an anchored regex to the vended version.\n *\n * The leading and trailing `[\\s\\S]*` anchor the match to the whole file, which\n * is what lets a capture group be rewritten on its own: GritQL binds the group\n * to a node it can replace, leaving every other byte untouched. Without the\n * anchors nothing matches.\n */\nconst rewriteCapture = (pattern: string, vended: string): string =>\n `r\"[\\\\s\\\\S]*${pattern}[\\\\s\\\\S]*\"($version) where { $version => \\`${vended}\\` }`;\n\n/**\n * Versions a pin's regex currently matches in the file.\n *\n * Read before rewriting so a version the user raised past what this release\n * vends is left alone, matching how every other surface behaves.\n */\nconst declaredVersions = (contents: string, pattern: string): string[] => {\n const matches = contents.matchAll(new RegExp(pattern, 'g'));\n return [...matches].flatMap((match) => (match[1] ? [match[1]] : []));\n};\n\n/**\n * Occurrences of one pin a single rewrite will handle.\n *\n * GritQL rewrites each match separately, so its cost grows with how many a\n * pattern matches — ~10ms an occurrence, which a hand-authored file with hundreds\n * of `RUN npm install` lines turns into minutes of an unattended `nx migrate`.\n * Past this the file is left alone and reported, since a wrong version the user\n * can see and fix beats an upgrade that appears to hang.\n */\nconst MAX_OCCURRENCES_PER_PIN = 100;\n\n/**\n * Apply the pins whose declared version this release moves forward.\n *\n * A single rewrite covers every occurrence of a pin in the file, so each pin is\n * applied once. Reports whether anything changed, and whether a pin was left\n * alone for exceeding {@link MAX_OCCURRENCES_PER_PIN}.\n */\nconst applyPins = async (\n tree: Tree,\n path: string,\n pins: readonly EmbeddedPin[],\n): Promise<{ changed: boolean; skipped: boolean }> => {\n // Read once and re-read only after a rewrite: a rewrite parses the whole file,\n // and there is a pin per owned package, so re-reading per pin would scale the\n // cost of a large file with the size of the owned set.\n let contents = tree.read(path, 'utf-8') ?? '';\n let changed = false;\n let skipped = false;\n\n for (const { pattern, vended, kind = 'version' } of pins) {\n const declared = declaredVersions(contents, pattern);\n if (declared.length === 0) {\n continue;\n }\n if (declared.length > MAX_OCCURRENCES_PER_PIN) {\n skipped = true;\n continue;\n }\n const outOfDate =\n kind === 'tag'\n ? (tag: string) => tag !== vended\n : (version: string) => isVendedUpgrade(vended, version);\n // A rewrite replaces every occurrence at once, so this must hold for all of\n // them — a pin already at or beyond the vended version is left as it is.\n if (!declared.every(outOfDate)) {\n continue;\n }\n if (await applyGritQL(tree, path, rewriteCapture(pattern, vended))) {\n contents = tree.read(path, 'utf-8') ?? '';\n changed = true;\n }\n }\n\n return { changed, skipped };\n};\n\n/**\n * The version this release vends for a package, or undefined for one it doesn't\n * vend at all.\n *\n * Ownership is applied by the caller, which only ever passes a name drawn from\n * the owned set — so a package the user pinned themselves never reaches here and\n * keeps the version they chose.\n */\nconst vendedTsVersion = (name: string): string | undefined =>\n TS_VERSIONS[name as keyof typeof TS_VERSIONS];\n\n/** `PY_VERSIONS` records the `==` operator; a pin holds the bare version. */\nconst vendedPyVersion = (name: string): string | undefined =>\n PY_VERSIONS[name as keyof typeof PY_VERSIONS]?.replace(/^==/, '');\n\n/**\n * The ways a generated `Dockerfile` pins a TypeScript package's version, as\n * regex fragments taking the escaped package name.\n *\n * The name is required to run to its delimiter, so a package whose name merely\n * ends with another's — `some-npm` against `npm` — cannot match, and an\n * installed version must start with a digit so a `@latest` style tag is left\n * alone.\n */\nconst DOCKERFILE_PIN_SHAPES: readonly ((name: string) => string)[] = [\n // Installed by the image build. `install` and its `i` alias are both used, as\n // are `-g` and several packages in one command, so the name only has to follow\n // an `npm` subcommand rather than sit right after it. The whitespace before it\n // is matched rather than asserted, since GritQL's regex engine has no\n // lookbehind — which also keeps `some-npm` from matching `npm`, and unlike a\n // `\\b` boundary still reaches a `@scope/name`.\n (name) =>\n `npm (?:install|i|add)[^\\\\n]*?\\\\s${name}@([0-9][^${VERSION_TERMINATORS}]*)`,\n // Held at a fixed version through an `npm pkg set` override, to clear a known\n // vulnerability in a transitive dependency.\n (name) => `overrides\\\\.${name}=([^${VERSION_TERMINATORS}]+)`,\n];\n\n/**\n * Every pin a generated `Dockerfile` may carry, for the packages owned where it\n * sits.\n *\n * Driven off the owned packages rather than a list of the ones that happen to be\n * pinned today: a pin added to a template in a later release is then covered\n * without this module changing, which is the whole point — the versions baked\n * into image builds are pinned precisely because they clear a known\n * vulnerability.\n *\n * A package the user pinned themselves is not owned, so it is never matched.\n */\nconst dockerfilePins = (owned: {\n readonly ts: ReadonlySet<string>;\n}): EmbeddedPin[] => {\n const pins: EmbeddedPin[] = [];\n\n for (const name of owned.ts) {\n const vended = vendedTsVersion(name);\n if (!vended) {\n continue;\n }\n for (const shape of DOCKERFILE_PIN_SHAPES) {\n pins.push({ pattern: shape(escapeRegExp(name)), vended });\n }\n }\n\n for (const image of Object.values(BASE_IMAGES)) {\n const [repository, tag] = splitImageReference(image);\n pins.push({\n // Only a `FROM` that is the whole instruction. A build stage names itself\n // — `FROM <repo>:24 AS builder` — and picks its tag for what that stage has\n // to run: the smithy builder needs curl and unzip, which the slim tag this\n // release vends for a runtime image does not carry. Rewriting it would\n // break the build, and the two share a repository, so the instruction\n // ending is what separates them.\n pattern: `FROM ${escapeRegExp(repository)}:([^\\\\s]+)\\\\n`,\n vended: tag,\n kind: 'tag',\n });\n }\n\n return pins;\n};\n\n/**\n * The repository and tag of a pinned image reference. The tag is the part after\n * the last `:`, which a registry port would otherwise be mistaken for — every\n * reference here carries one.\n */\nconst splitImageReference = (image: string): [string, string] => {\n const at = image.lastIndexOf(':');\n return [image.slice(0, at), image.slice(at + 1)];\n};\n\n/**\n * Whether a file is a Dockerfile: exactly `Dockerfile`, or the `<name>.Dockerfile`\n * form the smithy templates vend as `build.Dockerfile`.\n *\n * Deliberately exact rather than a prefix match, which would also claim a\n * `Dockerfile.bak` or a `Dockerfile.md` the user keeps beside a real one.\n */\nexport const isDockerfile = (filePath: string): boolean => {\n const name = filePath.split('/').pop() ?? '';\n return name === 'Dockerfile' || name.endsWith('.Dockerfile');\n};\n\n/**\n * Sync the pins in every generated Dockerfile.\n *\n * Ownership is resolved per file, so a Dockerfile is only rewritten for the\n * packages the project it belongs to owns — a sibling project owning `prisma`\n * does not license rewriting a `prisma` pin here.\n */\nconst syncDockerfiles = async (\n tree: Tree,\n owned: OwnedDependencies,\n): Promise<string[]> => {\n const dockerfiles: string[] = [];\n\n visitNotIgnoredFiles(tree, '.', (path) => {\n if (isDockerfile(path)) {\n dockerfiles.push(path);\n }\n });\n\n const skipped: string[] = [];\n for (const path of dockerfiles) {\n const result = await applyPins(\n tree,\n path,\n dockerfilePins(ownedForFile(owned, path)),\n );\n if (result.skipped) {\n skipped.push(path);\n }\n }\n return skipped;\n};\n\n/** The `uv run --with` pins to apply, for the Python packages owned where a file sits. */\nconst terraformScriptPins = (owned: {\n readonly py: ReadonlySet<string>;\n}): EmbeddedPin[] =>\n [...owned.py].flatMap((name) => {\n const vended = vendedPyVersion(name);\n return vended\n ? [\n {\n pattern: `--with ${escapeRegExp(name)}==([^${VERSION_TERMINATORS}]+)`,\n vended,\n },\n ]\n : [];\n });\n\n/**\n * Sync the Python pins a generated Terraform inline script runs through\n * `uv run --with <package>==<version>`.\n *\n * These are the plugin's own pins, in a file the Terraform provider sync already\n * visits but only reads `required_providers` from. Driven off the owned Python\n * packages, so a pin added to a template later is covered without a change here.\n *\n * Scoped per file like the Dockerfiles. The modules carrying these live in the\n * shared Terraform project, which no single generator owns — a file there belongs\n * to no project, so it takes the workspace-wide union, which is the set of\n * generators that legitimately write into it.\n */\nconst syncTerraformScriptPins = async (\n tree: Tree,\n owned: OwnedDependencies,\n): Promise<string[]> => {\n const terraformFiles: string[] = [];\n\n visitNotIgnoredFiles(tree, '.', (path) => {\n if (path.endsWith('.tf')) {\n terraformFiles.push(path);\n }\n });\n\n const skipped: string[] = [];\n for (const path of terraformFiles) {\n const result = await applyPins(\n tree,\n path,\n terraformScriptPins(ownedForFile(owned, path)),\n );\n if (result.skipped) {\n skipped.push(path);\n }\n }\n return skipped;\n};\n\n/**\n * The ways a `uvx` invocation pins a Python version: the tool it runs, and any\n * package it adds to that tool's environment.\n *\n * A command string is JSON here, so a quote ends a version too.\n */\nconst UVX_PIN_SHAPES: readonly ((name: string) => string)[] = [\n (name) => `uvx --from ${name}==`,\n (name) => `--with ${name}==`,\n];\n\n/**\n * Sync the pinned tools a `project.json` target command runs: a container image,\n * and the Python versions a `uvx` invocation pins.\n *\n * Both are built into the command string rather than declared as a dependency, so\n * nothing else reaches them. The images are driven off `CONTAINER_REPOSITORIES`\n * and the Python versions off `PY_VERSIONS`, so a tool pinned in a target command\n * later is covered without a change here — the same property the Dockerfile and\n * Terraform paths get from the owned set.\n *\n * Unscoped, unlike the file-body pins: a `uvx` invocation installs nothing into\n * the project, so there is no dependency for a generator to own. A version is only\n * rewritten where this release vends that exact package at a higher one.\n */\nconst syncTargetToolPins = async (tree: Tree): Promise<string[]> => {\n const projectJsons: string[] = [];\n\n visitNotIgnoredFiles(tree, '.', (path) => {\n if (path.endsWith('project.json')) {\n projectJsons.push(path);\n }\n });\n\n const pins: EmbeddedPin[] = [\n ...Object.entries(CONTAINER_REPOSITORIES).map(([tool, repository]) => ({\n // A command string is JSON here, so a quote ends the reference too.\n pattern: `${escapeRegExp(repository)}:([^${VERSION_TERMINATORS}']+)`,\n vended: CONTAINER_VERSIONS[tool as keyof typeof CONTAINER_VERSIONS],\n })),\n ...Object.keys(PY_VERSIONS).flatMap((name) => {\n const vended = vendedPyVersion(name);\n return vended\n ? UVX_PIN_SHAPES.map((shape) => ({\n pattern: `${shape(escapeRegExp(name))}([^${VERSION_TERMINATORS}']+)`,\n vended,\n }))\n : [];\n }),\n ];\n\n const skipped: string[] = [];\n for (const path of projectJsons) {\n if ((await applyPins(tree, path, pins)).skipped) {\n skipped.push(path);\n }\n }\n return skipped;\n};\n\n/**\n * Sync the vended versions baked into generated file bodies: `Dockerfile` pins,\n * the Python pins in Terraform inline scripts, and the tooling images\n * `project.json` target commands run.\n *\n * Reports only the files left for the user: a pin that takes effect the next time\n * the thing holding it runs needs no follow-up, but one this skipped for holding\n * more occurrences than it will rewrite at once does.\n *\n * @returns paths whose pins were left as they were\n */\nexport const syncEmbeddedVersions = async (\n tree: Tree,\n owned: OwnedDependencies,\n): Promise<string[]> => [\n ...(await syncDockerfiles(tree, owned)),\n ...(await syncTerraformScriptPins(tree, owned)),\n ...(await syncTargetToolPins(tree)),\n];\n"],"names":["visitNotIgnoredFiles","applyGritQL","BASE_IMAGES","CONTAINER_REPOSITORIES","CONTAINER_VERSIONS","PY_VERSIONS","TS_VERSIONS","ownedForFile","isVendedUpgrade","escapeRegExp","value","replace","VERSION_TERMINATORS","rewriteCapture","pattern","vended","declaredVersions","contents","matches","matchAll","RegExp","flatMap","match","MAX_OCCURRENCES_PER_PIN","applyPins","tree","path","pins","read","changed","skipped","kind","declared","length","outOfDate","tag","version","every","vendedTsVersion","name","vendedPyVersion","DOCKERFILE_PIN_SHAPES","dockerfilePins","owned","ts","shape","push","image","Object","values","repository","splitImageReference","at","lastIndexOf","slice","isDockerfile","filePath","split","pop","endsWith","syncDockerfiles","dockerfiles","result","terraformScriptPins","py","syncTerraformScriptPins","terraformFiles","UVX_PIN_SHAPES","syncTargetToolPins","projectJsons","entries","map","tool","keys","syncEmbeddedVersions"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/utils/version-upgrade-migration/sync-embedded-versions.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { ProjectConfiguration, Tree } from '@nx/devkit';\nimport {\n getProjects,\n joinPathFragments,\n visitNotIgnoredFiles,\n} from '@nx/devkit';\nimport { SMITHY_PROJECT_GENERATOR_INFO } from '../../smithy/project/generator';\nimport { applyGritQL } from '../ast';\nimport {\n BASE_IMAGES,\n CONTAINER_REPOSITORIES,\n CONTAINER_VERSIONS,\n JAVA_ARTIFACTS,\n JAVA_VERSIONS,\n MISE_VERSIONS,\n PY_VERSIONS,\n TS_VERSIONS,\n} from '../versions';\nimport { type OwnedDependencies, ownedForFile } from './owned-dependencies';\nimport { isVendedUpgrade } from './vended-upgrade';\n\n/**\n * Sync the vended versions generators bake into the body of a file rather than\n * into a manifest: the container image pins in a `Dockerfile`, the Python pins\n * in a Terraform inline script, and the tooling images a `project.json` target\n * command runs.\n *\n * Every version here is pinned to clear a known HIGH/CRITICAL vulnerability, or\n * to keep a generated image reproducible, so leaving them behind strands a\n * workspace on exactly the versions most in need of an upgrade.\n *\n * These sit inside shell commands, which GritQL has no grammar for — so instead\n * of pattern-matching the surrounding syntax, each pin is located by an anchored\n * regex whose single capture group is the version, and only that capture is\n * rewritten. The file's own text around it is never reconstructed, so a\n * reformatted or hand-edited file syncs the same way a freshly generated one\n * does.\n */\n\n/** A pin found in a file body, and the version this release vends for it. */\ninterface EmbeddedPin {\n /** Regex matching the pin, with the version as its only capture group. */\n readonly pattern: string;\n readonly vended: string;\n /**\n * Whether the declared value is a version to move forward, or a tag to replace\n * whenever it differs. A tag — `lts-slim`, say — has no ordering to compare, so\n * one that isn't what this release vends is simply out of date.\n */\n readonly kind?: 'version' | 'tag';\n}\n\n/** Escape a package name or image reference for use inside a regex. */\nconst escapeRegExp = (value: string): string =>\n value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/**\n * Characters that end a pinned version: whitespace, the backslash continuing a\n * shell line, and the quote closing the string the pin sits in.\n *\n * The quote is escaped because the pattern is itself a double-quoted GritQL\n * regex literal, which a bare quote would terminate.\n */\nconst VERSION_TERMINATORS = '\\\\s\\\\\\\\\\\\\"';\n\n/**\n * Rewrite the capture group of an anchored regex to the vended version.\n *\n * The leading and trailing `[\\s\\S]*` anchor the match to the whole file, which\n * is what lets a capture group be rewritten on its own: GritQL binds the group\n * to a node it can replace, leaving every other byte untouched. Without the\n * anchors nothing matches.\n */\nconst rewriteCapture = (pattern: string, vended: string): string =>\n `r\"[\\\\s\\\\S]*${pattern}[\\\\s\\\\S]*\"($version) where { $version => \\`${vended}\\` }`;\n\n/**\n * Versions a pin's regex currently matches in the file.\n *\n * Read before rewriting so a version the user raised past what this release\n * vends is left alone, matching how every other surface behaves.\n */\nconst declaredVersions = (contents: string, pattern: string): string[] => {\n const matches = contents.matchAll(new RegExp(pattern, 'g'));\n return [...matches].flatMap((match) => (match[1] ? [match[1]] : []));\n};\n\n/**\n * Occurrences of one pin a single rewrite will handle.\n *\n * GritQL rewrites each match separately, so its cost grows with how many a\n * pattern matches — ~10ms an occurrence, which a hand-authored file with hundreds\n * of `RUN npm install` lines turns into minutes of an unattended `nx migrate`.\n * Past this the file is left alone and reported, since a wrong version the user\n * can see and fix beats an upgrade that appears to hang.\n */\nconst MAX_OCCURRENCES_PER_PIN = 100;\n\n/**\n * Apply the pins whose declared version this release moves forward.\n *\n * A single rewrite covers every occurrence of a pin in the file, so each pin is\n * applied once. Reports whether anything changed, and whether a pin was left\n * alone for exceeding {@link MAX_OCCURRENCES_PER_PIN}.\n */\nconst applyPins = async (\n tree: Tree,\n path: string,\n pins: readonly EmbeddedPin[],\n): Promise<{ changed: boolean; skipped: boolean }> => {\n // Read once and re-read only after a rewrite: a rewrite parses the whole file,\n // and there is a pin per owned package, so re-reading per pin would scale the\n // cost of a large file with the size of the owned set.\n let contents = tree.read(path, 'utf-8') ?? '';\n let changed = false;\n let skipped = false;\n\n for (const { pattern, vended, kind = 'version' } of pins) {\n const declared = declaredVersions(contents, pattern);\n if (declared.length === 0) {\n continue;\n }\n if (declared.length > MAX_OCCURRENCES_PER_PIN) {\n skipped = true;\n continue;\n }\n const outOfDate =\n kind === 'tag'\n ? (tag: string) => tag !== vended\n : (version: string) => isVendedUpgrade(vended, version);\n // A rewrite replaces every occurrence at once, so this must hold for all of\n // them — a pin already at or beyond the vended version is left as it is.\n if (!declared.every(outOfDate)) {\n continue;\n }\n if (await applyGritQL(tree, path, rewriteCapture(pattern, vended))) {\n contents = tree.read(path, 'utf-8') ?? '';\n changed = true;\n }\n }\n\n return { changed, skipped };\n};\n\n/**\n * The version this release vends for a package, or undefined for one it doesn't\n * vend at all.\n *\n * Ownership is applied by the caller, which only ever passes a name drawn from\n * the owned set — so a package the user pinned themselves never reaches here and\n * keeps the version they chose.\n */\nconst vendedTsVersion = (name: string): string | undefined =>\n TS_VERSIONS[name as keyof typeof TS_VERSIONS];\n\n/** `PY_VERSIONS` records the `==` operator; a pin holds the bare version. */\nconst vendedPyVersion = (name: string): string | undefined =>\n PY_VERSIONS[name as keyof typeof PY_VERSIONS]?.replace(/^==/, '');\n\n/**\n * The ways a generated `Dockerfile` pins a TypeScript package's version, as\n * regex fragments taking the escaped package name.\n *\n * The name is required to run to its delimiter, so a package whose name merely\n * ends with another's — `some-npm` against `npm` — cannot match, and an\n * installed version must start with a digit so a `@latest` style tag is left\n * alone.\n */\nconst DOCKERFILE_PIN_SHAPES: readonly ((name: string) => string)[] = [\n // Installed by the image build. `install` and its `i` alias are both used, as\n // are `-g` and several packages in one command, so the name only has to follow\n // an `npm` subcommand rather than sit right after it. The whitespace before it\n // is matched rather than asserted, since GritQL's regex engine has no\n // lookbehind — which also keeps `some-npm` from matching `npm`, and unlike a\n // `\\b` boundary still reaches a `@scope/name`.\n (name) =>\n `npm (?:install|i|add)[^\\\\n]*?\\\\s${name}@([0-9][^${VERSION_TERMINATORS}]*)`,\n // Held at a fixed version through an `npm pkg set` override, to clear a known\n // vulnerability in a transitive dependency.\n (name) => `overrides\\\\.${name}=([^${VERSION_TERMINATORS}]+)`,\n];\n\n/**\n * Every pin a generated `Dockerfile` may carry, for the packages owned where it\n * sits.\n *\n * Driven off the owned packages rather than a list of the ones that happen to be\n * pinned today: a pin added to a template in a later release is then covered\n * without this module changing, which is the whole point — the versions baked\n * into image builds are pinned precisely because they clear a known\n * vulnerability.\n *\n * A package the user pinned themselves is not owned, so it is never matched.\n */\nconst dockerfilePins = (owned: {\n readonly ts: ReadonlySet<string>;\n}): EmbeddedPin[] => {\n const pins: EmbeddedPin[] = [];\n\n for (const name of owned.ts) {\n const vended = vendedTsVersion(name);\n if (!vended) {\n continue;\n }\n for (const shape of DOCKERFILE_PIN_SHAPES) {\n pins.push({ pattern: shape(escapeRegExp(name)), vended });\n }\n }\n\n for (const image of Object.values(BASE_IMAGES)) {\n const [repository, tag] = splitImageReference(image);\n pins.push({\n // Only a `FROM` that is the whole instruction. A build stage names itself\n // — `FROM <repo>:24 AS builder` — and picks its tag for what that stage has\n // to run: the smithy builder needs curl and unzip, which the slim tag this\n // release vends for a runtime image does not carry. Rewriting it would\n // break the build, and the two share a repository, so the instruction\n // ending is what separates them.\n pattern: `FROM ${escapeRegExp(repository)}:([^\\\\s]+)\\\\n`,\n vended: tag,\n kind: 'tag',\n });\n }\n\n return pins;\n};\n\n/**\n * The repository and tag of a pinned image reference. The tag is the part after\n * the last `:`, which a registry port would otherwise be mistaken for — every\n * reference here carries one.\n */\nconst splitImageReference = (image: string): [string, string] => {\n const at = image.lastIndexOf(':');\n return [image.slice(0, at), image.slice(at + 1)];\n};\n\n/**\n * Whether a file is a Dockerfile: exactly `Dockerfile`, or the `<name>.Dockerfile`\n * form the smithy templates vend as `build.Dockerfile`.\n *\n * Deliberately exact rather than a prefix match, which would also claim a\n * `Dockerfile.bak` or a `Dockerfile.md` the user keeps beside a real one.\n */\nexport const isDockerfile = (filePath: string): boolean => {\n const name = filePath.split('/').pop() ?? '';\n return name === 'Dockerfile' || name.endsWith('.Dockerfile');\n};\n\n/**\n * Sync the pins in every generated Dockerfile.\n *\n * Ownership is resolved per file, so a Dockerfile is only rewritten for the\n * packages the project it belongs to owns — a sibling project owning `prisma`\n * does not license rewriting a `prisma` pin here.\n */\nconst syncDockerfiles = async (\n tree: Tree,\n owned: OwnedDependencies,\n): Promise<string[]> => {\n const dockerfiles: string[] = [];\n\n visitNotIgnoredFiles(tree, '.', (path) => {\n if (isDockerfile(path)) {\n dockerfiles.push(path);\n }\n });\n\n const skipped: string[] = [];\n for (const path of dockerfiles) {\n const result = await applyPins(\n tree,\n path,\n dockerfilePins(ownedForFile(owned, path)),\n );\n if (result.skipped) {\n skipped.push(path);\n }\n }\n return skipped;\n};\n\n/** The `uv run --with` pins to apply, for the Python packages owned where a file sits. */\nconst terraformScriptPins = (owned: {\n readonly py: ReadonlySet<string>;\n}): EmbeddedPin[] =>\n [...owned.py].flatMap((name) => {\n const vended = vendedPyVersion(name);\n return vended\n ? [\n {\n pattern: `--with ${escapeRegExp(name)}==([^${VERSION_TERMINATORS}]+)`,\n vended,\n },\n ]\n : [];\n });\n\n/**\n * Sync the Python pins a generated Terraform inline script runs through\n * `uv run --with <package>==<version>`.\n *\n * These are the plugin's own pins, in a file the Terraform provider sync already\n * visits but only reads `required_providers` from. Driven off the owned Python\n * packages, so a pin added to a template later is covered without a change here.\n *\n * Scoped per file like the Dockerfiles. The modules carrying these live in the\n * shared Terraform project, which no single generator owns — a file there belongs\n * to no project, so it takes the workspace-wide union, which is the set of\n * generators that legitimately write into it.\n */\nconst syncTerraformScriptPins = async (\n tree: Tree,\n owned: OwnedDependencies,\n): Promise<string[]> => {\n const terraformFiles: string[] = [];\n\n visitNotIgnoredFiles(tree, '.', (path) => {\n if (path.endsWith('.tf')) {\n terraformFiles.push(path);\n }\n });\n\n const skipped: string[] = [];\n for (const path of terraformFiles) {\n const result = await applyPins(\n tree,\n path,\n terraformScriptPins(ownedForFile(owned, path)),\n );\n if (result.skipped) {\n skipped.push(path);\n }\n }\n return skipped;\n};\n\n/**\n * The ways a `uvx` invocation pins a Python version: the tool it runs, and any\n * package it adds to that tool's environment.\n *\n * A command string is JSON here, so a quote ends a version too.\n */\nconst UVX_PIN_SHAPES: readonly ((name: string) => string)[] = [\n (name) => `uvx --from ${name}==`,\n (name) => `--with ${name}==`,\n];\n\n/**\n * Sync the pinned tools a `project.json` target command runs: a container image,\n * and the Python versions a `uvx` invocation pins.\n *\n * Both are built into the command string rather than declared as a dependency, so\n * nothing else reaches them. The images are driven off `CONTAINER_REPOSITORIES`\n * and the Python versions off `PY_VERSIONS`, so a tool pinned in a target command\n * later is covered without a change here — the same property the Dockerfile and\n * Terraform paths get from the owned set.\n *\n * Unscoped, unlike the file-body pins: a `uvx` invocation installs nothing into\n * the project, so there is no dependency for a generator to own. A version is only\n * rewritten where this release vends that exact package at a higher one.\n */\nconst syncTargetToolPins = async (tree: Tree): Promise<string[]> => {\n const projectJsons: string[] = [];\n\n visitNotIgnoredFiles(tree, '.', (path) => {\n if (path.endsWith('project.json')) {\n projectJsons.push(path);\n }\n });\n\n const pins: EmbeddedPin[] = [\n ...Object.entries(CONTAINER_REPOSITORIES).map(([tool, repository]) => ({\n // A command string is JSON here, so a quote ends the reference too.\n pattern: `${escapeRegExp(repository)}:([^${VERSION_TERMINATORS}']+)`,\n vended: CONTAINER_VERSIONS[tool as keyof typeof CONTAINER_VERSIONS],\n })),\n // The Smithy CLI a Smithy project's compile target runs, and the `mise` that\n // resolves it. Neither is installed into the workspace — the target fetches\n // mise with `npx` — so this command is the only place either version sits.\n {\n pattern: `exec smithy@([^${VERSION_TERMINATORS}']+)`,\n vended: MISE_VERSIONS.smithy,\n },\n {\n pattern: `npx -y mise@([^${VERSION_TERMINATORS}']+)`,\n vended: TS_VERSIONS.mise,\n },\n ...Object.keys(PY_VERSIONS).flatMap((name) => {\n const vended = vendedPyVersion(name);\n return vended\n ? UVX_PIN_SHAPES.map((shape) => ({\n pattern: `${shape(escapeRegExp(name))}([^${VERSION_TERMINATORS}']+)`,\n vended,\n }))\n : [];\n }),\n ];\n\n const skipped: string[] = [];\n for (const path of projectJsons) {\n if ((await applyPins(tree, path, pins)).skipped) {\n skipped.push(path);\n }\n }\n return skipped;\n};\n\n/**\n * Sync the Maven coordinates a generated `smithy-build.json` resolves.\n *\n * These are Java artifacts the Smithy CLI downloads, so they appear in no\n * manifest the dependency sync reads — this file is the only place they sit. Each\n * is matched by its `group:artifact` prefix so only the version is rewritten,\n * leaving any coordinate the user added alone.\n *\n * Scoped to the projects `smithy#project` generated: a `smithy-build.json` a user\n * wrote themselves keeps the versions they chose.\n */\nconst syncSmithyMavenPins = async (tree: Tree): Promise<string[]> => {\n const isGeneratedSmithyProject = (project: ProjectConfiguration): boolean =>\n (project.metadata as { generator?: string } | undefined)?.generator ===\n SMITHY_PROJECT_GENERATOR_INFO.id;\n\n const smithyBuilds: string[] = [];\n for (const [, project] of getProjects(tree)) {\n if (!isGeneratedSmithyProject(project)) {\n continue;\n }\n const path = joinPathFragments(project.root, 'smithy-build.json');\n if (tree.exists(path)) {\n smithyBuilds.push(path);\n }\n }\n\n const pins: EmbeddedPin[] = JAVA_ARTIFACTS.map((artifact) => ({\n // A coordinate is a JSON string here, so a quote ends the version.\n pattern: `${escapeRegExp(artifact)}:([^${VERSION_TERMINATORS}']+)`,\n vended: JAVA_VERSIONS[artifact],\n }));\n\n const skipped: string[] = [];\n for (const path of smithyBuilds) {\n if ((await applyPins(tree, path, pins)).skipped) {\n skipped.push(path);\n }\n }\n return skipped;\n};\n\n/**\n * Sync the vended versions baked into generated file bodies: `Dockerfile` pins,\n * the Python pins in Terraform inline scripts, the tooling `project.json` target\n * commands run, and the Maven coordinates a `smithy-build.json` resolves.\n *\n * Reports only the files left for the user: a pin that takes effect the next time\n * the thing holding it runs needs no follow-up, but one this skipped for holding\n * more occurrences than it will rewrite at once does.\n *\n * @returns paths whose pins were left as they were\n */\nexport const syncEmbeddedVersions = async (\n tree: Tree,\n owned: OwnedDependencies,\n): Promise<string[]> => [\n ...(await syncDockerfiles(tree, owned)),\n ...(await syncTerraformScriptPins(tree, owned)),\n ...(await syncTargetToolPins(tree)),\n ...(await syncSmithyMavenPins(tree)),\n];\n"],"names":["getProjects","joinPathFragments","visitNotIgnoredFiles","SMITHY_PROJECT_GENERATOR_INFO","applyGritQL","BASE_IMAGES","CONTAINER_REPOSITORIES","CONTAINER_VERSIONS","JAVA_ARTIFACTS","JAVA_VERSIONS","MISE_VERSIONS","PY_VERSIONS","TS_VERSIONS","ownedForFile","isVendedUpgrade","escapeRegExp","value","replace","VERSION_TERMINATORS","rewriteCapture","pattern","vended","declaredVersions","contents","matches","matchAll","RegExp","flatMap","match","MAX_OCCURRENCES_PER_PIN","applyPins","tree","path","pins","read","changed","skipped","kind","declared","length","outOfDate","tag","version","every","vendedTsVersion","name","vendedPyVersion","DOCKERFILE_PIN_SHAPES","dockerfilePins","owned","ts","shape","push","image","Object","values","repository","splitImageReference","at","lastIndexOf","slice","isDockerfile","filePath","split","pop","endsWith","syncDockerfiles","dockerfiles","result","terraformScriptPins","py","syncTerraformScriptPins","terraformFiles","UVX_PIN_SHAPES","syncTargetToolPins","projectJsons","entries","map","tool","smithy","mise","keys","syncSmithyMavenPins","isGeneratedSmithyProject","project","metadata","generator","id","smithyBuilds","root","exists","artifact","syncEmbeddedVersions"],"mappings":"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"}
@@ -93,6 +93,7 @@ export declare const TS_VERSIONS: {
93
93
  readonly 'class-variance-authority': "0.7.1";
94
94
  readonly clsx: "2.1.1";
95
95
  readonly commander: "15.0.0";
96
+ readonly 'cpy-cli': "7.0.0";
96
97
  readonly electrodb: "3.9.1";
97
98
  readonly esbuild: "0.28.1";
98
99
  readonly 'event-source-polyfill': "1.0.31";
@@ -110,6 +111,7 @@ export declare const TS_VERSIONS: {
110
111
  readonly '@types/fs-extra': "11.0.4";
111
112
  readonly 'make-dir-cli': "4.0.0";
112
113
  readonly mariadb: "3.5.3";
114
+ readonly mise: "2026.8.3";
113
115
  readonly ncp: "2.0.0";
114
116
  readonly npm: "12.0.2";
115
117
  readonly 'npm-check-updates': "22.2.9";
@@ -122,7 +124,6 @@ export declare const TS_VERSIONS: {
122
124
  readonly rimraf: "6.1.3";
123
125
  readonly rolldown: "1.2.2";
124
126
  readonly 'rolldown-plugin-dts': "0.28.0";
125
- readonly '@rollup/plugin-esm-shim': "0.1.8";
126
127
  readonly 'simple-git': "3.36.0";
127
128
  readonly 'source-map-support': "0.5.21";
128
129
  readonly 'starlight-blog': "0.28.0";
@@ -210,6 +211,37 @@ export declare const withPyVersions: <D extends DependencyDeclaration>(declarati
210
211
  export declare const VENDORED_VERSIONS: {
211
212
  readonly 'git-secrets': "1.3.0";
212
213
  };
214
+ /**
215
+ * Versions of Java dependencies added by generators, keyed by Maven coordinate.
216
+ *
217
+ * Every entry is resolved from Maven Central by the version update and named
218
+ * `<group>:<artifact>:<version>` where a generator writes it.
219
+ */
220
+ export declare const JAVA_VERSIONS: {
221
+ readonly 'software.amazon.smithy:smithy-model': "1.72.1";
222
+ readonly 'software.amazon.smithy:smithy-aws-traits': "1.72.1";
223
+ readonly 'software.amazon.smithy:smithy-validation-model': "1.72.1";
224
+ readonly 'software.amazon.smithy:smithy-openapi': "1.72.1";
225
+ readonly 'software.amazon.smithy.typescript:smithy-aws-typescript-codegen': "0.50.0";
226
+ };
227
+ export type IJavaVersion = keyof typeof JAVA_VERSIONS;
228
+ /** The Maven coordinates the version update resolves, in declaration order. */
229
+ export declare const JAVA_ARTIFACTS: IJavaVersion[];
230
+ /** A Maven coordinate as a dependency names it: `<group>:<artifact>:<version>`. */
231
+ export declare const javaMavenDependency: (artifact: IJavaVersion) => string;
232
+ /**
233
+ * Versions of tools resolved by mise, keyed by the tool name mise knows.
234
+ *
235
+ * Every entry is checked with `mise latest <tool>` by the version update. Nothing
236
+ * is installed into the workspace: the pin travels in the `project.json` target
237
+ * command, which is what the version sync reaches to move it forward.
238
+ */
239
+ export declare const MISE_VERSIONS: {
240
+ readonly smithy: "1.72.1";
241
+ };
242
+ export type IMiseVersion = keyof typeof MISE_VERSIONS;
243
+ /** The tools the version update resolves through mise, in declaration order. */
244
+ export declare const MISE_TOOLS: IMiseVersion[];
213
245
  /**
214
246
  * Base container images used by generated Dockerfiles. Pinned exactly so
215
247
  * generated images are reproducible, and chosen to be free of known
@@ -99,6 +99,7 @@
99
99
  'class-variance-authority': '0.7.1',
100
100
  clsx: '2.1.1',
101
101
  commander: '15.0.0',
102
+ 'cpy-cli': '7.0.0',
102
103
  electrodb: '3.9.1',
103
104
  esbuild: '0.28.1',
104
105
  'event-source-polyfill': '1.0.31',
@@ -116,6 +117,7 @@
116
117
  '@types/fs-extra': '11.0.4',
117
118
  'make-dir-cli': '4.0.0',
118
119
  mariadb: '3.5.3',
120
+ mise: '2026.8.3',
119
121
  ncp: '2.0.0',
120
122
  npm: '12.0.2',
121
123
  'npm-check-updates': '22.2.9',
@@ -128,7 +130,6 @@
128
130
  rimraf: '6.1.3',
129
131
  rolldown: '1.2.2',
130
132
  'rolldown-plugin-dts': '0.28.0',
131
- '@rollup/plugin-esm-shim': '0.1.8',
132
133
  'simple-git': '3.36.0',
133
134
  'source-map-support': '0.5.21',
134
135
  'starlight-blog': '0.28.0',
@@ -235,6 +236,30 @@
235
236
  */ export const VENDORED_VERSIONS = {
236
237
  'git-secrets': '1.3.0'
237
238
  };
239
+ /**
240
+ * Versions of Java dependencies added by generators, keyed by Maven coordinate.
241
+ *
242
+ * Every entry is resolved from Maven Central by the version update and named
243
+ * `<group>:<artifact>:<version>` where a generator writes it.
244
+ */ export const JAVA_VERSIONS = {
245
+ 'software.amazon.smithy:smithy-model': '1.72.1',
246
+ 'software.amazon.smithy:smithy-aws-traits': '1.72.1',
247
+ 'software.amazon.smithy:smithy-validation-model': '1.72.1',
248
+ 'software.amazon.smithy:smithy-openapi': '1.72.1',
249
+ 'software.amazon.smithy.typescript:smithy-aws-typescript-codegen': '0.50.0'
250
+ };
251
+ /** The Maven coordinates the version update resolves, in declaration order. */ export const JAVA_ARTIFACTS = Object.keys(JAVA_VERSIONS);
252
+ /** A Maven coordinate as a dependency names it: `<group>:<artifact>:<version>`. */ export const javaMavenDependency = (artifact)=>`${artifact}:${JAVA_VERSIONS[artifact]}`;
253
+ /**
254
+ * Versions of tools resolved by mise, keyed by the tool name mise knows.
255
+ *
256
+ * Every entry is checked with `mise latest <tool>` by the version update. Nothing
257
+ * is installed into the workspace: the pin travels in the `project.json` target
258
+ * command, which is what the version sync reaches to move it forward.
259
+ */ export const MISE_VERSIONS = {
260
+ smithy: '1.72.1'
261
+ };
262
+ /** The tools the version update resolves through mise, in declaration order. */ export const MISE_TOOLS = Object.keys(MISE_VERSIONS);
238
263
  /**
239
264
  * Base container images used by generated Dockerfiles. Pinned exactly so
240
265
  * generated images are reproducible, and chosen to be free of known