@nx/js 24.0.0-rc.0 → 24.0.0
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
|
-
|
|
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
|
|
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
|
|
56
|
-
*
|
|
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
|
|
61
|
+
function groupScriptsByProjectRoot(files, workspaceRoot, includeAllRoots) {
|
|
62
|
+
const handed = new Map();
|
|
60
63
|
const scripts = [];
|
|
61
64
|
for (const file of files) {
|
|
62
|
-
|
|
63
|
-
|
|
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
|
|
93
|
-
const
|
|
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', `${
|
|
121
|
+
(0, internal_1.emitPluginWorkerLog)('warn', `${file}: ${warning}.`);
|
|
101
122
|
}
|
|
102
123
|
claimed.push({
|
|
103
|
-
path:
|
|
104
|
-
relativePath: node_path_1.posix.relative(projectRoot,
|
|
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
|
|
3
|
+
"version": "24.0.0",
|
|
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
|
|
166
|
-
"@nx/workspace": "24.0.0
|
|
165
|
+
"@nx/devkit": "24.0.0",
|
|
166
|
+
"@nx/workspace": "24.0.0",
|
|
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
|
|
187
|
-
"@nx/eslint": "24.0.0
|
|
188
|
-
"@nx/jest": "24.0.0
|
|
189
|
-
"@nx/oxlint": "24.0.0
|
|
190
|
-
"@nx/rollup": "24.0.0
|
|
191
|
-
"@nx/vite": "24.0.0
|
|
192
|
-
"@nx/vitest": "24.0.0
|
|
193
|
-
"nx": "24.0.0
|
|
186
|
+
"@nx/esbuild": "24.0.0",
|
|
187
|
+
"@nx/eslint": "24.0.0",
|
|
188
|
+
"@nx/jest": "24.0.0",
|
|
189
|
+
"@nx/oxlint": "24.0.0",
|
|
190
|
+
"@nx/rollup": "24.0.0",
|
|
191
|
+
"@nx/vite": "24.0.0",
|
|
192
|
+
"@nx/vitest": "24.0.0",
|
|
193
|
+
"nx": "24.0.0"
|
|
194
194
|
},
|
|
195
195
|
"peerDependencies": {
|
|
196
196
|
"@swc/cli": ">=0.6.0 <0.9.0",
|