@nx/js 0.0.0-pr-3-e51e28c → 0.0.0-pr-30418-4e2b721

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/js",
3
- "version": "0.0.0-pr-3-e51e28c",
3
+ "version": "0.0.0-pr-30418-4e2b721",
4
4
  "private": false,
5
5
  "description": "The JS plugin for Nx contains executors and generators that provide the best experience for developing JavaScript and TypeScript projects. ",
6
6
  "repository": {
@@ -39,8 +39,8 @@
39
39
  "@babel/preset-env": "^7.23.2",
40
40
  "@babel/preset-typescript": "^7.22.5",
41
41
  "@babel/runtime": "^7.22.6",
42
- "@nx/devkit": "0.0.0-pr-3-e51e28c",
43
- "@nx/workspace": "0.0.0-pr-3-e51e28c",
42
+ "@nx/devkit": "0.0.0-pr-30418-4e2b721",
43
+ "@nx/workspace": "0.0.0-pr-30418-4e2b721",
44
44
  "@zkochan/js-yaml": "0.0.7",
45
45
  "babel-plugin-const-enum": "^1.0.1",
46
46
  "babel-plugin-macros": "^3.1.0",
@@ -52,10 +52,11 @@
52
52
  "ignore": "^5.0.4",
53
53
  "js-tokens": "^4.0.0",
54
54
  "jsonc-parser": "3.2.0",
55
- "minimatch": "9.0.3",
56
55
  "npm-package-arg": "11.0.1",
57
56
  "npm-run-path": "^4.0.1",
58
57
  "ora": "5.3.0",
58
+ "picocolors": "^1.1.0",
59
+ "picomatch": "4.0.2",
59
60
  "semver": "^7.5.3",
60
61
  "source-map-support": "0.5.19",
61
62
  "tinyglobby": "^0.2.10",
@@ -298,7 +298,7 @@ function getFileToRun(context, project, buildOptions, buildTargetExecutor) {
298
298
  const outputFilePath = (0, utils_1.interpolate)(outputPath, {
299
299
  projectName: project.name,
300
300
  projectRoot: project.data.root,
301
- workspaceRoot: '',
301
+ workspaceRoot: context.root,
302
302
  });
303
303
  return path.join(outputFilePath, 'main.js');
304
304
  }
@@ -54,8 +54,7 @@ async function initGeneratorInternal(tree, schema) {
54
54
  schema.addPlugin ??=
55
55
  process.env.NX_ADD_PLUGINS !== 'false' &&
56
56
  nxJson.useInferencePlugins !== false;
57
- schema.addTsPlugin ??=
58
- schema.addPlugin && process.env.NX_ADD_TS_PLUGIN !== 'false';
57
+ schema.addTsPlugin ??= schema.addPlugin;
59
58
  if (schema.addTsPlugin) {
60
59
  await (0, add_plugin_1.addPlugin)(tree, await (0, devkit_1.createProjectGraphAsync)(), '@nx/js/typescript', plugin_1.createNodesV2, {
61
60
  typecheck: [
@@ -22,7 +22,6 @@ const ts_solution_setup_1 = require("../../utils/typescript/ts-solution-setup");
22
22
  const versions_1 = require("../../utils/versions");
23
23
  const init_1 = require("../init/init");
24
24
  const sort_fields_1 = require("../../utils/package-json/sort-fields");
25
- const get_import_path_1 = require("../../utils/get-import-path");
26
25
  const add_release_config_1 = require("./utils/add-release-config");
27
26
  const defaultOutputDirectory = 'dist';
28
27
  async function libraryGenerator(tree, schema) {
@@ -43,16 +42,16 @@ async function libraryGeneratorInternal(tree, schema) {
43
42
  formatter: (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree) ? 'none' : 'prettier',
44
43
  }));
45
44
  const options = await normalizeOptions(tree, schema);
46
- // If we are using the new TS solution
47
- // We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
48
- if (options.isUsingTsSolutionConfig) {
49
- (0, ts_solution_setup_1.addProjectToTsSolutionWorkspace)(tree, options.projectRoot);
50
- }
51
45
  createFiles(tree, options);
52
46
  await configureProject(tree, options);
53
47
  if (!options.skipPackageJson) {
54
48
  tasks.push(addProjectDependencies(tree, options));
55
49
  }
50
+ // If we are using the new TS solution
51
+ // We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
52
+ if (options.isUsingTsSolutionConfig) {
53
+ await (0, ts_solution_setup_1.addProjectToTsSolutionWorkspace)(tree, options.projectRoot);
54
+ }
56
55
  if (options.bundler === 'rollup') {
57
56
  const { configurationGenerator } = (0, devkit_1.ensurePackage)('@nx/rollup', versions_1.nxVersion);
58
57
  await configurationGenerator(tree, {
@@ -161,7 +160,7 @@ async function libraryGeneratorInternal(tree, schema) {
161
160
  async function configureProject(tree, options) {
162
161
  if (options.hasPlugin) {
163
162
  const nxJson = (0, devkit_1.readNxJson)(tree);
164
- (0, plugin_1.ensureProjectIsIncludedInPluginRegistrations)(nxJson, options.projectRoot);
163
+ (0, plugin_1.ensureProjectIsIncludedInPluginRegistrations)(nxJson, options.projectRoot, options.bundler === 'none' ? null : 'build');
165
164
  (0, devkit_1.updateNxJson)(tree, nxJson);
166
165
  }
167
166
  const projectConfiguration = {
@@ -236,9 +235,7 @@ async function configureProject(tree, options) {
236
235
  }
237
236
  }
238
237
  // empty targets are cleaned up automatically by `updateProjectConfiguration`
239
- (0, devkit_1.updateProjectConfiguration)(tree, options.isUsingTsSolutionConfig
240
- ? options.importPath ?? options.name
241
- : options.name, projectConfiguration);
238
+ (0, devkit_1.updateProjectConfiguration)(tree, options.name, projectConfiguration);
242
239
  }
243
240
  else if (options.config === 'workspace' || options.config === 'project') {
244
241
  (0, devkit_1.addProjectConfiguration)(tree, options.name, projectConfiguration);
@@ -468,6 +465,11 @@ function createFiles(tree, options) {
468
465
  format: ['esm'],
469
466
  });
470
467
  }
468
+ if (!options.useProjectJson && options.name !== options.importPath) {
469
+ packageJson.nx = {
470
+ name: options.name,
471
+ };
472
+ }
471
473
  (0, devkit_1.writeJson)(tree, packageJsonPath, packageJson);
472
474
  }
473
475
  if (options.config === 'npm-scripts') {
@@ -527,7 +529,7 @@ function replaceJestConfig(tree, options) {
527
529
  });
528
530
  }
529
531
  async function normalizeOptions(tree, options) {
530
- await (0, project_name_and_root_utils_1.ensureProjectName)(tree, options, 'library');
532
+ await (0, project_name_and_root_utils_1.ensureRootProjectName)(options, 'library');
531
533
  const nxJson = (0, devkit_1.readNxJson)(tree);
532
534
  options.addPlugin ??=
533
535
  process.env.NX_ADD_PLUGINS !== 'false' &&
@@ -629,9 +631,7 @@ async function normalizeOptions(tree, options) {
629
631
  return {
630
632
  ...options,
631
633
  fileName,
632
- name: isUsingTsSolutionConfig
633
- ? (0, get_import_path_1.getImportPath)(tree, projectName)
634
- : projectName,
634
+ name: isUsingTsSolutionConfig && !options.name ? importPath : projectName,
635
635
  projectNames,
636
636
  projectRoot,
637
637
  parsedTags,
@@ -719,9 +719,7 @@ function createProjectTsConfigs(tree, options) {
719
719
  .map(([k, v]) => `${JSON.stringify(k)}: ${JSON.stringify(v)}`)
720
720
  .join(',\n '),
721
721
  tmpl: '',
722
- outDir: options.bundler === 'tsc'
723
- ? 'dist'
724
- : `out-tsc/${options.projectRoot.split('/').pop()}`,
722
+ outDir: 'dist',
725
723
  emitDeclarationOnly: options.bundler === 'tsc' ? false : true,
726
724
  });
727
725
  // tsconfig.json
@@ -734,6 +732,12 @@ function createProjectTsConfigs(tree, options) {
734
732
  json.references.push({
735
733
  path: './tsconfig.lib.json',
736
734
  });
735
+ // If using `tsc` to build, then we do not want a typecheck target that duplicates the work, since both run `tsc`.
736
+ // This applies to `@nx/js/typescript` plugin only.
737
+ if (options.bundler === 'tsc') {
738
+ json['nx'] ??= {};
739
+ json['nx'].addTypecheckTarget = false;
740
+ }
737
741
  return json;
738
742
  });
739
743
  }
@@ -745,6 +749,12 @@ function createProjectTsConfigs(tree, options) {
745
749
  include: [],
746
750
  references: [{ path: './tsconfig.lib.json' }],
747
751
  };
752
+ // If using `tsc` to build, then we do not want a typecheck target that duplicates the work, since both run `tsc`.
753
+ // This applies to `@nx/js/typescript` plugin only.
754
+ if (options.bundler === 'tsc') {
755
+ tsconfig['nx'] ??= {};
756
+ tsconfig['nx'].addTypecheckTarget = false;
757
+ }
748
758
  (0, devkit_1.writeJson)(tree, (0, devkit_1.joinPathFragments)(options.projectRoot, 'tsconfig.json'), tsconfig);
749
759
  // update root project tsconfig.json references with the new lib tsconfig
750
760
  (0, devkit_1.updateJson)(tree, 'tsconfig.json', (json) => {
@@ -666,7 +666,10 @@ To fix this you will either need to add a package.json file at that location, or
666
666
  deletedFiles.push(...(await cb(opts.dryRun)));
667
667
  }
668
668
  const cwd = tree.root;
669
- changedFiles.push(...(await (0, update_lock_file_1.updateLockFile)(cwd, opts)));
669
+ changedFiles.push(...(await (0, update_lock_file_1.updateLockFile)(cwd, {
670
+ ...opts,
671
+ useLegacyVersioning: true,
672
+ })));
670
673
  return { changedFiles, deletedFiles };
671
674
  },
672
675
  };
@@ -1 +1 @@
1
- export { ReleaseVersionGeneratorSchema } from 'nx/src/command-line/release/version';
1
+ export { ReleaseVersionGeneratorSchema } from 'nx/src/command-line/release/version-legacy';
@@ -8,6 +8,8 @@
8
8
  "properties": {
9
9
  "projects": {
10
10
  "type": "array",
11
+ "hidden": true,
12
+ "$comment": "This is not configured/passed by the user. It is provided by the version command.",
11
13
  "description": "The ProjectGraphProjectNodes being versioned in the current execution.",
12
14
  "items": {
13
15
  "type": "object"
@@ -15,16 +17,33 @@
15
17
  },
16
18
  "projectGraph": {
17
19
  "type": "object",
20
+ "hidden": true,
21
+ "$comment": "This is not configured/passed by the user. It is provided by the version command.",
18
22
  "description": "ProjectGraph instance"
19
23
  },
20
- "specifier": {
21
- "type": "string",
22
- "description": "Exact version or semver keyword to apply to the selected release group. Overrides specifierSource."
23
- },
24
24
  "releaseGroup": {
25
25
  "type": "object",
26
+ "hidden": true,
27
+ "$comment": "This is not configured/passed by the user. It is provided by the version command.",
26
28
  "description": "The resolved release group configuration, including name, relevant to all projects in the current execution."
27
29
  },
30
+ "conventionalCommitsConfig": {
31
+ "type": "object",
32
+ "hidden": true,
33
+ "$comment": "This is not configured/passed by the user. It is provided by the version command.",
34
+ "description": "The conventional commits configuration to use when determining the next version of the project.",
35
+ "default": {}
36
+ },
37
+ "firstRelease": {
38
+ "type": "boolean",
39
+ "hidden": true,
40
+ "$comment": "This is not configured/passed by the user. It is provided by the version command.",
41
+ "description": "Whether this is the first release of the project (which skips some validation within the generator)."
42
+ },
43
+ "specifier": {
44
+ "type": "string",
45
+ "description": "Exact version or semver keyword to apply to the selected release group. Overrides specifierSource."
46
+ },
28
47
  "specifierSource": {
29
48
  "type": "string",
30
49
  "default": "prompt",
@@ -1,5 +1,10 @@
1
- export declare function updateLockFile(cwd: string, { dryRun, verbose, generatorOptions, }: {
1
+ export declare function updateLockFile(cwd: string, { dryRun, verbose, useLegacyVersioning, options, }: {
2
2
  dryRun?: boolean;
3
3
  verbose?: boolean;
4
- generatorOptions?: Record<string, unknown>;
4
+ useLegacyVersioning?: boolean;
5
+ options?: {
6
+ skipLockFileUpdate?: boolean;
7
+ installArgs?: string;
8
+ installIgnoreScripts?: boolean;
9
+ };
5
10
  }): Promise<string[]>;
@@ -7,8 +7,8 @@ const client_1 = require("nx/src/daemon/client/client");
7
7
  // eslint-disable-next-line @typescript-eslint/no-restricted-imports
8
8
  const lock_file_1 = require("nx/src/plugins/js/lock-file/lock-file");
9
9
  const semver_1 = require("semver");
10
- async function updateLockFile(cwd, { dryRun, verbose, generatorOptions, }) {
11
- if (generatorOptions?.skipLockFileUpdate) {
10
+ async function updateLockFile(cwd, { dryRun, verbose, useLegacyVersioning, options, }) {
11
+ if (options?.skipLockFileUpdate) {
12
12
  if (verbose) {
13
13
  console.log('\nSkipped lock file update because skipLockFileUpdate was set.');
14
14
  }
@@ -36,10 +36,10 @@ async function updateLockFile(cwd, { dryRun, verbose, generatorOptions, }) {
36
36
  await client_1.daemonClient.stop();
37
37
  }
38
38
  const packageManagerCommands = (0, devkit_1.getPackageManagerCommand)(packageManager);
39
- let installArgs = generatorOptions?.installArgs || '';
39
+ let installArgs = options?.installArgs || '';
40
40
  devkit_1.output.logSingleLine(`Updating ${packageManager} lock file`);
41
41
  let env = {};
42
- if (generatorOptions?.installIgnoreScripts) {
42
+ if (options?.installIgnoreScripts) {
43
43
  if (packageManager === 'yarn') {
44
44
  env = { YARN_ENABLE_SCRIPTS: 'false' };
45
45
  }
@@ -62,7 +62,7 @@ async function updateLockFile(cwd, { dryRun, verbose, generatorOptions, }) {
62
62
  if (dryRun) {
63
63
  return [];
64
64
  }
65
- execLockFileUpdate(command, cwd, env);
65
+ execLockFileUpdate(command, cwd, env, useLegacyVersioning);
66
66
  if (isDaemonEnabled) {
67
67
  try {
68
68
  await client_1.daemonClient.startInBackground();
@@ -79,7 +79,7 @@ async function updateLockFile(cwd, { dryRun, verbose, generatorOptions, }) {
79
79
  }
80
80
  return [lockFile];
81
81
  }
82
- function execLockFileUpdate(command, cwd, env = {}) {
82
+ function execLockFileUpdate(command, cwd, env, useLegacyVersioning) {
83
83
  try {
84
84
  const LARGE_BUFFER = 1024 * 1000000;
85
85
  (0, child_process_1.execSync)(command, {
@@ -93,13 +93,16 @@ function execLockFileUpdate(command, cwd, env = {}) {
93
93
  });
94
94
  }
95
95
  catch (e) {
96
+ const configPathStart = useLegacyVersioning
97
+ ? 'release.version.generatorOptions'
98
+ : 'release.version.versionActionsOptions';
96
99
  devkit_1.output.error({
97
100
  title: `Error updating lock file with command '${command}'`,
98
101
  bodyLines: [
99
102
  `Verify that '${command}' succeeds when run from the workspace root.`,
100
- `To configure a string of arguments to be passed to this command, set the 'release.version.generatorOptions.installArgs' property in nx.json.`,
101
- `To ignore install lifecycle scripts, set 'release.version.generatorOptions.installIgnoreScripts' to true in nx.json.`,
102
- `To disable this step entirely, set 'release.version.generatorOptions.skipLockFileUpdate' to true in nx.json.`,
103
+ `To configure a string of arguments to be passed to this command, set the '${configPathStart}.installArgs' property in nx.json.`,
104
+ `To ignore install lifecycle scripts, set '${configPathStart}.installIgnoreScripts' to true in nx.json.`,
105
+ `To disable this step entirely, set '${configPathStart}.skipLockFileUpdate' to true in nx.json.`,
103
106
  ],
104
107
  });
105
108
  throw e;
@@ -0,0 +1,28 @@
1
+ import { ProjectGraph, Tree } from '@nx/devkit';
2
+ import { ManifestData, VersionActions } from 'nx/release';
3
+ import type { NxReleaseVersionV2Configuration } from 'nx/src/config/nx-json';
4
+ export default class JsVersionActions extends VersionActions {
5
+ manifestFilename: string;
6
+ static createAfterAllProjectsVersionedCallback(cwd: string, opts: {
7
+ dryRun?: boolean;
8
+ verbose?: boolean;
9
+ versionActionsOptions?: Record<string, unknown>;
10
+ }): () => Promise<{
11
+ changedFiles: string[];
12
+ deletedFiles: any[];
13
+ }>;
14
+ readSourceManifestData(tree: Tree): Promise<ManifestData>;
15
+ readCurrentVersionFromSourceManifest(tree: Tree): Promise<string>;
16
+ readCurrentVersionFromRegistry(tree: Tree, currentVersionResolverMetadata: NxReleaseVersionV2Configuration['currentVersionResolverMetadata']): Promise<{
17
+ currentVersion: string;
18
+ logText: string;
19
+ }>;
20
+ getCurrentVersionOfDependency(tree: Tree, projectGraph: ProjectGraph, dependencyProjectName: string): Promise<{
21
+ currentVersion: string | null;
22
+ dependencyCollection: string | null;
23
+ }>;
24
+ isLocalDependencyProtocol(versionSpecifier: string): boolean;
25
+ writeVersionToManifests(tree: Tree, newVersion: string): Promise<void>;
26
+ updateDependencies(tree: Tree, projectGraph: ProjectGraph, dependenciesToUpdate: Record<string, string>): Promise<void>;
27
+ private parseDependencies;
28
+ }
@@ -0,0 +1,213 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const devkit_1 = require("@nx/devkit");
4
+ const node_child_process_1 = require("node:child_process");
5
+ const node_path_1 = require("node:path");
6
+ const release_1 = require("nx/release");
7
+ const npm_config_1 = require("../../utils/npm-config");
8
+ const resolve_version_spec_1 = require("./utils/resolve-version-spec");
9
+ const update_lock_file_1 = require("./utils/update-lock-file");
10
+ const chalk = require("chalk");
11
+ // Cache at the module level to avoid re-detecting the package manager for each instance
12
+ let pm;
13
+ class JsVersionActions extends release_1.VersionActions {
14
+ constructor() {
15
+ super(...arguments);
16
+ this.manifestFilename = 'package.json';
17
+ }
18
+ static createAfterAllProjectsVersionedCallback(cwd, opts) {
19
+ return async () => {
20
+ return {
21
+ changedFiles: await (0, update_lock_file_1.updateLockFile)(cwd, {
22
+ ...opts,
23
+ useLegacyVersioning: false,
24
+ }),
25
+ deletedFiles: [],
26
+ };
27
+ };
28
+ }
29
+ async readSourceManifestData(tree) {
30
+ const sourcePackageJsonPath = this.getSourceManifestPath();
31
+ try {
32
+ const packageJson = (0, devkit_1.readJson)(tree, sourcePackageJsonPath);
33
+ const dependencies = this.parseDependencies(packageJson);
34
+ return {
35
+ name: packageJson.name,
36
+ currentVersion: packageJson.version,
37
+ dependencies,
38
+ };
39
+ }
40
+ catch {
41
+ throw new Error(`Unable to read the package.json file at ${sourcePackageJsonPath}, please ensure that the file exists and is valid`);
42
+ }
43
+ }
44
+ async readCurrentVersionFromSourceManifest(tree) {
45
+ const sourcePackageJsonPath = this.getSourceManifestPath();
46
+ try {
47
+ const packageJson = (0, devkit_1.readJson)(tree, sourcePackageJsonPath);
48
+ return packageJson.version;
49
+ }
50
+ catch {
51
+ throw new Error(`Unable to determine the current version for project "${this.projectGraphNode.name}" from ${sourcePackageJsonPath}, please ensure that the "version" field is set within the package.json file`);
52
+ }
53
+ }
54
+ async readCurrentVersionFromRegistry(tree, currentVersionResolverMetadata) {
55
+ const sourceManifestPath = this.getSourceManifestPath();
56
+ const sourceManifestRoot = (0, node_path_1.dirname)(sourceManifestPath);
57
+ const packageJson = (0, devkit_1.readJson)(tree, sourceManifestPath);
58
+ const packageName = packageJson.name;
59
+ const metadata = currentVersionResolverMetadata;
60
+ const registryArg = typeof metadata?.registry === 'string' ? metadata.registry : undefined;
61
+ const tagArg = typeof metadata?.tag === 'string' ? metadata.tag : undefined;
62
+ const warnFn = (message) => {
63
+ console.log(chalk.keyword('orange')(message));
64
+ };
65
+ const { registry, tag, registryConfigKey } = await (0, npm_config_1.parseRegistryOptions)(devkit_1.workspaceRoot, {
66
+ packageRoot: sourceManifestRoot,
67
+ packageJson,
68
+ }, {
69
+ registry: registryArg,
70
+ tag: tagArg,
71
+ }, warnFn);
72
+ let currentVersion = null;
73
+ try {
74
+ // Must be non-blocking async to allow spinner to render
75
+ currentVersion = await new Promise((resolve, reject) => {
76
+ (0, node_child_process_1.exec)(`npm view ${packageName} version --"${registryConfigKey}=${registry}" --tag=${tag}`, {
77
+ windowsHide: false,
78
+ }, (error, stdout, stderr) => {
79
+ if (error) {
80
+ return reject(error);
81
+ }
82
+ if (stderr) {
83
+ return reject(stderr);
84
+ }
85
+ return resolve(stdout.trim());
86
+ });
87
+ });
88
+ }
89
+ catch { }
90
+ return {
91
+ currentVersion,
92
+ // Make troubleshooting easier by including the registry and tag data in the log text
93
+ logText: `"${registryConfigKey}=${registry}" tag=${tag}`,
94
+ };
95
+ }
96
+ async getCurrentVersionOfDependency(tree, projectGraph, dependencyProjectName) {
97
+ const json = (0, devkit_1.readJson)(tree, this.getSourceManifestPath());
98
+ // Resolve the package name from the project graph metadata, as it may not match the project name
99
+ const dependencyPackageName = projectGraph.nodes[dependencyProjectName].data.metadata?.js?.packageName;
100
+ const dependencyTypes = [
101
+ 'dependencies',
102
+ 'devDependencies',
103
+ 'peerDependencies',
104
+ 'optionalDependencies',
105
+ ];
106
+ let currentVersion = null;
107
+ let dependencyCollection = null;
108
+ for (const depType of dependencyTypes) {
109
+ if (json[depType] && json[depType][dependencyPackageName]) {
110
+ currentVersion = json[depType][dependencyPackageName];
111
+ dependencyCollection = depType;
112
+ break;
113
+ }
114
+ }
115
+ return {
116
+ currentVersion,
117
+ dependencyCollection,
118
+ };
119
+ }
120
+ // NOTE: The TODOs were carried over from the original implementation, they are not yet implemented
121
+ isLocalDependencyProtocol(versionSpecifier) {
122
+ const localPackageProtocols = [
123
+ 'file:', // all package managers
124
+ 'workspace:', // not npm
125
+ // TODO: Support portal protocol at the project graph level before enabling here
126
+ // 'portal:', // modern yarn only
127
+ ];
128
+ // Not using a supported local protocol
129
+ if (!localPackageProtocols.some((protocol) => versionSpecifier.startsWith(protocol))) {
130
+ return false;
131
+ }
132
+ // Supported by all package managers
133
+ if (versionSpecifier.startsWith('file:')) {
134
+ return true;
135
+ }
136
+ // Determine specific package manager in use
137
+ if (!pm) {
138
+ pm = (0, devkit_1.detectPackageManager)();
139
+ // pmVersion = getPackageManagerVersion(pm);
140
+ }
141
+ if (pm === 'npm' && versionSpecifier.startsWith('workspace:')) {
142
+ throw new Error(`The "workspace:" protocol is not yet supported by npm (https://github.com/npm/rfcs/issues/765). Please ensure you have a valid setup according to your package manager before attempting to release packages.`);
143
+ }
144
+ // TODO: Support portal protocol at the project graph level before enabling here
145
+ // if (
146
+ // version.startsWith('portal:') &&
147
+ // (pm !== 'yarn' || lt(pmVersion, '2.0.0'))
148
+ // ) {
149
+ // throw new Error(
150
+ // `The "portal:" protocol is only supported by yarn@2.0.0 and above. Please ensure you have a valid setup according to your package manager before attempting to release packages.`
151
+ // );
152
+ // }
153
+ return true;
154
+ }
155
+ async writeVersionToManifests(tree, newVersion) {
156
+ for (const manifestPath of this.manifestsToUpdate) {
157
+ (0, devkit_1.updateJson)(tree, manifestPath, (json) => {
158
+ json.version = newVersion;
159
+ return json;
160
+ });
161
+ }
162
+ }
163
+ async updateDependencies(tree, projectGraph, dependenciesToUpdate) {
164
+ for (const manifestPath of this.manifestsToUpdate) {
165
+ (0, devkit_1.updateJson)(tree, manifestPath, (json) => {
166
+ const dependencyTypes = [
167
+ 'dependencies',
168
+ 'devDependencies',
169
+ 'peerDependencies',
170
+ 'optionalDependencies',
171
+ ];
172
+ for (const depType of dependencyTypes) {
173
+ if (json[depType]) {
174
+ for (const [dep, version] of Object.entries(dependenciesToUpdate)) {
175
+ // Resolve the package name from the project graph metadata, as it may not match the project name
176
+ const packageName = projectGraph.nodes[dep].data.metadata?.js?.packageName;
177
+ if (!packageName) {
178
+ throw new Error(`Unable to determine the package name for project "${dep}" from the project graph metadata, please ensure that the "@nx/js" plugin is installed and the project graph has been built. If the issue persists, please report this issue on https://github.com/nrwl/nx/issues`);
179
+ }
180
+ if (json[depType][packageName]) {
181
+ json[depType][packageName] = version;
182
+ }
183
+ }
184
+ }
185
+ }
186
+ return json;
187
+ });
188
+ }
189
+ }
190
+ parseDependencies(packageJson) {
191
+ const result = {};
192
+ const dependencyCollections = [
193
+ 'dependencies',
194
+ 'devDependencies',
195
+ 'peerDependencies',
196
+ 'optionalDependencies',
197
+ ];
198
+ for (const depCollection of dependencyCollections) {
199
+ if (packageJson[depCollection]) {
200
+ result[depCollection] = {};
201
+ for (const [dep, spec] of Object.entries(packageJson[depCollection])) {
202
+ const resolvedSpec = (0, resolve_version_spec_1.resolveVersionSpec)(dep, packageJson.version, spec, this.projectGraphNode.data.root);
203
+ result[depCollection][dep] = {
204
+ resolvedVersion: resolvedSpec,
205
+ rawVersionSpec: spec,
206
+ };
207
+ }
208
+ }
209
+ }
210
+ return result;
211
+ }
212
+ }
213
+ exports.default = JsVersionActions;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createNodes = exports.createNodesV2 = exports.PLUGIN_NAME = exports.createDependencies = void 0;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const get_named_inputs_1 = require("@nx/devkit/src/utils/get-named-inputs");
6
- const minimatch_1 = require("minimatch");
6
+ const picomatch = require("picomatch");
7
7
  const node_fs_1 = require("node:fs");
8
8
  const node_path_1 = require("node:path");
9
9
  const posix = require("node:path/posix");
@@ -178,7 +178,9 @@ function buildTscTargets(configFilePath, projectRoot, options, context) {
178
178
  const tsConfig = retrieveTsConfigFromCache(configFilePath, context.workspaceRoot);
179
179
  let internalProjectReferences;
180
180
  // Typecheck target
181
- if ((0, node_path_1.basename)(configFilePath) === 'tsconfig.json' && options.typecheck) {
181
+ if ((0, node_path_1.basename)(configFilePath) === 'tsconfig.json' &&
182
+ options.typecheck &&
183
+ tsConfig.raw?.['nx']?.addTypecheckTarget !== false) {
182
184
  internalProjectReferences = resolveInternalProjectReferences(tsConfig, context.workspaceRoot, projectRoot);
183
185
  const externalProjectReferences = resolveShallowExternalProjectReferences(tsConfig, context.workspaceRoot, projectRoot);
184
186
  const targetName = options.typecheck.targetName;
@@ -214,7 +216,7 @@ function buildTscTargets(configFilePath, projectRoot, options, context) {
214
216
  // Build target
215
217
  if (options.build &&
216
218
  (0, node_path_1.basename)(configFilePath) === options.build.configName &&
217
- isValidPackageJsonBuildConfig(tsConfig, context.workspaceRoot, projectRoot)) {
219
+ (0, util_1.isValidPackageJsonBuildConfig)(tsConfig, context.workspaceRoot, projectRoot)) {
218
220
  internalProjectReferences ??= resolveInternalProjectReferences(tsConfig, context.workspaceRoot, projectRoot);
219
221
  const targetName = options.build.targetName;
220
222
  targets[targetName] = {
@@ -276,8 +278,8 @@ function getInputs(namedInputs, configFilePath, tsConfig, internalProjectReferen
276
278
  });
277
279
  const normalize = (p) => (p.startsWith('./') ? p.slice(2) : p);
278
280
  config.raw.exclude.forEach((excludePath) => {
279
- if (!otherFilesInclude.some((includePath) => (0, minimatch_1.minimatch)(normalize(includePath), normalize(excludePath)) ||
280
- (0, minimatch_1.minimatch)(normalize(excludePath), normalize(includePath)))) {
281
+ if (!otherFilesInclude.some((includePath) => picomatch(normalize(excludePath))(normalize(includePath)) ||
282
+ picomatch(normalize(includePath))(normalize(excludePath)))) {
281
283
  excludePaths.add(excludePath);
282
284
  }
283
285
  });
@@ -369,87 +371,6 @@ function getOutputs(configFilePath, tsConfig, internalProjectReferences, workspa
369
371
  });
370
372
  return Array.from(outputs);
371
373
  }
372
- /**
373
- * Validates the build configuration of a `package.json` file by ensuring that paths in the `exports`, `module`,
374
- * and `main` fields reference valid output paths within the `outDir` defined in the TypeScript configuration.
375
- * Priority is given to the `exports` field, specifically the `.` export if defined. If `exports` is not defined,
376
- * the function falls back to validating `main` and `module` fields. If `outFile` is specified, it validates that the file
377
- * is located within the output directory.
378
- * If no `package.json` file exists, it assumes the configuration is valid.
379
- *
380
- * @param tsConfig The TypeScript configuration object.
381
- * @param workspaceRoot The workspace root path.
382
- * @param projectRoot The project root path.
383
- * @returns `true` if the package has a valid build configuration; otherwise, `false`.
384
- */
385
- function isValidPackageJsonBuildConfig(tsConfig, workspaceRoot, projectRoot) {
386
- const packageJsonPath = (0, node_path_1.join)(workspaceRoot, projectRoot, 'package.json');
387
- if (!(0, node_fs_1.existsSync)(packageJsonPath)) {
388
- // If the package.json file does not exist.
389
- // Assume it's valid because it would be using `project.json` instead.
390
- return true;
391
- }
392
- const packageJson = (0, devkit_1.readJsonFile)(packageJsonPath);
393
- const outDir = tsConfig.options.outFile
394
- ? (0, node_path_1.dirname)(tsConfig.options.outFile)
395
- : tsConfig.options.outDir;
396
- const resolvedOutDir = outDir
397
- ? (0, node_path_1.resolve)(workspaceRoot, projectRoot, outDir)
398
- : undefined;
399
- const isPathSourceFile = (path) => {
400
- if (resolvedOutDir) {
401
- const pathToCheck = (0, node_path_1.resolve)(workspaceRoot, projectRoot, path);
402
- return !pathToCheck.startsWith(resolvedOutDir);
403
- }
404
- const ext = (0, node_path_1.extname)(path);
405
- // Check that the file extension is a TS file extension. As the source files are in the same directory as the output files.
406
- return ['.ts', '.tsx', '.cts', '.mts'].includes(ext);
407
- };
408
- // Checks if the value is a path within the `src` directory.
409
- const containsInvalidPath = (value) => {
410
- if (typeof value === 'string') {
411
- return isPathSourceFile(value);
412
- }
413
- else if (typeof value === 'object') {
414
- return Object.entries(value).some(([currentKey, subValue]) => {
415
- // Skip types field
416
- if (currentKey === 'types') {
417
- return false;
418
- }
419
- if (typeof subValue === 'string') {
420
- return isPathSourceFile(subValue);
421
- }
422
- return false;
423
- });
424
- }
425
- return false;
426
- };
427
- const exports = packageJson?.exports;
428
- // Check the `.` export if `exports` is defined.
429
- if (exports) {
430
- if (typeof exports === 'string') {
431
- return !isPathSourceFile(exports);
432
- }
433
- if (typeof exports === 'object' && '.' in exports) {
434
- return !containsInvalidPath(exports['.']);
435
- }
436
- // Check other exports if `.` is not defined or valid.
437
- for (const key in exports) {
438
- if (key !== '.' && containsInvalidPath(exports[key])) {
439
- return false;
440
- }
441
- }
442
- return true;
443
- }
444
- // If `exports` is not defined, fallback to `main` and `module` fields.
445
- const buildPaths = ['main', 'module'];
446
- for (const field of buildPaths) {
447
- if (packageJson[field] && isPathSourceFile(packageJson[field])) {
448
- return false;
449
- }
450
- }
451
- return true;
452
- }
453
374
  function pathToInputOrOutput(path, workspaceRoot, projectRoot) {
454
375
  const fullProjectRoot = (0, node_path_1.resolve)(workspaceRoot, projectRoot);
455
376
  const fullPath = (0, node_path_1.resolve)(workspaceRoot, path);
@@ -554,7 +475,7 @@ function hasExternalProjectReferences(tsConfigPath, tsConfig, workspaceRoot, pro
554
475
  return false;
555
476
  }
556
477
  function isExternalProjectReference(refTsConfigPath, workspaceRoot, projectRoot) {
557
- const relativePath = posix.relative(workspaceRoot, refTsConfigPath);
478
+ const relativePath = posixRelative(workspaceRoot, refTsConfigPath);
558
479
  if (cache.isExternalProjectReference[relativePath] !== undefined) {
559
480
  return cache.isExternalProjectReference[relativePath];
560
481
  }
@@ -584,7 +505,7 @@ function getTsConfigDirName(tsConfigPath) {
584
505
  : (0, node_path_1.normalize)(tsConfigPath);
585
506
  }
586
507
  function retrieveTsConfigFromCache(tsConfigPath, workspaceRoot) {
587
- const relativePath = posix.relative(workspaceRoot, tsConfigPath);
508
+ const relativePath = posixRelative(workspaceRoot, tsConfigPath);
588
509
  // we don't need to check the hash if it's in the cache, because we've already
589
510
  // checked it when we initially populated the cache
590
511
  return tsConfigCache[relativePath]
@@ -600,7 +521,7 @@ function initializeTsConfigCache(configFilePaths, workspaceRoot) {
600
521
  }
601
522
  }
602
523
  function readTsConfigAndCache(tsConfigPath, workspaceRoot) {
603
- const relativePath = posix.relative(workspaceRoot, tsConfigPath);
524
+ const relativePath = posixRelative(workspaceRoot, tsConfigPath);
604
525
  const hash = getFileHash(tsConfigPath, workspaceRoot);
605
526
  let extendedFilesHash;
606
527
  if (tsConfigCache[relativePath] &&
@@ -716,7 +637,7 @@ function resolveExtendedTsConfigPath(tsConfigPath, directory) {
716
637
  }
717
638
  }
718
639
  function getFileHash(filePath, workspaceRoot) {
719
- const relativePath = posix.relative(workspaceRoot, filePath);
640
+ const relativePath = posixRelative(workspaceRoot, filePath);
720
641
  if (!cache.fileHashes[relativePath]) {
721
642
  const content = readFile(filePath, workspaceRoot);
722
643
  cache.fileHashes[relativePath] = (0, file_hasher_1.hashArray)([content]);
@@ -724,7 +645,7 @@ function getFileHash(filePath, workspaceRoot) {
724
645
  return cache.fileHashes[relativePath];
725
646
  }
726
647
  function readFile(filePath, workspaceRoot) {
727
- const relativePath = posix.relative(workspaceRoot, filePath);
648
+ const relativePath = posixRelative(workspaceRoot, filePath);
728
649
  if (!cache.rawFiles[relativePath]) {
729
650
  const content = (0, node_fs_1.readFileSync)(filePath, 'utf8');
730
651
  cache.rawFiles[relativePath] = content;
@@ -737,6 +658,9 @@ function toAbsolutePaths(cache, workspaceRoot) {
737
658
  updatedCache[key] = {
738
659
  data: {
739
660
  options: { noEmit: data.options.noEmit },
661
+ raw: {
662
+ nx: { addTypecheckTarget: data.raw?.['nx']?.addTypecheckTarget },
663
+ },
740
664
  extendedConfigFile: data.extendedConfigFile,
741
665
  },
742
666
  extendedFilesHash,
@@ -769,29 +693,38 @@ function toRelativePaths(cache, workspaceRoot) {
769
693
  updatedCache[key] = {
770
694
  data: {
771
695
  options: { noEmit: data.options.noEmit },
696
+ raw: {
697
+ nx: { addTypecheckTarget: data.raw?.['nx']?.addTypecheckTarget },
698
+ },
772
699
  extendedConfigFile: data.extendedConfigFile,
773
700
  },
774
701
  extendedFilesHash,
775
702
  hash,
776
703
  };
777
704
  if (data.options.rootDir) {
778
- updatedCache[key].data.options.rootDir = posix.relative(workspaceRoot, data.options.rootDir);
705
+ updatedCache[key].data.options.rootDir = posixRelative(workspaceRoot, data.options.rootDir);
779
706
  }
780
707
  if (data.options.outDir) {
781
- updatedCache[key].data.options.outDir = posix.relative(workspaceRoot, data.options.outDir);
708
+ updatedCache[key].data.options.outDir = posixRelative(workspaceRoot, data.options.outDir);
782
709
  }
783
710
  if (data.options.outFile) {
784
- updatedCache[key].data.options.outFile = posix.relative(workspaceRoot, data.options.outFile);
711
+ updatedCache[key].data.options.outFile = posixRelative(workspaceRoot, data.options.outFile);
785
712
  }
786
713
  if (data.options.tsBuildInfoFile) {
787
- updatedCache[key].data.options.tsBuildInfoFile = posix.relative(workspaceRoot, data.options.tsBuildInfoFile);
714
+ updatedCache[key].data.options.tsBuildInfoFile = posixRelative(workspaceRoot, data.options.tsBuildInfoFile);
788
715
  }
789
716
  if (data.extendedConfigFile?.filePath) {
790
- updatedCache[key].data.extendedConfigFile.filePath = posix.relative(workspaceRoot, data.extendedConfigFile.filePath);
717
+ updatedCache[key].data.extendedConfigFile.filePath = posixRelative(workspaceRoot, data.extendedConfigFile.filePath);
791
718
  }
792
719
  if (data.projectReferences) {
793
- updatedCache[key].data.projectReferences = data.projectReferences.map((ref) => ({ ...ref, path: posix.relative(workspaceRoot, ref.path) }));
720
+ updatedCache[key].data.projectReferences = data.projectReferences.map((ref) => ({
721
+ ...ref,
722
+ path: posixRelative(workspaceRoot, ref.path),
723
+ }));
794
724
  }
795
725
  }
796
726
  return updatedCache;
797
727
  }
728
+ function posixRelative(workspaceRoot, path) {
729
+ return posix.normalize((0, node_path_1.relative)(workspaceRoot, path));
730
+ }
@@ -1,5 +1,12 @@
1
1
  import { type TargetConfiguration } from '@nx/devkit';
2
2
  import { type PackageManagerCommands } from 'nx/src/utils/package-manager';
3
+ import { type ParsedCommandLine } from 'typescript';
4
+ export type ParsedTsconfigData = Pick<ParsedCommandLine, 'options' | 'projectReferences' | 'raw'> & {
5
+ extendedConfigFile: {
6
+ filePath: string;
7
+ externalPackage?: string;
8
+ } | null;
9
+ };
3
10
  /**
4
11
  * Allow uses that use incremental builds to run `nx watch-deps` to continuously build all dependencies.
5
12
  */
@@ -7,3 +14,4 @@ export declare function addBuildAndWatchDepsTargets(workspaceRoot: string, proje
7
14
  buildDepsTargetName?: string;
8
15
  watchDepsTargetName?: string;
9
16
  }, pmc: PackageManagerCommands): void;
17
+ export declare function isValidPackageJsonBuildConfig(tsConfig: ParsedTsconfigData, workspaceRoot: string, projectRoot: string): boolean;
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.addBuildAndWatchDepsTargets = addBuildAndWatchDepsTargets;
4
+ exports.isValidPackageJsonBuildConfig = isValidPackageJsonBuildConfig;
4
5
  const devkit_1 = require("@nx/devkit");
5
6
  const node_fs_1 = require("node:fs");
7
+ const node_path_1 = require("node:path");
6
8
  const path_1 = require("path");
7
9
  /**
8
10
  * Allow uses that use incremental builds to run `nx watch-deps` to continuously build all dependencies.
@@ -27,9 +29,79 @@ function addBuildAndWatchDepsTargets(workspaceRoot, projectRoot, targets, option
27
29
  dependsOn: ['^build'],
28
30
  };
29
31
  targets[options.watchDepsTargetName ?? 'watch-deps'] = {
30
- continuous: true,
31
32
  dependsOn: [buildDepsTargetName],
32
33
  command: `${pmc.exec} nx watch --projects ${projectName} --includeDependentProjects -- ${pmc.exec} nx ${buildDepsTargetName} ${projectName}`,
33
34
  };
34
35
  }
35
36
  }
37
+ function isValidPackageJsonBuildConfig(tsConfig, workspaceRoot, projectRoot) {
38
+ const resolvedProjectPath = (0, node_path_1.isAbsolute)(projectRoot)
39
+ ? (0, node_path_1.relative)(workspaceRoot, projectRoot)
40
+ : projectRoot;
41
+ const packageJsonPath = (0, path_1.join)(workspaceRoot, resolvedProjectPath, 'package.json');
42
+ if (!(0, node_fs_1.existsSync)(packageJsonPath)) {
43
+ // If the package.json file does not exist.
44
+ // Assume it's valid because it would be using `project.json` instead.
45
+ return true;
46
+ }
47
+ const packageJson = (0, devkit_1.readJsonFile)(packageJsonPath);
48
+ const outDir = tsConfig.options.outFile
49
+ ? (0, node_path_1.dirname)(tsConfig.options.outFile)
50
+ : tsConfig.options.outDir;
51
+ const resolvedOutDir = outDir
52
+ ? (0, node_path_1.resolve)(workspaceRoot, resolvedProjectPath, outDir)
53
+ : undefined;
54
+ const isPathSourceFile = (path) => {
55
+ if (resolvedOutDir) {
56
+ const pathToCheck = (0, node_path_1.resolve)(workspaceRoot, resolvedProjectPath, path);
57
+ return !pathToCheck.startsWith(resolvedOutDir);
58
+ }
59
+ const ext = (0, node_path_1.extname)(path);
60
+ // Check that the file extension is a TS file extension. As the source files are in the same directory as the output files.
61
+ return ['.ts', '.tsx', '.cts', '.mts'].includes(ext);
62
+ };
63
+ // Checks if the value is a path within the `src` directory.
64
+ const containsInvalidPath = (value) => {
65
+ if (typeof value === 'string') {
66
+ return isPathSourceFile(value);
67
+ }
68
+ else if (typeof value === 'object') {
69
+ return Object.entries(value).some(([currentKey, subValue]) => {
70
+ // Skip types field
71
+ if (currentKey === 'types') {
72
+ return false;
73
+ }
74
+ if (typeof subValue === 'string') {
75
+ return isPathSourceFile(subValue);
76
+ }
77
+ return false;
78
+ });
79
+ }
80
+ return false;
81
+ };
82
+ const exports = packageJson?.exports;
83
+ // Check the `.` export if `exports` is defined.
84
+ if (exports) {
85
+ if (typeof exports === 'string') {
86
+ return !isPathSourceFile(exports);
87
+ }
88
+ if (typeof exports === 'object' && '.' in exports) {
89
+ return !containsInvalidPath(exports['.']);
90
+ }
91
+ // Check other exports if `.` is not defined or valid.
92
+ for (const key in exports) {
93
+ if (key !== '.' && containsInvalidPath(exports[key])) {
94
+ return false;
95
+ }
96
+ }
97
+ return true;
98
+ }
99
+ // If `exports` is not defined, fallback to `main` and `module` fields.
100
+ const buildPaths = ['main', 'module'];
101
+ for (const field of buildPaths) {
102
+ if (packageJson[field] && isPathSourceFile(packageJson[field])) {
103
+ return false;
104
+ }
105
+ }
106
+ return true;
107
+ }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CopyAssetsHandler = exports.defaultFileEventHandler = void 0;
4
- const minimatch_1 = require("minimatch");
4
+ const picomatch = require("picomatch");
5
5
  const node_fs_1 = require("node:fs");
6
6
  const pathPosix = require("node:path/posix");
7
7
  const path = require("node:path");
@@ -9,6 +9,7 @@ const ignore_1 = require("ignore");
9
9
  const tinyglobby_1 = require("tinyglobby");
10
10
  const devkit_1 = require("@nx/devkit");
11
11
  const client_1 = require("nx/src/daemon/client/client");
12
+ const picocolors_1 = require("picocolors");
12
13
  const defaultFileEventHandler = (events) => {
13
14
  const dirs = new Set(events.map((event) => path.dirname(event.dest)));
14
15
  dirs.forEach((d) => (0, node_fs_1.mkdirSync)(d, { recursive: true }));
@@ -24,6 +25,9 @@ const defaultFileEventHandler = (events) => {
24
25
  else {
25
26
  devkit_1.logger.error(`Unknown file event: ${event.type}`);
26
27
  }
28
+ const eventDir = path.dirname(event.src);
29
+ const relativeDest = path.relative(eventDir, event.dest);
30
+ devkit_1.logger.log(`\n${(0, picocolors_1.dim)(relativeDest)}`);
27
31
  });
28
32
  };
29
33
  exports.defaultFileEventHandler = defaultFileEventHandler;
@@ -115,10 +119,12 @@ class CopyAssetsHandler {
115
119
  async processWatchEvents(events) {
116
120
  const fileEvents = [];
117
121
  for (const event of events) {
118
- const pathFromRoot = path.relative(this.rootDir, event.path);
122
+ const pathFromRoot = event.path.startsWith(this.rootDir)
123
+ ? path.relative(this.rootDir, event.path)
124
+ : event.path;
119
125
  for (const ag of this.assetGlobs) {
120
- if ((0, minimatch_1.minimatch)(pathFromRoot, ag.pattern) &&
121
- !ag.ignore?.some((ig) => (0, minimatch_1.minimatch)(pathFromRoot, ig)) &&
126
+ if (picomatch(ag.pattern)(pathFromRoot) &&
127
+ !ag.ignore?.some((ig) => picomatch(ig)(pathFromRoot)) &&
122
128
  !this.ignore.ignores(pathFromRoot)) {
123
129
  const relPath = path.relative(ag.input, pathFromRoot);
124
130
  const destPath = relPath.startsWith('..') ? pathFromRoot : relPath;
@@ -137,7 +143,7 @@ class CopyAssetsHandler {
137
143
  }
138
144
  filesToEvent(files, assetGlob) {
139
145
  return files.reduce((acc, src) => {
140
- if (!assetGlob.ignore?.some((ig) => (0, minimatch_1.minimatch)(src, ig)) &&
146
+ if (!assetGlob.ignore?.some((ig) => picomatch(ig)(src)) &&
141
147
  !this.ignore.ignores(src)) {
142
148
  const relPath = path.relative(assetGlob.input, src);
143
149
  const dest = relPath.startsWith('..') ? src : relPath;
@@ -16,6 +16,8 @@ const fileutils_1 = require("nx/src/utils/fileutils");
16
16
  const output_1 = require("nx/src/utils/output");
17
17
  const path_1 = require("path");
18
18
  const ts_config_1 = require("./typescript/ts-config");
19
+ const crypto_1 = require("crypto");
20
+ const project_graph_1 = require("nx/src/config/project-graph");
19
21
  function isBuildable(target, node) {
20
22
  return (node.data.targets &&
21
23
  node.data.targets[target] &&
@@ -48,7 +50,7 @@ function calculateProjectDependencies(projGraph, root, projectName, targetName,
48
50
  .map(({ name: dep, isTopLevel }) => {
49
51
  let project = null;
50
52
  const depNode = projGraph.nodes[dep] || projGraph.externalNodes[dep];
51
- if (depNode.type === 'lib') {
53
+ if ((0, project_graph_1.isProjectGraphProjectNode)(depNode) && depNode.type === 'lib') {
52
54
  if (isBuildable(targetName, depNode)) {
53
55
  const libPackageJsonPath = (0, path_1.join)(root, depNode.data.root, 'package.json');
54
56
  project = {
@@ -67,7 +69,7 @@ function calculateProjectDependencies(projGraph, root, projectName, targetName,
67
69
  nonBuildableDependencies.push(dep);
68
70
  }
69
71
  }
70
- else if (depNode.type === 'npm') {
72
+ else if ((0, project_graph_1.isProjectGraphExternalNode)(depNode)) {
71
73
  project = {
72
74
  name: depNode.data.packageName,
73
75
  outputs: [],
@@ -229,7 +231,7 @@ function computeCompilerOptionsPaths(tsConfig, dependencies) {
229
231
  return paths;
230
232
  }
231
233
  function createTmpTsConfig(tsconfigPath, workspaceRoot, projectRoot, dependencies, useWorkspaceAsBaseUrl = false) {
232
- const tmpTsConfigPath = (0, path_1.join)(workspaceRoot, 'tmp', projectRoot, process.env.NX_TASK_TARGET_TARGET ?? 'build', 'tsconfig.generated.json');
234
+ const tmpTsConfigPath = (0, path_1.join)(workspaceRoot, 'tmp', projectRoot, process.env.NX_TASK_TARGET_TARGET ?? 'build', `tsconfig.generated.${(0, crypto_1.randomUUID)()}.json`);
233
235
  if (tsconfigPath === tmpTsConfigPath) {
234
236
  return tsconfigPath;
235
237
  }
@@ -283,10 +285,9 @@ function findMissingBuildDependencies(root, projectName, targetName, projectDepe
283
285
  function updatePaths(dependencies, paths) {
284
286
  const pathsKeys = Object.keys(paths);
285
287
  // For each registered dependency
286
- dependencies.forEach((dep) => {
287
- if (dep.node.type === 'npm') {
288
- return;
289
- }
288
+ dependencies
289
+ .filter((dep) => (0, project_graph_1.isProjectGraphProjectNode)(dep.node))
290
+ .forEach((dep) => {
290
291
  // If there are outputs
291
292
  if (dep.outputs && dep.outputs.length > 0) {
292
293
  // Directly map the dependency name to the output paths (dist/packages/..., etc.)
@@ -350,7 +351,8 @@ function updateBuildableProjectPackageJsonDependencies(root, projectName, target
350
351
  !hasDependency(packageJson, 'peerDependencies', packageName)) {
351
352
  try {
352
353
  let depVersion;
353
- if (entry.node.type === 'lib') {
354
+ if ((0, project_graph_1.isProjectGraphProjectNode)(entry.node) &&
355
+ entry.node.type === 'lib') {
354
356
  const outputs = (0, devkit_1.getOutputsForTargetAndConfiguration)({
355
357
  project: projectName,
356
358
  target: targetName,
@@ -1,6 +1,7 @@
1
1
  import { type GeneratorCallback, type Tree } from '@nx/devkit';
2
2
  export type ProjectPackageManagerWorkspaceState = 'included' | 'excluded' | 'no-workspaces';
3
3
  export declare function getProjectPackageManagerWorkspaceState(tree: Tree, projectRoot: string): ProjectPackageManagerWorkspaceState;
4
+ export declare function getPackageManagerWorkspacesPatterns(tree: Tree): string[];
4
5
  export declare function isUsingPackageManagerWorkspaces(tree: Tree): boolean;
5
6
  export declare function isWorkspacesEnabled(tree: Tree): boolean;
6
7
  export declare function getProjectPackageManagerWorkspaceStateWarningTask(projectPackageManagerWorkspaceState: ProjectPackageManagerWorkspaceState, workspaceRoot: string): GeneratorCallback;
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getProjectPackageManagerWorkspaceState = getProjectPackageManagerWorkspaceState;
4
+ exports.getPackageManagerWorkspacesPatterns = getPackageManagerWorkspacesPatterns;
4
5
  exports.isUsingPackageManagerWorkspaces = isUsingPackageManagerWorkspaces;
5
6
  exports.isWorkspacesEnabled = isWorkspacesEnabled;
6
7
  exports.getProjectPackageManagerWorkspaceStateWarningTask = getProjectPackageManagerWorkspaceStateWarningTask;
7
8
  const devkit_1 = require("@nx/devkit");
8
- const minimatch_1 = require("minimatch");
9
+ const picomatch = require("picomatch");
9
10
  const posix_1 = require("node:path/posix");
10
11
  const package_json_1 = require("nx/src/plugins/package-json");
11
12
  const semver_1 = require("semver");
@@ -13,17 +14,21 @@ function getProjectPackageManagerWorkspaceState(tree, projectRoot) {
13
14
  if (!isUsingPackageManagerWorkspaces(tree)) {
14
15
  return 'no-workspaces';
15
16
  }
16
- const patterns = (0, package_json_1.getGlobPatternsFromPackageManagerWorkspaces)(tree.root, (path) => (0, devkit_1.readJson)(tree, path, { expectComments: true }));
17
- const isIncluded = patterns.some((p) => (0, minimatch_1.minimatch)((0, posix_1.join)(projectRoot, 'package.json'), p));
17
+ const patterns = getPackageManagerWorkspacesPatterns(tree);
18
+ const isIncluded = patterns.some((p) => picomatch(p)((0, posix_1.join)(projectRoot, 'package.json')));
18
19
  return isIncluded ? 'included' : 'excluded';
19
20
  }
21
+ function getPackageManagerWorkspacesPatterns(tree) {
22
+ return (0, package_json_1.getGlobPatternsFromPackageManagerWorkspaces)(tree.root, (path) => (0, devkit_1.readJson)(tree, path, { expectComments: true }), (path) => {
23
+ const content = tree.read(path, 'utf-8');
24
+ const { load } = require('@zkochan/js-yaml');
25
+ return load(content, { filename: path });
26
+ }, (path) => tree.exists(path));
27
+ }
20
28
  function isUsingPackageManagerWorkspaces(tree) {
21
29
  return isWorkspacesEnabled(tree);
22
30
  }
23
- function isWorkspacesEnabled(tree
24
- // packageManager: PackageManager = detectPackageManager(),
25
- // root: string = workspaceRoot
26
- ) {
31
+ function isWorkspacesEnabled(tree) {
27
32
  const packageManager = (0, devkit_1.detectPackageManager)(tree.root);
28
33
  if (packageManager === 'pnpm') {
29
34
  return tree.exists('pnpm-workspace.yaml');
@@ -1,3 +1,3 @@
1
1
  import type { NxJsonConfiguration } from '@nx/devkit';
2
- export declare function ensureProjectIsIncludedInPluginRegistrations(nxJson: NxJsonConfiguration, projectRoot: string, buildTargetName?: string): void;
2
+ export declare function ensureProjectIsIncludedInPluginRegistrations(nxJson: NxJsonConfiguration, projectRoot: string, buildTargetName: string | null): void;
3
3
  export declare function ensureProjectIsExcludedFromPluginRegistrations(nxJson: NxJsonConfiguration, projectRoot: string): void;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ensureProjectIsIncludedInPluginRegistrations = ensureProjectIsIncludedInPluginRegistrations;
4
4
  exports.ensureProjectIsExcludedFromPluginRegistrations = ensureProjectIsExcludedFromPluginRegistrations;
5
5
  const devkit_internals_1 = require("nx/src/devkit-internals");
6
- function ensureProjectIsIncludedInPluginRegistrations(nxJson, projectRoot, buildTargetName = 'build') {
6
+ function ensureProjectIsIncludedInPluginRegistrations(nxJson, projectRoot, buildTargetName) {
7
7
  nxJson.plugins ??= [];
8
8
  let isIncluded = false;
9
9
  let index = 0;
@@ -13,12 +13,17 @@ function ensureProjectIsIncludedInPluginRegistrations(nxJson, projectRoot, build
13
13
  continue;
14
14
  }
15
15
  if (typeof registration === 'string') {
16
- // if it's a string all projects are included but the are no user-specified options
17
- // and the build task is not inferred by default, so we need to exclude it
18
- nxJson.plugins[index] = {
19
- plugin: '@nx/js/typescript',
20
- exclude: [`${projectRoot}/*`],
21
- };
16
+ if (buildTargetName) {
17
+ // if it's a string all projects are included but the are no user-specified options
18
+ // and the build task is not inferred by default, so we need to exclude it
19
+ nxJson.plugins[index] = {
20
+ plugin: '@nx/js/typescript',
21
+ exclude: [`${projectRoot}/*`],
22
+ };
23
+ }
24
+ else {
25
+ isIncluded = true;
26
+ }
22
27
  }
23
28
  else {
24
29
  // check if the project would be included by the plugin registration
@@ -27,7 +32,7 @@ function ensureProjectIsIncludedInPluginRegistrations(nxJson, projectRoot, build
27
32
  // it's included by the plugin registration, check if the user-specified options would result
28
33
  // in the appropriate build task being inferred, if not, we need to exclude it
29
34
  if (registration.options?.typecheck !== false &&
30
- matchesBuildTarget(registration.options?.build, buildTargetName)) {
35
+ matchesBuildTargetDefinition(registration.options?.build, buildTargetName)) {
31
36
  // it has the desired options, do nothing, but continue processing
32
37
  // other registrations to exclude as needed
33
38
  isIncluded = true;
@@ -40,7 +45,7 @@ function ensureProjectIsIncludedInPluginRegistrations(nxJson, projectRoot, build
40
45
  }
41
46
  else if (!isIncluded &&
42
47
  registration.options?.typecheck !== false &&
43
- matchesBuildTarget(registration.options?.build, buildTargetName)) {
48
+ matchesBuildTargetDefinition(registration.options?.build, buildTargetName)) {
44
49
  if (!registration.exclude?.length) {
45
50
  // negative pattern are not supported by the `exclude` option so we
46
51
  // can't update it to not exclude the project, so we only update the
@@ -66,17 +71,20 @@ function ensureProjectIsIncludedInPluginRegistrations(nxJson, projectRoot, build
66
71
  if (!isIncluded) {
67
72
  // the project is not included by any plugin registration with an inferred build task
68
73
  // with the given name, so we create a new plugin registration for it
69
- nxJson.plugins.push({
74
+ const registration = {
70
75
  plugin: '@nx/js/typescript',
71
76
  include: [`${projectRoot}/*`],
72
77
  options: {
73
78
  typecheck: { targetName: 'typecheck' },
74
- build: {
75
- targetName: buildTargetName,
76
- configName: 'tsconfig.lib.json',
77
- },
78
79
  },
79
- });
80
+ };
81
+ if (buildTargetName) {
82
+ registration.options.build = {
83
+ targetName: buildTargetName,
84
+ configName: 'tsconfig.lib.json',
85
+ };
86
+ }
87
+ nxJson.plugins.push(registration);
80
88
  }
81
89
  }
82
90
  function ensureProjectIsExcludedFromPluginRegistrations(nxJson, projectRoot) {
@@ -115,8 +123,11 @@ function isTypeScriptPluginRegistration(plugin) {
115
123
  return ((typeof plugin === 'string' && plugin === '@nx/js/typescript') ||
116
124
  (typeof plugin !== 'string' && plugin.plugin === '@nx/js/typescript'));
117
125
  }
118
- function matchesBuildTarget(buildOptions, buildTargetName) {
126
+ function matchesBuildTargetDefinition(buildOptions, buildTargetName) {
119
127
  if (buildOptions === undefined || buildOptions === false) {
128
+ return !buildTargetName;
129
+ }
130
+ if (!buildTargetName) {
120
131
  return false;
121
132
  }
122
133
  if (buildOptions === true && buildTargetName === 'build') {
@@ -2,7 +2,8 @@ import { type Tree } from '@nx/devkit';
2
2
  export declare function isUsingTypeScriptPlugin(tree: Tree): boolean;
3
3
  export declare function isUsingTsSolutionSetup(tree?: Tree): boolean;
4
4
  export declare function assertNotUsingTsSolutionSetup(tree: Tree, pluginName: string, generatorName: string): void;
5
- export declare function findRuntimeTsConfigName(tree: Tree, projectRoot: string): string | null;
5
+ export declare function findRuntimeTsConfigName(projectRoot: string, tree?: Tree): string | null;
6
6
  export declare function updateTsconfigFiles(tree: Tree, projectRoot: string, runtimeTsconfigFileName: string, compilerOptions: Record<string, string | boolean | string[]>, exclude?: string[], rootDir?: string): void;
7
- export declare function addProjectToTsSolutionWorkspace(tree: Tree, projectDir: string): void;
7
+ export declare function addProjectToTsSolutionWorkspace(tree: Tree, projectDir: string): Promise<void>;
8
8
  export declare function getProjectType(tree: Tree, projectRoot: string, projectType?: 'library' | 'application'): 'library' | 'application';
9
+ export declare function getProjectSourceRoot(tree: Tree, projectSourceRoot: string | undefined, projectRoot: string): string | undefined;
@@ -7,6 +7,7 @@ exports.findRuntimeTsConfigName = findRuntimeTsConfigName;
7
7
  exports.updateTsconfigFiles = updateTsconfigFiles;
8
8
  exports.addProjectToTsSolutionWorkspace = addProjectToTsSolutionWorkspace;
9
9
  exports.getProjectType = getProjectType;
10
+ exports.getProjectSourceRoot = getProjectSourceRoot;
10
11
  const devkit_1 = require("@nx/devkit");
11
12
  const posix_1 = require("node:path/posix");
12
13
  const tree_1 = require("nx/src/generators/tree");
@@ -71,7 +72,8 @@ function assertNotUsingTsSolutionSetup(tree, pluginName, generatorName) {
71
72
  });
72
73
  throw new Error(`The ${artifactString} doesn't yet support the existing TypeScript setup. See the error above.`);
73
74
  }
74
- function findRuntimeTsConfigName(tree, projectRoot) {
75
+ function findRuntimeTsConfigName(projectRoot, tree) {
76
+ tree ??= new tree_1.FsTree(devkit_1.workspaceRoot, false);
75
77
  if (tree.exists((0, devkit_1.joinPathFragments)(projectRoot, 'tsconfig.app.json')))
76
78
  return 'tsconfig.app.json';
77
79
  if (tree.exists((0, devkit_1.joinPathFragments)(projectRoot, 'tsconfig.lib.json')))
@@ -90,9 +92,7 @@ function updateTsconfigFiles(tree, projectRoot, runtimeTsconfigFileName, compile
90
92
  json.extends = (0, devkit_1.joinPathFragments)(offset, 'tsconfig.base.json');
91
93
  json.compilerOptions = {
92
94
  ...json.compilerOptions,
93
- // Make sure d.ts files from typecheck does not conflict with bundlers.
94
- // Other tooling like jest write to "out-tsc/jest" to we just default to "out-tsc/<project-name>".
95
- outDir: (0, devkit_1.joinPathFragments)('out-tsc', projectRoot.split('/').at(-1)),
95
+ outDir: 'dist',
96
96
  rootDir,
97
97
  ...compilerOptions,
98
98
  };
@@ -145,12 +145,29 @@ function updateTsconfigFiles(tree, projectRoot, runtimeTsconfigFileName, compile
145
145
  });
146
146
  }
147
147
  }
148
- function addProjectToTsSolutionWorkspace(tree, projectDir) {
149
- // If dir is "libs/foo" then use "libs/*" so we don't need so many entries in the workspace file.
150
- // If dir is nested like "libs/shared/foo" then we add "libs/shared/*".
151
- // If the dir is just "foo" then we have to add it as is.
148
+ async function addProjectToTsSolutionWorkspace(tree, projectDir) {
149
+ const state = (0, package_manager_workspaces_1.getProjectPackageManagerWorkspaceState)(tree, projectDir);
150
+ if (state === 'included') {
151
+ return;
152
+ }
153
+ // If dir is "libs/foo", we try to use "libs/*" but we only do it if it's
154
+ // safe to do so. So, we first check if adding that pattern doesn't result
155
+ // in extra projects being matched. If extra projects are matched, or the
156
+ // dir is just "foo" then we add it as is.
152
157
  const baseDir = (0, posix_1.dirname)(projectDir);
153
- const pattern = baseDir === '.' ? projectDir : `${baseDir}/*`;
158
+ let pattern = projectDir;
159
+ if (baseDir !== '.') {
160
+ const patterns = (0, package_manager_workspaces_1.getPackageManagerWorkspacesPatterns)(tree);
161
+ const projectsBefore = await (0, devkit_1.globAsync)(tree, patterns);
162
+ patterns.push(`${baseDir}/*/package.json`);
163
+ const projectsAfter = await (0, devkit_1.globAsync)(tree, patterns);
164
+ if (projectsBefore.length + 1 === projectsAfter.length) {
165
+ // Adding the pattern to the parent directory only results in one extra
166
+ // project being matched, which is the project we're adding. It's safe
167
+ // to add the pattern to the parent directory.
168
+ pattern = `${baseDir}/*`;
169
+ }
170
+ }
154
171
  if (tree.exists('pnpm-workspace.yaml')) {
155
172
  const { load, dump } = require('@zkochan/js-yaml');
156
173
  const workspaceFile = tree.read('pnpm-workspace.yaml', 'utf-8');
@@ -189,3 +206,9 @@ function getProjectType(tree, projectRoot, projectType) {
189
206
  return 'application';
190
207
  return 'library';
191
208
  }
209
+ function getProjectSourceRoot(tree, projectSourceRoot, projectRoot) {
210
+ return (projectSourceRoot ??
211
+ (tree.exists((0, devkit_1.joinPathFragments)(projectRoot, 'src'))
212
+ ? (0, devkit_1.joinPathFragments)(projectRoot, 'src')
213
+ : projectRoot));
214
+ }