@haltcase/run 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.
Files changed (56) hide show
  1. package/dist/cli/bin.d.ts +2 -0
  2. package/dist/cli/bin.js +8 -0
  3. package/dist/cli/bin.js.map +1 -0
  4. package/dist/cli/handler.d.ts +22 -0
  5. package/dist/cli/handler.js +79 -0
  6. package/dist/cli/handler.js.map +1 -0
  7. package/dist/cli/handler.test.d.ts +1 -0
  8. package/dist/cli/handler.test.js +23 -0
  9. package/dist/cli/handler.test.js.map +1 -0
  10. package/dist/cli/main.d.ts +21 -0
  11. package/dist/cli/main.js +57 -0
  12. package/dist/cli/main.js.map +1 -0
  13. package/dist/cli/parseOptions.d.ts +12 -0
  14. package/dist/cli/parseOptions.js +45 -0
  15. package/dist/cli/parseOptions.js.map +1 -0
  16. package/dist/cli/parseOptions.test.d.ts +1 -0
  17. package/dist/cli/parseOptions.test.js +35 -0
  18. package/dist/cli/parseOptions.test.js.map +1 -0
  19. package/dist/cli/util.d.ts +15 -0
  20. package/dist/cli/util.js +68 -0
  21. package/dist/config.d.ts +16 -0
  22. package/dist/config.js +17 -0
  23. package/dist/config.js.map +1 -0
  24. package/dist/index.d.ts +4 -0
  25. package/dist/index.js +2 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/tasks/executeTask.d.ts +12 -0
  28. package/dist/tasks/executeTask.js +43 -0
  29. package/dist/tasks/executeTask.js.map +1 -0
  30. package/dist/tasks/guards.d.ts +3 -0
  31. package/dist/tasks/guards.js +3 -0
  32. package/dist/tasks/guards.js.map +1 -0
  33. package/dist/tasks/task.d.ts +7 -0
  34. package/dist/tasks/task.js +39 -0
  35. package/dist/tasks/task.js.map +1 -0
  36. package/dist/tasks/task.test.d.ts +1 -0
  37. package/dist/tasks/task.test.js +25 -0
  38. package/dist/tasks/task.test.js.map +1 -0
  39. package/dist/tasks/types.d.ts +57 -0
  40. package/dist/tasks/types.js +2 -0
  41. package/dist/tasks/types.js.map +1 -0
  42. package/dist/tsconfig.build.tsbuildinfo +1 -0
  43. package/dist/util/loadTaskFile.d.ts +8 -0
  44. package/dist/util/loadTaskFile.js +31 -0
  45. package/dist/util/loadTaskFile.js.map +1 -0
  46. package/dist/util/resolveTaskFile.d.ts +2 -0
  47. package/dist/util/resolveTaskFile.js +18 -0
  48. package/dist/util/resolveTaskFile.js.map +1 -0
  49. package/dist/util/result.d.ts +9 -0
  50. package/dist/util/result.js +2 -0
  51. package/dist/util/result.js.map +1 -0
  52. package/dist/util/types.d.ts +7 -0
  53. package/dist/util/types.js +1 -0
  54. package/license +21 -0
  55. package/package.json +80 -0
  56. package/readme.md +352 -0
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import { createHandler } from "./handler.js";
3
+ import { main } from "./main.js";
4
+ const handler = createHandler();
5
+ void main({
6
+ handler
7
+ });
8
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../../src/cli/bin.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;AAEhC,KAAK,IAAI,CAAC;IACT,OAAO;CACP,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { Spinner } from "@favware/colorette-spinner";
2
+ import type { MainContextWithData } from "./main.js";
3
+ export declare const failWith: (spinner: Spinner, message: unknown) => never;
4
+ export declare const write: (message: string) => void;
5
+ interface HelpContextCommand {
6
+ command: string;
7
+ }
8
+ interface HelpContextScript extends MainContextWithData {
9
+ taskList: true;
10
+ }
11
+ type HelpContext = HelpContextCommand | HelpContextScript;
12
+ export declare const commandHandler: (_context: HelpContextCommand) => string;
13
+ export declare const taskListHandler: (context: HelpContextScript) => string;
14
+ export declare const help: (context: HelpContext) => string;
15
+ export interface Handler {
16
+ spinner: Spinner;
17
+ help: (context: HelpContext) => string;
18
+ write: (message: string) => void;
19
+ failWith: (message: unknown) => never;
20
+ }
21
+ export declare const createHandler: () => Handler;
22
+ export {};
@@ -0,0 +1,79 @@
1
+ import { Spinner } from "@favware/colorette-spinner";
2
+ import cliui from "@isaacs/cliui";
3
+ import { bold, yellow } from "colorette";
4
+ import { isBrandedTask } from "../tasks/guards.js";
5
+ export const failWith = (spinner, message) => {
6
+ let text;
7
+ if (Array.isArray(message)) {
8
+ text = message.map(String).join("\n");
9
+ }
10
+ if (text == null || typeof text !== "string") {
11
+ text = String(message);
12
+ }
13
+ spinner.error({
14
+ text
15
+ });
16
+ process.exit(1);
17
+ };
18
+ export const write = (message) => {
19
+ process.stdout.write(`${message}\n`);
20
+ };
21
+ const usage = `Usage: ${yellow("hr")} <action> [task]`;
22
+ export const commandHandler = (_context) => {
23
+ return usage;
24
+ };
25
+ export const taskListHandler = (context) => {
26
+ const ui = cliui({
27
+ width: Math.max(0, process.stdout.columns - 4),
28
+ wrap: true
29
+ });
30
+ const { config } = context.taskFile.data;
31
+ const taskInfo = Object.entries(config)
32
+ .map(([name, value]) => {
33
+ if (!value) {
34
+ return "";
35
+ }
36
+ const formattedName = bold(name);
37
+ if (isBrandedTask(value)) {
38
+ if (value.kind === "strictTask") {
39
+ const keys = Object.keys(value.inputSchema).join(", ");
40
+ const { description = "" } = value.schema;
41
+ return [formattedName, keys && `{ ${keys} }`, description]
42
+ .filter(Boolean)
43
+ .join("\t");
44
+ }
45
+ return formattedName;
46
+ }
47
+ return formattedName;
48
+ })
49
+ .join("\n");
50
+ ui.div(usage.replace("<action>", context.taskFile.name));
51
+ ui.div({
52
+ text: "Available tasks:",
53
+ padding: [1, 0, 1, 0]
54
+ });
55
+ ui.div({
56
+ text: taskInfo,
57
+ padding: [0, 2, 1, 2]
58
+ });
59
+ return ui.toString();
60
+ };
61
+ export const help = (context) => {
62
+ if ("command" in context) {
63
+ return commandHandler(context);
64
+ }
65
+ if ("taskList" in context) {
66
+ return taskListHandler(context);
67
+ }
68
+ return "";
69
+ };
70
+ export const createHandler = () => {
71
+ const spinner = new Spinner();
72
+ return {
73
+ spinner,
74
+ help,
75
+ write,
76
+ failWith: (message) => failWith(spinner, message)
77
+ };
78
+ };
79
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/cli/handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
1
+ import { expect, test, vi } from "vitest";
2
+ import { createHandler } from "./handler.js";
3
+ const handler = createHandler();
4
+ const stdoutSpy = vi.spyOn(globalThis.process.stdout, "write");
5
+ const stderrSpy = vi.spyOn(globalThis.process.stderr, "write");
6
+ const exitSpy = vi.spyOn(globalThis.process, "exit");
7
+ test("handler: writes to stdout", () => {
8
+ const stdout = stdoutSpy.mockImplementationOnce(() => true);
9
+ const message = "Success";
10
+ handler.write(message);
11
+ expect(stdout).toHaveBeenCalledWith(`${message}\n`);
12
+ });
13
+ test("handler: writes to stderr and exits", () => {
14
+ const stderr = stderrSpy.mockImplementationOnce(() => true);
15
+ // @ts-expect-error we can't actually return never
16
+ const exit = exitSpy.mockImplementationOnce(() => {
17
+ // nothing
18
+ });
19
+ handler.failWith("Error message");
20
+ expect(stderr).toHaveBeenCalled();
21
+ expect(exit).toHaveBeenCalled();
22
+ });
23
+ //# sourceMappingURL=handler.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.test.js","sourceRoot":"","sources":["../../src/cli/handler.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE1C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;AAEhC,MAAM,SAAS,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC/D,MAAM,SAAS,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC/D,MAAM,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AAErD,IAAI,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACtC,MAAM,MAAM,GAAG,SAAS,CAAC,sBAAsB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,SAAS,CAAC;IAC1B,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACvB,MAAM,CAAC,MAAM,CAAC,CAAC,oBAAoB,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;AACrD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qCAAqC,EAAE,GAAG,EAAE;IAChD,MAAM,MAAM,GAAG,SAAS,CAAC,sBAAsB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAC5D,kDAAkD;IAClD,MAAM,IAAI,GAAG,OAAO,CAAC,sBAAsB,CAAC,GAAG,EAAE;QAChD,UAAU;IACX,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;IAElC,MAAM,CAAC,MAAM,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAClC,MAAM,CAAC,IAAI,CAAC,CAAC,gBAAgB,EAAE,CAAC;AACjC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { ParsedPath } from "node:path";
2
+ import type { AppConfig } from "../config.js";
3
+ import type { TaskCollection } from "../tasks/types.js";
4
+ import type { ResolvedConfigWithFile } from "../util/loadTaskFile.js";
5
+ import type { Handler } from "./handler.js";
6
+ export interface MainProps {
7
+ handler: Handler;
8
+ }
9
+ export interface MainContext extends MainProps {
10
+ config: AppConfig;
11
+ taskFile: ParsedPath & {
12
+ path: string;
13
+ };
14
+ taskName: string;
15
+ }
16
+ export interface MainContextWithData extends MainContext {
17
+ taskFile: MainContext["taskFile"] & {
18
+ data: ResolvedConfigWithFile<TaskCollection>;
19
+ };
20
+ }
21
+ export declare const main: (props: MainProps) => Promise<void>;
@@ -0,0 +1,57 @@
1
+ import { parse, resolve } from "node:path";
2
+ import { getAppConfig } from "../config.js";
3
+ import { executeTask } from "../tasks/executeTask.js";
4
+ import { loadTaskFile } from "../util/loadTaskFile.js";
5
+ import { resolveTaskFile } from "../util/resolveTaskFile.js";
6
+ import { parseOptions } from "./parseOptions.js";
7
+ export const main = async (props) => {
8
+ const { config } = await getAppConfig();
9
+ const inputFileName = process.argv[2];
10
+ const taskName = process.argv[3] ?? "";
11
+ if (!inputFileName) {
12
+ props.handler.help({ command: "help" });
13
+ props.handler.failWith("Task file name is required");
14
+ }
15
+ const fullFilePath = resolve(config.taskDirectory, inputFileName);
16
+ const context = {
17
+ ...props,
18
+ config,
19
+ taskFile: {
20
+ ...parse(fullFilePath),
21
+ path: fullFilePath
22
+ },
23
+ taskName
24
+ };
25
+ const resolutions = resolveTaskFile(context);
26
+ if (Array.isArray(resolutions)) {
27
+ props.handler.failWith([
28
+ `Found multiple task files with the name '${context.taskFile.name}'`,
29
+ `Rename the ambiguous files or specify an extension and try again`,
30
+ resolutions.map((it) => ` ${it}`).join("\n")
31
+ ]);
32
+ }
33
+ const taskFileResult = await loadTaskFile(context);
34
+ if (!taskFileResult.ok) {
35
+ props.handler.failWith(taskFileResult.error);
36
+ }
37
+ const contextWithData = {
38
+ ...context,
39
+ taskFile: {
40
+ ...context.taskFile,
41
+ data: taskFileResult.value
42
+ }
43
+ };
44
+ try {
45
+ const options = parseOptions(process.argv.slice(4));
46
+ await executeTask(contextWithData, options);
47
+ if (!config.quiet) {
48
+ props.handler.spinner.success({
49
+ text: "Success"
50
+ });
51
+ }
52
+ }
53
+ catch (error) {
54
+ props.handler.failWith([`Failed to execute task`, String(error)]);
55
+ }
56
+ };
57
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAG3C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAoBjD,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,EAAE,KAAgB,EAAE,EAAE;IAC9C,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,YAAY,EAAE,CAAC;IAExC,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAEvC,IAAI,CAAC,aAAa,EAAE,CAAC;QACpB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;IAElE,MAAM,OAAO,GAAG;QACf,GAAG,KAAK;QACR,MAAM;QACN,QAAQ,EAAE;YACT,GAAG,KAAK,CAAC,YAAY,CAAC;YACtB,IAAI,EAAE,YAAY;SAClB;QACD,QAAQ;KACc,CAAC;IAExB,MAAM,WAAW,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAE7C,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;YACtB,4CAA4C,OAAO,CAAC,QAAQ,CAAC,IAAI,GAAG;YACpE,kEAAkE;YAClE,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;SAC7C,CAAC,CAAC;IACJ,CAAC;IAED,MAAM,cAAc,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;IAEnD,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,CAAC;QACxB,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,eAAe,GAAG;QACvB,GAAG,OAAO;QACV,QAAQ,EAAE;YACT,GAAG,OAAO,CAAC,QAAQ;YACnB,IAAI,EAAE,cAAc,CAAC,KAAK;SAC1B;KAC6B,CAAC;IAEhC,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,WAAW,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QAE5C,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACnB,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;gBAC7B,IAAI,EAAE,SAAS;aACf,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,wBAAwB,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnE,CAAC;AACF,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ export interface ParsedOptions {
2
+ _: string[];
3
+ [key: string]: unknown;
4
+ }
5
+ /**
6
+ * Wrapper around Node's {@link parseArgs} that treats options as strings
7
+ * by default, instead of boolean flags.
8
+ *
9
+ * @param args - argv-like string
10
+ * @returns
11
+ */
12
+ export declare const parseOptions: (args: string[]) => ParsedOptions;
@@ -0,0 +1,45 @@
1
+ import { parseArgs } from "node:util";
2
+ /**
3
+ * Wrapper around Node's {@link parseArgs} that treats options as strings
4
+ * by default, instead of boolean flags.
5
+ *
6
+ * @param args - argv-like string
7
+ * @returns
8
+ */
9
+ export const parseOptions = (args) => {
10
+ const { tokens } = parseArgs({
11
+ args,
12
+ allowPositionals: true,
13
+ strict: false,
14
+ tokens: true
15
+ });
16
+ const options = {
17
+ _: []
18
+ };
19
+ for (let index = 0; index < tokens.length; index++) {
20
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
21
+ const token = tokens[index];
22
+ if (token.kind === "option-terminator") {
23
+ continue;
24
+ }
25
+ if (token.kind === "option") {
26
+ if (index + 1 < tokens.length) {
27
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
28
+ const next = tokens[index + 1];
29
+ if (next.kind !== "positional") {
30
+ throw new Error(`Expected value for option ${token.rawName}`);
31
+ }
32
+ options[token.name] = next.value;
33
+ index++;
34
+ }
35
+ else {
36
+ throw new Error(`Expected option ${token.rawName} to be followed by a value`);
37
+ }
38
+ }
39
+ if (token.kind === "positional") {
40
+ options._.push(token.value);
41
+ }
42
+ }
43
+ return options;
44
+ };
45
+ //# sourceMappingURL=parseOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseOptions.js","sourceRoot":"","sources":["../../src/cli/parseOptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAOtC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAc,EAAiB,EAAE;IAC7D,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;QAC5B,IAAI;QACJ,gBAAgB,EAAE,IAAI;QACtB,MAAM,EAAE,KAAK;QACb,MAAM,EAAE,IAAI;KACZ,CAAC,CAAC;IAEH,MAAM,OAAO,GAAkB;QAC9B,CAAC,EAAE,EAAE;KACL,CAAC;IAEF,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QACpD,oEAAoE;QACpE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAE,CAAC;QAE7B,IAAI,KAAK,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;YACxC,SAAS;QACV,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,IAAI,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;gBAC/B,oEAAoE;gBACpE,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,CAAE,CAAC;gBAEhC,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBAChC,MAAM,IAAI,KAAK,CAAC,6BAA6B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC/D,CAAC;gBAED,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;gBACjC,KAAK,EAAE,CAAC;YACT,CAAC;iBAAM,CAAC;gBACP,MAAM,IAAI,KAAK,CACd,mBAAmB,KAAK,CAAC,OAAO,4BAA4B,CAC5D,CAAC;YACH,CAAC;QACF,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACjC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;IACF,CAAC;IAED,OAAO,OAAO,CAAC;AAChB,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,35 @@
1
+ import { expect, test } from "vitest";
2
+ import { parseOptions } from "./parseOptions.js";
3
+ test("parseOptions: parses options as key/value and returns positionals", () => {
4
+ expect(parseOptions([
5
+ "--file",
6
+ "readme.md",
7
+ "--dryRun",
8
+ "true",
9
+ "you",
10
+ "spin",
11
+ "me",
12
+ "right",
13
+ "round"
14
+ ])).toStrictEqual({
15
+ _: ["you", "spin", "me", "right", "round"],
16
+ file: "readme.md",
17
+ dryRun: "true"
18
+ });
19
+ });
20
+ test("parseOptions: expects all options to have values", () => {
21
+ expect(() => parseOptions(["--name"])).toThrow("Expected option --name to be followed by a value");
22
+ });
23
+ test("parseOptions: returns everything after terminator as positionals", () => {
24
+ expect(parseOptions(["--color", "blue", "--", "--name", "-aBcDeF"]))
25
+ .toMatchInlineSnapshot(`
26
+ {
27
+ "_": [
28
+ "--name",
29
+ "-aBcDeF",
30
+ ],
31
+ "color": "blue",
32
+ }
33
+ `);
34
+ });
35
+ //# sourceMappingURL=parseOptions.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseOptions.test.js","sourceRoot":"","sources":["../../src/cli/parseOptions.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,IAAI,CAAC,mEAAmE,EAAE,GAAG,EAAE;IAC9E,MAAM,CACL,YAAY,CAAC;QACZ,QAAQ;QACR,WAAW;QACX,UAAU;QACV,MAAM;QACN,KAAK;QACL,MAAM;QACN,IAAI;QACJ,OAAO;QACP,OAAO;KACP,CAAC,CACF,CAAC,aAAa,CAAC;QACf,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC;QAC1C,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,MAAM;KACd,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,kDAAkD,EAAE,GAAG,EAAE;IAC7D,MAAM,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAC7C,kDAAkD,CAClD,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,kEAAkE,EAAE,GAAG,EAAE;IAC7E,MAAM,CAAC,YAAY,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;SAClE,qBAAqB,CAAC;;;;;;;;EAQvB,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { ResultError } from "../util/result.js";
2
+ import type { MainContextWithData } from "./main.js";
3
+ export declare const failWith: (message: unknown) => ResultError<Error>;
4
+ export declare const write: (message: string) => void;
5
+ interface HelpContextCommand {
6
+ command: string;
7
+ }
8
+ interface HelpContextScript extends MainContextWithData {
9
+ taskList: true;
10
+ }
11
+ type HelpContext = HelpContextCommand | HelpContextScript;
12
+ export declare const commandHandler: (_context: HelpContextCommand) => string;
13
+ export declare const taskListHandler: (context: HelpContextScript) => string;
14
+ export declare const help: (context: HelpContext) => string;
15
+ export {};
@@ -0,0 +1,68 @@
1
+ import cliui from "@isaacs/cliui";
2
+ import { bold, yellow } from "colorette";
3
+ import { isBrandedTask } from "../tasks/guards.js";
4
+ export const failWith = (message) => {
5
+ let text;
6
+ if (Array.isArray(message)) {
7
+ text = message.map(String).join("\n");
8
+ }
9
+ if (text == null || typeof text !== "string") {
10
+ text = String(message);
11
+ }
12
+ return {
13
+ ok: false,
14
+ error: new Error(text)
15
+ };
16
+ };
17
+ export const write = (message) => {
18
+ process.stdout.write(`${message}\n`);
19
+ };
20
+ const usage = `Usage: ${yellow("funtask")} <action> [task]`;
21
+ export const commandHandler = (_context) => {
22
+ return usage;
23
+ };
24
+ export const taskListHandler = (context) => {
25
+ const ui = cliui({
26
+ width: Math.max(0, process.stdout.columns - 4),
27
+ wrap: true
28
+ });
29
+ const { config } = context.taskFile.data;
30
+ const taskInfo = Object.entries(config)
31
+ .map(([name, value]) => {
32
+ if (!value) {
33
+ return "";
34
+ }
35
+ const formattedName = bold(name);
36
+ if (isBrandedTask(value)) {
37
+ if (value.kind === "strictTask") {
38
+ const keys = Object.keys(value.inputSchema).join(", ");
39
+ const { description = "" } = value.schema;
40
+ return [formattedName, keys && `{ ${keys} }`, description]
41
+ .filter(Boolean)
42
+ .join("\t");
43
+ }
44
+ return formattedName;
45
+ }
46
+ return formattedName;
47
+ })
48
+ .join("\n");
49
+ ui.div(usage.replace("<action>", context.taskFile.name));
50
+ ui.div({
51
+ text: "Available tasks:",
52
+ padding: [1, 0, 1, 0]
53
+ });
54
+ ui.div({
55
+ text: taskInfo,
56
+ padding: [0, 2, 1, 2]
57
+ });
58
+ return ui.toString();
59
+ };
60
+ export const help = (context) => {
61
+ if ("command" in context) {
62
+ return commandHandler(context);
63
+ }
64
+ if ("taskList" in context) {
65
+ return taskListHandler(context);
66
+ }
67
+ return "";
68
+ };
@@ -0,0 +1,16 @@
1
+ export interface AppConfig {
2
+ /**
3
+ * Directory containing task files. Defaults to the `scripts` folder within
4
+ * the current working directory.
5
+ *
6
+ * @default `<cwd>/scripts`
7
+ */
8
+ taskDirectory: string;
9
+ /**
10
+ * Print no output unless errors occur.
11
+ *
12
+ * @default false
13
+ */
14
+ quiet: boolean;
15
+ }
16
+ export declare const getAppConfig: () => Promise<import("c12").ResolvedConfig<AppConfig, import("c12").ConfigLayerMeta>>;
package/dist/config.js ADDED
@@ -0,0 +1,17 @@
1
+ import { join } from "node:path";
2
+ import { cwd } from "node:process";
3
+ import { loadConfig } from "c12";
4
+ export const getAppConfig = async () => {
5
+ const configName = "haltcase.run";
6
+ return loadConfig({
7
+ name: configName,
8
+ configFile: configName,
9
+ packageJson: configName,
10
+ rcFile: configName,
11
+ defaults: {
12
+ taskDirectory: join(cwd(), "scripts"),
13
+ quiet: false
14
+ }
15
+ });
16
+ };
17
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAmBjC,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE;IACtC,MAAM,UAAU,GAAG,cAAc,CAAC;IAElC,OAAO,UAAU,CAAY;QAC5B,IAAI,EAAE,UAAU;QAChB,UAAU,EAAE,UAAU;QACtB,WAAW,EAAE,UAAU;QACvB,MAAM,EAAE,UAAU;QAElB,QAAQ,EAAE;YACT,aAAa,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC;YACrC,KAAK,EAAE,KAAK;SACZ;KACD,CAAC,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export type { ParsedOptions } from "./cli/parseOptions.js";
2
+ export type { AppConfig as HaltcaseRunConfig } from "./config.js";
3
+ export { task } from "./tasks/task.js";
4
+ export type { Task } from "./tasks/types.js";
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { task } from "./tasks/task.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { MainContextWithData } from "../cli/main.js";
2
+ import type { ParsedOptions } from "../cli/parseOptions.js";
3
+ export declare const taskUtilities: {
4
+ command: import("execa").ExecaMethod<{}>;
5
+ $: import("execa").ExecaScriptMethod<{}>;
6
+ exec: import("execa").ExecaMethod<{
7
+ stdin: "inherit";
8
+ stdout: "inherit";
9
+ stderr: "inherit";
10
+ }>;
11
+ };
12
+ export declare const executeTask: (context: MainContextWithData, options: ParsedOptions) => Promise<void>;
@@ -0,0 +1,43 @@
1
+ import { join } from "node:path";
2
+ import { $, execa } from "execa";
3
+ const execaInherited = execa({
4
+ stdin: "inherit",
5
+ stdout: "inherit",
6
+ stderr: "inherit"
7
+ });
8
+ export const taskUtilities = {
9
+ command: execa,
10
+ $,
11
+ exec: execaInherited
12
+ };
13
+ export const executeTask = async (context, options) => {
14
+ const taskFunction = context.taskFile.data.config[context.taskName];
15
+ const specifier = `${context.taskFile.name}::${context.taskName}`;
16
+ if (taskFunction == null) {
17
+ context.handler.write(context.handler.help({
18
+ taskList: true,
19
+ ...context
20
+ }));
21
+ if (!context.taskName) {
22
+ context.handler.failWith(`Task name is required.`);
23
+ }
24
+ context.handler.failWith([
25
+ `Task file '${context.taskFile.base}' does not export '${context.taskName}'`,
26
+ `Resolved to: ${join(context.taskFile.dir, context.taskFile.base)}`
27
+ ]);
28
+ }
29
+ try {
30
+ await taskFunction(options, taskUtilities);
31
+ }
32
+ catch (error) {
33
+ const message = error instanceof Error ? error.message : String(error);
34
+ if (message.includes("is not a function")) {
35
+ context.handler.failWith([
36
+ `Failed to execute ${specifier}`,
37
+ `Exported value '${context.taskName}' is not a function`
38
+ ]);
39
+ }
40
+ context.handler.failWith([`Failed to execute ${specifier}`, message]);
41
+ }
42
+ };
43
+ //# sourceMappingURL=executeTask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executeTask.js","sourceRoot":"","sources":["../../src/tasks/executeTask.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAMjC,MAAM,cAAc,GAAG,KAAK,CAAC;IAC5B,KAAK,EAAE,SAAS;IAChB,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,SAAS;CACjB,CAAiC,CAAC;AAEnC,MAAM,CAAC,MAAM,aAAa,GAAG;IAC5B,OAAO,EAAE,KAAK;IACd,CAAC;IACD,IAAI,EAAE,cAAc;CACI,CAAC;AAE1B,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAC/B,OAA4B,EAC5B,OAAsB,EACrB,EAAE;IACH,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpE,MAAM,SAAS,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC;IAElE,IAAI,YAAY,IAAI,IAAI,EAAE,CAAC;QAC1B,OAAO,CAAC,OAAO,CAAC,KAAK,CACpB,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;YACpB,QAAQ,EAAE,IAAI;YACd,GAAG,OAAO;SACV,CAAC,CACF,CAAC;QAEF,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACvB,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC;YACxB,cAAc,OAAO,CAAC,QAAQ,CAAC,IAAI,sBAAsB,OAAO,CAAC,QAAQ,GAAG;YAC5E,gBAAgB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;SACnE,CAAC,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACJ,MAAM,YAAY,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAEvE,IAAI,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC3C,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC;gBACxB,qBAAqB,SAAS,EAAE;gBAChC,mBAAmB,OAAO,CAAC,QAAQ,qBAAqB;aACxD,CAAC,CAAC;QACJ,CAAC;QAED,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,qBAAqB,SAAS,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;IACvE,CAAC;AACF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { BrandedTask, BrandedTaskStrict, Task } from "./types.js";
2
+ export declare const isBrandedTask: (task: Task) => task is BrandedTask;
3
+ export declare const isBrandedTaskStrict: (task: Task) => task is BrandedTaskStrict;
@@ -0,0 +1,3 @@
1
+ export const isBrandedTask = (task) => "kind" in task;
2
+ export const isBrandedTaskStrict = (task) => "kind" in task && task.kind === "strictTask";
3
+ //# sourceMappingURL=guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.js","sourceRoot":"","sources":["../../src/tasks/guards.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAU,EAAuB,EAAE,CAChE,MAAM,IAAI,IAAI,CAAC;AAEhB,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,IAAU,EAA6B,EAAE,CAC5E,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { z } from "zod";
2
+ import type { ParsedOptions } from "../cli/parseOptions.js";
3
+ import type { BrandedTask, ExpectShape, Task } from "./types.js";
4
+ export declare const task: {
5
+ <T = ParsedOptions>(fn: Task<T>): BrandedTask<T>;
6
+ strict<TShape extends ExpectShape, TSchema extends z.ZodObject<TShape> = z.ZodObject<TShape, z.UnknownKeysParam, z.ZodTypeAny, z.objectUtil.addQuestionMarks<z.baseObjectOutputType<TShape>, any> extends infer T ? { [k in keyof T]: z.objectUtil.addQuestionMarks<z.baseObjectOutputType<TShape>, any>[k]; } : never, z.baseObjectInputType<TShape> extends infer T_1 ? { [k_1 in keyof T_1]: z.baseObjectInputType<TShape>[k_1]; } : never>>(shape: TShape, fn: Task<z.infer<TSchema>>): BrandedTask<z.infer<TSchema>>;
7
+ };
@@ -0,0 +1,39 @@
1
+ import { red } from "colorette";
2
+ import { z } from "zod";
3
+ import { fromZodError } from "zod-validation-error";
4
+ const zodMessageBuilder = (issues) => issues
5
+ .map((issue) => {
6
+ const propertyName = issue.path[0];
7
+ if (issue.code === "unrecognized_keys") {
8
+ const keyList = issue.keys.map((key) => `--${key}`).join(", ");
9
+ return `${red("Unrecognized options")}: ${keyList}`;
10
+ }
11
+ if (!propertyName) {
12
+ return issue.message;
13
+ }
14
+ const optionText = propertyName === "_" ? "Positionals" : `--{propertyName}`;
15
+ // we currently assume there is only ever one path segment
16
+ return `${red(optionText)}: ${issue.message}`;
17
+ })
18
+ .join("\n");
19
+ export const task = (fn) => {
20
+ fn.kind = "task";
21
+ return fn;
22
+ };
23
+ task.strict = (shape, fn) => {
24
+ const schema = z.strictObject(shape);
25
+ const taskFunction = (options, utilities) => {
26
+ const { data, success, error } = schema.safeParse(options);
27
+ if (!success) {
28
+ throw new Error(fromZodError(error, { messageBuilder: zodMessageBuilder }).message, {
29
+ cause: error
30
+ });
31
+ }
32
+ return fn(data, utilities);
33
+ };
34
+ taskFunction.kind = "strictTask";
35
+ taskFunction.schema = schema;
36
+ taskFunction.inputSchema = shape;
37
+ return taskFunction;
38
+ };
39
+ //# sourceMappingURL=task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.js","sourceRoot":"","sources":["../../src/tasks/task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAUpD,MAAM,iBAAiB,GAAmB,CAAC,MAAM,EAAE,EAAE,CACpD,MAAM;KACJ,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;IACd,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAEnC,IAAI,KAAK,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;QACxC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/D,OAAO,GAAG,GAAG,CAAC,sBAAsB,CAAC,KAAK,OAAO,EAAE,CAAC;IACrD,CAAC;IAED,IAAI,CAAC,YAAY,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,MAAM,UAAU,GACf,YAAY,KAAK,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,kBAAkB,CAAC;IAE3D,0DAA0D;IAC1D,OAAO,GAAG,GAAG,CAAC,UAAU,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;AAC/C,CAAC,CAAC;KACD,IAAI,CAAC,IAAI,CAAC,CAAC;AAEd,MAAM,CAAC,MAAM,IAAI,GAAG,CAAoB,EAAW,EAAkB,EAAE;IACrE,EAAqB,CAAC,IAAI,GAAG,MAAM,CAAC;IACrC,OAAO,EAAoB,CAAC;AAC7B,CAAC,CAAC;AAEF,IAAI,CAAC,MAAM,GAAG,CAIb,KAAa,EACb,EAA0B,EACM,EAAE;IAClC,MAAM,MAAM,GAAG,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAErC,MAAM,YAAY,GAAwC,CACzD,OAAO,EACP,SAAS,EACR,EAAE;QACH,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAE3D,IAAI,CAAC,OAAO,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CACd,YAAY,CAAC,KAAK,EAAE,EAAE,cAAc,EAAE,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAClE;gBACC,KAAK,EAAE,KAAK;aACZ,CACD,CAAC;QACH,CAAC;QAED,OAAO,EAAE,CAAC,IAAwB,EAAE,SAAS,CAAC,CAAC;IAChD,CAAC,CAAC;IAEF,YAAY,CAAC,IAAI,GAAG,YAAY,CAAC;IACjC,YAAY,CAAC,MAAM,GAAG,MAAM,CAAC;IAC7B,YAAY,CAAC,WAAW,GAAG,KAAK,CAAC;IAEjC,OAAO,YAAY,CAAC;AACrB,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};