@aws/nx-plugin 1.0.7 → 1.0.8

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 (52) hide show
  1. package/migrations.json +16 -1
  2. package/package.json +1 -1
  3. package/src/infra/app/__snapshots__/generator.spec.ts.snap +10 -0
  4. package/src/infra/app/files/app/README.md.template +12 -0
  5. package/src/infra/app/generator.js +8 -0
  6. package/src/infra/app/generator.js.map +1 -1
  7. package/src/migrations/latest/cache-inputs-outputs/metadata.json +3 -0
  8. package/src/migrations/latest/cache-inputs-outputs/migration.d.ts +6 -0
  9. package/src/migrations/latest/cache-inputs-outputs/migration.js +176 -0
  10. package/src/migrations/latest/cache-inputs-outputs/migration.js.map +1 -0
  11. package/src/migrations/latest/infra-test-loop/metadata.json +3 -0
  12. package/src/migrations/latest/infra-test-loop/migration.d.ts +6 -0
  13. package/src/migrations/latest/infra-test-loop/migration.js +110 -0
  14. package/src/migrations/latest/infra-test-loop/migration.js.map +1 -0
  15. package/src/migrations/latest/py-dynamodb-type-base-model-meta/metadata.json +3 -0
  16. package/src/migrations/latest/py-dynamodb-type-base-model-meta/migration.d.ts +6 -0
  17. package/src/migrations/latest/py-dynamodb-type-base-model-meta/migration.js +87 -0
  18. package/src/migrations/latest/py-dynamodb-type-base-model-meta/migration.js.map +1 -0
  19. package/src/migrations/v1.0.0-rc.90/0004-python-test-input-scoping/migration.js +8 -2
  20. package/src/migrations/v1.0.0-rc.90/0004-python-test-input-scoping/migration.js.map +1 -1
  21. package/src/open-api/py-client/files/client/__clientModuleName__.py.template +17 -6
  22. package/src/py/dynamodb/__snapshots__/generator.spec.ts.snap +4 -4
  23. package/src/py/dynamodb/files/__name__/entities/base.py.template +2 -2
  24. package/src/smithy/project/__snapshots__/generator.spec.ts.snap +9 -0
  25. package/src/smithy/project/generator.d.ts +9 -0
  26. package/src/smithy/project/generator.js +15 -0
  27. package/src/smithy/project/generator.js.map +1 -1
  28. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +2 -0
  29. package/src/terraform/project/generator.js +2 -4
  30. package/src/terraform/project/generator.js.map +1 -1
  31. package/src/ts/lib/__snapshots__/generator.spec.ts.snap +1 -1
  32. package/src/ts/lib/generator.d.ts +14 -3
  33. package/src/ts/lib/generator.js +18 -7
  34. package/src/ts/lib/generator.js.map +1 -1
  35. package/src/ts/rdb/generator.js +4 -0
  36. package/src/ts/rdb/generator.js.map +1 -1
  37. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +102 -2
  38. package/src/utils/__snapshots__/cdk-test-setup.spec.ts.snap +25 -0
  39. package/src/utils/cdk-test-setup.d.ts +22 -0
  40. package/src/utils/cdk-test-setup.js +38 -0
  41. package/src/utils/cdk-test-setup.js.map +1 -0
  42. package/src/utils/files/cdk-test-setup/tests/global-setup.ts.template +45 -0
  43. package/src/utils/shared-constructs.js +2 -0
  44. package/src/utils/shared-constructs.js.map +1 -1
  45. package/src/utils/test/python-dependencies.d.ts +6 -0
  46. package/src/utils/test/python-dependencies.js +9 -0
  47. package/src/utils/test/python-dependencies.js.map +1 -1
  48. package/src/utils/test/warm-python-cache.js +40 -21
  49. package/src/utils/test/warm-python-cache.js.map +1 -1
  50. package/src/utils/versions.d.ts +1 -1
  51. package/src/utils/versions.js +1 -1
  52. package/src/utils/versions.js.map +1 -1
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */ import { getProjects, joinPathFragments } from "@nx/devkit";
5
+ import { PY_DYNAMODB_GENERATOR_INFO } from "../../../py/dynamodb/generator.js";
6
+ import { formatFilesInSubtree } from "../../../utils/format.js";
7
+ /**
8
+ * Type the `Meta` class of the `BaseModel` that py#dynamodb vends in
9
+ * `<module>/entities/base.py` as a subclass of pynamodb's `MetaProtocol`.
10
+ *
11
+ * pynamodb declares `Model.Meta: MetaProtocol`. The vended nested `class Meta:`
12
+ * defines only some of the protocol's members, and infers `region` as `str`
13
+ * where the protocol declares a mutable `Optional[str]`. From ty 0.0.86 that
14
+ * makes the project's `typecheck` target fail with `invalid-attribute-override`.
15
+ * Subclassing the protocol declares every member with the protocol's type.
16
+ * The members it only annotates are not set on the class, so pynamodb's
17
+ * runtime defaults apply as before.
18
+ *
19
+ * The generator writes base.py once and keeps the user's copy, so this brings
20
+ * existing workspaces up to date. A base.py is edited only where its import
21
+ * line and `Meta` block still have the exact shape the generator wrote. One
22
+ * that has diverged is left untouched and reported via `nextSteps`.
23
+ */ const OLD_IMPORT = '\nfrom pynamodb.models import Model\n';
24
+ const NEW_IMPORT = '\nfrom pynamodb.models import MetaProtocol, Model\n';
25
+ const OLD_META_HEADER = ' class Meta:\n';
26
+ const NEW_META_HEADER = ' class Meta(MetaProtocol):\n';
27
+ /**
28
+ * The helper the vended `host` line reads the local port through. Workspaces
29
+ * generated before the serve-local -> local-dev rename use `_serve_local`.
30
+ */ const LOCAL_DEV_HELPERS = [
31
+ '_local_dev',
32
+ '_serve_local'
33
+ ];
34
+ /**
35
+ * The quote the block's string literals use: the template's single quotes, or
36
+ * the double quotes `ruff format` rewrites them to.
37
+ */ const QUOTES = [
38
+ '"',
39
+ "'"
40
+ ];
41
+ /** The vended `BaseModel.Meta` block, up to the blank line that ends it. */ const metaBlock = (header, localDevHelper, quote)=>`${header} table_name: str
42
+ region = os.environ.get("AWS_REGION", ${quote}us-east-1${quote})
43
+ host = f"http://localhost:{${localDevHelper}()['port']}" if is_local() else None
44
+ aws_access_key_id = ${quote}UNUSED${quote} if is_local() else None
45
+ aws_secret_access_key = ${quote}UNUSED${quote} if is_local() else None
46
+
47
+ `;
48
+ /** Every shape of the block the generator has written. */ const OLD_META_SHAPES = LOCAL_DEV_HELPERS.flatMap((helper)=>QUOTES.map((quote)=>({
49
+ helper,
50
+ quote
51
+ })));
52
+ const divergedNextStep = (filePath)=>`${filePath}: its BaseModel Meta class or its pynamodb.models import has been customised, so it was left unchanged. If \`ty check\` reports invalid-attribute-override for it, declare it as \`class Meta(MetaProtocol):\`, importing MetaProtocol from pynamodb.models.`;
53
+ /**
54
+ * Rewrite a base.py still in the generated shape. Already migrated and missing
55
+ * files are left alone; a diverged one is reported via nextSteps.
56
+ */ const migrateBasePy = (tree, filePath, nextSteps)=>{
57
+ if (!tree.exists(filePath)) {
58
+ return;
59
+ }
60
+ const content = tree.read(filePath, 'utf-8') ?? '';
61
+ if (content.includes(NEW_META_HEADER)) {
62
+ return; // Already migrated (or user-added).
63
+ }
64
+ const shape = OLD_META_SHAPES.find(({ helper, quote })=>content.includes(metaBlock(OLD_META_HEADER, helper, quote)));
65
+ if (!shape || !content.includes(OLD_IMPORT)) {
66
+ nextSteps.push(divergedNextStep(filePath));
67
+ return;
68
+ }
69
+ tree.write(filePath, content.replace(OLD_IMPORT, NEW_IMPORT).replace(metaBlock(OLD_META_HEADER, shape.helper, shape.quote), metaBlock(NEW_META_HEADER, shape.helper, shape.quote)));
70
+ };
71
+ export default async function migration(tree) {
72
+ const nextSteps = [];
73
+ for (const project of getProjects(tree).values()){
74
+ const generator = project.metadata?.generator;
75
+ // py#dynamodb writes its package under the project's sourceRoot.
76
+ if (generator !== PY_DYNAMODB_GENERATOR_INFO.id || !project.sourceRoot) {
77
+ continue;
78
+ }
79
+ migrateBasePy(tree, joinPathFragments(project.sourceRoot, 'entities', 'base.py'), nextSteps);
80
+ }
81
+ await formatFilesInSubtree(tree);
82
+ return {
83
+ nextSteps
84
+ };
85
+ }
86
+
87
+ //# sourceMappingURL=migration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/py-dynamodb-type-base-model-meta/migration.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 joinPathFragments,\n type MigrationReturnObject,\n type Tree,\n} from '@nx/devkit';\nimport { PY_DYNAMODB_GENERATOR_INFO } from '../../../py/dynamodb/generator.js';\nimport { formatFilesInSubtree } from '../../../utils/format.js';\n\n/**\n * Type the `Meta` class of the `BaseModel` that py#dynamodb vends in\n * `<module>/entities/base.py` as a subclass of pynamodb's `MetaProtocol`.\n *\n * pynamodb declares `Model.Meta: MetaProtocol`. The vended nested `class Meta:`\n * defines only some of the protocol's members, and infers `region` as `str`\n * where the protocol declares a mutable `Optional[str]`. From ty 0.0.86 that\n * makes the project's `typecheck` target fail with `invalid-attribute-override`.\n * Subclassing the protocol declares every member with the protocol's type.\n * The members it only annotates are not set on the class, so pynamodb's\n * runtime defaults apply as before.\n *\n * The generator writes base.py once and keeps the user's copy, so this brings\n * existing workspaces up to date. A base.py is edited only where its import\n * line and `Meta` block still have the exact shape the generator wrote. One\n * that has diverged is left untouched and reported via `nextSteps`.\n */\n\nconst OLD_IMPORT = '\\nfrom pynamodb.models import Model\\n';\nconst NEW_IMPORT = '\\nfrom pynamodb.models import MetaProtocol, Model\\n';\n\nconst OLD_META_HEADER = ' class Meta:\\n';\nconst NEW_META_HEADER = ' class Meta(MetaProtocol):\\n';\n\n/**\n * The helper the vended `host` line reads the local port through. Workspaces\n * generated before the serve-local -> local-dev rename use `_serve_local`.\n */\nconst LOCAL_DEV_HELPERS = ['_local_dev', '_serve_local'];\n\n/**\n * The quote the block's string literals use: the template's single quotes, or\n * the double quotes `ruff format` rewrites them to.\n */\nconst QUOTES = ['\"', \"'\"];\n\n/** The vended `BaseModel.Meta` block, up to the blank line that ends it. */\nconst metaBlock = (\n header: string,\n localDevHelper: string,\n quote: string,\n): string =>\n `${header} table_name: str\n region = os.environ.get(\"AWS_REGION\", ${quote}us-east-1${quote})\n host = f\"http://localhost:{${localDevHelper}()['port']}\" if is_local() else None\n aws_access_key_id = ${quote}UNUSED${quote} if is_local() else None\n aws_secret_access_key = ${quote}UNUSED${quote} if is_local() else None\n\n`;\n\n/** Every shape of the block the generator has written. */\nconst OLD_META_SHAPES = LOCAL_DEV_HELPERS.flatMap((helper) =>\n QUOTES.map((quote) => ({ helper, quote })),\n);\n\nconst divergedNextStep = (filePath: string): string =>\n `${filePath}: its BaseModel Meta class or its pynamodb.models import has been customised, so it was left unchanged. If \\`ty check\\` reports invalid-attribute-override for it, declare it as \\`class Meta(MetaProtocol):\\`, importing MetaProtocol from pynamodb.models.`;\n\n/**\n * Rewrite a base.py still in the generated shape. Already migrated and missing\n * files are left alone; a diverged one is reported via nextSteps.\n */\nconst migrateBasePy = (\n tree: Tree,\n filePath: string,\n nextSteps: string[],\n): void => {\n if (!tree.exists(filePath)) {\n return;\n }\n\n const content = tree.read(filePath, 'utf-8') ?? '';\n if (content.includes(NEW_META_HEADER)) {\n return; // Already migrated (or user-added).\n }\n\n const shape = OLD_META_SHAPES.find(({ helper, quote }) =>\n content.includes(metaBlock(OLD_META_HEADER, helper, quote)),\n );\n if (!shape || !content.includes(OLD_IMPORT)) {\n nextSteps.push(divergedNextStep(filePath));\n return;\n }\n\n tree.write(\n filePath,\n content\n .replace(OLD_IMPORT, NEW_IMPORT)\n .replace(\n metaBlock(OLD_META_HEADER, shape.helper, shape.quote),\n metaBlock(NEW_META_HEADER, shape.helper, shape.quote),\n ),\n );\n};\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n for (const project of getProjects(tree).values()) {\n const generator = (project.metadata as { generator?: string } | undefined)\n ?.generator;\n // py#dynamodb writes its package under the project's sourceRoot.\n if (generator !== PY_DYNAMODB_GENERATOR_INFO.id || !project.sourceRoot) {\n continue;\n }\n migrateBasePy(\n tree,\n joinPathFragments(project.sourceRoot, 'entities', 'base.py'),\n nextSteps,\n );\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["getProjects","joinPathFragments","PY_DYNAMODB_GENERATOR_INFO","formatFilesInSubtree","OLD_IMPORT","NEW_IMPORT","OLD_META_HEADER","NEW_META_HEADER","LOCAL_DEV_HELPERS","QUOTES","metaBlock","header","localDevHelper","quote","OLD_META_SHAPES","flatMap","helper","map","divergedNextStep","filePath","migrateBasePy","tree","nextSteps","exists","content","read","includes","shape","find","push","write","replace","migration","project","values","generator","metadata","id","sourceRoot"],"mappings":"AAAA;;;CAGC,GACD,SACEA,WAAW,EACXC,iBAAiB,QAGZ,aAAa;AACpB,SAASC,0BAA0B,QAAQ,oCAAoC;AAC/E,SAASC,oBAAoB,QAAQ,2BAA2B;AAEhE;;;;;;;;;;;;;;;;CAgBC,GAED,MAAMC,aAAa;AACnB,MAAMC,aAAa;AAEnB,MAAMC,kBAAkB;AACxB,MAAMC,kBAAkB;AAExB;;;CAGC,GACD,MAAMC,oBAAoB;IAAC;IAAc;CAAe;AAExD;;;CAGC,GACD,MAAMC,SAAS;IAAC;IAAK;CAAI;AAEzB,0EAA0E,GAC1E,MAAMC,YAAY,CAChBC,QACAC,gBACAC,QAEA,GAAGF,OAAO;8CACkC,EAAEE,MAAM,SAAS,EAAEA,MAAM;mCACpC,EAAED,eAAe;4BACxB,EAAEC,MAAM,MAAM,EAAEA,MAAM;gCAClB,EAAEA,MAAM,MAAM,EAAEA,MAAM;;AAEtD,CAAC;AAED,wDAAwD,GACxD,MAAMC,kBAAkBN,kBAAkBO,OAAO,CAAC,CAACC,SACjDP,OAAOQ,GAAG,CAAC,CAACJ,QAAW,CAAA;YAAEG;YAAQH;QAAM,CAAA;AAGzC,MAAMK,mBAAmB,CAACC,WACxB,GAAGA,SAAS,4PAA4P,CAAC;AAE3Q;;;CAGC,GACD,MAAMC,gBAAgB,CACpBC,MACAF,UACAG;IAEA,IAAI,CAACD,KAAKE,MAAM,CAACJ,WAAW;QAC1B;IACF;IAEA,MAAMK,UAAUH,KAAKI,IAAI,CAACN,UAAU,YAAY;IAChD,IAAIK,QAAQE,QAAQ,CAACnB,kBAAkB;QACrC,QAAQ,oCAAoC;IAC9C;IAEA,MAAMoB,QAAQb,gBAAgBc,IAAI,CAAC,CAAC,EAAEZ,MAAM,EAAEH,KAAK,EAAE,GACnDW,QAAQE,QAAQ,CAAChB,UAAUJ,iBAAiBU,QAAQH;IAEtD,IAAI,CAACc,SAAS,CAACH,QAAQE,QAAQ,CAACtB,aAAa;QAC3CkB,UAAUO,IAAI,CAACX,iBAAiBC;QAChC;IACF;IAEAE,KAAKS,KAAK,CACRX,UACAK,QACGO,OAAO,CAAC3B,YAAYC,YACpB0B,OAAO,CACNrB,UAAUJ,iBAAiBqB,MAAMX,MAAM,EAAEW,MAAMd,KAAK,GACpDH,UAAUH,iBAAiBoB,MAAMX,MAAM,EAAEW,MAAMd,KAAK;AAG5D;AAEA,eAAe,eAAemB,UAC5BX,IAAU;IAEV,MAAMC,YAAsB,EAAE;IAE9B,KAAK,MAAMW,WAAWjC,YAAYqB,MAAMa,MAAM,GAAI;QAChD,MAAMC,YAAaF,QAAQG,QAAQ,EAC/BD;QACJ,iEAAiE;QACjE,IAAIA,cAAcjC,2BAA2BmC,EAAE,IAAI,CAACJ,QAAQK,UAAU,EAAE;YACtE;QACF;QACAlB,cACEC,MACApB,kBAAkBgC,QAAQK,UAAU,EAAE,YAAY,YAClDhB;IAEJ;IAEA,MAAMnB,qBAAqBkB;IAE3B,OAAO;QAAEC;IAAU;AACrB"}
@@ -3,7 +3,6 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */ import { getProjects, readNxJson, updateNxJson, updateProjectConfiguration } from "@nx/devkit";
5
5
  import { PYTHON_TEST_FILE_EXCLUSIONS } from "../../../py/project/generator.js";
