@jpillora/take 0.9.1 → 0.11.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 (3) hide show
  1. package/package.json +1 -1
  2. package/take.d.mts +18 -1
  3. package/take.mjs +89 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jpillora/take",
3
- "version": "0.9.1",
3
+ "version": "0.11.0",
4
4
  "description": "A minimal CLI library for building TypeScript-based command-line tools",
5
5
  "type": "module",
6
6
  "main": "./take.mjs",
package/take.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { SpawnOptions as nodeSpawnOptions } from "node:child_process";
1
+ import { type SpawnOptions as nodeSpawnOptions } from "node:child_process";
2
2
  export type Flag = {
3
3
  initial: number | string | boolean | Date;
4
4
  description: string;
@@ -20,6 +20,7 @@ export declare function newFlags<F extends Flags>(flags: F): F;
20
20
  export type NewCommand<F extends Flags = Flags> = TakeCommand<F> & {
21
21
  flagValues: FlagValues<F>;
22
22
  input: CommandInput<F>;
23
+ flagsInitial: FlagValues<F>;
23
24
  };
24
25
  export type CommandInput<F extends Flags> = {
25
26
  flags: FlagValues<F>;
@@ -34,6 +35,22 @@ export type SpawnOptions = {
34
35
  args?: string[];
35
36
  } & nodeSpawnOptions;
36
37
  export declare function spawn(options: SpawnOptions): Promise<number>;
38
+ export type RunResult = {
39
+ code: number;
40
+ stdout: string;
41
+ stderr: string;
42
+ combined: string;
43
+ error?: string;
44
+ success: boolean;
45
+ };
46
+ export type ExecResult = {
47
+ pid: number;
48
+ error?: string;
49
+ wait: () => Promise<RunResult>;
50
+ kill: (signal: number) => void;
51
+ };
52
+ export declare function exec(options: SpawnOptions): ExecResult;
53
+ export declare function run(options: SpawnOptions): Promise<RunResult>;
37
54
  export declare const $: (script: string) => Promise<void>;
38
55
  export declare const timer: () => () => string;
39
56
  export declare function Register(...commands: NewCommand<any>[]): Promise<void>;
package/take.mjs CHANGED
@@ -1,6 +1,8 @@
1
- // Take is a mini-CLI library for building typescript-based command-line tools
2
- // Works with Deno, Node.js (with type stripping), and Bun
1
+ // Take is a mini-CLI library for building typescript-based command-line tools.
2
+ // Works with Deno, Node.js (with type stripping), and Bun.
3
+ // IMPORTANT: All code must stay in 1 file.
3
4
  // deno-lint-ignore-file no-explicit-any
5
+ import { Buffer } from "node:buffer";
4
6
  import { readFile } from "node:fs/promises";
5
7
  import { basename } from "node:path";
6
8
  import { spawn as nodeSpawn, } from "node:child_process";
@@ -51,6 +53,84 @@ export async function spawn(options) {
51
53
  });
52
54
  });
53
55
  }
56
+ export function exec(options) {
57
+ let code = -1;
58
+ let error = "";
59
+ const datas = {
60
+ out: [],
61
+ err: [],
62
+ combined: [],
63
+ };
64
+ const result = {
65
+ get code() {
66
+ return code;
67
+ },
68
+ get stdout() {
69
+ return Buffer.concat(datas.out).toString();
70
+ },
71
+ get stderr() {
72
+ return Buffer.concat(datas.err).toString();
73
+ },
74
+ get combined() {
75
+ return Buffer.concat(datas.combined).toString();
76
+ },
77
+ get error() {
78
+ return error || undefined;
79
+ },
80
+ get success() {
81
+ return code === 0;
82
+ },
83
+ };
84
+ try {
85
+ const child = nodeSpawn(options.program, options.args ?? [], options);
86
+ child.stdout?.on("data", (data) => {
87
+ const buf = Buffer.from(data);
88
+ datas.out.push(buf);
89
+ datas.combined.push(buf);
90
+ });
91
+ child.stderr?.on("data", (data) => {
92
+ const buf = Buffer.from(data);
93
+ datas.err.push(buf);
94
+ datas.combined.push(buf);
95
+ });
96
+ let resolved = false;
97
+ const resultPromise = new Promise((resolve) => {
98
+ const done = (finalCode) => {
99
+ if (resolved) {
100
+ return;
101
+ }
102
+ code = finalCode;
103
+ resolved = true;
104
+ resolve(result);
105
+ };
106
+ child.on("error", (err) => {
107
+ error = err.message;
108
+ done(1);
109
+ });
110
+ child.on("close", (c) => {
111
+ done(c ?? 1);
112
+ });
113
+ });
114
+ return {
115
+ pid: child.pid ?? 0,
116
+ wait: () => resultPromise,
117
+ kill: (signal) => child.kill(signal),
118
+ };
119
+ }
120
+ catch (err) {
121
+ code = 1;
122
+ error = err instanceof Error ? err.message : String(err);
123
+ return {
124
+ pid: 0,
125
+ error,
126
+ wait: () => Promise.resolve(result),
127
+ kill: () => { },
128
+ };
129
+ }
130
+ }
131
+ export function run(options) {
132
+ return exec(options).wait();
133
+ }
54
134
  // helper for running bash scripts
55
135
  export const $ = async (script) => {
56
136
  await spawn({
@@ -372,7 +452,13 @@ export async function Register(...commands) {
372
452
  }
373
453
  }
374
454
  export function Command(command) {
375
- return { ...command, flagValues: null, input: null };
455
+ const flagsInitial = Object.fromEntries(Object.entries(command.flags).map(([k, v]) => [k, v.initial]));
456
+ return {
457
+ ...command,
458
+ flagValues: null,
459
+ input: null,
460
+ flagsInitial,
461
+ };
376
462
  }
377
463
  // deno-lint-ignore no-constant-condition
378
464
  if (42 < 7) {