@dropthis/cli 0.5.0 → 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 +329 -283
- 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"],
|
|
541
|
-
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"],
|
|
600
|
+
drops: {
|
|
549
601
|
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,46 +1292,6 @@ 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
|
|
1307
1297
|
var prompts4 = __toESM(require("@clack/prompts"), 1);
|
|
@@ -1355,17 +1345,14 @@ async function runUpdate(target, input, raw, deps) {
|
|
|
1355
1345
|
},
|
|
1356
1346
|
"upd"
|
|
1357
1347
|
)
|
|
1358
|
-
) : updateInput ? await deps.client.
|
|
1348
|
+
) : updateInput ? await deps.client.deploy(
|
|
1359
1349
|
target,
|
|
1360
1350
|
updateInput,
|
|
1361
|
-
withIdempotencyKey(
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
"upd"
|
|
1367
|
-
)
|
|
1368
|
-
) : await deps.client.update(target, parsed, revisionOptions);
|
|
1351
|
+
withIdempotencyKey({ ...parsed, ...revisionOptions }, "upd")
|
|
1352
|
+
) : await deps.client.update(
|
|
1353
|
+
target,
|
|
1354
|
+
withIdempotencyKey({ ...parsed, ...revisionOptions }, "upd")
|
|
1355
|
+
);
|
|
1369
1356
|
if (result.error) {
|
|
1370
1357
|
spin?.fail();
|
|
1371
1358
|
return writeApiError(deps, result.error);
|
|
@@ -1556,7 +1543,7 @@ async function handleUpdateDryRun(target, input, raw, deps) {
|
|
|
1556
1543
|
raw.fromJson
|
|
1557
1544
|
);
|
|
1558
1545
|
deps.stdout(
|
|
1559
|
-
`${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)}
|
|
1560
1547
|
`
|
|
1561
1548
|
);
|
|
1562
1549
|
return { exitCode: 0 };
|
|
@@ -1572,7 +1559,7 @@ async function handleUpdateDryRun(target, input, raw, deps) {
|
|
|
1572
1559
|
if (options.expiresAt) fields.expires_at = options.expiresAt;
|
|
1573
1560
|
if (options.metadata) fields.metadata = options.metadata;
|
|
1574
1561
|
deps.stdout(
|
|
1575
|
-
`${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)}
|
|
1576
1563
|
`
|
|
1577
1564
|
);
|
|
1578
1565
|
return { exitCode: 0 };
|
|
@@ -1582,7 +1569,9 @@ async function handleUpdateDryRun(target, input, raw, deps) {
|
|
|
1582
1569
|
}
|
|
1583
1570
|
const prepared = await deps.client.prepare(input, options);
|
|
1584
1571
|
const output = formatDryRunManifest(prepared, { target });
|
|
1585
|
-
|
|
1572
|
+
if (prepared.kind === "staged") {
|
|
1573
|
+
validateManifestFileCount(prepared.manifest.files.length);
|
|
1574
|
+
}
|
|
1586
1575
|
deps.stdout(`${JSON.stringify(output, null, 2)}
|
|
1587
1576
|
`);
|
|
1588
1577
|
return { exitCode: 0 };
|
|
@@ -1603,6 +1592,7 @@ function assertDropId(target) {
|
|
|
1603
1592
|
// src/commands/whoami.ts
|
|
1604
1593
|
async function runWhoami(_input, deps) {
|
|
1605
1594
|
const credential = await resolveCredential({
|
|
1595
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
1606
1596
|
env: deps.env,
|
|
1607
1597
|
store: deps.store
|
|
1608
1598
|
});
|
|
@@ -1613,21 +1603,34 @@ async function runWhoami(_input, deps) {
|
|
|
1613
1603
|
});
|
|
1614
1604
|
return { exitCode: 0 };
|
|
1615
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 ?? {};
|
|
1616
1616
|
const masked = maskKey(credential.apiKey);
|
|
1617
|
+
const last4 = credential.keyLast4 ?? credential.apiKey.slice(-4);
|
|
1617
1618
|
const pairs = [];
|
|
1618
|
-
if (credential.email
|
|
1619
|
+
if (credential.email ?? account.email)
|
|
1620
|
+
pairs.push(["Email", String(credential.email ?? account.email)]);
|
|
1619
1621
|
pairs.push(["Key", masked]);
|
|
1620
1622
|
pairs.push(["Source", credential.source]);
|
|
1621
|
-
if (credential.accountId
|
|
1623
|
+
if (credential.accountId ?? account.id)
|
|
1624
|
+
pairs.push(["Account", String(credential.accountId ?? account.id)]);
|
|
1622
1625
|
const jsonEnvelope = {
|
|
1623
1626
|
ok: true,
|
|
1624
1627
|
authenticated: true,
|
|
1625
1628
|
source: credential.source,
|
|
1626
1629
|
masked_key: masked,
|
|
1627
1630
|
...credential.keyId ? { key_id: credential.keyId } : {},
|
|
1628
|
-
...
|
|
1629
|
-
...credential.accountId ? { account_id: credential.accountId } : {},
|
|
1630
|
-
...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) } : {}
|
|
1631
1634
|
};
|
|
1632
1635
|
writeKv(deps, pairs, jsonEnvelope);
|
|
1633
1636
|
return { exitCode: 0 };
|
|
@@ -1660,9 +1663,9 @@ function createContext(input) {
|
|
|
1660
1663
|
}
|
|
1661
1664
|
|
|
1662
1665
|
// src/storage.ts
|
|
1663
|
-
var
|
|
1666
|
+
var import_promises3 = require("fs/promises");
|
|
1664
1667
|
var import_node_os = require("os");
|
|
1665
|
-
var
|
|
1668
|
+
var import_node_path = require("path");
|
|
1666
1669
|
var import_keyring = require("@napi-rs/keyring");
|
|
1667
1670
|
var MemoryCredentialStore = class {
|
|
1668
1671
|
credential = null;
|
|
@@ -1694,7 +1697,7 @@ var InsecureFileCredentialStore = class {
|
|
|
1694
1697
|
});
|
|
1695
1698
|
}
|
|
1696
1699
|
async clear() {
|
|
1697
|
-
await (0,
|
|
1700
|
+
await (0, import_promises3.rm)(this.filePath, { force: true });
|
|
1698
1701
|
}
|
|
1699
1702
|
};
|
|
1700
1703
|
var KeyringCredentialStore = class {
|
|
@@ -1721,7 +1724,7 @@ var KeyringCredentialStore = class {
|
|
|
1721
1724
|
}
|
|
1722
1725
|
async clear() {
|
|
1723
1726
|
await this.keyring.deletePassword();
|
|
1724
|
-
await (0,
|
|
1727
|
+
await (0, import_promises3.rm)(this.filePath, { force: true });
|
|
1725
1728
|
}
|
|
1726
1729
|
};
|
|
1727
1730
|
function createCredentialStore(options = {}) {
|
|
@@ -1739,14 +1742,14 @@ function defaultKeyringAdapter() {
|
|
|
1739
1742
|
};
|
|
1740
1743
|
}
|
|
1741
1744
|
function credentialPath(configDir) {
|
|
1742
|
-
return (0,
|
|
1743
|
-
configDir ?? (0,
|
|
1745
|
+
return (0, import_node_path.join)(
|
|
1746
|
+
configDir ?? (0, import_node_path.join)((0, import_node_os.homedir)(), ".config", "dropthis"),
|
|
1744
1747
|
"credentials.json"
|
|
1745
1748
|
);
|
|
1746
1749
|
}
|
|
1747
1750
|
async function readJsonFile(path) {
|
|
1748
1751
|
try {
|
|
1749
|
-
return JSON.parse(await (0,
|
|
1752
|
+
return JSON.parse(await (0, import_promises3.readFile)(path, "utf8"));
|
|
1750
1753
|
} catch (error2) {
|
|
1751
1754
|
if (error2 && typeof error2 === "object" && "code" in error2 && error2.code === "ENOENT") {
|
|
1752
1755
|
return null;
|
|
@@ -1755,20 +1758,34 @@ async function readJsonFile(path) {
|
|
|
1755
1758
|
}
|
|
1756
1759
|
}
|
|
1757
1760
|
async function writeCredentialFile(path, credential) {
|
|
1758
|
-
await (0,
|
|
1761
|
+
await (0, import_promises3.mkdir)((0, import_node_path.dirname)(path), { recursive: true });
|
|
1759
1762
|
const tmpPath = `${path}.${process.pid}.tmp`;
|
|
1760
|
-
await (0,
|
|
1763
|
+
await (0, import_promises3.writeFile)(tmpPath, `${JSON.stringify(credential, null, 2)}
|
|
1761
1764
|
`, {
|
|
1762
1765
|
mode: 384
|
|
1763
1766
|
});
|
|
1764
|
-
await (0,
|
|
1765
|
-
await (0,
|
|
1767
|
+
await (0, import_promises3.chmod)(tmpPath, 384);
|
|
1768
|
+
await (0, import_promises3.rename)(tmpPath, path);
|
|
1766
1769
|
}
|
|
1767
1770
|
|
|
1768
1771
|
// src/program.ts
|
|
1769
1772
|
function buildProgram(options = {}) {
|
|
1770
1773
|
const program = new import_commander.Command();
|
|
1771
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
|
+
});
|
|
1772
1789
|
program.name("dropthis").description(
|
|
1773
1790
|
[
|
|
1774
1791
|
import_picocolors4.default.dim("Publish anything online and get a URL back."),
|
|
@@ -1777,7 +1794,7 @@ function buildProgram(options = {}) {
|
|
|
1777
1794
|
` ${import_picocolors4.default.cyan("dropthis login")}`,
|
|
1778
1795
|
` ${import_picocolors4.default.cyan("dropthis publish ./dist")}`
|
|
1779
1796
|
].join("\n")
|
|
1780
|
-
).version("0.
|
|
1797
|
+
).version("0.6.0").configureHelp({
|
|
1781
1798
|
subcommandTerm(cmd) {
|
|
1782
1799
|
const args = cmd.registeredArguments.map((a) => {
|
|
1783
1800
|
const name = a.name();
|
|
@@ -1807,7 +1824,10 @@ function buildProgram(options = {}) {
|
|
|
1807
1824
|
).option(
|
|
1808
1825
|
"--metadata <json>",
|
|
1809
1826
|
`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(
|
|
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(
|
|
1811
1831
|
"--idempotency-key <key>",
|
|
1812
1832
|
"Prevent duplicate publishes on retry (auto-generated)"
|
|
1813
1833
|
).action(async (inputs, commandOptions) => {
|
|
@@ -1825,15 +1845,11 @@ function buildProgram(options = {}) {
|
|
|
1825
1845
|
);
|
|
1826
1846
|
let publishInput;
|
|
1827
1847
|
try {
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
options.stdin,
|
|
1834
|
-
stdinIsTTY
|
|
1835
|
-
);
|
|
1836
|
-
}
|
|
1848
|
+
publishInput = await resolvePublishInputs(
|
|
1849
|
+
inputs,
|
|
1850
|
+
options.stdin,
|
|
1851
|
+
stdinIsTTY
|
|
1852
|
+
);
|
|
1837
1853
|
} catch (err) {
|
|
1838
1854
|
const msg = err instanceof Error ? err.message : "Invalid input.";
|
|
1839
1855
|
process.exitCode = writeError(deps, "local_input_error", msg).exitCode;
|
|
@@ -1876,7 +1892,10 @@ function buildProgram(options = {}) {
|
|
|
1876
1892
|
"--if-revision <n>",
|
|
1877
1893
|
"Fail if current revision doesn't match (optimistic lock)",
|
|
1878
1894
|
parseInteger
|
|
1879
|
-
).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(
|
|
1880
1899
|
"--from-json <path>",
|
|
1881
1900
|
"Send raw API deployment body from a JSON file"
|
|
1882
1901
|
).option(
|
|
@@ -2045,11 +2064,36 @@ function buildProgram(options = {}) {
|
|
|
2045
2064
|
const result = await runWhoami(commandOptions, deps);
|
|
2046
2065
|
process.exitCode = result.exitCode;
|
|
2047
2066
|
});
|
|
2048
|
-
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) => {
|
|
2049
2069
|
const deps = await commandDeps(program, options, store, commandOptions);
|
|
2050
2070
|
const result = await runAccountGet(commandOptions, deps);
|
|
2051
2071
|
process.exitCode = result.exitCode;
|
|
2052
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
|
+
});
|
|
2053
2097
|
program.command("doctor").description("Report CLI diagnostics").option("--json", "Force JSON output").action(async (commandOptions) => {
|
|
2054
2098
|
const deps = await commandDeps(
|
|
2055
2099
|
program,
|
|
@@ -2067,7 +2111,7 @@ function buildProgram(options = {}) {
|
|
|
2067
2111
|
store,
|
|
2068
2112
|
commandOptions
|
|
2069
2113
|
);
|
|
2070
|
-
const result = await runCommands(commandOptions, deps);
|
|
2114
|
+
const result = await runCommands(commandOptions, { ...deps, program });
|
|
2071
2115
|
process.exitCode = result.exitCode;
|
|
2072
2116
|
});
|
|
2073
2117
|
return program;
|
|
@@ -2196,44 +2240,12 @@ async function resolvePublishInputs(inputs, stdin, stdinIsTTY) {
|
|
|
2196
2240
|
}
|
|
2197
2241
|
return inputs[0];
|
|
2198
2242
|
}
|
|
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) {
|
|
2243
|
+
if (inputs.includes("-")) {
|
|
2222
2244
|
throw new Error(
|
|
2223
|
-
|
|
2245
|
+
"Cannot read stdin (-) alongside multiple file arguments. Pass file paths only."
|
|
2224
2246
|
);
|
|
2225
2247
|
}
|
|
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;
|
|
2248
|
+
return inputs;
|
|
2237
2249
|
}
|
|
2238
2250
|
async function readStdinBytes(stdin) {
|
|
2239
2251
|
const chunks = [];
|
|
@@ -2246,8 +2258,42 @@ async function readStdinBytes(stdin) {
|
|
|
2246
2258
|
}
|
|
2247
2259
|
|
|
2248
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
|
+
}
|
|
2249
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
|
+
}
|
|
2250
2292
|
console.error(error2);
|
|
2251
2293
|
process.exitCode = 1;
|
|
2252
2294
|
});
|
|
2295
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
2296
|
+
0 && (module.exports = {
|
|
2297
|
+
writeUsageErrorEnvelope
|
|
2298
|
+
});
|
|
2253
2299
|
//# sourceMappingURL=cli.cjs.map
|