@fynjs/run 1.1.0 → 1.1.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.
Files changed (103) hide show
  1. package/bin/qrun.js +6 -1
  2. package/bin/xrun.js +1 -1
  3. package/dist/cli/check-global.d.ts +1 -0
  4. package/{cli → dist/cli}/check-global.js +3 -3
  5. package/dist/cli/ck.d.ts +1 -0
  6. package/dist/cli/cli-options.d.ts +80 -0
  7. package/dist/cli/cli-options.js +95 -0
  8. package/dist/cli/config.d.ts +7 -0
  9. package/dist/cli/config.js +7 -0
  10. package/dist/cli/env.d.ts +17 -0
  11. package/dist/cli/env.js +31 -0
  12. package/dist/cli/npm-loader.d.ts +2 -0
  13. package/dist/cli/npm-loader.js +43 -0
  14. package/dist/cli/parse-cmd-args.d.ts +34 -0
  15. package/dist/cli/parse-cmd-args.js +199 -0
  16. package/dist/cli/provider-packages.d.ts +28 -0
  17. package/dist/cli/provider-packages.js +62 -0
  18. package/dist/cli/search-up-task-file.d.ts +8 -0
  19. package/dist/cli/search-up-task-file.js +79 -0
  20. package/dist/cli/task-file.d.ts +40 -0
  21. package/dist/cli/task-file.js +177 -0
  22. package/dist/cli/ts-runner.d.ts +2 -0
  23. package/dist/cli/ts-runner.js +60 -0
  24. package/dist/cli/usage.d.ts +2 -0
  25. package/dist/cli/wrap-process.d.ts +10 -0
  26. package/dist/cli/wrap-process.js +26 -0
  27. package/dist/cli/xrun-main.d.ts +119 -0
  28. package/dist/cli/xrun-main.js +417 -0
  29. package/dist/cli/xrun.d.ts +2 -0
  30. package/{cli → dist/cli}/xrun.js +0 -1
  31. package/dist/lib/chalk.d.ts +2 -0
  32. package/{lib → dist/lib}/chalk.js +0 -1
  33. package/dist/lib/cli-context.d.ts +97 -0
  34. package/dist/lib/cli-context.js +129 -0
  35. package/dist/lib/defaults.d.ts +30 -0
  36. package/{lib → dist/lib}/defaults.js +13 -16
  37. package/dist/lib/gen-xqid.d.ts +2 -0
  38. package/dist/lib/gen-xqid.js +8 -0
  39. package/dist/lib/index.d.ts +3 -0
  40. package/{lib → dist/lib}/index.js +0 -3
  41. package/dist/lib/logger.d.ts +2 -0
  42. package/dist/lib/logger.js +95 -0
  43. package/dist/lib/my-pkg.d.ts +4 -0
  44. package/dist/lib/my-pkg.js +42 -0
  45. package/dist/lib/ns-order.d.ts +7 -0
  46. package/dist/lib/ns-order.js +62 -0
  47. package/dist/lib/print-tasks/index.d.ts +2 -0
  48. package/dist/lib/print-tasks/index.js +100 -0
  49. package/dist/lib/reporters/console.d.ts +20 -0
  50. package/dist/lib/reporters/console.js +119 -0
  51. package/dist/lib/stringify.d.ts +2 -0
  52. package/dist/lib/stringify.js +19 -0
  53. package/dist/lib/util/parse-array.d.ts +2 -0
  54. package/dist/lib/util/parse-array.js +5 -0
  55. package/dist/lib/util/task-options.d.ts +37 -0
  56. package/dist/lib/util/task-options.js +115 -0
  57. package/dist/lib/util/update-env.d.ts +1 -0
  58. package/dist/lib/util/update-env.js +18 -0
  59. package/dist/lib/xqitem.d.ts +22 -0
  60. package/dist/lib/xqitem.js +57 -0
  61. package/dist/lib/xqtor.d.ts +57 -0
  62. package/dist/lib/xqtor.js +704 -0
  63. package/dist/lib/xqtree.d.ts +11 -0
  64. package/dist/lib/xqtree.js +33 -0
  65. package/dist/lib/xrun-instance.d.ts +9 -0
  66. package/dist/lib/xrun-instance.js +27 -0
  67. package/dist/lib/xrun.d.ts +55 -0
  68. package/dist/lib/xrun.js +317 -0
  69. package/dist/lib/xtask-spec.d.ts +10 -0
  70. package/dist/lib/xtask-spec.js +57 -0
  71. package/dist/lib/xtasks.d.ts +25 -0
  72. package/dist/lib/xtasks.js +119 -0
  73. package/package.json +39 -15
  74. package/cli/cli-options.js +0 -98
  75. package/cli/config.js +0 -8
  76. package/cli/env.js +0 -33
  77. package/cli/npm-loader.js +0 -56
  78. package/cli/parse-cmd-args.js +0 -156
  79. package/cli/provider-packages.js +0 -73
  80. package/cli/search-up-task-file.js +0 -92
  81. package/cli/task-file.js +0 -192
  82. package/cli/ts-runner.js +0 -62
  83. package/cli/wrap-process.js +0 -27
  84. package/cli/xrun-main.js +0 -425
  85. package/lib/cli-context.js +0 -145
  86. package/lib/gen-xqid.js +0 -10
  87. package/lib/logger.js +0 -105
  88. package/lib/ns-order.js +0 -76
  89. package/lib/print-tasks/index.js +0 -105
  90. package/lib/reporters/console.js +0 -133
  91. package/lib/stringify.js +0 -16
  92. package/lib/util/parse-array.js +0 -5
  93. package/lib/util/update-env.js +0 -16
  94. package/lib/xqitem.js +0 -70
  95. package/lib/xqtor.js +0 -814
  96. package/lib/xqtree.js +0 -41
  97. package/lib/xrun-instance.js +0 -33
  98. package/lib/xrun.d.ts +0 -89
  99. package/lib/xrun.js +0 -344
  100. package/lib/xtask-spec.js +0 -63
  101. package/lib/xtasks.js +0 -137
  102. /package/{cli → dist/cli}/ck.js +0 -0
  103. /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
+ };
@@ -0,0 +1,2 @@
1
+ import { xrunMain } from "./xrun-main.js";
2
+ export default xrunMain;
@@ -1,5 +1,4 @@
1
1
  import { xrunMain } from "./xrun-main.js";
2
-
3
2
  //
4
3
  // Async: task files load through `import()` so a task file can use top-level await, which
5
4
  // `require` can never support. Callers must await this - bin/xrun.js does, and so must any
@@ -0,0 +1,2 @@
1
+ import chalk from "chalk";
2
+ export default chalk;
@@ -7,5 +7,4 @@
7
7
  // consumers as a module namespace, and call sites assign to `chalk.level`.
8
8
  //
9
9
  import chalk from "chalk";
10
-
11
10
  export default chalk;
@@ -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;