@nx/js 23.2.0-pr.36527.2252709 → 23.2.0-pr.36838.ef8e258
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/README.md +2 -2
- package/dist/internal.d.ts +3 -0
- package/dist/internal.js +10 -2
- package/dist/src/executors/copy-workspace-modules/copy-workspace-modules.js +120 -17
- package/dist/src/executors/prune-lockfile/prune-lockfile.js +38 -26
- package/dist/src/executors/tsc/lib/typescript-compilation.js +1 -1
- package/dist/src/generators/library/schema.d.ts +1 -2
- package/dist/src/index.d.ts +1 -2
- package/dist/src/index.js +3 -3
- package/dist/src/migrations/update-23-2-0/add-pnpm-deploy-output-cache-inputs.d.ts +14 -0
- package/dist/src/migrations/update-23-2-0/add-pnpm-deploy-output-cache-inputs.js +242 -0
- package/dist/src/migrations/update-23-2-0/add-pnpm-deploy-output-cache-inputs.md +64 -0
- package/dist/src/migrations/update-23-2-0/add-pnpm-prune-lockfile-cache-config.d.ts +2 -0
- package/dist/src/migrations/update-23-2-0/add-pnpm-prune-lockfile-cache-config.js +305 -0
- package/dist/src/migrations/update-23-2-0/add-pnpm-prune-lockfile-cache-config.md +59 -0
- package/dist/src/release/utils/update-lock-file.js +42 -1
- package/dist/src/release/version-actions.d.ts +5 -1
- package/dist/src/release/version-actions.js +151 -47
- package/dist/src/utils/package-json/update-package-json.d.ts +1 -1
- package/dist/src/utils/package-json/update-package-json.js +7 -13
- package/dist/src/utils/pnpm-deploy-output-cache-inputs.d.ts +29 -0
- package/dist/src/utils/pnpm-deploy-output-cache-inputs.js +177 -0
- package/dist/src/utils/pnpm-install-settings-inputs.d.ts +45 -0
- package/dist/src/utils/pnpm-install-settings-inputs.js +77 -0
- package/dist/src/utils/schema.d.ts +1 -2
- package/dist/src/utils/swc/compile-swc.d.ts +1 -0
- package/dist/src/utils/swc/compile-swc.js +7 -2
- package/dist/src/utils/target-defaults-matching.d.ts +57 -0
- package/dist/src/utils/target-defaults-matching.js +126 -0
- package/dist/src/utils/workspace-module-sections.d.ts +16 -0
- package/dist/src/utils/workspace-module-sections.js +24 -0
- package/migrations.json +12 -0
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
|
|
8
8
|
<div style="text-align: center;">
|
|
9
9
|
|
|
10
|
-
[]()
|
|
10
|
+
[](<>)
|
|
11
11
|
[](https://www.npmjs.com/package/nx)
|
|
12
|
-
[]()
|
|
12
|
+
[](<>)
|
|
13
13
|
[](http://commitizen.github.io/cz-cli/)
|
|
14
14
|
[](https://go.nx.dev/community)
|
|
15
15
|
[](https://nx.dev/docs/features/ci-features/sandboxing)
|
package/dist/internal.d.ts
CHANGED
|
@@ -3,6 +3,9 @@ export { TargetProjectLocator, isBuiltinModuleImport, } from '@nx/devkit/interna
|
|
|
3
3
|
export { findProjectsNpmDependencies } from '@nx/devkit/internal';
|
|
4
4
|
export { walkTsconfigExtendsChain, type RawTsconfigJsonCache, } from './src/utils/typescript/raw-tsconfig';
|
|
5
5
|
export { isEsmProject } from './src/utils/module-format/is-esm-project';
|
|
6
|
+
export { PNPM_INSTALL_SETTINGS_INPUTS, PNPM_MAJOR_RUNTIME_INPUT, pnpmInstallSettingsInputsForInferredTarget, shouldIncludePnpmMajorRuntimeInput, } from './src/utils/pnpm-install-settings-inputs';
|
|
7
|
+
export { addPnpmDeployOutputCacheInputs } from './src/utils/pnpm-deploy-output-cache-inputs';
|
|
8
|
+
export type { MatchedTargetRef } from './src/utils/target-defaults-matching';
|
|
6
9
|
export { TS_SOLUTION_SETUP_TSCONFIG_INPUT, addProjectToTsSolutionWorkspace, assertNotUsingTsSolutionSetup, findRuntimeTsConfigName, getDefinedCustomConditionName, getProjectSourceRoot, getProjectType, isUsingTsSolutionSetup, shouldConfigureTsSolutionSetup, updateTsconfigFiles, } from './src/utils/typescript/ts-solution-setup';
|
|
7
10
|
export { getTsConfigBaseOptions } from './src/utils/typescript/create-ts-config';
|
|
8
11
|
export { createTreeParseConfigHost, type TreeParseConfigHost, } from './src/utils/typescript/ts-config';
|
package/dist/internal.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// internal consumers and may change without semver protection. Consider it
|
|
6
6
|
// the @nx/js equivalent of `@nx/devkit/internal`.
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.
|
|
9
|
-
exports.typesNodeVersion = exports.tsLibVersion = exports.swcNodeVersion = exports.swcHelpersVersion = exports.swcCoreVersion = exports.swcCliVersion = exports.prettierVersion = exports.esbuildVersion = exports.nxVersion = exports.releaseTasks = exports.addReleaseConfigForTsSolution = exports.addReleaseConfigForNonTsSolution = exports.addLocalRegistryScripts = exports.stripGlobToBaseDir = void 0;
|
|
8
|
+
exports.normalizeLinterOption = exports.isValidPackageJsonBuildConfig = exports.addBuildAndWatchDepsTargets = exports.findNpmDependencies = exports.getProjectPackageManagerWorkspaceStateWarningTask = exports.getProjectPackageManagerWorkspaceState = exports.getNpmScope = exports.sortPackageJsonFields = exports.CopyAssetsHandler = exports.addSwcRegisterDependencies = exports.addSwcDependencies = exports.addSwcTestConfig = exports.addSwcConfig = exports.createTmpTsConfig = exports.computeCompilerOptionsPaths = exports.calculateProjectDependencies = exports.calculateProjectBuildableDependencies = exports.compileTypeScript = exports.getNeededCompilerOptionOverrides = exports.isTypescriptVersionAtLeast = exports.getTsConfigModuleResolution = exports.getRangeMinimum = exports.ensureTypescript = exports.createTreeParseConfigHost = exports.getTsConfigBaseOptions = exports.updateTsconfigFiles = exports.shouldConfigureTsSolutionSetup = exports.isUsingTsSolutionSetup = exports.getProjectType = exports.getProjectSourceRoot = exports.getDefinedCustomConditionName = exports.findRuntimeTsConfigName = exports.assertNotUsingTsSolutionSetup = exports.addProjectToTsSolutionWorkspace = exports.TS_SOLUTION_SETUP_TSCONFIG_INPUT = exports.addPnpmDeployOutputCacheInputs = exports.shouldIncludePnpmMajorRuntimeInput = exports.pnpmInstallSettingsInputsForInferredTarget = exports.PNPM_MAJOR_RUNTIME_INPUT = exports.PNPM_INSTALL_SETTINGS_INPUTS = exports.isEsmProject = exports.walkTsconfigExtendsChain = exports.findProjectsNpmDependencies = exports.isBuiltinModuleImport = exports.TargetProjectLocator = exports.requireWithTsconfigFallback = exports.registerTsConfigPaths = exports.registerTsProject = exports.loadTsFile = exports.forceRegisterEsmLoader = void 0;
|
|
9
|
+
exports.typesNodeVersion = exports.tsLibVersion = exports.swcNodeVersion = exports.swcHelpersVersion = exports.swcCoreVersion = exports.swcCliVersion = exports.prettierVersion = exports.esbuildVersion = exports.nxVersion = exports.releaseTasks = exports.addReleaseConfigForTsSolution = exports.addReleaseConfigForNonTsSolution = exports.addLocalRegistryScripts = exports.stripGlobToBaseDir = exports.getImportPath = exports.createGlobPatternsForDependencies = exports.addLintingToProject = exports.detectLinters = exports.normalizeUnitTestRunnerOption = void 0;
|
|
10
10
|
// Re-exports of nx-source internals.
|
|
11
11
|
var internal_1 = require("@nx/devkit/internal");
|
|
12
12
|
Object.defineProperty(exports, "forceRegisterEsmLoader", { enumerable: true, get: function () { return internal_1.forceRegisterEsmLoader; } });
|
|
@@ -26,6 +26,14 @@ Object.defineProperty(exports, "walkTsconfigExtendsChain", { enumerable: true, g
|
|
|
26
26
|
// TS solution awareness; mirrors Node's nearest-package.json semantics).
|
|
27
27
|
var is_esm_project_1 = require("./src/utils/module-format/is-esm-project");
|
|
28
28
|
Object.defineProperty(exports, "isEsmProject", { enumerable: true, get: function () { return is_esm_project_1.isEsmProject; } });
|
|
29
|
+
// Inputs for build targets that emit a pruned pnpm deploy output
|
|
30
|
+
var pnpm_install_settings_inputs_1 = require("./src/utils/pnpm-install-settings-inputs");
|
|
31
|
+
Object.defineProperty(exports, "PNPM_INSTALL_SETTINGS_INPUTS", { enumerable: true, get: function () { return pnpm_install_settings_inputs_1.PNPM_INSTALL_SETTINGS_INPUTS; } });
|
|
32
|
+
Object.defineProperty(exports, "PNPM_MAJOR_RUNTIME_INPUT", { enumerable: true, get: function () { return pnpm_install_settings_inputs_1.PNPM_MAJOR_RUNTIME_INPUT; } });
|
|
33
|
+
Object.defineProperty(exports, "pnpmInstallSettingsInputsForInferredTarget", { enumerable: true, get: function () { return pnpm_install_settings_inputs_1.pnpmInstallSettingsInputsForInferredTarget; } });
|
|
34
|
+
Object.defineProperty(exports, "shouldIncludePnpmMajorRuntimeInput", { enumerable: true, get: function () { return pnpm_install_settings_inputs_1.shouldIncludePnpmMajorRuntimeInput; } });
|
|
35
|
+
var pnpm_deploy_output_cache_inputs_1 = require("./src/utils/pnpm-deploy-output-cache-inputs");
|
|
36
|
+
Object.defineProperty(exports, "addPnpmDeployOutputCacheInputs", { enumerable: true, get: function () { return pnpm_deploy_output_cache_inputs_1.addPnpmDeployOutputCacheInputs; } });
|
|
29
37
|
// TS solution setup detection
|
|
30
38
|
var ts_solution_setup_1 = require("./src/utils/typescript/ts-solution-setup");
|
|
31
39
|
Object.defineProperty(exports, "TS_SOLUTION_SETUP_TSCONFIG_INPUT", { enumerable: true, get: function () { return ts_solution_setup_1.TS_SOLUTION_SETUP_TSCONFIG_INPUT; } });
|
|
@@ -7,6 +7,49 @@ const node_fs_1 = require("node:fs");
|
|
|
7
7
|
const path_1 = require("path");
|
|
8
8
|
const fs_1 = require("fs");
|
|
9
9
|
const strip_glob_to_base_dir_1 = require("../../utils/strip-glob-to-base-dir");
|
|
10
|
+
const workspace_module_sections_1 = require("../../utils/workspace-module-sections");
|
|
11
|
+
// Sections of a copied module's own manifest whose workspace-module deps are
|
|
12
|
+
// rewritten to file: and recursed into. pnpm installs a transitive dependency's
|
|
13
|
+
// regular, optional, and auto-installed peer deps (a workspace peer is linked
|
|
14
|
+
// and recorded under the depending importer's dependencies in the lockfile), but
|
|
15
|
+
// never its devDependencies. A workspace-module peer is moved into dependencies,
|
|
16
|
+
// since pnpm rejects a file: spec under peerDependencies (mirrors the app-level
|
|
17
|
+
// move in prune-lockfile).
|
|
18
|
+
const TRANSITIVE_INSTALL_SECTIONS = [
|
|
19
|
+
'dependencies',
|
|
20
|
+
'optionalDependencies',
|
|
21
|
+
'peerDependencies',
|
|
22
|
+
];
|
|
23
|
+
// Resolve `catalog:` references in a copied module manifest to the version the
|
|
24
|
+
// workspace pinned. Only the sections pnpm installs for a `file:` directory
|
|
25
|
+
// dependency are resolved: a copied module's devDependencies are never
|
|
26
|
+
// installed, so a `catalog:` there is inert (pnpm leaves it untouched), and
|
|
27
|
+
// resolving it would abort the whole deploy build if that catalog entry does
|
|
28
|
+
// not exist. Returns whether anything changed.
|
|
29
|
+
function resolveCatalogReferences(packageJson, manager) {
|
|
30
|
+
if (!manager) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
let modified = false;
|
|
34
|
+
for (const section of TRANSITIVE_INSTALL_SECTIONS) {
|
|
35
|
+
const deps = packageJson[section];
|
|
36
|
+
if (!deps) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
for (const [name, version] of Object.entries(deps)) {
|
|
40
|
+
if (!manager.isCatalogReference(version)) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
const resolved = manager.resolveCatalogReference(devkit_1.workspaceRoot, name, version);
|
|
44
|
+
if (!resolved) {
|
|
45
|
+
throw new Error(`Could not resolve catalog reference for package ${name}@${version}.`);
|
|
46
|
+
}
|
|
47
|
+
deps[name] = resolved;
|
|
48
|
+
modified = true;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return modified;
|
|
52
|
+
}
|
|
10
53
|
async function copyWorkspaceModules(schema, context) {
|
|
11
54
|
devkit_1.logger.log('Copying Workspace Modules to Build Directory...');
|
|
12
55
|
const outputDirectory = getOutputDir(schema, context);
|
|
@@ -17,10 +60,14 @@ async function copyWorkspaceModules(schema, context) {
|
|
|
17
60
|
return { success: true };
|
|
18
61
|
}
|
|
19
62
|
function handleWorkspaceModules(outputDirectory, packageJson, projectGraph) {
|
|
20
|
-
if (!
|
|
63
|
+
if (!workspace_module_sections_1.WORKSPACE_MODULE_INSTALL_SECTIONS.some((section) => packageJson[section])) {
|
|
21
64
|
return;
|
|
22
65
|
}
|
|
23
66
|
const workspaceModules = (0, internal_1.getWorkspacePackagesFromGraph)(projectGraph);
|
|
67
|
+
const catalogManager = (0, internal_1.getCatalogManager)(devkit_1.workspaceRoot);
|
|
68
|
+
// Only the pnpm prune path ships non-workspace local-path targets, so only
|
|
69
|
+
// pnpm manifests get their file:/link: specs relocated.
|
|
70
|
+
const isPnpmWorkspace = (0, devkit_1.detectPackageManager)(devkit_1.workspaceRoot) === 'pnpm';
|
|
24
71
|
const processedModules = new Set();
|
|
25
72
|
const workspaceModulesDir = (0, path_1.join)(outputDirectory, 'workspace_modules');
|
|
26
73
|
function calculateRelativePath(fromPkgName, toPkgName) {
|
|
@@ -41,11 +88,18 @@ function handleWorkspaceModules(outputDirectory, packageJson, projectGraph) {
|
|
|
41
88
|
processedModules.add(pkgName);
|
|
42
89
|
devkit_1.logger.verbose(`Copying ${pkgName}.`);
|
|
43
90
|
const workspaceModuleProject = workspaceModules.get(pkgName);
|
|
44
|
-
const workspaceModuleRoot =
|
|
91
|
+
const workspaceModuleRoot = workspaceModuleProject.data.root;
|
|
92
|
+
// data.root is workspace-root-relative in the graph, but may arrive
|
|
93
|
+
// absolute; normalize so the local-path relocation math is in
|
|
94
|
+
// workspace-root space.
|
|
95
|
+
const moduleWsRelativeRoot = (0, path_1.isAbsolute)(workspaceModuleRoot)
|
|
96
|
+
? (0, path_1.relative)(devkit_1.workspaceRoot, workspaceModuleRoot).split(path_1.sep).join('/')
|
|
97
|
+
: workspaceModuleRoot;
|
|
45
98
|
const newWorkspaceModulePath = (0, path_1.join)(workspaceModulesDir, pkgName);
|
|
46
|
-
// Copy the module
|
|
99
|
+
// Copy the module, from the workspace root rather than the process cwd: a
|
|
100
|
+
// graph root arrives workspace-relative in the common case.
|
|
47
101
|
(0, node_fs_1.mkdirSync)(newWorkspaceModulePath, { recursive: true });
|
|
48
|
-
(0, node_fs_1.cpSync)(
|
|
102
|
+
(0, node_fs_1.cpSync)((0, path_1.join)(devkit_1.workspaceRoot, moduleWsRelativeRoot), newWorkspaceModulePath, {
|
|
49
103
|
filter: (src) => !src.includes('node_modules'),
|
|
50
104
|
recursive: true,
|
|
51
105
|
});
|
|
@@ -60,26 +114,75 @@ function handleWorkspaceModules(outputDirectory, packageJson, projectGraph) {
|
|
|
60
114
|
devkit_1.logger.warn(`Could not read package.json for ${pkgName}: ${e.message}`);
|
|
61
115
|
return;
|
|
62
116
|
}
|
|
63
|
-
//
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
117
|
+
// The standalone dist ships no catalog definition, so resolve any
|
|
118
|
+
// `catalog:` references to the version the workspace pinned.
|
|
119
|
+
let packageJsonModified = resolveCatalogReferences(copiedPackageJson, catalogManager);
|
|
120
|
+
// Rewrite sibling workspace-module deps to file: paths and recurse. A peer
|
|
121
|
+
// is moved into dependencies (pnpm rejects a file: spec under
|
|
122
|
+
// peerDependencies), dropping its now-orphaned optional/required marker.
|
|
123
|
+
for (const section of TRANSITIVE_INSTALL_SECTIONS) {
|
|
124
|
+
const deps = copiedPackageJson[section];
|
|
125
|
+
if (!deps) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
for (const depName of Object.keys(deps)) {
|
|
67
129
|
if (workspaceModules.has(depName)) {
|
|
68
|
-
const
|
|
69
|
-
|
|
130
|
+
const fileSpec = `file:${calculateRelativePath(pkgName, depName)}`;
|
|
131
|
+
if (section === 'peerDependencies') {
|
|
132
|
+
(0, internal_1.movePeerDependencyToDependencies)(copiedPackageJson, depName, fileSpec);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
deps[depName] = fileSpec;
|
|
136
|
+
}
|
|
70
137
|
packageJsonModified = true;
|
|
71
138
|
processModule(depName);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
// A non-workspace file:/link: dep must keep resolving after the module
|
|
142
|
+
// moves. pnpm reads a non-importer manifest file: spec relative to the
|
|
143
|
+
// package dir but a link: spec relative to the install root, so each
|
|
144
|
+
// rebases onto a different base (pnpm-only; see isPnpmWorkspace).
|
|
145
|
+
if (!isPnpmWorkspace) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
const spec = deps[depName];
|
|
149
|
+
const relocation = (0, internal_1.relocatePrunedLocalPathSpec)(spec, moduleWsRelativeRoot, spec.startsWith('link:') ? '' : `workspace_modules/${pkgName}`);
|
|
150
|
+
if (!relocation) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (relocation.reason) {
|
|
154
|
+
(0, internal_1.warnUnshippableLocalPathSpec)(`"${spec}" in ${pkgName}`, relocation.reason);
|
|
155
|
+
}
|
|
156
|
+
if (section === 'peerDependencies') {
|
|
157
|
+
// Moved even when the target cannot ship: pnpm rejects the spec here
|
|
158
|
+
// either way.
|
|
159
|
+
(0, internal_1.movePeerDependencyToDependencies)(copiedPackageJson, depName, relocation.spec);
|
|
160
|
+
packageJsonModified = true;
|
|
161
|
+
}
|
|
162
|
+
else if (!relocation.reason) {
|
|
163
|
+
deps[depName] = relocation.spec;
|
|
164
|
+
packageJsonModified = true;
|
|
72
165
|
}
|
|
73
166
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
167
|
+
}
|
|
168
|
+
(0, internal_1.dropEmptyPeerDependencySections)(copiedPackageJson);
|
|
169
|
+
if (packageJsonModified) {
|
|
170
|
+
(0, node_fs_1.writeFileSync)(copiedPackageJsonPath, JSON.stringify(copiedPackageJson, null, 2));
|
|
171
|
+
devkit_1.logger.verbose(`Updated package.json for ${pkgName}.`);
|
|
78
172
|
}
|
|
79
173
|
}
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
174
|
+
// Seed from every section the app declares a workspace module in. Copied
|
|
175
|
+
// modules recurse over production sections only (see processModule).
|
|
176
|
+
// processModule dedups via processedModules, so a module listed in several
|
|
177
|
+
// sections is copied once.
|
|
178
|
+
for (const section of workspace_module_sections_1.WORKSPACE_MODULE_INSTALL_SECTIONS) {
|
|
179
|
+
const deps = packageJson[section];
|
|
180
|
+
if (!deps) {
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
for (const pkgName of Object.keys(deps)) {
|
|
184
|
+
processModule(pkgName);
|
|
185
|
+
}
|
|
83
186
|
}
|
|
84
187
|
}
|
|
85
188
|
function createWorkspaceModules(outputDirectory) {
|
|
@@ -3,48 +3,60 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.default = pruneLockfileExecutor;
|
|
4
4
|
exports.resolveCatalogReferences = resolveCatalogReferences;
|
|
5
5
|
const devkit_1 = require("@nx/devkit");
|
|
6
|
-
const internal_1 = require("@nx/devkit/internal");
|
|
7
6
|
const fs_1 = require("fs");
|
|
8
7
|
const path_1 = require("path");
|
|
8
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
9
9
|
const strip_glob_to_base_dir_1 = require("../../utils/strip-glob-to-base-dir");
|
|
10
|
+
const workspace_module_sections_1 = require("../../utils/workspace-module-sections");
|
|
10
11
|
async function pruneLockfileExecutor(schema, context) {
|
|
11
12
|
devkit_1.logger.log('Pruning lockfile...');
|
|
12
13
|
const outputDirectory = getOutputDir(schema, context);
|
|
13
14
|
const packageJson = resolveCatalogReferences(getPackageJson(schema, context));
|
|
14
15
|
mergeAllowScripts(packageJson);
|
|
15
16
|
const packageManager = (0, devkit_1.detectPackageManager)(devkit_1.workspaceRoot);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
17
|
+
const { project } = (0, devkit_1.parseTargetString)(schema.buildTarget, context);
|
|
18
|
+
const projectRoot = context.projectGraph.nodes[project].data.root;
|
|
19
|
+
(0, internal_1.generatePrunedDeployOutput)(packageJson, context.projectGraph, projectRoot, {
|
|
20
|
+
outputDirectory,
|
|
21
|
+
packageManager,
|
|
22
|
+
workspaceRoot: devkit_1.workspaceRoot,
|
|
23
|
+
});
|
|
24
|
+
rewriteWorkspaceModuleSpecifiers(packageJson, context.projectGraph);
|
|
25
|
+
(0, fs_1.writeFileSync)((0, path_1.join)(outputDirectory, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
26
|
+
devkit_1.logger.log(`Pruned deploy output written to ${outputDirectory}`);
|
|
27
27
|
return {
|
|
28
28
|
success: true,
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
// Point every workspace-module dependency at its copied directory so the
|
|
32
|
+
// standalone output installs them as pnpm `file:` directory dependencies.
|
|
33
|
+
// pnpm rejects a `file:` spec under peerDependencies, so a peer-declared
|
|
34
|
+
// workspace module is moved into dependencies instead (an optional peer
|
|
35
|
+
// becomes required, which is moot since the module is always copied in). Gate
|
|
36
|
+
// strictly on graph membership: a `file:`/`link:` spec to a non-workspace
|
|
37
|
+
// local path (e.g. a vendored tarball) is left alone, since
|
|
38
|
+
// copy-workspace-modules only ever copies actual workspace projects.
|
|
39
|
+
function rewriteWorkspaceModuleSpecifiers(packageJson, graph) {
|
|
35
40
|
const workspacePackages = (0, internal_1.getWorkspacePackagesFromGraph)(graph);
|
|
36
|
-
for (const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
for (const section of workspace_module_sections_1.WORKSPACE_MODULE_INSTALL_SECTIONS) {
|
|
42
|
+
const deps = packageJson[section];
|
|
43
|
+
if (!deps) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
for (const pkgName of Object.keys(deps)) {
|
|
47
|
+
if (!workspacePackages.has(pkgName)) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const fileSpec = `file:./workspace_modules/${pkgName}`;
|
|
51
|
+
if (section === 'peerDependencies') {
|
|
52
|
+
(0, internal_1.movePeerDependencyToDependencies)(packageJson, pkgName, fileSpec);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
deps[pkgName] = fileSpec;
|
|
56
|
+
}
|
|
42
57
|
}
|
|
43
58
|
}
|
|
44
|
-
|
|
45
|
-
lockfileName,
|
|
46
|
-
lockFile,
|
|
47
|
-
};
|
|
59
|
+
(0, internal_1.dropEmptyPeerDependencySections)(packageJson);
|
|
48
60
|
}
|
|
49
61
|
/**
|
|
50
62
|
* npm reads the `allowScripts` install-script allowlist only from the install
|
|
@@ -154,7 +154,7 @@ function compileTSWithWatch(context, logger, hooks, reporters) {
|
|
|
154
154
|
project.kind !== ts.InvalidatedProjectKind.UpdateOutputFileStamps) {
|
|
155
155
|
logger.warn(`The project ${projectName} ` +
|
|
156
156
|
`is using the deprecated "prepend" Typescript compiler option. ` +
|
|
157
|
-
`This option is not supported by the batch executor and it's ignored
|
|
157
|
+
`This option is not supported by the batch executor and it's ignored.`, project.project);
|
|
158
158
|
continue;
|
|
159
159
|
}
|
|
160
160
|
hooks?.beforeProjectCompilationCallback(project.project);
|
|
@@ -41,8 +41,7 @@ export interface LibraryGeneratorSchema {
|
|
|
41
41
|
passWithNoTests?: boolean;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
export interface NormalizedLibraryGeneratorOptions
|
|
45
|
-
extends LibraryGeneratorSchema {
|
|
44
|
+
export interface NormalizedLibraryGeneratorOptions extends LibraryGeneratorSchema {
|
|
46
45
|
name: string;
|
|
47
46
|
/** `normalizeOptions` always resolves this, so it is no longer optional. */
|
|
48
47
|
linter: LinterType;
|
package/dist/src/index.d.ts
CHANGED
|
@@ -18,5 +18,4 @@ export { setupPrettierGenerator } from './generators/setup-prettier/generator';
|
|
|
18
18
|
export { setupVerdaccio } from './generators/setup-verdaccio/generator';
|
|
19
19
|
export { isValidVariable } from './utils/is-valid-variable';
|
|
20
20
|
export { type LinterType } from './utils/linter';
|
|
21
|
-
export { createLockFile, getLockFileName } from '@nx/devkit/internal';
|
|
22
|
-
export { createPackageJson } from '@nx/devkit/internal';
|
|
21
|
+
export { createLockFile, createPackageJson, generatePrunedDeployOutput, getLockFileName, } from '@nx/devkit/internal';
|
package/dist/src/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.getLockFileName = exports.generatePrunedDeployOutput = exports.createPackageJson = exports.createLockFile = exports.isValidVariable = exports.setupVerdaccio = exports.setupPrettierGenerator = exports.setUpFormatter = exports.initGenerator = exports.libraryGenerator = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
tslib_1.__exportStar(require("./utils/typescript/add-tslib-dependencies"), exports);
|
|
6
6
|
tslib_1.__exportStar(require("./utils/typescript/load-ts-transformers"), exports);
|
|
@@ -29,6 +29,6 @@ var is_valid_variable_1 = require("./utils/is-valid-variable");
|
|
|
29
29
|
Object.defineProperty(exports, "isValidVariable", { enumerable: true, get: function () { return is_valid_variable_1.isValidVariable; } });
|
|
30
30
|
var internal_1 = require("@nx/devkit/internal");
|
|
31
31
|
Object.defineProperty(exports, "createLockFile", { enumerable: true, get: function () { return internal_1.createLockFile; } });
|
|
32
|
+
Object.defineProperty(exports, "createPackageJson", { enumerable: true, get: function () { return internal_1.createPackageJson; } });
|
|
33
|
+
Object.defineProperty(exports, "generatePrunedDeployOutput", { enumerable: true, get: function () { return internal_1.generatePrunedDeployOutput; } });
|
|
32
34
|
Object.defineProperty(exports, "getLockFileName", { enumerable: true, get: function () { return internal_1.getLockFileName; } });
|
|
33
|
-
var internal_2 = require("@nx/devkit/internal");
|
|
34
|
-
Object.defineProperty(exports, "createPackageJson", { enumerable: true, get: function () { return internal_2.createPackageJson; } });
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Tree } from '@nx/devkit';
|
|
2
|
+
/**
|
|
3
|
+
* Adds the workspace-root pnpm install settings sources to the `inputs` of
|
|
4
|
+
* build targets that emit the pruned pnpm deploy output. The build approvals
|
|
5
|
+
* and `supportedArchitectures` those outputs carry reach no lockfile, so
|
|
6
|
+
* without these a revoked approval leaves the task hash unchanged and a cached
|
|
7
|
+
* run replays an output that still grants it. Inferred targets are covered by
|
|
8
|
+
* the `@nx/webpack` and `@nx/rspack` plugins themselves; this migration covers
|
|
9
|
+
* the explicitly configured executor targets, plus overlays of inferred
|
|
10
|
+
* targets (a project-level entry, under the exact name or a glob-pattern key
|
|
11
|
+
* matching it, or a matching `targetDefaults` entry) whose replacing `inputs`
|
|
12
|
+
* array discards the plugin-generated one.
|
|
13
|
+
*/
|
|
14
|
+
export default function update(tree: Tree): Promise<void>;
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = update;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
const pnpm_deploy_output_cache_inputs_1 = require("../../utils/pnpm-deploy-output-cache-inputs");
|
|
8
|
+
const target_defaults_matching_1 = require("../../utils/target-defaults-matching");
|
|
9
|
+
// The executors that emit the pruned pnpm deploy output (lockfile,
|
|
10
|
+
// settings-only pnpm-workspace.yaml, patches, vendored local paths), each with
|
|
11
|
+
// the option that turns the emission on. webpack, rspack, vite and esbuild
|
|
12
|
+
// gate it on `generatePackageJson`; next, remix, tsc and swc emit the manifest
|
|
13
|
+
// regardless and gate only the deploy output on `generateLockfile`.
|
|
14
|
+
const DEPLOY_OUTPUT_EXECUTORS = {
|
|
15
|
+
'@nx/webpack:webpack': 'generatePackageJson',
|
|
16
|
+
'@nx/rspack:rspack': 'generatePackageJson',
|
|
17
|
+
'@nx/vite:build': 'generatePackageJson',
|
|
18
|
+
'@nx/esbuild:esbuild': 'generatePackageJson',
|
|
19
|
+
'@nx/next:build': 'generateLockfile',
|
|
20
|
+
'@nx/remix:build': 'generateLockfile',
|
|
21
|
+
'@nx/js:tsc': 'generateLockfile',
|
|
22
|
+
'@nx/js:swc': 'generateLockfile',
|
|
23
|
+
};
|
|
24
|
+
// The config-file plugins whose inferred build target can emit the deploy
|
|
25
|
+
// output (NxAppWebpackPlugin/NxAppRspackPlugin with generatePackageJson).
|
|
26
|
+
// The globs mirror each plugin's own createNodes pattern; the commands are
|
|
27
|
+
// what each plugin sets on the build target it creates.
|
|
28
|
+
const INFERRED_DEPLOY_PLUGINS = {
|
|
29
|
+
'@nx/webpack/plugin': {
|
|
30
|
+
configGlob: '**/webpack.config.{js,ts,mjs,cjs}',
|
|
31
|
+
command: 'webpack-cli build',
|
|
32
|
+
},
|
|
33
|
+
'@nx/rspack/plugin': {
|
|
34
|
+
configGlob: '**/rspack.config.{js,ts,mjs,mts,cjs,cts}',
|
|
35
|
+
command: 'rspack build',
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Adds the workspace-root pnpm install settings sources to the `inputs` of
|
|
40
|
+
* build targets that emit the pruned pnpm deploy output. The build approvals
|
|
41
|
+
* and `supportedArchitectures` those outputs carry reach no lockfile, so
|
|
42
|
+
* without these a revoked approval leaves the task hash unchanged and a cached
|
|
43
|
+
* run replays an output that still grants it. Inferred targets are covered by
|
|
44
|
+
* the `@nx/webpack` and `@nx/rspack` plugins themselves; this migration covers
|
|
45
|
+
* the explicitly configured executor targets, plus overlays of inferred
|
|
46
|
+
* targets (a project-level entry, under the exact name or a glob-pattern key
|
|
47
|
+
* matching it, or a matching `targetDefaults` entry) whose replacing `inputs`
|
|
48
|
+
* array discards the plugin-generated one.
|
|
49
|
+
*/
|
|
50
|
+
async function update(tree) {
|
|
51
|
+
// The deploy output's install settings are pnpm-specific; other package
|
|
52
|
+
// managers' outputs hash everything they are built from already.
|
|
53
|
+
if (!tree.exists('pnpm-lock.yaml')) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const nxJson = (0, devkit_1.readNxJson)(tree);
|
|
57
|
+
const targetDefaults = nxJson?.targetDefaults;
|
|
58
|
+
const projects = new Map();
|
|
59
|
+
const changedProjects = new Set();
|
|
60
|
+
let defaultsChanged = false;
|
|
61
|
+
for (const [projectName, project] of (0, devkit_1.getProjects)(tree)) {
|
|
62
|
+
projects.set(projectName, project);
|
|
63
|
+
const projectNode = {
|
|
64
|
+
name: projectName,
|
|
65
|
+
type: 'lib',
|
|
66
|
+
data: { root: project.root, tags: project.tags },
|
|
67
|
+
};
|
|
68
|
+
for (const [targetName, target] of Object.entries(project.targets ?? {})) {
|
|
69
|
+
// The executor may come from a matching targetDefaults entry rather
|
|
70
|
+
// than the target itself. A `command` target resolves to nx:run-commands
|
|
71
|
+
// before defaults apply, so a default can never re-identify it.
|
|
72
|
+
const executor = target.executor ??
|
|
73
|
+
(target.command
|
|
74
|
+
? 'nx:run-commands'
|
|
75
|
+
: (0, target_defaults_matching_1.resolveDefaultsExecutor)(targetName, projectName, projectNode, targetDefaults));
|
|
76
|
+
if (!executor || !DEPLOY_OUTPUT_EXECUTORS[executor]) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const ref = {
|
|
80
|
+
targetName,
|
|
81
|
+
projectName,
|
|
82
|
+
projectNode,
|
|
83
|
+
matcherExecutor: target.executor,
|
|
84
|
+
target,
|
|
85
|
+
};
|
|
86
|
+
const selectedKey = targetDefaults
|
|
87
|
+
? (0, target_defaults_matching_1.selectDefaultsKey)(ref, targetDefaults, executor)
|
|
88
|
+
: null;
|
|
89
|
+
const entries = (0, target_defaults_matching_1.compatibleDefaultsEntries)(ref, selectedKey, targetDefaults);
|
|
90
|
+
const defaults = entries.length
|
|
91
|
+
? (0, internal_1.readTargetDefaultsForTarget)(targetName, { [selectedKey]: entries }, ref.matcherExecutor, { projectName, projectNode })
|
|
92
|
+
: null;
|
|
93
|
+
// The effective view, not the target's own: the gating option may be
|
|
94
|
+
// supplied by a matching defaults entry or set only in a configuration.
|
|
95
|
+
const effective = (0, internal_1.mergeTargetConfigurations)(target, defaults ?? {});
|
|
96
|
+
if (!emitsDeployOutput(effective, DEPLOY_OUTPUT_EXECUTORS[executor])) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const changed = (0, pnpm_deploy_output_cache_inputs_1.addPnpmDeployOutputCacheInputs)(ref, targetDefaults, executor);
|
|
100
|
+
if (changed === 'target') {
|
|
101
|
+
changedProjects.add(projectName);
|
|
102
|
+
}
|
|
103
|
+
else if (changed === 'defaults') {
|
|
104
|
+
defaultsChanged = true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Overlays of plugin-inferred build targets carry no executor, so the loop
|
|
109
|
+
// above cannot see them, yet a replacing `inputs` array in one discards the
|
|
110
|
+
// settings inputs the plugin generates. The plugin adds those inputs without
|
|
111
|
+
// knowing whether the config enables generatePackageJson (that lives inside
|
|
112
|
+
// the user's config file), so the overlay repair is equally unconditional.
|
|
113
|
+
// It appends the runtime probe even where the plugin omits it under a valid
|
|
114
|
+
// pnpm pin: the repair runs once and the pin can be removed later.
|
|
115
|
+
for (const ref of await inferredDeployTargetOverlayRefs(tree, nxJson, projects)) {
|
|
116
|
+
const changed = (0, pnpm_deploy_output_cache_inputs_1.addPnpmDeployOutputCacheInputsToInferredTargetOverlay)(ref, targetDefaults);
|
|
117
|
+
if (changed === 'target') {
|
|
118
|
+
changedProjects.add(ref.projectName);
|
|
119
|
+
}
|
|
120
|
+
else if (changed === 'defaults') {
|
|
121
|
+
defaultsChanged = true;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
for (const projectName of changedProjects) {
|
|
125
|
+
(0, devkit_1.updateProjectConfiguration)(tree, projectName, projects.get(projectName));
|
|
126
|
+
}
|
|
127
|
+
if (defaultsChanged) {
|
|
128
|
+
(0, devkit_1.updateNxJson)(tree, nxJson);
|
|
129
|
+
}
|
|
130
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* One ref per (project, inferred build target) the registered `@nx/webpack` or
|
|
134
|
+
* `@nx/rspack` config-file plugins would create, resolved the way the plugins
|
|
135
|
+
* do: their createNodes glob filtered by each registration's include/exclude,
|
|
136
|
+
* the config file's directory as the project root, and the registration's
|
|
137
|
+
* `buildTargetName` option. The overlaying project-level entry may sit under
|
|
138
|
+
* the exact target name or a glob-pattern key matching it; one that replaces
|
|
139
|
+
* what the target runs disqualifies the target instead.
|
|
140
|
+
*/
|
|
141
|
+
async function inferredDeployTargetOverlayRefs(tree, nxJson, projects) {
|
|
142
|
+
const rootToProject = new Map();
|
|
143
|
+
for (const [projectName, project] of projects) {
|
|
144
|
+
rootToProject.set(project.root, projectName);
|
|
145
|
+
}
|
|
146
|
+
const refs = [];
|
|
147
|
+
for (const registration of nxJson?.plugins ?? []) {
|
|
148
|
+
const pluginName = typeof registration === 'string' ? registration : registration.plugin;
|
|
149
|
+
const inferredPlugin = INFERRED_DEPLOY_PLUGINS[pluginName];
|
|
150
|
+
if (!inferredPlugin) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
const options = typeof registration === 'string'
|
|
154
|
+
? undefined
|
|
155
|
+
: registration.options;
|
|
156
|
+
const targetName = options?.buildTargetName ?? 'build';
|
|
157
|
+
const configFiles = (0, internal_1.findMatchingConfigFiles)(await (0, devkit_1.globAsync)(tree, [inferredPlugin.configGlob]), typeof registration === 'string' ? undefined : registration.include, typeof registration === 'string' ? undefined : registration.exclude);
|
|
158
|
+
for (const configFile of configFiles) {
|
|
159
|
+
const projectName = rootToProject.get((0, path_1.dirname)(configFile));
|
|
160
|
+
if (!projectName) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const project = projects.get(projectName);
|
|
164
|
+
const target = inferredTargetOverlayEntry(project.targets, targetName);
|
|
165
|
+
// An entry that changes what the target runs is not an overlay; the
|
|
166
|
+
// executor loop covers the deploy executors among those.
|
|
167
|
+
if (target &&
|
|
168
|
+
replacesInferredRunCommandsIdentity(target, inferredPlugin.command, project.root)) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
refs.push({
|
|
172
|
+
targetName,
|
|
173
|
+
projectName,
|
|
174
|
+
projectNode: {
|
|
175
|
+
name: projectName,
|
|
176
|
+
type: 'lib',
|
|
177
|
+
data: { root: project.root, tags: project.tags },
|
|
178
|
+
},
|
|
179
|
+
// the runtime matcher sees the plugin target's effective identity:
|
|
180
|
+
// its `command` payload resolves to nx:run-commands
|
|
181
|
+
matcherExecutor: 'nx:run-commands',
|
|
182
|
+
// the runtime drops the plugin attribution as soon as the project
|
|
183
|
+
// entry authors an executor or command, restated or not, so a
|
|
184
|
+
// plugin-filtered defaults entry no longer applies to the target
|
|
185
|
+
sourcePlugin: target?.executor !== undefined || target?.command !== undefined
|
|
186
|
+
? undefined
|
|
187
|
+
: pluginName,
|
|
188
|
+
target: target ?? {},
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return refs;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* The project-level entry that overlays the inferred `targetName`. Its key is
|
|
196
|
+
* the exact name or a glob pattern the name matches; the inferred target
|
|
197
|
+
* exists before any project-level entry merges, so a matching glob key
|
|
198
|
+
* overlays it too. When several keys match, each entry merges against the
|
|
199
|
+
* inferred target independently and the last write wins, so only the last
|
|
200
|
+
* one applies. A glob key matching an earlier same-file sibling never
|
|
201
|
+
* surfaces here: the project read already collapsed it onto that sibling and
|
|
202
|
+
* dropped the key.
|
|
203
|
+
*/
|
|
204
|
+
function inferredTargetOverlayEntry(targets, targetName) {
|
|
205
|
+
const matching = Object.entries(targets ?? {}).filter(([key]) => key === targetName ||
|
|
206
|
+
(0, internal_1.findMatchingTargetNames)(key, [targetName]).length > 0);
|
|
207
|
+
return matching[matching.length - 1]?.[1];
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Whether the entry changes what the inferred run-commands target runs when
|
|
211
|
+
* merged, resolved with nx's own merge so `"..."` placement and restated
|
|
212
|
+
* identities land the way the runtime lands them: a merged executor other
|
|
213
|
+
* than nx:run-commands, an effective command differing from the plugin's, or
|
|
214
|
+
* a `command`/`commands` clash the run-commands schema rejects. An entry
|
|
215
|
+
* restating the identity the plugin infers is still an overlay.
|
|
216
|
+
*/
|
|
217
|
+
function replacesInferredRunCommandsIdentity(target, inferredCommand, projectRoot) {
|
|
218
|
+
// `command` alongside `executor` fails graph construction outright;
|
|
219
|
+
// there is nothing running to repair.
|
|
220
|
+
if (target.command && target.executor) {
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
const merged = (0, internal_1.mergeTargetConfigurations)((0, internal_1.resolveCommandSyntacticSugar)(target, projectRoot), { executor: 'nx:run-commands', options: { command: inferredCommand } });
|
|
224
|
+
if (merged.executor !== 'nx:run-commands') {
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
// Both present fails the run-commands schema's oneOf; the target cannot run.
|
|
228
|
+
if (merged.options?.command && merged.options?.commands) {
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
const command = merged.options?.command ?? merged.options?.commands?.join(' && ');
|
|
232
|
+
return command !== inferredCommand;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Whether the target ships the deploy output in any of its runs: the gating
|
|
236
|
+
* option can sit in `options` or in any configuration, and `inputs` cannot
|
|
237
|
+
* vary per configuration, so one enabled configuration is enough.
|
|
238
|
+
*/
|
|
239
|
+
function emitsDeployOutput(effective, gate) {
|
|
240
|
+
return (Boolean(effective.options?.[gate]) ||
|
|
241
|
+
Object.values(effective.configurations ?? {}).some((configuration) => Boolean(configuration?.[gate])));
|
|
242
|
+
}
|