@fynjs/run 1.1.0 → 1.1.2
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/bin/qrun.js +6 -1
- package/bin/xrun.js +1 -1
- package/dist/cli/check-global.d.ts +1 -0
- package/{cli → dist/cli}/check-global.js +3 -3
- package/dist/cli/ck.d.ts +1 -0
- package/dist/cli/cli-options.d.ts +80 -0
- package/dist/cli/cli-options.js +95 -0
- package/dist/cli/config.d.ts +7 -0
- package/dist/cli/config.js +7 -0
- package/dist/cli/env.d.ts +17 -0
- package/dist/cli/env.js +31 -0
- package/dist/cli/npm-loader.d.ts +2 -0
- package/dist/cli/npm-loader.js +43 -0
- package/dist/cli/parse-cmd-args.d.ts +34 -0
- package/dist/cli/parse-cmd-args.js +199 -0
- package/dist/cli/provider-packages.d.ts +28 -0
- package/dist/cli/provider-packages.js +62 -0
- package/dist/cli/search-up-task-file.d.ts +8 -0
- package/dist/cli/search-up-task-file.js +79 -0
- package/dist/cli/task-file.d.ts +40 -0
- package/dist/cli/task-file.js +177 -0
- package/dist/cli/ts-runner.d.ts +2 -0
- package/dist/cli/ts-runner.js +60 -0
- package/dist/cli/usage.d.ts +2 -0
- package/dist/cli/wrap-process.d.ts +10 -0
- package/dist/cli/wrap-process.js +26 -0
- package/dist/cli/xrun-main.d.ts +119 -0
- package/dist/cli/xrun-main.js +417 -0
- package/dist/cli/xrun.d.ts +2 -0
- package/{cli → dist/cli}/xrun.js +0 -1
- package/dist/lib/chalk.d.ts +2 -0
- package/{lib → dist/lib}/chalk.js +0 -1
- package/dist/lib/cli-context.d.ts +97 -0
- package/dist/lib/cli-context.js +129 -0
- package/dist/lib/defaults.d.ts +30 -0
- package/{lib → dist/lib}/defaults.js +13 -16
- package/dist/lib/gen-xqid.d.ts +2 -0
- package/dist/lib/gen-xqid.js +8 -0
- package/dist/lib/index.d.ts +3 -0
- package/{lib → dist/lib}/index.js +0 -3
- package/dist/lib/logger.d.ts +2 -0
- package/dist/lib/logger.js +95 -0
- package/dist/lib/my-pkg.d.ts +4 -0
- package/dist/lib/my-pkg.js +42 -0
- package/dist/lib/ns-order.d.ts +7 -0
- package/dist/lib/ns-order.js +62 -0
- package/dist/lib/print-tasks/index.d.ts +2 -0
- package/dist/lib/print-tasks/index.js +100 -0
- package/dist/lib/reporters/console.d.ts +20 -0
- package/dist/lib/reporters/console.js +119 -0
- package/dist/lib/stringify.d.ts +2 -0
- package/dist/lib/stringify.js +19 -0
- package/dist/lib/util/parse-array.d.ts +2 -0
- package/dist/lib/util/parse-array.js +5 -0
- package/dist/lib/util/task-options.d.ts +37 -0
- package/dist/lib/util/task-options.js +115 -0
- package/dist/lib/util/update-env.d.ts +1 -0
- package/dist/lib/util/update-env.js +18 -0
- package/dist/lib/xqitem.d.ts +22 -0
- package/dist/lib/xqitem.js +57 -0
- package/dist/lib/xqtor.d.ts +57 -0
- package/dist/lib/xqtor.js +704 -0
- package/dist/lib/xqtree.d.ts +11 -0
- package/dist/lib/xqtree.js +33 -0
- package/dist/lib/xrun-instance.d.ts +9 -0
- package/dist/lib/xrun-instance.js +27 -0
- package/dist/lib/xrun.d.ts +55 -0
- package/dist/lib/xrun.js +317 -0
- package/dist/lib/xtask-spec.d.ts +10 -0
- package/dist/lib/xtask-spec.js +57 -0
- package/dist/lib/xtasks.d.ts +25 -0
- package/dist/lib/xtasks.js +119 -0
- package/package.json +39 -15
- package/cli/cli-options.js +0 -98
- package/cli/config.js +0 -8
- package/cli/env.js +0 -33
- package/cli/npm-loader.js +0 -56
- package/cli/parse-cmd-args.js +0 -156
- package/cli/provider-packages.js +0 -73
- package/cli/search-up-task-file.js +0 -92
- package/cli/task-file.js +0 -192
- package/cli/ts-runner.js +0 -62
- package/cli/wrap-process.js +0 -27
- package/cli/xrun-main.js +0 -425
- package/lib/cli-context.js +0 -145
- package/lib/gen-xqid.js +0 -10
- package/lib/logger.js +0 -105
- package/lib/ns-order.js +0 -76
- package/lib/print-tasks/index.js +0 -105
- package/lib/reporters/console.js +0 -133
- package/lib/stringify.js +0 -16
- package/lib/util/parse-array.js +0 -5
- package/lib/util/update-env.js +0 -16
- package/lib/xqitem.js +0 -70
- package/lib/xqtor.js +0 -814
- package/lib/xqtree.js +0 -41
- package/lib/xrun-instance.js +0 -33
- package/lib/xrun.d.ts +0 -89
- package/lib/xrun.js +0 -344
- package/lib/xtask-spec.js +0 -63
- package/lib/xtasks.js +0 -137
- /package/{cli → dist/cli}/ck.js +0 -0
- /package/{cli → dist/cli}/usage.js +0 -0
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
import ownInstance from "../lib/xrun-instance.js";
|
|
2
|
+
import Path from "path";
|
|
3
|
+
import parseCmdArgs from "./parse-cmd-args.js";
|
|
4
|
+
import chalk from "../lib/chalk.js";
|
|
5
|
+
import logger from "../lib/logger.js";
|
|
6
|
+
import usage from "./usage.js";
|
|
7
|
+
import { envPath as envPath } from "xsh";
|
|
8
|
+
import Fs from "fs";
|
|
9
|
+
import xsh from "xsh";
|
|
10
|
+
import cliOptions from "./cli-options.js";
|
|
11
|
+
import parseArray from "../lib/util/parse-array.js";
|
|
12
|
+
import { makeOptionalRequire } from "optional-require";
|
|
13
|
+
import { createRequire } from "node:module";
|
|
14
|
+
const require = createRequire(import.meta.url);
|
|
15
|
+
const optionalRequire = makeOptionalRequire(require);
|
|
16
|
+
import env from "./env.js";
|
|
17
|
+
import WrapProcess from "./wrap-process.js";
|
|
18
|
+
import { CliContext } from "../lib/cli-context.js";
|
|
19
|
+
import { myPkgDir } from "../lib/my-pkg.js";
|
|
20
|
+
/**
|
|
21
|
+
* Flush logger based on options
|
|
22
|
+
* @param {Object} opts - Options
|
|
23
|
+
*/
|
|
24
|
+
function flushLogger(opts) {
|
|
25
|
+
// only opts carries a quiet preference - without one, leave the current setting alone
|
|
26
|
+
// rather than silently un-quieting the logger
|
|
27
|
+
if (opts) {
|
|
28
|
+
logger.quiet(opts.quiet);
|
|
29
|
+
}
|
|
30
|
+
logger.resetBuffer(true, false);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Handle process exit or callback
|
|
34
|
+
* @param {number} code - Exit code
|
|
35
|
+
* @param {Function} done - Optional callback
|
|
36
|
+
*/
|
|
37
|
+
function handleExitOrDone(code, done) {
|
|
38
|
+
if (done) {
|
|
39
|
+
const err = new Error(`exit code: ${code}`);
|
|
40
|
+
err.exitCode = code;
|
|
41
|
+
done(err);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
WrapProcess.exit(code);
|
|
45
|
+
}
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Process environment options from command line
|
|
50
|
+
* @param {Object} opts - Options object containing env property
|
|
51
|
+
*/
|
|
52
|
+
function processEnvOptions(opts) {
|
|
53
|
+
const envs = [].concat(opts.env).filter(Boolean);
|
|
54
|
+
for (const envStr of envs) {
|
|
55
|
+
const [key, val] = envStr.split("=");
|
|
56
|
+
if (key) {
|
|
57
|
+
env.set(key, val);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* List CLI options for shell auto completion
|
|
63
|
+
* @param {Array} argv - Command line arguments
|
|
64
|
+
* @param {number} offset - Argument offset
|
|
65
|
+
* @param {Function} done - Optional callback
|
|
66
|
+
* @returns {void}
|
|
67
|
+
*/
|
|
68
|
+
function handleCliOptions(argv, offset, done) {
|
|
69
|
+
if (argv.length === 3 && argv[offset] === "--options") {
|
|
70
|
+
Object.keys(cliOptions).forEach(k => {
|
|
71
|
+
const x = cliOptions[k];
|
|
72
|
+
console.log(`--${k}`);
|
|
73
|
+
console.log(`-${x.alias}`);
|
|
74
|
+
});
|
|
75
|
+
return handleExitOrDone(0, done);
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Find and load the runner module
|
|
81
|
+
* @param {string} xrunPath - Path to xrun
|
|
82
|
+
* @returns {Object} Runner module and its path
|
|
83
|
+
*/
|
|
84
|
+
function findRunnerModule(xrunPath) {
|
|
85
|
+
let runner;
|
|
86
|
+
//
|
|
87
|
+
// Only a copy of this package that is NOT the one running counts here. Node lets a package
|
|
88
|
+
// self-reference its own name once it declares `exports`, so `require("@fynjs/run")` from
|
|
89
|
+
// inside our own cli resolves right back to our own `main` - loading a SECOND copy of every
|
|
90
|
+
// module, with a second xrun instance. Tasks get registered into the instance this module
|
|
91
|
+
// graph owns, so that second runner reports zero tasks and the run dies with "No tasks found".
|
|
92
|
+
//
|
|
93
|
+
// The runner may resolve to a copy's ESM entry, in which case require(esm) hands back the
|
|
94
|
+
// module namespace rather than the instance - the runner sits on `.default`. A copy that is
|
|
95
|
+
// still CJS has no `.default` and is used as-is.
|
|
96
|
+
//
|
|
97
|
+
/* istanbul ignore next: the .default arm needs a real require of this package - see below */
|
|
98
|
+
const loadRunner = p => {
|
|
99
|
+
let resolved;
|
|
100
|
+
try {
|
|
101
|
+
resolved = require.resolve(p);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
if (!Path.relative(myPkgDir, resolved).startsWith("..")) {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
const mod = optionalRequire(p);
|
|
110
|
+
return mod && (mod.default || mod);
|
|
111
|
+
};
|
|
112
|
+
const foundReq = [
|
|
113
|
+
xrunPath, // first look for it in path passed from cli
|
|
114
|
+
"@fynjs/run" // let node.js resolve by package name
|
|
115
|
+
].find(p => p && (runner = loadRunner(p)));
|
|
116
|
+
//
|
|
117
|
+
// Not covered on purpose. Exercising this means letting `optionalRequire` load a real copy
|
|
118
|
+
// of this package through node's own registry, which is a second, uninstrumented copy of
|
|
119
|
+
// every module in it - the rest of the run then uses that copy and coverage collapses for
|
|
120
|
+
// files that have nothing to do with this branch. A test here costs ~20 statements elsewhere.
|
|
121
|
+
//
|
|
122
|
+
/* istanbul ignore next */
|
|
123
|
+
if (runner) {
|
|
124
|
+
return { runner, foundPath: Path.dirname(require.resolve(foundReq)) };
|
|
125
|
+
}
|
|
126
|
+
//
|
|
127
|
+
// Definitive known location. This used to be `optionalRequire("..")`, but resolving our own
|
|
128
|
+
// package at runtime can load a second copy of it - a distinct xrun instance, with distinct
|
|
129
|
+
// Symbols - which is exactly what the two earlier entries are for. A static import is the
|
|
130
|
+
// same module by construction.
|
|
131
|
+
//
|
|
132
|
+
return { runner: ownInstance.xrun, foundPath: Path.dirname(import.meta.dirname) };
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Handle case when no tasks are found
|
|
136
|
+
* @param {CliContext} cliContext - Command context
|
|
137
|
+
* @param {string} cwd - Current working directory
|
|
138
|
+
* @param {Function} done - Optional callback
|
|
139
|
+
*/
|
|
140
|
+
function handleNoTasks(cliContext, cwd, done, opts) {
|
|
141
|
+
//
|
|
142
|
+
// Flush first, like handleTaskListing does. Without this the whole diagnostic below is
|
|
143
|
+
// written into the logger's buffer and then thrown away by the exit, so a missing, broken,
|
|
144
|
+
// or unloadable task file made xrun exit 1 with no output at all.
|
|
145
|
+
//
|
|
146
|
+
flushLogger(opts);
|
|
147
|
+
const fromCwd = optionalRequire.resolve("@fynjs/run") || "not found - probably not installed";
|
|
148
|
+
//
|
|
149
|
+
// Purely diagnostic, so it must never be the thing that throws. `require.resolve("..")` goes
|
|
150
|
+
// through this package's own `main`, which does not exist when running from source before a
|
|
151
|
+
// build - and a "no tasks found" message that dies while explaining itself is worse than the
|
|
152
|
+
// original problem.
|
|
153
|
+
//
|
|
154
|
+
let fromMyDir;
|
|
155
|
+
try {
|
|
156
|
+
fromMyDir = Path.dirname(require.resolve(".."));
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
// only reachable running from source with no build in place, which a test run is not
|
|
160
|
+
/* istanbul ignore next */
|
|
161
|
+
fromMyDir = `not resolvable from ${import.meta.dirname}`;
|
|
162
|
+
}
|
|
163
|
+
const searchResult = cliContext.getSearchResult();
|
|
164
|
+
const info = searchResult.xrunFile
|
|
165
|
+
? `
|
|
166
|
+
This could be due to a few reasons:
|
|
167
|
+
|
|
168
|
+
1. your task file ${searchResult.xrunFile} didn't load any tasks or contains errors.
|
|
169
|
+
2. there are multiple copies of this package (@fynjs/run) installed in "node_modules".
|
|
170
|
+
`
|
|
171
|
+
: `
|
|
172
|
+
You do not have a "xrun-tasks.js|ts" file, so the only tasks may come from your
|
|
173
|
+
'package.json' npm scripts, and you probably don't have any defined there either.
|
|
174
|
+
`;
|
|
175
|
+
logger.error(`${chalk.red("*** No tasks found ***")}
|
|
176
|
+
${info}
|
|
177
|
+
For reference, some paths used to search for tasks:
|
|
178
|
+
- my current import.meta.dirname: '${import.meta.dirname}'
|
|
179
|
+
- dir used to search for tasks:
|
|
180
|
+
'${cwd}'
|
|
181
|
+
|
|
182
|
+
Some paths used to resolve @fynjs/run:
|
|
183
|
+
- resolved from CWD: '${fromCwd}'
|
|
184
|
+
- resolved from my dir: '${fromMyDir}'
|
|
185
|
+
`);
|
|
186
|
+
return handleExitOrDone(1, done);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Handle task listing
|
|
190
|
+
* @param {Object} runner - Runner instance
|
|
191
|
+
* @param {Object} opts - Options
|
|
192
|
+
* @param {Function} done - Optional callback
|
|
193
|
+
* @returns {void}
|
|
194
|
+
*/
|
|
195
|
+
function handleTaskListing(runner, opts, done) {
|
|
196
|
+
flushLogger(opts);
|
|
197
|
+
const ns = opts.list && opts.list.split(",").map(x => x.trim());
|
|
198
|
+
try {
|
|
199
|
+
if (opts.full) {
|
|
200
|
+
let fn = runner._tasks.fullNames(ns);
|
|
201
|
+
if (opts.full > 1)
|
|
202
|
+
fn = fn.map(x => (x.startsWith("/") ? x : `/${x}`));
|
|
203
|
+
console.log(fn.join("\n"));
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
console.log(runner._tasks.names(ns).join("\n"));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
catch (err) {
|
|
210
|
+
console.log(err.message);
|
|
211
|
+
}
|
|
212
|
+
return handleExitOrDone(0, done);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Handle namespace listing
|
|
216
|
+
* @param {Object} runner - Runner instance
|
|
217
|
+
* @param {Object} opts - Options
|
|
218
|
+
* @param {Function} done - Optional callback
|
|
219
|
+
* @returns {void}
|
|
220
|
+
*/
|
|
221
|
+
function handleNamespaceListing(runner, opts, done) {
|
|
222
|
+
flushLogger(opts);
|
|
223
|
+
console.log(runner._tasks._namespaces.join("\n"));
|
|
224
|
+
return handleExitOrDone(0, done);
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Handle help display
|
|
228
|
+
* @param {Object} runner - Runner instance
|
|
229
|
+
* @param {CliContext} cliContext - Command context
|
|
230
|
+
* @param {Object} opts - Options
|
|
231
|
+
* @param {string} cmdName - Command name
|
|
232
|
+
* @param {Function} done - Optional callback
|
|
233
|
+
* @returns {void}
|
|
234
|
+
*/
|
|
235
|
+
function handleHelp(runner, cliContext, opts, cmdName, done) {
|
|
236
|
+
flushLogger(opts);
|
|
237
|
+
runner.printTasks();
|
|
238
|
+
/* istanbul ignore if */
|
|
239
|
+
if (!opts.quiet) {
|
|
240
|
+
console.log(`${usage}`);
|
|
241
|
+
console.log(chalk.bold(" Help:"), `${cmdName} -h`, chalk.bold(" Example:"), `${cmdName} build\n`);
|
|
242
|
+
}
|
|
243
|
+
return handleExitOrDone(1, done);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Setup node_modules bin in PATH
|
|
247
|
+
* @param {Object} opts - Options
|
|
248
|
+
*/
|
|
249
|
+
function setupNodeModulesBin(opts) {
|
|
250
|
+
if (opts.nmbin) {
|
|
251
|
+
const nmBin = Path.join(opts.cwd, "node_modules", ".bin");
|
|
252
|
+
if (Fs.existsSync(nmBin)) {
|
|
253
|
+
const x = chalk.magenta(`${xsh.pathCwd.replace(nmBin, ".")}`);
|
|
254
|
+
const pathStr = env.get(envPath.envKey) || "";
|
|
255
|
+
const updated = envPath.addToFront(nmBin);
|
|
256
|
+
if (updated !== pathStr) {
|
|
257
|
+
logger.log(`Added ${x} to front of PATH`);
|
|
258
|
+
}
|
|
259
|
+
else if (!env.get(env.xrunId)) {
|
|
260
|
+
logger.log(`PATH already contains ${x}`, pathStr);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Setup environment variables
|
|
267
|
+
*/
|
|
268
|
+
function setupEnvironment() {
|
|
269
|
+
if (!env.get(env.xrunId)) {
|
|
270
|
+
env.set(env.xrunId, "1");
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
env.set(env.xrunId, parseInt(env.get(env.xrunId)) + 1);
|
|
274
|
+
}
|
|
275
|
+
if (!env.has(env.forceColor)) {
|
|
276
|
+
env.set(env.forceColor, "1");
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Process task arguments
|
|
281
|
+
* @param {Array} tasks - Task arguments
|
|
282
|
+
* @param {Object} opts - Options
|
|
283
|
+
* @returns {Array} Processed tasks
|
|
284
|
+
*/
|
|
285
|
+
function processTasks(tasks, opts) {
|
|
286
|
+
tasks = tasks.map(x => {
|
|
287
|
+
if (x.startsWith("/") && x.indexOf("/", 1) > 1) {
|
|
288
|
+
return x.substring(1);
|
|
289
|
+
}
|
|
290
|
+
return x;
|
|
291
|
+
});
|
|
292
|
+
if (tasks[0].startsWith("[")) {
|
|
293
|
+
let arrayStr;
|
|
294
|
+
try {
|
|
295
|
+
arrayStr = tasks.join(" ");
|
|
296
|
+
tasks = parseArray(arrayStr);
|
|
297
|
+
}
|
|
298
|
+
catch (e) {
|
|
299
|
+
console.log("Parsing array of tasks failed:", chalk.red(`${e.message}:`), chalk.cyan(arrayStr));
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (tasks.length > 1 && tasks[0] !== "." && opts && opts.serial) {
|
|
304
|
+
tasks = ["."].concat(tasks);
|
|
305
|
+
}
|
|
306
|
+
return tasks;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Handle quiet flag setting in environment
|
|
310
|
+
* @param {Object} jsonMeta - Command metadata
|
|
311
|
+
* @param {Object} opts - Command options
|
|
312
|
+
* @returns {boolean} - Whether quiet mode is enabled
|
|
313
|
+
*/
|
|
314
|
+
function handleQuietFlag(jsonMeta, opts) {
|
|
315
|
+
if (jsonMeta.source.quiet === "default") {
|
|
316
|
+
opts.quiet = env.get(env.xrunQuiet) === "1";
|
|
317
|
+
jsonMeta.source.quiet = "env";
|
|
318
|
+
}
|
|
319
|
+
else if (opts.quiet) {
|
|
320
|
+
env.set(env.xrunQuiet, "1");
|
|
321
|
+
}
|
|
322
|
+
return opts.quiet;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Main entry point for xrun
|
|
326
|
+
* @param {Array} argv - Command line arguments
|
|
327
|
+
* @param {number} offset - Argument offset
|
|
328
|
+
* @param {string} xrunPath - Path to xrun
|
|
329
|
+
* @param {Function} done - Optional callback
|
|
330
|
+
* @returns {*} Runner result or void
|
|
331
|
+
*/
|
|
332
|
+
async function xrunMain(argv, offset, xrunPath = "", done = null) {
|
|
333
|
+
let cmdName = "xrun";
|
|
334
|
+
const cwd = WrapProcess.cwd();
|
|
335
|
+
if (!argv) {
|
|
336
|
+
cmdName = Path.basename(WrapProcess.argv[1]);
|
|
337
|
+
argv = WrapProcess.argv;
|
|
338
|
+
offset = 2;
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
cmdName = "xrun";
|
|
342
|
+
}
|
|
343
|
+
// Handle CLI options listing
|
|
344
|
+
if (handleCliOptions(argv, offset, done))
|
|
345
|
+
return;
|
|
346
|
+
// Find and load runner module
|
|
347
|
+
const { runner, foundPath } = findRunnerModule(xrunPath);
|
|
348
|
+
const rawCmdArgs = await parseCmdArgs.parseArgs(argv, offset);
|
|
349
|
+
if (rawCmdArgs.parsed?.errorNodes?.length > 0) {
|
|
350
|
+
return handleExitOrDone(1, done);
|
|
351
|
+
}
|
|
352
|
+
// Create CliContext as the primary interface
|
|
353
|
+
const cliContext = new CliContext(rawCmdArgs);
|
|
354
|
+
const numTasks = runner.countTasks();
|
|
355
|
+
const jsonMeta = cliContext.getMetadata();
|
|
356
|
+
const opts = cliContext.getGlobalOptions();
|
|
357
|
+
// Handle quiet flag
|
|
358
|
+
handleQuietFlag(jsonMeta, opts);
|
|
359
|
+
// Handle no tasks case
|
|
360
|
+
if (numTasks === 0) {
|
|
361
|
+
return handleNoTasks(cliContext, cwd, done, opts);
|
|
362
|
+
}
|
|
363
|
+
// Handle task listing
|
|
364
|
+
else if (jsonMeta.source.list !== "default") {
|
|
365
|
+
return handleTaskListing(runner, opts, done);
|
|
366
|
+
}
|
|
367
|
+
// Handle namespace listing
|
|
368
|
+
else if (opts.ns) {
|
|
369
|
+
return handleNamespaceListing(runner, opts, done);
|
|
370
|
+
}
|
|
371
|
+
// Handle help display
|
|
372
|
+
/* istanbul ignore if */
|
|
373
|
+
if (cliContext.getTasks().length === 0) {
|
|
374
|
+
/* istanbul ignore next */
|
|
375
|
+
return handleHelp(runner, cliContext, opts, cmdName, done);
|
|
376
|
+
}
|
|
377
|
+
flushLogger(opts);
|
|
378
|
+
// Setup environment
|
|
379
|
+
setupNodeModulesBin(opts);
|
|
380
|
+
setupEnvironment();
|
|
381
|
+
// Configure runner with CliContext
|
|
382
|
+
if (runner.stopOnError === undefined || jsonMeta.source.soe !== "default") {
|
|
383
|
+
runner.stopOnError = cliContext.getStopOnError();
|
|
384
|
+
}
|
|
385
|
+
// Set CliContext on runner
|
|
386
|
+
runner.setCliContext(cliContext);
|
|
387
|
+
// Process tasks using CliContext
|
|
388
|
+
const processedTasks = processTasks(cliContext.getTasks(), opts);
|
|
389
|
+
/* istanbul ignore next */
|
|
390
|
+
if (processedTasks === null) {
|
|
391
|
+
/* istanbul ignore next */
|
|
392
|
+
return handleExitOrDone(1, done);
|
|
393
|
+
}
|
|
394
|
+
processEnvOptions(opts);
|
|
395
|
+
// Run tasks with CliContext already set on runner
|
|
396
|
+
return runner.run(processedTasks.length === 1 ? processedTasks[0] : processedTasks, done);
|
|
397
|
+
}
|
|
398
|
+
import { INTERNALS } from "../lib/defaults.js";
|
|
399
|
+
export { xrunMain };
|
|
400
|
+
export default {
|
|
401
|
+
xrunMain,
|
|
402
|
+
[INTERNALS]: {
|
|
403
|
+
flushLogger,
|
|
404
|
+
handleExitOrDone,
|
|
405
|
+
handleCliOptions,
|
|
406
|
+
findRunnerModule,
|
|
407
|
+
handleNoTasks,
|
|
408
|
+
handleTaskListing,
|
|
409
|
+
handleNamespaceListing,
|
|
410
|
+
handleHelp,
|
|
411
|
+
setupNodeModulesBin,
|
|
412
|
+
setupEnvironment,
|
|
413
|
+
processTasks,
|
|
414
|
+
handleQuietFlag,
|
|
415
|
+
processEnvOptions
|
|
416
|
+
}
|
|
417
|
+
};
|
package/{cli → dist/cli}/xrun.js
RENAMED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CliContext encapsulates all CLI-related information from command line parsing
|
|
3
|
+
* This provides a clean interface for accessing command arguments, options, and metadata
|
|
4
|
+
* throughout the execution pipeline without tight coupling to CLI parsing details.
|
|
5
|
+
*/
|
|
6
|
+
declare class CliContext {
|
|
7
|
+
_cmdArgs: any;
|
|
8
|
+
_opts: any;
|
|
9
|
+
_parsed: any;
|
|
10
|
+
_remainingArgs: any;
|
|
11
|
+
_searchResult: any;
|
|
12
|
+
_subCmdNodes: any;
|
|
13
|
+
_tasks: any;
|
|
14
|
+
constructor(cmdArgs: any);
|
|
15
|
+
/**
|
|
16
|
+
* Get command information for a specific task
|
|
17
|
+
* @param {string} taskName - Name of the task
|
|
18
|
+
* @returns {Object} Task command object with argv, opts, etc.
|
|
19
|
+
*/
|
|
20
|
+
getTaskCommand(taskName: any): any;
|
|
21
|
+
/**
|
|
22
|
+
* Get argv array for a specific task
|
|
23
|
+
* @param {string} taskName - Name of the task
|
|
24
|
+
* @returns {Array} Task arguments array
|
|
25
|
+
*/
|
|
26
|
+
getTaskArgv(taskName: any): any;
|
|
27
|
+
/**
|
|
28
|
+
* Get global command line options
|
|
29
|
+
* @returns {Object} Global options object
|
|
30
|
+
*/
|
|
31
|
+
getGlobalOptions(): any;
|
|
32
|
+
/**
|
|
33
|
+
* Get command metadata (jsonMeta)
|
|
34
|
+
* @returns {Object} Command metadata
|
|
35
|
+
*/
|
|
36
|
+
getMetadata(): any;
|
|
37
|
+
/**
|
|
38
|
+
* Get the list of tasks to execute
|
|
39
|
+
* @returns {Array} Tasks array
|
|
40
|
+
*/
|
|
41
|
+
getTasks(): any;
|
|
42
|
+
/**
|
|
43
|
+
* Get search result information
|
|
44
|
+
* @returns {Object} Search result with found files, directories, etc.
|
|
45
|
+
*/
|
|
46
|
+
getSearchResult(): any;
|
|
47
|
+
/**
|
|
48
|
+
* Check if quiet mode is enabled
|
|
49
|
+
* @returns {boolean} True if quiet mode
|
|
50
|
+
*/
|
|
51
|
+
isQuiet(): any;
|
|
52
|
+
/**
|
|
53
|
+
* Check if serial execution is requested
|
|
54
|
+
* @returns {boolean} True if serial execution
|
|
55
|
+
*/
|
|
56
|
+
isSerial(): any;
|
|
57
|
+
/**
|
|
58
|
+
* Get stop on error setting
|
|
59
|
+
* @returns {string|boolean} Stop on error setting
|
|
60
|
+
*/
|
|
61
|
+
getStopOnError(): any;
|
|
62
|
+
/**
|
|
63
|
+
* Get arguments that came after "--" in the CLI
|
|
64
|
+
* These are stored in parsed._ by @fynjs/cli-args
|
|
65
|
+
* @returns {Array} Arguments after "--"
|
|
66
|
+
*/
|
|
67
|
+
getRemainingArgs(): any;
|
|
68
|
+
/**
|
|
69
|
+
* Check if there are any remaining arguments after "--"
|
|
70
|
+
* @returns {boolean} True if there are remaining arguments
|
|
71
|
+
*/
|
|
72
|
+
hasRemainingArgs(): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Get raw command args for backward compatibility
|
|
75
|
+
* @returns {Object} Raw command args object
|
|
76
|
+
*/
|
|
77
|
+
getRawCmdArgs(): any;
|
|
78
|
+
/**
|
|
79
|
+
* Get raw parsed command for backward compatibility
|
|
80
|
+
* @returns {Object} Raw parsed command object
|
|
81
|
+
*/
|
|
82
|
+
getRawParsed(): any;
|
|
83
|
+
/**
|
|
84
|
+
* Get all task names that have command nodes
|
|
85
|
+
* @returns {Array} Array of task names
|
|
86
|
+
*/
|
|
87
|
+
getAllTaskNames(): string[];
|
|
88
|
+
/**
|
|
89
|
+
* Check if a given task is the last task from CLI arguments
|
|
90
|
+
* This is used to determine where to append remaining args
|
|
91
|
+
* @param {string} taskName - Name of the task to check
|
|
92
|
+
* @param {string} taskType - Type of task (e.g., 'shell', 'function')
|
|
93
|
+
* @returns {boolean} True if this is the last CLI task and it's a shell task
|
|
94
|
+
*/
|
|
95
|
+
isLastTask(taskName: any): boolean;
|
|
96
|
+
}
|
|
97
|
+
export { CliContext };
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CliContext encapsulates all CLI-related information from command line parsing
|
|
3
|
+
* This provides a clean interface for accessing command arguments, options, and metadata
|
|
4
|
+
* throughout the execution pipeline without tight coupling to CLI parsing details.
|
|
5
|
+
*/
|
|
6
|
+
class CliContext {
|
|
7
|
+
constructor(cmdArgs) {
|
|
8
|
+
// Full cmdArgs from CLI parsing
|
|
9
|
+
this._cmdArgs = cmdArgs;
|
|
10
|
+
this._parsed = cmdArgs.parsed;
|
|
11
|
+
this._subCmdNodes = cmdArgs.cmdNodes || cmdArgs.parsed?.command?.subCmdNodes || {};
|
|
12
|
+
this._opts = cmdArgs.opts;
|
|
13
|
+
this._tasks = cmdArgs.tasks || [];
|
|
14
|
+
this._searchResult = cmdArgs.searchResult;
|
|
15
|
+
this._remainingArgs = cmdArgs.parsed?._ || [];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Get command information for a specific task
|
|
19
|
+
* @param {string} taskName - Name of the task
|
|
20
|
+
* @returns {Object} Task command object with argv, opts, etc.
|
|
21
|
+
*/
|
|
22
|
+
getTaskCommand(taskName) {
|
|
23
|
+
return this._subCmdNodes[taskName] || {};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get argv array for a specific task
|
|
27
|
+
* @param {string} taskName - Name of the task
|
|
28
|
+
* @returns {Array} Task arguments array
|
|
29
|
+
*/
|
|
30
|
+
getTaskArgv(taskName) {
|
|
31
|
+
return this.getTaskCommand(taskName).argv || [];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get global command line options
|
|
35
|
+
* @returns {Object} Global options object
|
|
36
|
+
*/
|
|
37
|
+
getGlobalOptions() {
|
|
38
|
+
return this._opts;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get command metadata (jsonMeta)
|
|
42
|
+
* @returns {Object} Command metadata
|
|
43
|
+
*/
|
|
44
|
+
getMetadata() {
|
|
45
|
+
return this._parsed?.command?.jsonMeta || {};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get the list of tasks to execute
|
|
49
|
+
* @returns {Array} Tasks array
|
|
50
|
+
*/
|
|
51
|
+
getTasks() {
|
|
52
|
+
return this._tasks;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get search result information
|
|
56
|
+
* @returns {Object} Search result with found files, directories, etc.
|
|
57
|
+
*/
|
|
58
|
+
getSearchResult() {
|
|
59
|
+
return this._searchResult;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check if quiet mode is enabled
|
|
63
|
+
* @returns {boolean} True if quiet mode
|
|
64
|
+
*/
|
|
65
|
+
isQuiet() {
|
|
66
|
+
return this._opts.quiet;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Check if serial execution is requested
|
|
70
|
+
* @returns {boolean} True if serial execution
|
|
71
|
+
*/
|
|
72
|
+
isSerial() {
|
|
73
|
+
return this._opts.serial;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get stop on error setting
|
|
77
|
+
* @returns {string|boolean} Stop on error setting
|
|
78
|
+
*/
|
|
79
|
+
getStopOnError() {
|
|
80
|
+
return this._opts.soe;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get arguments that came after "--" in the CLI
|
|
84
|
+
* These are stored in parsed._ by @fynjs/cli-args
|
|
85
|
+
* @returns {Array} Arguments after "--"
|
|
86
|
+
*/
|
|
87
|
+
getRemainingArgs() {
|
|
88
|
+
return this._remainingArgs;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Check if there are any remaining arguments after "--"
|
|
92
|
+
* @returns {boolean} True if there are remaining arguments
|
|
93
|
+
*/
|
|
94
|
+
hasRemainingArgs() {
|
|
95
|
+
return this._remainingArgs && this._remainingArgs.length > 0;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get raw command args for backward compatibility
|
|
99
|
+
* @returns {Object} Raw command args object
|
|
100
|
+
*/
|
|
101
|
+
getRawCmdArgs() {
|
|
102
|
+
return this._cmdArgs;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get raw parsed command for backward compatibility
|
|
106
|
+
* @returns {Object} Raw parsed command object
|
|
107
|
+
*/
|
|
108
|
+
getRawParsed() {
|
|
109
|
+
return this._parsed;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Get all task names that have command nodes
|
|
113
|
+
* @returns {Array} Array of task names
|
|
114
|
+
*/
|
|
115
|
+
getAllTaskNames() {
|
|
116
|
+
return Object.keys(this._subCmdNodes);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Check if a given task is the last task from CLI arguments
|
|
120
|
+
* This is used to determine where to append remaining args
|
|
121
|
+
* @param {string} taskName - Name of the task to check
|
|
122
|
+
* @param {string} taskType - Type of task (e.g., 'shell', 'function')
|
|
123
|
+
* @returns {boolean} True if this is the last CLI task and it's a shell task
|
|
124
|
+
*/
|
|
125
|
+
isLastTask(taskName) {
|
|
126
|
+
return this._tasks.at(-1) === taskName;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
export { CliContext };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
declare const SERIAL_SYM: unique symbol;
|
|
2
|
+
declare const CONCURRENT_SYM: unique symbol;
|
|
3
|
+
export declare const NAMESPACE = "/";
|
|
4
|
+
export declare const NS_SEP = "/";
|
|
5
|
+
export declare const SERIAL_SIG: (string | symbol)[];
|
|
6
|
+
export declare const CONCURRENT_SIG: (string | symbol)[];
|
|
7
|
+
export declare const ANON_SHELL_SIG: string[];
|
|
8
|
+
export declare const ANON_SHELL_OPT_SIG: string[];
|
|
9
|
+
export declare const ANON_SHELL_OPT_CLOSE_SIG: string[];
|
|
10
|
+
export declare const SHELL_FLAGS: string[];
|
|
11
|
+
export declare const STR_ARRAY_SIG = "~[";
|
|
12
|
+
export declare const STOP_SYM: unique symbol;
|
|
13
|
+
export declare const INTERNALS: unique symbol;
|
|
14
|
+
export { CONCURRENT_SYM, SERIAL_SYM };
|
|
15
|
+
declare const _default: {
|
|
16
|
+
NAMESPACE: string;
|
|
17
|
+
NS_SEP: string;
|
|
18
|
+
SERIAL_SIG: (string | symbol)[];
|
|
19
|
+
CONCURRENT_SIG: (string | symbol)[];
|
|
20
|
+
ANON_SHELL_SIG: string[];
|
|
21
|
+
ANON_SHELL_OPT_SIG: string[];
|
|
22
|
+
ANON_SHELL_OPT_CLOSE_SIG: string[];
|
|
23
|
+
SHELL_FLAGS: string[];
|
|
24
|
+
STR_ARRAY_SIG: string;
|
|
25
|
+
CONCURRENT_SYM: symbol;
|
|
26
|
+
SERIAL_SYM: symbol;
|
|
27
|
+
STOP_SYM: symbol;
|
|
28
|
+
INTERNALS: symbol;
|
|
29
|
+
};
|
|
30
|
+
export default _default;
|