@baseworks/cli 0.2.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/dist/args.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Lightweight arg/flag parser for Node CLI binaries.
3
+ *
4
+ * Supports:
5
+ * --flag → { flag: true }
6
+ * --flag value → { flag: 'value' }
7
+ * --flag=value → { flag: 'value' }
8
+ * positional args → args[]
9
+ *
10
+ * Usage:
11
+ * const { args, flags } = parseFlags(process.argv.slice(2));
12
+ * if (flags.json) { ... }
13
+ * const [ws, proj] = args;
14
+ */
15
+ interface ParsedArgs {
16
+ /** Positional (non-flag) arguments in order. */
17
+ args: string[];
18
+ /** Parsed flags. Values are string if the flag had a value, true if bare. */
19
+ flags: Record<string, string | boolean>;
20
+ }
21
+ declare function parseFlags(argv: string[]): ParsedArgs;
22
+ /** Returns true if --json or -j flag is present in process.argv. */
23
+ declare function isJsonMode(argv?: string[]): boolean;
24
+ /**
25
+ * Extract a named flag value from argv.
26
+ * getFlag(process.argv, '--public-key') → string | undefined
27
+ */
28
+ declare function getFlag(argv: string[], flag: string): string | undefined;
29
+
30
+ export { type ParsedArgs, getFlag, isJsonMode, parseFlags };
package/dist/args.js ADDED
@@ -0,0 +1,10 @@
1
+ import {
2
+ getFlag,
3
+ isJsonMode,
4
+ parseFlags
5
+ } from "./chunk-H4M2NPA2.js";
6
+ export {
7
+ getFlag,
8
+ isJsonMode,
9
+ parseFlags
10
+ };
@@ -0,0 +1,26 @@
1
+ import {
2
+ clr
3
+ } from "./chunk-C2YZKMJ7.js";
4
+
5
+ // src/tree.ts
6
+ function tree(nodes, prefix = "") {
7
+ for (let i = 0; i < nodes.length; i++) {
8
+ const node = nodes[i];
9
+ const last = i === nodes.length - 1;
10
+ const isRoot = prefix === "";
11
+ const connector = isRoot ? "" : last ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
12
+ const childPfx = isRoot ? last ? " " : "\u2502 " : prefix + (last ? " " : "\u2502 ");
13
+ const badge = node.badge ? node.badge + " " : "";
14
+ const meta = node.meta ? ` ${clr.dim}${node.meta}${clr.reset}` : "";
15
+ console.log(
16
+ `${clr.dim}${prefix}${connector}${clr.reset}${badge}${clr.bold}${node.label}${clr.reset}${meta}`
17
+ );
18
+ if (node.children?.length) {
19
+ tree(node.children, childPfx);
20
+ }
21
+ }
22
+ }
23
+
24
+ export {
25
+ tree
26
+ };
@@ -0,0 +1,17 @@
1
+ // src/config-loader.ts
2
+ function resolveToken(cfg, opts = {}) {
3
+ return cfg.token ?? (opts.env ? process.env[opts.env] : void 0);
4
+ }
5
+ function resolveApiBase(cfg, opts = {}) {
6
+ const raw = cfg.apiBase ?? (opts.env ? process.env[opts.env] : void 0) ?? opts.default ?? "";
7
+ return raw.replace(/\/$/, "");
8
+ }
9
+ function resolveField(cfg, key, opts = {}) {
10
+ return cfg[key] ?? (opts.env ? process.env[opts.env] : void 0) ?? opts.default;
11
+ }
12
+
13
+ export {
14
+ resolveToken,
15
+ resolveApiBase,
16
+ resolveField
17
+ };
@@ -0,0 +1,185 @@
1
+ // src/display.ts
2
+ import { createInterface } from "readline";
3
+ var isTTY = typeof process !== "undefined" && process.stdout?.isTTY;
4
+ var clr = {
5
+ reset: isTTY ? "\x1B[0m" : "",
6
+ bold: isTTY ? "\x1B[1m" : "",
7
+ dim: isTTY ? "\x1B[2m" : "",
8
+ green: isTTY ? "\x1B[32m" : "",
9
+ yellow: isTTY ? "\x1B[33m" : "",
10
+ cyan: isTTY ? "\x1B[36m" : "",
11
+ red: isTTY ? "\x1B[31m" : ""
12
+ };
13
+ function truncateId(id, n = 8) {
14
+ if (!id || id.length <= n + 1) return id;
15
+ const isUuid = /^[0-9a-f]{8}-/i.test(id);
16
+ return isUuid ? id.slice(0, n) + "\u2026" : id;
17
+ }
18
+ function statusColor(status) {
19
+ const s = status.toLowerCase();
20
+ if (["active", "succeeded", "paid", "completed"].includes(s))
21
+ return `${clr.green}${status}${clr.reset}`;
22
+ if (["canceled", "cancelled", "failed", "expired", "revoked"].includes(s))
23
+ return `${clr.dim}${status}${clr.reset}`;
24
+ if (["trialing", "past_due", "pending", "draft"].includes(s))
25
+ return `${clr.yellow}${status}${clr.reset}`;
26
+ return status;
27
+ }
28
+ function summary(text) {
29
+ console.log(` ${clr.dim}${text}${clr.reset}`);
30
+ }
31
+ function visibleLength(str) {
32
+ return str.replace(/\x1b\[[0-9;]*m/g, "").length;
33
+ }
34
+ function padEnd(str, width) {
35
+ return str + " ".repeat(Math.max(0, width - visibleLength(str)));
36
+ }
37
+ function table(rows, cols, opts = {}) {
38
+ const isWide = opts.wide ?? (process.argv.includes("--detail") || process.argv.includes("-d") || process.argv.includes("-o") && process.argv[process.argv.indexOf("-o") + 1] === "wide" || process.argv.includes("--output") && process.argv[process.argv.indexOf("--output") + 1] === "wide");
39
+ const visibleCols = cols.filter((c) => !c.wide && !c.detail || isWide);
40
+ if (!rows.length) {
41
+ const msg = opts.emptyHint ?? "(none)";
42
+ console.log(` ${clr.dim}${msg}${clr.reset}`);
43
+ return;
44
+ }
45
+ const widths = visibleCols.map((col, i) => {
46
+ const labelLen = col.label.length;
47
+ const maxVal = Math.max(...rows.map((r) => visibleLength(String(col.fmt ? col.fmt(r[col.key], r) : r[col.key] ?? "\u2014"))));
48
+ return Math.max(labelLen, maxVal, i);
49
+ });
50
+ console.log("");
51
+ const header = visibleCols.map(
52
+ (col, i) => padEnd(`${clr.bold}${clr.dim}${col.label}${clr.reset}`, widths[i] ?? col.label.length)
53
+ ).join(" ");
54
+ console.log(" " + header);
55
+ console.log(" " + widths.map((w) => "\u2500".repeat(w)).join(" "));
56
+ for (const row of rows) {
57
+ const line = visibleCols.map((col, i) => {
58
+ const val = col.fmt ? col.fmt(row[col.key], row) : row[col.key] ?? "\u2014";
59
+ return padEnd(String(val), widths[i] ?? 0);
60
+ }).join(" ");
61
+ console.log(" " + line);
62
+ }
63
+ console.log("");
64
+ }
65
+ function kv(pairs) {
66
+ const w = Math.max(...pairs.map(([k]) => k.length));
67
+ for (const [k, v] of pairs) {
68
+ console.log(` ${clr.dim}${k.padEnd(w)}${clr.reset} ${v}`);
69
+ }
70
+ }
71
+ function success(msg) {
72
+ console.log(`${clr.green}\u2713${clr.reset} ${msg}`);
73
+ }
74
+ function warn(msg) {
75
+ console.warn(`${clr.yellow}\u26A0${clr.reset} ${msg}`);
76
+ }
77
+ function fatal(msg) {
78
+ console.error(`${clr.red}error:${clr.reset} ${msg}`);
79
+ process.exit(1);
80
+ throw new Error(msg);
81
+ }
82
+ function prompt(question) {
83
+ return new Promise((resolve) => {
84
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
85
+ rl.question(question, (ans) => {
86
+ rl.close();
87
+ resolve(ans.trim());
88
+ });
89
+ });
90
+ }
91
+ function helpFor(cmdName, args, flags, helpMap) {
92
+ if (!flags["help"] && !flags["h"]) return false;
93
+ const key = args.join(" ").trim();
94
+ const text = (key && helpMap[key]) ?? helpMap[""] ?? null;
95
+ if (text) {
96
+ console.log(text);
97
+ } else {
98
+ const lines = Object.entries(helpMap).filter(([k]) => k !== "").map(([k, v]) => ` ${cmdName} ${k.padEnd(28)}${v.split("\n")[0]}`);
99
+ console.log(`
100
+ ${clr.bold}${cmdName}${clr.reset}
101
+
102
+ ${lines.join("\n")}
103
+ `);
104
+ }
105
+ return true;
106
+ }
107
+ function printOrJson(data, textFn, argv = process.argv) {
108
+ if (argv.includes("--json") || argv.includes("-j")) {
109
+ console.log(JSON.stringify(data, null, 2));
110
+ } else {
111
+ textFn();
112
+ }
113
+ }
114
+ function printOutput(data, format, renderFn, codeKey) {
115
+ const fmt = format ?? "table";
116
+ switch (fmt) {
117
+ case "json":
118
+ console.log(JSON.stringify(data, null, 2));
119
+ break;
120
+ case "yaml": {
121
+ const toYaml = (v, indent = 0) => {
122
+ const pad = " ".repeat(indent);
123
+ if (v === null || v === void 0) return "null";
124
+ if (typeof v === "string") return /[:\n#{}[\],&*?|<>=!%@`]/.test(v) ? `"${v.replace(/"/g, '\\"')}"` : v;
125
+ if (typeof v === "number" || typeof v === "boolean") return String(v);
126
+ if (Array.isArray(v)) {
127
+ if (v.length === 0) return "[]";
128
+ return v.map((item) => `${pad}- ${toYaml(item, indent + 2).trimStart()}`).join("\n");
129
+ }
130
+ if (typeof v === "object") {
131
+ return Object.entries(v).map(([k, val]) => {
132
+ const rendered = toYaml(val, indent + 2);
133
+ return typeof val === "object" && val !== null && !Array.isArray(val) ? `${pad}${k}:
134
+ ${rendered}` : `${pad}${k}: ${rendered}`;
135
+ }).join("\n");
136
+ }
137
+ return String(v);
138
+ };
139
+ console.log(toYaml(data));
140
+ break;
141
+ }
142
+ case "code": {
143
+ const items = Array.isArray(data) ? data : [data];
144
+ for (const item of items) {
145
+ let code;
146
+ if (typeof codeKey === "function") {
147
+ code = codeKey(item);
148
+ } else if (codeKey && item[codeKey] != null) {
149
+ code = String(item[codeKey]);
150
+ } else {
151
+ code = String(item["slug"] ?? item["code"] ?? item["short_id"] ?? item["id"] ?? "");
152
+ }
153
+ if (code) console.log(code);
154
+ }
155
+ break;
156
+ }
157
+ case "wide":
158
+ renderFn(true);
159
+ break;
160
+ case "table":
161
+ default:
162
+ renderFn(false);
163
+ break;
164
+ }
165
+ }
166
+ function outputOption() {
167
+ return ["-o, --output <format>", "Output format: table|wide|json|yaml|code", "table"];
168
+ }
169
+
170
+ export {
171
+ clr,
172
+ truncateId,
173
+ statusColor,
174
+ summary,
175
+ table,
176
+ kv,
177
+ success,
178
+ warn,
179
+ fatal,
180
+ prompt,
181
+ helpFor,
182
+ printOrJson,
183
+ printOutput,
184
+ outputOption
185
+ };
@@ -0,0 +1,46 @@
1
+ // src/args.ts
2
+ function parseFlags(argv) {
3
+ const args = [];
4
+ const flags = {};
5
+ let i = 0;
6
+ while (i < argv.length) {
7
+ const token = argv[i];
8
+ if (token.startsWith("--")) {
9
+ const eqIdx = token.indexOf("=");
10
+ if (eqIdx !== -1) {
11
+ const key = token.slice(2, eqIdx);
12
+ const val = token.slice(eqIdx + 1);
13
+ flags[key] = val;
14
+ } else {
15
+ const key = token.slice(2);
16
+ const next = argv[i + 1];
17
+ if (next !== void 0 && !next.startsWith("--")) {
18
+ flags[key] = next;
19
+ i++;
20
+ } else {
21
+ flags[key] = true;
22
+ }
23
+ }
24
+ } else if (token.startsWith("-") && token.length === 2) {
25
+ flags[token.slice(1)] = true;
26
+ } else {
27
+ args.push(token);
28
+ }
29
+ i++;
30
+ }
31
+ return { args, flags };
32
+ }
33
+ function isJsonMode(argv = process.argv) {
34
+ return argv.includes("--json") || argv.includes("-j");
35
+ }
36
+ function getFlag(argv, flag) {
37
+ const i = argv.indexOf(flag);
38
+ if (i === -1) return void 0;
39
+ return argv[i + 1];
40
+ }
41
+
42
+ export {
43
+ parseFlags,
44
+ isJsonMode,
45
+ getFlag
46
+ };
@@ -0,0 +1,40 @@
1
+ import {
2
+ clr
3
+ } from "./chunk-C2YZKMJ7.js";
4
+
5
+ // src/fmt.ts
6
+ function fmtDate(val) {
7
+ if (val === null || val === void 0) return `${clr.dim}\u2014${clr.reset}`;
8
+ const d = typeof val === "number" ? new Date(val) : new Date(val);
9
+ if (isNaN(d.getTime())) return `${clr.dim}\u2014${clr.reset}`;
10
+ return `${clr.dim}${d.toISOString().slice(0, 10)}${clr.reset}`;
11
+ }
12
+ function fmtRole(role) {
13
+ if (role === "owner") return `${clr.cyan}owner${clr.reset}`;
14
+ if (role === "admin") return `${clr.yellow}admin${clr.reset}`;
15
+ if (role === "member") return "member";
16
+ return `${clr.dim}${role ?? "\u2014"}${clr.reset}`;
17
+ }
18
+ function fmtStatus(revokedAt) {
19
+ return revokedAt ? `${clr.dim}revoked${clr.reset}` : `${clr.green}active${clr.reset}`;
20
+ }
21
+ function fmtBool(val) {
22
+ return val ? `${clr.green}yes${clr.reset}` : `${clr.dim}no${clr.reset}`;
23
+ }
24
+ function fmtCount(n) {
25
+ if (!n) return `${clr.dim}0${clr.reset}`;
26
+ return String(n);
27
+ }
28
+ function fmtId(id) {
29
+ if (!id) return `${clr.dim}\u2014${clr.reset}`;
30
+ return `${clr.dim}${id}${clr.reset}`;
31
+ }
32
+
33
+ export {
34
+ fmtDate,
35
+ fmtRole,
36
+ fmtStatus,
37
+ fmtBool,
38
+ fmtCount,
39
+ fmtId
40
+ };
@@ -0,0 +1,98 @@
1
+ import {
2
+ confirmDestructive,
3
+ requiresContext,
4
+ requiresToken
5
+ } from "./chunk-TSVJD4R6.js";
6
+ import {
7
+ parseFlags
8
+ } from "./chunk-H4M2NPA2.js";
9
+ import {
10
+ fatal
11
+ } from "./chunk-C2YZKMJ7.js";
12
+ import {
13
+ createApiClient
14
+ } from "./chunk-XQGLG3X3.js";
15
+
16
+ // src/runner.ts
17
+ function createCliRunner(config) {
18
+ const allCommands = {};
19
+ const allAliases = {};
20
+ const helpSections = [];
21
+ let activeHooks = {};
22
+ return {
23
+ register(plugin) {
24
+ for (const [name, cmd] of Object.entries(plugin.commands)) {
25
+ allCommands[name] = cmd;
26
+ }
27
+ for (const [alias, target] of Object.entries(plugin.aliases ?? {})) {
28
+ allAliases[alias] = target;
29
+ }
30
+ if (plugin.helpText) helpSections.push(plugin.helpText);
31
+ },
32
+ hooks(h) {
33
+ activeHooks = { ...activeHooks, ...h };
34
+ },
35
+ async run(argv) {
36
+ const { args: topArgs, flags: topFlags } = parseFlags(argv);
37
+ if (topFlags["version"] || topFlags["v"]) {
38
+ return;
39
+ }
40
+ const rawCmd = topArgs[0];
41
+ const globalHelp = !rawCmd || argv[0] === "--help" || argv[0] === "-h";
42
+ if (globalHelp) {
43
+ console.log(helpSections.join("\n"));
44
+ return;
45
+ }
46
+ const cmdName = allAliases[rawCmd] ?? rawCmd;
47
+ const cmd = allCommands[cmdName];
48
+ if (!cmd) {
49
+ fatal(`Unknown command: ${rawCmd}. Run with --help for usage.`);
50
+ }
51
+ const rawIdx = argv.indexOf(rawCmd);
52
+ const restArgv = argv.slice(rawIdx + 1);
53
+ const { args, flags } = parseFlags(restArgv);
54
+ const deps = {
55
+ argv: restArgv,
56
+ args,
57
+ flags,
58
+ http: createApiClient(config.getToken, config.getApiBase),
59
+ ctx: config.ctx,
60
+ appBase: config.appBase,
61
+ token: config.getToken()
62
+ };
63
+ await activeHooks.beforeCommand?.(cmdName, deps);
64
+ const t0 = Date.now();
65
+ try {
66
+ await executeCommand(cmd, deps);
67
+ await activeHooks.afterCommand?.(cmdName, deps, Date.now() - t0);
68
+ } catch (e) {
69
+ const err = e instanceof Error ? e : new Error(String(e));
70
+ if (activeHooks.onError) {
71
+ await activeHooks.onError(cmdName, err, deps);
72
+ } else {
73
+ fatal(err.message);
74
+ }
75
+ }
76
+ }
77
+ };
78
+ }
79
+ async function executeCommand(cmd, deps) {
80
+ const chain = [];
81
+ if (cmd.requiresToken !== false) chain.push(requiresToken());
82
+ if (cmd.requiresContext) chain.push(requiresContext());
83
+ if (cmd.confirm) chain.push(confirmDestructive(cmd.confirm));
84
+ if (cmd.middleware?.length) chain.push(...cmd.middleware);
85
+ let i = 0;
86
+ const next = async () => {
87
+ if (i < chain.length) {
88
+ await chain[i++](deps, next);
89
+ } else {
90
+ await cmd.fn(deps);
91
+ }
92
+ };
93
+ await next();
94
+ }
95
+
96
+ export {
97
+ createCliRunner
98
+ };
@@ -0,0 +1,51 @@
1
+ import {
2
+ fatal,
3
+ prompt,
4
+ warn
5
+ } from "./chunk-C2YZKMJ7.js";
6
+
7
+ // src/middleware.ts
8
+ function requiresToken() {
9
+ return async (deps, next) => {
10
+ if (!deps.token) {
11
+ fatal("No API token found. Run: login");
12
+ }
13
+ await next();
14
+ };
15
+ }
16
+ function requiresContext() {
17
+ return async (deps, next) => {
18
+ const ctx = deps.ctx.getContext();
19
+ if (!ctx) {
20
+ fatal("No active context. Set one with: use <org>");
21
+ }
22
+ deps.context = ctx;
23
+ await next();
24
+ };
25
+ }
26
+ function confirmDestructive(message) {
27
+ return async (deps, next) => {
28
+ if (deps.flags["yes"] || deps.flags["y"]) {
29
+ await next();
30
+ return;
31
+ }
32
+ const isTTY = Boolean(process.stdin.isTTY);
33
+ if (!isTTY) {
34
+ fatal(`Destructive operation requires confirmation. Re-run with --yes to proceed.
35
+ ${message}`);
36
+ }
37
+ warn(message);
38
+ const answer = await prompt("Continue? (y/N) ");
39
+ if (answer.toLowerCase() !== "y") {
40
+ console.log("Aborted.");
41
+ process.exit(0);
42
+ }
43
+ await next();
44
+ };
45
+ }
46
+
47
+ export {
48
+ requiresToken,
49
+ requiresContext,
50
+ confirmDestructive
51
+ };
@@ -0,0 +1,54 @@
1
+ // src/client.ts
2
+ var ApiError = class extends Error {
3
+ constructor(status, code, message) {
4
+ super(message);
5
+ this.status = status;
6
+ this.code = code;
7
+ }
8
+ };
9
+ function createApiClient(getToken, getApiBase, getExtraHeaders) {
10
+ async function api(method, path, body, extra = {}) {
11
+ const token = getToken();
12
+ const base = getApiBase().replace(/\/$/, "");
13
+ const headers = {
14
+ ...token ? { Authorization: `Bearer ${token}` } : {},
15
+ ...body !== void 0 ? { "Content-Type": "application/json" } : {},
16
+ ...getExtraHeaders ? getExtraHeaders() : {},
17
+ ...extra
18
+ // per-call headers override defaults
19
+ };
20
+ const res = await fetch(`${base}${path}`, {
21
+ method,
22
+ headers,
23
+ body: body !== void 0 ? JSON.stringify(body) : void 0
24
+ });
25
+ if (res.status === 204) return null;
26
+ const text = await res.text();
27
+ let data;
28
+ try {
29
+ data = JSON.parse(text);
30
+ } catch {
31
+ if (!res.ok) throw new ApiError(res.status, "parse_error", `${res.status}: ${text}`);
32
+ return text;
33
+ }
34
+ if (!res.ok) {
35
+ const err = data;
36
+ const code = err?.error?.code ?? "unknown";
37
+ const msg = err?.error?.message ?? res.statusText;
38
+ throw new ApiError(res.status, code, `${res.status} ${code}: ${msg}`);
39
+ }
40
+ return data;
41
+ }
42
+ return {
43
+ api,
44
+ get: (path, h) => api("GET", path, void 0, h),
45
+ post: (path, body, h) => api("POST", path, body, h),
46
+ patch: (path, body, h) => api("PATCH", path, body, h),
47
+ del: (path, h) => api("DELETE", path, void 0, h)
48
+ };
49
+ }
50
+
51
+ export {
52
+ ApiError,
53
+ createApiClient
54
+ };
@@ -0,0 +1,59 @@
1
+ // src/context.ts
2
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
3
+ import { homedir } from "os";
4
+ import { join } from "path";
5
+ function createContextManager(appName) {
6
+ const globalDir = join(homedir(), `.${appName}`);
7
+ const globalPath = join(globalDir, "config.json");
8
+ function resolveActivePath() {
9
+ const localDir = join(process.cwd(), `.${appName}`);
10
+ const localPath = join(localDir, "config.json");
11
+ const isLocal = existsSync(localPath) || existsSync(localDir);
12
+ return isLocal ? { cfgPath: localPath, cfgDir: localDir, isLocal: true } : { cfgPath: globalPath, cfgDir: globalDir, isLocal: false };
13
+ }
14
+ function resolveReadPath() {
15
+ return resolveActivePath().cfgPath;
16
+ }
17
+ function resolveWritePath() {
18
+ const { cfgPath, cfgDir } = resolveActivePath();
19
+ return { cfgPath, cfgDir };
20
+ }
21
+ function loadConfig() {
22
+ const cfgPath = resolveReadPath();
23
+ if (!existsSync(cfgPath)) return {};
24
+ try {
25
+ return JSON.parse(readFileSync(cfgPath, "utf8"));
26
+ } catch {
27
+ return {};
28
+ }
29
+ }
30
+ function saveConfig(cfg) {
31
+ const { cfgPath, cfgDir } = resolveWritePath();
32
+ mkdirSync(cfgDir, { recursive: true });
33
+ writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + "\n");
34
+ }
35
+ return {
36
+ get configPath() {
37
+ return resolveWritePath().cfgPath;
38
+ },
39
+ loadConfig,
40
+ saveConfig,
41
+ getContext() {
42
+ return loadConfig().context;
43
+ },
44
+ setContext(parts) {
45
+ const cfg = loadConfig();
46
+ cfg.context = { ...cfg.context ?? {}, ...parts };
47
+ saveConfig(cfg);
48
+ },
49
+ clearContext() {
50
+ const cfg = loadConfig();
51
+ delete cfg.context;
52
+ saveConfig(cfg);
53
+ }
54
+ };
55
+ }
56
+
57
+ export {
58
+ createContextManager
59
+ };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Generic HTTP client factory for Node CLI binaries.
3
+ *
4
+ * Usage:
5
+ * const { get, post, patch, del } = createApiClient(
6
+ * () => cfg.token ?? process.env.MY_TOKEN,
7
+ * () => cfg.apiBase ?? 'https://api.example.com',
8
+ * );
9
+ */
10
+ interface ApiClient {
11
+ api<T>(method: string, path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
12
+ get<T>(path: string, headers?: Record<string, string>): Promise<T>;
13
+ post<T>(path: string, body: unknown, headers?: Record<string, string>): Promise<T>;
14
+ patch<T>(path: string, body: unknown, headers?: Record<string, string>): Promise<T>;
15
+ del<T>(path: string, headers?: Record<string, string>): Promise<T>;
16
+ }
17
+ declare class ApiError extends Error {
18
+ readonly status: number;
19
+ readonly code: string;
20
+ constructor(status: number, code: string, message: string);
21
+ }
22
+ declare function createApiClient(getToken: () => string | undefined, getApiBase: () => string, getExtraHeaders?: () => Record<string, string>): ApiClient;
23
+
24
+ export { type ApiClient, ApiError, createApiClient };
package/dist/client.js ADDED
@@ -0,0 +1,8 @@
1
+ import {
2
+ ApiError,
3
+ createApiClient
4
+ } from "./chunk-XQGLG3X3.js";
5
+ export {
6
+ ApiError,
7
+ createApiClient
8
+ };