@dropthis/cli 0.4.1 → 0.6.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/cli.cjs +514 -287
- package/dist/cli.cjs.map +1 -1
- package/node_modules/@dropthis/node/README.md +93 -21
- package/node_modules/@dropthis/node/dist/drops-BPdmUPCT.d.cts +394 -0
- package/node_modules/@dropthis/node/dist/drops-BPdmUPCT.d.ts +394 -0
- package/node_modules/@dropthis/node/dist/edge.cjs +805 -0
- package/node_modules/@dropthis/node/dist/edge.cjs.map +1 -0
- package/node_modules/@dropthis/node/dist/edge.d.cts +21 -0
- package/node_modules/@dropthis/node/dist/edge.d.ts +21 -0
- package/node_modules/@dropthis/node/dist/edge.mjs +778 -0
- package/node_modules/@dropthis/node/dist/edge.mjs.map +1 -0
- package/node_modules/@dropthis/node/dist/index.cjs +469 -422
- package/node_modules/@dropthis/node/dist/index.cjs.map +1 -1
- package/node_modules/@dropthis/node/dist/index.d.cts +13 -408
- package/node_modules/@dropthis/node/dist/index.d.ts +13 -408
- package/node_modules/@dropthis/node/dist/index.mjs +468 -422
- package/node_modules/@dropthis/node/dist/index.mjs.map +1 -1
- package/node_modules/@dropthis/node/package.json +11 -1
- package/package.json +2 -2
package/dist/cli.cjs
CHANGED
|
@@ -29,6 +29,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
29
29
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
30
30
|
mod
|
|
31
31
|
));
|
|
32
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
33
|
|
|
33
34
|
// src/inline-auth.ts
|
|
34
35
|
var inline_auth_exports = {};
|
|
@@ -150,42 +151,12 @@ var init_inline_auth = __esm({
|
|
|
150
151
|
}
|
|
151
152
|
});
|
|
152
153
|
|
|
153
|
-
// src/
|
|
154
|
-
var
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (input.apiKey) return { apiKey: input.apiKey, source: "flag" };
|
|
160
|
-
if (input.env.DROPTHIS_API_KEY) {
|
|
161
|
-
return { apiKey: input.env.DROPTHIS_API_KEY, source: "env" };
|
|
162
|
-
}
|
|
163
|
-
const stored = await input.store.read();
|
|
164
|
-
if (!stored) return null;
|
|
165
|
-
return {
|
|
166
|
-
apiKey: stored.apiKey,
|
|
167
|
-
source: "storage",
|
|
168
|
-
...stored.keyId ? { keyId: stored.keyId } : {},
|
|
169
|
-
...stored.keyLast4 ? { keyLast4: stored.keyLast4 } : {},
|
|
170
|
-
...stored.accountId ? { accountId: stored.accountId } : {},
|
|
171
|
-
...stored.email ? { email: stored.email } : {}
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
async function requireCredential(input) {
|
|
175
|
-
const credential = await resolveCredential(input);
|
|
176
|
-
if (!credential) {
|
|
177
|
-
throw Object.assign(new Error("No API key found."), {
|
|
178
|
-
code: "auth_error"
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
return credential;
|
|
182
|
-
}
|
|
183
|
-
function maskKey(apiKey) {
|
|
184
|
-
return apiKey.length <= 8 ? "sk_..." : `${apiKey.slice(0, 3)}...${apiKey.slice(-4)}`;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// src/fmt.ts
|
|
188
|
-
var import_picocolors2 = __toESM(require("picocolors"), 1);
|
|
154
|
+
// src/cli.ts
|
|
155
|
+
var cli_exports = {};
|
|
156
|
+
__export(cli_exports, {
|
|
157
|
+
writeUsageErrorEnvelope: () => writeUsageErrorEnvelope
|
|
158
|
+
});
|
|
159
|
+
module.exports = __toCommonJS(cli_exports);
|
|
189
160
|
|
|
190
161
|
// src/output.ts
|
|
191
162
|
var UPLOAD_NEXT_ACTIONS = {
|
|
@@ -213,7 +184,7 @@ function apiErrorEnvelope(error2) {
|
|
|
213
184
|
return {
|
|
214
185
|
ok: false,
|
|
215
186
|
error: {
|
|
216
|
-
code: error2
|
|
187
|
+
code: normalizeApiErrorCode(error2),
|
|
217
188
|
message: error2.message,
|
|
218
189
|
...error2.statusCode !== void 0 ? { status: error2.statusCode } : {},
|
|
219
190
|
...typeof error2.detail === "string" ? { detail: error2.detail } : {},
|
|
@@ -226,6 +197,11 @@ function apiErrorEnvelope(error2) {
|
|
|
226
197
|
}
|
|
227
198
|
};
|
|
228
199
|
}
|
|
200
|
+
function normalizeApiErrorCode(error2) {
|
|
201
|
+
if (error2.code) return error2.code;
|
|
202
|
+
if (error2.statusCode === 404) return "not_found";
|
|
203
|
+
return "api_error";
|
|
204
|
+
}
|
|
229
205
|
function nextActionForApiError(error2) {
|
|
230
206
|
if (error2.suggestion) return error2.suggestion;
|
|
231
207
|
const uploadNextAction = error2.code ? UPLOAD_NEXT_ACTIONS[error2.code] : void 0;
|
|
@@ -233,6 +209,9 @@ function nextActionForApiError(error2) {
|
|
|
233
209
|
if (error2.code === "revision_conflict") {
|
|
234
210
|
return "Fetch the drop, merge your changes, and retry with the current revision.";
|
|
235
211
|
}
|
|
212
|
+
if (error2.statusCode === 404 || error2.code === "not_found") {
|
|
213
|
+
return "Check the drop id or slug and retry; list your drops with dropthis drops list.";
|
|
214
|
+
}
|
|
236
215
|
if (error2.statusCode === 401 || error2.code === "missing_api_key") {
|
|
237
216
|
return "Authenticate with dropthis login or set DROPTHIS_API_KEY.";
|
|
238
217
|
}
|
|
@@ -248,6 +227,7 @@ function nextActionForApiError(error2) {
|
|
|
248
227
|
return "Fix the request or retry after checking the drop state.";
|
|
249
228
|
}
|
|
250
229
|
function exitCodeFor(code) {
|
|
230
|
+
if (code === "usage_error") return 2;
|
|
251
231
|
if (code === "invalid_usage") return 2;
|
|
252
232
|
if (code === "auth_error") return 3;
|
|
253
233
|
if (code === "local_input_error") return 4;
|
|
@@ -255,6 +235,43 @@ function exitCodeFor(code) {
|
|
|
255
235
|
return 1;
|
|
256
236
|
}
|
|
257
237
|
|
|
238
|
+
// src/program.ts
|
|
239
|
+
var import_commander = require("commander");
|
|
240
|
+
var import_picocolors4 = __toESM(require("picocolors"), 1);
|
|
241
|
+
|
|
242
|
+
// src/auth.ts
|
|
243
|
+
async function resolveCredential(input) {
|
|
244
|
+
if (input.apiKey) return { apiKey: input.apiKey, source: "flag" };
|
|
245
|
+
if (input.env.DROPTHIS_API_KEY) {
|
|
246
|
+
return { apiKey: input.env.DROPTHIS_API_KEY, source: "env" };
|
|
247
|
+
}
|
|
248
|
+
const stored = await input.store.read();
|
|
249
|
+
if (!stored) return null;
|
|
250
|
+
return {
|
|
251
|
+
apiKey: stored.apiKey,
|
|
252
|
+
source: "storage",
|
|
253
|
+
...stored.keyId ? { keyId: stored.keyId } : {},
|
|
254
|
+
...stored.keyLast4 ? { keyLast4: stored.keyLast4 } : {},
|
|
255
|
+
...stored.accountId ? { accountId: stored.accountId } : {},
|
|
256
|
+
...stored.email ? { email: stored.email } : {}
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
async function requireCredential(input) {
|
|
260
|
+
const credential = await resolveCredential(input);
|
|
261
|
+
if (!credential) {
|
|
262
|
+
throw Object.assign(new Error("No API key found."), {
|
|
263
|
+
code: "auth_error"
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
return credential;
|
|
267
|
+
}
|
|
268
|
+
function maskKey(apiKey) {
|
|
269
|
+
return apiKey.length <= 8 ? "sk_..." : `${apiKey.slice(0, 3)}...${apiKey.slice(-4)}`;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// src/fmt.ts
|
|
273
|
+
var import_picocolors2 = __toESM(require("picocolors"), 1);
|
|
274
|
+
|
|
258
275
|
// src/ui.ts
|
|
259
276
|
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
260
277
|
var symbols = {
|
|
@@ -295,13 +312,13 @@ function writeResult(deps, link, verb, data) {
|
|
|
295
312
|
}
|
|
296
313
|
function formatDropDetails(data) {
|
|
297
314
|
const parts = [];
|
|
298
|
-
const size = data.sizeBytes
|
|
315
|
+
const size = data.sizeBytes;
|
|
299
316
|
if (typeof size === "number") parts.push(formatBytes(size));
|
|
300
|
-
const ct = data.contentType
|
|
317
|
+
const ct = data.contentType;
|
|
301
318
|
if (typeof ct === "string") parts.push(ct.split(";")[0]);
|
|
302
319
|
const vis = data.visibility;
|
|
303
320
|
if (vis === "unlisted") parts.push("unlisted");
|
|
304
|
-
const exp = data.expiresAt
|
|
321
|
+
const exp = data.expiresAt;
|
|
305
322
|
if (typeof exp === "string") parts.push(`expires ${exp.split("T")[0]}`);
|
|
306
323
|
if (parts.length === 0) return "";
|
|
307
324
|
return ` ${import_picocolors2.default.dim(parts.join(" \xB7 "))}`;
|
|
@@ -404,16 +421,66 @@ async function runAccountGet(_input, deps) {
|
|
|
404
421
|
}
|
|
405
422
|
const result = await deps.client.account.get();
|
|
406
423
|
if (result.error) {
|
|
407
|
-
return
|
|
424
|
+
return writeApiError(deps, result.error);
|
|
408
425
|
}
|
|
409
426
|
const data = result.data;
|
|
410
427
|
const pairs = [];
|
|
411
428
|
if (data?.id) pairs.push(["ID", String(data.id)]);
|
|
412
429
|
if (data?.email) pairs.push(["Email", String(data.email)]);
|
|
413
430
|
if (data?.plan) pairs.push(["Plan", String(data.plan)]);
|
|
431
|
+
if (data?.displayName) pairs.push(["Name", String(data.displayName)]);
|
|
432
|
+
if (data?.status) pairs.push(["Status", String(data.status)]);
|
|
433
|
+
if (data?.createdAt)
|
|
434
|
+
pairs.push(["Created", String(data.createdAt).split("T")[0]]);
|
|
414
435
|
writeKv(deps, pairs, { ok: true, account: result.data });
|
|
415
436
|
return { exitCode: 0 };
|
|
416
437
|
}
|
|
438
|
+
async function runAccountUpdate(input, deps) {
|
|
439
|
+
try {
|
|
440
|
+
await requireCredential({
|
|
441
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
442
|
+
env: deps.env,
|
|
443
|
+
store: deps.store
|
|
444
|
+
});
|
|
445
|
+
} catch {
|
|
446
|
+
return writeAuthError(deps);
|
|
447
|
+
}
|
|
448
|
+
const result = await deps.client.account.update({
|
|
449
|
+
displayName: input.displayName
|
|
450
|
+
});
|
|
451
|
+
if (result.error) return writeApiError(deps, result.error);
|
|
452
|
+
const data = result.data;
|
|
453
|
+
const pairs = [];
|
|
454
|
+
if (data?.id) pairs.push(["ID", String(data.id)]);
|
|
455
|
+
if (data?.displayName) pairs.push(["Name", String(data.displayName)]);
|
|
456
|
+
writeKv(deps, pairs, { ok: true, account: result.data });
|
|
457
|
+
return { exitCode: 0 };
|
|
458
|
+
}
|
|
459
|
+
async function runAccountDelete(input, deps) {
|
|
460
|
+
if (!input.yes && input.interactive === false) {
|
|
461
|
+
return writeError(
|
|
462
|
+
deps,
|
|
463
|
+
"invalid_usage",
|
|
464
|
+
"Pass --yes to delete the account in non-interactive mode."
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
try {
|
|
468
|
+
await requireCredential({
|
|
469
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
470
|
+
env: deps.env,
|
|
471
|
+
store: deps.store
|
|
472
|
+
});
|
|
473
|
+
} catch {
|
|
474
|
+
return writeAuthError(deps);
|
|
475
|
+
}
|
|
476
|
+
const result = await deps.client.account.delete();
|
|
477
|
+
if (result.error) return writeApiError(deps, result.error);
|
|
478
|
+
writeHumanOrJson(deps, success("Account deleted"), {
|
|
479
|
+
ok: true,
|
|
480
|
+
deleted: true
|
|
481
|
+
});
|
|
482
|
+
return { exitCode: 0 };
|
|
483
|
+
}
|
|
417
484
|
|
|
418
485
|
// src/commands/api-keys.ts
|
|
419
486
|
var prompts = __toESM(require("@clack/prompts"), 1);
|
|
@@ -445,12 +512,12 @@ async function runApiKeysCreate(input, deps) {
|
|
|
445
512
|
return writeAuthError(deps);
|
|
446
513
|
}
|
|
447
514
|
const result = await deps.client.apiKeys.create({ label: input.label });
|
|
448
|
-
if (result.error) return
|
|
515
|
+
if (result.error) return writeApiError(deps, result.error);
|
|
449
516
|
const data = result.data;
|
|
450
517
|
const pairs = [];
|
|
451
518
|
if (data.id) pairs.push(["ID", String(data.id)]);
|
|
452
519
|
if (data.key) pairs.push(["Key", String(data.key)]);
|
|
453
|
-
if (data.
|
|
520
|
+
if (data.keyLast4) pairs.push(["Last 4", String(data.keyLast4)]);
|
|
454
521
|
writeKv(deps, pairs, { ok: true, api_key: result.data });
|
|
455
522
|
return { exitCode: 0 };
|
|
456
523
|
}
|
|
@@ -465,8 +532,8 @@ async function runApiKeysList(_input, deps) {
|
|
|
465
532
|
return writeAuthError(deps);
|
|
466
533
|
}
|
|
467
534
|
const result = await deps.client.apiKeys.list();
|
|
468
|
-
if (result.error) return
|
|
469
|
-
const raw = unwrapListData(result.data
|
|
535
|
+
if (result.error) return writeApiError(deps, result.error);
|
|
536
|
+
const raw = unwrapListData(result.data);
|
|
470
537
|
const items = Array.isArray(raw) ? raw : void 0;
|
|
471
538
|
if (deps.outputMode === "human") {
|
|
472
539
|
if (!items || items.length === 0) {
|
|
@@ -474,7 +541,7 @@ async function runApiKeysList(_input, deps) {
|
|
|
474
541
|
} else {
|
|
475
542
|
for (const item of items) {
|
|
476
543
|
deps.stdout(
|
|
477
|
-
`${item.id ?? ""} ${item.label ?? ""} ...${item.
|
|
544
|
+
`${item.id ?? ""} ${item.label ?? ""} ...${item.keyLast4 ?? ""}
|
|
478
545
|
`
|
|
479
546
|
);
|
|
480
547
|
}
|
|
@@ -510,7 +577,7 @@ async function runApiKeysDelete(keyId, input, deps) {
|
|
|
510
577
|
return writeAuthError(deps);
|
|
511
578
|
}
|
|
512
579
|
const result = await deps.client.apiKeys.delete(keyId);
|
|
513
|
-
if (result?.error) return
|
|
580
|
+
if (result?.error) return writeApiError(deps, result.error);
|
|
514
581
|
writeHumanOrJson(deps, success(`Deleted ${keyId}`), {
|
|
515
582
|
ok: true,
|
|
516
583
|
deleted: true,
|
|
@@ -520,12 +587,9 @@ async function runApiKeysDelete(keyId, input, deps) {
|
|
|
520
587
|
}
|
|
521
588
|
|
|
522
589
|
// src/catalog.ts
|
|
523
|
-
var
|
|
524
|
-
{
|
|
525
|
-
|
|
526
|
-
description: "Publish an input and return a Dropthis URL.",
|
|
527
|
-
arguments: ["input"],
|
|
528
|
-
options: ["--json", "--url", "--dry-run", "--title", "--metadata"],
|
|
590
|
+
var COMMAND_ANNOTATIONS = {
|
|
591
|
+
publish: {
|
|
592
|
+
auth: "required",
|
|
529
593
|
examples: [
|
|
530
594
|
"dropthis ./file.html",
|
|
531
595
|
"dropthis publish ./site --json",
|
|
@@ -533,69 +597,70 @@ var COMMAND_CATALOG = [
|
|
|
533
597
|
"dropthis publish ./dist --dry-run"
|
|
534
598
|
]
|
|
535
599
|
},
|
|
536
|
-
{
|
|
537
|
-
name: "deployments list <dropId>",
|
|
538
|
-
description: "List deployments for a drop.",
|
|
539
|
-
arguments: ["dropId"],
|
|
540
|
-
options: ["--json", "--limit", "--cursor"],
|
|
600
|
+
drops: {
|
|
541
601
|
auth: "required",
|
|
542
|
-
examples: ["dropthis deployments list drop_abc --json"]
|
|
543
|
-
},
|
|
544
|
-
{
|
|
545
|
-
name: "deployments get <dropId> <deploymentId>",
|
|
546
|
-
description: "Get deployment details for a drop.",
|
|
547
|
-
arguments: ["dropId", "deploymentId"],
|
|
548
|
-
options: ["--json"],
|
|
549
|
-
auth: "required",
|
|
550
|
-
examples: ["dropthis deployments get drop_abc dep_abc --json"]
|
|
551
|
-
},
|
|
552
|
-
{
|
|
553
|
-
name: "drops",
|
|
554
|
-
description: "List, inspect, update, and delete drops.",
|
|
555
602
|
examples: [
|
|
556
603
|
"dropthis drops list --json",
|
|
557
604
|
"dropthis drops update drop_abc ./site --json",
|
|
558
605
|
"dropthis drops update drop_abc --title 'New Title' --dry-run"
|
|
559
606
|
]
|
|
560
607
|
},
|
|
561
|
-
{
|
|
562
|
-
|
|
563
|
-
|
|
608
|
+
deployments: { auth: "required" },
|
|
609
|
+
"deployments list": {
|
|
610
|
+
auth: "required",
|
|
611
|
+
examples: ["dropthis deployments list drop_abc --json"]
|
|
612
|
+
},
|
|
613
|
+
"deployments get": {
|
|
614
|
+
auth: "required",
|
|
615
|
+
examples: ["dropthis deployments get drop_abc dep_abc --json"]
|
|
616
|
+
},
|
|
617
|
+
"api-keys": {
|
|
618
|
+
auth: "required",
|
|
564
619
|
examples: ["dropthis api-keys create --label CI --json"]
|
|
565
620
|
},
|
|
566
|
-
{
|
|
567
|
-
name: "login",
|
|
568
|
-
description: "Authenticate with email OTP and store an API key.",
|
|
621
|
+
login: {
|
|
569
622
|
examples: [
|
|
570
623
|
"dropthis login verify --email user@example.com --otp 123456 --json"
|
|
571
624
|
]
|
|
572
625
|
},
|
|
573
|
-
{
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
description: "Show current auth source and credential metadata.",
|
|
581
|
-
examples: ["dropthis whoami --json"]
|
|
582
|
-
},
|
|
583
|
-
{
|
|
584
|
-
name: "account",
|
|
585
|
-
description: "Get account details.",
|
|
586
|
-
examples: ["dropthis account --json"]
|
|
626
|
+
logout: { examples: ["dropthis logout --json"] },
|
|
627
|
+
whoami: { auth: "required", examples: ["dropthis whoami --json"] },
|
|
628
|
+
account: { auth: "required", examples: ["dropthis account --json"] },
|
|
629
|
+
"account get": { auth: "required" },
|
|
630
|
+
"account update": {
|
|
631
|
+
auth: "required",
|
|
632
|
+
examples: ["dropthis account update --display-name 'Ada' --json"]
|
|
587
633
|
},
|
|
588
|
-
{
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
examples: ["dropthis doctor --json"]
|
|
634
|
+
"account delete": {
|
|
635
|
+
auth: "required",
|
|
636
|
+
examples: ["dropthis account delete --yes --json"]
|
|
592
637
|
},
|
|
593
|
-
{
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
638
|
+
doctor: { examples: ["dropthis doctor --json"] },
|
|
639
|
+
commands: { examples: ["dropthis commands --json"] }
|
|
640
|
+
};
|
|
641
|
+
function describeArgs(cmd) {
|
|
642
|
+
return cmd.registeredArguments.map((a) => a.name());
|
|
643
|
+
}
|
|
644
|
+
function describeOptions(cmd) {
|
|
645
|
+
return cmd.options.map((o) => o.long ?? o.short ?? o.flags);
|
|
646
|
+
}
|
|
647
|
+
function toEntry(cmd, path) {
|
|
648
|
+
const fullPath = [...path, cmd.name()];
|
|
649
|
+
const annotation = COMMAND_ANNOTATIONS[fullPath.join(" ")];
|
|
650
|
+
const subs = cmd.commands.map((sub) => toEntry(sub, fullPath));
|
|
651
|
+
return {
|
|
652
|
+
name: cmd.name(),
|
|
653
|
+
description: cmd.description(),
|
|
654
|
+
...describeArgs(cmd).length ? { arguments: describeArgs(cmd) } : {},
|
|
655
|
+
...describeOptions(cmd).length ? { options: describeOptions(cmd) } : {},
|
|
656
|
+
...annotation?.auth ? { auth: annotation.auth } : {},
|
|
657
|
+
...annotation?.examples ? { examples: annotation.examples } : {},
|
|
658
|
+
...subs.length ? { subcommands: subs } : {}
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
function buildCatalog(program) {
|
|
662
|
+
return program.commands.map((cmd) => toEntry(cmd, []));
|
|
663
|
+
}
|
|
599
664
|
|
|
600
665
|
// src/commands/commands.ts
|
|
601
666
|
async function runCommands(_input, deps) {
|
|
@@ -603,7 +668,7 @@ async function runCommands(_input, deps) {
|
|
|
603
668
|
`${JSON.stringify({
|
|
604
669
|
ok: true,
|
|
605
670
|
output: "JSON by default in CI, pipes, non-TTY, --json, or --quiet.",
|
|
606
|
-
commands:
|
|
671
|
+
commands: buildCatalog(deps.program)
|
|
607
672
|
})}
|
|
608
673
|
`
|
|
609
674
|
);
|
|
@@ -640,7 +705,7 @@ async function runDeploymentsList(dropId, input, deps) {
|
|
|
640
705
|
} else if (Array.isArray(items)) {
|
|
641
706
|
for (const item of items) {
|
|
642
707
|
deps.stdout(
|
|
643
|
-
`${item.id ?? ""} rev ${item.revision ?? "?"} ${item.
|
|
708
|
+
`${item.id ?? ""} rev ${item.revision ?? "?"} ${item.createdAt ?? ""}
|
|
644
709
|
`
|
|
645
710
|
);
|
|
646
711
|
}
|
|
@@ -671,7 +736,7 @@ async function runDeploymentsGet(dropId, deploymentId, _input, deps) {
|
|
|
671
736
|
if (data.id) pairs.push(["ID", String(data.id)]);
|
|
672
737
|
if (data.revision !== void 0)
|
|
673
738
|
pairs.push(["Revision", String(data.revision)]);
|
|
674
|
-
if (data.
|
|
739
|
+
if (data.createdAt) pairs.push(["Created", String(data.createdAt)]);
|
|
675
740
|
writeKv(deps, pairs, { ok: true, deployment: result.data });
|
|
676
741
|
return { exitCode: 0 };
|
|
677
742
|
}
|
|
@@ -689,13 +754,13 @@ async function runDoctor(_input, deps) {
|
|
|
689
754
|
const authSource = credential?.source ?? "missing";
|
|
690
755
|
const storageBackend = stored?.storage ?? "none";
|
|
691
756
|
const pairs = [
|
|
692
|
-
["Version", "0.
|
|
757
|
+
["Version", "0.6.0"],
|
|
693
758
|
["Auth", authSource],
|
|
694
759
|
["Storage", storageBackend]
|
|
695
760
|
];
|
|
696
761
|
writeKv(deps, pairs, {
|
|
697
762
|
ok: true,
|
|
698
|
-
version: "0.
|
|
763
|
+
version: "0.6.0",
|
|
699
764
|
auth: { source: authSource },
|
|
700
765
|
storage: { backend: storageBackend }
|
|
701
766
|
});
|
|
@@ -719,7 +784,7 @@ async function runDropsList(input, deps) {
|
|
|
719
784
|
...input.cursor ? { cursor: input.cursor } : {}
|
|
720
785
|
};
|
|
721
786
|
const result = await deps.client.drops.list(params);
|
|
722
|
-
if (result.error) return
|
|
787
|
+
if (result.error) return writeApiError(deps, result.error);
|
|
723
788
|
const raw = unwrapListData(result.data, "drops");
|
|
724
789
|
const items = Array.isArray(raw) ? raw : void 0;
|
|
725
790
|
if (deps.outputMode === "human") {
|
|
@@ -749,7 +814,7 @@ async function runDropsGet(dropId, _input, deps) {
|
|
|
749
814
|
return writeAuthError(deps);
|
|
750
815
|
}
|
|
751
816
|
const result = await deps.client.drops.get(dropId);
|
|
752
|
-
if (result.error) return
|
|
817
|
+
if (result.error) return writeApiError(deps, result.error);
|
|
753
818
|
const data = result.data;
|
|
754
819
|
const pairs = [];
|
|
755
820
|
if (data.id) pairs.push(["ID", String(data.id)]);
|
|
@@ -758,7 +823,7 @@ async function runDropsGet(dropId, _input, deps) {
|
|
|
758
823
|
if (data.visibility) pairs.push(["Visibility", String(data.visibility)]);
|
|
759
824
|
if (data.revision !== void 0)
|
|
760
825
|
pairs.push(["Revision", String(data.revision)]);
|
|
761
|
-
if (data.
|
|
826
|
+
if (data.createdAt) pairs.push(["Created", String(data.createdAt)]);
|
|
762
827
|
if (data.accessible !== void 0)
|
|
763
828
|
pairs.push(["Accessible", String(data.accessible)]);
|
|
764
829
|
if (data.persistent !== void 0)
|
|
@@ -794,7 +859,7 @@ async function runDropsDelete(dropId, input, deps) {
|
|
|
794
859
|
return writeAuthError(deps);
|
|
795
860
|
}
|
|
796
861
|
const result = await deps.client.drops.delete(dropId);
|
|
797
|
-
if (result?.error) return
|
|
862
|
+
if (result?.error) return writeApiError(deps, result.error);
|
|
798
863
|
writeHumanOrJson(deps, success(`Deleted ${dropId}`), {
|
|
799
864
|
ok: true,
|
|
800
865
|
deleted: true,
|
|
@@ -946,51 +1011,16 @@ async function runLogout(input, deps) {
|
|
|
946
1011
|
return { exitCode: 0 };
|
|
947
1012
|
}
|
|
948
1013
|
|
|
949
|
-
// src/commands/publish.ts
|
|
950
|
-
var import_promises3 = require("fs/promises");
|
|
951
|
-
var import_node_path2 = require("path");
|
|
952
|
-
|
|
953
1014
|
// src/drop-operations.ts
|
|
954
1015
|
var import_node_crypto = require("crypto");
|
|
955
|
-
var import_node_path = require("path");
|
|
956
1016
|
var MAX_BUNDLE_FILE_COUNT = 200;
|
|
957
1017
|
function isFileSystemError(error2) {
|
|
958
1018
|
if (!(error2 instanceof Error)) return false;
|
|
959
1019
|
const code = error2.code;
|
|
960
1020
|
return code === "ENOENT" || code === "ENOTDIR" || code === "EACCES" || code === "ELIMIT";
|
|
961
1021
|
}
|
|
962
|
-
function
|
|
963
|
-
|
|
964
|
-
const types = {
|
|
965
|
-
".html": "text/html",
|
|
966
|
-
".htm": "text/html",
|
|
967
|
-
".css": "text/css",
|
|
968
|
-
".js": "text/javascript",
|
|
969
|
-
".mjs": "text/javascript",
|
|
970
|
-
".json": "application/json",
|
|
971
|
-
".xml": "application/xml",
|
|
972
|
-
".svg": "image/svg+xml",
|
|
973
|
-
".txt": "text/plain",
|
|
974
|
-
".md": "text/markdown",
|
|
975
|
-
".jpg": "image/jpeg",
|
|
976
|
-
".jpeg": "image/jpeg",
|
|
977
|
-
".png": "image/png",
|
|
978
|
-
".gif": "image/gif",
|
|
979
|
-
".webp": "image/webp",
|
|
980
|
-
".ico": "image/x-icon",
|
|
981
|
-
".avif": "image/avif",
|
|
982
|
-
".pdf": "application/pdf",
|
|
983
|
-
".zip": "application/zip",
|
|
984
|
-
".woff": "font/woff",
|
|
985
|
-
".woff2": "font/woff2",
|
|
986
|
-
".ttf": "font/ttf",
|
|
987
|
-
".mp4": "video/mp4",
|
|
988
|
-
".webm": "video/webm"
|
|
989
|
-
};
|
|
990
|
-
return types[ext] ?? "application/octet-stream";
|
|
991
|
-
}
|
|
992
|
-
function withIdempotencyKey(options, prefix) {
|
|
993
|
-
return options.idempotencyKey ? options : { ...options, idempotencyKey: `cli_${prefix}_${(0, import_node_crypto.randomUUID)()}` };
|
|
1022
|
+
function withIdempotencyKey(options, _prefix) {
|
|
1023
|
+
return options.idempotencyKey ? options : { ...options, idempotencyKey: (0, import_node_crypto.randomUUID)() };
|
|
994
1024
|
}
|
|
995
1025
|
function validateManifestFileCount(count) {
|
|
996
1026
|
if (count > MAX_BUNDLE_FILE_COUNT) {
|
|
@@ -1003,11 +1033,23 @@ function validateManifestFileCount(count) {
|
|
|
1003
1033
|
}
|
|
1004
1034
|
}
|
|
1005
1035
|
function formatDryRunManifest(prepared, extra) {
|
|
1036
|
+
if (prepared.kind === "source") {
|
|
1037
|
+
return {
|
|
1038
|
+
ok: true,
|
|
1039
|
+
dryRun: true,
|
|
1040
|
+
kind: "source",
|
|
1041
|
+
...extra,
|
|
1042
|
+
sourceUrl: prepared.sourceUrl,
|
|
1043
|
+
options: prepared.options,
|
|
1044
|
+
...prepared.metadata ? { metadata: prepared.metadata } : {}
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1006
1047
|
const totalBytes = prepared.manifest.files.reduce(
|
|
1007
1048
|
(sum, f) => sum + f.sizeBytes,
|
|
1008
1049
|
0
|
|
1009
1050
|
);
|
|
1010
1051
|
return {
|
|
1052
|
+
ok: true,
|
|
1011
1053
|
dryRun: true,
|
|
1012
1054
|
kind: "staged",
|
|
1013
1055
|
...extra,
|
|
@@ -1020,15 +1062,6 @@ function formatDryRunManifest(prepared, extra) {
|
|
|
1020
1062
|
totalBytes
|
|
1021
1063
|
};
|
|
1022
1064
|
}
|
|
1023
|
-
function dryRunOptionsBody(options) {
|
|
1024
|
-
const result = {};
|
|
1025
|
-
if (options.title) result.title = options.title;
|
|
1026
|
-
if (options.visibility) result.visibility = options.visibility;
|
|
1027
|
-
if (options.password !== void 0) result.password = options.password;
|
|
1028
|
-
if (options.noindex !== void 0) result.noindex = options.noindex;
|
|
1029
|
-
if (options.expiresAt) result.expires_at = options.expiresAt;
|
|
1030
|
-
return result;
|
|
1031
|
-
}
|
|
1032
1065
|
|
|
1033
1066
|
// src/options.ts
|
|
1034
1067
|
var import_promises = require("fs/promises");
|
|
@@ -1156,16 +1189,16 @@ async function runPublish(input, raw, deps) {
|
|
|
1156
1189
|
if (raw.dryRun) {
|
|
1157
1190
|
return handlePublishDryRun(input, raw, deps, client);
|
|
1158
1191
|
}
|
|
1159
|
-
const
|
|
1192
|
+
const hasInput = Array.isArray(input) ? input.length > 0 : input !== void 0;
|
|
1160
1193
|
const spin = shouldSpin(deps.outputMode) ? createSpinner("Publishing\u2026", deps.stderr) : void 0;
|
|
1161
1194
|
try {
|
|
1162
|
-
if (raw.fromJson &&
|
|
1195
|
+
if (raw.fromJson && hasInput) {
|
|
1163
1196
|
throw new Error("Use either <input> or --from-json, not both.");
|
|
1164
1197
|
}
|
|
1165
1198
|
const options = withIdempotencyKey(await parseDropOptions(raw), "pub");
|
|
1166
1199
|
const jsonBody = raw.fromJson ? await (deps.readJsonObject ?? readJsonObjectFile)(raw.fromJson) : void 0;
|
|
1167
1200
|
const idempotencyOpt = options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {};
|
|
1168
|
-
const doPublish = (c) => jsonBody ? c.drops.createRaw(jsonBody, idempotencyOpt) :
|
|
1201
|
+
const doPublish = (c) => jsonBody ? c.drops.createRaw(jsonBody, idempotencyOpt) : hasInput ? c.publish(input, options) : (() => {
|
|
1169
1202
|
throw new Error("Publish requires <input> or --from-json.");
|
|
1170
1203
|
})();
|
|
1171
1204
|
const result = await doPublish(client);
|
|
@@ -1233,7 +1266,7 @@ async function handlePublishDryRun(input, raw, deps, client) {
|
|
|
1233
1266
|
raw.fromJson
|
|
1234
1267
|
);
|
|
1235
1268
|
deps.stdout(
|
|
1236
|
-
`${JSON.stringify({ dryRun: true, kind: "raw_json", endpoint: "POST /drops", body }, null, 2)}
|
|
1269
|
+
`${JSON.stringify({ ok: true, dryRun: true, kind: "raw_json", endpoint: "POST /drops", body }, null, 2)}
|
|
1237
1270
|
`
|
|
1238
1271
|
);
|
|
1239
1272
|
return { exitCode: 0 };
|
|
@@ -1242,17 +1275,14 @@ async function handlePublishDryRun(input, raw, deps, client) {
|
|
|
1242
1275
|
throw new Error("Publish requires <input> or --from-json.");
|
|
1243
1276
|
}
|
|
1244
1277
|
const options = await parseDropOptions(raw);
|
|
1245
|
-
if (Array.isArray(input)) {
|
|
1246
|
-
return dryRunMultiFile(input, options, deps);
|
|
1247
|
-
}
|
|
1248
1278
|
if (!client.prepare) {
|
|
1249
1279
|
throw new Error("Client does not support dry-run.");
|
|
1250
1280
|
}
|
|
1251
1281
|
const prepared = await client.prepare(input, options);
|
|
1252
1282
|
const output = formatDryRunManifest(prepared);
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1283
|
+
if (prepared.kind === "staged") {
|
|
1284
|
+
validateManifestFileCount(prepared.manifest.files.length);
|
|
1285
|
+
}
|
|
1256
1286
|
deps.stdout(`${JSON.stringify(output, null, 2)}
|
|
1257
1287
|
`);
|
|
1258
1288
|
return { exitCode: 0 };
|
|
@@ -1262,48 +1292,11 @@ async function handlePublishDryRun(input, raw, deps, client) {
|
|
|
1262
1292
|
return writeError(deps, code, message);
|
|
1263
1293
|
}
|
|
1264
1294
|
}
|
|
1265
|
-
async function dryRunMultiFile(inputs, options, deps) {
|
|
1266
|
-
const files = [];
|
|
1267
|
-
for (const filePath of inputs) {
|
|
1268
|
-
let info;
|
|
1269
|
-
try {
|
|
1270
|
-
info = await (0, import_promises3.stat)(filePath);
|
|
1271
|
-
} catch {
|
|
1272
|
-
return writeError(
|
|
1273
|
-
deps,
|
|
1274
|
-
"local_input_error",
|
|
1275
|
-
`File not found: ${filePath}`
|
|
1276
|
-
);
|
|
1277
|
-
}
|
|
1278
|
-
if (info.isDirectory()) {
|
|
1279
|
-
return writeError(
|
|
1280
|
-
deps,
|
|
1281
|
-
"local_input_error",
|
|
1282
|
-
`Cannot mix directories with multiple file arguments. Use a single folder instead: dropthis publish ${filePath}`
|
|
1283
|
-
);
|
|
1284
|
-
}
|
|
1285
|
-
files.push({
|
|
1286
|
-
path: (0, import_node_path2.basename)(filePath),
|
|
1287
|
-
contentType: mimeForPath(filePath),
|
|
1288
|
-
sizeBytes: info.size
|
|
1289
|
-
});
|
|
1290
|
-
}
|
|
1291
|
-
validateManifestFileCount(files.length);
|
|
1292
|
-
const entry = options.entry ?? files.find((f) => f.path === "index.html")?.path ?? files[0]?.path ?? null;
|
|
1293
|
-
const totalBytes = files.reduce((sum, f) => sum + f.sizeBytes, 0);
|
|
1294
|
-
const output = {
|
|
1295
|
-
dryRun: true,
|
|
1296
|
-
kind: "staged",
|
|
1297
|
-
manifest: { files, entry },
|
|
1298
|
-
options: dryRunOptionsBody(options),
|
|
1299
|
-
totalBytes
|
|
1300
|
-
};
|
|
1301
|
-
deps.stdout(`${JSON.stringify(output, null, 2)}
|
|
1302
|
-
`);
|
|
1303
|
-
return { exitCode: 0 };
|
|
1304
|
-
}
|
|
1305
1295
|
|
|
1306
1296
|
// src/commands/update.ts
|
|
1297
|
+
var prompts4 = __toESM(require("@clack/prompts"), 1);
|
|
1298
|
+
var NO_UPDATE_MESSAGE = "Nothing to update. Provide an input path or at least one update option.";
|
|
1299
|
+
var NO_UPDATE_NEXT_ACTION = "Run dropthis drops update --help, or retry with an input path (for example, dropthis drops update <dropId> ./dist) or one of: --title, --slug, --visibility, --password, --no-password, --noindex, --index, --expires-at, or --metadata.";
|
|
1307
1300
|
async function runUpdate(target, input, raw, deps) {
|
|
1308
1301
|
try {
|
|
1309
1302
|
await requireCredential({
|
|
@@ -1317,14 +1310,31 @@ async function runUpdate(target, input, raw, deps) {
|
|
|
1317
1310
|
if (raw.dryRun) {
|
|
1318
1311
|
return handleUpdateDryRun(target, input, raw, deps);
|
|
1319
1312
|
}
|
|
1320
|
-
|
|
1313
|
+
let spin;
|
|
1321
1314
|
try {
|
|
1322
1315
|
assertDropId(target);
|
|
1323
1316
|
if (raw.fromJson && input) {
|
|
1324
1317
|
throw new Error("Use either [input] or --from-json, not both.");
|
|
1325
1318
|
}
|
|
1326
|
-
|
|
1319
|
+
let updateInput = input;
|
|
1320
|
+
let parsed = await parseDropOptions(raw);
|
|
1321
|
+
if (!updateInput && !raw.fromJson && !hasUpdateFields(parsed)) {
|
|
1322
|
+
if (shouldPromptForUpdate(deps)) {
|
|
1323
|
+
const prompted = await promptForUpdate(target, deps.prompts ?? prompts4);
|
|
1324
|
+
if (!prompted) return { exitCode: 0 };
|
|
1325
|
+
updateInput = prompted.input;
|
|
1326
|
+
parsed = { ...parsed, ...prompted.options };
|
|
1327
|
+
} else {
|
|
1328
|
+
return writeError(
|
|
1329
|
+
deps,
|
|
1330
|
+
"invalid_usage",
|
|
1331
|
+
NO_UPDATE_MESSAGE,
|
|
1332
|
+
NO_UPDATE_NEXT_ACTION
|
|
1333
|
+
);
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1327
1336
|
const revisionOptions = raw.ifRevision !== void 0 ? { ifRevision: Number(raw.ifRevision) } : {};
|
|
1337
|
+
spin = shouldSpin(deps.outputMode) ? createSpinner("Updating\u2026", deps.stderr) : void 0;
|
|
1328
1338
|
const result = raw.fromJson ? await deps.client.deployments.createRaw(
|
|
1329
1339
|
target,
|
|
1330
1340
|
await (deps.readJsonObject ?? readJsonObjectFile)(raw.fromJson),
|
|
@@ -1335,17 +1345,14 @@ async function runUpdate(target, input, raw, deps) {
|
|
|
1335
1345
|
},
|
|
1336
1346
|
"upd"
|
|
1337
1347
|
)
|
|
1338
|
-
) :
|
|
1348
|
+
) : updateInput ? await deps.client.deploy(
|
|
1339
1349
|
target,
|
|
1340
|
-
|
|
1341
|
-
withIdempotencyKey(
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
"upd"
|
|
1347
|
-
)
|
|
1348
|
-
) : await deps.client.update(target, parsed, revisionOptions);
|
|
1350
|
+
updateInput,
|
|
1351
|
+
withIdempotencyKey({ ...parsed, ...revisionOptions }, "upd")
|
|
1352
|
+
) : await deps.client.update(
|
|
1353
|
+
target,
|
|
1354
|
+
withIdempotencyKey({ ...parsed, ...revisionOptions }, "upd")
|
|
1355
|
+
);
|
|
1349
1356
|
if (result.error) {
|
|
1350
1357
|
spin?.fail();
|
|
1351
1358
|
return writeApiError(deps, result.error);
|
|
@@ -1362,6 +1369,162 @@ async function runUpdate(target, input, raw, deps) {
|
|
|
1362
1369
|
return writeError(deps, code, message);
|
|
1363
1370
|
}
|
|
1364
1371
|
}
|
|
1372
|
+
function hasUpdateFields(options) {
|
|
1373
|
+
const { idempotencyKey: _, ...fields } = options;
|
|
1374
|
+
return Object.keys(fields).length > 0;
|
|
1375
|
+
}
|
|
1376
|
+
function shouldPromptForUpdate(deps) {
|
|
1377
|
+
return deps.outputMode === "human" && deps.interactive === true;
|
|
1378
|
+
}
|
|
1379
|
+
async function promptForUpdate(target, prompt) {
|
|
1380
|
+
prompt.intro(`Update ${target}`);
|
|
1381
|
+
const fields = await prompt.multiselect({
|
|
1382
|
+
message: "What do you want to update?",
|
|
1383
|
+
required: true,
|
|
1384
|
+
options: [
|
|
1385
|
+
{
|
|
1386
|
+
value: "content",
|
|
1387
|
+
label: "Content",
|
|
1388
|
+
hint: "replace files, folder, URL, or text"
|
|
1389
|
+
},
|
|
1390
|
+
{ value: "title", label: "Title", hint: "--title" },
|
|
1391
|
+
{ value: "slug", label: "Slug", hint: "--slug" },
|
|
1392
|
+
{ value: "visibility", label: "Visibility", hint: "--visibility" },
|
|
1393
|
+
{
|
|
1394
|
+
value: "password",
|
|
1395
|
+
label: "Password",
|
|
1396
|
+
hint: "--password or --no-password"
|
|
1397
|
+
},
|
|
1398
|
+
{
|
|
1399
|
+
value: "indexing",
|
|
1400
|
+
label: "Search indexing",
|
|
1401
|
+
hint: "--noindex or --index"
|
|
1402
|
+
},
|
|
1403
|
+
{ value: "expiresAt", label: "Expiration", hint: "--expires-at" },
|
|
1404
|
+
{ value: "metadata", label: "Metadata", hint: "--metadata" }
|
|
1405
|
+
]
|
|
1406
|
+
});
|
|
1407
|
+
if (prompt.isCancel(fields)) {
|
|
1408
|
+
prompt.cancel("Update cancelled.");
|
|
1409
|
+
return void 0;
|
|
1410
|
+
}
|
|
1411
|
+
const selected = new Set(fields);
|
|
1412
|
+
const options = {};
|
|
1413
|
+
let input;
|
|
1414
|
+
if (selected.has("content")) {
|
|
1415
|
+
const value = await prompt.text({
|
|
1416
|
+
message: "Content path, URL, or text",
|
|
1417
|
+
validate: requireNonEmpty("Enter content or a path.")
|
|
1418
|
+
});
|
|
1419
|
+
if (prompt.isCancel(value)) return cancelUpdate(prompt);
|
|
1420
|
+
input = value.trim();
|
|
1421
|
+
}
|
|
1422
|
+
if (selected.has("title")) {
|
|
1423
|
+
const value = await prompt.text({
|
|
1424
|
+
message: "Title",
|
|
1425
|
+
validate: requireNonEmpty("Enter a title.")
|
|
1426
|
+
});
|
|
1427
|
+
if (prompt.isCancel(value)) return cancelUpdate(prompt);
|
|
1428
|
+
options.title = value.trim();
|
|
1429
|
+
}
|
|
1430
|
+
if (selected.has("slug")) {
|
|
1431
|
+
const value = await prompt.text({
|
|
1432
|
+
message: "Slug",
|
|
1433
|
+
validate: requireNonEmpty("Enter a slug.")
|
|
1434
|
+
});
|
|
1435
|
+
if (prompt.isCancel(value)) return cancelUpdate(prompt);
|
|
1436
|
+
options.slug = value.trim();
|
|
1437
|
+
}
|
|
1438
|
+
if (selected.has("visibility")) {
|
|
1439
|
+
const value = await prompt.select({
|
|
1440
|
+
message: "Visibility",
|
|
1441
|
+
options: [
|
|
1442
|
+
{ value: "public", label: "Public" },
|
|
1443
|
+
{ value: "unlisted", label: "Unlisted" }
|
|
1444
|
+
]
|
|
1445
|
+
});
|
|
1446
|
+
if (prompt.isCancel(value)) return cancelUpdate(prompt);
|
|
1447
|
+
options.visibility = value;
|
|
1448
|
+
}
|
|
1449
|
+
if (selected.has("password")) {
|
|
1450
|
+
const action = await prompt.select({
|
|
1451
|
+
message: "Password",
|
|
1452
|
+
options: [
|
|
1453
|
+
{ value: "set", label: "Set password" },
|
|
1454
|
+
{ value: "remove", label: "Remove password" }
|
|
1455
|
+
]
|
|
1456
|
+
});
|
|
1457
|
+
if (prompt.isCancel(action)) return cancelUpdate(prompt);
|
|
1458
|
+
if (action === "set") {
|
|
1459
|
+
const value = await prompt.password({
|
|
1460
|
+
message: "Password",
|
|
1461
|
+
validate: requireNonEmpty("Enter a password.")
|
|
1462
|
+
});
|
|
1463
|
+
if (prompt.isCancel(value)) return cancelUpdate(prompt);
|
|
1464
|
+
options.password = value;
|
|
1465
|
+
} else {
|
|
1466
|
+
options.password = null;
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
if (selected.has("indexing")) {
|
|
1470
|
+
const value = await prompt.select({
|
|
1471
|
+
message: "Search indexing",
|
|
1472
|
+
options: [
|
|
1473
|
+
{ value: "noindex", label: "Prevent indexing" },
|
|
1474
|
+
{ value: "index", label: "Allow indexing" }
|
|
1475
|
+
]
|
|
1476
|
+
});
|
|
1477
|
+
if (prompt.isCancel(value)) return cancelUpdate(prompt);
|
|
1478
|
+
options.noindex = value === "noindex";
|
|
1479
|
+
}
|
|
1480
|
+
if (selected.has("expiresAt")) {
|
|
1481
|
+
const value = await prompt.text({
|
|
1482
|
+
message: "Expiration date",
|
|
1483
|
+
placeholder: "2025-12-31T23:59:59Z",
|
|
1484
|
+
validate: validateIsoDate
|
|
1485
|
+
});
|
|
1486
|
+
if (prompt.isCancel(value)) return cancelUpdate(prompt);
|
|
1487
|
+
options.expiresAt = value.trim();
|
|
1488
|
+
}
|
|
1489
|
+
if (selected.has("metadata")) {
|
|
1490
|
+
const value = await prompt.text({
|
|
1491
|
+
message: "Metadata JSON object",
|
|
1492
|
+
placeholder: '{"source":"cli"}',
|
|
1493
|
+
validate: validateJsonObject
|
|
1494
|
+
});
|
|
1495
|
+
if (prompt.isCancel(value)) return cancelUpdate(prompt);
|
|
1496
|
+
options.metadata = parseJsonObject2(value);
|
|
1497
|
+
}
|
|
1498
|
+
return { ...input ? { input } : {}, options };
|
|
1499
|
+
}
|
|
1500
|
+
function cancelUpdate(prompt) {
|
|
1501
|
+
prompt.cancel("Update cancelled.");
|
|
1502
|
+
return void 0;
|
|
1503
|
+
}
|
|
1504
|
+
function requireNonEmpty(message) {
|
|
1505
|
+
return (value) => value?.trim() ? void 0 : message;
|
|
1506
|
+
}
|
|
1507
|
+
function validateIsoDate(value) {
|
|
1508
|
+
if (!value?.trim()) return "Enter an ISO 8601 date.";
|
|
1509
|
+
const d = new Date(value);
|
|
1510
|
+
return Number.isNaN(d.getTime()) ? "Enter a valid ISO 8601 date." : void 0;
|
|
1511
|
+
}
|
|
1512
|
+
function validateJsonObject(value) {
|
|
1513
|
+
if (!value?.trim()) return "Enter a JSON object.";
|
|
1514
|
+
try {
|
|
1515
|
+
parseJsonObject2(value);
|
|
1516
|
+
return void 0;
|
|
1517
|
+
} catch {
|
|
1518
|
+
return "Enter a valid JSON object.";
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
function parseJsonObject2(value) {
|
|
1522
|
+
const parsed = JSON.parse(value);
|
|
1523
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1524
|
+
throw new Error("Metadata must be a JSON object.");
|
|
1525
|
+
}
|
|
1526
|
+
return parsed;
|
|
1527
|
+
}
|
|
1365
1528
|
async function handleUpdateDryRun(target, input, raw, deps) {
|
|
1366
1529
|
if (raw.url) {
|
|
1367
1530
|
return writeError(
|
|
@@ -1380,7 +1543,7 @@ async function handleUpdateDryRun(target, input, raw, deps) {
|
|
|
1380
1543
|
raw.fromJson
|
|
1381
1544
|
);
|
|
1382
1545
|
deps.stdout(
|
|
1383
|
-
`${JSON.stringify({ dryRun: true, kind: "raw_json", endpoint: `POST /drops/${target}/deployments`, body }, null, 2)}
|
|
1546
|
+
`${JSON.stringify({ ok: true, dryRun: true, kind: "raw_json", endpoint: `POST /drops/${target}/deployments`, body }, null, 2)}
|
|
1384
1547
|
`
|
|
1385
1548
|
);
|
|
1386
1549
|
return { exitCode: 0 };
|
|
@@ -1396,7 +1559,7 @@ async function handleUpdateDryRun(target, input, raw, deps) {
|
|
|
1396
1559
|
if (options.expiresAt) fields.expires_at = options.expiresAt;
|
|
1397
1560
|
if (options.metadata) fields.metadata = options.metadata;
|
|
1398
1561
|
deps.stdout(
|
|
1399
|
-
`${JSON.stringify({ dryRun: true, kind: "options_update", target, fields }, null, 2)}
|
|
1562
|
+
`${JSON.stringify({ ok: true, dryRun: true, kind: "options_update", target, fields }, null, 2)}
|
|
1400
1563
|
`
|
|
1401
1564
|
);
|
|
1402
1565
|
return { exitCode: 0 };
|
|
@@ -1406,7 +1569,9 @@ async function handleUpdateDryRun(target, input, raw, deps) {
|
|
|
1406
1569
|
}
|
|
1407
1570
|
const prepared = await deps.client.prepare(input, options);
|
|
1408
1571
|
const output = formatDryRunManifest(prepared, { target });
|
|
1409
|
-
|
|
1572
|
+
if (prepared.kind === "staged") {
|
|
1573
|
+
validateManifestFileCount(prepared.manifest.files.length);
|
|
1574
|
+
}
|
|
1410
1575
|
deps.stdout(`${JSON.stringify(output, null, 2)}
|
|
1411
1576
|
`);
|
|
1412
1577
|
return { exitCode: 0 };
|
|
@@ -1427,6 +1592,7 @@ function assertDropId(target) {
|
|
|
1427
1592
|
// src/commands/whoami.ts
|
|
1428
1593
|
async function runWhoami(_input, deps) {
|
|
1429
1594
|
const credential = await resolveCredential({
|
|
1595
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
1430
1596
|
env: deps.env,
|
|
1431
1597
|
store: deps.store
|
|
1432
1598
|
});
|
|
@@ -1437,21 +1603,34 @@ async function runWhoami(_input, deps) {
|
|
|
1437
1603
|
});
|
|
1438
1604
|
return { exitCode: 0 };
|
|
1439
1605
|
}
|
|
1606
|
+
const result = await deps.client.account.get();
|
|
1607
|
+
if (result.error) {
|
|
1608
|
+
writeHumanOrJson(
|
|
1609
|
+
deps,
|
|
1610
|
+
`Not authenticated: ${result.error.message}. Run dropthis login.`,
|
|
1611
|
+
{ ok: true, authenticated: false, reason: result.error.message }
|
|
1612
|
+
);
|
|
1613
|
+
return { exitCode: 0 };
|
|
1614
|
+
}
|
|
1615
|
+
const account = result.data ?? {};
|
|
1440
1616
|
const masked = maskKey(credential.apiKey);
|
|
1617
|
+
const last4 = credential.keyLast4 ?? credential.apiKey.slice(-4);
|
|
1441
1618
|
const pairs = [];
|
|
1442
|
-
if (credential.email
|
|
1619
|
+
if (credential.email ?? account.email)
|
|
1620
|
+
pairs.push(["Email", String(credential.email ?? account.email)]);
|
|
1443
1621
|
pairs.push(["Key", masked]);
|
|
1444
1622
|
pairs.push(["Source", credential.source]);
|
|
1445
|
-
if (credential.accountId
|
|
1623
|
+
if (credential.accountId ?? account.id)
|
|
1624
|
+
pairs.push(["Account", String(credential.accountId ?? account.id)]);
|
|
1446
1625
|
const jsonEnvelope = {
|
|
1447
1626
|
ok: true,
|
|
1448
1627
|
authenticated: true,
|
|
1449
1628
|
source: credential.source,
|
|
1450
1629
|
masked_key: masked,
|
|
1451
1630
|
...credential.keyId ? { key_id: credential.keyId } : {},
|
|
1452
|
-
...
|
|
1453
|
-
...credential.accountId ? { account_id: credential.accountId } : {},
|
|
1454
|
-
...credential.email ? { email: credential.email } : {}
|
|
1631
|
+
...last4 ? { key_last4: last4 } : {},
|
|
1632
|
+
...credential.accountId ?? account.id ? { account_id: String(credential.accountId ?? account.id) } : {},
|
|
1633
|
+
...credential.email ?? account.email ? { email: String(credential.email ?? account.email) } : {}
|
|
1455
1634
|
};
|
|
1456
1635
|
writeKv(deps, pairs, jsonEnvelope);
|
|
1457
1636
|
return { exitCode: 0 };
|
|
@@ -1484,9 +1663,9 @@ function createContext(input) {
|
|
|
1484
1663
|
}
|
|
1485
1664
|
|
|
1486
1665
|
// src/storage.ts
|
|
1487
|
-
var
|
|
1666
|
+
var import_promises3 = require("fs/promises");
|
|
1488
1667
|
var import_node_os = require("os");
|
|
1489
|
-
var
|
|
1668
|
+
var import_node_path = require("path");
|
|
1490
1669
|
var import_keyring = require("@napi-rs/keyring");
|
|
1491
1670
|
var MemoryCredentialStore = class {
|
|
1492
1671
|
credential = null;
|
|
@@ -1518,7 +1697,7 @@ var InsecureFileCredentialStore = class {
|
|
|
1518
1697
|
});
|
|
1519
1698
|
}
|
|
1520
1699
|
async clear() {
|
|
1521
|
-
await (0,
|
|
1700
|
+
await (0, import_promises3.rm)(this.filePath, { force: true });
|
|
1522
1701
|
}
|
|
1523
1702
|
};
|
|
1524
1703
|
var KeyringCredentialStore = class {
|
|
@@ -1545,7 +1724,7 @@ var KeyringCredentialStore = class {
|
|
|
1545
1724
|
}
|
|
1546
1725
|
async clear() {
|
|
1547
1726
|
await this.keyring.deletePassword();
|
|
1548
|
-
await (0,
|
|
1727
|
+
await (0, import_promises3.rm)(this.filePath, { force: true });
|
|
1549
1728
|
}
|
|
1550
1729
|
};
|
|
1551
1730
|
function createCredentialStore(options = {}) {
|
|
@@ -1563,14 +1742,14 @@ function defaultKeyringAdapter() {
|
|
|
1563
1742
|
};
|
|
1564
1743
|
}
|
|
1565
1744
|
function credentialPath(configDir) {
|
|
1566
|
-
return (0,
|
|
1567
|
-
configDir ?? (0,
|
|
1745
|
+
return (0, import_node_path.join)(
|
|
1746
|
+
configDir ?? (0, import_node_path.join)((0, import_node_os.homedir)(), ".config", "dropthis"),
|
|
1568
1747
|
"credentials.json"
|
|
1569
1748
|
);
|
|
1570
1749
|
}
|
|
1571
1750
|
async function readJsonFile(path) {
|
|
1572
1751
|
try {
|
|
1573
|
-
return JSON.parse(await (0,
|
|
1752
|
+
return JSON.parse(await (0, import_promises3.readFile)(path, "utf8"));
|
|
1574
1753
|
} catch (error2) {
|
|
1575
1754
|
if (error2 && typeof error2 === "object" && "code" in error2 && error2.code === "ENOENT") {
|
|
1576
1755
|
return null;
|
|
@@ -1579,20 +1758,34 @@ async function readJsonFile(path) {
|
|
|
1579
1758
|
}
|
|
1580
1759
|
}
|
|
1581
1760
|
async function writeCredentialFile(path, credential) {
|
|
1582
|
-
await (0,
|
|
1761
|
+
await (0, import_promises3.mkdir)((0, import_node_path.dirname)(path), { recursive: true });
|
|
1583
1762
|
const tmpPath = `${path}.${process.pid}.tmp`;
|
|
1584
|
-
await (0,
|
|
1763
|
+
await (0, import_promises3.writeFile)(tmpPath, `${JSON.stringify(credential, null, 2)}
|
|
1585
1764
|
`, {
|
|
1586
1765
|
mode: 384
|
|
1587
1766
|
});
|
|
1588
|
-
await (0,
|
|
1589
|
-
await (0,
|
|
1767
|
+
await (0, import_promises3.chmod)(tmpPath, 384);
|
|
1768
|
+
await (0, import_promises3.rename)(tmpPath, path);
|
|
1590
1769
|
}
|
|
1591
1770
|
|
|
1592
1771
|
// src/program.ts
|
|
1593
1772
|
function buildProgram(options = {}) {
|
|
1594
1773
|
const program = new import_commander.Command();
|
|
1595
1774
|
const store = options.store ?? new MemoryCredentialStore();
|
|
1775
|
+
const writeErr = options.stderr ?? ((value) => process.stderr.write(value));
|
|
1776
|
+
const jsonModeForOutput = () => {
|
|
1777
|
+
const argv = program.rawArgs ?? process.argv;
|
|
1778
|
+
return argv.includes("--json") || argv.includes("--quiet") || argv.includes("-q") || options.env?.CI === "true" || options.env === void 0 && process.env.CI === "true" || options.stdoutIsTTY === false || options.stdoutIsTTY === void 0 && process.stdout.isTTY !== true;
|
|
1779
|
+
};
|
|
1780
|
+
program.exitOverride();
|
|
1781
|
+
program.configureOutput({
|
|
1782
|
+
writeErr,
|
|
1783
|
+
// In JSON mode, suppress commander's default plain-text error so the
|
|
1784
|
+
// single JSON envelope written by cli.ts's catch is the only output.
|
|
1785
|
+
outputError: (str, write) => {
|
|
1786
|
+
if (!jsonModeForOutput()) write(str);
|
|
1787
|
+
}
|
|
1788
|
+
});
|
|
1596
1789
|
program.name("dropthis").description(
|
|
1597
1790
|
[
|
|
1598
1791
|
import_picocolors4.default.dim("Publish anything online and get a URL back."),
|
|
@@ -1601,7 +1794,7 @@ function buildProgram(options = {}) {
|
|
|
1601
1794
|
` ${import_picocolors4.default.cyan("dropthis login")}`,
|
|
1602
1795
|
` ${import_picocolors4.default.cyan("dropthis publish ./dist")}`
|
|
1603
1796
|
].join("\n")
|
|
1604
|
-
).version("0.
|
|
1797
|
+
).version("0.6.0").configureHelp({
|
|
1605
1798
|
subcommandTerm(cmd) {
|
|
1606
1799
|
const args = cmd.registeredArguments.map((a) => {
|
|
1607
1800
|
const name = a.name();
|
|
@@ -1631,7 +1824,10 @@ function buildProgram(options = {}) {
|
|
|
1631
1824
|
).option(
|
|
1632
1825
|
"--metadata <json>",
|
|
1633
1826
|
`Attach JSON key-value pairs, e.g. '{"source":"ci"}'`
|
|
1634
|
-
).option("--metadata-file <path>", "Read metadata JSON from a file").option("--path <name>", "Set filename when publishing from stdin").option("--url", "Print only the published URL (no JSON envelope)").option(
|
|
1827
|
+
).option("--metadata-file <path>", "Read metadata JSON from a file").option("--path <name>", "Set filename when publishing from stdin").option("--url", "Print only the published URL (no JSON envelope)").option(
|
|
1828
|
+
"--dry-run",
|
|
1829
|
+
"Show what would be published without publishing (JSON; cannot combine with --url)"
|
|
1830
|
+
).option("--json", "Force JSON output").option("--from-json <path>", "Send raw API request body from a JSON file").option(
|
|
1635
1831
|
"--idempotency-key <key>",
|
|
1636
1832
|
"Prevent duplicate publishes on retry (auto-generated)"
|
|
1637
1833
|
).action(async (inputs, commandOptions) => {
|
|
@@ -1649,15 +1845,11 @@ function buildProgram(options = {}) {
|
|
|
1649
1845
|
);
|
|
1650
1846
|
let publishInput;
|
|
1651
1847
|
try {
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
options.stdin,
|
|
1658
|
-
stdinIsTTY
|
|
1659
|
-
);
|
|
1660
|
-
}
|
|
1848
|
+
publishInput = await resolvePublishInputs(
|
|
1849
|
+
inputs,
|
|
1850
|
+
options.stdin,
|
|
1851
|
+
stdinIsTTY
|
|
1852
|
+
);
|
|
1661
1853
|
} catch (err) {
|
|
1662
1854
|
const msg = err instanceof Error ? err.message : "Invalid input.";
|
|
1663
1855
|
process.exitCode = writeError(deps, "local_input_error", msg).exitCode;
|
|
@@ -1700,7 +1892,10 @@ function buildProgram(options = {}) {
|
|
|
1700
1892
|
"--if-revision <n>",
|
|
1701
1893
|
"Fail if current revision doesn't match (optimistic lock)",
|
|
1702
1894
|
parseInteger
|
|
1703
|
-
).option("--url", "Print only the published URL (no JSON envelope)").option(
|
|
1895
|
+
).option("--url", "Print only the published URL (no JSON envelope)").option(
|
|
1896
|
+
"--dry-run",
|
|
1897
|
+
"Show what would be updated without updating (JSON; cannot combine with --url)"
|
|
1898
|
+
).option("--json", "Force JSON output").option(
|
|
1704
1899
|
"--from-json <path>",
|
|
1705
1900
|
"Send raw API deployment body from a JSON file"
|
|
1706
1901
|
).option(
|
|
@@ -1708,6 +1903,8 @@ function buildProgram(options = {}) {
|
|
|
1708
1903
|
"Prevent duplicate updates on retry (auto-generated)"
|
|
1709
1904
|
).action(
|
|
1710
1905
|
async (dropId, input, commandOptions) => {
|
|
1906
|
+
const stdinIsTTY = options.stdinIsTTY ?? process.stdin.isTTY ?? false;
|
|
1907
|
+
const global = globalOptions(program, commandOptions);
|
|
1711
1908
|
const deps = await commandDeps(program, options, store, commandOptions);
|
|
1712
1909
|
let updateInput;
|
|
1713
1910
|
try {
|
|
@@ -1729,7 +1926,10 @@ function buildProgram(options = {}) {
|
|
|
1729
1926
|
process.exitCode = writeError(deps, "invalid_usage", msg).exitCode;
|
|
1730
1927
|
return;
|
|
1731
1928
|
}
|
|
1732
|
-
const result = await runUpdate(dropId, updateInput, dropOpts,
|
|
1929
|
+
const result = await runUpdate(dropId, updateInput, dropOpts, {
|
|
1930
|
+
...deps,
|
|
1931
|
+
interactive: isInteractive(stdinIsTTY, deps.env, global)
|
|
1932
|
+
});
|
|
1733
1933
|
process.exitCode = result.exitCode;
|
|
1734
1934
|
}
|
|
1735
1935
|
);
|
|
@@ -1864,11 +2064,36 @@ function buildProgram(options = {}) {
|
|
|
1864
2064
|
const result = await runWhoami(commandOptions, deps);
|
|
1865
2065
|
process.exitCode = result.exitCode;
|
|
1866
2066
|
});
|
|
1867
|
-
program.command("account").description("Show
|
|
2067
|
+
const account = program.command("account").description("Show or manage your account");
|
|
2068
|
+
account.command("get", { isDefault: true }).description("Show account details").option("--json", "Force JSON output").action(async (commandOptions) => {
|
|
1868
2069
|
const deps = await commandDeps(program, options, store, commandOptions);
|
|
1869
2070
|
const result = await runAccountGet(commandOptions, deps);
|
|
1870
2071
|
process.exitCode = result.exitCode;
|
|
1871
2072
|
});
|
|
2073
|
+
account.command("update").description("Update account display name").requiredOption("--display-name <name>", "Set the display name").option("--json", "Force JSON output").action(async (commandOptions) => {
|
|
2074
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
2075
|
+
const result = await runAccountUpdate(
|
|
2076
|
+
{
|
|
2077
|
+
displayName: commandOptions.displayName,
|
|
2078
|
+
...commandOptions.json !== void 0 ? { json: commandOptions.json } : {}
|
|
2079
|
+
},
|
|
2080
|
+
deps
|
|
2081
|
+
);
|
|
2082
|
+
process.exitCode = result.exitCode;
|
|
2083
|
+
});
|
|
2084
|
+
account.command("delete").description("Delete your account").option("--yes", "Confirm deletion").option("--json", "Force JSON output").action(async (commandOptions) => {
|
|
2085
|
+
const stdinIsTTY = options.stdinIsTTY ?? process.stdin.isTTY ?? false;
|
|
2086
|
+
const global = globalOptions(program, commandOptions);
|
|
2087
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
2088
|
+
const result = await runAccountDelete(
|
|
2089
|
+
{
|
|
2090
|
+
...commandOptions,
|
|
2091
|
+
interactive: isInteractive(stdinIsTTY, deps.env, global)
|
|
2092
|
+
},
|
|
2093
|
+
deps
|
|
2094
|
+
);
|
|
2095
|
+
process.exitCode = result.exitCode;
|
|
2096
|
+
});
|
|
1872
2097
|
program.command("doctor").description("Report CLI diagnostics").option("--json", "Force JSON output").action(async (commandOptions) => {
|
|
1873
2098
|
const deps = await commandDeps(
|
|
1874
2099
|
program,
|
|
@@ -1886,7 +2111,7 @@ function buildProgram(options = {}) {
|
|
|
1886
2111
|
store,
|
|
1887
2112
|
commandOptions
|
|
1888
2113
|
);
|
|
1889
|
-
const result = await runCommands(commandOptions, deps);
|
|
2114
|
+
const result = await runCommands(commandOptions, { ...deps, program });
|
|
1890
2115
|
process.exitCode = result.exitCode;
|
|
1891
2116
|
});
|
|
1892
2117
|
return program;
|
|
@@ -2015,44 +2240,12 @@ async function resolvePublishInputs(inputs, stdin, stdinIsTTY) {
|
|
|
2015
2240
|
}
|
|
2016
2241
|
return inputs[0];
|
|
2017
2242
|
}
|
|
2018
|
-
|
|
2019
|
-
mkdtemp,
|
|
2020
|
-
copyFile,
|
|
2021
|
-
writeFile: writeFile2,
|
|
2022
|
-
stat: fsStat
|
|
2023
|
-
} = await import("fs/promises");
|
|
2024
|
-
const { join: join2, basename: pathBasename } = await import("path");
|
|
2025
|
-
const { tmpdir } = await import("os");
|
|
2026
|
-
const tmpDir = await mkdtemp(join2(tmpdir(), "dropthis-multi-"));
|
|
2027
|
-
const resolved = [];
|
|
2028
|
-
for (const input of inputs) {
|
|
2029
|
-
if (input === "-") {
|
|
2030
|
-
const buf = await readStdinBytes(stdin ?? process.stdin);
|
|
2031
|
-
const tmpPath = join2(tmpDir, `stdin-${Date.now()}`);
|
|
2032
|
-
await writeFile2(tmpPath, buf);
|
|
2033
|
-
resolved.push(tmpPath);
|
|
2034
|
-
} else {
|
|
2035
|
-
resolved.push(input);
|
|
2036
|
-
}
|
|
2037
|
-
}
|
|
2038
|
-
const names = resolved.map((f) => pathBasename(f));
|
|
2039
|
-
const dupes = names.filter((n, i) => names.indexOf(n) !== i);
|
|
2040
|
-
if (dupes.length > 0) {
|
|
2243
|
+
if (inputs.includes("-")) {
|
|
2041
2244
|
throw new Error(
|
|
2042
|
-
|
|
2245
|
+
"Cannot read stdin (-) alongside multiple file arguments. Pass file paths only."
|
|
2043
2246
|
);
|
|
2044
2247
|
}
|
|
2045
|
-
|
|
2046
|
-
const info = await fsStat(filePath);
|
|
2047
|
-
if (info.isDirectory()) {
|
|
2048
|
-
throw new Error(
|
|
2049
|
-
`Cannot mix directories with multiple file arguments. Use a single folder instead: dropthis publish ${filePath}`
|
|
2050
|
-
);
|
|
2051
|
-
}
|
|
2052
|
-
const destName = pathBasename(filePath);
|
|
2053
|
-
await copyFile(filePath, join2(tmpDir, destName));
|
|
2054
|
-
}
|
|
2055
|
-
return tmpDir;
|
|
2248
|
+
return inputs;
|
|
2056
2249
|
}
|
|
2057
2250
|
async function readStdinBytes(stdin) {
|
|
2058
2251
|
const chunks = [];
|
|
@@ -2065,8 +2258,42 @@ async function readStdinBytes(stdin) {
|
|
|
2065
2258
|
}
|
|
2066
2259
|
|
|
2067
2260
|
// src/cli.ts
|
|
2261
|
+
function writeUsageErrorEnvelope(input) {
|
|
2262
|
+
if (input.json) {
|
|
2263
|
+
input.stderr(
|
|
2264
|
+
`${JSON.stringify(errorEnvelope("usage_error", input.message))}
|
|
2265
|
+
`
|
|
2266
|
+
);
|
|
2267
|
+
} else {
|
|
2268
|
+
input.stderr(`${input.message}
|
|
2269
|
+
`);
|
|
2270
|
+
}
|
|
2271
|
+
return 2;
|
|
2272
|
+
}
|
|
2273
|
+
function isCommanderError(err) {
|
|
2274
|
+
return typeof err === "object" && err !== null && typeof err.code === "string" && err.code.startsWith("commander.");
|
|
2275
|
+
}
|
|
2276
|
+
function wantsJson(argv) {
|
|
2277
|
+
return argv.includes("--json") || argv.includes("--quiet") || argv.includes("-q") || process.env.CI === "true" || process.stdout.isTTY !== true;
|
|
2278
|
+
}
|
|
2068
2279
|
buildProgram({ store: createCredentialStore() }).parseAsync(process.argv).catch((error2) => {
|
|
2280
|
+
if (isCommanderError(error2)) {
|
|
2281
|
+
if (error2.code === "commander.help" || error2.code === "commander.helpDisplayed" || error2.code === "commander.version") {
|
|
2282
|
+
process.exitCode = 0;
|
|
2283
|
+
return;
|
|
2284
|
+
}
|
|
2285
|
+
process.exitCode = writeUsageErrorEnvelope({
|
|
2286
|
+
message: error2.message,
|
|
2287
|
+
json: wantsJson(process.argv.slice(2)),
|
|
2288
|
+
stderr: (value) => process.stderr.write(value)
|
|
2289
|
+
});
|
|
2290
|
+
return;
|
|
2291
|
+
}
|
|
2069
2292
|
console.error(error2);
|
|
2070
2293
|
process.exitCode = 1;
|
|
2071
2294
|
});
|
|
2295
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
2296
|
+
0 && (module.exports = {
|
|
2297
|
+
writeUsageErrorEnvelope
|
|
2298
|
+
});
|
|
2072
2299
|
//# sourceMappingURL=cli.cjs.map
|