@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.
- 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
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const SERIAL_SYM = Symbol("serial");
|
|
2
2
|
const CONCURRENT_SYM = Symbol("concurrent");
|
|
3
|
-
|
|
4
3
|
export const NAMESPACE = "/";
|
|
5
4
|
export const NS_SEP = "/";
|
|
6
5
|
export const SERIAL_SIG = [".", "-s", "--serial", "--ser", SERIAL_SYM];
|
|
@@ -12,21 +11,19 @@ export const SHELL_FLAGS = ["tty", "spawn", "sync", "noenv", "npm"];
|
|
|
12
11
|
export const STR_ARRAY_SIG = "~[";
|
|
13
12
|
export const STOP_SYM = Symbol("xrun.stop");
|
|
14
13
|
export const INTERNALS = Symbol("xrun.internals");
|
|
15
|
-
|
|
16
14
|
export { CONCURRENT_SYM, SERIAL_SYM };
|
|
17
|
-
|
|
18
15
|
export default {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
16
|
+
NAMESPACE,
|
|
17
|
+
NS_SEP,
|
|
18
|
+
SERIAL_SIG,
|
|
19
|
+
CONCURRENT_SIG,
|
|
20
|
+
ANON_SHELL_SIG,
|
|
21
|
+
ANON_SHELL_OPT_SIG,
|
|
22
|
+
ANON_SHELL_OPT_CLOSE_SIG,
|
|
23
|
+
SHELL_FLAGS,
|
|
24
|
+
STR_ARRAY_SIG,
|
|
25
|
+
CONCURRENT_SYM,
|
|
26
|
+
SERIAL_SYM,
|
|
27
|
+
STOP_SYM,
|
|
28
|
+
INTERNALS
|
|
32
29
|
};
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import container from "./xrun-instance.js";
|
|
2
|
-
|
|
3
2
|
const xrun = container.xrun;
|
|
4
|
-
|
|
5
3
|
export default xrun;
|
|
6
|
-
|
|
7
4
|
//
|
|
8
5
|
// Keep `require("@fynjs/run")` returning the xrun instance itself rather than the module
|
|
9
6
|
// namespace, so a CommonJS task file - still a first class way to use this - does not have to
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import chalk from "./chalk.js";
|
|
2
|
+
const MSEC_IN_SECOND = 1000;
|
|
3
|
+
const MSEC_IN_MINUTE = 60 * MSEC_IN_SECOND;
|
|
4
|
+
const pad2 = x => {
|
|
5
|
+
return (x < 10 ? "0" : "") + x;
|
|
6
|
+
};
|
|
7
|
+
class Logger {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.coloring(true);
|
|
10
|
+
this.buffering(true);
|
|
11
|
+
this.quiet(true);
|
|
12
|
+
}
|
|
13
|
+
quiet(q) {
|
|
14
|
+
this._quiet = q;
|
|
15
|
+
}
|
|
16
|
+
buffering(f) {
|
|
17
|
+
if (f) {
|
|
18
|
+
if (!this._buf)
|
|
19
|
+
this._buf = [];
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
this._buf = undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
resetBuffer(flush, buffering) {
|
|
26
|
+
if (this._buf) {
|
|
27
|
+
const buf = this._buf;
|
|
28
|
+
this._buf = [];
|
|
29
|
+
if (flush && !this._quiet) {
|
|
30
|
+
buf.forEach(l => this.write(`${l}\n`));
|
|
31
|
+
}
|
|
32
|
+
this.buffering(buffering);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
coloring(f) {
|
|
36
|
+
if (f) {
|
|
37
|
+
this._L = `${chalk.magenta("[")}`;
|
|
38
|
+
this._R = `${chalk.magenta("]")}`;
|
|
39
|
+
this._c = true;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
this._L = `[`;
|
|
43
|
+
this._R = `]`;
|
|
44
|
+
this._c = false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
get buffer() {
|
|
48
|
+
return this._buf || [];
|
|
49
|
+
}
|
|
50
|
+
timestamp() {
|
|
51
|
+
const d = new Date();
|
|
52
|
+
const ts = `${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())}`;
|
|
53
|
+
return ts;
|
|
54
|
+
}
|
|
55
|
+
_ts() {
|
|
56
|
+
return this._c
|
|
57
|
+
? `${this._L}${chalk.gray(this.timestamp())}${this._R}`
|
|
58
|
+
: `${this._L}${this.timestamp()}${this._R}`;
|
|
59
|
+
}
|
|
60
|
+
formatElapse(elapse) {
|
|
61
|
+
if (elapse >= MSEC_IN_MINUTE) {
|
|
62
|
+
const min = elapse / MSEC_IN_MINUTE;
|
|
63
|
+
return `${min.toFixed(2)} min`;
|
|
64
|
+
}
|
|
65
|
+
else if (elapse >= MSEC_IN_SECOND) {
|
|
66
|
+
const sec = elapse / MSEC_IN_SECOND;
|
|
67
|
+
return `${sec.toFixed(2)} sec`;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
return `${elapse} ms`;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
log(...args) {
|
|
74
|
+
const msg = args.join(" ");
|
|
75
|
+
const output = `${this._ts()} ${msg}`;
|
|
76
|
+
if (this._buf) {
|
|
77
|
+
this._buf.push(output);
|
|
78
|
+
}
|
|
79
|
+
else if (!this._quiet) {
|
|
80
|
+
this.write(`${output}\n`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
error(...args) {
|
|
84
|
+
const x = this._quiet;
|
|
85
|
+
this._quiet = false;
|
|
86
|
+
this.log(...args);
|
|
87
|
+
this.quiet(x);
|
|
88
|
+
}
|
|
89
|
+
write(output) {
|
|
90
|
+
process.stdout.write(output);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const logger = new Logger();
|
|
94
|
+
logger.pad2 = pad2;
|
|
95
|
+
export default logger;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import Fs from "fs";
|
|
2
|
+
import Path from "path";
|
|
3
|
+
//
|
|
4
|
+
// This package's own manifest, and the directory holding it.
|
|
5
|
+
//
|
|
6
|
+
// It used to be `import myPkg from "../package.json" with { type: "json" }` in six files. That
|
|
7
|
+
// cannot survive the build: tsc pulls the JSON into the program and emits a COPY at
|
|
8
|
+
// dist/package.json, and that copy - name "@fynjs/run", `main` "./dist/lib/index.js" - then
|
|
9
|
+
// becomes what node's self-reference resolution finds when anything inside dist/ requires
|
|
10
|
+
// "@fynjs/run". It resolved to dist/dist/lib/index.js and the bin died before printing anything.
|
|
11
|
+
//
|
|
12
|
+
// Walking up to the first manifest that is actually ours works from source (lib/) and from the
|
|
13
|
+
// build (dist/lib/) alike, and emits no JSON.
|
|
14
|
+
//
|
|
15
|
+
const findOwnPkg = () => {
|
|
16
|
+
let dir = import.meta.dirname;
|
|
17
|
+
for (;;) {
|
|
18
|
+
const file = Path.join(dir, "package.json");
|
|
19
|
+
if (Fs.existsSync(file)) {
|
|
20
|
+
try {
|
|
21
|
+
const json = JSON.parse(Fs.readFileSync(file, "utf8"));
|
|
22
|
+
if (json.name === "@fynjs/run") {
|
|
23
|
+
return { json, dir };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// unreadable or malformed - keep walking rather than dying at import time
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const parent = Path.dirname(dir);
|
|
31
|
+
// walking past the filesystem root means this file is not inside its own package at all
|
|
32
|
+
/* istanbul ignore next */
|
|
33
|
+
if (parent === dir) {
|
|
34
|
+
return { json: {}, dir: import.meta.dirname };
|
|
35
|
+
}
|
|
36
|
+
dir = parent;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const own = findOwnPkg();
|
|
40
|
+
/** directory of this package's own manifest - the root of this copy of @fynjs/run */
|
|
41
|
+
export const myPkgDir = own.dir;
|
|
42
|
+
export default own.json;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
class NSOrder {
|
|
3
|
+
constructor() {
|
|
4
|
+
this._namespaces = [];
|
|
5
|
+
this._overrides = {};
|
|
6
|
+
}
|
|
7
|
+
//
|
|
8
|
+
// make name order before overrides (string or array of string)
|
|
9
|
+
//
|
|
10
|
+
// the ordering is kept by an integer
|
|
11
|
+
// each new namespace is reset with a init value (default 1)
|
|
12
|
+
// then the max of values of its overrides is looked up
|
|
13
|
+
// if its value is not > max, then it's set to max + 1
|
|
14
|
+
// process repeated until all override max are smaller
|
|
15
|
+
//
|
|
16
|
+
// finally sort namespace by order value
|
|
17
|
+
//
|
|
18
|
+
add(name, overrides, priority = 1) {
|
|
19
|
+
let overrideMap = this._overrides[name];
|
|
20
|
+
if (!overrideMap) {
|
|
21
|
+
overrideMap = this._overrides[name] = { initValue: priority, others: [] };
|
|
22
|
+
this._namespaces.push(name);
|
|
23
|
+
}
|
|
24
|
+
if (!overrides) {
|
|
25
|
+
overrides = [];
|
|
26
|
+
}
|
|
27
|
+
else if (!Array.isArray(overrides)) {
|
|
28
|
+
overrides = [overrides];
|
|
29
|
+
}
|
|
30
|
+
overrideMap.others = overrideMap.others.concat(overrides);
|
|
31
|
+
// do a first level circular check
|
|
32
|
+
for (const [ns, ov] of Object.entries(this._overrides)) {
|
|
33
|
+
if (ns !== name && overrideMap.others.indexOf(ns) >= 0 && ov.others.indexOf(name) >= 0) {
|
|
34
|
+
throw new Error(`circular namespace override between '${name}' and '${ns}'`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// reset all values
|
|
38
|
+
for (const v of Object.values(this._overrides)) {
|
|
39
|
+
v.value = v.initValue;
|
|
40
|
+
}
|
|
41
|
+
// assign value base on override map
|
|
42
|
+
let done;
|
|
43
|
+
let n = 0;
|
|
44
|
+
do {
|
|
45
|
+
done = true;
|
|
46
|
+
for (const ov of Object.values(this._overrides)) {
|
|
47
|
+
if (ov.others.length === 0)
|
|
48
|
+
continue;
|
|
49
|
+
const max = ov.others.reduce((max, oname) => Math.max((this._overrides[oname] && this._overrides[oname].value) || 0, max), 1);
|
|
50
|
+
if (ov.value <= max) {
|
|
51
|
+
done = false;
|
|
52
|
+
ov.value = 1 + max;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
n++;
|
|
56
|
+
assert(n < 10, "calculating namespace order looped too many times, there may be circular overrides");
|
|
57
|
+
} while (!done);
|
|
58
|
+
this._namespaces.sort((a, b) => this._overrides[b].value - this._overrides[a].value);
|
|
59
|
+
return this._namespaces;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export default NSOrder;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import stringify from "../stringify.js";
|
|
2
|
+
import chalk from "../chalk.js";
|
|
3
|
+
import assert from "assert";
|
|
4
|
+
import Path from "path";
|
|
5
|
+
import xsh from "xsh";
|
|
6
|
+
const replaceCwd = p => xsh.pathCwdNm.replace(p, null, "g");
|
|
7
|
+
const stringifyTask = x => {
|
|
8
|
+
x = stringify(x);
|
|
9
|
+
/* istanbul ignore next */
|
|
10
|
+
if (Path.sep === "\\") {
|
|
11
|
+
/* istanbul ignore next */
|
|
12
|
+
x = x.replace(/\\\\/g, "\\");
|
|
13
|
+
}
|
|
14
|
+
return replaceCwd(x);
|
|
15
|
+
};
|
|
16
|
+
const printNSTasks = (title, names, tasks) => {
|
|
17
|
+
let guideChar = ".";
|
|
18
|
+
let nameColor = "cyan";
|
|
19
|
+
const taskType = task => task !== null && task !== undefined && task.constructor.name;
|
|
20
|
+
const maxNameLen = 2 +
|
|
21
|
+
names.reduce((l, x) => {
|
|
22
|
+
const task = tasks[x];
|
|
23
|
+
if (taskType(task) === "Object" && !task.desc) {
|
|
24
|
+
return l;
|
|
25
|
+
}
|
|
26
|
+
return x.length > l ? x.length : l;
|
|
27
|
+
}, 0);
|
|
28
|
+
const printTask = name => {
|
|
29
|
+
const task = tasks[name];
|
|
30
|
+
const tof = taskType(task);
|
|
31
|
+
const paddedArr = new Array(Math.max(1, maxNameLen - name.length));
|
|
32
|
+
const paddedName = chalk[nameColor](` ${name} ${paddedArr.join(guideChar)}`);
|
|
33
|
+
if (tof === "String") {
|
|
34
|
+
console.log(paddedName, chalk.magenta(replaceCwd(task)));
|
|
35
|
+
}
|
|
36
|
+
else if (tof === "Array") {
|
|
37
|
+
console.log(paddedName, chalk.green(`${stringifyTask(task)}`));
|
|
38
|
+
}
|
|
39
|
+
else if (tof === "Object") {
|
|
40
|
+
if (!task.desc) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
console.log(paddedName, chalk.yellow(task.desc));
|
|
44
|
+
const spacePad = new Array(maxNameLen + 4).join(" ");
|
|
45
|
+
if (task.task) {
|
|
46
|
+
console.log(chalk.dim.green(`${spacePad} tasks: ${stringifyTask(task.task)}`));
|
|
47
|
+
}
|
|
48
|
+
if (task.dep) {
|
|
49
|
+
console.log(chalk.dim.cyan(`${spacePad} deps: ${stringifyTask(task.dep)}`));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else if (tof === "Function") {
|
|
53
|
+
console.log(paddedName, "function", task.name);
|
|
54
|
+
}
|
|
55
|
+
else if (tof === "XTaskSpec") {
|
|
56
|
+
console.log(paddedName, chalk.magenta(replaceCwd(task.toString())));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
console.log(paddedName, chalk.red(`Unknown task type ${tof}`));
|
|
60
|
+
}
|
|
61
|
+
guideChar = guideChar === "." ? "-" : ".";
|
|
62
|
+
nameColor = nameColor === "cyan" ? "blue" : "cyan";
|
|
63
|
+
};
|
|
64
|
+
console.log(chalk.underline(title));
|
|
65
|
+
console.log("");
|
|
66
|
+
names.sort().forEach(printTask);
|
|
67
|
+
console.log("");
|
|
68
|
+
};
|
|
69
|
+
function printTasks(xtasks) {
|
|
70
|
+
const namespaces = xtasks._namespaces;
|
|
71
|
+
const tasks = xtasks._tasks;
|
|
72
|
+
namespaces.forEach(n => {
|
|
73
|
+
const nTasks = tasks[n];
|
|
74
|
+
assert(nTasks, `Task namespace ${n} is falsy`);
|
|
75
|
+
if (Object.keys(nTasks).length === 0) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
console.log(chalk.inverse.bold.red(`Namespace '${n}'`));
|
|
79
|
+
const taskNames = Object.keys(nTasks).reduce((an, tn) => {
|
|
80
|
+
let lbl;
|
|
81
|
+
if (tn.match(/(^\.)|([$~])/)) {
|
|
82
|
+
lbl = "Hidden";
|
|
83
|
+
}
|
|
84
|
+
else if (tn.match(/^[a-zA-Z_0-9]+$/)) {
|
|
85
|
+
lbl = "Primary";
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
lbl = "Other";
|
|
89
|
+
}
|
|
90
|
+
an[lbl] = an[lbl] || [];
|
|
91
|
+
an[lbl].push(tn);
|
|
92
|
+
return an;
|
|
93
|
+
}, {});
|
|
94
|
+
const isEmpty = x => !x || x.length === 0;
|
|
95
|
+
["Primary", "Other"]
|
|
96
|
+
.filter(tt => !isEmpty(taskNames[tt]))
|
|
97
|
+
.forEach(tt => printNSTasks(chalk.bold(`${tt} Tasks`), taskNames[tt], nTasks));
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
export default printTasks;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
declare class XReporterConsole {
|
|
2
|
+
_logger: any;
|
|
3
|
+
_sep: any;
|
|
4
|
+
_tags: any;
|
|
5
|
+
_xrun: any;
|
|
6
|
+
constructor(xrun: any);
|
|
7
|
+
_log(qItem: any, msg: any): void;
|
|
8
|
+
_indent(qItem: any, sep?: any): string;
|
|
9
|
+
_onExecute(data: any): void;
|
|
10
|
+
_depMsg(qItem: any): "" | "'s dependency";
|
|
11
|
+
_onExeType_env(data: any): void;
|
|
12
|
+
_onExeType_shell(data: any): void;
|
|
13
|
+
_onExeType_lookup(_data: any): void;
|
|
14
|
+
_onExeType_serial_arr(data: any): void;
|
|
15
|
+
_onExeType_concurrent_arr(data: any): void;
|
|
16
|
+
_onExeType_function(data: any): void;
|
|
17
|
+
_itemDisplayName(qItem: any): string;
|
|
18
|
+
_onDoneItem(data: any): void;
|
|
19
|
+
}
|
|
20
|
+
export default XReporterConsole;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import chalk from "../chalk.js";
|
|
2
|
+
import logger from "../logger.js";
|
|
3
|
+
import stringify from "../stringify.js";
|
|
4
|
+
import assert from "assert";
|
|
5
|
+
import defaults from "../defaults.js";
|
|
6
|
+
import xsh from "xsh";
|
|
7
|
+
class XReporterConsole {
|
|
8
|
+
constructor(xrun) {
|
|
9
|
+
this._xrun = xrun;
|
|
10
|
+
xrun.on("execute", data => this._onExecute(data));
|
|
11
|
+
xrun.on("done-item", data => this._onDoneItem(data));
|
|
12
|
+
xrun.on("run", () => (this._sep = ""));
|
|
13
|
+
xrun.on("not-found", err => {
|
|
14
|
+
this._logger.log(err.message);
|
|
15
|
+
});
|
|
16
|
+
xrun.once("warn-finally", () => {
|
|
17
|
+
logger.log(chalk.yellow("NOTE: finally hook is unreliable when stopOnError is set to full"));
|
|
18
|
+
});
|
|
19
|
+
this._tags = {};
|
|
20
|
+
this._logger = logger;
|
|
21
|
+
}
|
|
22
|
+
_log(qItem, msg) {
|
|
23
|
+
this._logger.log(`${this._indent(qItem)}${msg}`);
|
|
24
|
+
this._tags[qItem.id] = { sep: this._sep, msg };
|
|
25
|
+
}
|
|
26
|
+
_indent(qItem, sep) {
|
|
27
|
+
if (sep === undefined) {
|
|
28
|
+
this._sep = this._sep === "." ? "-" : ".";
|
|
29
|
+
sep = this._sep;
|
|
30
|
+
}
|
|
31
|
+
if (qItem.level) {
|
|
32
|
+
return chalk.magenta(new Array(qItem.level + 1).join(sep));
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
return "";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
_onExecute(data) {
|
|
39
|
+
const m = `_onExeType_${data.type.replace(/-/g, "_")}`;
|
|
40
|
+
this[m](data);
|
|
41
|
+
}
|
|
42
|
+
_depMsg(qItem) {
|
|
43
|
+
const depDee = qItem.value().depDee;
|
|
44
|
+
const dep = depDee ? "'s dependency" : "";
|
|
45
|
+
return dep;
|
|
46
|
+
}
|
|
47
|
+
_onExeType_env(data) {
|
|
48
|
+
const qItem = data.qItem;
|
|
49
|
+
const name = this._itemDisplayName(qItem);
|
|
50
|
+
const str = data.cmdVal.toString();
|
|
51
|
+
const msg = `Execute ${name} setting ${chalk.blue(str)}`;
|
|
52
|
+
this._log(qItem, msg);
|
|
53
|
+
}
|
|
54
|
+
_onExeType_shell(data) {
|
|
55
|
+
const qItem = data.qItem;
|
|
56
|
+
const name = this._itemDisplayName(qItem);
|
|
57
|
+
let cmd;
|
|
58
|
+
if (data.cmdVal.constructor.name === "XTaskSpec") {
|
|
59
|
+
cmd = xsh.pathCwd.replace(data.cmdVal.toString(data.cmd2), ".", "g");
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
cmd = xsh.pathCwd.replace(data.cmd, ".", "g");
|
|
63
|
+
}
|
|
64
|
+
const msg = data.anon
|
|
65
|
+
? `Execute ${chalk.cyan(cmd)}`
|
|
66
|
+
: `Execute ${name}${this._depMsg(qItem)} ${chalk.blue(cmd)}`;
|
|
67
|
+
this._log(qItem, msg);
|
|
68
|
+
}
|
|
69
|
+
_onExeType_lookup(_data) {
|
|
70
|
+
// do nothing
|
|
71
|
+
}
|
|
72
|
+
_onExeType_serial_arr(data) {
|
|
73
|
+
const qItem = data.qItem;
|
|
74
|
+
const name = this._itemDisplayName(qItem);
|
|
75
|
+
const ts = chalk.blue(stringify(data.array));
|
|
76
|
+
const msg = `Process ${name}${this._depMsg(qItem)} serial array ${ts}`;
|
|
77
|
+
this._log(qItem, msg);
|
|
78
|
+
}
|
|
79
|
+
_onExeType_concurrent_arr(data) {
|
|
80
|
+
const qItem = data.qItem;
|
|
81
|
+
const name = this._itemDisplayName(qItem);
|
|
82
|
+
const ts = chalk.blue(xsh.pathCwd.replace(stringify(data.array), ".", "g"));
|
|
83
|
+
const msg = `Process ${name}${this._depMsg(qItem)} concurrent array ${ts}`;
|
|
84
|
+
this._log(qItem, msg);
|
|
85
|
+
}
|
|
86
|
+
_onExeType_function(data) {
|
|
87
|
+
const qItem = data.qItem;
|
|
88
|
+
const name = this._itemDisplayName(qItem);
|
|
89
|
+
const anon = qItem.anon ? " anonymous " : " as ";
|
|
90
|
+
const msg = `Execute ${name}${this._depMsg(qItem)}${anon}function`;
|
|
91
|
+
this._log(qItem, msg);
|
|
92
|
+
}
|
|
93
|
+
_itemDisplayName(qItem) {
|
|
94
|
+
let ns = "";
|
|
95
|
+
const ix = qItem.name.indexOf(defaults.NS_SEP);
|
|
96
|
+
if (ix < 0) {
|
|
97
|
+
if (qItem.ns === defaults.NAMESPACE) {
|
|
98
|
+
ns = chalk.dim.cyan(qItem.ns);
|
|
99
|
+
}
|
|
100
|
+
else if (qItem.ns) {
|
|
101
|
+
ns = chalk.dim.cyan(`${qItem.ns}${defaults.NS_SEP}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const finallyMsg = qItem.isFinally ? chalk.magenta(":finally") : "";
|
|
105
|
+
return `${ns}${chalk.cyan(qItem.name)}${finallyMsg}`;
|
|
106
|
+
}
|
|
107
|
+
_onDoneItem(data) {
|
|
108
|
+
// const qItem = data.qItem;
|
|
109
|
+
const xqItem = data.xqItem;
|
|
110
|
+
const elapseStr = `(${logger.formatElapse(data.elapse)})`;
|
|
111
|
+
const failed = !!this._xrun.failed || !!xqItem.err;
|
|
112
|
+
const result = xqItem.err ? "Failed" : "Done";
|
|
113
|
+
const status = failed ? chalk.red(result) : chalk.green(result);
|
|
114
|
+
const tag = this._tags[xqItem.id];
|
|
115
|
+
assert(tag, `console reporter no tag found for ${xqItem.name}`);
|
|
116
|
+
this._logger.log(`${this._indent(xqItem, ">")}${status} ${tag.msg} ${chalk.magenta(elapseStr)}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export default XReporterConsole;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export default data => {
|
|
2
|
+
try {
|
|
3
|
+
return JSON.stringify(data, (key, value) => {
|
|
4
|
+
if (typeof value === "function") {
|
|
5
|
+
return "func";
|
|
6
|
+
}
|
|
7
|
+
else if (value.constructor.name === "XTaskSpec") {
|
|
8
|
+
return value.toString();
|
|
9
|
+
}
|
|
10
|
+
else if (typeof value === "symbol") {
|
|
11
|
+
return `<${value.toString().match(/\(([^)]+)\)/)[1]}>`;
|
|
12
|
+
}
|
|
13
|
+
return value;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
return `ERROR: ${err.message}`;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize task option specifications into @fynjs/cli-args compatible OptionSpec.
|
|
3
|
+
* Supports:
|
|
4
|
+
* - Native @fynjs/cli-args spec: { required: true, args: "<val string>", alias: "f" }
|
|
5
|
+
* - Shorthand args without value name: { args: "<string>" } -> { args: "<val string>" }
|
|
6
|
+
* - Legacy format: { require: true, type: "string", alias: "f" }
|
|
7
|
+
* - Legacy array format: { type: "array" } -> { args: "[val string..]" }
|
|
8
|
+
* - Legacy count format: { type: "count" } -> { counting: Infinity }
|
|
9
|
+
*
|
|
10
|
+
* @param {Record<string, any>} rawOpts - Raw options dictionary
|
|
11
|
+
* @returns {Record<string, any>} Normalized options dictionary
|
|
12
|
+
*/
|
|
13
|
+
export declare function normalizeTaskOptions(rawOpts?: Record<string, any>): Record<string, any>;
|
|
14
|
+
/**
|
|
15
|
+
* Normalize subcommand definitions so nested options and commands are properly structured.
|
|
16
|
+
*
|
|
17
|
+
* @param {Record<string, any>} rawCmds - Raw commands dictionary
|
|
18
|
+
* @returns {Record<string, any>} Normalized commands dictionary
|
|
19
|
+
*/
|
|
20
|
+
export declare function normalizeTaskCommands(rawCmds?: Record<string, any>): Record<string, any>;
|
|
21
|
+
/**
|
|
22
|
+
* Extract and normalize option specifications for a given task definition.
|
|
23
|
+
*
|
|
24
|
+
* @param {any} task - Task item or task object
|
|
25
|
+
* @returns {{ options: Record<string, any>, commands: Record<string, any>, allowUnknownOption?: boolean }}
|
|
26
|
+
*/
|
|
27
|
+
export declare function getTaskOptionSpec(task: any): {
|
|
28
|
+
options: Record<string, any>;
|
|
29
|
+
commands: Record<string, any>;
|
|
30
|
+
allowUnknownOption?: boolean;
|
|
31
|
+
};
|
|
32
|
+
declare const _default: {
|
|
33
|
+
normalizeTaskOptions: typeof normalizeTaskOptions;
|
|
34
|
+
normalizeTaskCommands: typeof normalizeTaskCommands;
|
|
35
|
+
getTaskOptionSpec: typeof getTaskOptionSpec;
|
|
36
|
+
};
|
|
37
|
+
export default _default;
|