hereby 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Jake Bailey
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # hereby
2
+
3
+ `hereby` is a simple task runner.
4
+
5
+ # Herebyfile.mjs
6
+
7
+ Tasks are defined in `Herebyfile.mjs`, like:
8
+
9
+ ```js
10
+ import { execa } from "execa";
11
+ import { task } from "hereby";
12
+
13
+ export const build = task({
14
+ name: "build",
15
+ run: async () => {
16
+ await execa("tsc", ["-b", "./src"]);
17
+ },
18
+ });
19
+
20
+ export const test = task({
21
+ name: "test",
22
+ dependencies: [build],
23
+ run: async () => {
24
+ await execa("node", ["./out/test.js"]);
25
+ },
26
+ });
27
+
28
+ export const lint = task({
29
+ name: "lint",
30
+ run: async () => {
31
+ await runLinter(...);
32
+ },
33
+ })
34
+
35
+ export const testAndLint = task({
36
+ name: "testAndLint",
37
+ dependencies: [test, lint],
38
+ })
39
+
40
+ export default testAndLint;
41
+ ```
42
+
43
+ # Running tasks
44
+
45
+ Given the above Herebyfile:
46
+
47
+ ```
48
+ $ hereby build # Run only build
49
+ $ hereby test # Run test, which depends on build.
50
+ $ hereby # Run the default exported task.
51
+ ```
52
+
53
+ # Flags
54
+
55
+ `hereby` also supports a handful of flags:
56
+
57
+ ```
58
+ -h, --help Display this usage guide.
59
+ --herebyfile path A path to a Herebyfile. Optional.
60
+ -T, --tasks Print a listing of the available tasks.
61
+ ```
62
+
63
+ # ESM
64
+
65
+ `hereby` is implemented in ES modules. But, don't fret! This does not mean
66
+ that your project must be ESM-only, only that your `Herebyfile` must be ESM
67
+ module so that `hereby`'s `task` function can be imported. It's recommended
68
+ to use the filename `Herebyfile.mjs` to ensure that it is treated as ESM. This
69
+ will work in a CommonJS project; ES modules can import CommonJS modules.
70
+
71
+ If your package already sets `"type": "module"`, `Herebyfile.js` will work
72
+ as well.
@@ -0,0 +1,28 @@
1
+ import chalk from "chalk";
2
+ import commandLineUsage from "command-line-usage";
3
+ import { stringSorter, taskSorter } from "./utils.js";
4
+ export function formatTasks(tasks, defaultTask) {
5
+ tasks = tasks.slice(0).sort(taskSorter);
6
+ const sections = [];
7
+ sections.push({
8
+ header: "Available tasks",
9
+ content: tasks.map((task) => {
10
+ const blueName = chalk.blue(task.options.name);
11
+ const name = task !== defaultTask ? blueName : `${blueName} (default)`;
12
+ const descriptionParts = [];
13
+ if (task.options.description) {
14
+ descriptionParts.push(task.options.description);
15
+ }
16
+ if (task.options.dependencies && task.options.dependencies.length > 0) {
17
+ const deps = task.options.dependencies
18
+ .map((task) => task.options.name)
19
+ .sort(stringSorter)
20
+ .map((v) => chalk.blue(v));
21
+ descriptionParts.push(`Depends on: ${deps.join(", ")}`);
22
+ }
23
+ return { name, description: descriptionParts.join("\n") };
24
+ }),
25
+ });
26
+ return commandLineUsage(sections);
27
+ }
28
+ //# sourceMappingURL=formatTasks.js.map
@@ -0,0 +1,74 @@
1
+ import chalk from "chalk";
2
+ import path from "path";
3
+ import { formatTasks } from "./formatTasks.js";
4
+ import { findHerebyfile, loadHerebyfile } from "./loadHerebyfile.js";
5
+ import { getUsage, parseArgs } from "./parseArgs.js";
6
+ import { reexec } from "./reexec.js";
7
+ import { runTasksWithCLIRunner } from "./runner.js";
8
+ import { ExitCodeError, simplifyPath, UserError } from "./utils.js";
9
+ export async function main(system) {
10
+ try {
11
+ await mainWorker(system);
12
+ }
13
+ catch (e) {
14
+ if (e instanceof ExitCodeError) {
15
+ system.process.exitCode = e.exitCode;
16
+ }
17
+ else if (e instanceof UserError) {
18
+ system.error(`${chalk.red("Error")}: ${e.message}`);
19
+ system.process.exitCode = 1;
20
+ }
21
+ else {
22
+ throw e;
23
+ }
24
+ }
25
+ }
26
+ async function mainWorker(system) {
27
+ const args = parseArgs(system.process.argv.slice(2));
28
+ if (args.help) {
29
+ system.log(getUsage());
30
+ return;
31
+ }
32
+ let herebyfilePath = args.herebyfile ?? (await findHerebyfile(system.process.cwd()));
33
+ herebyfilePath = path.resolve(system.process.cwd(), herebyfilePath);
34
+ if (await reexec(system, herebyfilePath)) {
35
+ return;
36
+ }
37
+ system.process.chdir(path.dirname(herebyfilePath));
38
+ const herebyfile = await loadHerebyfile(herebyfilePath);
39
+ if (args.printTasks) {
40
+ system.log(formatTasks(herebyfile.tasks, herebyfile.defaultTask));
41
+ return;
42
+ }
43
+ const allTasks = new Map();
44
+ for (const task of herebyfile.tasks) {
45
+ allTasks.set(task.options.name, task);
46
+ }
47
+ let tasks;
48
+ if (args.run && args.run.length > 0) {
49
+ tasks = args.run.map((name) => {
50
+ const task = allTasks.get(name);
51
+ if (!task) {
52
+ throw new UserError(`Task ${name} does not exist or is not exported in the Herebyfile.`);
53
+ }
54
+ return task;
55
+ });
56
+ }
57
+ else {
58
+ if (!herebyfile.defaultTask) {
59
+ throw new UserError("No default task defined; please specify a task name.");
60
+ }
61
+ tasks = [herebyfile.defaultTask];
62
+ }
63
+ system.log(`Using ${simplifyPath(herebyfilePath)}`);
64
+ try {
65
+ await runTasksWithCLIRunner(system, ...tasks);
66
+ }
67
+ catch {
68
+ // We will have already printed some message here.
69
+ // Set the error code and let the process run to completion,
70
+ // so we don't end up with an unflushed output.
71
+ throw new ExitCodeError(1);
72
+ }
73
+ }
74
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,74 @@
1
+ import chalk from "chalk";
2
+ import fs from "fs/promises";
3
+ import path from "path";
4
+ import { Task } from "../index.js";
5
+ import { forEachTask } from "../utils.js";
6
+ import { UserError } from "./utils.js";
7
+ const filenames = ["Herebyfile", "herebyfile"];
8
+ const extensions = ["mjs", "js"];
9
+ const allFilenames = new Set(extensions.map((e) => filenames.map((f) => `${f}.${e}`)).flat());
10
+ export async function findHerebyfile(dir) {
11
+ const root = path.parse(dir).root;
12
+ for (; dir !== root; dir = path.dirname(dir)) {
13
+ const entries = await fs.readdir(dir);
14
+ const matching = entries.filter((e) => allFilenames.has(e));
15
+ if (matching.length > 1) {
16
+ throw new UserError(`Found more than one Herebyfile: ${matching.join(", ")}`);
17
+ }
18
+ if (matching.length === 1) {
19
+ const candidate = path.join(dir, matching[0]);
20
+ const stat = await fs.stat(candidate);
21
+ if (!stat.isFile()) {
22
+ throw new UserError(`${matching[0]} is not a file.`);
23
+ }
24
+ return candidate;
25
+ }
26
+ if (entries.includes("package.json")) {
27
+ break;
28
+ }
29
+ }
30
+ throw new UserError("Unable to find Herebyfile.");
31
+ }
32
+ export async function loadHerebyfile(herebyfilePath) {
33
+ const herebyfile = await import(herebyfilePath);
34
+ const exportedTasks = new Set();
35
+ let defaultTask;
36
+ for (const [key, value] of Object.entries(herebyfile)) {
37
+ if (value instanceof Task) {
38
+ if (key === "default") {
39
+ defaultTask = value;
40
+ }
41
+ else if (exportedTasks.has(value)) {
42
+ throw new UserError(`Task "${chalk.blue(value.options.name)}" has been exported twice.`);
43
+ }
44
+ else {
45
+ exportedTasks.add(value);
46
+ }
47
+ }
48
+ }
49
+ if (defaultTask) {
50
+ exportedTasks.add(defaultTask);
51
+ }
52
+ if (exportedTasks.size === 0) {
53
+ throw new UserError("No tasks found. Did you forget to export your tasks?");
54
+ }
55
+ const tasks = Array.from(exportedTasks.values());
56
+ // We check this here by walking the DAG, as some dependencies may not be
57
+ // exported and therefore would not be seen by the above loop.
58
+ assertUniqueNames(tasks);
59
+ return {
60
+ tasks,
61
+ defaultTask,
62
+ };
63
+ }
64
+ function assertUniqueNames(tasks) {
65
+ const names = new Set();
66
+ forEachTask(tasks, (task) => {
67
+ const name = task.options.name;
68
+ if (names.has(name)) {
69
+ throw new UserError(`Task "${chalk.blue(name)}" was declared twice.`);
70
+ }
71
+ names.add(name);
72
+ });
73
+ }
74
+ //# sourceMappingURL=loadHerebyfile.js.map
@@ -0,0 +1,70 @@
1
+ import commandLineArgs from "command-line-args";
2
+ import commandLineUsage from "command-line-usage";
3
+ export function parseArgs(argv) {
4
+ const idx = argv.indexOf("--");
5
+ if (idx !== -1) {
6
+ argv = argv.slice(0, idx);
7
+ }
8
+ const options = commandLineArgs([
9
+ { name: "run", multiple: true, defaultOption: true, type: String },
10
+ { name: "herebyfile", type: String },
11
+ { name: "tasks", alias: "T", type: Boolean },
12
+ { name: "help", alias: "h", type: Boolean },
13
+ ], {
14
+ argv,
15
+ stopAtFirstUnknown: true,
16
+ });
17
+ return {
18
+ help: options["help"],
19
+ run: options["run"],
20
+ herebyfile: options["herebyfile"],
21
+ printTasks: options["tasks"],
22
+ };
23
+ }
24
+ export function getUsage() {
25
+ const usage = commandLineUsage([
26
+ {
27
+ header: "hereby",
28
+ content: "A simple task runner.",
29
+ },
30
+ {
31
+ header: "Synopsis",
32
+ content: "$ hereby <task>",
33
+ },
34
+ {
35
+ header: "Options",
36
+ optionList: [
37
+ {
38
+ name: "help",
39
+ description: "Display this usage guide.",
40
+ alias: "h",
41
+ type: Boolean,
42
+ },
43
+ {
44
+ name: "herebyfile",
45
+ description: "A path to a Herebyfile. Optional.",
46
+ type: String,
47
+ defaultOption: true,
48
+ typeLabel: "{underline path}",
49
+ },
50
+ {
51
+ name: "tasks",
52
+ description: "Print a listing of the available tasks.",
53
+ alias: "T",
54
+ type: Boolean,
55
+ },
56
+ ],
57
+ },
58
+ {
59
+ header: "Example usage",
60
+ content: [
61
+ "$ hereby build",
62
+ "$ hereby build lint",
63
+ "$ hereby test --skip someTest --lint=false",
64
+ "$ hereby --tasks",
65
+ ],
66
+ },
67
+ ]);
68
+ return usage;
69
+ }
70
+ //# sourceMappingURL=parseArgs.js.map
@@ -0,0 +1,31 @@
1
+ import chalk from "chalk";
2
+ import foregroundChild from "foreground-child";
3
+ import { resolve } from "import-meta-resolve";
4
+ import { fileURLToPath, pathToFileURL } from "url";
5
+ export async function reexec(system, herebyfilePath) {
6
+ // If hereby is installed globally, but run against a Herebyfile in some
7
+ // other package, that Herebyfile's import will resolve to a different
8
+ // installation of the hereby package. There's no guarantee that the two
9
+ // are compatible (in fact, are guaranteed not to be as Task is a class).
10
+ //
11
+ // Rather than trying to fix this by messing around with Node's resolution
12
+ // (which won't work in ESM anyway), instead opt to figure out the location
13
+ // of hereby as imported by the Herebyfile, and fork to execute it instead.
14
+ //
15
+ // TODO: Rather than spawning a child process, perhaps we could instead
16
+ // import the CLI from the other version and run it.
17
+ const thisCLI = await resolveToPath("hereby/cli", new URL(import.meta.url));
18
+ const otherCLI = await resolveToPath("hereby/cli", pathToFileURL(herebyfilePath));
19
+ if (thisCLI === otherCLI) {
20
+ return false;
21
+ }
22
+ // TODO: If this turns out to be common, remove this warning.
23
+ system.error(`${chalk.yellow("Warning")}: re-running hereby as imported by the Herebyfile.`);
24
+ const args = [...system.process.execArgv, otherCLI, ...system.process.argv.slice(2)];
25
+ foregroundChild(system.process.execPath, args);
26
+ return true;
27
+ }
28
+ async function resolveToPath(specifier, url) {
29
+ return fileURLToPath(new URL(await resolve(specifier, url.toString())));
30
+ }
31
+ //# sourceMappingURL=reexec.js.map
@@ -0,0 +1,42 @@
1
+ import assert from "assert";
2
+ import chalk from "chalk";
3
+ import prettyMilliseconds from "pretty-ms";
4
+ import { Runner } from "../runner.js";
5
+ export function runTasksWithCLIRunner(system, ...tasks) {
6
+ return new CLIRunner({ system, concurrency: system.numCPUs }).runTasks(...tasks);
7
+ }
8
+ class CLIRunner extends Runner {
9
+ constructor(options) {
10
+ super(options);
11
+ this._errored = false;
12
+ this._startTimes = new WeakMap();
13
+ this._system = options.system;
14
+ }
15
+ onTaskStart(task) {
16
+ this._startTimes.set(task, Date.now());
17
+ if (this._errored) {
18
+ return; // Skip logging.
19
+ }
20
+ this._system.log(`Starting ${chalk.blue(task.options.name)}`);
21
+ }
22
+ onTaskFinish(task) {
23
+ if (this._errored) {
24
+ return; // Skip logging.
25
+ }
26
+ const took = Date.now() - checkDefined(this._startTimes.get(task));
27
+ this._system.log(`Finished ${chalk.green(task.options.name)} in ${prettyMilliseconds(took)}`);
28
+ }
29
+ onTaskError(task, e) {
30
+ if (this._errored) {
31
+ return; // Skip logging.
32
+ }
33
+ this._errored = true;
34
+ this._system.error(`Error in ${chalk.red(task.options.name)}`);
35
+ this._system.error(`${e}`);
36
+ }
37
+ }
38
+ function checkDefined(value) {
39
+ assert(value);
40
+ return value;
41
+ }
42
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1,50 @@
1
+ import os from "os";
2
+ import path from "path";
3
+ export function taskSorter(a, b) {
4
+ return stringSorter(a.options.name, b.options.name);
5
+ }
6
+ export function stringSorter(a, b) {
7
+ return a.localeCompare(b);
8
+ }
9
+ export function simplifyPath(p) {
10
+ let homedir = os.homedir();
11
+ if (!p.endsWith(path.sep)) {
12
+ homedir += path.sep;
13
+ }
14
+ if (p.startsWith(homedir)) {
15
+ p = p.slice(homedir.length);
16
+ return `~${path.sep}${p}`;
17
+ }
18
+ return p;
19
+ }
20
+ /**
21
+ * UserError is a special error that, when caught in the CLI will be printed
22
+ * as a message only, without stacktrace. Use this instead of process.exit.
23
+ */
24
+ export class UserError extends Error {
25
+ constructor(message) {
26
+ super(message);
27
+ }
28
+ }
29
+ /**
30
+ * When thrown, ExitCodeError causes the process to exit with a specific error code,
31
+ * without logging anything.
32
+ */
33
+ export class ExitCodeError {
34
+ constructor(exitCode) {
35
+ this.exitCode = exitCode;
36
+ }
37
+ }
38
+ export function createSystem(process) {
39
+ return {
40
+ log(message) {
41
+ process.stdout.write(message + "\n");
42
+ },
43
+ error(message) {
44
+ process.stderr.write(message + "\n");
45
+ },
46
+ process,
47
+ numCPUs: os.cpus().length,
48
+ };
49
+ }
50
+ //# sourceMappingURL=utils.js.map
package/dist/cli.js ADDED
@@ -0,0 +1,5 @@
1
+ import { main } from "./cli/index.js";
2
+ import { createSystem } from "./cli/utils.js";
3
+ // eslint-disable-next-line no-restricted-globals
4
+ await main(createSystem(process));
5
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1,32 @@
1
+ export interface TaskOptions {
2
+ /**
3
+ * The name of the task, as referenced in logs and the CLI.
4
+ *
5
+ * This name must not start with a "-" in order to prevent conflicts
6
+ * with flags.
7
+ */
8
+ name: string;
9
+ /**
10
+ * A description of the task, for display in the CLI.
11
+ */
12
+ description?: string | undefined;
13
+ /**
14
+ * A list of tasks that must has been run to completion before
15
+ * this task can execute.
16
+ */
17
+ dependencies?: Task[] | undefined;
18
+ /**
19
+ * A function to execute when this task is run.
20
+ */
21
+ run?: (() => void | Promise<void>) | undefined;
22
+ }
23
+ /**
24
+ * A hereby Task. To get an instance, call `test`.
25
+ */
26
+ export declare class Task {
27
+ private constructor();
28
+ }
29
+ /**
30
+ * Creates a new Task.
31
+ */
32
+ export declare function task(options: TaskOptions): Task;
package/dist/index.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * A hereby Task. To get an instance, call `test`.
3
+ */
4
+ export class Task {
5
+ constructor(options) {
6
+ if (!options.name) {
7
+ throw new Error("Task name must not be empty.");
8
+ }
9
+ if (options.name.startsWith("-")) {
10
+ throw new Error('Task name must not start with "-".');
11
+ }
12
+ if (!options.dependencies?.length && !options.run) {
13
+ throw new Error("Task must have at run function or dependencies.");
14
+ }
15
+ this.options = options;
16
+ }
17
+ /* @internal */
18
+ static create(options) {
19
+ return new Task(options);
20
+ }
21
+ }
22
+ /**
23
+ * Creates a new Task.
24
+ */
25
+ export function task(options) {
26
+ return Task.create(options);
27
+ }
28
+ //# sourceMappingURL=index.js.map
package/dist/runner.js ADDED
@@ -0,0 +1,40 @@
1
+ import PQueue from "p-queue";
2
+ export class Runner {
3
+ constructor(options) {
4
+ this._addedTasks = new WeakMap();
5
+ this._queue = new PQueue({ concurrency: options?.concurrency ?? Infinity });
6
+ }
7
+ async runTasks(...tasks) {
8
+ await Promise.all(tasks.map((task) => {
9
+ const cached = this._addedTasks.get(task);
10
+ if (cached) {
11
+ return cached;
12
+ }
13
+ const promise = this._runTask(task);
14
+ this._addedTasks.set(task, promise);
15
+ return promise;
16
+ }));
17
+ }
18
+ async _runTask(task) {
19
+ this.onTaskAdd?.(task);
20
+ const { dependencies, run } = task.options;
21
+ if (dependencies) {
22
+ await this.runTasks(...dependencies);
23
+ }
24
+ if (!run) {
25
+ return;
26
+ }
27
+ return this._queue.add(async () => {
28
+ try {
29
+ this.onTaskStart?.(task);
30
+ await run();
31
+ this.onTaskFinish?.(task);
32
+ }
33
+ catch (e) {
34
+ this.onTaskError?.(task, e);
35
+ throw e;
36
+ }
37
+ });
38
+ }
39
+ }
40
+ //# sourceMappingURL=runner.js.map
package/dist/utils.js ADDED
@@ -0,0 +1,13 @@
1
+ export function forEachTask(tasks, fn, seen = new Set()) {
2
+ tasks.forEach(visit);
3
+ return;
4
+ function visit(task) {
5
+ if (seen.has(task)) {
6
+ return;
7
+ }
8
+ seen.add(task);
9
+ fn(task);
10
+ task.options.dependencies?.forEach(visit);
11
+ }
12
+ }
13
+ //# sourceMappingURL=utils.js.map
package/package.json ADDED
@@ -0,0 +1,117 @@
1
+ {
2
+ "name": "hereby",
3
+ "version": "1.0.0",
4
+ "description": "A simple task runner",
5
+ "repository": "github:jakebailey/hereby",
6
+ "type": "module",
7
+ "bin": "./dist/cli.js",
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/index.js",
13
+ "types": "./dist/index.d.ts"
14
+ },
15
+ "./cli": "./dist/cli.js",
16
+ "./package.json": "./package.json"
17
+ },
18
+ "author": "Jake Bailey",
19
+ "license": "MIT",
20
+ "keywords": [
21
+ "hereby",
22
+ "herebyfile",
23
+ "task",
24
+ "runner",
25
+ "build",
26
+ "gulp",
27
+ "make",
28
+ "makefile"
29
+ ],
30
+ "engines": {
31
+ "node": ">= 14.16"
32
+ },
33
+ "files": [
34
+ "README.md",
35
+ "LICENSE",
36
+ "./dist/**/*.js",
37
+ "!**/__tests__/**",
38
+ "./dist/index.d.ts",
39
+ "!./dist/testUtils.js"
40
+ ],
41
+ "dependencies": {
42
+ "chalk": "^5.0.1",
43
+ "command-line-args": "^5.2.1",
44
+ "command-line-usage": "^6.1.3",
45
+ "foreground-child": "^2.0.0",
46
+ "import-meta-resolve": "^2.1.0",
47
+ "p-queue": "^7.3.0",
48
+ "pretty-ms": "^8.0.0"
49
+ },
50
+ "devDependencies": {
51
+ "@ava/typescript": "^3.0.1",
52
+ "@tsconfig/node14": "^1.0.3",
53
+ "@types/command-line-args": "^5.2.0",
54
+ "@types/command-line-usage": "^5.0.2",
55
+ "@types/node": "^14.18.24",
56
+ "@typescript-eslint/eslint-plugin": "^5.33.1",
57
+ "@typescript-eslint/parser": "^5.33.1",
58
+ "ava": "^4.3.1",
59
+ "c8": "^7.12.0",
60
+ "cross-env": "^7.0.3",
61
+ "eslint": "^8.22.0",
62
+ "eslint-config-prettier": "^8.5.0",
63
+ "eslint-plugin-ava": "^13.2.0",
64
+ "eslint-plugin-simple-import-sort": "^7.0.0",
65
+ "esmock": "^1.9.4",
66
+ "execa": "^6.1.0",
67
+ "moq.ts": "^9.0.2",
68
+ "prettier": "^2.7.1",
69
+ "release-it": "^15.3.0",
70
+ "rimraf": "^3.0.2",
71
+ "tempy": "^3.0.0",
72
+ "typescript": "^4.7.4"
73
+ },
74
+ "packageManager": "npm@8.17.0",
75
+ "volta": {
76
+ "node": "14.20.0",
77
+ "npm": "8.17.0"
78
+ },
79
+ "scripts": {
80
+ "build": "tsc",
81
+ "watch": "tsc --watch",
82
+ "test": "ava",
83
+ "coverage": "c8 ava",
84
+ "prepack": "rimraf dist && npm run build"
85
+ },
86
+ "ava": {
87
+ "typescript": {
88
+ "rewritePaths": {
89
+ "src/": "dist/"
90
+ },
91
+ "compile": false
92
+ },
93
+ "environmentVariables": {
94
+ "NODE_OPTIONS": "--loader=esmock",
95
+ "NODE_NO_WARNINGS": "1",
96
+ "FORCE_COLOR": "0"
97
+ }
98
+ },
99
+ "c8": {
100
+ "all": true,
101
+ "include": "dist",
102
+ "reporter": [
103
+ "text",
104
+ "html",
105
+ "lcov"
106
+ ]
107
+ },
108
+ "release-it": {
109
+ "git": {
110
+ "commitMessage": "Release v${version}",
111
+ "tagName": "v${version}"
112
+ },
113
+ "hooks": {
114
+ "before:init": "npm run test"
115
+ }
116
+ }
117
+ }