6
- import { DEPENDENT_TASKS_OUTPUT_FILES_INPUT } from "../../../ts/lib/generator.js";
7
6
  import { formatFilesInSubtree } from "../../../utils/format.js";
8
7
  /**
9
8
  * Editing a Python test file used to invalidate the whole build chain for its
@@ -39,6 +38,13 @@ import { formatFilesInSubtree } from "../../../utils/format.js";
39
38
  '**/*',
40
39
  'dist/**'
41
40
  ];
41
+ /**
42
+ * The dependent-task-output glob this migration shipped with at release. A
43
+ * released migration's output must not change, so this is the literal value
44
+ * rather than a reference to ts/lib/generator.ts's current constant, which a
45
+ * later migration (cache-inputs-outputs) widens further and reports through
46
+ * its own stale-pass advisory.
47
+ */ const RELEASED_DEPENDENT_TASKS_OUTPUT_GLOB = '!{reports,coverage}/**';
42
48
  const isPythonProject = (project)=>Object.values(project.targets ?? {}).some((target)=>String(target?.executor ?? '').startsWith('@nxlv/python'));
43
49
  /**
44
50
  * An OpenAPI spec generation target as the generators vend it: named `openapi`
@@ -71,7 +77,7 @@ const arraysEqual = (a, b)=>a.length === b.length && a.every((entry, index)=>ent
71
77
  const defaultInput = nxJson.namedInputs?.default;
72
78
  let nextDefault = defaultInput;
73
79
  if (defaultInput) {
74
- const glob = DEPENDENT_TASKS_OUTPUT_FILES_INPUT.dependentTasksOutputFiles;
80
+ const glob = RELEASED_DEPENDENT_TASKS_OUTPUT_GLOB;
75
81
  // Only an entry this plugin vended is rewritten; a different glob is the
76
82
  // user's own scoping decision.
77
83
  nextDefault = defaultInput.map((input)=>typeof input === 'object' && input !== null && 'dependentTasksOutputFiles' in input && PREVIOUSLY_VENDED_GLOBS.includes(input.dependentTasksOutputFiles) ? {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/v1.0.0-rc.90/0004-python-test-input-scoping/migration.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 MigrationReturnObject,\n type ProjectConfiguration,\n readNxJson,\n type TargetConfiguration,\n type Tree,\n updateNxJson,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { PYTHON_TEST_FILE_EXCLUSIONS } from '../../../py/project/generator.js';\nimport { DEPENDENT_TASKS_OUTPUT_FILES_INPUT } from '../../../ts/lib/generator.js';\nimport { formatFilesInSubtree } from '../../../utils/format.js';\n\n/**\n * Editing a Python test file used to invalidate the whole build chain for its\n * project, and cascade into every downstream project. Two independent causes:\n *\n * 1. The `production` named input excluded TypeScript specs but nothing Python,\n * and the Python build targets read `default` (every file in the project), so\n * a test file was a build input by construction.\n * 2. `default` consumed *every* output of a dependency task. The Python `test`\n * target writes JUnit and coverage reports that pytest stamps wall-clock time\n * into, so each test run minted a new hash that propagated downstream.\n *\n * Targets whose output genuinely cannot contain a test file move to\n * `production`; `typecheck` deliberately stays on `default`, because `ty` checks\n * the tests directory and must re-run when a test changes.\n */\n\n/** The Python targets whose declared output cannot contain a test file. */\nconst PRODUCTION_SCOPED_TARGETS = ['compile', 'bundle-x86', 'bundle-arm'];\n\n/** The inputs those targets read once scoped to production sources. */\nconst PRODUCTION_INPUTS = ['production', '^production'];\n\n/** The inputs those targets previously read. */\nconst PREVIOUS_INPUTS = ['default', '^production'];\n\n/**\n * Dependent-task-output globs this plugin has vended. Any of them is rewritten\n * to the current one; anything else is the user's own scoping decision.\n */\nconst PREVIOUSLY_VENDED_GLOBS = ['**/*', 'dist/**'];\n\nconst isPythonProject = (project: ProjectConfiguration): boolean =>\n Object.values(project.targets ?? {}).some((target) =>\n String(target?.executor ?? '').startsWith('@nxlv/python'),\n );\n\n/**\n * An OpenAPI spec generation target as the generators vend it: named `openapi`\n * or `<agent>-openapi`, running a command, and writing its spec under\n * `dist/.../openapi`. The extra checks keep a user-authored target that merely\n * shares the suffix from being rescoped, since these targets are identified by\n * declaring no `inputs` at all.\n */\nconst isOpenApiTarget = (\n name: string,\n target?: TargetConfiguration,\n): boolean => {\n if (name !== 'openapi' && !name.endsWith('-openapi')) return false;\n if (!target) return true;\n return (\n target.executor === 'nx:run-commands' &&\n (target.outputs ?? []).some((output) => output.includes('/openapi'))\n );\n};\n\nconst arraysEqual = (a: readonly unknown[], b: readonly unknown[]): boolean =>\n a.length === b.length && a.every((entry, index) => entry === b[index]);\n\n/**\n * Excludes Python test files from the `production` named input, and narrows the\n * dependent-task-output input so test reports no longer propagate downstream.\n */\nconst migrateNamedInputs = (tree: Tree, nextSteps: string[]): void => {\n const nxJson = readNxJson(tree);\n if (!nxJson) return;\n\n // Seeded as `['default']` when absent, exactly as the generator does. The\n // targets below are rewritten to read `production`, and Nx fails hard on a\n // named input that is not defined, so the two must not diverge.\n const production = nxJson.namedInputs?.production ?? ['default'];\n const nextProduction = [\n ...production,\n ...PYTHON_TEST_FILE_EXCLUSIONS.filter(\n (exclusion) => !production.includes(exclusion),\n ),\n ];\n\n const defaultInput = nxJson.namedInputs?.default;\n let nextDefault = defaultInput;\n if (defaultInput) {\n const glob = DEPENDENT_TASKS_OUTPUT_FILES_INPUT.dependentTasksOutputFiles;\n // Only an entry this plugin vended is rewritten; a different glob is the\n // user's own scoping decision.\n nextDefault = defaultInput.map((input) =>\n typeof input === 'object' &&\n input !== null &&\n 'dependentTasksOutputFiles' in input &&\n PREVIOUSLY_VENDED_GLOBS.includes(\n input.dependentTasksOutputFiles as string,\n )\n ? { ...input, dependentTasksOutputFiles: glob }\n : input,\n );\n const hadVendedEntry = nextDefault.some(\n (input) =>\n typeof input === 'object' &&\n input !== null &&\n 'dependentTasksOutputFiles' in input &&\n input.dependentTasksOutputFiles === glob,\n );\n const hasCustomEntry = defaultInput.some(\n (input) =>\n typeof input === 'object' &&\n input !== null &&\n 'dependentTasksOutputFiles' in input &&\n !PREVIOUSLY_VENDED_GLOBS.includes(\n input.dependentTasksOutputFiles as string,\n ) &&\n input.dependentTasksOutputFiles !== glob,\n );\n if (!hadVendedEntry && hasCustomEntry) {\n nextSteps.push(\n `nx.json's 'default' named input scopes 'dependentTasksOutputFiles' to a custom glob — left untouched. Narrow it to '${glob}' so timestamped test reports do not invalidate downstream tasks.`,\n );\n }\n }\n\n updateNxJson(tree, {\n ...nxJson,\n namedInputs: {\n ...nxJson.namedInputs,\n production: nextProduction,\n ...(nextDefault ? { default: nextDefault } : {}),\n },\n });\n};\n\n/**\n * Scopes a Python project's build-chain targets to production sources. Only\n * targets still carrying the inputs the generator vended are rewritten, so a\n * project whose inputs the user has tuned is reported rather than clobbered.\n */\nconst migrateProjectTargets = (\n tree: Tree,\n projectName: string,\n project: ProjectConfiguration,\n nextSteps: string[],\n): void => {\n let changed = false;\n\n for (const [targetName, target] of Object.entries(project.targets ?? {})) {\n if (\n !PRODUCTION_SCOPED_TARGETS.includes(targetName) &&\n !isOpenApiTarget(targetName, target)\n ) {\n continue;\n }\n\n const inputs = target.inputs;\n\n // Already migrated, so a re-run is a no-op.\n if (inputs && arraysEqual(inputs as unknown[], PRODUCTION_INPUTS)) {\n continue;\n }\n\n // The OpenAPI targets declared no inputs at all, so they fell back to\n // `default`. Everything else carried the vended pair.\n const isVendedShape = inputs\n ? arraysEqual(inputs as unknown[], PREVIOUS_INPUTS)\n : isOpenApiTarget(targetName, target);\n\n if (!isVendedShape) {\n nextSteps.push(\n `${projectName}:${targetName}: 'inputs' has diverged from the generated shape — left untouched. Scope it to ['production', '^production'] so Python test edits do not invalidate it.`,\n );\n continue;\n }\n\n target.inputs = [...PRODUCTION_INPUTS];\n changed = true;\n }\n\n if (changed) {\n updateProjectConfiguration(tree, projectName, project);\n }\n};\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n migrateNamedInputs(tree, nextSteps);\n\n for (const [projectName, project] of getProjects(tree)) {\n if (!isPythonProject(project)) continue;\n migrateProjectTargets(tree, projectName, project, nextSteps);\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["getProjects","readNxJson","updateNxJson","updateProjectConfiguration","PYTHON_TEST_FILE_EXCLUSIONS","DEPENDENT_TASKS_OUTPUT_FILES_INPUT","formatFilesInSubtree","PRODUCTION_SCOPED_TARGETS","PRODUCTION_INPUTS","PREVIOUS_INPUTS","PREVIOUSLY_VENDED_GLOBS","isPythonProject","project","Object","values","targets","some","target","String","executor","startsWith","isOpenApiTarget","name","endsWith","outputs","output","includes","arraysEqual","a","b","length","every","entry","index","migrateNamedInputs","tree","nextSteps","nxJson","production","namedInputs","nextProduction","filter","exclusion","defaultInput","default","nextDefault","glob","dependentTasksOutputFiles","map","input","hadVendedEntry","hasCustomEntry","push","migrateProjectTargets","projectName","changed","targetName","entries","inputs","isVendedShape","migration"],"mappings":"AAAA;;;CAGC,GACD,SACEA,WAAW,EAGXC,UAAU,EAGVC,YAAY,EACZC,0BAA0B,QACrB,aAAa;AACpB,SAASC,2BAA2B,QAAQ,mCAAmC;AAC/E,SAASC,kCAAkC,QAAQ,+BAA+B;AAClF,SAASC,oBAAoB,QAAQ,2BAA2B;AAEhE;;;;;;;;;;;;;;CAcC,GAED,yEAAyE,GACzE,MAAMC,4BAA4B;IAAC;IAAW;IAAc;CAAa;AAEzE,qEAAqE,GACrE,MAAMC,oBAAoB;IAAC;IAAc;CAAc;AAEvD,8CAA8C,GAC9C,MAAMC,kBAAkB;IAAC;IAAW;CAAc;AAElD;;;CAGC,GACD,MAAMC,0BAA0B;IAAC;IAAQ;CAAU;AAEnD,MAAMC,kBAAkB,CAACC,UACvBC,OAAOC,MAAM,CAACF,QAAQG,OAAO,IAAI,CAAC,GAAGC,IAAI,CAAC,CAACC,SACzCC,OAAOD,QAAQE,YAAY,IAAIC,UAAU,CAAC;AAG9C;;;;;;CAMC,GACD,MAAMC,kBAAkB,CACtBC,MACAL;IAEA,IAAIK,SAAS,aAAa,CAACA,KAAKC,QAAQ,CAAC,aAAa,OAAO;IAC7D,IAAI,CAACN,QAAQ,OAAO;IACpB,OACEA,OAAOE,QAAQ,KAAK,qBACpB,AAACF,CAAAA,OAAOO,OAAO,IAAI,EAAE,AAAD,EAAGR,IAAI,CAAC,CAACS,SAAWA,OAAOC,QAAQ,CAAC;AAE5D;AAEA,MAAMC,cAAc,CAACC,GAAuBC,IAC1CD,EAAEE,MAAM,KAAKD,EAAEC,MAAM,IAAIF,EAAEG,KAAK,CAAC,CAACC,OAAOC,QAAUD,UAAUH,CAAC,CAACI,MAAM;AAEvE;;;CAGC,GACD,MAAMC,qBAAqB,CAACC,MAAYC;IACtC,MAAMC,SAASpC,WAAWkC;IAC1B,IAAI,CAACE,QAAQ;IAEb,0EAA0E;IAC1E,2EAA2E;IAC3E,gEAAgE;IAChE,MAAMC,aAAaD,OAAOE,WAAW,EAAED,cAAc;QAAC;KAAU;IAChE,MAAME,iBAAiB;WAClBF;WACAlC,4BAA4BqC,MAAM,CACnC,CAACC,YAAc,CAACJ,WAAWZ,QAAQ,CAACgB;KAEvC;IAED,MAAMC,eAAeN,OAAOE,WAAW,EAAEK;IACzC,IAAIC,cAAcF;IAClB,IAAIA,cAAc;QAChB,MAAMG,OAAOzC,mCAAmC0C,yBAAyB;QACzE,yEAAyE;QACzE,+BAA+B;QAC/BF,cAAcF,aAAaK,GAAG,CAAC,CAACC,QAC9B,OAAOA,UAAU,YACjBA,UAAU,QACV,+BAA+BA,SAC/BvC,wBAAwBgB,QAAQ,CAC9BuB,MAAMF,yBAAyB,IAE7B;gBAAE,GAAGE,KAAK;gBAAEF,2BAA2BD;YAAK,IAC5CG;QAEN,MAAMC,iBAAiBL,YAAY7B,IAAI,CACrC,CAACiC,QACC,OAAOA,UAAU,YACjBA,UAAU,QACV,+BAA+BA,SAC/BA,MAAMF,yBAAyB,KAAKD;QAExC,MAAMK,iBAAiBR,aAAa3B,IAAI,CACtC,CAACiC,QACC,OAAOA,UAAU,YACjBA,UAAU,QACV,+BAA+BA,SAC/B,CAACvC,wBAAwBgB,QAAQ,CAC/BuB,MAAMF,yBAAyB,KAEjCE,MAAMF,yBAAyB,KAAKD;QAExC,IAAI,CAACI,kBAAkBC,gBAAgB;YACrCf,UAAUgB,IAAI,CACZ,CAAC,oHAAoH,EAAEN,KAAK,iEAAiE,CAAC;QAElM;IACF;IAEA5C,aAAaiC,MAAM;QACjB,GAAGE,MAAM;QACTE,aAAa;YACX,GAAGF,OAAOE,WAAW;YACrBD,YAAYE;YACZ,GAAIK,cAAc;gBAAED,SAASC;YAAY,IAAI,CAAC,CAAC;QACjD;IACF;AACF;AAEA;;;;CAIC,GACD,MAAMQ,wBAAwB,CAC5BlB,MACAmB,aACA1C,SACAwB;IAEA,IAAImB,UAAU;IAEd,KAAK,MAAM,CAACC,YAAYvC,OAAO,IAAIJ,OAAO4C,OAAO,CAAC7C,QAAQG,OAAO,IAAI,CAAC,GAAI;QACxE,IACE,CAACR,0BAA0BmB,QAAQ,CAAC8B,eACpC,CAACnC,gBAAgBmC,YAAYvC,SAC7B;YACA;QACF;QAEA,MAAMyC,SAASzC,OAAOyC,MAAM;QAE5B,4CAA4C;QAC5C,IAAIA,UAAU/B,YAAY+B,QAAqBlD,oBAAoB;YACjE;QACF;QAEA,sEAAsE;QACtE,sDAAsD;QACtD,MAAMmD,gBAAgBD,SAClB/B,YAAY+B,QAAqBjD,mBACjCY,gBAAgBmC,YAAYvC;QAEhC,IAAI,CAAC0C,eAAe;YAClBvB,UAAUgB,IAAI,CACZ,GAAGE,YAAY,CAAC,EAAEE,WAAW,uJAAuJ,CAAC;YAEvL;QACF;QAEAvC,OAAOyC,MAAM,GAAG;eAAIlD;SAAkB;QACtC+C,UAAU;IACZ;IAEA,IAAIA,SAAS;QACXpD,2BAA2BgC,MAAMmB,aAAa1C;IAChD;AACF;AAEA,eAAe,eAAegD,UAC5BzB,IAAU;IAEV,MAAMC,YAAsB,EAAE;IAE9BF,mBAAmBC,MAAMC;IAEzB,KAAK,MAAM,CAACkB,aAAa1C,QAAQ,IAAIZ,YAAYmC,MAAO;QACtD,IAAI,CAACxB,gBAAgBC,UAAU;QAC/ByC,sBAAsBlB,MAAMmB,aAAa1C,SAASwB;IACpD;IAEA,MAAM9B,qBAAqB6B;IAE3B,OAAO;QAAEC;IAAU;AACrB"}
1
+ {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/v1.0.0-rc.90/0004-python-test-input-scoping/migration.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 MigrationReturnObject,\n type ProjectConfiguration,\n readNxJson,\n type TargetConfiguration,\n type Tree,\n updateNxJson,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { PYTHON_TEST_FILE_EXCLUSIONS } from '../../../py/project/generator.js';\nimport { formatFilesInSubtree } from '../../../utils/format.js';\n\n/**\n * Editing a Python test file used to invalidate the whole build chain for its\n * project, and cascade into every downstream project. Two independent causes:\n *\n * 1. The `production` named input excluded TypeScript specs but nothing Python,\n * and the Python build targets read `default` (every file in the project), so\n * a test file was a build input by construction.\n * 2. `default` consumed *every* output of a dependency task. The Python `test`\n * target writes JUnit and coverage reports that pytest stamps wall-clock time\n * into, so each test run minted a new hash that propagated downstream.\n *\n * Targets whose output genuinely cannot contain a test file move to\n * `production`; `typecheck` deliberately stays on `default`, because `ty` checks\n * the tests directory and must re-run when a test changes.\n */\n\n/** The Python targets whose declared output cannot contain a test file. */\nconst PRODUCTION_SCOPED_TARGETS = ['compile', 'bundle-x86', 'bundle-arm'];\n\n/** The inputs those targets read once scoped to production sources. */\nconst PRODUCTION_INPUTS = ['production', '^production'];\n\n/** The inputs those targets previously read. */\nconst PREVIOUS_INPUTS = ['default', '^production'];\n\n/**\n * Dependent-task-output globs this plugin has vended. Any of them is rewritten\n * to the current one; anything else is the user's own scoping decision.\n */\nconst PREVIOUSLY_VENDED_GLOBS = ['**/*', 'dist/**'];\n\n/**\n * The dependent-task-output glob this migration shipped with at release. A\n * released migration's output must not change, so this is the literal value\n * rather than a reference to ts/lib/generator.ts's current constant, which a\n * later migration (cache-inputs-outputs) widens further and reports through\n * its own stale-pass advisory.\n */\nconst RELEASED_DEPENDENT_TASKS_OUTPUT_GLOB = '!{reports,coverage}/**';\n\nconst isPythonProject = (project: ProjectConfiguration): boolean =>\n Object.values(project.targets ?? {}).some((target) =>\n String(target?.executor ?? '').startsWith('@nxlv/python'),\n );\n\n/**\n * An OpenAPI spec generation target as the generators vend it: named `openapi`\n * or `<agent>-openapi`, running a command, and writing its spec under\n * `dist/.../openapi`. The extra checks keep a user-authored target that merely\n * shares the suffix from being rescoped, since these targets are identified by\n * declaring no `inputs` at all.\n */\nconst isOpenApiTarget = (\n name: string,\n target?: TargetConfiguration,\n): boolean => {\n if (name !== 'openapi' && !name.endsWith('-openapi')) return false;\n if (!target) return true;\n return (\n target.executor === 'nx:run-commands' &&\n (target.outputs ?? []).some((output) => output.includes('/openapi'))\n );\n};\n\nconst arraysEqual = (a: readonly unknown[], b: readonly unknown[]): boolean =>\n a.length === b.length && a.every((entry, index) => entry === b[index]);\n\n/**\n * Excludes Python test files from the `production` named input, and narrows the\n * dependent-task-output input so test reports no longer propagate downstream.\n */\nconst migrateNamedInputs = (tree: Tree, nextSteps: string[]): void => {\n const nxJson = readNxJson(tree);\n if (!nxJson) return;\n\n // Seeded as `['default']` when absent, exactly as the generator does. The\n // targets below are rewritten to read `production`, and Nx fails hard on a\n // named input that is not defined, so the two must not diverge.\n const production = nxJson.namedInputs?.production ?? ['default'];\n const nextProduction = [\n ...production,\n ...PYTHON_TEST_FILE_EXCLUSIONS.filter(\n (exclusion) => !production.includes(exclusion),\n ),\n ];\n\n const defaultInput = nxJson.namedInputs?.default;\n let nextDefault = defaultInput;\n if (defaultInput) {\n const glob = RELEASED_DEPENDENT_TASKS_OUTPUT_GLOB;\n // Only an entry this plugin vended is rewritten; a different glob is the\n // user's own scoping decision.\n nextDefault = defaultInput.map((input) =>\n typeof input === 'object' &&\n input !== null &&\n 'dependentTasksOutputFiles' in input &&\n PREVIOUSLY_VENDED_GLOBS.includes(\n input.dependentTasksOutputFiles as string,\n )\n ? { ...input, dependentTasksOutputFiles: glob }\n : input,\n );\n const hadVendedEntry = nextDefault.some(\n (input) =>\n typeof input === 'object' &&\n input !== null &&\n 'dependentTasksOutputFiles' in input &&\n input.dependentTasksOutputFiles === glob,\n );\n const hasCustomEntry = defaultInput.some(\n (input) =>\n typeof input === 'object' &&\n input !== null &&\n 'dependentTasksOutputFiles' in input &&\n !PREVIOUSLY_VENDED_GLOBS.includes(\n input.dependentTasksOutputFiles as string,\n ) &&\n input.dependentTasksOutputFiles !== glob,\n );\n if (!hadVendedEntry && hasCustomEntry) {\n nextSteps.push(\n `nx.json's 'default' named input scopes 'dependentTasksOutputFiles' to a custom glob — left untouched. Narrow it to '${glob}' so timestamped test reports do not invalidate downstream tasks.`,\n );\n }\n }\n\n updateNxJson(tree, {\n ...nxJson,\n namedInputs: {\n ...nxJson.namedInputs,\n production: nextProduction,\n ...(nextDefault ? { default: nextDefault } : {}),\n },\n });\n};\n\n/**\n * Scopes a Python project's build-chain targets to production sources. Only\n * targets still carrying the inputs the generator vended are rewritten, so a\n * project whose inputs the user has tuned is reported rather than clobbered.\n */\nconst migrateProjectTargets = (\n tree: Tree,\n projectName: string,\n project: ProjectConfiguration,\n nextSteps: string[],\n): void => {\n let changed = false;\n\n for (const [targetName, target] of Object.entries(project.targets ?? {})) {\n if (\n !PRODUCTION_SCOPED_TARGETS.includes(targetName) &&\n !isOpenApiTarget(targetName, target)\n ) {\n continue;\n }\n\n const inputs = target.inputs;\n\n // Already migrated, so a re-run is a no-op.\n if (inputs && arraysEqual(inputs as unknown[], PRODUCTION_INPUTS)) {\n continue;\n }\n\n // The OpenAPI targets declared no inputs at all, so they fell back to\n // `default`. Everything else carried the vended pair.\n const isVendedShape = inputs\n ? arraysEqual(inputs as unknown[], PREVIOUS_INPUTS)\n : isOpenApiTarget(targetName, target);\n\n if (!isVendedShape) {\n nextSteps.push(\n `${projectName}:${targetName}: 'inputs' has diverged from the generated shape — left untouched. Scope it to ['production', '^production'] so Python test edits do not invalidate it.`,\n );\n continue;\n }\n\n target.inputs = [...PRODUCTION_INPUTS];\n changed = true;\n }\n\n if (changed) {\n updateProjectConfiguration(tree, projectName, project);\n }\n};\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n migrateNamedInputs(tree, nextSteps);\n\n for (const [projectName, project] of getProjects(tree)) {\n if (!isPythonProject(project)) continue;\n migrateProjectTargets(tree, projectName, project, nextSteps);\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["getProjects","readNxJson","updateNxJson","updateProjectConfiguration","PYTHON_TEST_FILE_EXCLUSIONS","formatFilesInSubtree","PRODUCTION_SCOPED_TARGETS","PRODUCTION_INPUTS","PREVIOUS_INPUTS","PREVIOUSLY_VENDED_GLOBS","RELEASED_DEPENDENT_TASKS_OUTPUT_GLOB","isPythonProject","project","Object","values","targets","some","target","String","executor","startsWith","isOpenApiTarget","name","endsWith","outputs","output","includes","arraysEqual","a","b","length","every","entry","index","migrateNamedInputs","tree","nextSteps","nxJson","production","namedInputs","nextProduction","filter","exclusion","defaultInput","default","nextDefault","glob","map","input","dependentTasksOutputFiles","hadVendedEntry","hasCustomEntry","push","migrateProjectTargets","projectName","changed","targetName","entries","inputs","isVendedShape","migration"],"mappings":"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"}
@@ -46,12 +46,23 @@ const clientClassName = `${asyncPrefix}${className}`;
46
46
  const streamType = (item) => `${isAsync ? 'AsyncGenerator' : 'Iterator'}[${item}]`;
47
47
 
48
48
  /**
49
- * The `collections.abc` names the module imports. Async needs two — a
50
- * `AsyncGenerator` for an operation's stream and a separate `AsyncIterator` for
51
- * the `_stream_with_url` yield type — where sync spells both `Iterator`.
49
+ * The `collections.abc` names the module imports. `_stream_with_url` is
50
+ * decorated `@contextmanager`/`@asynccontextmanager`, which must be annotated
51
+ * `Generator`/`AsyncGenerator` rather than `Iterator`/`AsyncIterator` — a type
52
+ * checker (e.g. `ty`) rejects the iterator form on a context-manager function.
53
+ * Async spells both names `AsyncGenerator`; sync needs both `Iterator` (an
54
+ * operation's stream) and `Generator` (the context manager).
52
55
  */
53
56
  const streamAbc = isAsync ? 'AsyncGenerator' : 'Iterator';
54
- const contextAbc = isAsync ? 'AsyncIterator' : 'Iterator';
57
+ const contextAbcName = isAsync ? 'AsyncGenerator' : 'Generator';
58
+
59
+ /**
60
+ * The declared return type of a `@contextmanager`/`@asynccontextmanager`
61
+ * function. `AsyncGenerator` takes a send type, `Generator` also takes a
62
+ * return type — both left as `None` since nothing here uses either.
63
+ */
64
+ const contextReturnType = (item) =>
65
+ isAsync ? `AsyncGenerator[${item}, None]` : `Generator[${item}, None, None]`;
55
66
 
56
67
  const resultTypeFor = (op) => {
57
68
  if (op.isStreaming) {
@@ -329,7 +340,7 @@ const tagGroups = operationsByTag;
329
340
  const hasContentJsonParams = allOperations.some(op => (op.parameters || []).some(p => p.in !== 'body' && p.mediaType === 'application/json'));
330
341
  const hasPartContentTypes = allOperations.some(op => op.parametersBody && op.parametersBody.partContentTypes);
331
342
  const hasAllowReservedParams = allOperations.some(op => (op.parameters || []).some(p => p.in === 'query' && p.allowReserved));
332
- const abcImports = [...new Set([streamAbc, ...(hasAllowReservedParams ? [contextAbc] : [])])].join(', ');
343
+ const abcImports = [...new Set([streamAbc, ...(hasAllowReservedParams ? [contextAbcName] : [])])].join(', ');
333
344
  // A response declaring several media types is read through `_json_body`.
334
345
  const hasMultiMediaResponse = allOperations.some(op => (op.responses || []).some(r => (r.mediaTypes || []).length > 1));
335
346
  // An untyped streamed item is decoded with `json.loads`, which needs the import.
@@ -681,7 +692,7 @@ class <%- clientClassName %>:
681
692
  @<%- contextManager %>
682
693
  <%- kw.def %> _stream_with_url(
683
694
  self, final_url: str, **kwargs: Any
684
- ) -> <%- contextAbc %>[httpx.Response]:
695
+ ) -> <%- contextReturnType('httpx.Response') %>:
685
696
  # The streaming counterpart of `_send_with_url`: `stream()` would rebuild
686
697
  # the query from the client's params and percent-encode a hand-built one.
687
698
  request = self._client.build_request(**kwargs)
@@ -739,7 +739,7 @@ exports[`py#dynamodb generator > should generate the dynamodb project > packages
739
739
 
740
740
  from pynamodb.attributes import DiscriminatorAttribute, UnicodeAttribute
741
741
  from pynamodb.indexes import AllProjection, GlobalSecondaryIndex
742
- from pynamodb.models import Model
742
+ from pynamodb.models import MetaProtocol, Model
743
743
 
744
744
  from ..client import _local_dev, get_table_name, is_local
745
745
 
@@ -775,7 +775,7 @@ class BaseModel(Model):
775
775
  See https://pynamodb.readthedocs.io/en/stable/polymorphism.html
776
776
  """
777
777
 
778
- class Meta:
778
+ class Meta(MetaProtocol):
779
779
  table_name: str
780
780
  region = os.environ.get("AWS_REGION", "us-east-1")
781
781
  host = f"http://localhost:{_local_dev()['port']}" if is_local() else None
@@ -1459,7 +1459,7 @@ exports[`py#dynamodb generator > should generate with infra=none then upgrade to
1459
1459
 
1460
1460
  from pynamodb.attributes import DiscriminatorAttribute, UnicodeAttribute
1461
1461
  from pynamodb.indexes import AllProjection, GlobalSecondaryIndex
1462
- from pynamodb.models import Model
1462
+ from pynamodb.models import MetaProtocol, Model
1463
1463
 
1464
1464
  from ..client import _local_dev, get_table_name, is_local
1465
1465
 
@@ -1495,7 +1495,7 @@ class BaseModel(Model):
1495
1495
  See https://pynamodb.readthedocs.io/en/stable/polymorphism.html
1496
1496
  """
1497
1497
 
1498
- class Meta:
1498
+ class Meta(MetaProtocol):
1499
1499
  table_name: str
1500
1500
  region = os.environ.get("AWS_REGION", "us-east-1")
1501
1501
  host = f"http://localhost:{_local_dev()['port']}" if is_local() else None
@@ -2,7 +2,7 @@ import os
2
2
 
3
3
  from pynamodb.attributes import DiscriminatorAttribute, UnicodeAttribute
4
4
  from pynamodb.indexes import AllProjection, GlobalSecondaryIndex
5
- from pynamodb.models import Model
5
+ from pynamodb.models import MetaProtocol, Model
6
6
 
7
7
  from ..client import _local_dev, get_table_name, is_local
8
8
 
@@ -38,7 +38,7 @@ class BaseModel(Model):
38
38
  See https://pynamodb.readthedocs.io/en/stable/polymorphism.html
39
39
  """
40
40
 
41
- class Meta:
41
+ class Meta(MetaProtocol):
42
42
  table_name: str
43
43
  region = os.environ.get("AWS_REGION", 'us-east-1')
44
44
  host = f"http://localhost:{_local_dev()['port']}" if is_local() else None
@@ -35,6 +35,7 @@ exports[`smithyProjectGenerator > shape libraries > should generate a shape libr
35
35
  },
36
36
  "compile": {
37
37
  "cache": true,
38
+ "inputs": ["default"],
38
39
  "outputs": [
39
40
  "{workspaceRoot}/dist/{projectRoot}/smithy",
40
41
  "{workspaceRoot}/dist/{projectRoot}/build/model.json"
@@ -112,6 +113,7 @@ exports[`smithyProjectGenerator > should generate smithy project with all custom
112
113
  },
113
114
  "compile": {
114
115
  "cache": true,
116
+ "inputs": ["default"],
115
117
  "outputs": [
116
118
  "{workspaceRoot}/dist/{projectRoot}/smithy",
117
119
  "{workspaceRoot}/dist/{projectRoot}/build/openapi"
@@ -132,6 +134,7 @@ exports[`smithyProjectGenerator > should generate smithy project with all custom
132
134
  },
133
135
  "generate-ssdk": {
134
136
  "cache": true,
137
+ "inputs": ["default"],
135
138
  "outputs": ["{workspaceRoot}/dist/{projectRoot}/build/ssdk"],
136
139
  "executor": "nx:run-commands",
137
140
  "dependsOn": ["compile"],
@@ -170,6 +173,7 @@ exports[`smithyProjectGenerator > should generate smithy project with custom dir
170
173
  },
171
174
  "compile": {
172
175
  "cache": true,
176
+ "inputs": ["default"],
173
177
  "outputs": [
174
178
  "{workspaceRoot}/dist/{projectRoot}/smithy",
175
179
  "{workspaceRoot}/dist/{projectRoot}/build/openapi"
@@ -190,6 +194,7 @@ exports[`smithyProjectGenerator > should generate smithy project with custom dir
190
194
  },
191
195
  "generate-ssdk": {
192
196
  "cache": true,
197
+ "inputs": ["default"],
193
198
  "outputs": ["{workspaceRoot}/dist/{projectRoot}/build/ssdk"],
194
199
  "executor": "nx:run-commands",
195
200
  "dependsOn": ["compile"],
@@ -320,6 +325,7 @@ exports[`smithyProjectGenerator > should generate smithy project with default op
320
325
  },
321
326
  "compile": {
322
327
  "cache": true,
328
+ "inputs": ["default"],
323
329
  "outputs": [
324
330
  "{workspaceRoot}/dist/{projectRoot}/smithy",
325
331
  "{workspaceRoot}/dist/{projectRoot}/build/openapi"
@@ -340,6 +346,7 @@ exports[`smithyProjectGenerator > should generate smithy project with default op
340
346
  },
341
347
  "generate-ssdk": {
342
348
  "cache": true,
349
+ "inputs": ["default"],
343
350
  "outputs": ["{workspaceRoot}/dist/{projectRoot}/build/ssdk"],
344
351
  "executor": "nx:run-commands",
345
352
  "dependsOn": ["compile"],
@@ -464,6 +471,7 @@ exports[`smithyProjectGenerator > should generate smithy project with subdirecto
464
471
  },
465
472
  "compile": {
466
473
  "cache": true,
474
+ "inputs": ["default"],
467
475
  "outputs": [
468
476
  "{workspaceRoot}/dist/{projectRoot}/smithy",
469
477
  "{workspaceRoot}/dist/{projectRoot}/build/openapi"
@@ -484,6 +492,7 @@ exports[`smithyProjectGenerator > should generate smithy project with subdirecto
484
492
  },
485
493
  "generate-ssdk": {
486
494
  "cache": true,
495
+ "inputs": ["default"],
487
496
  "outputs": ["{workspaceRoot}/dist/{projectRoot}/build/ssdk"],
488
497
  "executor": "nx:run-commands",
489
498
  "dependsOn": ["compile"],
@@ -62,12 +62,21 @@ export declare const smithyGenerateSsdkCommands: () => string[];
62
62
  * restoring `compile` from cache would otherwise discard the Server SDK beside it.
63
63
  */
64
64
  export declare const smithyCompileOutputs: (type: SmithyProjectGeneratorSchema["type"]) => string[];
65
+ /**
66
+ * What a Smithy build target hashes: its own sources plus the outputs of the
67
+ * tasks it depends on. That covers a consumed shape library's output only
68
+ * when nx.json's `default` named input carries the `dependentTasksOutputFiles`
69
+ * entry, which only ts/lib/generator.ts writes - a Smithy-only workspace has
70
+ * no such entry, so `default` falls back to Nx's `{projectRoot}/**\/*`.
71
+ */
72
+ export declare const SMITHY_TARGET_INPUTS: string[];
65
73
  /**
66
74
  * The target that builds a service's Server SDK, shared with the migration moving
67
75
  * an existing project onto it.
68
76
  */
69
77
  export declare const smithyGenerateSsdkTarget: () => {
70
78
  cache: boolean;
79
+ inputs: string[];
71
80
  outputs: string[];
72
81
  executor: string;
73
82
  dependsOn: string[];
@@ -112,11 +112,23 @@ const BUILD_DIR = 'dist/{projectRoot}/build';
112
112
  `{workspaceRoot}/${SMITHY_OUT_DIR}`,
113
113
  type === 'shapes' ? `{workspaceRoot}/${BUILD_DIR}/model.json` : `{workspaceRoot}/${BUILD_DIR}/openapi`
114
114
  ];
115
+ /**
116
+ * What a Smithy build target hashes: its own sources plus the outputs of the
117
+ * tasks it depends on. That covers a consumed shape library's output only
118
+ * when nx.json's `default` named input carries the `dependentTasksOutputFiles`
119
+ * entry, which only ts/lib/generator.ts writes - a Smithy-only workspace has
120
+ * no such entry, so `default` falls back to Nx's `{projectRoot}/**\/*`.
121
+ */ export const SMITHY_TARGET_INPUTS = [
122
+ 'default'
123
+ ];
115
124
  /**
116
125
  * The target that builds a service's Server SDK, shared with the migration moving
117
126
  * an existing project onto it.
118
127
  */ export const smithyGenerateSsdkTarget = ()=>({
119
128
  cache: true,
129
+ inputs: [
130
+ ...SMITHY_TARGET_INPUTS
131
+ ],
120
132
  outputs: [
121
133
  `{workspaceRoot}/${BUILD_DIR}/ssdk`
122
134
  ],
@@ -176,6 +188,9 @@ export const smithyProjectGenerator = async (tree, options)=>{
176
188
  },
177
189
  compile: {
178
190
  cache: true,
191
+ inputs: [
192
+ ...SMITHY_TARGET_INPUTS
193
+ ],
179
194
  outputs: smithyCompileOutputs(type),
180
195
  executor: 'nx:run-commands',
181
196
  options: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../packages/nx-plugin/src/smithy/project/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n addProjectConfiguration,\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type Tree,\n} from '@nx/devkit';\nimport { getTsLibDetails } from '../../ts/lib/generator.js';\nimport { addTsDependencies } from '../../utils/add-dependencies.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../utils/declared-dependencies.js';\nimport { formatFilesInSubtree } from '../../utils/format.js';\nimport { FS_DEPENDENCIES, FsCommands } from '../../utils/fs.js';\nimport { installDependencies } from '../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics.js';\nimport { toClassName, toKebabCase } from '../../utils/names.js';\nimport { getNpmScope } from '../../utils/npm-scope.js';\nimport {\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n projectExists,\n} from '../../utils/nx.js';\nimport { getRelativePathToRootByDirectory } from '../../utils/paths.js';\nimport {\n smithyCliCommand,\n smithyMavenVersions,\n warnIfSmithyMissing,\n} from '../../utils/smithy.js';\nimport type { SmithyProjectGeneratorSchema } from './schema';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface SmithyProjectMetadata {\n readonly smithyType: NonNullable<SmithyProjectGeneratorSchema['type']>;\n readonly namespace: string;\n}\n\n/**\n * Only a service project generates a Server SDK, so only a service needs the\n * bundler that turns it into the single module its backend imports. A shape\n * library assembles a model and stops.\n */\nconst isService = (metadata: SmithyProjectMetadata) =>\n metadata.smithyType === 'service';\n\n/**\n * Everything a Smithy build runs, all of it workspace tooling in the root\n * manifest rather than anything the model itself imports.\n *\n * Neither the Smithy CLI nor `mise` is among them: the compile target fetches mise\n * with `npx` and mise resolves the CLI, so neither is a workspace dependency — see\n * `utils/smithy.ts`.\n */\nexport const DEPENDENCIES = declareDependencies<SmithyProjectMetadata>()({\n ts: [\n // Added to the root by `FsCommands` as it builds each command.\n ...ownedElsewhere(FS_DEPENDENCIES),\n { name: 'rolldown', dev: true, root: true, when: isService },\n { name: 'rolldown-plugin-dts', dev: true, root: true, when: isService },\n // Resolved by `rolldown-plugin-dts` to emit the bundled declaration.\n { name: 'typescript', dev: true, root: true, when: isService },\n ],\n});\n\nexport const SMITHY_PROJECT_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\n/**\n * Where the Smithy CLI writes its artifacts, and where the build publishes the\n * ones consumers read. Both sit under `dist` so a build writes nothing into the\n * project, keeping the source tree clean and the target's outputs cacheable.\n *\n * The CLI's own output is kept beside the published tree rather than inside it:\n * it holds the generated SSDK package and its installed `node_modules`, which\n * must not be mistaken for a build artifact.\n */\nconst SMITHY_OUT_DIR = 'dist/{projectRoot}/smithy';\nconst BUILD_DIR = 'dist/{projectRoot}/build';\n\n/** The projection every generated `smithy-build.json` builds. */\nconst SOURCE_PROJECTION = `${SMITHY_OUT_DIR}/source`;\n\n/** Where the generated TypeScript Server SDK lands before it is bundled. */\nconst SSDK_CODEGEN_DIR = `${SOURCE_PROJECTION}/typescript-ssdk-codegen`;\n\n/**\n * The commands that build a Smithy project's model, run from the workspace root.\n *\n * This is the whole of a shape library's build. A service's Server SDK is built\n * separately by {@link smithyGenerateSsdkCommands}, from the codegen output this\n * leaves under {@link SMITHY_OUT_DIR}.\n */\nexport const smithyCompileCommands = (\n cmd: FsCommands<typeof DEPENDENCIES>,\n type: SmithyProjectGeneratorSchema['type'],\n): string[] => [\n cmd.rm(BUILD_DIR),\n cmd.rm(SMITHY_OUT_DIR),\n cmd.mkdir(BUILD_DIR),\n // `imports` in smithy-build.json resolve relative to that file, so a shape\n // library is referenced by its path from the consuming project.\n `${smithyCliCommand()} build -c {projectRoot}/smithy-build.json --output ${SMITHY_OUT_DIR}`,\n ...(type === 'shapes'\n ? [\n cmd.cpFile(\n `${SOURCE_PROJECTION}/model/model.json`,\n `${BUILD_DIR}/model.json`,\n ),\n ]\n : [\n cmd.mkdir(`${BUILD_DIR}/openapi`),\n // Named after the service shape by the OpenAPI plugin, so it is matched\n // rather than named, and published under a stable name.\n cmd.cpGlobToFile(\n `${SOURCE_PROJECTION}/openapi/*.openapi.json`,\n `${BUILD_DIR}/openapi`,\n 'openapi.json',\n ),\n ]),\n];\n\n/**\n * The commands that turn a service's generated TypeScript Server SDK into the\n * single module its consumer imports, run from the workspace root.\n *\n * Only a service has one, and it reads what the model build left behind, so this\n * runs after `compile`.\n */\nexport const smithyGenerateSsdkCommands = (): string[] => [\n // `npm` regardless of the workspace's package manager: this installs a generated\n // package under `dist` that is not a workspace member, and npm ships with Node so\n // it is always present. It reads the user's `.npmrc`, so a private registry still\n // applies. `--include=dev` because the bundler resolves types from the generated\n // package's devDependencies, which `NODE_ENV=production` would otherwise omit.\n `npm install --prefix ${SSDK_CODEGEN_DIR} --include=dev --ignore-scripts --no-audit --no-fund`,\n // Bundled straight from the generated TypeScript sources, emitting the module and\n // its declarations together — see ssdk.rolldown.config.mjs for why the sources\n // rather than a `tsc` pre-pass.\n `rolldown -c {projectRoot}/ssdk.rolldown.config.mjs`,\n];\n\n/**\n * What the model build publishes, listed per artifact rather than as the whole\n * `build` directory: a service's `generate-ssdk` writes into that directory too, and\n * restoring `compile` from cache would otherwise discard the Server SDK beside it.\n */\nexport const smithyCompileOutputs = (\n type: SmithyProjectGeneratorSchema['type'],\n): string[] => [\n `{workspaceRoot}/${SMITHY_OUT_DIR}`,\n type === 'shapes'\n ? `{workspaceRoot}/${BUILD_DIR}/model.json`\n : `{workspaceRoot}/${BUILD_DIR}/openapi`,\n];\n\n/**\n * The target that builds a service's Server SDK, shared with the migration moving\n * an existing project onto it.\n */\nexport const smithyGenerateSsdkTarget = () => ({\n cache: true,\n outputs: [`{workspaceRoot}/${BUILD_DIR}/ssdk`],\n executor: 'nx:run-commands',\n dependsOn: ['compile'],\n options: {\n commands: smithyGenerateSsdkCommands(),\n parallel: false,\n cwd: '{workspaceRoot}',\n },\n});\n\n/**\n * Write the rolldown config that bundles a service's generated Server SDK.\n *\n * Shared with the migration moving an existing project off the container build,\n * so a migrated project's config cannot drift from a freshly generated one.\n */\nexport const writeSsdkBundleConfig = (tree: Tree, projectRoot: string): void =>\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'ssdk-bundle'),\n projectRoot,\n // The config's paths are workspace-root relative, so it needs only the\n // project's root — the compile target runs from the workspace root.\n { projectRoot },\n // Generated configuration rather than anything the user edits, so a re-run\n // refreshes it — unlike the models beside it.\n { overwriteStrategy: OverwriteStrategy.Overwrite },\n );\n\nexport const smithyProjectGenerator = async (\n tree: Tree,\n options: SmithyProjectGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const cmd = new FsCommands(tree, DEPENDENCIES);\n const type = options.type ?? 'service';\n\n // Create project.json\n const { fullyQualifiedName, dir } = getTsLibDetails(tree, options);\n\n if (!projectExists(tree, fullyQualifiedName)) {\n addProjectConfiguration(tree, fullyQualifiedName, {\n name: fullyQualifiedName,\n root: dir,\n sourceRoot: joinPathFragments(dir, 'src'),\n projectType: 'library',\n targets: {\n build: {\n dependsOn:\n type === 'shapes' ? ['compile'] : ['compile', 'generate-ssdk'],\n },\n // Everything this project's build does is artifact production, so\n // `assemble` carries the same dependencies.\n assemble: {\n dependsOn:\n type === 'shapes' ? ['compile'] : ['compile', 'generate-ssdk'],\n },\n compile: {\n cache: true,\n outputs: smithyCompileOutputs(type),\n executor: 'nx:run-commands',\n options: {\n commands: smithyCompileCommands(cmd, type),\n parallel: false,\n cwd: '{workspaceRoot}',\n },\n },\n // Only a service generates a Server SDK, and it is built from what the\n // model build leaves behind.\n ...(type === 'shapes'\n ? {}\n : { 'generate-ssdk': smithyGenerateSsdkTarget() }),\n },\n });\n }\n\n const serviceName = options.serviceName ?? options.name;\n const serviceNameClassName = toClassName(serviceName);\n const serviceNameKebabCase = toKebabCase(serviceName);\n const scope = getNpmScope(tree);\n const namespace = options.namespace ?? toKebabCase(scope).replace(/-/g, '.');\n\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', type),\n dir,\n {\n namespace,\n serviceNameClassName,\n serviceNameKebabCase,\n scope,\n projectRoot: dir,\n relativePathToWorkspaceRoot: getRelativePathToRootByDirectory(dir),\n ...smithyMavenVersions(),\n },\n {\n // Smithy models are user-owned — a re-run must not discard edits\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n if (type === 'service') {\n writeSsdkBundleConfig(tree, dir);\n }\n\n // Recorded here and read by the declaration's predicates, so the packages\n // added below are exactly the ones the version sync will own.\n const metadata: SmithyProjectMetadata = { smithyType: type, namespace };\n\n addGeneratorMetadata(\n tree,\n fullyQualifiedName,\n SMITHY_PROJECT_GENERATOR_INFO,\n {\n ...metadata,\n ...(type === 'service' ? { apiName: options.name } : {}),\n },\n );\n\n // No projectRoot: a Smithy model project has no manifest of its own, and every\n // dependency here is workspace tooling the build runs rather than anything the\n // model imports.\n addTsDependencies(tree, DEPENDENCIES, { metadata });\n\n await addGeneratorMetricsIfApplicable(tree, [SMITHY_PROJECT_GENERATOR_INFO]);\n\n // On Windows the build runs the Smithy CLI from the PATH rather than through\n // mise, so flag a missing prerequisite while the project is still being set up.\n warnIfSmithyMissing();\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\nexport default smithyProjectGenerator;\n"],"names":["addProjectConfiguration","generateFiles","joinPathFragments","OverwriteStrategy","getTsLibDetails","addTsDependencies","declareDependencies","ownedElsewhere","formatFilesInSubtree","FS_DEPENDENCIES","FsCommands","installDependencies","addGeneratorMetricsIfApplicable","toClassName","toKebabCase","getNpmScope","addGeneratorMetadata","getGeneratorInfo","projectExists","getRelativePathToRootByDirectory","smithyCliCommand","smithyMavenVersions","warnIfSmithyMissing","isService","metadata","smithyType","DEPENDENCIES","ts","name","dev","root","when","SMITHY_PROJECT_GENERATOR_INFO","filename","SMITHY_OUT_DIR","BUILD_DIR","SOURCE_PROJECTION","SSDK_CODEGEN_DIR","smithyCompileCommands","cmd","type","rm","mkdir","cpFile","cpGlobToFile","smithyGenerateSsdkCommands","smithyCompileOutputs","smithyGenerateSsdkTarget","cache","outputs","executor","dependsOn","options","commands","parallel","cwd","writeSsdkBundleConfig","tree","projectRoot","dirname","overwriteStrategy","Overwrite","smithyProjectGenerator","fullyQualifiedName","dir","sourceRoot","projectType","targets","build","assemble","compile","serviceName","serviceNameClassName","serviceNameKebabCase","scope","namespace","replace","relativePathToWorkspaceRoot","KeepExisting","apiName","preferInstallDependencies","languages"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/smithy/project/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n addProjectConfiguration,\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type Tree,\n} from '@nx/devkit';\nimport { getTsLibDetails } from '../../ts/lib/generator.js';\nimport { addTsDependencies } from '../../utils/add-dependencies.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../utils/declared-dependencies.js';\nimport { formatFilesInSubtree } from '../../utils/format.js';\nimport { FS_DEPENDENCIES, FsCommands } from '../../utils/fs.js';\nimport { installDependencies } from '../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics.js';\nimport { toClassName, toKebabCase } from '../../utils/names.js';\nimport { getNpmScope } from '../../utils/npm-scope.js';\nimport {\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n projectExists,\n} from '../../utils/nx.js';\nimport { getRelativePathToRootByDirectory } from '../../utils/paths.js';\nimport {\n smithyCliCommand,\n smithyMavenVersions,\n warnIfSmithyMissing,\n} from '../../utils/smithy.js';\nimport type { SmithyProjectGeneratorSchema } from './schema';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface SmithyProjectMetadata {\n readonly smithyType: NonNullable<SmithyProjectGeneratorSchema['type']>;\n readonly namespace: string;\n}\n\n/**\n * Only a service project generates a Server SDK, so only a service needs the\n * bundler that turns it into the single module its backend imports. A shape\n * library assembles a model and stops.\n */\nconst isService = (metadata: SmithyProjectMetadata) =>\n metadata.smithyType === 'service';\n\n/**\n * Everything a Smithy build runs, all of it workspace tooling in the root\n * manifest rather than anything the model itself imports.\n *\n * Neither the Smithy CLI nor `mise` is among them: the compile target fetches mise\n * with `npx` and mise resolves the CLI, so neither is a workspace dependency — see\n * `utils/smithy.ts`.\n */\nexport const DEPENDENCIES = declareDependencies<SmithyProjectMetadata>()({\n ts: [\n // Added to the root by `FsCommands` as it builds each command.\n ...ownedElsewhere(FS_DEPENDENCIES),\n { name: 'rolldown', dev: true, root: true, when: isService },\n { name: 'rolldown-plugin-dts', dev: true, root: true, when: isService },\n // Resolved by `rolldown-plugin-dts` to emit the bundled declaration.\n { name: 'typescript', dev: true, root: true, when: isService },\n ],\n});\n\nexport const SMITHY_PROJECT_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\n/**\n * Where the Smithy CLI writes its artifacts, and where the build publishes the\n * ones consumers read. Both sit under `dist` so a build writes nothing into the\n * project, keeping the source tree clean and the target's outputs cacheable.\n *\n * The CLI's own output is kept beside the published tree rather than inside it:\n * it holds the generated SSDK package and its installed `node_modules`, which\n * must not be mistaken for a build artifact.\n */\nconst SMITHY_OUT_DIR = 'dist/{projectRoot}/smithy';\nconst BUILD_DIR = 'dist/{projectRoot}/build';\n\n/** The projection every generated `smithy-build.json` builds. */\nconst SOURCE_PROJECTION = `${SMITHY_OUT_DIR}/source`;\n\n/** Where the generated TypeScript Server SDK lands before it is bundled. */\nconst SSDK_CODEGEN_DIR = `${SOURCE_PROJECTION}/typescript-ssdk-codegen`;\n\n/**\n * The commands that build a Smithy project's model, run from the workspace root.\n *\n * This is the whole of a shape library's build. A service's Server SDK is built\n * separately by {@link smithyGenerateSsdkCommands}, from the codegen output this\n * leaves under {@link SMITHY_OUT_DIR}.\n */\nexport const smithyCompileCommands = (\n cmd: FsCommands<typeof DEPENDENCIES>,\n type: SmithyProjectGeneratorSchema['type'],\n): string[] => [\n cmd.rm(BUILD_DIR),\n cmd.rm(SMITHY_OUT_DIR),\n cmd.mkdir(BUILD_DIR),\n // `imports` in smithy-build.json resolve relative to that file, so a shape\n // library is referenced by its path from the consuming project.\n `${smithyCliCommand()} build -c {projectRoot}/smithy-build.json --output ${SMITHY_OUT_DIR}`,\n ...(type === 'shapes'\n ? [\n cmd.cpFile(\n `${SOURCE_PROJECTION}/model/model.json`,\n `${BUILD_DIR}/model.json`,\n ),\n ]\n : [\n cmd.mkdir(`${BUILD_DIR}/openapi`),\n // Named after the service shape by the OpenAPI plugin, so it is matched\n // rather than named, and published under a stable name.\n cmd.cpGlobToFile(\n `${SOURCE_PROJECTION}/openapi/*.openapi.json`,\n `${BUILD_DIR}/openapi`,\n 'openapi.json',\n ),\n ]),\n];\n\n/**\n * The commands that turn a service's generated TypeScript Server SDK into the\n * single module its consumer imports, run from the workspace root.\n *\n * Only a service has one, and it reads what the model build left behind, so this\n * runs after `compile`.\n */\nexport const smithyGenerateSsdkCommands = (): string[] => [\n // `npm` regardless of the workspace's package manager: this installs a generated\n // package under `dist` that is not a workspace member, and npm ships with Node so\n // it is always present. It reads the user's `.npmrc`, so a private registry still\n // applies. `--include=dev` because the bundler resolves types from the generated\n // package's devDependencies, which `NODE_ENV=production` would otherwise omit.\n `npm install --prefix ${SSDK_CODEGEN_DIR} --include=dev --ignore-scripts --no-audit --no-fund`,\n // Bundled straight from the generated TypeScript sources, emitting the module and\n // its declarations together — see ssdk.rolldown.config.mjs for why the sources\n // rather than a `tsc` pre-pass.\n `rolldown -c {projectRoot}/ssdk.rolldown.config.mjs`,\n];\n\n/**\n * What the model build publishes, listed per artifact rather than as the whole\n * `build` directory: a service's `generate-ssdk` writes into that directory too, and\n * restoring `compile` from cache would otherwise discard the Server SDK beside it.\n */\nexport const smithyCompileOutputs = (\n type: SmithyProjectGeneratorSchema['type'],\n): string[] => [\n `{workspaceRoot}/${SMITHY_OUT_DIR}`,\n type === 'shapes'\n ? `{workspaceRoot}/${BUILD_DIR}/model.json`\n : `{workspaceRoot}/${BUILD_DIR}/openapi`,\n];\n\n/**\n * What a Smithy build target hashes: its own sources plus the outputs of the\n * tasks it depends on. That covers a consumed shape library's output only\n * when nx.json's `default` named input carries the `dependentTasksOutputFiles`\n * entry, which only ts/lib/generator.ts writes - a Smithy-only workspace has\n * no such entry, so `default` falls back to Nx's `{projectRoot}/**\\/*`.\n */\nexport const SMITHY_TARGET_INPUTS = ['default'];\n\n/**\n * The target that builds a service's Server SDK, shared with the migration moving\n * an existing project onto it.\n */\nexport const smithyGenerateSsdkTarget = () => ({\n cache: true,\n inputs: [...SMITHY_TARGET_INPUTS],\n outputs: [`{workspaceRoot}/${BUILD_DIR}/ssdk`],\n executor: 'nx:run-commands',\n dependsOn: ['compile'],\n options: {\n commands: smithyGenerateSsdkCommands(),\n parallel: false,\n cwd: '{workspaceRoot}',\n },\n});\n\n/**\n * Write the rolldown config that bundles a service's generated Server SDK.\n *\n * Shared with the migration moving an existing project off the container build,\n * so a migrated project's config cannot drift from a freshly generated one.\n */\nexport const writeSsdkBundleConfig = (tree: Tree, projectRoot: string): void =>\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'ssdk-bundle'),\n projectRoot,\n // The config's paths are workspace-root relative, so it needs only the\n // project's root — the compile target runs from the workspace root.\n { projectRoot },\n // Generated configuration rather than anything the user edits, so a re-run\n // refreshes it — unlike the models beside it.\n { overwriteStrategy: OverwriteStrategy.Overwrite },\n );\n\nexport const smithyProjectGenerator = async (\n tree: Tree,\n options: SmithyProjectGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const cmd = new FsCommands(tree, DEPENDENCIES);\n const type = options.type ?? 'service';\n\n // Create project.json\n const { fullyQualifiedName, dir } = getTsLibDetails(tree, options);\n\n if (!projectExists(tree, fullyQualifiedName)) {\n addProjectConfiguration(tree, fullyQualifiedName, {\n name: fullyQualifiedName,\n root: dir,\n sourceRoot: joinPathFragments(dir, 'src'),\n projectType: 'library',\n targets: {\n build: {\n dependsOn:\n type === 'shapes' ? ['compile'] : ['compile', 'generate-ssdk'],\n },\n // Everything this project's build does is artifact production, so\n // `assemble` carries the same dependencies.\n assemble: {\n dependsOn:\n type === 'shapes' ? ['compile'] : ['compile', 'generate-ssdk'],\n },\n compile: {\n cache: true,\n inputs: [...SMITHY_TARGET_INPUTS],\n outputs: smithyCompileOutputs(type),\n executor: 'nx:run-commands',\n options: {\n commands: smithyCompileCommands(cmd, type),\n parallel: false,\n cwd: '{workspaceRoot}',\n },\n },\n // Only a service generates a Server SDK, and it is built from what the\n // model build leaves behind.\n ...(type === 'shapes'\n ? {}\n : { 'generate-ssdk': smithyGenerateSsdkTarget() }),\n },\n });\n }\n\n const serviceName = options.serviceName ?? options.name;\n const serviceNameClassName = toClassName(serviceName);\n const serviceNameKebabCase = toKebabCase(serviceName);\n const scope = getNpmScope(tree);\n const namespace = options.namespace ?? toKebabCase(scope).replace(/-/g, '.');\n\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', type),\n dir,\n {\n namespace,\n serviceNameClassName,\n serviceNameKebabCase,\n scope,\n projectRoot: dir,\n relativePathToWorkspaceRoot: getRelativePathToRootByDirectory(dir),\n ...smithyMavenVersions(),\n },\n {\n // Smithy models are user-owned — a re-run must not discard edits\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n if (type === 'service') {\n writeSsdkBundleConfig(tree, dir);\n }\n\n // Recorded here and read by the declaration's predicates, so the packages\n // added below are exactly the ones the version sync will own.\n const metadata: SmithyProjectMetadata = { smithyType: type, namespace };\n\n addGeneratorMetadata(\n tree,\n fullyQualifiedName,\n SMITHY_PROJECT_GENERATOR_INFO,\n {\n ...metadata,\n ...(type === 'service' ? { apiName: options.name } : {}),\n },\n );\n\n // No projectRoot: a Smithy model project has no manifest of its own, and every\n // dependency here is workspace tooling the build runs rather than anything the\n // model imports.\n addTsDependencies(tree, DEPENDENCIES, { metadata });\n\n await addGeneratorMetricsIfApplicable(tree, [SMITHY_PROJECT_GENERATOR_INFO]);\n\n // On Windows the build runs the Smithy CLI from the PATH rather than through\n // mise, so flag a missing prerequisite while the project is still being set up.\n warnIfSmithyMissing();\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\nexport default smithyProjectGenerator;\n"],"names":["addProjectConfiguration","generateFiles","joinPathFragments","OverwriteStrategy","getTsLibDetails","addTsDependencies","declareDependencies","ownedElsewhere","formatFilesInSubtree","FS_DEPENDENCIES","FsCommands","installDependencies","addGeneratorMetricsIfApplicable","toClassName","toKebabCase","getNpmScope","addGeneratorMetadata","getGeneratorInfo","projectExists","getRelativePathToRootByDirectory","smithyCliCommand","smithyMavenVersions","warnIfSmithyMissing","isService","metadata","smithyType","DEPENDENCIES","ts","name","dev","root","when","SMITHY_PROJECT_GENERATOR_INFO","filename","SMITHY_OUT_DIR","BUILD_DIR","SOURCE_PROJECTION","SSDK_CODEGEN_DIR","smithyCompileCommands","cmd","type","rm","mkdir","cpFile","cpGlobToFile","smithyGenerateSsdkCommands","smithyCompileOutputs","SMITHY_TARGET_INPUTS","smithyGenerateSsdkTarget","cache","inputs","outputs","executor","dependsOn","options","commands","parallel","cwd","writeSsdkBundleConfig","tree","projectRoot","dirname","overwriteStrategy","Overwrite","smithyProjectGenerator","fullyQualifiedName","dir","sourceRoot","projectType","targets","build","assemble","compile","serviceName","serviceNameClassName","serviceNameKebabCase","scope","namespace","replace","relativePathToWorkspaceRoot","KeepExisting","apiName","preferInstallDependencies","languages"],"mappings":"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"}
@@ -2165,6 +2165,7 @@ exports[`tsSmithyApiGenerator > should generate smithy ts api with default optio
2165
2165
  },
2166
2166
  "compile": {
2167
2167
  "cache": true,
2168
+ "inputs": ["default"],
2168
2169
  "outputs": [
2169
2170
  "{workspaceRoot}/dist/{projectRoot}/smithy",
2170
2171
  "{workspaceRoot}/dist/{projectRoot}/build/openapi"
@@ -2185,6 +2186,7 @@ exports[`tsSmithyApiGenerator > should generate smithy ts api with default optio
2185
2186
  },
2186
2187
  "generate-ssdk": {
2187
2188
  "cache": true,
2189
+ "inputs": ["default"],
2188
2190
  "outputs": ["{workspaceRoot}/dist/{projectRoot}/build/ssdk"],
2189
2191
  "executor": "nx:run-commands",
2190
2192
  "dependsOn": ["compile"],
@@ -231,12 +231,10 @@ export async function terraformProjectGenerator(tree, schema) {
231
231
  '^init'
232
232
  ]
233
233
  },
234
+ // Reads remote state, which no input can hash.
234
235
  output: {
235
236
  executor: 'nx:run-commands',
236
- cache: true,
237
- inputs: [
238
- 'default'
239
- ],
237
+ cache: false,
240
238
  options: {
241
239
  command: 'terraform output -json',
242
240
  forwardAllArgs: true,