@dropthis/cli 0.5.0 → 0.6.1
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/README.md +0 -1
- package/dist/cli.cjs +330 -346
- package/dist/cli.cjs.map +1 -1
- package/node_modules/@dropthis/node/README.md +88 -20
- package/node_modules/@dropthis/node/dist/{drops-fK63OCk6.d.cts → drops-BPdmUPCT.d.cts} +65 -56
- package/node_modules/@dropthis/node/dist/{drops-fK63OCk6.d.ts → drops-BPdmUPCT.d.ts} +65 -56
- package/node_modules/@dropthis/node/dist/edge.cjs +389 -168
- package/node_modules/@dropthis/node/dist/edge.cjs.map +1 -1
- package/node_modules/@dropthis/node/dist/edge.d.cts +4 -32
- package/node_modules/@dropthis/node/dist/edge.d.ts +4 -32
- package/node_modules/@dropthis/node/dist/edge.mjs +389 -168
- package/node_modules/@dropthis/node/dist/edge.mjs.map +1 -1
- package/node_modules/@dropthis/node/dist/index.cjs +449 -429
- package/node_modules/@dropthis/node/dist/index.cjs.map +1 -1
- package/node_modules/@dropthis/node/dist/index.d.cts +13 -39
- package/node_modules/@dropthis/node/dist/index.d.ts +13 -39
- package/node_modules/@dropthis/node/dist/index.mjs +448 -429
- package/node_modules/@dropthis/node/dist/index.mjs.map +1 -1
- package/node_modules/@dropthis/node/package.json +1 -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]]);
|
|
435
|
+
writeKv(deps, pairs, { ok: true, account: result.data });
|
|
436
|
+
return { exitCode: 0 };
|
|
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)]);
|
|
414
456
|
writeKv(deps, pairs, { ok: true, account: result.data });
|
|
415
457
|
return { exitCode: 0 };
|
|
416
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.1"],
|
|
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.1",
|
|
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");
|
|
@@ -1107,22 +1140,6 @@ function shouldSpin(outputMode) {
|
|
|
1107
1140
|
return outputMode === "human" && process.stderr.isTTY === true && !process.env.CI;
|
|
1108
1141
|
}
|
|
1109
1142
|
|
|
1110
|
-
// src/commands/json_body.ts
|
|
1111
|
-
var import_promises2 = require("fs/promises");
|
|
1112
|
-
async function readJsonObjectFile(path) {
|
|
1113
|
-
let parsed;
|
|
1114
|
-
try {
|
|
1115
|
-
parsed = JSON.parse(await (0, import_promises2.readFile)(path, "utf8"));
|
|
1116
|
-
} catch (error2) {
|
|
1117
|
-
const message = error2 instanceof Error ? error2.message : "Unknown parse error";
|
|
1118
|
-
throw new Error(`Invalid JSON body in ${path}: ${message}`);
|
|
1119
|
-
}
|
|
1120
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1121
|
-
throw new Error("JSON body must be an object.");
|
|
1122
|
-
}
|
|
1123
|
-
return parsed;
|
|
1124
|
-
}
|
|
1125
|
-
|
|
1126
1143
|
// src/commands/publish.ts
|
|
1127
1144
|
async function runPublish(input, raw, deps) {
|
|
1128
1145
|
let credential;
|
|
@@ -1156,17 +1173,12 @@ async function runPublish(input, raw, deps) {
|
|
|
1156
1173
|
if (raw.dryRun) {
|
|
1157
1174
|
return handlePublishDryRun(input, raw, deps, client);
|
|
1158
1175
|
}
|
|
1159
|
-
const
|
|
1176
|
+
const hasInput = Array.isArray(input) ? input.length > 0 : input !== void 0;
|
|
1160
1177
|
const spin = shouldSpin(deps.outputMode) ? createSpinner("Publishing\u2026", deps.stderr) : void 0;
|
|
1161
1178
|
try {
|
|
1162
|
-
if (raw.fromJson && singleInput) {
|
|
1163
|
-
throw new Error("Use either <input> or --from-json, not both.");
|
|
1164
|
-
}
|
|
1165
1179
|
const options = withIdempotencyKey(await parseDropOptions(raw), "pub");
|
|
1166
|
-
const
|
|
1167
|
-
|
|
1168
|
-
const doPublish = (c) => jsonBody ? c.drops.createRaw(jsonBody, idempotencyOpt) : singleInput ? c.publish(singleInput, options) : (() => {
|
|
1169
|
-
throw new Error("Publish requires <input> or --from-json.");
|
|
1180
|
+
const doPublish = (c) => hasInput ? c.publish(input, options) : (() => {
|
|
1181
|
+
throw new Error("Publish requires <input>.");
|
|
1170
1182
|
})();
|
|
1171
1183
|
const result = await doPublish(client);
|
|
1172
1184
|
if (result.error) {
|
|
@@ -1226,33 +1238,18 @@ async function handlePublishDryRun(input, raw, deps, client) {
|
|
|
1226
1238
|
);
|
|
1227
1239
|
}
|
|
1228
1240
|
try {
|
|
1229
|
-
if (raw.fromJson) {
|
|
1230
|
-
if (input)
|
|
1231
|
-
throw new Error("Use either <input> or --from-json, not both.");
|
|
1232
|
-
const body = await (deps.readJsonObject ?? readJsonObjectFile)(
|
|
1233
|
-
raw.fromJson
|
|
1234
|
-
);
|
|
1235
|
-
deps.stdout(
|
|
1236
|
-
`${JSON.stringify({ dryRun: true, kind: "raw_json", endpoint: "POST /drops", body }, null, 2)}
|
|
1237
|
-
`
|
|
1238
|
-
);
|
|
1239
|
-
return { exitCode: 0 };
|
|
1240
|
-
}
|
|
1241
1241
|
if (!input || Array.isArray(input) && input.length === 0) {
|
|
1242
|
-
throw new Error("Publish requires <input
|
|
1242
|
+
throw new Error("Publish requires <input>.");
|
|
1243
1243
|
}
|
|
1244
1244
|
const options = await parseDropOptions(raw);
|
|
1245
|
-
if (Array.isArray(input)) {
|
|
1246
|
-
return dryRunMultiFile(input, options, deps);
|
|
1247
|
-
}
|
|
1248
1245
|
if (!client.prepare) {
|
|
1249
1246
|
throw new Error("Client does not support dry-run.");
|
|
1250
1247
|
}
|
|
1251
1248
|
const prepared = await client.prepare(input, options);
|
|
1252
1249
|
const output = formatDryRunManifest(prepared);
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1250
|
+
if (prepared.kind === "staged") {
|
|
1251
|
+
validateManifestFileCount(prepared.manifest.files.length);
|
|
1252
|
+
}
|
|
1256
1253
|
deps.stdout(`${JSON.stringify(output, null, 2)}
|
|
1257
1254
|
`);
|
|
1258
1255
|
return { exitCode: 0 };
|
|
@@ -1262,46 +1259,6 @@ async function handlePublishDryRun(input, raw, deps, client) {
|
|
|
1262
1259
|
return writeError(deps, code, message);
|
|
1263
1260
|
}
|
|
1264
1261
|
}
|
|
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
1262
|
|
|
1306
1263
|
// src/commands/update.ts
|
|
1307
1264
|
var prompts4 = __toESM(require("@clack/prompts"), 1);
|
|
@@ -1323,12 +1280,9 @@ async function runUpdate(target, input, raw, deps) {
|
|
|
1323
1280
|
let spin;
|
|
1324
1281
|
try {
|
|
1325
1282
|
assertDropId(target);
|
|
1326
|
-
if (raw.fromJson && input) {
|
|
1327
|
-
throw new Error("Use either [input] or --from-json, not both.");
|
|
1328
|
-
}
|
|
1329
1283
|
let updateInput = input;
|
|
1330
1284
|
let parsed = await parseDropOptions(raw);
|
|
1331
|
-
if (!updateInput && !
|
|
1285
|
+
if (!updateInput && !hasUpdateFields(parsed)) {
|
|
1332
1286
|
if (shouldPromptForUpdate(deps)) {
|
|
1333
1287
|
const prompted = await promptForUpdate(target, deps.prompts ?? prompts4);
|
|
1334
1288
|
if (!prompted) return { exitCode: 0 };
|
|
@@ -1345,27 +1299,14 @@ async function runUpdate(target, input, raw, deps) {
|
|
|
1345
1299
|
}
|
|
1346
1300
|
const revisionOptions = raw.ifRevision !== void 0 ? { ifRevision: Number(raw.ifRevision) } : {};
|
|
1347
1301
|
spin = shouldSpin(deps.outputMode) ? createSpinner("Updating\u2026", deps.stderr) : void 0;
|
|
1348
|
-
const result =
|
|
1349
|
-
target,
|
|
1350
|
-
await (deps.readJsonObject ?? readJsonObjectFile)(raw.fromJson),
|
|
1351
|
-
withIdempotencyKey(
|
|
1352
|
-
{
|
|
1353
|
-
...revisionOptions,
|
|
1354
|
-
...parsed.idempotencyKey ? { idempotencyKey: parsed.idempotencyKey } : {}
|
|
1355
|
-
},
|
|
1356
|
-
"upd"
|
|
1357
|
-
)
|
|
1358
|
-
) : updateInput ? await deps.client.update(
|
|
1302
|
+
const result = updateInput ? await deps.client.deploy(
|
|
1359
1303
|
target,
|
|
1360
1304
|
updateInput,
|
|
1361
|
-
withIdempotencyKey(
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
"upd"
|
|
1367
|
-
)
|
|
1368
|
-
) : await deps.client.update(target, parsed, revisionOptions);
|
|
1305
|
+
withIdempotencyKey({ ...parsed, ...revisionOptions }, "upd")
|
|
1306
|
+
) : await deps.client.update(
|
|
1307
|
+
target,
|
|
1308
|
+
withIdempotencyKey({ ...parsed, ...revisionOptions }, "upd")
|
|
1309
|
+
);
|
|
1369
1310
|
if (result.error) {
|
|
1370
1311
|
spin?.fail();
|
|
1371
1312
|
return writeApiError(deps, result.error);
|
|
@@ -1549,18 +1490,6 @@ async function handleUpdateDryRun(target, input, raw, deps) {
|
|
|
1549
1490
|
}
|
|
1550
1491
|
try {
|
|
1551
1492
|
assertDropId(target);
|
|
1552
|
-
if (raw.fromJson) {
|
|
1553
|
-
if (input)
|
|
1554
|
-
throw new Error("Use either [input] or --from-json, not both.");
|
|
1555
|
-
const body = await (deps.readJsonObject ?? readJsonObjectFile)(
|
|
1556
|
-
raw.fromJson
|
|
1557
|
-
);
|
|
1558
|
-
deps.stdout(
|
|
1559
|
-
`${JSON.stringify({ dryRun: true, kind: "raw_json", endpoint: `POST /drops/${target}/deployments`, body }, null, 2)}
|
|
1560
|
-
`
|
|
1561
|
-
);
|
|
1562
|
-
return { exitCode: 0 };
|
|
1563
|
-
}
|
|
1564
1493
|
const options = await parseDropOptions(raw);
|
|
1565
1494
|
if (!input) {
|
|
1566
1495
|
const fields = {};
|
|
@@ -1572,7 +1501,7 @@ async function handleUpdateDryRun(target, input, raw, deps) {
|
|
|
1572
1501
|
if (options.expiresAt) fields.expires_at = options.expiresAt;
|
|
1573
1502
|
if (options.metadata) fields.metadata = options.metadata;
|
|
1574
1503
|
deps.stdout(
|
|
1575
|
-
`${JSON.stringify({ dryRun: true, kind: "options_update", target, fields }, null, 2)}
|
|
1504
|
+
`${JSON.stringify({ ok: true, dryRun: true, kind: "options_update", target, fields }, null, 2)}
|
|
1576
1505
|
`
|
|
1577
1506
|
);
|
|
1578
1507
|
return { exitCode: 0 };
|
|
@@ -1582,7 +1511,9 @@ async function handleUpdateDryRun(target, input, raw, deps) {
|
|
|
1582
1511
|
}
|
|
1583
1512
|
const prepared = await deps.client.prepare(input, options);
|
|
1584
1513
|
const output = formatDryRunManifest(prepared, { target });
|
|
1585
|
-
|
|
1514
|
+
if (prepared.kind === "staged") {
|
|
1515
|
+
validateManifestFileCount(prepared.manifest.files.length);
|
|
1516
|
+
}
|
|
1586
1517
|
deps.stdout(`${JSON.stringify(output, null, 2)}
|
|
1587
1518
|
`);
|
|
1588
1519
|
return { exitCode: 0 };
|
|
@@ -1603,6 +1534,7 @@ function assertDropId(target) {
|
|
|
1603
1534
|
// src/commands/whoami.ts
|
|
1604
1535
|
async function runWhoami(_input, deps) {
|
|
1605
1536
|
const credential = await resolveCredential({
|
|
1537
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
1606
1538
|
env: deps.env,
|
|
1607
1539
|
store: deps.store
|
|
1608
1540
|
});
|
|
@@ -1613,21 +1545,34 @@ async function runWhoami(_input, deps) {
|
|
|
1613
1545
|
});
|
|
1614
1546
|
return { exitCode: 0 };
|
|
1615
1547
|
}
|
|
1548
|
+
const result = await deps.client.account.get();
|
|
1549
|
+
if (result.error) {
|
|
1550
|
+
writeHumanOrJson(
|
|
1551
|
+
deps,
|
|
1552
|
+
`Not authenticated: ${result.error.message}. Run dropthis login.`,
|
|
1553
|
+
{ ok: true, authenticated: false, reason: result.error.message }
|
|
1554
|
+
);
|
|
1555
|
+
return { exitCode: 0 };
|
|
1556
|
+
}
|
|
1557
|
+
const account = result.data ?? {};
|
|
1616
1558
|
const masked = maskKey(credential.apiKey);
|
|
1559
|
+
const last4 = credential.keyLast4 ?? credential.apiKey.slice(-4);
|
|
1617
1560
|
const pairs = [];
|
|
1618
|
-
if (credential.email
|
|
1561
|
+
if (credential.email ?? account.email)
|
|
1562
|
+
pairs.push(["Email", String(credential.email ?? account.email)]);
|
|
1619
1563
|
pairs.push(["Key", masked]);
|
|
1620
1564
|
pairs.push(["Source", credential.source]);
|
|
1621
|
-
if (credential.accountId
|
|
1565
|
+
if (credential.accountId ?? account.id)
|
|
1566
|
+
pairs.push(["Account", String(credential.accountId ?? account.id)]);
|
|
1622
1567
|
const jsonEnvelope = {
|
|
1623
1568
|
ok: true,
|
|
1624
1569
|
authenticated: true,
|
|
1625
1570
|
source: credential.source,
|
|
1626
1571
|
masked_key: masked,
|
|
1627
1572
|
...credential.keyId ? { key_id: credential.keyId } : {},
|
|
1628
|
-
...
|
|
1629
|
-
...credential.accountId ? { account_id: credential.accountId } : {},
|
|
1630
|
-
...credential.email ? { email: credential.email } : {}
|
|
1573
|
+
...last4 ? { key_last4: last4 } : {},
|
|
1574
|
+
...credential.accountId ?? account.id ? { account_id: String(credential.accountId ?? account.id) } : {},
|
|
1575
|
+
...credential.email ?? account.email ? { email: String(credential.email ?? account.email) } : {}
|
|
1631
1576
|
};
|
|
1632
1577
|
writeKv(deps, pairs, jsonEnvelope);
|
|
1633
1578
|
return { exitCode: 0 };
|
|
@@ -1660,9 +1605,9 @@ function createContext(input) {
|
|
|
1660
1605
|
}
|
|
1661
1606
|
|
|
1662
1607
|
// src/storage.ts
|
|
1663
|
-
var
|
|
1608
|
+
var import_promises2 = require("fs/promises");
|
|
1664
1609
|
var import_node_os = require("os");
|
|
1665
|
-
var
|
|
1610
|
+
var import_node_path = require("path");
|
|
1666
1611
|
var import_keyring = require("@napi-rs/keyring");
|
|
1667
1612
|
var MemoryCredentialStore = class {
|
|
1668
1613
|
credential = null;
|
|
@@ -1694,7 +1639,7 @@ var InsecureFileCredentialStore = class {
|
|
|
1694
1639
|
});
|
|
1695
1640
|
}
|
|
1696
1641
|
async clear() {
|
|
1697
|
-
await (0,
|
|
1642
|
+
await (0, import_promises2.rm)(this.filePath, { force: true });
|
|
1698
1643
|
}
|
|
1699
1644
|
};
|
|
1700
1645
|
var KeyringCredentialStore = class {
|
|
@@ -1721,7 +1666,7 @@ var KeyringCredentialStore = class {
|
|
|
1721
1666
|
}
|
|
1722
1667
|
async clear() {
|
|
1723
1668
|
await this.keyring.deletePassword();
|
|
1724
|
-
await (0,
|
|
1669
|
+
await (0, import_promises2.rm)(this.filePath, { force: true });
|
|
1725
1670
|
}
|
|
1726
1671
|
};
|
|
1727
1672
|
function createCredentialStore(options = {}) {
|
|
@@ -1739,14 +1684,14 @@ function defaultKeyringAdapter() {
|
|
|
1739
1684
|
};
|
|
1740
1685
|
}
|
|
1741
1686
|
function credentialPath(configDir) {
|
|
1742
|
-
return (0,
|
|
1743
|
-
configDir ?? (0,
|
|
1687
|
+
return (0, import_node_path.join)(
|
|
1688
|
+
configDir ?? (0, import_node_path.join)((0, import_node_os.homedir)(), ".config", "dropthis"),
|
|
1744
1689
|
"credentials.json"
|
|
1745
1690
|
);
|
|
1746
1691
|
}
|
|
1747
1692
|
async function readJsonFile(path) {
|
|
1748
1693
|
try {
|
|
1749
|
-
return JSON.parse(await (0,
|
|
1694
|
+
return JSON.parse(await (0, import_promises2.readFile)(path, "utf8"));
|
|
1750
1695
|
} catch (error2) {
|
|
1751
1696
|
if (error2 && typeof error2 === "object" && "code" in error2 && error2.code === "ENOENT") {
|
|
1752
1697
|
return null;
|
|
@@ -1755,20 +1700,34 @@ async function readJsonFile(path) {
|
|
|
1755
1700
|
}
|
|
1756
1701
|
}
|
|
1757
1702
|
async function writeCredentialFile(path, credential) {
|
|
1758
|
-
await (0,
|
|
1703
|
+
await (0, import_promises2.mkdir)((0, import_node_path.dirname)(path), { recursive: true });
|
|
1759
1704
|
const tmpPath = `${path}.${process.pid}.tmp`;
|
|
1760
|
-
await (0,
|
|
1705
|
+
await (0, import_promises2.writeFile)(tmpPath, `${JSON.stringify(credential, null, 2)}
|
|
1761
1706
|
`, {
|
|
1762
1707
|
mode: 384
|
|
1763
1708
|
});
|
|
1764
|
-
await (0,
|
|
1765
|
-
await (0,
|
|
1709
|
+
await (0, import_promises2.chmod)(tmpPath, 384);
|
|
1710
|
+
await (0, import_promises2.rename)(tmpPath, path);
|
|
1766
1711
|
}
|
|
1767
1712
|
|
|
1768
1713
|
// src/program.ts
|
|
1769
1714
|
function buildProgram(options = {}) {
|
|
1770
1715
|
const program = new import_commander.Command();
|
|
1771
1716
|
const store = options.store ?? new MemoryCredentialStore();
|
|
1717
|
+
const writeErr = options.stderr ?? ((value) => process.stderr.write(value));
|
|
1718
|
+
const jsonModeForOutput = () => {
|
|
1719
|
+
const argv = program.rawArgs ?? process.argv;
|
|
1720
|
+
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;
|
|
1721
|
+
};
|
|
1722
|
+
program.exitOverride();
|
|
1723
|
+
program.configureOutput({
|
|
1724
|
+
writeErr,
|
|
1725
|
+
// In JSON mode, suppress commander's default plain-text error so the
|
|
1726
|
+
// single JSON envelope written by cli.ts's catch is the only output.
|
|
1727
|
+
outputError: (str, write) => {
|
|
1728
|
+
if (!jsonModeForOutput()) write(str);
|
|
1729
|
+
}
|
|
1730
|
+
});
|
|
1772
1731
|
program.name("dropthis").description(
|
|
1773
1732
|
[
|
|
1774
1733
|
import_picocolors4.default.dim("Publish anything online and get a URL back."),
|
|
@@ -1777,7 +1736,7 @@ function buildProgram(options = {}) {
|
|
|
1777
1736
|
` ${import_picocolors4.default.cyan("dropthis login")}`,
|
|
1778
1737
|
` ${import_picocolors4.default.cyan("dropthis publish ./dist")}`
|
|
1779
1738
|
].join("\n")
|
|
1780
|
-
).version("0.
|
|
1739
|
+
).version("0.6.1").configureHelp({
|
|
1781
1740
|
subcommandTerm(cmd) {
|
|
1782
1741
|
const args = cmd.registeredArguments.map((a) => {
|
|
1783
1742
|
const name = a.name();
|
|
@@ -1807,12 +1766,15 @@ function buildProgram(options = {}) {
|
|
|
1807
1766
|
).option(
|
|
1808
1767
|
"--metadata <json>",
|
|
1809
1768
|
`Attach JSON key-value pairs, e.g. '{"source":"ci"}'`
|
|
1810
|
-
).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(
|
|
1769
|
+
).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(
|
|
1770
|
+
"--dry-run",
|
|
1771
|
+
"Show what would be published without publishing (JSON; cannot combine with --url)"
|
|
1772
|
+
).option("--json", "Force JSON output").option(
|
|
1811
1773
|
"--idempotency-key <key>",
|
|
1812
1774
|
"Prevent duplicate publishes on retry (auto-generated)"
|
|
1813
1775
|
).action(async (inputs, commandOptions) => {
|
|
1814
1776
|
const stdinIsTTY = options.stdinIsTTY ?? process.stdin.isTTY ?? false;
|
|
1815
|
-
if (inputs.length === 0 && stdinIsTTY
|
|
1777
|
+
if (inputs.length === 0 && stdinIsTTY) {
|
|
1816
1778
|
program.outputHelp();
|
|
1817
1779
|
return;
|
|
1818
1780
|
}
|
|
@@ -1825,15 +1787,11 @@ function buildProgram(options = {}) {
|
|
|
1825
1787
|
);
|
|
1826
1788
|
let publishInput;
|
|
1827
1789
|
try {
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
options.stdin,
|
|
1834
|
-
stdinIsTTY
|
|
1835
|
-
);
|
|
1836
|
-
}
|
|
1790
|
+
publishInput = await resolvePublishInputs(
|
|
1791
|
+
inputs,
|
|
1792
|
+
options.stdin,
|
|
1793
|
+
stdinIsTTY
|
|
1794
|
+
);
|
|
1837
1795
|
} catch (err) {
|
|
1838
1796
|
const msg = err instanceof Error ? err.message : "Invalid input.";
|
|
1839
1797
|
process.exitCode = writeError(deps, "local_input_error", msg).exitCode;
|
|
@@ -1876,10 +1834,10 @@ function buildProgram(options = {}) {
|
|
|
1876
1834
|
"--if-revision <n>",
|
|
1877
1835
|
"Fail if current revision doesn't match (optimistic lock)",
|
|
1878
1836
|
parseInteger
|
|
1879
|
-
).option("--url", "Print only the published URL (no JSON envelope)").option(
|
|
1880
|
-
"--
|
|
1881
|
-
"
|
|
1882
|
-
).option(
|
|
1837
|
+
).option("--url", "Print only the published URL (no JSON envelope)").option(
|
|
1838
|
+
"--dry-run",
|
|
1839
|
+
"Show what would be updated without updating (JSON; cannot combine with --url)"
|
|
1840
|
+
).option("--json", "Force JSON output").option(
|
|
1883
1841
|
"--idempotency-key <key>",
|
|
1884
1842
|
"Prevent duplicate updates on retry (auto-generated)"
|
|
1885
1843
|
).action(
|
|
@@ -2045,11 +2003,36 @@ function buildProgram(options = {}) {
|
|
|
2045
2003
|
const result = await runWhoami(commandOptions, deps);
|
|
2046
2004
|
process.exitCode = result.exitCode;
|
|
2047
2005
|
});
|
|
2048
|
-
program.command("account").description("Show
|
|
2006
|
+
const account = program.command("account").description("Show or manage your account");
|
|
2007
|
+
account.command("get", { isDefault: true }).description("Show account details").option("--json", "Force JSON output").action(async (commandOptions) => {
|
|
2049
2008
|
const deps = await commandDeps(program, options, store, commandOptions);
|
|
2050
2009
|
const result = await runAccountGet(commandOptions, deps);
|
|
2051
2010
|
process.exitCode = result.exitCode;
|
|
2052
2011
|
});
|
|
2012
|
+
account.command("update").description("Update account display name").requiredOption("--display-name <name>", "Set the display name").option("--json", "Force JSON output").action(async (commandOptions) => {
|
|
2013
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
2014
|
+
const result = await runAccountUpdate(
|
|
2015
|
+
{
|
|
2016
|
+
displayName: commandOptions.displayName,
|
|
2017
|
+
...commandOptions.json !== void 0 ? { json: commandOptions.json } : {}
|
|
2018
|
+
},
|
|
2019
|
+
deps
|
|
2020
|
+
);
|
|
2021
|
+
process.exitCode = result.exitCode;
|
|
2022
|
+
});
|
|
2023
|
+
account.command("delete").description("Delete your account").option("--yes", "Confirm deletion").option("--json", "Force JSON output").action(async (commandOptions) => {
|
|
2024
|
+
const stdinIsTTY = options.stdinIsTTY ?? process.stdin.isTTY ?? false;
|
|
2025
|
+
const global = globalOptions(program, commandOptions);
|
|
2026
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
2027
|
+
const result = await runAccountDelete(
|
|
2028
|
+
{
|
|
2029
|
+
...commandOptions,
|
|
2030
|
+
interactive: isInteractive(stdinIsTTY, deps.env, global)
|
|
2031
|
+
},
|
|
2032
|
+
deps
|
|
2033
|
+
);
|
|
2034
|
+
process.exitCode = result.exitCode;
|
|
2035
|
+
});
|
|
2053
2036
|
program.command("doctor").description("Report CLI diagnostics").option("--json", "Force JSON output").action(async (commandOptions) => {
|
|
2054
2037
|
const deps = await commandDeps(
|
|
2055
2038
|
program,
|
|
@@ -2067,7 +2050,7 @@ function buildProgram(options = {}) {
|
|
|
2067
2050
|
store,
|
|
2068
2051
|
commandOptions
|
|
2069
2052
|
);
|
|
2070
|
-
const result = await runCommands(commandOptions, deps);
|
|
2053
|
+
const result = await runCommands(commandOptions, { ...deps, program });
|
|
2071
2054
|
process.exitCode = result.exitCode;
|
|
2072
2055
|
});
|
|
2073
2056
|
return program;
|
|
@@ -2168,7 +2151,6 @@ function toDropOptions(options) {
|
|
|
2168
2151
|
...options.quiet !== void 0 ? { quiet: options.quiet } : {},
|
|
2169
2152
|
...options.url !== void 0 ? { url: options.url } : {},
|
|
2170
2153
|
...options.ifRevision !== void 0 ? { ifRevision: options.ifRevision } : {},
|
|
2171
|
-
...options.fromJson ? { fromJson: options.fromJson } : {},
|
|
2172
2154
|
...options.dryRun ? { dryRun: options.dryRun } : {}
|
|
2173
2155
|
};
|
|
2174
2156
|
}
|
|
@@ -2196,44 +2178,12 @@ async function resolvePublishInputs(inputs, stdin, stdinIsTTY) {
|
|
|
2196
2178
|
}
|
|
2197
2179
|
return inputs[0];
|
|
2198
2180
|
}
|
|
2199
|
-
|
|
2200
|
-
mkdtemp,
|
|
2201
|
-
copyFile,
|
|
2202
|
-
writeFile: writeFile2,
|
|
2203
|
-
stat: fsStat
|
|
2204
|
-
} = await import("fs/promises");
|
|
2205
|
-
const { join: join2, basename: pathBasename } = await import("path");
|
|
2206
|
-
const { tmpdir } = await import("os");
|
|
2207
|
-
const tmpDir = await mkdtemp(join2(tmpdir(), "dropthis-multi-"));
|
|
2208
|
-
const resolved = [];
|
|
2209
|
-
for (const input of inputs) {
|
|
2210
|
-
if (input === "-") {
|
|
2211
|
-
const buf = await readStdinBytes(stdin ?? process.stdin);
|
|
2212
|
-
const tmpPath = join2(tmpDir, `stdin-${Date.now()}`);
|
|
2213
|
-
await writeFile2(tmpPath, buf);
|
|
2214
|
-
resolved.push(tmpPath);
|
|
2215
|
-
} else {
|
|
2216
|
-
resolved.push(input);
|
|
2217
|
-
}
|
|
2218
|
-
}
|
|
2219
|
-
const names = resolved.map((f) => pathBasename(f));
|
|
2220
|
-
const dupes = names.filter((n, i) => names.indexOf(n) !== i);
|
|
2221
|
-
if (dupes.length > 0) {
|
|
2181
|
+
if (inputs.includes("-")) {
|
|
2222
2182
|
throw new Error(
|
|
2223
|
-
|
|
2183
|
+
"Cannot read stdin (-) alongside multiple file arguments. Pass file paths only."
|
|
2224
2184
|
);
|
|
2225
2185
|
}
|
|
2226
|
-
|
|
2227
|
-
const info = await fsStat(filePath);
|
|
2228
|
-
if (info.isDirectory()) {
|
|
2229
|
-
throw new Error(
|
|
2230
|
-
`Cannot mix directories with multiple file arguments. Use a single folder instead: dropthis publish ${filePath}`
|
|
2231
|
-
);
|
|
2232
|
-
}
|
|
2233
|
-
const destName = pathBasename(filePath);
|
|
2234
|
-
await copyFile(filePath, join2(tmpDir, destName));
|
|
2235
|
-
}
|
|
2236
|
-
return tmpDir;
|
|
2186
|
+
return inputs;
|
|
2237
2187
|
}
|
|
2238
2188
|
async function readStdinBytes(stdin) {
|
|
2239
2189
|
const chunks = [];
|
|
@@ -2246,8 +2196,42 @@ async function readStdinBytes(stdin) {
|
|
|
2246
2196
|
}
|
|
2247
2197
|
|
|
2248
2198
|
// src/cli.ts
|
|
2199
|
+
function writeUsageErrorEnvelope(input) {
|
|
2200
|
+
if (input.json) {
|
|
2201
|
+
input.stderr(
|
|
2202
|
+
`${JSON.stringify(errorEnvelope("usage_error", input.message))}
|
|
2203
|
+
`
|
|
2204
|
+
);
|
|
2205
|
+
} else {
|
|
2206
|
+
input.stderr(`${input.message}
|
|
2207
|
+
`);
|
|
2208
|
+
}
|
|
2209
|
+
return 2;
|
|
2210
|
+
}
|
|
2211
|
+
function isCommanderError(err) {
|
|
2212
|
+
return typeof err === "object" && err !== null && typeof err.code === "string" && err.code.startsWith("commander.");
|
|
2213
|
+
}
|
|
2214
|
+
function wantsJson(argv) {
|
|
2215
|
+
return argv.includes("--json") || argv.includes("--quiet") || argv.includes("-q") || process.env.CI === "true" || process.stdout.isTTY !== true;
|
|
2216
|
+
}
|
|
2249
2217
|
buildProgram({ store: createCredentialStore() }).parseAsync(process.argv).catch((error2) => {
|
|
2218
|
+
if (isCommanderError(error2)) {
|
|
2219
|
+
if (error2.code === "commander.help" || error2.code === "commander.helpDisplayed" || error2.code === "commander.version") {
|
|
2220
|
+
process.exitCode = 0;
|
|
2221
|
+
return;
|
|
2222
|
+
}
|
|
2223
|
+
process.exitCode = writeUsageErrorEnvelope({
|
|
2224
|
+
message: error2.message,
|
|
2225
|
+
json: wantsJson(process.argv.slice(2)),
|
|
2226
|
+
stderr: (value) => process.stderr.write(value)
|
|
2227
|
+
});
|
|
2228
|
+
return;
|
|
2229
|
+
}
|
|
2250
2230
|
console.error(error2);
|
|
2251
2231
|
process.exitCode = 1;
|
|
2252
2232
|
});
|
|
2233
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
2234
|
+
0 && (module.exports = {
|
|
2235
|
+
writeUsageErrorEnvelope
|
|
2236
|
+
});
|
|
2253
2237
|
//# sourceMappingURL=cli.cjs.map
|