@mushi-mushi/cli 0.18.2 → 0.20.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/version.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  MUSHI_CLI_VERSION
3
- } from "./chunk-E4IZPV6D.js";
3
+ } from "./chunk-6LM2KW4S.js";
4
4
  export {
5
5
  MUSHI_CLI_VERSION
6
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mushi-mushi/cli",
3
- "version": "0.18.2",
3
+ "version": "0.20.0",
4
4
  "license": "MIT",
5
5
  "description": "CLI for Mushi Mushi — `mushi init` wizard installs the right SDK for your framework, plus report triage and pipeline health commands",
6
6
  "bin": {
@@ -1,313 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- CLOUD_API_ENDPOINT
4
- } from "./chunk-LDPFTQLE.js";
5
-
6
- // src/config.ts
7
- import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync } from "fs";
8
- import { homedir } from "os";
9
- import { dirname, join } from "path";
10
- var SECURE_FILE_MODE = 384;
11
- var SECURE_DIR_MODE = 448;
12
- function resolveXdgConfigPath() {
13
- const xdg = process.env["XDG_CONFIG_HOME"];
14
- if (xdg && xdg.length > 0) {
15
- return join(xdg, "mushi", "config.json");
16
- }
17
- if (process.platform === "win32") {
18
- const appData = process.env["APPDATA"];
19
- if (appData && appData.length > 0) {
20
- return join(appData, "mushi", "config.json");
21
- }
22
- }
23
- return join(homedir(), ".config", "mushi", "config.json");
24
- }
25
- var LEGACY_CONFIG_PATH = join(homedir(), ".mushirc");
26
- var CONFIG_PATH = resolveXdgConfigPath();
27
- function loadConfig(path = CONFIG_PATH) {
28
- let file = {};
29
- if (existsSync(path)) {
30
- tightenPermissions(path);
31
- try {
32
- file = JSON.parse(readFileSync(path, "utf-8"));
33
- } catch {
34
- }
35
- } else if (path === CONFIG_PATH && existsSync(LEGACY_CONFIG_PATH)) {
36
- file = migrateLegacyConfig() ?? {};
37
- }
38
- const endpointFromEnv = process.env["MUSHI_API_ENDPOINT"] ?? process.env["MUSHI_ENDPOINT"] ?? void 0;
39
- const fromEnv = {
40
- ...process.env["MUSHI_API_KEY"] ? { apiKey: process.env["MUSHI_API_KEY"] } : {},
41
- ...process.env["MUSHI_PROJECT_ID"] ? { projectId: process.env["MUSHI_PROJECT_ID"] } : {},
42
- ...endpointFromEnv ? { endpoint: endpointFromEnv } : {}
43
- };
44
- return { ...file, ...fromEnv };
45
- }
46
- function saveConfig(config, path = CONFIG_PATH) {
47
- const dir = dirname(path);
48
- if (!existsSync(dir)) {
49
- mkdirSync(dir, { recursive: true, mode: SECURE_DIR_MODE });
50
- } else {
51
- tightenDirPermissions(dir);
52
- }
53
- writeFileSync(path, JSON.stringify(config, null, 2), { mode: SECURE_FILE_MODE });
54
- tightenPermissions(path);
55
- }
56
- function migrateLegacyConfig(legacyPath = LEGACY_CONFIG_PATH, destPath = CONFIG_PATH) {
57
- if (!existsSync(legacyPath)) return null;
58
- let parsed;
59
- try {
60
- parsed = JSON.parse(readFileSync(legacyPath, "utf-8"));
61
- } catch {
62
- return null;
63
- }
64
- const dir = dirname(destPath);
65
- if (!existsSync(dir)) {
66
- mkdirSync(dir, { recursive: true, mode: SECURE_DIR_MODE });
67
- }
68
- try {
69
- renameSync(legacyPath, destPath);
70
- } catch {
71
- writeFileSync(destPath, JSON.stringify(parsed, null, 2), { mode: SECURE_FILE_MODE });
72
- try {
73
- unlinkSync(legacyPath);
74
- } catch {
75
- }
76
- }
77
- tightenPermissions(destPath);
78
- tightenDirPermissions(dir);
79
- return parsed;
80
- }
81
- function tightenPermissions(path) {
82
- if (process.platform === "win32") return;
83
- try {
84
- const current = statSync(path).mode & 511;
85
- if (current !== SECURE_FILE_MODE) chmodSync(path, SECURE_FILE_MODE);
86
- } catch {
87
- }
88
- }
89
- function tightenDirPermissions(path) {
90
- if (process.platform === "win32") return;
91
- try {
92
- const current = statSync(path).mode & 511;
93
- if (current !== SECURE_DIR_MODE) chmodSync(path, SECURE_DIR_MODE);
94
- } catch {
95
- }
96
- }
97
-
98
- // src/version.ts
99
- var MUSHI_CLI_VERSION = true ? "0.18.2" : "0.0.0-dev";
100
-
101
- // src/errors.ts
102
- var EXIT_CODE_MAP = {
103
- E_AUTH_MISSING: 2,
104
- E_AUTH_INVALID: 2,
105
- E_PROJECT_MISSING: 2,
106
- E_ENDPOINT_INVALID: 2,
107
- E_INVALID_INPUT: 2,
108
- E_NOT_INTERACTIVE: 2,
109
- E_NETWORK: 3,
110
- E_TIMEOUT: 3,
111
- E_API_ERROR: 3,
112
- E_RATE_LIMITED: 3,
113
- E_FILE_NOT_FOUND: 1,
114
- E_FILE_PERMISSION: 1,
115
- E_FRESHNESS_STALE: 1,
116
- E_INTERRUPTED: 130,
117
- // 128 + SIGINT (2). POSIX convention.
118
- E_INTERNAL: 1
119
- };
120
- var MushiCliError = class extends Error {
121
- code;
122
- hint;
123
- cause;
124
- constructor(code, message, hint, cause) {
125
- super(message);
126
- this.name = "MushiCliError";
127
- this.code = code;
128
- if (hint) this.hint = hint;
129
- if (cause !== void 0) this.cause = cause;
130
- }
131
- /** Exit code POSIX-aware shell scripts should branch on. */
132
- get exitCode() {
133
- return EXIT_CODE_MAP[this.code];
134
- }
135
- /**
136
- * Format for `--json` output. Used by the JSON writer when a CLI
137
- * subcommand was invoked with `--json` and an error escapes.
138
- */
139
- toJSON() {
140
- return {
141
- error: {
142
- code: this.code,
143
- message: this.message,
144
- ...this.hint ? { hint: this.hint } : {}
145
- }
146
- };
147
- }
148
- };
149
-
150
- // src/signals.ts
151
- var installed = false;
152
- var activeController = null;
153
- function installSignalHandlers() {
154
- if (installed) return;
155
- installed = true;
156
- const abortAndExit = (signal) => {
157
- activeController?.abort(
158
- new MushiCliError(
159
- "E_INTERRUPTED",
160
- `aborted by ${signal}`,
161
- "partial state on the server is safe to retry \u2014 re-run the same command"
162
- )
163
- );
164
- const code = signal === "SIGINT" ? 130 : signal === "SIGTERM" ? 143 : 1;
165
- process.nextTick(() => {
166
- process.exit(code);
167
- });
168
- };
169
- process.on("SIGINT", () => abortAndExit("SIGINT"));
170
- process.on("SIGTERM", () => abortAndExit("SIGTERM"));
171
- }
172
- function getAbortSignal(external) {
173
- if (external) return external.signal;
174
- if (!activeController || activeController.signal.aborted) {
175
- activeController = new AbortController();
176
- }
177
- return activeController.signal;
178
- }
179
-
180
- // src/cli-shared.ts
181
- var API_TIMEOUT_MS = 15e3;
182
- async function apiCall(path, config, options = {}) {
183
- const endpoint = config.endpoint;
184
- if (!endpoint) {
185
- return {
186
- ok: false,
187
- error: {
188
- code: "NO_ENDPOINT",
189
- message: "No API endpoint configured.\n Run: mushi login --api-key <key> --endpoint <url> --project-id <id>\n Or: export MUSHI_API_ENDPOINT=https://<project-ref>.supabase.co/functions/v1/api"
190
- }
191
- };
192
- }
193
- const controller = new AbortController();
194
- const timer = setTimeout(() => controller.abort(), API_TIMEOUT_MS);
195
- const signals = [controller.signal, getAbortSignal()];
196
- const compositeSignal = AbortSignal.any ? AbortSignal.any(signals) : controller.signal;
197
- try {
198
- const res = await fetch(`${endpoint}${path}`, {
199
- ...options,
200
- signal: compositeSignal,
201
- headers: {
202
- "Content-Type": "application/json",
203
- // `apiKeyAuth` reads X-Mushi-Api-Key; the Authorization header is a
204
- // fallback accepted by some older middleware. Both are sent.
205
- "Authorization": `Bearer ${config.apiKey ?? ""}`,
206
- "X-Mushi-Api-Key": config.apiKey ?? "",
207
- "X-Mushi-Project": config.projectId ?? "",
208
- "X-Mushi-Cli-Version": MUSHI_CLI_VERSION,
209
- ...options.headers
210
- }
211
- });
212
- clearTimeout(timer);
213
- let body;
214
- const contentType = res.headers.get("content-type") ?? "";
215
- if (contentType.includes("application/json")) {
216
- try {
217
- body = await res.json();
218
- } catch {
219
- body = null;
220
- }
221
- } else {
222
- const text = await res.text();
223
- try {
224
- body = JSON.parse(text);
225
- } catch {
226
- body = {
227
- ok: false,
228
- error: {
229
- code: `HTTP_${res.status}`,
230
- message: text.trim().slice(0, 300) || `HTTP ${res.status}`
231
- }
232
- };
233
- }
234
- }
235
- if (!res.ok && typeof body === "object" && body !== null && !("ok" in body)) {
236
- const b = body;
237
- return {
238
- ok: false,
239
- httpStatus: res.status,
240
- error: {
241
- code: b["code"] ?? `HTTP_${res.status}`,
242
- message: b["message"] ?? `Request failed (${res.status})`
243
- }
244
- };
245
- }
246
- return body;
247
- } catch (err) {
248
- clearTimeout(timer);
249
- if (err instanceof Error && err.name === "AbortError") {
250
- return {
251
- ok: false,
252
- error: {
253
- code: "TIMEOUT",
254
- message: `Request timed out after ${API_TIMEOUT_MS / 1e3}s. Check your network or endpoint.`
255
- }
256
- };
257
- }
258
- return {
259
- ok: false,
260
- error: {
261
- code: "NETWORK_ERROR",
262
- message: err instanceof Error ? err.message : String(err)
263
- }
264
- };
265
- }
266
- }
267
- function die(result, exitCode = 1) {
268
- const { code, message } = result.error;
269
- const status = result.httpStatus ? ` [${result.httpStatus}]` : "";
270
- process.stderr.write(`error${status}: ${code} \u2014 ${message}
271
- `);
272
- process.exit(exitCode);
273
- }
274
- function requireConfig(opts = {}) {
275
- const config = loadConfig();
276
- if (!config.apiKey) {
277
- process.stderr.write(
278
- "error: API key not configured.\n Run: mushi login --api-key <key>\n Or: export MUSHI_API_KEY=<key>\n"
279
- );
280
- process.exit(2);
281
- }
282
- if (!config.endpoint) {
283
- config.endpoint = process.env.MUSHI_API_ENDPOINT?.trim() || CLOUD_API_ENDPOINT;
284
- }
285
- if (opts.needsProject && !config.projectId) {
286
- process.stderr.write(
287
- "error: Project ID not configured.\n Run: mushi login --project-id <uuid>\n Or: export MUSHI_PROJECT_ID=<uuid>\n Find your project ID: https://kensaur.us/mushi-mushi/projects\n"
288
- );
289
- process.exit(2);
290
- }
291
- return config;
292
- }
293
- function fmtDate(iso) {
294
- if (!iso) return "\u2014";
295
- return new Date(iso).toLocaleString(void 0, { dateStyle: "short", timeStyle: "short" });
296
- }
297
- function pad(s, width) {
298
- return s.length >= width ? s : s + " ".repeat(width - s.length);
299
- }
300
-
301
- export {
302
- installSignalHandlers,
303
- MUSHI_CLI_VERSION,
304
- CONFIG_PATH,
305
- loadConfig,
306
- saveConfig,
307
- API_TIMEOUT_MS,
308
- apiCall,
309
- die,
310
- requireConfig,
311
- fmtDate,
312
- pad
313
- };
@@ -1,6 +0,0 @@
1
- // src/version.ts
2
- var MUSHI_CLI_VERSION = true ? "0.18.2" : "0.0.0-dev";
3
-
4
- export {
5
- MUSHI_CLI_VERSION
6
- };
@@ -1,18 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- API_TIMEOUT_MS,
4
- apiCall,
5
- die,
6
- fmtDate,
7
- pad,
8
- requireConfig
9
- } from "./chunk-A2NHESSJ.js";
10
- import "./chunk-LDPFTQLE.js";
11
- export {
12
- API_TIMEOUT_MS,
13
- apiCall,
14
- die,
15
- fmtDate,
16
- pad,
17
- requireConfig
18
- };