@cardelli/ambit 0.1.4 → 0.1.5
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/esm/deno.js +1 -1
- package/esm/deps/jsr.io/@zod/zod/4.3.6/src/v4/core/json-schema-generator.d.ts +1 -1
- package/esm/lib/cli.d.ts +0 -1
- package/esm/lib/cli.d.ts.map +1 -1
- package/esm/lib/cli.js +41 -26
- package/esm/lib/command.d.ts +23 -48
- package/esm/lib/command.d.ts.map +1 -1
- package/esm/lib/command.js +60 -89
- package/esm/lib/output.d.ts +1 -1
- package/esm/lib/output.d.ts.map +1 -1
- package/esm/lib/output.js +5 -9
- package/esm/lib/result.d.ts +19 -7
- package/esm/lib/result.d.ts.map +1 -1
- package/esm/lib/result.js +47 -1
- package/esm/src/cli/commands/create.js +110 -96
- package/esm/src/cli/commands/deploy.js +17 -13
- package/esm/src/cli/commands/destroy.js +3 -3
- package/esm/src/cli/commands/doctor.js +1 -1
- package/esm/src/discovery.d.ts +4 -1
- package/esm/src/discovery.d.ts.map +1 -1
- package/esm/src/discovery.js +15 -1
- package/esm/src/docker/router/start.sh +18 -72
- package/esm/src/providers/fly.d.ts +6 -0
- package/esm/src/providers/fly.d.ts.map +1 -1
- package/esm/src/providers/fly.js +77 -81
- package/esm/src/providers/tailscale.d.ts.map +1 -1
- package/esm/src/providers/tailscale.js +5 -11
- package/esm/src/template.d.ts +3 -4
- package/esm/src/template.d.ts.map +1 -1
- package/esm/src/template.js +15 -17
- package/package.json +7 -1
package/esm/deno.js
CHANGED
|
@@ -44,7 +44,7 @@ export declare class JSONSchemaGenerator {
|
|
|
44
44
|
path: (string | number)[];
|
|
45
45
|
}) => void;
|
|
46
46
|
/** @deprecated Access via ctx instead */
|
|
47
|
-
get io(): "
|
|
47
|
+
get io(): "input" | "output";
|
|
48
48
|
/** @deprecated Access via ctx instead */
|
|
49
49
|
get counter(): number;
|
|
50
50
|
set counter(value: number);
|
package/esm/lib/cli.d.ts
CHANGED
|
@@ -25,7 +25,6 @@ export declare const prompt: (message: string) => Promise<string>;
|
|
|
25
25
|
export declare const confirm: (message: string) => Promise<boolean>;
|
|
26
26
|
export declare const readSecret: (message: string) => Promise<string>;
|
|
27
27
|
export declare const fileExists: (path: string) => Promise<boolean>;
|
|
28
|
-
export declare const fileExistsSync: (path: string) => boolean;
|
|
29
28
|
export declare const getConfigDir: () => string;
|
|
30
29
|
export declare const getConfigPath: () => string;
|
|
31
30
|
export declare const ensureConfigDir: () => Promise<void>;
|
package/esm/lib/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/lib/cli.ts"],"names":[],"mappings":"AAKA,OAAO,sBAAsB,CAAC;AAiB9B,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,KAAG,MAAkC,CAAC;AACvE,eAAO,MAAM,GAAG,GAAI,MAAM,MAAM,KAAG,MAAiC,CAAC;AACrE,eAAO,MAAM,GAAG,GAAI,MAAM,MAAM,KAAG,MAAiC,CAAC;AACrE,eAAO,MAAM,KAAK,GAAI,MAAM,MAAM,KAAG,MAAmC,CAAC;AACzE,eAAO,MAAM,MAAM,GAAI,MAAM,MAAM,KAAG,MAAoC,CAAC;AAC3E,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,KAAG,MAAkC,CAAC;AACvE,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,KAAG,MAAkC,CAAC;AAMvE,eAAO,MAAM,QAAQ,GAAI,SAAS,MAAM,KAAG,IAE1C,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,KAAG,IAE5C,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,SAAS,MAAM,KAAG,IAE3C,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,KAAG,IAE5C,CAAC;AAMF,eAAO,MAAM,GAAG,GAAI,SAAS,MAAM,KAAG,KAGrC,CAAC;AAQF,qBAAa,OAAO;IAClB,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,OAAO,CAAM;IAErB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAe5B,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI7B,IAAI,IAAI,IAAI;IASZ,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK9B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAI5B;AAMD,eAAO,MAAM,MAAM,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,MAAM,CAW5D,CAAC;AAEF,eAAO,MAAM,OAAO,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,OAAO,CAG9D,CAAC;AAEF,eAAO,MAAM,UAAU,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/lib/cli.ts"],"names":[],"mappings":"AAKA,OAAO,sBAAsB,CAAC;AAiB9B,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,KAAG,MAAkC,CAAC;AACvE,eAAO,MAAM,GAAG,GAAI,MAAM,MAAM,KAAG,MAAiC,CAAC;AACrE,eAAO,MAAM,GAAG,GAAI,MAAM,MAAM,KAAG,MAAiC,CAAC;AACrE,eAAO,MAAM,KAAK,GAAI,MAAM,MAAM,KAAG,MAAmC,CAAC;AACzE,eAAO,MAAM,MAAM,GAAI,MAAM,MAAM,KAAG,MAAoC,CAAC;AAC3E,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,KAAG,MAAkC,CAAC;AACvE,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,KAAG,MAAkC,CAAC;AAMvE,eAAO,MAAM,QAAQ,GAAI,SAAS,MAAM,KAAG,IAE1C,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,KAAG,IAE5C,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,SAAS,MAAM,KAAG,IAE3C,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,KAAG,IAE5C,CAAC;AAMF,eAAO,MAAM,GAAG,GAAI,SAAS,MAAM,KAAG,KAGrC,CAAC;AAQF,qBAAa,OAAO;IAClB,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,OAAO,CAAM;IAErB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAe5B,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI7B,IAAI,IAAI,IAAI;IASZ,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK9B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAI5B;AAMD,eAAO,MAAM,MAAM,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,MAAM,CAW5D,CAAC;AAEF,eAAO,MAAM,OAAO,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,OAAO,CAG9D,CAAC;AAEF,eAAO,MAAM,UAAU,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,MAAM,CAoChE,CAAC;AAMF,eAAO,MAAM,UAAU,GAAU,MAAM,MAAM,KAAG,OAAO,CAAC,OAAO,CAI9D,CAAC;AAMF,eAAO,MAAM,YAAY,QAAO,MAG/B,CAAC;AAEF,eAAO,MAAM,aAAa,QAAO,MAEhC,CAAC;AAEF,eAAO,MAAM,eAAe,QAAa,OAAO,CAAC,IAAI,CAUpD,CAAC;AAMF,eAAO,MAAM,QAAQ,GAAI,SAAQ,MAAU,KAAG,MAM7C,CAAC;AAMF,eAAO,MAAM,aAAa,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,OAAO,CASpE,CAAC"}
|
package/esm/lib/cli.js
CHANGED
|
@@ -102,30 +102,46 @@ export const confirm = async (message) => {
|
|
|
102
102
|
return answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
|
|
103
103
|
};
|
|
104
104
|
export const readSecret = async (message) => {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
if (!dntShim.Deno.stdin.isTerminal) {
|
|
106
|
+
return await prompt(message);
|
|
107
|
+
}
|
|
108
|
+
const encoder = new TextEncoder();
|
|
109
|
+
const decoder = new TextDecoder();
|
|
110
|
+
await dntShim.Deno.stdout.write(encoder.encode(message));
|
|
111
|
+
let echoDisabled = false;
|
|
112
|
+
try {
|
|
113
|
+
const sttyOff = await new dntShim.Deno.Command("stty", {
|
|
114
|
+
args: ["-echo"],
|
|
115
|
+
stdin: "inherit",
|
|
116
|
+
stdout: "null",
|
|
117
|
+
stderr: "null",
|
|
118
|
+
}).output();
|
|
119
|
+
echoDisabled = sttyOff.success;
|
|
120
|
+
const buf = new Uint8Array(1024);
|
|
121
|
+
const n = await dntShim.Deno.stdin.read(buf);
|
|
122
|
+
if (n === null)
|
|
123
|
+
return "";
|
|
124
|
+
return decoder.decode(buf.subarray(0, n)).trim();
|
|
125
|
+
}
|
|
126
|
+
finally {
|
|
127
|
+
if (echoDisabled) {
|
|
128
|
+
await new dntShim.Deno.Command("stty", {
|
|
129
|
+
args: ["echo"],
|
|
130
|
+
stdin: "inherit",
|
|
131
|
+
stdout: "null",
|
|
132
|
+
stderr: "null",
|
|
133
|
+
}).output();
|
|
134
|
+
}
|
|
135
|
+
await dntShim.Deno.stdout.write(encoder.encode("\n"));
|
|
136
|
+
}
|
|
108
137
|
};
|
|
109
138
|
// =============================================================================
|
|
110
139
|
// File Utilities
|
|
111
140
|
// =============================================================================
|
|
112
141
|
export const fileExists = async (path) => {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
catch {
|
|
118
|
-
return false;
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
export const fileExistsSync = (path) => {
|
|
122
|
-
try {
|
|
123
|
-
dntShim.Deno.statSync(path);
|
|
124
|
-
return true;
|
|
125
|
-
}
|
|
126
|
-
catch {
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
142
|
+
return dntShim.Deno.stat(path)
|
|
143
|
+
.then(() => true)
|
|
144
|
+
.catch(() => false);
|
|
129
145
|
};
|
|
130
146
|
// =============================================================================
|
|
131
147
|
// Config Directory
|
|
@@ -142,8 +158,11 @@ export const ensureConfigDir = async () => {
|
|
|
142
158
|
try {
|
|
143
159
|
await dntShim.Deno.mkdir(dir, { recursive: true });
|
|
144
160
|
}
|
|
145
|
-
catch {
|
|
146
|
-
|
|
161
|
+
catch (error) {
|
|
162
|
+
if (error instanceof dntShim.Deno.errors.AlreadyExists) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
throw error;
|
|
147
166
|
}
|
|
148
167
|
};
|
|
149
168
|
// =============================================================================
|
|
@@ -151,11 +170,7 @@ export const ensureConfigDir = async () => {
|
|
|
151
170
|
// =============================================================================
|
|
152
171
|
export const randomId = (length = 6) => {
|
|
153
172
|
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
154
|
-
|
|
155
|
-
for (let i = 0; i < length; i++) {
|
|
156
|
-
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
157
|
-
}
|
|
158
|
-
return result;
|
|
173
|
+
return Array.from({ length }, () => chars[Math.floor(Math.random() * chars.length)]).join("");
|
|
159
174
|
};
|
|
160
175
|
// =============================================================================
|
|
161
176
|
// Command Exists Check
|
package/esm/lib/command.d.ts
CHANGED
|
@@ -1,54 +1,29 @@
|
|
|
1
1
|
import "../_dnt.polyfills.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
stdout: string;
|
|
6
|
-
stderr: string;
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Run a command and capture output.
|
|
10
|
-
*/
|
|
11
|
-
export declare const runCommand: (args: string[], options?: {
|
|
2
|
+
import { Result } from "./result.js";
|
|
3
|
+
export interface RunOptions {
|
|
4
|
+
interactive?: boolean;
|
|
12
5
|
cwd?: string;
|
|
13
6
|
env?: Record<string, string>;
|
|
14
|
-
stdin?: "inherit" | "null"
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Run a command while showing a spinner.
|
|
29
|
-
*/
|
|
30
|
-
export declare const runWithSpinner: (label: string, args: string[], options?: {
|
|
31
|
-
cwd?: string;
|
|
32
|
-
env?: Record<string, string>;
|
|
33
|
-
}) => Promise<CommandResult>;
|
|
34
|
-
/**
|
|
35
|
-
* Run a command with spinner and return simplified result.
|
|
36
|
-
*/
|
|
37
|
-
export declare const runQuiet: (label: string, args: string[], options?: {
|
|
38
|
-
cwd?: string;
|
|
39
|
-
env?: Record<string, string>;
|
|
40
|
-
}) => Promise<{
|
|
41
|
-
success: boolean;
|
|
42
|
-
output: string;
|
|
43
|
-
}>;
|
|
7
|
+
stdin?: "inherit" | "null";
|
|
8
|
+
}
|
|
9
|
+
export declare class CmdResult {
|
|
10
|
+
readonly code: number;
|
|
11
|
+
readonly stdout: string;
|
|
12
|
+
readonly stderr: string;
|
|
13
|
+
readonly ok: boolean;
|
|
14
|
+
constructor(code: number, stdout: string, stderr: string);
|
|
15
|
+
/** Parse stdout as JSON, returning Result<T>. */
|
|
16
|
+
json<T>(): Result<T>;
|
|
17
|
+
/** Merged stdout + stderr. */
|
|
18
|
+
get output(): string;
|
|
19
|
+
}
|
|
44
20
|
/**
|
|
45
|
-
* Run a command
|
|
21
|
+
* Run a command and capture output.
|
|
22
|
+
* When `interactive: true`, inherits all stdio (no capture).
|
|
46
23
|
*/
|
|
47
|
-
export declare const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
code: number;
|
|
53
|
-
}>;
|
|
24
|
+
export declare const runCommand: (args: string[], options?: RunOptions) => Promise<CmdResult>;
|
|
25
|
+
/** Run with spinner, return CmdResult. */
|
|
26
|
+
export declare const runQuiet: (label: string, args: string[], options?: RunOptions) => Promise<CmdResult>;
|
|
27
|
+
/** Run and parse stdout as JSON. */
|
|
28
|
+
export declare const runJson: <T>(args: string[], options?: RunOptions) => Promise<Result<T>>;
|
|
54
29
|
//# sourceMappingURL=command.d.ts.map
|
package/esm/lib/command.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/lib/command.ts"],"names":[],"mappings":"AAGA,OAAO,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/lib/command.ts"],"names":[],"mappings":"AAGA,OAAO,sBAAsB,CAAC;AAK9B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAMrC,MAAM,WAAW,UAAU;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;CAC5B;AAMD,qBAAa,SAAS;IAIlB,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM;IALzB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;gBAGV,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM;IAKzB,iDAAiD;IACjD,IAAI,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC;IAapB,8BAA8B;IAC9B,IAAI,MAAM,IAAI,MAAM,CAEnB;CACF;AAMD;;;GAGG;AACH,eAAO,MAAM,UAAU,GACrB,MAAM,MAAM,EAAE,EACd,UAAU,UAAU,KACnB,OAAO,CAAC,SAAS,CA2CnB,CAAC;AAMF,0CAA0C;AAC1C,eAAO,MAAM,QAAQ,GACnB,OAAO,MAAM,EACb,MAAM,MAAM,EAAE,EACd,UAAU,UAAU,KACnB,OAAO,CAAC,SAAS,CAOnB,CAAC;AAEF,oCAAoC;AACpC,eAAO,MAAM,OAAO,GAAI,CAAC,EACvB,MAAM,MAAM,EAAE,EACd,UAAU,UAAU,KACnB,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAuD,CAAC"}
|
package/esm/lib/command.js
CHANGED
|
@@ -4,24 +4,69 @@
|
|
|
4
4
|
import "../_dnt.polyfills.js";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
6
|
import { Spinner } from "./cli.js";
|
|
7
|
+
import { Result } from "./result.js";
|
|
8
|
+
// =============================================================================
|
|
9
|
+
// Command Result
|
|
10
|
+
// =============================================================================
|
|
11
|
+
export class CmdResult {
|
|
12
|
+
code;
|
|
13
|
+
stdout;
|
|
14
|
+
stderr;
|
|
15
|
+
ok;
|
|
16
|
+
constructor(code, stdout, stderr) {
|
|
17
|
+
this.code = code;
|
|
18
|
+
this.stdout = stdout;
|
|
19
|
+
this.stderr = stderr;
|
|
20
|
+
this.ok = code === 0;
|
|
21
|
+
}
|
|
22
|
+
/** Parse stdout as JSON, returning Result<T>. */
|
|
23
|
+
json() {
|
|
24
|
+
if (!this.ok) {
|
|
25
|
+
return Result.err(this.stderr || `Command failed with code ${this.code}`);
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
return Result.ok(JSON.parse(this.stdout));
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return Result.err(`Failed to parse JSON: ${this.stdout.slice(0, 100)}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Merged stdout + stderr. */
|
|
35
|
+
get output() {
|
|
36
|
+
return (this.stdout + this.stderr).trimEnd();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
7
39
|
// =============================================================================
|
|
8
40
|
// Run Command
|
|
9
41
|
// =============================================================================
|
|
10
42
|
/**
|
|
11
43
|
* Run a command and capture output.
|
|
44
|
+
* When `interactive: true`, inherits all stdio (no capture).
|
|
12
45
|
*/
|
|
13
46
|
export const runCommand = (args, options) => {
|
|
14
47
|
const [cmd, ...cmdArgs] = args;
|
|
48
|
+
const interactive = options?.interactive ?? false;
|
|
15
49
|
return new Promise((resolve) => {
|
|
16
50
|
const child = spawn(cmd, cmdArgs, {
|
|
17
51
|
cwd: options?.cwd,
|
|
18
52
|
env: options?.env ? { ...process.env, ...options.env } : undefined,
|
|
19
|
-
stdio:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
53
|
+
stdio: interactive
|
|
54
|
+
? "inherit"
|
|
55
|
+
: [
|
|
56
|
+
options?.stdin === "inherit" ? "inherit" : "ignore",
|
|
57
|
+
"pipe",
|
|
58
|
+
"pipe",
|
|
59
|
+
],
|
|
24
60
|
});
|
|
61
|
+
if (interactive) {
|
|
62
|
+
child.on("error", () => {
|
|
63
|
+
resolve(new CmdResult(-1, "", ""));
|
|
64
|
+
});
|
|
65
|
+
child.on("close", (code) => {
|
|
66
|
+
resolve(new CmdResult(code ?? 1, "", ""));
|
|
67
|
+
});
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
25
70
|
const stdout = [];
|
|
26
71
|
const stderr = [];
|
|
27
72
|
child.stdout.setEncoding("utf8");
|
|
@@ -29,98 +74,24 @@ export const runCommand = (args, options) => {
|
|
|
29
74
|
child.stdout.on("data", (chunk) => stdout.push(chunk));
|
|
30
75
|
child.stderr.on("data", (chunk) => stderr.push(chunk));
|
|
31
76
|
child.on("error", (error) => {
|
|
32
|
-
resolve(
|
|
33
|
-
success: false,
|
|
34
|
-
code: -1,
|
|
35
|
-
stdout: "",
|
|
36
|
-
stderr: error.message,
|
|
37
|
-
});
|
|
77
|
+
resolve(new CmdResult(-1, "", error.message));
|
|
38
78
|
});
|
|
39
79
|
child.on("close", (code) => {
|
|
40
|
-
resolve(
|
|
41
|
-
success: code === 0,
|
|
42
|
-
code: code ?? 1,
|
|
43
|
-
stdout: stdout.join(""),
|
|
44
|
-
stderr: stderr.join(""),
|
|
45
|
-
});
|
|
80
|
+
resolve(new CmdResult(code ?? 1, stdout.join(""), stderr.join("")));
|
|
46
81
|
});
|
|
47
82
|
});
|
|
48
83
|
};
|
|
49
84
|
// =============================================================================
|
|
50
|
-
//
|
|
51
|
-
// =============================================================================
|
|
52
|
-
/**
|
|
53
|
-
* Run a command that outputs JSON and parse it.
|
|
54
|
-
*/
|
|
55
|
-
export const runCommandJson = async (args, options) => {
|
|
56
|
-
const result = await runCommand(args, options);
|
|
57
|
-
if (!result.success) {
|
|
58
|
-
return {
|
|
59
|
-
success: false,
|
|
60
|
-
error: result.stderr || `Command failed with code ${result.code}`,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
try {
|
|
64
|
-
const data = JSON.parse(result.stdout);
|
|
65
|
-
return { success: true, data };
|
|
66
|
-
}
|
|
67
|
-
catch {
|
|
68
|
-
return {
|
|
69
|
-
success: false,
|
|
70
|
-
error: `Failed to parse JSON output: ${result.stdout.slice(0, 100)}`,
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
// =============================================================================
|
|
75
|
-
// Run with Spinner
|
|
85
|
+
// Wrappers
|
|
76
86
|
// =============================================================================
|
|
77
|
-
/**
|
|
78
|
-
|
|
79
|
-
*/
|
|
80
|
-
export const runWithSpinner = async (label, args, options) => {
|
|
87
|
+
/** Run with spinner, return CmdResult. */
|
|
88
|
+
export const runQuiet = (label, args, options) => {
|
|
81
89
|
const spinner = new Spinner();
|
|
82
90
|
spinner.start(label);
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
spinner.fail(label);
|
|
89
|
-
}
|
|
90
|
-
return result;
|
|
91
|
-
};
|
|
92
|
-
// =============================================================================
|
|
93
|
-
// Run Quiet
|
|
94
|
-
// =============================================================================
|
|
95
|
-
/**
|
|
96
|
-
* Run a command with spinner and return simplified result.
|
|
97
|
-
*/
|
|
98
|
-
export const runQuiet = async (label, args, options) => {
|
|
99
|
-
const result = await runWithSpinner(label, args, options);
|
|
100
|
-
return {
|
|
101
|
-
success: result.success,
|
|
102
|
-
output: result.stdout + result.stderr,
|
|
103
|
-
};
|
|
104
|
-
};
|
|
105
|
-
// =============================================================================
|
|
106
|
-
// Run Interactive
|
|
107
|
-
// =============================================================================
|
|
108
|
-
/**
|
|
109
|
-
* Run a command interactively (inherits stdio).
|
|
110
|
-
*/
|
|
111
|
-
export const runInteractive = (args, options) => {
|
|
112
|
-
const [cmd, ...cmdArgs] = args;
|
|
113
|
-
return new Promise((resolve) => {
|
|
114
|
-
const child = spawn(cmd, cmdArgs, {
|
|
115
|
-
cwd: options?.cwd,
|
|
116
|
-
env: options?.env ? { ...process.env, ...options.env } : undefined,
|
|
117
|
-
stdio: "inherit",
|
|
118
|
-
});
|
|
119
|
-
child.on("error", () => {
|
|
120
|
-
resolve({ success: false, code: -1 });
|
|
121
|
-
});
|
|
122
|
-
child.on("close", (code) => {
|
|
123
|
-
resolve({ success: (code ?? 1) === 0, code: code ?? 1 });
|
|
124
|
-
});
|
|
91
|
+
return runCommand(args, options).then((r) => {
|
|
92
|
+
r.ok ? spinner.success(label) : spinner.fail(label);
|
|
93
|
+
return r;
|
|
125
94
|
});
|
|
126
95
|
};
|
|
96
|
+
/** Run and parse stdout as JSON. */
|
|
97
|
+
export const runJson = (args, options) => runCommand(args, options).then((r) => r.json());
|
package/esm/lib/output.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export declare class Output<T extends Record<string, unknown>> {
|
|
|
12
12
|
constructor(jsonMode: boolean);
|
|
13
13
|
done(data: T): this;
|
|
14
14
|
fail(error: string, data?: Record<string, unknown>): this;
|
|
15
|
+
print(): void;
|
|
15
16
|
ok(text: string): this;
|
|
16
17
|
err(text: string): this;
|
|
17
18
|
info(text: string): this;
|
|
@@ -25,7 +26,6 @@ export declare class Output<T extends Record<string, unknown>> {
|
|
|
25
26
|
fail(msg: string): void;
|
|
26
27
|
stop(): void;
|
|
27
28
|
};
|
|
28
|
-
print(): void;
|
|
29
29
|
die(message: string): never;
|
|
30
30
|
isJson(): boolean;
|
|
31
31
|
}
|
package/esm/lib/output.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/lib/output.ts"],"names":[],"mappings":"AAGA,OAAO,sBAAsB,CAAC;AAmB9B,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG,CAAC,CAAC;AAChD,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAMvD,qBAAa,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACnD,OAAO,CAAC,MAAM,CAGE;IAChB,OAAO,CAAC,QAAQ,CAAU;gBAEd,QAAQ,EAAE,OAAO;IAS7B,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAMnB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/lib/output.ts"],"names":[],"mappings":"AAGA,OAAO,sBAAsB,CAAC;AAmB9B,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG,CAAC,CAAC;AAChD,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAMvD,qBAAa,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACnD,OAAO,CAAC,MAAM,CAGE;IAChB,OAAO,CAAC,QAAQ,CAAU;gBAEd,QAAQ,EAAE,OAAO;IAS7B,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAMnB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAKzD,KAAK,IAAI,IAAI;IAUb,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKtB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKvB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKxB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKxB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKxB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKvB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK1B,KAAK,IAAI,IAAI;IAKb,OAAO,CACL,OAAO,EAAE,MAAM,GACd;QAAE,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,IAAI,IAAI,CAAA;KAAE;IAiBxE,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK;IAS3B,MAAM,IAAI,OAAO;CAGlB;AAMD,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5D,QAAQ,EAAE,OAAO,GAChB,MAAM,CAAC,CAAC,CAAC,CAEX"}
|
package/esm/lib/output.js
CHANGED
|
@@ -26,6 +26,11 @@ export class Output {
|
|
|
26
26
|
this.result = { ok: false, error, ...data };
|
|
27
27
|
return this;
|
|
28
28
|
}
|
|
29
|
+
print() {
|
|
30
|
+
if (this.jsonMode && this.result) {
|
|
31
|
+
console.log(JSON.stringify(this.result, null, 2));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
29
34
|
// ===========================================================================
|
|
30
35
|
// Human-Mode Output (no-op in JSON mode)
|
|
31
36
|
// ===========================================================================
|
|
@@ -69,7 +74,6 @@ export class Output {
|
|
|
69
74
|
console.log();
|
|
70
75
|
return this;
|
|
71
76
|
}
|
|
72
|
-
// JSON-aware spinner — no-op in JSON mode
|
|
73
77
|
spinner(message) {
|
|
74
78
|
if (this.jsonMode) {
|
|
75
79
|
return { success: () => { }, fail: () => { }, stop: () => { } };
|
|
@@ -85,13 +89,6 @@ export class Output {
|
|
|
85
89
|
// ===========================================================================
|
|
86
90
|
// Terminal Output
|
|
87
91
|
// ===========================================================================
|
|
88
|
-
// Print result as JSON (no-op in human mode)
|
|
89
|
-
print() {
|
|
90
|
-
if (this.jsonMode && this.result) {
|
|
91
|
-
console.log(JSON.stringify(this.result, null, 2));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
// Fatal error — outputs { ok: false, error } and exits
|
|
95
92
|
die(message) {
|
|
96
93
|
if (this.jsonMode) {
|
|
97
94
|
console.log(JSON.stringify({ ok: false, error: message }, null, 2));
|
|
@@ -101,7 +98,6 @@ export class Output {
|
|
|
101
98
|
}
|
|
102
99
|
dntShim.Deno.exit(1);
|
|
103
100
|
}
|
|
104
|
-
// Check if in JSON mode
|
|
105
101
|
isJson() {
|
|
106
102
|
return this.jsonMode;
|
|
107
103
|
}
|
package/esm/lib/result.d.ts
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import "../_dnt.polyfills.js";
|
|
2
|
+
export declare class Result<T> {
|
|
3
|
+
readonly ok: boolean;
|
|
4
|
+
private readonly _value;
|
|
5
|
+
private readonly _error;
|
|
6
|
+
private constructor();
|
|
7
|
+
static ok<T>(value: T): Result<T>;
|
|
8
|
+
static err<T = never>(error: string): Result<T>;
|
|
9
|
+
get value(): T | undefined;
|
|
10
|
+
get error(): string | undefined;
|
|
11
|
+
map<U>(fn: (value: T) => U): Result<U>;
|
|
12
|
+
flatMap<U>(fn: (value: T) => Result<U>): Result<U>;
|
|
13
|
+
unwrap(): T;
|
|
14
|
+
unwrapOr(fallback: T): T;
|
|
15
|
+
match<U>(cases: {
|
|
16
|
+
ok: (value: T) => U;
|
|
17
|
+
err: (error: string) => U;
|
|
18
|
+
}): U;
|
|
19
|
+
}
|
|
8
20
|
//# sourceMappingURL=result.d.ts.map
|
package/esm/lib/result.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/lib/result.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/lib/result.ts"],"names":[],"mappings":"AAGA,OAAO,sBAAsB,CAAC;AAG9B,qBAAa,MAAM,CAAC,CAAC;IAEjB,QAAQ,CAAC,EAAE,EAAE,OAAO;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHzB,OAAO;IAMP,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IAIjC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;IAI/C,IAAI,KAAK,IAAI,CAAC,GAAG,SAAS,CAEzB;IAED,IAAI,KAAK,IAAI,MAAM,GAAG,SAAS,CAE9B;IAED,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IAKtC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IAKlD,MAAM,IAAI,CAAC;IAKX,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC;IAIxB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE;QAAE,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;QAAC,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,CAAC,CAAA;KAAE,GAAG,CAAC;CAGvE"}
|
package/esm/lib/result.js
CHANGED
|
@@ -1 +1,47 @@
|
|
|
1
|
-
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Result<T> — Shared Success/Failure Type
|
|
3
|
+
// =============================================================================
|
|
4
|
+
import "../_dnt.polyfills.js";
|
|
5
|
+
export class Result {
|
|
6
|
+
ok;
|
|
7
|
+
_value;
|
|
8
|
+
_error;
|
|
9
|
+
constructor(ok, _value, _error) {
|
|
10
|
+
this.ok = ok;
|
|
11
|
+
this._value = _value;
|
|
12
|
+
this._error = _error;
|
|
13
|
+
}
|
|
14
|
+
static ok(value) {
|
|
15
|
+
return new Result(true, value, undefined);
|
|
16
|
+
}
|
|
17
|
+
static err(error) {
|
|
18
|
+
return new Result(false, undefined, error);
|
|
19
|
+
}
|
|
20
|
+
get value() {
|
|
21
|
+
return this._value;
|
|
22
|
+
}
|
|
23
|
+
get error() {
|
|
24
|
+
return this._error;
|
|
25
|
+
}
|
|
26
|
+
map(fn) {
|
|
27
|
+
if (this.ok)
|
|
28
|
+
return Result.ok(fn(this._value));
|
|
29
|
+
return Result.err(this._error);
|
|
30
|
+
}
|
|
31
|
+
flatMap(fn) {
|
|
32
|
+
if (this.ok)
|
|
33
|
+
return fn(this._value);
|
|
34
|
+
return Result.err(this._error);
|
|
35
|
+
}
|
|
36
|
+
unwrap() {
|
|
37
|
+
if (this.ok)
|
|
38
|
+
return this._value;
|
|
39
|
+
throw new Error(this._error);
|
|
40
|
+
}
|
|
41
|
+
unwrapOr(fallback) {
|
|
42
|
+
return this.ok ? this._value : fallback;
|
|
43
|
+
}
|
|
44
|
+
match(cases) {
|
|
45
|
+
return this.ok ? cases.ok(this._value) : cases.err(this._error);
|
|
46
|
+
}
|
|
47
|
+
}
|