hereby 1.7.0 → 1.8.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.
- package/dist/cli/formatTasks.js +15 -17
- package/dist/cli/index.js +6 -6
- package/dist/cli/loadHerebyfile.js +7 -5
- package/dist/cli/parseArgs.js +13 -17
- package/dist/cli/reexec.js +1 -1
- package/dist/cli/runner.js +1 -1
- package/dist/cli/utils.js +9 -10
- package/dist/index.d.ts +1 -1
- package/dist/index.js +8 -8
- package/package.json +4 -3
package/dist/cli/formatTasks.js
CHANGED
|
@@ -1,37 +1,35 @@
|
|
|
1
1
|
import commandLineUsage from "command-line-usage";
|
|
2
2
|
import pc from "picocolors";
|
|
3
|
-
import {
|
|
3
|
+
import { compareStrings, compareTaskNames } from "./utils.js";
|
|
4
4
|
export function formatTasks(format, tasks, defaultTask) {
|
|
5
|
-
tasks = tasks
|
|
6
|
-
.slice(0)
|
|
7
|
-
.filter((task) => !task.options.hiddenFromTaskList)
|
|
8
|
-
.sort(taskSorter);
|
|
5
|
+
tasks = tasks.filter(isTaskVisible).sort(compareTaskNames);
|
|
9
6
|
if (format === "simple") {
|
|
10
7
|
return tasks.map((task) => task.options.name).join("\n");
|
|
11
8
|
}
|
|
12
|
-
|
|
13
|
-
sections.push({
|
|
9
|
+
return commandLineUsage({
|
|
14
10
|
header: "Available tasks",
|
|
15
11
|
content: tasks.map((task) => {
|
|
16
12
|
var _a;
|
|
17
|
-
const name = task
|
|
18
|
-
? pc.
|
|
19
|
-
:
|
|
20
|
-
|
|
13
|
+
const name = task === defaultTask
|
|
14
|
+
? `${pc.green(task.options.name)} (default)`
|
|
15
|
+
: pc.blue(task.options.name);
|
|
16
|
+
let descriptionParts;
|
|
21
17
|
if (task.options.description) {
|
|
22
|
-
descriptionParts
|
|
18
|
+
descriptionParts = [task.options.description];
|
|
23
19
|
}
|
|
24
|
-
const deps = (_a = task.options.dependencies) === null || _a === void 0 ? void 0 : _a.filter(
|
|
20
|
+
const deps = (_a = task.options.dependencies) === null || _a === void 0 ? void 0 : _a.filter(isTaskVisible);
|
|
25
21
|
if (deps && deps.length > 0) {
|
|
26
22
|
const depNames = deps
|
|
27
23
|
.map((task) => task.options.name)
|
|
28
|
-
.sort(
|
|
24
|
+
.sort(compareStrings)
|
|
29
25
|
.map((v) => pc.blue(v));
|
|
30
|
-
descriptionParts.push(`Depends on: ${depNames.join(", ")}`);
|
|
26
|
+
(descriptionParts !== null && descriptionParts !== void 0 ? descriptionParts : (descriptionParts = [])).push(`Depends on: ${depNames.join(", ")}`);
|
|
31
27
|
}
|
|
32
|
-
return { name, description: descriptionParts.join("\n") };
|
|
28
|
+
return { name, description: descriptionParts === null || descriptionParts === void 0 ? void 0 : descriptionParts.join("\n") };
|
|
33
29
|
}),
|
|
34
30
|
});
|
|
35
|
-
|
|
31
|
+
}
|
|
32
|
+
function isTaskVisible(task) {
|
|
33
|
+
return !task.options.hiddenFromTaskList;
|
|
36
34
|
}
|
|
37
35
|
//# sourceMappingURL=formatTasks.js.map
|
package/dist/cli/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import path from "path";
|
|
1
|
+
import path from "node:path";
|
|
2
2
|
import pc from "picocolors";
|
|
3
3
|
import { formatTasks } from "./formatTasks.js";
|
|
4
4
|
import { findHerebyfile, loadHerebyfile } from "./loadHerebyfile.js";
|
|
5
5
|
import { getUsage, parseArgs } from "./parseArgs.js";
|
|
6
6
|
import { reexec } from "./reexec.js";
|
|
7
7
|
import { Runner } from "./runner.js";
|
|
8
|
-
import { ExitCodeError, UserError } from "./utils.js";
|
|
8
|
+
import { compareTaskNames, ExitCodeError, UserError } from "./utils.js";
|
|
9
9
|
export async function main(d) {
|
|
10
10
|
try {
|
|
11
11
|
await mainWorker(d);
|
|
@@ -46,7 +46,7 @@ async function mainWorker(d) {
|
|
|
46
46
|
return;
|
|
47
47
|
}
|
|
48
48
|
const tasks = await selectTasks(d, herebyfile, herebyfilePath, args.run);
|
|
49
|
-
const taskNames = tasks.map((
|
|
49
|
+
const taskNames = tasks.map((task) => pc.blue(task.options.name)).join(", ");
|
|
50
50
|
d.log(`Using ${pc.yellow(d.simplifyPath(herebyfilePath))} to run ${taskNames}`);
|
|
51
51
|
const start = Date.now();
|
|
52
52
|
let errored = false;
|
|
@@ -72,14 +72,14 @@ export async function selectTasks(d, herebyfile, herebyfilePath, taskNames) {
|
|
|
72
72
|
for (const task of herebyfile.tasks) {
|
|
73
73
|
allTasks.set(task.options.name, task);
|
|
74
74
|
}
|
|
75
|
-
if (taskNames
|
|
75
|
+
if (taskNames.length > 0) {
|
|
76
76
|
const tasks = [];
|
|
77
77
|
for (const name of taskNames) {
|
|
78
78
|
const task = allTasks.get(name);
|
|
79
79
|
if (!task) {
|
|
80
80
|
let message = `Task "${name}" does not exist or is not exported from ${d.simplifyPath(herebyfilePath)}.`;
|
|
81
81
|
const { closest, distance } = await import("fastest-levenshtein");
|
|
82
|
-
const candidate = closest(name,
|
|
82
|
+
const candidate = closest(name, [...allTasks.keys()]);
|
|
83
83
|
if (distance(name, candidate) < name.length * 0.4) {
|
|
84
84
|
message += ` Did you mean "${candidate}"?`;
|
|
85
85
|
}
|
|
@@ -87,7 +87,7 @@ export async function selectTasks(d, herebyfile, herebyfilePath, taskNames) {
|
|
|
87
87
|
}
|
|
88
88
|
tasks.push(task);
|
|
89
89
|
}
|
|
90
|
-
return tasks;
|
|
90
|
+
return tasks.sort(compareTaskNames);
|
|
91
91
|
}
|
|
92
92
|
if (!herebyfile.defaultTask) {
|
|
93
93
|
throw new UserError(`No default task has been exported from ${d.simplifyPath(herebyfilePath)}; please specify a task name.`);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
3
4
|
import pc from "picocolors";
|
|
4
|
-
import { pathToFileURL } from "url";
|
|
5
5
|
import { Task } from "../index.js";
|
|
6
6
|
import { UserError } from "./utils.js";
|
|
7
7
|
const filenames = ["Herebyfile", "herebyfile"];
|
|
8
8
|
const extensions = ["mjs", "js"];
|
|
9
|
-
const allFilenames = new Set(extensions.
|
|
9
|
+
const allFilenames = new Set(extensions.flatMap((e) => filenames.map((f) => `${f}.${e}`)));
|
|
10
10
|
export async function findHerebyfile(dir) {
|
|
11
11
|
const root = path.parse(dir).root;
|
|
12
12
|
for (; dir !== root; dir = path.dirname(dir)) {
|
|
@@ -30,6 +30,8 @@ export async function findHerebyfile(dir) {
|
|
|
30
30
|
throw new UserError("Unable to find Herebyfile.");
|
|
31
31
|
}
|
|
32
32
|
export async function loadHerebyfile(herebyfilePath) {
|
|
33
|
+
// Note: calling pathToFileURL is required on Windows to disambiguate URLs
|
|
34
|
+
// from drive letters.
|
|
33
35
|
const herebyfile = await import(pathToFileURL(herebyfilePath).toString());
|
|
34
36
|
const exportedTasks = new Set();
|
|
35
37
|
let defaultTask;
|
|
@@ -52,7 +54,7 @@ export async function loadHerebyfile(herebyfilePath) {
|
|
|
52
54
|
if (exportedTasks.size === 0) {
|
|
53
55
|
throw new UserError("No tasks found. Did you forget to export your tasks?");
|
|
54
56
|
}
|
|
55
|
-
const tasks =
|
|
57
|
+
const tasks = [...exportedTasks.values()];
|
|
56
58
|
// We check this here by walking the DAG, as some dependencies may not be
|
|
57
59
|
// exported and therefore would not be seen by the above loop.
|
|
58
60
|
checkTaskInvariants(tasks);
|
package/dist/cli/parseArgs.js
CHANGED
|
@@ -1,26 +1,22 @@
|
|
|
1
|
-
import commandLineArgs from "command-line-args";
|
|
2
1
|
import commandLineUsage from "command-line-usage";
|
|
2
|
+
import minimist from "minimist";
|
|
3
3
|
export function parseArgs(argv) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
{ name: "version", type: Boolean },
|
|
15
|
-
], {
|
|
16
|
-
argv,
|
|
17
|
-
stopAtFirstUnknown: true,
|
|
4
|
+
let parseUnknownAsTask = true;
|
|
5
|
+
const options = minimist(argv, {
|
|
6
|
+
"--": true,
|
|
7
|
+
string: ["herebyfile"],
|
|
8
|
+
boolean: ["tasks", "tasks-simple", "help", "version"],
|
|
9
|
+
alias: {
|
|
10
|
+
"h": "help",
|
|
11
|
+
"T": "tasks",
|
|
12
|
+
},
|
|
13
|
+
unknown: (name) => parseUnknownAsTask && (parseUnknownAsTask = !name.startsWith("-")),
|
|
18
14
|
});
|
|
19
15
|
return {
|
|
20
16
|
help: options["help"],
|
|
21
|
-
run: options["
|
|
17
|
+
run: options["_"],
|
|
22
18
|
herebyfile: options["herebyfile"],
|
|
23
|
-
printTasks: options["tasks"] ? "normal" : options["tasks-simple"] ? "simple" : undefined,
|
|
19
|
+
printTasks: options["tasks"] ? "normal" : (options["tasks-simple"] ? "simple" : undefined),
|
|
24
20
|
version: options["version"],
|
|
25
21
|
};
|
|
26
22
|
}
|
package/dist/cli/reexec.js
CHANGED
package/dist/cli/runner.js
CHANGED
package/dist/cli/utils.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import os from "os";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import { fileURLToPath } from "url";
|
|
5
|
-
export function
|
|
6
|
-
return
|
|
7
|
-
}
|
|
8
|
-
export function stringSorter(a, b) {
|
|
9
|
-
return a.localeCompare(b);
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
export function compareTaskNames(a, b) {
|
|
6
|
+
return compareStrings(a.options.name, b.options.name);
|
|
10
7
|
}
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
9
|
+
export const compareStrings = new Intl.Collator(undefined, { numeric: true }).compare;
|
|
11
10
|
// Exported for testing.
|
|
12
11
|
export function simplifyPath(p) {
|
|
13
12
|
let homedir = os.homedir();
|
|
@@ -59,7 +58,7 @@ export async function real() {
|
|
|
59
58
|
// Not bothering to memoize this function; it will only be called once.
|
|
60
59
|
const resolve = await importResolve();
|
|
61
60
|
const packageJsonPath = fileURLToPath(await resolve("hereby/package.json", import.meta.url));
|
|
62
|
-
const packageJson = await fs.promises.readFile(packageJsonPath, "
|
|
61
|
+
const packageJson = await fs.promises.readFile(packageJsonPath, "utf8");
|
|
63
62
|
const { version } = JSON.parse(packageJson);
|
|
64
63
|
return version;
|
|
65
64
|
},
|
package/dist/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export interface TaskOptions {
|
|
|
11
11
|
*/
|
|
12
12
|
description?: string | undefined;
|
|
13
13
|
/**
|
|
14
|
-
* A list of tasks that must
|
|
14
|
+
* A list of tasks that must have been run to completion before
|
|
15
15
|
* this task can execute.
|
|
16
16
|
*/
|
|
17
17
|
dependencies?: readonly Task[] | undefined;
|
package/dist/index.js
CHANGED
|
@@ -15,23 +15,23 @@ export class Task {
|
|
|
15
15
|
// typechecking, so this is helpful.
|
|
16
16
|
var _a;
|
|
17
17
|
if (typeof options.name !== "string") {
|
|
18
|
-
throw new
|
|
18
|
+
throw new TypeError("Task name is not a string.");
|
|
19
19
|
}
|
|
20
|
-
if (typeof options.description !== "string" &&
|
|
21
|
-
throw new
|
|
20
|
+
if (typeof options.description !== "string" && options.description !== undefined) {
|
|
21
|
+
throw new TypeError("Task description is not a string or undefined.");
|
|
22
22
|
}
|
|
23
|
-
if (!Array.isArray(options.dependencies) &&
|
|
24
|
-
throw new
|
|
23
|
+
if (!Array.isArray(options.dependencies) && options.dependencies !== undefined) {
|
|
24
|
+
throw new TypeError("Task dependencies is not an array or undefined.");
|
|
25
25
|
}
|
|
26
26
|
if (options.dependencies) {
|
|
27
27
|
for (const dep of options.dependencies) {
|
|
28
28
|
if (!(dep instanceof Task)) {
|
|
29
|
-
throw new
|
|
29
|
+
throw new TypeError("Task dependency is not a task.");
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
-
if (typeof options.run !== "function" &&
|
|
34
|
-
throw new
|
|
33
|
+
if (typeof options.run !== "function" && options.run !== undefined) {
|
|
34
|
+
throw new TypeError("Task run is not a function or undefined.");
|
|
35
35
|
}
|
|
36
36
|
// Non-type checks.
|
|
37
37
|
if (!options.name) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hereby",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "A simple task runner",
|
|
5
5
|
"repository": "github:jakebailey/hereby",
|
|
6
6
|
"type": "module",
|
|
@@ -38,18 +38,18 @@
|
|
|
38
38
|
"./dist/index.d.ts"
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"command-line-args": "^5.2.1",
|
|
42
41
|
"command-line-usage": "^6.1.3",
|
|
43
42
|
"fastest-levenshtein": "^1.0.16",
|
|
44
43
|
"import-meta-resolve": "^2.2.1",
|
|
44
|
+
"minimist": "^1.2.7",
|
|
45
45
|
"picocolors": "^1.0.0",
|
|
46
46
|
"pretty-ms": "^8.0.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@ava/typescript": "^3.0.1",
|
|
50
50
|
"@tsconfig/node12": "^1.0.11",
|
|
51
|
-
"@types/command-line-args": "^5.2.0",
|
|
52
51
|
"@types/command-line-usage": "^5.0.2",
|
|
52
|
+
"@types/minimist": "^1.2.2",
|
|
53
53
|
"@types/node": "^14.18.36",
|
|
54
54
|
"@types/tmp": "^0.2.3",
|
|
55
55
|
"@typescript-eslint/eslint-plugin": "^5.48.2",
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
"eslint": "^8.32.0",
|
|
61
61
|
"eslint-plugin-ava": "^14.0.0",
|
|
62
62
|
"eslint-plugin-simple-import-sort": "^9.0.0",
|
|
63
|
+
"eslint-plugin-unicorn": "^45.0.2",
|
|
63
64
|
"execa": "^6.1.0",
|
|
64
65
|
"moq.ts": "^9.0.2",
|
|
65
66
|
"rimraf": "^4.1.1",
|