@aws/nx-plugin 1.0.0-rc.40 → 1.0.0-rc.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/infra/app/__snapshots__/generator.spec.ts.snap +42 -0
- package/src/open-api/ts-client/generator.js.map +1 -1
- package/src/open-api/ts-hooks/generator.js.map +1 -1
- package/src/preset/__snapshots__/generator.spec.ts.snap +4 -1
- package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +1 -1
- package/src/py/project/generator.js +27 -0
- package/src/py/project/generator.js.map +1 -1
- package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +17 -0
- package/src/ts/lib/__snapshots__/generator.spec.ts.snap +51 -0
- package/src/ts/lib/biome.js +36 -3
- package/src/ts/lib/biome.js.map +1 -1
- package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +572 -195
- package/src/ts/sync/generator.js +0 -2
- package/src/ts/sync/generator.js.map +1 -1
- package/src/utils/ast.js.map +1 -1
- package/src/utils/files/terraform/src/core/asset-bucket/asset-bucket.tf.template +61 -70
- package/src/utils/format.d.ts +6 -0
- package/src/utils/format.js +62 -28
- package/src/utils/format.js.map +1 -1
- package/src/utils/versions.d.ts +1 -0
- package/src/utils/versions.js +1 -0
- package/src/utils/versions.js.map +1 -1
- package/src/utils/warm-ruff-cache.d.ts +8 -0
- package/src/utils/warm-ruff-cache.js +30 -0
- package/src/utils/warm-ruff-cache.js.map +1 -0
- package/src/utils/website-constructs/files/cdk/core/static-website.ts.template +127 -36
- package/src/utils/website-constructs/files/terraform/core/static-website/static-website.tf.template +77 -74
package/package.json
CHANGED
|
@@ -207,6 +207,24 @@ exports[`infra generator > should configure project.json with correct targets >
|
|
|
207
207
|
"cwd": "{projectRoot}",
|
|
208
208
|
},
|
|
209
209
|
},
|
|
210
|
+
"format": {
|
|
211
|
+
"cache": true,
|
|
212
|
+
"configurations": {
|
|
213
|
+
"fix": {
|
|
214
|
+
"command": "biome format --write {projectRoot}",
|
|
215
|
+
},
|
|
216
|
+
"skip-lint": {
|
|
217
|
+
"command": "node -e """,
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
"executor": "nx:run-commands",
|
|
221
|
+
"inputs": [
|
|
222
|
+
"biome",
|
|
223
|
+
],
|
|
224
|
+
"options": {
|
|
225
|
+
"command": "biome format {projectRoot}",
|
|
226
|
+
},
|
|
227
|
+
},
|
|
210
228
|
"lint": {
|
|
211
229
|
"cache": true,
|
|
212
230
|
"configurations": {
|
|
@@ -217,6 +235,9 @@ exports[`infra generator > should configure project.json with correct targets >
|
|
|
217
235
|
"command": "node -e """,
|
|
218
236
|
},
|
|
219
237
|
},
|
|
238
|
+
"dependsOn": [
|
|
239
|
+
"format",
|
|
240
|
+
],
|
|
220
241
|
"executor": "nx:run-commands",
|
|
221
242
|
"inputs": [
|
|
222
243
|
"biome",
|
|
@@ -763,6 +784,24 @@ exports[`infra generator > should handle custom project names correctly > custom
|
|
|
763
784
|
"cwd": "{projectRoot}",
|
|
764
785
|
},
|
|
765
786
|
},
|
|
787
|
+
"format": {
|
|
788
|
+
"cache": true,
|
|
789
|
+
"configurations": {
|
|
790
|
+
"fix": {
|
|
791
|
+
"command": "biome format --write {projectRoot}",
|
|
792
|
+
},
|
|
793
|
+
"skip-lint": {
|
|
794
|
+
"command": "node -e """,
|
|
795
|
+
},
|
|
796
|
+
},
|
|
797
|
+
"executor": "nx:run-commands",
|
|
798
|
+
"inputs": [
|
|
799
|
+
"biome",
|
|
800
|
+
],
|
|
801
|
+
"options": {
|
|
802
|
+
"command": "biome format {projectRoot}",
|
|
803
|
+
},
|
|
804
|
+
},
|
|
766
805
|
"lint": {
|
|
767
806
|
"cache": true,
|
|
768
807
|
"configurations": {
|
|
@@ -773,6 +812,9 @@ exports[`infra generator > should handle custom project names correctly > custom
|
|
|
773
812
|
"command": "node -e """,
|
|
774
813
|
},
|
|
775
814
|
},
|
|
815
|
+
"dependsOn": [
|
|
816
|
+
"format",
|
|
817
|
+
],
|
|
776
818
|
"executor": "nx:run-commands",
|
|
777
819
|
"inputs": [
|
|
778
820
|
"biome",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/open-api/ts-client/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { generateFiles, logger, type Tree } from '@nx/devkit';\nimport * as path from 'path';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { esmVars } from '../../utils/module-format';\nimport { buildOpenApiCodeGenData } from '../utils/codegen-data';\nimport type { CodeGenData } from '../utils/codegen-data/types';\nimport { parseOpenApiSpec } from '../utils/parse';\nimport type { Spec } from '../utils/types';\nimport type { OpenApiTsClientGeneratorSchema } from './schema';\n\n/**\n * Generates typescript client from an openapi spec\n */\nexport const openApiTsClientGenerator = async (\n tree: Tree,\n options: OpenApiTsClientGeneratorSchema,\n) => {\n const data = await buildOpenApiCodeGenerationData(\n tree,\n options.openApiSpecPath,\n );\n\n generateOpenApiTsClient(tree, data, options.outputPath);\n\n await formatFilesInSubtree(tree);\n};\n\n/**\n * Build a data structure which can be used to generate code from OpenAPI\n */\nexport const buildOpenApiCodeGenerationData = async (\n tree: Tree,\n specPath: string,\n) => {\n const spec = await parseOpenApiSpec(tree, specPath);\n warnForUnsupportedFeatures(spec);\n return buildOpenApiCodeGenData(spec);\n};\n\n/**\n * Warn for spec features the generated client does not implement, so their\n * omission is never silent.\n */\nconst warnForUnsupportedFeatures = (spec: Spec) => {\n if (Object.keys((spec as { webhooks?: object }).webhooks ?? {}).length > 0) {\n logger.warn(\n 'OpenAPI webhooks are not supported and no client code is generated for them',\n );\n }\n for (const [p, pathItem] of Object.entries(spec.paths ?? {})) {\n for (const [method, op] of Object.entries(pathItem ?? {})) {\n if (typeof op !== 'object' || op === null) continue;\n const operation = op as {\n callbacks?: object;\n servers?: unknown[];\n };\n if (Object.keys(operation.callbacks ?? {}).length > 0) {\n logger.warn(\n `Operation ${method.toUpperCase()} ${p} declares callbacks, which are not supported and are ignored`,\n );\n }\n if ((operation.servers ?? []).length > 0) {\n logger.warn(\n `Operation ${method.toUpperCase()} ${p} declares operation-level servers, which are ignored — the client always uses its configured url`,\n );\n }\n }\n }\n};\n\n/**\n * Generate an OpenAPI typescript client in the target directory\n */\nexport const generateOpenApiTsClient = (\n tree: Tree,\n data: CodeGenData,\n outputPath: string,\n) => {\n generateFiles(
|
|
1
|
+
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/open-api/ts-client/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { generateFiles, logger, type Tree } from '@nx/devkit';\nimport * as path from 'path';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { esmVars } from '../../utils/module-format';\nimport { buildOpenApiCodeGenData } from '../utils/codegen-data';\nimport type { CodeGenData } from '../utils/codegen-data/types';\nimport { parseOpenApiSpec } from '../utils/parse';\nimport type { Spec } from '../utils/types';\nimport type { OpenApiTsClientGeneratorSchema } from './schema';\n\n/**\n * Generates typescript client from an openapi spec\n */\nexport const openApiTsClientGenerator = async (\n tree: Tree,\n options: OpenApiTsClientGeneratorSchema,\n) => {\n const data = await buildOpenApiCodeGenerationData(\n tree,\n options.openApiSpecPath,\n );\n\n generateOpenApiTsClient(tree, data, options.outputPath);\n\n await formatFilesInSubtree(tree);\n};\n\n/**\n * Build a data structure which can be used to generate code from OpenAPI\n */\nexport const buildOpenApiCodeGenerationData = async (\n tree: Tree,\n specPath: string,\n) => {\n const spec = await parseOpenApiSpec(tree, specPath);\n warnForUnsupportedFeatures(spec);\n return buildOpenApiCodeGenData(spec);\n};\n\n/**\n * Warn for spec features the generated client does not implement, so their\n * omission is never silent.\n */\nconst warnForUnsupportedFeatures = (spec: Spec) => {\n if (Object.keys((spec as { webhooks?: object }).webhooks ?? {}).length > 0) {\n logger.warn(\n 'OpenAPI webhooks are not supported and no client code is generated for them',\n );\n }\n for (const [p, pathItem] of Object.entries(spec.paths ?? {})) {\n for (const [method, op] of Object.entries(pathItem ?? {})) {\n if (typeof op !== 'object' || op === null) continue;\n const operation = op as {\n callbacks?: object;\n servers?: unknown[];\n };\n if (Object.keys(operation.callbacks ?? {}).length > 0) {\n logger.warn(\n `Operation ${method.toUpperCase()} ${p} declares callbacks, which are not supported and are ignored`,\n );\n }\n if ((operation.servers ?? []).length > 0) {\n logger.warn(\n `Operation ${method.toUpperCase()} ${p} declares operation-level servers, which are ignored — the client always uses its configured url`,\n );\n }\n }\n }\n};\n\n/**\n * Generate an OpenAPI typescript client in the target directory\n */\nexport const generateOpenApiTsClient = (\n tree: Tree,\n data: CodeGenData,\n outputPath: string,\n) => {\n generateFiles(tree, path.join(import.meta.dirname, 'files'), outputPath, {\n ...data,\n ...esmVars(tree),\n });\n};\n\nexport default openApiTsClientGenerator;\n"],"names":["generateFiles","logger","path","formatFilesInSubtree","esmVars","buildOpenApiCodeGenData","parseOpenApiSpec","openApiTsClientGenerator","tree","options","data","buildOpenApiCodeGenerationData","openApiSpecPath","generateOpenApiTsClient","outputPath","specPath","spec","warnForUnsupportedFeatures","Object","keys","webhooks","length","warn","p","pathItem","entries","paths","method","op","operation","callbacks","toUpperCase","servers","join","dirname"],"mappings":"AAAA;;;CAGC,GACD,SAASA,aAAa,EAAEC,MAAM,QAAmB,aAAa;AAC9D,YAAYC,UAAU,OAAO;AAC7B,SAASC,oBAAoB,QAAQ,wBAAqB;AAC1D,SAASC,OAAO,QAAQ,+BAA4B;AACpD,SAASC,uBAAuB,QAAQ,2BAAwB;AAEhE,SAASC,gBAAgB,QAAQ,oBAAiB;AAIlD;;CAEC,GACD,OAAO,MAAMC,2BAA2B,OACtCC,MACAC;IAEA,MAAMC,OAAO,MAAMC,+BACjBH,MACAC,QAAQG,eAAe;IAGzBC,wBAAwBL,MAAME,MAAMD,QAAQK,UAAU;IAEtD,MAAMX,qBAAqBK;AAC7B,EAAE;AAEF;;CAEC,GACD,OAAO,MAAMG,iCAAiC,OAC5CH,MACAO;IAEA,MAAMC,OAAO,MAAMV,iBAAiBE,MAAMO;IAC1CE,2BAA2BD;IAC3B,OAAOX,wBAAwBW;AACjC,EAAE;AAEF;;;CAGC,GACD,MAAMC,6BAA6B,CAACD;IAClC,IAAIE,OAAOC,IAAI,CAAC,AAACH,KAA+BI,QAAQ,IAAI,CAAC,GAAGC,MAAM,GAAG,GAAG;QAC1EpB,OAAOqB,IAAI,CACT;IAEJ;IACA,KAAK,MAAM,CAACC,GAAGC,SAAS,IAAIN,OAAOO,OAAO,CAACT,KAAKU,KAAK,IAAI,CAAC,GAAI;QAC5D,KAAK,MAAM,CAACC,QAAQC,GAAG,IAAIV,OAAOO,OAAO,CAACD,YAAY,CAAC,GAAI;YACzD,IAAI,OAAOI,OAAO,YAAYA,OAAO,MAAM;YAC3C,MAAMC,YAAYD;YAIlB,IAAIV,OAAOC,IAAI,CAACU,UAAUC,SAAS,IAAI,CAAC,GAAGT,MAAM,GAAG,GAAG;gBACrDpB,OAAOqB,IAAI,CACT,CAAC,UAAU,EAAEK,OAAOI,WAAW,GAAG,CAAC,EAAER,EAAE,4DAA4D,CAAC;YAExG;YACA,IAAI,AAACM,CAAAA,UAAUG,OAAO,IAAI,EAAE,AAAD,EAAGX,MAAM,GAAG,GAAG;gBACxCpB,OAAOqB,IAAI,CACT,CAAC,UAAU,EAAEK,OAAOI,WAAW,GAAG,CAAC,EAAER,EAAE,gGAAgG,CAAC;YAE5I;QACF;IACF;AACF;AAEA;;CAEC,GACD,OAAO,MAAMV,0BAA0B,CACrCL,MACAE,MACAI;IAEAd,cAAcQ,MAAMN,KAAK+B,IAAI,CAAC,YAAYC,OAAO,EAAE,UAAUpB,YAAY;QACvE,GAAGJ,IAAI;QACP,GAAGN,QAAQI,KAAK;IAClB;AACF,EAAE;AAEF,eAAeD,yBAAyB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/open-api/ts-hooks/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { generateFiles, type Tree } from '@nx/devkit';\nimport path from 'path';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { esmVars } from '../../utils/module-format';\nimport {\n buildOpenApiCodeGenerationData,\n generateOpenApiTsClient,\n} from '../ts-client/generator';\nimport type { CodeGenData } from '../utils/codegen-data/types';\nimport type { OpenApiTsHooksGeneratorSchema } from './schema';\n\n/**\n * Generates typescript hooks from an openapi spec\n */\nexport const openApiTsHooksGenerator = async (\n tree: Tree,\n options: OpenApiTsHooksGeneratorSchema,\n) => {\n const data = await buildOpenApiCodeGenerationData(\n tree,\n options.openApiSpecPath,\n );\n\n generateOpenApiTsClient(tree, data, options.outputPath);\n generateOpenApiTsHooks(tree, data, options.outputPath);\n\n await formatFilesInSubtree(tree);\n};\n\n/**\n * Generate OpenAPI typescript hooks in the target directory\n */\nexport const generateOpenApiTsHooks = (\n tree: Tree,\n data: CodeGenData,\n outputPath: string,\n) => {\n generateFiles(
|
|
1
|
+
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/open-api/ts-hooks/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { generateFiles, type Tree } from '@nx/devkit';\nimport path from 'path';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { esmVars } from '../../utils/module-format';\nimport {\n buildOpenApiCodeGenerationData,\n generateOpenApiTsClient,\n} from '../ts-client/generator';\nimport type { CodeGenData } from '../utils/codegen-data/types';\nimport type { OpenApiTsHooksGeneratorSchema } from './schema';\n\n/**\n * Generates typescript hooks from an openapi spec\n */\nexport const openApiTsHooksGenerator = async (\n tree: Tree,\n options: OpenApiTsHooksGeneratorSchema,\n) => {\n const data = await buildOpenApiCodeGenerationData(\n tree,\n options.openApiSpecPath,\n );\n\n generateOpenApiTsClient(tree, data, options.outputPath);\n generateOpenApiTsHooks(tree, data, options.outputPath);\n\n await formatFilesInSubtree(tree);\n};\n\n/**\n * Generate OpenAPI typescript hooks in the target directory\n */\nexport const generateOpenApiTsHooks = (\n tree: Tree,\n data: CodeGenData,\n outputPath: string,\n) => {\n generateFiles(tree, path.join(import.meta.dirname, 'files'), outputPath, {\n ...data,\n ...esmVars(tree),\n });\n};\n\nexport default openApiTsHooksGenerator;\n"],"names":["generateFiles","path","formatFilesInSubtree","esmVars","buildOpenApiCodeGenerationData","generateOpenApiTsClient","openApiTsHooksGenerator","tree","options","data","openApiSpecPath","outputPath","generateOpenApiTsHooks","join","dirname"],"mappings":"AAAA;;;CAGC,GACD,SAASA,aAAa,QAAmB,aAAa;AACtD,OAAOC,UAAU,OAAO;AACxB,SAASC,oBAAoB,QAAQ,wBAAqB;AAC1D,SAASC,OAAO,QAAQ,+BAA4B;AACpD,SACEC,8BAA8B,EAC9BC,uBAAuB,QAClB,4BAAyB;AAIhC;;CAEC,GACD,OAAO,MAAMC,0BAA0B,OACrCC,MACAC;IAEA,MAAMC,OAAO,MAAML,+BACjBG,MACAC,QAAQE,eAAe;IAGzBL,wBAAwBE,MAAME,MAAMD,QAAQG,UAAU;IACtDC,uBAAuBL,MAAME,MAAMD,QAAQG,UAAU;IAErD,MAAMT,qBAAqBK;AAC7B,EAAE;AAEF;;CAEC,GACD,OAAO,MAAMK,yBAAyB,CACpCL,MACAE,MACAE;IAEAX,cAAcO,MAAMN,KAAKY,IAAI,CAAC,YAAYC,OAAO,EAAE,UAAUH,YAAY;QACvE,GAAGF,IAAI;QACP,GAAGN,QAAQI,KAAK;IAClB;AACF,EAAE;AAEF,eAAeD,wBAAwB"}
|
|
@@ -289,7 +289,10 @@ exports[`preset generator > should run successfully > biome.json 1`] = `
|
|
|
289
289
|
"!**/node_modules",
|
|
290
290
|
"!**/.nx",
|
|
291
291
|
"!**/.venv",
|
|
292
|
-
"!**/*.css"
|
|
292
|
+
"!**/*.css",
|
|
293
|
+
"!**/*.gen.*",
|
|
294
|
+
"!**/generated/**",
|
|
295
|
+
"!**/tsconfig*.json"
|
|
293
296
|
]
|
|
294
297
|
}
|
|
295
298
|
}
|
|
@@ -147,7 +147,7 @@ async def add_correlation_id(request: Request, call_next):
|
|
|
147
147
|
try:
|
|
148
148
|
lambda_context = json.loads(lambda_context_header)
|
|
149
149
|
corr_id = lambda_context.get("request_id")
|
|
150
|
-
except
|
|
150
|
+
except json.JSONDecodeError, KeyError:
|
|
151
151
|
pass
|
|
152
152
|
if not corr_id:
|
|
153
153
|
# If still empty, use uuid
|
|
@@ -191,9 +191,36 @@ const PYTHON_TRANSIENT_ARTIFACTS = [
|
|
|
191
191
|
}
|
|
192
192
|
return pyProjectToml;
|
|
193
193
|
});
|
|
194
|
+
// Pin ruff to the version generation-time formatting uses (PY_VERSIONS), so
|
|
195
|
+
// generated files stay `ruff format --check`-clean across ruff releases.
|
|
194
196
|
addDependenciesToDependencyGroupInPyProjectToml(tree, '.', 'dev', [
|
|
197
|
+
'ruff',
|
|
195
198
|
'ty'
|
|
196
199
|
]);
|
|
200
|
+
// Base format target checks rather than writes (so build/lint don't rewrite
|
|
201
|
+
// source); `fix` writes, and `skip-lint` writes without failing so it stays
|
|
202
|
+
// a no-op when propagated through the lint -> format dependency.
|
|
203
|
+
projectConfiguration.targets.format = {
|
|
204
|
+
...projectConfiguration.targets.format,
|
|
205
|
+
cache: true,
|
|
206
|
+
inputs: [
|
|
207
|
+
'default',
|
|
208
|
+
'^production'
|
|
209
|
+
],
|
|
210
|
+
options: {
|
|
211
|
+
...projectConfiguration.targets.format?.options,
|
|
212
|
+
check: true
|
|
213
|
+
},
|
|
214
|
+
configurations: {
|
|
215
|
+
...projectConfiguration.targets.format?.configurations,
|
|
216
|
+
fix: {
|
|
217
|
+
check: false
|
|
218
|
+
},
|
|
219
|
+
'skip-lint': {
|
|
220
|
+
check: false
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
};
|
|
197
224
|
// Add a dependency on the format target for lint in order to reduce the number of
|
|
198
225
|
// fixable lint errors (eg line too long)
|
|
199
226
|
projectConfiguration.targets.lint = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/py/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 addDependenciesToPackageJson,\n ensurePackage,\n type GeneratorCallback,\n joinPathFragments,\n readNxJson,\n readProjectConfiguration,\n type Tree,\n updateNxJson,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport {\n addLicenseCheckToLintTarget,\n ensurePythonLicenseCollector,\n} from '../../license/config';\nimport { updateGitIgnore } from '../../utils/git';\nimport { installDependencies } from '../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics';\nimport { normalizeDistributionName, toSnakeCase } from '../../utils/names';\nimport { getNpmScope } from '../../utils/npm-scope';\nimport {\n addDependencyToTargetIfNotPresent,\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n projectExists,\n} from '../../utils/nx';\nimport type { UVPyprojectToml } from '../../utils/nxlv-python';\nimport {\n migrateToSharedVenvGenerator,\n uvProjectGenerator,\n} from '../../utils/nxlv-python';\nimport { sortObjectKeys } from '../../utils/object';\nimport { addDependenciesToDependencyGroupInPyProjectToml } from '../../utils/py';\nimport { updateToml } from '../../utils/toml';\nimport { withVersions } from '../../utils/versions';\nimport type { PyProjectGeneratorSchema } from './schema';\n\nexport const PY_PROJECT_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\n// Transient artifacts that pytest, coverage and ruff create and remove while\n// the test, typecheck and compile targets run concurrently. `.coverage.*` are\n// the per-process data files pytest-cov writes (`.coverage.<host>.<pid>.<rand>`)\n// before combining them. Both `ty` (which respects .gitignore) and the\n// `@nxlv/python:build` copy (which respects `ignorePaths`) would otherwise fail\n// when they read one of these mid-deletion.\nconst PYTHON_TRANSIENT_ARTIFACTS = [\n '__pycache__',\n '.coverage',\n '.coverage.*',\n '.pytest_cache',\n 'pytest-cache-files-*',\n '.ruff_cache',\n];\n\nexport interface PyProjectDetails {\n /**\n * Fully qualified Nx project id including scope, in dot notation (eg foo.bar).\n * This is the identifier Nx uses (readProjectConfiguration, the project\n * graph, target references) and is intentionally kept dotted.\n */\n readonly fullyQualifiedName: string;\n /**\n * PEP 503 normalised Python distribution name (eg foo-bar). This is the name\n * written to the project's `[project].name`, the root `[tool.uv.sources]`\n * key, and any inter-project dependency string. It is hyphenated (not dotted)\n * so `uv` and `@nxlv/python` can match it: uv writes `uv.lock` keyed by the\n * PEP 503 hyphenated name, and `@nxlv/python`'s dependency inference splits a\n * dotted name on `.` and so would otherwise drop the edge entirely. Keeping\n * the distribution name decoupled from `fullyQualifiedName` is what lets the\n * workspace dependency edge appear in the Nx project graph.\n */\n readonly distributionName: string;\n /**\n * Directory of the library relative to the root\n */\n readonly dir: string;\n /**\n * Module name for the project\n */\n readonly normalizedModuleName: string;\n}\n\n/**\n * Returns details about the Python project to be created\n */\nexport const getPyProjectDetails = (\n tree: Tree,\n schema: {\n name: string;\n directory?: string;\n subDirectory?: string;\n moduleName?: string;\n },\n): PyProjectDetails => {\n const scope = toSnakeCase(getNpmScope(tree));\n const normalizedName = toSnakeCase(schema.name);\n const normalizedModuleName = toSnakeCase(\n schema.moduleName ?? `${scope}_${normalizedName}`,\n );\n const fullyQualifiedName = `${scope}.${normalizedName}`;\n // The Python distribution name is the PEP 503 normalised form of the\n // fully qualified name: hyphenated, never dotted. See PyProjectDetails.\n const distributionName = normalizeDistributionName(fullyQualifiedName);\n // NB: interactive nx generator cli can pass empty string\n const dir = joinPathFragments(\n schema.directory || '.',\n schema.subDirectory || normalizedName,\n );\n return { dir, fullyQualifiedName, distributionName, normalizedModuleName };\n};\n\n/**\n * Generates a Python project\n */\nexport const pyProjectGenerator = async (\n tree: Tree,\n schema: PyProjectGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const { dir, normalizedModuleName, fullyQualifiedName, distributionName } =\n getPyProjectDetails(tree, schema);\n\n const pythonPlugin = withVersions(['@nxlv/python']);\n addDependenciesToPackageJson(tree, {}, pythonPlugin);\n\n Object.entries(pythonPlugin).forEach(([name, version]) =>\n ensurePackage(name, version),\n );\n\n const nxJson = readNxJson(tree);\n\n // Only rewrite nx.json when the plugin needs adding, so re-running does not\n // reserialize (and reformat) the file when nothing has changed.\n if (\n !nxJson.plugins?.find((p) =>\n typeof p === 'string'\n ? p === '@nxlv/python'\n : p.plugin === '@nxlv/python',\n )\n ) {\n nxJson.plugins = [\n ...(nxJson.plugins ?? []),\n {\n plugin: '@nxlv/python',\n options: {\n packageManager: 'uv',\n },\n },\n ];\n updateNxJson(tree, nxJson);\n }\n\n // Only scaffold the project when it does not already exist so re-running with\n // the same name does not throw. The rest of the generator still runs to apply\n // any changed options to the existing project.\n if (!projectExists(tree, fullyQualifiedName)) {\n if (!tree.exists('uv.lock')) {\n await migrateToSharedVenvGenerator(tree, {\n autoActivate: true,\n packageManager: 'uv',\n moveDevDependencies: false,\n pyenvPythonVersion: '3.14.0',\n pyprojectPythonDependency: '>=3.14',\n });\n }\n\n await uvProjectGenerator(tree, {\n // The Nx project id (and `uv.workspace.members` etc.) keys off `name`, so\n // keep it dotted. `packageName` is the separate PEP 503 distribution name\n // written to `[project].name` and the root `[tool.uv.sources]` key; it is\n // hyphenated so `@nxlv/python` infers the workspace dependency edge (it\n // splits a dotted name on `.` and would otherwise drop it). This split is\n // the whole fix (see PyProjectDetails.distributionName).\n name: fullyQualifiedName,\n packageName: distributionName,\n publishable: false,\n buildLockedVersions: true,\n buildBundleLocalDependencies: true,\n linter: 'ruff',\n rootPyprojectDependencyGroup: 'main',\n pyenvPythonVersion: '3.14.0',\n pyprojectPythonDependency: '>=3.14',\n projectType: schema.type,\n projectNameAndRootFormat: 'as-provided',\n moduleName: normalizedModuleName,\n directory: dir,\n unitTestRunner: 'pytest',\n codeCoverage: true,\n codeCoverageHtmlReport: true,\n codeCoverageXmlReport: true,\n unitTestHtmlReport: true,\n unitTestJUnitReport: true,\n buildSystem: 'hatch',\n srcDir: false,\n });\n\n // Remove generated hello.py and test_hello.py as they are not needed\n [\n joinPathFragments(dir, normalizedModuleName, 'hello.py'),\n joinPathFragments(dir, 'tests', 'test_hello.py'),\n ].forEach((f) => tree.delete(f));\n\n // Add a placeholder test so pytest doesn't fail with \"no tests collected\"\n tree.write(\n joinPathFragments(dir, 'tests', 'test_noop.py'),\n 'def test_noop():\\n pass\\n',\n );\n }\n\n const outputPath = '{workspaceRoot}/dist/{projectRoot}';\n const buildOutputPath = joinPathFragments(outputPath, 'build');\n const projectConfiguration = readProjectConfiguration(\n tree,\n fullyQualifiedName,\n );\n projectConfiguration.name = fullyQualifiedName;\n // Derive the compile target from the uv build target, and rewrite build to\n // orchestrate the other targets. This only runs on first creation: on re-run\n // build has already been transformed, so re-deriving would corrupt compile\n // and duplicate the build dependencies.\n if (!projectConfiguration.targets.compile) {\n const buildTarget = projectConfiguration.targets.build;\n projectConfiguration.targets.compile = {\n ...buildTarget,\n inputs: ['default', '^production'],\n outputs: [buildOutputPath],\n options: {\n ...buildTarget.options,\n outputPath: buildOutputPath,\n // The build executor copies the project to a temp folder; exclude the\n // executor defaults plus transient artifacts so the copy does not race\n // a concurrent test/typecheck target deleting a file mid-copy.\n ignorePaths: ['.venv', '.tox', 'tests', ...PYTHON_TRANSIENT_ARTIFACTS],\n },\n };\n projectConfiguration.targets.build = {\n inputs: ['default', '^production'],\n dependsOn: [\n 'lint',\n 'compile',\n 'test',\n 'typecheck',\n ...(buildTarget.dependsOn ?? []),\n ],\n options: {\n outputPath,\n },\n };\n }\n projectConfiguration.targets.typecheck = {\n cache: true,\n inputs: ['default', '^production'],\n executor: '@nxlv/python:run-commands',\n options: {\n command: 'uv run ty check',\n cwd: '{projectRoot}',\n },\n };\n\n // Set the default line length to 120, as 88 is a little too strict\n updateToml(\n tree,\n joinPathFragments(dir, 'pyproject.toml'),\n (pyProjectToml: UVPyprojectToml) => {\n if ((pyProjectToml.tool as any)?.ruff) {\n (pyProjectToml.tool as any).ruff['line-length'] = 120;\n }\n return pyProjectToml;\n },\n );\n\n addDependenciesToDependencyGroupInPyProjectToml(tree, '.', 'dev', ['ty']);\n\n // Add a dependency on the format target for lint in order to reduce the number of\n // fixable lint errors (eg line too long)\n projectConfiguration.targets.lint = {\n ...projectConfiguration.targets.lint,\n cache: true,\n inputs: ['default', '^production'],\n configurations: {\n ...projectConfiguration.targets.lint?.configurations,\n fix: {\n fix: true,\n },\n 'skip-lint': {\n exitZero: true,\n },\n },\n };\n // Append `format` without moving an existing entry, so re-running does not\n // reorder lint dependencies (e.g. relative to a later-added license-check).\n addDependencyToTargetIfNotPresent(projectConfiguration, 'lint', 'format');\n\n projectConfiguration.targets = sortObjectKeys(projectConfiguration.targets);\n updateProjectConfiguration(tree, fullyQualifiedName, projectConfiguration);\n\n addGeneratorMetadata(tree, fullyQualifiedName, PY_PROJECT_GENERATOR_INFO);\n\n // Update root .gitignore\n updateGitIgnore(tree, '.', (patterns) => [...patterns, '/reports']);\n\n // Update project level .gitignore. The cache directories are also kept out\n // of type checking: `ty` respects .gitignore, and pytest creates and removes\n // transient `pytest-cache-files-*` directories while the test and typecheck\n // targets run concurrently, which would otherwise make `ty` fail with an I/O\n // error when it scans one mid-deletion.\n updateGitIgnore(tree, dir, (patterns) => [\n ...patterns,\n '**/__pycache__',\n ...PYTHON_TRANSIENT_ARTIFACTS.filter((p) => p !== '__pycache__'),\n ]);\n\n await addGeneratorMetricsIfApplicable(tree, [PY_PROJECT_GENERATOR_INFO]);\n\n await ensurePythonLicenseCollector(tree);\n\n // If license checking is configured, make this project's lint target depend\n // on the root license-check target. No-op if license checking isn't set up;\n // the license generator wires up existing projects itself, so the dependency\n // is added regardless of which generator runs first.\n addLicenseCheckToLintTarget(tree, fullyQualifiedName);\n\n return () =>\n installDependencies(tree, schema.preferInstallDependencies, {\n languages: ['typescript', 'python'],\n });\n};\nexport default pyProjectGenerator;\n"],"names":["addDependenciesToPackageJson","ensurePackage","joinPathFragments","readNxJson","readProjectConfiguration","updateNxJson","updateProjectConfiguration","addLicenseCheckToLintTarget","ensurePythonLicenseCollector","updateGitIgnore","installDependencies","addGeneratorMetricsIfApplicable","normalizeDistributionName","toSnakeCase","getNpmScope","addDependencyToTargetIfNotPresent","addGeneratorMetadata","getGeneratorInfo","projectExists","migrateToSharedVenvGenerator","uvProjectGenerator","sortObjectKeys","addDependenciesToDependencyGroupInPyProjectToml","updateToml","withVersions","PY_PROJECT_GENERATOR_INFO","filename","PYTHON_TRANSIENT_ARTIFACTS","getPyProjectDetails","tree","schema","scope","normalizedName","name","normalizedModuleName","moduleName","fullyQualifiedName","distributionName","dir","directory","subDirectory","pyProjectGenerator","pythonPlugin","Object","entries","forEach","version","nxJson","plugins","find","p","plugin","options","packageManager","exists","autoActivate","moveDevDependencies","pyenvPythonVersion","pyprojectPythonDependency","packageName","publishable","buildLockedVersions","buildBundleLocalDependencies","linter","rootPyprojectDependencyGroup","projectType","type","projectNameAndRootFormat","unitTestRunner","codeCoverage","codeCoverageHtmlReport","codeCoverageXmlReport","unitTestHtmlReport","unitTestJUnitReport","buildSystem","srcDir","f","delete","write","outputPath","buildOutputPath","projectConfiguration","targets","compile","buildTarget","build","inputs","outputs","ignorePaths","dependsOn","typecheck","cache","executor","command","cwd","pyProjectToml","tool","ruff","lint","configurations","fix","exitZero","patterns","filter","preferInstallDependencies","languages"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/py/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 addDependenciesToPackageJson,\n ensurePackage,\n type GeneratorCallback,\n joinPathFragments,\n readNxJson,\n readProjectConfiguration,\n type Tree,\n updateNxJson,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport {\n addLicenseCheckToLintTarget,\n ensurePythonLicenseCollector,\n} from '../../license/config';\nimport { updateGitIgnore } from '../../utils/git';\nimport { installDependencies } from '../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics';\nimport { normalizeDistributionName, toSnakeCase } from '../../utils/names';\nimport { getNpmScope } from '../../utils/npm-scope';\nimport {\n addDependencyToTargetIfNotPresent,\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n projectExists,\n} from '../../utils/nx';\nimport type { UVPyprojectToml } from '../../utils/nxlv-python';\nimport {\n migrateToSharedVenvGenerator,\n uvProjectGenerator,\n} from '../../utils/nxlv-python';\nimport { sortObjectKeys } from '../../utils/object';\nimport { addDependenciesToDependencyGroupInPyProjectToml } from '../../utils/py';\nimport { updateToml } from '../../utils/toml';\nimport { withVersions } from '../../utils/versions';\nimport type { PyProjectGeneratorSchema } from './schema';\n\nexport const PY_PROJECT_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\n// Transient artifacts that pytest, coverage and ruff create and remove while\n// the test, typecheck and compile targets run concurrently. `.coverage.*` are\n// the per-process data files pytest-cov writes (`.coverage.<host>.<pid>.<rand>`)\n// before combining them. Both `ty` (which respects .gitignore) and the\n// `@nxlv/python:build` copy (which respects `ignorePaths`) would otherwise fail\n// when they read one of these mid-deletion.\nconst PYTHON_TRANSIENT_ARTIFACTS = [\n '__pycache__',\n '.coverage',\n '.coverage.*',\n '.pytest_cache',\n 'pytest-cache-files-*',\n '.ruff_cache',\n];\n\nexport interface PyProjectDetails {\n /**\n * Fully qualified Nx project id including scope, in dot notation (eg foo.bar).\n * This is the identifier Nx uses (readProjectConfiguration, the project\n * graph, target references) and is intentionally kept dotted.\n */\n readonly fullyQualifiedName: string;\n /**\n * PEP 503 normalised Python distribution name (eg foo-bar). This is the name\n * written to the project's `[project].name`, the root `[tool.uv.sources]`\n * key, and any inter-project dependency string. It is hyphenated (not dotted)\n * so `uv` and `@nxlv/python` can match it: uv writes `uv.lock` keyed by the\n * PEP 503 hyphenated name, and `@nxlv/python`'s dependency inference splits a\n * dotted name on `.` and so would otherwise drop the edge entirely. Keeping\n * the distribution name decoupled from `fullyQualifiedName` is what lets the\n * workspace dependency edge appear in the Nx project graph.\n */\n readonly distributionName: string;\n /**\n * Directory of the library relative to the root\n */\n readonly dir: string;\n /**\n * Module name for the project\n */\n readonly normalizedModuleName: string;\n}\n\n/**\n * Returns details about the Python project to be created\n */\nexport const getPyProjectDetails = (\n tree: Tree,\n schema: {\n name: string;\n directory?: string;\n subDirectory?: string;\n moduleName?: string;\n },\n): PyProjectDetails => {\n const scope = toSnakeCase(getNpmScope(tree));\n const normalizedName = toSnakeCase(schema.name);\n const normalizedModuleName = toSnakeCase(\n schema.moduleName ?? `${scope}_${normalizedName}`,\n );\n const fullyQualifiedName = `${scope}.${normalizedName}`;\n // The Python distribution name is the PEP 503 normalised form of the\n // fully qualified name: hyphenated, never dotted. See PyProjectDetails.\n const distributionName = normalizeDistributionName(fullyQualifiedName);\n // NB: interactive nx generator cli can pass empty string\n const dir = joinPathFragments(\n schema.directory || '.',\n schema.subDirectory || normalizedName,\n );\n return { dir, fullyQualifiedName, distributionName, normalizedModuleName };\n};\n\n/**\n * Generates a Python project\n */\nexport const pyProjectGenerator = async (\n tree: Tree,\n schema: PyProjectGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const { dir, normalizedModuleName, fullyQualifiedName, distributionName } =\n getPyProjectDetails(tree, schema);\n\n const pythonPlugin = withVersions(['@nxlv/python']);\n addDependenciesToPackageJson(tree, {}, pythonPlugin);\n\n Object.entries(pythonPlugin).forEach(([name, version]) =>\n ensurePackage(name, version),\n );\n\n const nxJson = readNxJson(tree);\n\n // Only rewrite nx.json when the plugin needs adding, so re-running does not\n // reserialize (and reformat) the file when nothing has changed.\n if (\n !nxJson.plugins?.find((p) =>\n typeof p === 'string'\n ? p === '@nxlv/python'\n : p.plugin === '@nxlv/python',\n )\n ) {\n nxJson.plugins = [\n ...(nxJson.plugins ?? []),\n {\n plugin: '@nxlv/python',\n options: {\n packageManager: 'uv',\n },\n },\n ];\n updateNxJson(tree, nxJson);\n }\n\n // Only scaffold the project when it does not already exist so re-running with\n // the same name does not throw. The rest of the generator still runs to apply\n // any changed options to the existing project.\n if (!projectExists(tree, fullyQualifiedName)) {\n if (!tree.exists('uv.lock')) {\n await migrateToSharedVenvGenerator(tree, {\n autoActivate: true,\n packageManager: 'uv',\n moveDevDependencies: false,\n pyenvPythonVersion: '3.14.0',\n pyprojectPythonDependency: '>=3.14',\n });\n }\n\n await uvProjectGenerator(tree, {\n // The Nx project id (and `uv.workspace.members` etc.) keys off `name`, so\n // keep it dotted. `packageName` is the separate PEP 503 distribution name\n // written to `[project].name` and the root `[tool.uv.sources]` key; it is\n // hyphenated so `@nxlv/python` infers the workspace dependency edge (it\n // splits a dotted name on `.` and would otherwise drop it). This split is\n // the whole fix (see PyProjectDetails.distributionName).\n name: fullyQualifiedName,\n packageName: distributionName,\n publishable: false,\n buildLockedVersions: true,\n buildBundleLocalDependencies: true,\n linter: 'ruff',\n rootPyprojectDependencyGroup: 'main',\n pyenvPythonVersion: '3.14.0',\n pyprojectPythonDependency: '>=3.14',\n projectType: schema.type,\n projectNameAndRootFormat: 'as-provided',\n moduleName: normalizedModuleName,\n directory: dir,\n unitTestRunner: 'pytest',\n codeCoverage: true,\n codeCoverageHtmlReport: true,\n codeCoverageXmlReport: true,\n unitTestHtmlReport: true,\n unitTestJUnitReport: true,\n buildSystem: 'hatch',\n srcDir: false,\n });\n\n // Remove generated hello.py and test_hello.py as they are not needed\n [\n joinPathFragments(dir, normalizedModuleName, 'hello.py'),\n joinPathFragments(dir, 'tests', 'test_hello.py'),\n ].forEach((f) => tree.delete(f));\n\n // Add a placeholder test so pytest doesn't fail with \"no tests collected\"\n tree.write(\n joinPathFragments(dir, 'tests', 'test_noop.py'),\n 'def test_noop():\\n pass\\n',\n );\n }\n\n const outputPath = '{workspaceRoot}/dist/{projectRoot}';\n const buildOutputPath = joinPathFragments(outputPath, 'build');\n const projectConfiguration = readProjectConfiguration(\n tree,\n fullyQualifiedName,\n );\n projectConfiguration.name = fullyQualifiedName;\n // Derive the compile target from the uv build target, and rewrite build to\n // orchestrate the other targets. This only runs on first creation: on re-run\n // build has already been transformed, so re-deriving would corrupt compile\n // and duplicate the build dependencies.\n if (!projectConfiguration.targets.compile) {\n const buildTarget = projectConfiguration.targets.build;\n projectConfiguration.targets.compile = {\n ...buildTarget,\n inputs: ['default', '^production'],\n outputs: [buildOutputPath],\n options: {\n ...buildTarget.options,\n outputPath: buildOutputPath,\n // The build executor copies the project to a temp folder; exclude the\n // executor defaults plus transient artifacts so the copy does not race\n // a concurrent test/typecheck target deleting a file mid-copy.\n ignorePaths: ['.venv', '.tox', 'tests', ...PYTHON_TRANSIENT_ARTIFACTS],\n },\n };\n projectConfiguration.targets.build = {\n inputs: ['default', '^production'],\n dependsOn: [\n 'lint',\n 'compile',\n 'test',\n 'typecheck',\n ...(buildTarget.dependsOn ?? []),\n ],\n options: {\n outputPath,\n },\n };\n }\n projectConfiguration.targets.typecheck = {\n cache: true,\n inputs: ['default', '^production'],\n executor: '@nxlv/python:run-commands',\n options: {\n command: 'uv run ty check',\n cwd: '{projectRoot}',\n },\n };\n\n // Set the default line length to 120, as 88 is a little too strict\n updateToml(\n tree,\n joinPathFragments(dir, 'pyproject.toml'),\n (pyProjectToml: UVPyprojectToml) => {\n if ((pyProjectToml.tool as any)?.ruff) {\n (pyProjectToml.tool as any).ruff['line-length'] = 120;\n }\n return pyProjectToml;\n },\n );\n\n // Pin ruff to the version generation-time formatting uses (PY_VERSIONS), so\n // generated files stay `ruff format --check`-clean across ruff releases.\n addDependenciesToDependencyGroupInPyProjectToml(tree, '.', 'dev', [\n 'ruff',\n 'ty',\n ]);\n\n // Base format target checks rather than writes (so build/lint don't rewrite\n // source); `fix` writes, and `skip-lint` writes without failing so it stays\n // a no-op when propagated through the lint -> format dependency.\n projectConfiguration.targets.format = {\n ...projectConfiguration.targets.format,\n cache: true,\n inputs: ['default', '^production'],\n options: {\n ...projectConfiguration.targets.format?.options,\n check: true,\n },\n configurations: {\n ...projectConfiguration.targets.format?.configurations,\n fix: {\n check: false,\n },\n 'skip-lint': {\n check: false,\n },\n },\n };\n\n // Add a dependency on the format target for lint in order to reduce the number of\n // fixable lint errors (eg line too long)\n projectConfiguration.targets.lint = {\n ...projectConfiguration.targets.lint,\n cache: true,\n inputs: ['default', '^production'],\n configurations: {\n ...projectConfiguration.targets.lint?.configurations,\n fix: {\n fix: true,\n },\n 'skip-lint': {\n exitZero: true,\n },\n },\n };\n // Append `format` without moving an existing entry, so re-running does not\n // reorder lint dependencies (e.g. relative to a later-added license-check).\n addDependencyToTargetIfNotPresent(projectConfiguration, 'lint', 'format');\n\n projectConfiguration.targets = sortObjectKeys(projectConfiguration.targets);\n updateProjectConfiguration(tree, fullyQualifiedName, projectConfiguration);\n\n addGeneratorMetadata(tree, fullyQualifiedName, PY_PROJECT_GENERATOR_INFO);\n\n // Update root .gitignore\n updateGitIgnore(tree, '.', (patterns) => [...patterns, '/reports']);\n\n // Update project level .gitignore. The cache directories are also kept out\n // of type checking: `ty` respects .gitignore, and pytest creates and removes\n // transient `pytest-cache-files-*` directories while the test and typecheck\n // targets run concurrently, which would otherwise make `ty` fail with an I/O\n // error when it scans one mid-deletion.\n updateGitIgnore(tree, dir, (patterns) => [\n ...patterns,\n '**/__pycache__',\n ...PYTHON_TRANSIENT_ARTIFACTS.filter((p) => p !== '__pycache__'),\n ]);\n\n await addGeneratorMetricsIfApplicable(tree, [PY_PROJECT_GENERATOR_INFO]);\n\n await ensurePythonLicenseCollector(tree);\n\n // If license checking is configured, make this project's lint target depend\n // on the root license-check target. No-op if license checking isn't set up;\n // the license generator wires up existing projects itself, so the dependency\n // is added regardless of which generator runs first.\n addLicenseCheckToLintTarget(tree, fullyQualifiedName);\n\n return () =>\n installDependencies(tree, schema.preferInstallDependencies, {\n languages: ['typescript', 'python'],\n });\n};\nexport default pyProjectGenerator;\n"],"names":["addDependenciesToPackageJson","ensurePackage","joinPathFragments","readNxJson","readProjectConfiguration","updateNxJson","updateProjectConfiguration","addLicenseCheckToLintTarget","ensurePythonLicenseCollector","updateGitIgnore","installDependencies","addGeneratorMetricsIfApplicable","normalizeDistributionName","toSnakeCase","getNpmScope","addDependencyToTargetIfNotPresent","addGeneratorMetadata","getGeneratorInfo","projectExists","migrateToSharedVenvGenerator","uvProjectGenerator","sortObjectKeys","addDependenciesToDependencyGroupInPyProjectToml","updateToml","withVersions","PY_PROJECT_GENERATOR_INFO","filename","PYTHON_TRANSIENT_ARTIFACTS","getPyProjectDetails","tree","schema","scope","normalizedName","name","normalizedModuleName","moduleName","fullyQualifiedName","distributionName","dir","directory","subDirectory","pyProjectGenerator","pythonPlugin","Object","entries","forEach","version","nxJson","plugins","find","p","plugin","options","packageManager","exists","autoActivate","moveDevDependencies","pyenvPythonVersion","pyprojectPythonDependency","packageName","publishable","buildLockedVersions","buildBundleLocalDependencies","linter","rootPyprojectDependencyGroup","projectType","type","projectNameAndRootFormat","unitTestRunner","codeCoverage","codeCoverageHtmlReport","codeCoverageXmlReport","unitTestHtmlReport","unitTestJUnitReport","buildSystem","srcDir","f","delete","write","outputPath","buildOutputPath","projectConfiguration","targets","compile","buildTarget","build","inputs","outputs","ignorePaths","dependsOn","typecheck","cache","executor","command","cwd","pyProjectToml","tool","ruff","format","check","configurations","fix","lint","exitZero","patterns","filter","preferInstallDependencies","languages"],"mappings":"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"}
|
|
@@ -1491,10 +1491,27 @@ exports[`tsSmithyApiGenerator > should generate smithy ts api with default optio
|
|
|
1491
1491
|
"cwd": "{projectRoot}"
|
|
1492
1492
|
}
|
|
1493
1493
|
},
|
|
1494
|
+
"format": {
|
|
1495
|
+
"executor": "nx:run-commands",
|
|
1496
|
+
"cache": true,
|
|
1497
|
+
"inputs": ["biome"],
|
|
1498
|
+
"options": {
|
|
1499
|
+
"command": "biome format {projectRoot}"
|
|
1500
|
+
},
|
|
1501
|
+
"configurations": {
|
|
1502
|
+
"fix": {
|
|
1503
|
+
"command": "biome format --write {projectRoot}"
|
|
1504
|
+
},
|
|
1505
|
+
"skip-lint": {
|
|
1506
|
+
"command": "node -e \\"\\""
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
},
|
|
1494
1510
|
"lint": {
|
|
1495
1511
|
"executor": "nx:run-commands",
|
|
1496
1512
|
"cache": true,
|
|
1497
1513
|
"inputs": ["biome"],
|
|
1514
|
+
"dependsOn": ["format"],
|
|
1498
1515
|
"options": {
|
|
1499
1516
|
"command": "biome lint {projectRoot}"
|
|
1500
1517
|
},
|
|
@@ -95,10 +95,27 @@ exports[`ts lib generator > should generate library with custom directory > cust
|
|
|
95
95
|
"cwd": "{projectRoot}"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
|
+
"format": {
|
|
99
|
+
"executor": "nx:run-commands",
|
|
100
|
+
"cache": true,
|
|
101
|
+
"inputs": ["biome"],
|
|
102
|
+
"options": {
|
|
103
|
+
"command": "biome format {projectRoot}"
|
|
104
|
+
},
|
|
105
|
+
"configurations": {
|
|
106
|
+
"fix": {
|
|
107
|
+
"command": "biome format --write {projectRoot}"
|
|
108
|
+
},
|
|
109
|
+
"skip-lint": {
|
|
110
|
+
"command": "node -e \\"\\""
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
},
|
|
98
114
|
"lint": {
|
|
99
115
|
"executor": "nx:run-commands",
|
|
100
116
|
"cache": true,
|
|
101
117
|
"inputs": ["biome"],
|
|
118
|
+
"dependsOn": ["format"],
|
|
102
119
|
"options": {
|
|
103
120
|
"command": "biome lint {projectRoot}"
|
|
104
121
|
},
|
|
@@ -163,10 +180,27 @@ exports[`ts lib generator > should generate library with default options > proje
|
|
|
163
180
|
"cwd": "{projectRoot}"
|
|
164
181
|
}
|
|
165
182
|
},
|
|
183
|
+
"format": {
|
|
184
|
+
"executor": "nx:run-commands",
|
|
185
|
+
"cache": true,
|
|
186
|
+
"inputs": ["biome"],
|
|
187
|
+
"options": {
|
|
188
|
+
"command": "biome format {projectRoot}"
|
|
189
|
+
},
|
|
190
|
+
"configurations": {
|
|
191
|
+
"fix": {
|
|
192
|
+
"command": "biome format --write {projectRoot}"
|
|
193
|
+
},
|
|
194
|
+
"skip-lint": {
|
|
195
|
+
"command": "node -e \\"\\""
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
},
|
|
166
199
|
"lint": {
|
|
167
200
|
"executor": "nx:run-commands",
|
|
168
201
|
"cache": true,
|
|
169
202
|
"inputs": ["biome"],
|
|
203
|
+
"dependsOn": ["format"],
|
|
170
204
|
"options": {
|
|
171
205
|
"command": "biome lint {projectRoot}"
|
|
172
206
|
},
|
|
@@ -229,10 +263,27 @@ exports[`ts lib generator > should generate library with subdirectory > subdir-p
|
|
|
229
263
|
"cwd": "{projectRoot}"
|
|
230
264
|
}
|
|
231
265
|
},
|
|
266
|
+
"format": {
|
|
267
|
+
"executor": "nx:run-commands",
|
|
268
|
+
"cache": true,
|
|
269
|
+
"inputs": ["biome"],
|
|
270
|
+
"options": {
|
|
271
|
+
"command": "biome format {projectRoot}"
|
|
272
|
+
},
|
|
273
|
+
"configurations": {
|
|
274
|
+
"fix": {
|
|
275
|
+
"command": "biome format --write {projectRoot}"
|
|
276
|
+
},
|
|
277
|
+
"skip-lint": {
|
|
278
|
+
"command": "node -e \\"\\""
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
},
|
|
232
282
|
"lint": {
|
|
233
283
|
"executor": "nx:run-commands",
|
|
234
284
|
"cache": true,
|
|
235
285
|
"inputs": ["biome"],
|
|
286
|
+
"dependsOn": ["format"],
|
|
236
287
|
"options": {
|
|
237
288
|
"command": "biome lint {projectRoot}"
|
|
238
289
|
},
|
package/src/ts/lib/biome.js
CHANGED
|
@@ -6,9 +6,10 @@ import { readProjectConfigurationUnqualified } from "../../utils/nx.js";
|
|
|
6
6
|
import { sortObjectKeys } from "../../utils/object.js";
|
|
7
7
|
export const configureBiomeLint = async (tree, options)=>{
|
|
8
8
|
const projectJson = readProjectConfigurationUnqualified(tree, options.fullyQualifiedName);
|
|
9
|
+
const biomeConfigured = tree.exists('biome.json');
|
|
9
10
|
// When there's no root Biome configuration (eg the user removed it), make the
|
|
10
11
|
// lint target a no-op rather than failing on a missing config.
|
|
11
|
-
const lintTarget =
|
|
12
|
+
const lintTarget = biomeConfigured ? {
|
|
12
13
|
executor: 'nx:run-commands',
|
|
13
14
|
cache: true,
|
|
14
15
|
inputs: [
|
|
@@ -25,16 +26,48 @@ export const configureBiomeLint = async (tree, options)=>{
|
|
|
25
26
|
// Cross-platform no-op (`true` is not available on Windows cmd).
|
|
26
27
|
command: 'node -e ""'
|
|
27
28
|
}
|
|
29
|
+
},
|
|
30
|
+
// Format before linting so any fixable formatting issues (eg line too
|
|
31
|
+
// long) are resolved first, mirroring the Python project generator.
|
|
32
|
+
dependsOn: [
|
|
33
|
+
'format'
|
|
34
|
+
]
|
|
35
|
+
} : {
|
|
36
|
+
executor: 'nx:noop'
|
|
37
|
+
};
|
|
38
|
+
// The base format target checks formatting (failing when files aren't
|
|
39
|
+
// formatted); the `fix` configuration writes the changes. `skip-lint` is a
|
|
40
|
+
// no-op so `nx lint --configuration=skip-lint` propagates cleanly through the
|
|
41
|
+
// lint -> format dependency edge.
|
|
42
|
+
const formatTarget = biomeConfigured ? {
|
|
43
|
+
executor: 'nx:run-commands',
|
|
44
|
+
cache: true,
|
|
45
|
+
inputs: [
|
|
46
|
+
'biome'
|
|
47
|
+
],
|
|
48
|
+
options: {
|
|
49
|
+
command: 'biome format {projectRoot}'
|
|
50
|
+
},
|
|
51
|
+
configurations: {
|
|
52
|
+
fix: {
|
|
53
|
+
command: 'biome format --write {projectRoot}'
|
|
54
|
+
},
|
|
55
|
+
'skip-lint': {
|
|
56
|
+
// Cross-platform no-op (`true` is not available on Windows cmd).
|
|
57
|
+
command: 'node -e ""'
|
|
58
|
+
}
|
|
28
59
|
}
|
|
29
60
|
} : {
|
|
30
61
|
executor: 'nx:noop'
|
|
31
62
|
};
|
|
32
63
|
updateProjectConfiguration(tree, options.fullyQualifiedName, {
|
|
33
64
|
...projectJson,
|
|
34
|
-
// Sort targets so the lint
|
|
35
|
-
// regardless of whether
|
|
65
|
+
// Sort targets so the lint and format targets land in deterministic
|
|
66
|
+
// positions regardless of whether they already existed (keeps re-runs
|
|
67
|
+
// stable)
|
|
36
68
|
targets: sortObjectKeys({
|
|
37
69
|
...projectJson?.targets,
|
|
70
|
+
format: formatTarget,
|
|
38
71
|
lint: lintTarget
|
|
39
72
|
})
|
|
40
73
|
});
|
package/src/ts/lib/biome.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/ts/lib/biome.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n readNxJson,\n type Tree,\n updateNxJson,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { readProjectConfigurationUnqualified } from '../../utils/nx';\nimport { sortObjectKeys } from '../../utils/object';\nimport type { ConfigureProjectOptions } from './types';\n\nexport const configureBiomeLint = async (\n tree: Tree,\n options: ConfigureProjectOptions,\n) => {\n const projectJson = readProjectConfigurationUnqualified(\n tree,\n options.fullyQualifiedName,\n );\n\n // When there's no root Biome configuration (eg the user removed it), make the\n // lint target a no-op rather than failing on a missing config.\n const lintTarget =
|
|
1
|
+
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/ts/lib/biome.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n readNxJson,\n type Tree,\n updateNxJson,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { readProjectConfigurationUnqualified } from '../../utils/nx';\nimport { sortObjectKeys } from '../../utils/object';\nimport type { ConfigureProjectOptions } from './types';\n\nexport const configureBiomeLint = async (\n tree: Tree,\n options: ConfigureProjectOptions,\n) => {\n const projectJson = readProjectConfigurationUnqualified(\n tree,\n options.fullyQualifiedName,\n );\n\n const biomeConfigured = tree.exists('biome.json');\n\n // When there's no root Biome configuration (eg the user removed it), make the\n // lint target a no-op rather than failing on a missing config.\n const lintTarget = biomeConfigured\n ? {\n executor: 'nx:run-commands',\n cache: true,\n inputs: ['biome'],\n options: {\n command: 'biome lint {projectRoot}',\n },\n configurations: {\n fix: {\n command: 'biome check --write {projectRoot}',\n },\n 'skip-lint': {\n // Cross-platform no-op (`true` is not available on Windows cmd).\n command: 'node -e \"\"',\n },\n },\n // Format before linting so any fixable formatting issues (eg line too\n // long) are resolved first, mirroring the Python project generator.\n dependsOn: ['format'],\n }\n : { executor: 'nx:noop' };\n\n // The base format target checks formatting (failing when files aren't\n // formatted); the `fix` configuration writes the changes. `skip-lint` is a\n // no-op so `nx lint --configuration=skip-lint` propagates cleanly through the\n // lint -> format dependency edge.\n const formatTarget = biomeConfigured\n ? {\n executor: 'nx:run-commands',\n cache: true,\n inputs: ['biome'],\n options: {\n command: 'biome format {projectRoot}',\n },\n configurations: {\n fix: {\n command: 'biome format --write {projectRoot}',\n },\n 'skip-lint': {\n // Cross-platform no-op (`true` is not available on Windows cmd).\n command: 'node -e \"\"',\n },\n },\n }\n : { executor: 'nx:noop' };\n\n updateProjectConfiguration(tree, options.fullyQualifiedName, {\n ...projectJson,\n // Sort targets so the lint and format targets land in deterministic\n // positions regardless of whether they already existed (keeps re-runs\n // stable)\n targets: sortObjectKeys({\n ...projectJson?.targets,\n format: formatTarget,\n lint: lintTarget,\n }),\n });\n\n // Register the `biome` named input so lint targets are cache-invalidated when\n // the root biome.json changes.\n const nxJson = readNxJson(tree);\n if (\n !nxJson.namedInputs?.biome ||\n !nxJson.namedInputs.biome.includes('{workspaceRoot}/biome.json')\n ) {\n updateNxJson(tree, {\n ...nxJson,\n namedInputs: {\n ...nxJson.namedInputs,\n biome: ['default', '{workspaceRoot}/biome.json'],\n },\n });\n }\n};\n"],"names":["readNxJson","updateNxJson","updateProjectConfiguration","readProjectConfigurationUnqualified","sortObjectKeys","configureBiomeLint","tree","options","projectJson","fullyQualifiedName","biomeConfigured","exists","lintTarget","executor","cache","inputs","command","configurations","fix","dependsOn","formatTarget","targets","format","lint","nxJson","namedInputs","biome","includes"],"mappings":"AAAA;;;CAGC,GACD,SACEA,UAAU,EAEVC,YAAY,EACZC,0BAA0B,QACrB,aAAa;AACpB,SAASC,mCAAmC,QAAQ,oBAAiB;AACrE,SAASC,cAAc,QAAQ,wBAAqB;AAGpD,OAAO,MAAMC,qBAAqB,OAChCC,MACAC;IAEA,MAAMC,cAAcL,oCAClBG,MACAC,QAAQE,kBAAkB;IAG5B,MAAMC,kBAAkBJ,KAAKK,MAAM,CAAC;IAEpC,8EAA8E;IAC9E,+DAA+D;IAC/D,MAAMC,aAAaF,kBACf;QACEG,UAAU;QACVC,OAAO;QACPC,QAAQ;YAAC;SAAQ;QACjBR,SAAS;YACPS,SAAS;QACX;QACAC,gBAAgB;YACdC,KAAK;gBACHF,SAAS;YACX;YACA,aAAa;gBACX,iEAAiE;gBACjEA,SAAS;YACX;QACF;QACA,sEAAsE;QACtE,oEAAoE;QACpEG,WAAW;YAAC;SAAS;IACvB,IACA;QAAEN,UAAU;IAAU;IAE1B,sEAAsE;IACtE,2EAA2E;IAC3E,8EAA8E;IAC9E,kCAAkC;IAClC,MAAMO,eAAeV,kBACjB;QACEG,UAAU;QACVC,OAAO;QACPC,QAAQ;YAAC;SAAQ;QACjBR,SAAS;YACPS,SAAS;QACX;QACAC,gBAAgB;YACdC,KAAK;gBACHF,SAAS;YACX;YACA,aAAa;gBACX,iEAAiE;gBACjEA,SAAS;YACX;QACF;IACF,IACA;QAAEH,UAAU;IAAU;IAE1BX,2BAA2BI,MAAMC,QAAQE,kBAAkB,EAAE;QAC3D,GAAGD,WAAW;QACd,oEAAoE;QACpE,sEAAsE;QACtE,UAAU;QACVa,SAASjB,eAAe;YACtB,GAAGI,aAAaa,OAAO;YACvBC,QAAQF;YACRG,MAAMX;QACR;IACF;IAEA,8EAA8E;IAC9E,+BAA+B;IAC/B,MAAMY,SAASxB,WAAWM;IAC1B,IACE,CAACkB,OAAOC,WAAW,EAAEC,SACrB,CAACF,OAAOC,WAAW,CAACC,KAAK,CAACC,QAAQ,CAAC,+BACnC;QACA1B,aAAaK,MAAM;YACjB,GAAGkB,MAAM;YACTC,aAAa;gBACX,GAAGD,OAAOC,WAAW;gBACrBC,OAAO;oBAAC;oBAAW;iBAA6B;YAClD;QACF;IACF;AACF,EAAE"}
|