@nx/js 24.0.0-rc.0 → 24.0.0-rc.1

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.
@@ -1,7 +1,7 @@
1
1
  import { type CreateNodes, type TargetConfiguration } from '@nx/devkit';
2
2
  import { type Shebang } from './shebang';
3
3
  export interface ScriptPluginOptions {
4
- /** Runs claimed scripts in watch mode as continuous targets. */
4
+ /** Runs claimed scripts in watch mode as continuous targets. Defaults to `true`. */
5
5
  watch?: boolean;
6
6
  }
7
7
  export interface ScriptPluginDefinition<T extends ScriptPluginOptions> {
@@ -2,11 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createScriptNodes = createScriptNodes;
4
4
  exports.quoteShellArg = quoteShellArg;
5
+ const devkit_1 = require("@nx/devkit");
5
6
  const internal_1 = require("@nx/devkit/internal");
6
7
  const node_path_1 = require("node:path");
7
8
  const shebang_1 = require("./shebang");
8
9
  const target_name_1 = require("./target-name");
9
- const SCRIPT_GLOB = '**/*.{js,cjs,mjs,ts,cts,mts}';
10
+ /** Specs, tests, stories and typings are never scripts. */
11
+ const SCRIPT_GLOB = '**/!(*.spec|*.test|*.stories|*.d).{js,cjs,mjs,ts,cts,mts}';
10
12
  const PROJECT_MARKERS = ['package.json', 'project.json'];
11
13
  function createScriptNodes(definition) {
12
14
  return [
@@ -15,7 +17,7 @@ function createScriptNodes(definition) {
15
17
  ...PROJECT_MARKERS.map((marker) => `**/${marker}`),
16
18
  ]),
17
19
  async (files, options, context) => {
18
- const scriptsByRoot = groupScriptsByProjectRoot(files, !!definition.extraTargets);
20
+ const scriptsByRoot = groupScriptsByProjectRoot(files, context.workspaceRoot, !!definition.extraTargets);
19
21
  const projectRoots = [...scriptsByRoot.keys()];
20
22
  if (!projectRoots.length) {
21
23
  return [];
@@ -32,7 +34,7 @@ function createScriptNodes(definition) {
32
34
  if (!cache.has(key)) {
33
35
  cache.set(key, {
34
36
  ...(await definition.extraTargets?.(projectRoot, context.workspaceRoot, options)),
35
- ...createTargets(definition, context.workspaceRoot, projectRoot, scripts, options?.watch === true),
37
+ ...createTargets(definition, context.workspaceRoot, projectRoot, scripts, options?.watch !== false),
36
38
  });
37
39
  }
38
40
  const targets = cache.get(key);
@@ -52,18 +54,35 @@ function createScriptNodes(definition) {
52
54
  ];
53
55
  }
54
56
  /**
55
- * Assigns each script to its nearest enclosing project root. Roots without
56
- * scripts are kept only when `includeAllRoots` is set.
57
+ * Assigns each script to its nearest enclosing project root among the
58
+ * markers the plugin was handed, so `include`/`exclude` scope projects as well
59
+ * as scripts. Roots without scripts are kept only when `includeAllRoots` is set.
57
60
  */
58
- function groupScriptsByProjectRoot(files, includeAllRoots) {
59
- const markers = new Map();
61
+ function groupScriptsByProjectRoot(files, workspaceRoot, includeAllRoots) {
62
+ const handed = new Map();
60
63
  const scripts = [];
61
64
  for (const file of files) {
62
- if (PROJECT_MARKERS.includes((0, node_path_1.basename)(file))) {
63
- markers.set((0, node_path_1.dirname)(file), file);
64
- }
65
- else {
65
+ const name = (0, node_path_1.basename)(file);
66
+ if (!PROJECT_MARKERS.includes(name)) {
66
67
  scripts.push(file);
68
+ continue;
69
+ }
70
+ const dir = (0, node_path_1.dirname)(file);
71
+ const entry = handed.get(dir) ?? {};
72
+ entry[name === 'project.json' ? 'projectJson' : 'packageJson'] = file;
73
+ handed.set(dir, entry);
74
+ }
75
+ // A package.json is a project root only where core's default package-json
76
+ // plugin makes one: in the package manager workspaces, or beside a
77
+ // project.json. The opt-in `nx/plugins/package-json` is not consulted.
78
+ const inWorkspaces = isInPackageManagerWorkspaces(workspaceRoot);
79
+ const markers = new Map();
80
+ for (const [dir, { packageJson, projectJson }] of handed) {
81
+ if (projectJson) {
82
+ markers.set(dir, projectJson);
83
+ }
84
+ else if (inWorkspaces(packageJson)) {
85
+ markers.set(dir, packageJson);
67
86
  }
68
87
  }
69
88
  const byRoot = new Map();
@@ -87,21 +106,23 @@ function groupScriptsByProjectRoot(files, includeAllRoots) {
87
106
  }
88
107
  return byRoot;
89
108
  }
109
+ function isInPackageManagerWorkspaces(workspaceRoot) {
110
+ return (0, internal_1.buildPackageJsonWorkspacesMatcher)((0, internal_1.buildPackageJsonPatterns)(workspaceRoot, (file) => (0, devkit_1.readJsonFile)((0, node_path_1.join)(workspaceRoot, file))));
111
+ }
90
112
  function createTargets(definition, workspaceRoot, projectRoot, scripts, watch) {
91
113
  const claimed = [];
92
- for (const script of scripts) {
93
- const header = (0, shebang_1.readScriptHeader)((0, node_path_1.join)(workspaceRoot, script));
94
- const shebang = header === null ? null : (0, shebang_1.parseShebang)((0, shebang_1.getShebangLine)(header));
114
+ for (const { file, header } of (0, internal_1.readShebangHeaders)(workspaceRoot, scripts)) {
115
+ const shebang = (0, shebang_1.parseShebang)((0, shebang_1.getShebangLine)(header));
95
116
  if (!shebang || !definition.claims(shebang)) {
96
117
  continue;
97
118
  }
98
119
  const { name, warnings } = (0, target_name_1.parseTargetName)(header);
99
120
  for (const warning of warnings) {
100
- (0, internal_1.emitPluginWorkerLog)('warn', `${script}: ${warning}.`);
121
+ (0, internal_1.emitPluginWorkerLog)('warn', `${file}: ${warning}.`);
101
122
  }
102
123
  claimed.push({
103
- path: script,
104
- relativePath: node_path_1.posix.relative(projectRoot, script),
124
+ path: file,
125
+ relativePath: node_path_1.posix.relative(projectRoot, file),
105
126
  shebang,
106
127
  targetName: name,
107
128
  });
@@ -4,16 +4,10 @@ export interface Shebang {
4
4
  /** Arguments that follow the interpreter on the shebang line. */
5
5
  args: string[];
6
6
  }
7
- /**
8
- * Returns the first bytes of a script that starts with `#!`, or `null` when it
9
- * has no shebang or cannot be read (e.g. a tracked broken symlink).
10
- */
11
- export declare function readScriptHeader(absolutePath: string): string | null;
12
- /** The shebang line of a header from `readScriptHeader`, without `#!`. */
7
+ /** The shebang line of a header from `readShebangHeaders`, without `#!`. */
13
8
  export declare function getShebangLine(header: string): string;
14
9
  /**
15
10
  * Handles `/usr/bin/env node`, `/usr/bin/env -S node --flags`,
16
11
  * `/usr/bin/env -S npx tsx` and direct paths such as `/usr/local/bin/node`.
17
12
  */
18
13
  export declare function parseShebang(line: string): Shebang | null;
19
- export declare function stripBom(text: string): string;
@@ -1,43 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.readScriptHeader = readScriptHeader;
4
3
  exports.getShebangLine = getShebangLine;
5
4
  exports.parseShebang = parseShebang;
6
- exports.stripBom = stripBom;
7
- const node_fs_1 = require("node:fs");
8
5
  const node_path_1 = require("node:path");
9
- const SNIFF_BYTES = 512;
10
6
  const PACKAGE_RUNNERS = new Set(['npx', 'pnpx', 'bunx']);
11
- /**
12
- * Returns the first bytes of a script that starts with `#!`, or `null` when it
13
- * has no shebang or cannot be read (e.g. a tracked broken symlink).
14
- */
15
- function readScriptHeader(absolutePath) {
16
- const buffer = Buffer.alloc(SNIFF_BYTES);
17
- let bytesRead;
18
- try {
19
- const fd = (0, node_fs_1.openSync)(absolutePath, 'r');
20
- try {
21
- bytesRead = (0, node_fs_1.readSync)(fd, buffer, 0, SNIFF_BYTES, 0);
22
- }
23
- finally {
24
- (0, node_fs_1.closeSync)(fd);
25
- }
26
- }
27
- catch {
28
- return null;
29
- }
30
- let text = stripBom(buffer.toString('utf8', 0, bytesRead));
31
- if (!text.startsWith('#!')) {
32
- return null;
33
- }
34
- // Drop a line the sniff cut off, so a directive is never read truncated.
35
- if (bytesRead === SNIFF_BYTES && text.includes('\n')) {
36
- text = text.slice(0, text.lastIndexOf('\n'));
37
- }
38
- return text;
39
- }
40
- /** The shebang line of a header from `readScriptHeader`, without `#!`. */
7
+ /** The shebang line of a header from `readShebangHeaders`, without `#!`. */
41
8
  function getShebangLine(header) {
42
9
  const end = header.search(/\r?\n/);
43
10
  return (end === -1 ? header : header.slice(0, end)).slice(2).trim();
@@ -62,6 +29,3 @@ function parseShebang(line) {
62
29
  }
63
30
  return { interpreter: (0, node_path_1.basename)(tokens[0]), args: tokens.slice(1) };
64
31
  }
65
- function stripBom(text) {
66
- return text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;
67
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/js",
3
- "version": "24.0.0-rc.0",
3
+ "version": "24.0.0-rc.1",
4
4
  "private": false,
5
5
  "type": "commonjs",
6
6
  "files": [
@@ -162,8 +162,8 @@
162
162
  "@babel/preset-env": "^7.23.2",
163
163
  "@babel/preset-typescript": "^7.22.5",
164
164
  "@babel/runtime": "^7.22.6",
165
- "@nx/devkit": "24.0.0-rc.0",
166
- "@nx/workspace": "24.0.0-rc.0",
165
+ "@nx/devkit": "24.0.0-rc.1",
166
+ "@nx/workspace": "24.0.0-rc.1",
167
167
  "@zkochan/js-yaml": "0.0.7",
168
168
  "babel-plugin-const-enum": "^1.0.1",
169
169
  "babel-plugin-macros": "^3.1.0",
@@ -183,14 +183,14 @@
183
183
  "tslib": "^2.3.0"
184
184
  },
185
185
  "devDependencies": {
186
- "@nx/esbuild": "24.0.0-rc.0",
187
- "@nx/eslint": "24.0.0-rc.0",
188
- "@nx/jest": "24.0.0-rc.0",
189
- "@nx/oxlint": "24.0.0-rc.0",
190
- "@nx/rollup": "24.0.0-rc.0",
191
- "@nx/vite": "24.0.0-rc.0",
192
- "@nx/vitest": "24.0.0-rc.0",
193
- "nx": "24.0.0-rc.0"
186
+ "@nx/esbuild": "24.0.0-rc.1",
187
+ "@nx/eslint": "24.0.0-rc.1",
188
+ "@nx/jest": "24.0.0-rc.1",
189
+ "@nx/oxlint": "24.0.0-rc.1",
190
+ "@nx/rollup": "24.0.0-rc.1",
191
+ "@nx/vite": "24.0.0-rc.1",
192
+ "@nx/vitest": "24.0.0-rc.1",
193
+ "nx": "24.0.0-rc.1"
194
194
  },
195
195
  "peerDependencies": {
196
196
  "@swc/cli": ">=0.6.0 <0.9.0",