hereby 1.8.5 → 1.8.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import commandLineUsage from "command-line-usage";
2
2
  import pc from "picocolors";
3
- import { compareStrings, compareTaskNames } from "./utils.js";
3
+ import { compareTaskNames } from "./utils.js";
4
4
  export function formatTasks(format, tasks, defaultTask) {
5
5
  tasks = tasks.filter(isTaskVisible).sort(compareTaskNames);
6
6
  if (format === "simple") {
@@ -13,16 +13,10 @@ export function formatTasks(format, tasks, defaultTask) {
13
13
  const name = task === defaultTask
14
14
  ? `${pc.green(task.options.name)} (default)`
15
15
  : pc.blue(task.options.name);
16
- let descriptionParts;
17
- if (task.options.description) {
18
- descriptionParts = [task.options.description];
19
- }
20
- const deps = (_a = task.options.dependencies) === null || _a === void 0 ? void 0 : _a.filter(isTaskVisible);
21
- if (deps && deps.length > 0) {
22
- const depNames = deps
23
- .map((task) => task.options.name)
24
- .sort(compareStrings)
25
- .map((v) => pc.blue(v));
16
+ let descriptionParts = task.options.description ? [task.options.description] : undefined;
17
+ const deps = (_a = task.options.dependencies) === null || _a === void 0 ? void 0 : _a.filter(isTaskVisible).sort(compareTaskNames);
18
+ if (deps === null || deps === void 0 ? void 0 : deps.length) {
19
+ const depNames = deps.map((task) => pc.blue(task.options.name));
26
20
  (descriptionParts !== null && descriptionParts !== void 0 ? descriptionParts : (descriptionParts = [])).push(`Depends on: ${depNames.join(", ")}`);
27
21
  }
28
22
  return { name, description: descriptionParts === null || descriptionParts === void 0 ? void 0 : descriptionParts.join("\n") };
package/dist/cli/index.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import path from "node:path";
2
+ import util from "node:util";
2
3
  import pc from "picocolors";
3
4
  import { formatTasks } from "./formatTasks.js";
4
5
  import { findHerebyfile, loadHerebyfile } from "./loadHerebyfile.js";
5
6
  import { getUsage, parseArgs } from "./parseArgs.js";
6
7
  import { reexec } from "./reexec.js";
7
8
  import { Runner } from "./runner.js";
8
- import { compareTaskNames, ExitCodeError, UserError } from "./utils.js";
9
+ import { ExitCodeError, UserError } from "./utils.js";
9
10
  export async function main(d) {
10
11
  try {
11
12
  await mainWorker(d);
@@ -13,14 +14,18 @@ export async function main(d) {
13
14
  catch (e) {
14
15
  if (e instanceof ExitCodeError) {
15
16
  d.setExitCode(e.exitCode);
17
+ return;
16
18
  }
17
- else if (e instanceof UserError) {
19
+ if (e instanceof UserError) {
18
20
  d.error(`${pc.red("Error")}: ${e.message}`);
19
- d.setExitCode(1);
21
+ }
22
+ else if (util.types.isNativeError(e) && e.stack) {
23
+ d.error(e.stack);
20
24
  }
21
25
  else {
22
- throw e;
26
+ d.error(`${e}`);
23
27
  }
28
+ d.setExitCode(1);
24
29
  }
25
30
  }
26
31
  async function mainWorker(d) {
@@ -68,30 +73,27 @@ async function mainWorker(d) {
68
73
  }
69
74
  // Exported for testing.
70
75
  export async function selectTasks(d, herebyfile, herebyfilePath, taskNames) {
71
- const allTasks = new Map();
72
- for (const task of herebyfile.tasks) {
73
- allTasks.set(task.options.name, task);
76
+ if (taskNames.length === 0) {
77
+ if (!herebyfile.defaultTask) {
78
+ throw new UserError(`No default task has been exported from ${d.simplifyPath(herebyfilePath)}; please specify a task name.`);
79
+ }
80
+ return [herebyfile.defaultTask];
74
81
  }
75
- if (taskNames.length > 0) {
76
- const tasks = [];
77
- for (const name of taskNames) {
78
- const task = allTasks.get(name);
79
- if (!task) {
80
- let message = `Task "${name}" does not exist or is not exported from ${d.simplifyPath(herebyfilePath)}.`;
81
- const { closest, distance } = await import("fastest-levenshtein");
82
- const candidate = closest(name, [...allTasks.keys()]);
83
- if (distance(name, candidate) < name.length * 0.4) {
84
- message += ` Did you mean "${candidate}"?`;
85
- }
86
- throw new UserError(message);
82
+ const allTasks = new Map(herebyfile.tasks.map((task) => [task.options.name, task]));
83
+ const tasks = [];
84
+ for (const name of taskNames) {
85
+ const task = allTasks.get(name);
86
+ if (!task) {
87
+ let message = `Task "${name}" does not exist or is not exported from ${d.simplifyPath(herebyfilePath)}.`;
88
+ const { closest, distance } = await import("fastest-levenshtein");
89
+ const candidate = closest(name, [...allTasks.keys()]);
90
+ if (distance(name, candidate) < name.length * 0.4) {
91
+ message += ` Did you mean "${candidate}"?`;
87
92
  }
88
- tasks.push(task);
93
+ throw new UserError(message);
89
94
  }
90
- return tasks.sort(compareTaskNames);
91
- }
92
- if (!herebyfile.defaultTask) {
93
- throw new UserError(`No default task has been exported from ${d.simplifyPath(herebyfilePath)}; please specify a task name.`);
95
+ tasks.push(task);
94
96
  }
95
- return [herebyfile.defaultTask];
97
+ return tasks;
96
98
  }
97
99
  //# sourceMappingURL=index.js.map
@@ -4,14 +4,15 @@ import { pathToFileURL } from "node:url";
4
4
  import pc from "picocolors";
5
5
  import { Task } from "../index.js";
6
6
  import { UserError } from "./utils.js";
7
- const filenames = ["Herebyfile", "herebyfile"];
8
- const extensions = ["mjs", "js"];
9
- const allFilenames = new Set(extensions.flatMap((e) => filenames.map((f) => `${f}.${e}`)));
7
+ function isHerebyfile(p) {
8
+ p = p.toLowerCase();
9
+ return p === "herebyfile.mjs" || p === "herebyfile.js";
10
+ }
10
11
  export async function findHerebyfile(dir) {
11
12
  const root = path.parse(dir).root;
12
13
  for (; dir !== root; dir = path.dirname(dir)) {
13
14
  const entries = await fs.promises.readdir(dir);
14
- const matching = entries.filter((e) => allFilenames.has(e));
15
+ const matching = entries.filter(isHerebyfile);
15
16
  if (matching.length > 1) {
16
17
  throw new UserError(`Found more than one Herebyfile: ${matching.join(", ")}`);
17
18
  }
@@ -15,15 +15,6 @@ export async function reexec(d, herebyfilePath) {
15
15
  // Rather than trying to fix this by messing around with Node's resolution
16
16
  // (which won't work in ESM anyway), instead opt to figure out the location
17
17
  // of hereby as imported by the Herebyfile, and then "reexec" it by importing.
18
- if (d.isPnP) {
19
- // When we are running within PnP, we can't really figure out what to
20
- // do. import-meta-resolve doesn't implement this, so we can't do
21
- // anything until import.meta.resolve is no longer experimental.
22
- //
23
- // Just assume that everything is okay; we will error later if there's
24
- // a mismatch.
25
- return false;
26
- }
27
18
  const thisCLI = await d.resolve(cliExportName, import.meta.url);
28
19
  let otherCLI;
29
20
  try {
@@ -1,11 +1,10 @@
1
- import assert from "node:assert";
2
1
  import pc from "picocolors";
3
2
  export class Runner {
4
- constructor(d) {
3
+ constructor(_d) {
4
+ this._d = _d;
5
5
  this._addedTasks = new Map();
6
6
  this._errored = false;
7
7
  this._startTimes = new Map();
8
- this._d = d;
9
8
  }
10
9
  async runTasks(...tasks) {
11
10
  // Using allSettled here so that we don't immediately exit; it could be
@@ -55,7 +54,7 @@ export class Runner {
55
54
  if (this._errored) {
56
55
  return; // Skip logging.
57
56
  }
58
- const took = Date.now() - checkDefined(this._startTimes.get(task));
57
+ const took = Date.now() - this._startTimes.get(task);
59
58
  this._d.log(`Finished ${pc.green(task.options.name)} in ${this._d.prettyMilliseconds(took)}`);
60
59
  }
61
60
  onTaskError(task, e) {
@@ -63,12 +62,8 @@ export class Runner {
63
62
  return; // Skip logging.
64
63
  }
65
64
  this._errored = true;
66
- const took = Date.now() - checkDefined(this._startTimes.get(task));
65
+ const took = Date.now() - this._startTimes.get(task);
67
66
  this._d.error(`Error in ${pc.red(task.options.name)} in ${this._d.prettyMilliseconds(took)}\n${e}`);
68
67
  }
69
68
  }
70
- function checkDefined(value) {
71
- assert(value !== undefined);
72
- return value;
73
- }
74
69
  //# sourceMappingURL=runner.js.map
package/dist/cli/utils.js CHANGED
@@ -6,13 +6,11 @@ export function compareTaskNames(a, b) {
6
6
  return compareStrings(a.options.name, b.options.name);
7
7
  }
8
8
  // eslint-disable-next-line @typescript-eslint/unbound-method
9
- export const compareStrings = new Intl.Collator(undefined, { numeric: true }).compare;
9
+ const compareStrings = new Intl.Collator(undefined, { numeric: true }).compare;
10
10
  // Exported for testing.
11
11
  export function simplifyPath(p) {
12
- let homedir = os.homedir();
13
- if (!p.endsWith(path.sep)) {
14
- homedir += path.sep;
15
- }
12
+ p = path.normalize(p);
13
+ const homedir = path.normalize(os.homedir() + path.sep);
16
14
  if (p.startsWith(homedir)) {
17
15
  p = p.slice(homedir.length);
18
16
  return `~${path.sep}${p}`;
@@ -24,9 +22,6 @@ export function simplifyPath(p) {
24
22
  * as a message only, without stacktrace. Use this instead of process.exit.
25
23
  */
26
24
  export class UserError extends Error {
27
- constructor(message) {
28
- super(message);
29
- }
30
25
  }
31
26
  /**
32
27
  * When thrown, ExitCodeError causes the process to exit with a specific error code,
@@ -39,7 +34,6 @@ export class ExitCodeError {
39
34
  }
40
35
  }
41
36
  export async function real() {
42
- const importResolve = memoize(async () => (await import("import-meta-resolve")).resolve);
43
37
  const { default: prettyMilliseconds } = await import("pretty-ms");
44
38
  /* eslint-disable no-restricted-globals */
45
39
  return {
@@ -55,24 +49,18 @@ export async function real() {
55
49
  process.exitCode = code;
56
50
  },
57
51
  version: async () => {
58
- // Not bothering to memoize this function; it will only be called once.
59
- const resolve = await importResolve();
52
+ const { resolve } = await import("import-meta-resolve");
60
53
  const packageJsonPath = fileURLToPath(await resolve("hereby/package.json", import.meta.url));
61
54
  const packageJson = await fs.promises.readFile(packageJsonPath, "utf8");
62
55
  const { version } = JSON.parse(packageJson);
63
56
  return version;
64
57
  },
65
- isPnP: !!process.versions["pnp"],
66
58
  resolve: async (specifier, parent) => {
67
- const resolve = await importResolve();
59
+ const { resolve } = await import("import-meta-resolve");
68
60
  return resolve(specifier, parent);
69
61
  },
70
62
  prettyMilliseconds,
71
63
  };
72
64
  /* eslint-enable no-restricted-globals */
73
65
  }
74
- function memoize(fn) {
75
- let value;
76
- return () => (value !== null && value !== void 0 ? value : (value = fn()));
77
- }
78
66
  //# sourceMappingURL=utils.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hereby",
3
- "version": "1.8.5",
3
+ "version": "1.8.7",
4
4
  "description": "A simple task runner",
5
5
  "repository": "github:jakebailey/hereby",
6
6
  "type": "module",
@@ -30,6 +30,7 @@
30
30
  "engines": {
31
31
  "node": ">= 12.20"
32
32
  },
33
+ "preferUnplugged": true,
33
34
  "files": [
34
35
  "README.md",
35
36
  "LICENSE",
@@ -50,14 +51,14 @@
50
51
  "@tsconfig/node12": "^12.1.0",
51
52
  "@types/command-line-usage": "^5.0.2",
52
53
  "@types/minimist": "^1.2.2",
53
- "@types/node": "^14.18.54",
54
+ "@types/node": "^20.5.9",
54
55
  "@types/tmp": "^0.2.3",
55
- "@typescript-eslint/eslint-plugin": "^6.2.1",
56
- "@typescript-eslint/parser": "^6.2.1",
56
+ "@typescript-eslint/eslint-plugin": "^6.6.0",
57
+ "@typescript-eslint/parser": "^6.6.0",
57
58
  "ava": "~5.0.1",
58
59
  "c8": "^8.0.1",
59
60
  "dprint": "^0.40.2",
60
- "eslint": "^8.46.0",
61
+ "eslint": "^8.48.0",
61
62
  "eslint-plugin-ava": "^14.0.0",
62
63
  "eslint-plugin-simple-import-sort": "^10.0.0",
63
64
  "eslint-plugin-unicorn": "^48.0.1",
@@ -65,7 +66,7 @@
65
66
  "moq.ts": "^10.0.6",
66
67
  "rimraf": "^5.0.1",
67
68
  "tmp": "^0.2.1",
68
- "typescript": "^5.1.6"
69
+ "typescript": "^5.2.2"
69
70
  },
70
71
  "overrides": {
71
72
  "ava": {