@dropthis/cli 0.3.3 → 0.3.5
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 +240 -275
- package/dist/cli.cjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -44,6 +44,15 @@ async function resolveCredential(input) {
|
|
|
44
44
|
...stored.email ? { email: stored.email } : {}
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
|
+
async function requireCredential(input) {
|
|
48
|
+
const credential = await resolveCredential(input);
|
|
49
|
+
if (!credential) {
|
|
50
|
+
throw Object.assign(new Error("No API key found."), {
|
|
51
|
+
code: "auth_error"
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return credential;
|
|
55
|
+
}
|
|
47
56
|
function maskKey(apiKey) {
|
|
48
57
|
return apiKey.length <= 8 ? "sk_..." : `${apiKey.slice(0, 3)}...${apiKey.slice(-4)}`;
|
|
49
58
|
}
|
|
@@ -251,11 +260,13 @@ function writeEmpty(deps, message, json) {
|
|
|
251
260
|
|
|
252
261
|
// src/commands/account.ts
|
|
253
262
|
async function runAccountGet(_input, deps) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
263
|
+
try {
|
|
264
|
+
await requireCredential({
|
|
265
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
266
|
+
env: deps.env,
|
|
267
|
+
store: deps.store
|
|
268
|
+
});
|
|
269
|
+
} catch {
|
|
259
270
|
return writeAuthError(deps);
|
|
260
271
|
}
|
|
261
272
|
const result = await deps.client.account.get();
|
|
@@ -273,8 +284,33 @@ async function runAccountGet(_input, deps) {
|
|
|
273
284
|
|
|
274
285
|
// src/commands/api-keys.ts
|
|
275
286
|
var prompts = __toESM(require("@clack/prompts"), 1);
|
|
287
|
+
|
|
288
|
+
// src/types.ts
|
|
289
|
+
function unwrapListData(data, ...fallbackKeys) {
|
|
290
|
+
if (data && typeof data === "object") {
|
|
291
|
+
if ("data" in data) {
|
|
292
|
+
return data.data;
|
|
293
|
+
}
|
|
294
|
+
for (const key of fallbackKeys) {
|
|
295
|
+
if (key in data) {
|
|
296
|
+
return data[key];
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return data;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// src/commands/api-keys.ts
|
|
276
304
|
async function runApiKeysCreate(input, deps) {
|
|
277
|
-
|
|
305
|
+
try {
|
|
306
|
+
await requireCredential({
|
|
307
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
308
|
+
env: deps.env,
|
|
309
|
+
store: deps.store
|
|
310
|
+
});
|
|
311
|
+
} catch {
|
|
312
|
+
return writeAuthError(deps);
|
|
313
|
+
}
|
|
278
314
|
const result = await deps.client.apiKeys.create({ label: input.label });
|
|
279
315
|
if (result.error) return writeApiErrorSimple(deps, result.error.message);
|
|
280
316
|
const data = result.data;
|
|
@@ -286,10 +322,18 @@ async function runApiKeysCreate(input, deps) {
|
|
|
286
322
|
return { exitCode: 0 };
|
|
287
323
|
}
|
|
288
324
|
async function runApiKeysList(_input, deps) {
|
|
289
|
-
|
|
325
|
+
try {
|
|
326
|
+
await requireCredential({
|
|
327
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
328
|
+
env: deps.env,
|
|
329
|
+
store: deps.store
|
|
330
|
+
});
|
|
331
|
+
} catch {
|
|
332
|
+
return writeAuthError(deps);
|
|
333
|
+
}
|
|
290
334
|
const result = await deps.client.apiKeys.list();
|
|
291
335
|
if (result.error) return writeApiErrorSimple(deps, result.error.message);
|
|
292
|
-
const raw =
|
|
336
|
+
const raw = unwrapListData(result.data, "apiKeys", "api_keys");
|
|
293
337
|
const items = Array.isArray(raw) ? raw : void 0;
|
|
294
338
|
if (deps.outputMode === "human") {
|
|
295
339
|
if (!items || items.length === 0) {
|
|
@@ -323,7 +367,15 @@ async function runApiKeysDelete(keyId, input, deps) {
|
|
|
323
367
|
return { exitCode: 0 };
|
|
324
368
|
}
|
|
325
369
|
}
|
|
326
|
-
|
|
370
|
+
try {
|
|
371
|
+
await requireCredential({
|
|
372
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
373
|
+
env: deps.env,
|
|
374
|
+
store: deps.store
|
|
375
|
+
});
|
|
376
|
+
} catch {
|
|
377
|
+
return writeAuthError(deps);
|
|
378
|
+
}
|
|
327
379
|
const result = await deps.client.apiKeys.delete(keyId);
|
|
328
380
|
if (result?.error) return writeApiErrorSimple(deps, result.error.message);
|
|
329
381
|
writeHumanOrJson(deps, success(`Deleted ${keyId}`), {
|
|
@@ -333,25 +385,9 @@ async function runApiKeysDelete(keyId, input, deps) {
|
|
|
333
385
|
});
|
|
334
386
|
return { exitCode: 0 };
|
|
335
387
|
}
|
|
336
|
-
async function hasCredential(deps) {
|
|
337
|
-
return await resolveCredential({
|
|
338
|
-
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
339
|
-
env: deps.env,
|
|
340
|
-
store: deps.store
|
|
341
|
-
}) !== null;
|
|
342
|
-
}
|
|
343
|
-
function listItems(data) {
|
|
344
|
-
if (data && typeof data === "object" && "data" in data) {
|
|
345
|
-
return data.data;
|
|
346
|
-
}
|
|
347
|
-
if (data && typeof data === "object" && "apiKeys" in data) {
|
|
348
|
-
return data.apiKeys;
|
|
349
|
-
}
|
|
350
|
-
return data;
|
|
351
|
-
}
|
|
352
388
|
|
|
353
|
-
// src/
|
|
354
|
-
var
|
|
389
|
+
// src/catalog.ts
|
|
390
|
+
var COMMAND_CATALOG = [
|
|
355
391
|
{
|
|
356
392
|
name: "publish",
|
|
357
393
|
description: "Publish an input and return a Dropthis URL.",
|
|
@@ -426,70 +462,31 @@ var COMMANDS = [
|
|
|
426
462
|
examples: ["dropthis commands --json"]
|
|
427
463
|
}
|
|
428
464
|
];
|
|
465
|
+
|
|
466
|
+
// src/commands/commands.ts
|
|
429
467
|
async function runCommands(_input, deps) {
|
|
430
468
|
deps.stdout(
|
|
431
469
|
`${JSON.stringify({
|
|
432
470
|
ok: true,
|
|
433
471
|
output: "JSON by default in CI, pipes, non-TTY, --json, or --quiet.",
|
|
434
|
-
commands:
|
|
472
|
+
commands: COMMAND_CATALOG
|
|
435
473
|
})}
|
|
436
474
|
`
|
|
437
475
|
);
|
|
438
476
|
return { exitCode: 0 };
|
|
439
477
|
}
|
|
440
478
|
|
|
441
|
-
// src/commands/completions.ts
|
|
442
|
-
function generateCompletions(program) {
|
|
443
|
-
const name = program.name();
|
|
444
|
-
const cmds = program.commands.map((cmd) => ({
|
|
445
|
-
name: cmd.name(),
|
|
446
|
-
subs: cmd.commands.map((sub) => sub.name()),
|
|
447
|
-
opts: cmd.options.map((o) => o.long).filter(Boolean)
|
|
448
|
-
}));
|
|
449
|
-
const topNames = cmds.map((c) => c.name).join(" ");
|
|
450
|
-
const topOpts = program.options.map((o) => o.long).filter(Boolean).join(" ");
|
|
451
|
-
const cases = cmds.filter((c) => c.subs.length > 0).map(
|
|
452
|
-
(c) => ` ${c.name})
|
|
453
|
-
COMPREPLY=($(compgen -W "${c.subs.join(" ")}" -- "$cur"))
|
|
454
|
-
;;`
|
|
455
|
-
).join("\n");
|
|
456
|
-
return `
|
|
457
|
-
# ${name} shell completions \u2014 add to .bashrc/.zshrc:
|
|
458
|
-
# eval "$(${name} completions)"
|
|
459
|
-
|
|
460
|
-
if type complete &>/dev/null; then
|
|
461
|
-
_${name}_completions() {
|
|
462
|
-
local cur prev cmds
|
|
463
|
-
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
464
|
-
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
465
|
-
cmds="${topNames}"
|
|
466
|
-
|
|
467
|
-
if [[ \${COMP_CWORD} -eq 1 ]]; then
|
|
468
|
-
COMPREPLY=($(compgen -W "$cmds ${topOpts}" -- "$cur"))
|
|
469
|
-
return
|
|
470
|
-
fi
|
|
471
|
-
|
|
472
|
-
case "\${COMP_WORDS[1]}" in
|
|
473
|
-
${cases}
|
|
474
|
-
*)
|
|
475
|
-
COMPREPLY=($(compgen -f -- "$cur"))
|
|
476
|
-
;;
|
|
477
|
-
esac
|
|
478
|
-
}
|
|
479
|
-
complete -F _${name}_completions ${name}
|
|
480
|
-
|
|
481
|
-
elif type compctl &>/dev/null; then
|
|
482
|
-
_${name}_completions() {
|
|
483
|
-
reply=(${topNames})
|
|
484
|
-
}
|
|
485
|
-
compctl -K _${name}_completions + -f ${name}
|
|
486
|
-
fi
|
|
487
|
-
`.trimStart();
|
|
488
|
-
}
|
|
489
|
-
|
|
490
479
|
// src/commands/deployments.ts
|
|
491
480
|
async function runDeploymentsList(dropId, input, deps) {
|
|
492
|
-
|
|
481
|
+
try {
|
|
482
|
+
await requireCredential({
|
|
483
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
484
|
+
env: deps.env,
|
|
485
|
+
store: deps.store
|
|
486
|
+
});
|
|
487
|
+
} catch {
|
|
488
|
+
return writeAuthError(deps);
|
|
489
|
+
}
|
|
493
490
|
const params = {
|
|
494
491
|
...input.limit !== void 0 ? { limit: input.limit } : {},
|
|
495
492
|
...input.cursor ? { cursor: input.cursor } : {}
|
|
@@ -522,7 +519,15 @@ async function runDeploymentsList(dropId, input, deps) {
|
|
|
522
519
|
return { exitCode: 0 };
|
|
523
520
|
}
|
|
524
521
|
async function runDeploymentsGet(dropId, deploymentId, _input, deps) {
|
|
525
|
-
|
|
522
|
+
try {
|
|
523
|
+
await requireCredential({
|
|
524
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
525
|
+
env: deps.env,
|
|
526
|
+
store: deps.store
|
|
527
|
+
});
|
|
528
|
+
} catch {
|
|
529
|
+
return writeAuthError(deps);
|
|
530
|
+
}
|
|
526
531
|
const result = await deps.client.deployments.get(dropId, deploymentId);
|
|
527
532
|
if (result.error) {
|
|
528
533
|
return writeApiError(deps, result.error);
|
|
@@ -536,13 +541,6 @@ async function runDeploymentsGet(dropId, deploymentId, _input, deps) {
|
|
|
536
541
|
writeKv(deps, pairs, { ok: true, deployment: result.data });
|
|
537
542
|
return { exitCode: 0 };
|
|
538
543
|
}
|
|
539
|
-
async function hasCredential2(deps) {
|
|
540
|
-
return await resolveCredential({
|
|
541
|
-
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
542
|
-
env: deps.env,
|
|
543
|
-
store: deps.store
|
|
544
|
-
}) !== null;
|
|
545
|
-
}
|
|
546
544
|
function spreadData(data) {
|
|
547
545
|
return data && typeof data === "object" ? data : { data };
|
|
548
546
|
}
|
|
@@ -557,13 +555,13 @@ async function runDoctor(_input, deps) {
|
|
|
557
555
|
const authSource = credential?.source ?? "missing";
|
|
558
556
|
const storageBackend = stored?.storage ?? "none";
|
|
559
557
|
const pairs = [
|
|
560
|
-
["Version", "0.3.
|
|
558
|
+
["Version", "0.3.5"],
|
|
561
559
|
["Auth", authSource],
|
|
562
560
|
["Storage", storageBackend]
|
|
563
561
|
];
|
|
564
562
|
writeKv(deps, pairs, {
|
|
565
563
|
ok: true,
|
|
566
|
-
version: "0.3.
|
|
564
|
+
version: "0.3.5",
|
|
567
565
|
auth: { source: authSource },
|
|
568
566
|
storage: { backend: storageBackend }
|
|
569
567
|
});
|
|
@@ -573,14 +571,22 @@ async function runDoctor(_input, deps) {
|
|
|
573
571
|
// src/commands/drops.ts
|
|
574
572
|
var prompts2 = __toESM(require("@clack/prompts"), 1);
|
|
575
573
|
async function runDropsList(input, deps) {
|
|
576
|
-
|
|
574
|
+
try {
|
|
575
|
+
await requireCredential({
|
|
576
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
577
|
+
env: deps.env,
|
|
578
|
+
store: deps.store
|
|
579
|
+
});
|
|
580
|
+
} catch {
|
|
581
|
+
return writeAuthError(deps);
|
|
582
|
+
}
|
|
577
583
|
const params = {
|
|
578
584
|
...input.limit !== void 0 ? { limit: input.limit } : {},
|
|
579
585
|
...input.cursor ? { cursor: input.cursor } : {}
|
|
580
586
|
};
|
|
581
587
|
const result = await deps.client.drops.list(params);
|
|
582
588
|
if (result.error) return writeApiErrorSimple(deps, result.error.message);
|
|
583
|
-
const raw =
|
|
589
|
+
const raw = unwrapListData(result.data, "drops");
|
|
584
590
|
const items = Array.isArray(raw) ? raw : void 0;
|
|
585
591
|
if (deps.outputMode === "human") {
|
|
586
592
|
if (!items || items.length === 0) {
|
|
@@ -599,7 +605,15 @@ async function runDropsList(input, deps) {
|
|
|
599
605
|
return { exitCode: 0 };
|
|
600
606
|
}
|
|
601
607
|
async function runDropsGet(dropId, _input, deps) {
|
|
602
|
-
|
|
608
|
+
try {
|
|
609
|
+
await requireCredential({
|
|
610
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
611
|
+
env: deps.env,
|
|
612
|
+
store: deps.store
|
|
613
|
+
});
|
|
614
|
+
} catch {
|
|
615
|
+
return writeAuthError(deps);
|
|
616
|
+
}
|
|
603
617
|
const result = await deps.client.drops.get(dropId);
|
|
604
618
|
if (result.error) return writeApiErrorSimple(deps, result.error.message);
|
|
605
619
|
const data = result.data;
|
|
@@ -636,7 +650,15 @@ async function runDropsDelete(dropId, input, deps) {
|
|
|
636
650
|
return { exitCode: 0 };
|
|
637
651
|
}
|
|
638
652
|
}
|
|
639
|
-
|
|
653
|
+
try {
|
|
654
|
+
await requireCredential({
|
|
655
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
656
|
+
env: deps.env,
|
|
657
|
+
store: deps.store
|
|
658
|
+
});
|
|
659
|
+
} catch {
|
|
660
|
+
return writeAuthError(deps);
|
|
661
|
+
}
|
|
640
662
|
const result = await deps.client.drops.delete(dropId);
|
|
641
663
|
if (result?.error) return writeApiErrorSimple(deps, result.error.message);
|
|
642
664
|
writeHumanOrJson(deps, success(`Deleted ${dropId}`), {
|
|
@@ -646,22 +668,6 @@ async function runDropsDelete(dropId, input, deps) {
|
|
|
646
668
|
});
|
|
647
669
|
return { exitCode: 0 };
|
|
648
670
|
}
|
|
649
|
-
async function hasCredential3(deps) {
|
|
650
|
-
return await resolveCredential({
|
|
651
|
-
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
652
|
-
env: deps.env,
|
|
653
|
-
store: deps.store
|
|
654
|
-
}) !== null;
|
|
655
|
-
}
|
|
656
|
-
function listItems2(data) {
|
|
657
|
-
if (data && typeof data === "object" && "data" in data) {
|
|
658
|
-
return data.data;
|
|
659
|
-
}
|
|
660
|
-
if (data && typeof data === "object" && "drops" in data) {
|
|
661
|
-
return data.drops;
|
|
662
|
-
}
|
|
663
|
-
return data;
|
|
664
|
-
}
|
|
665
671
|
|
|
666
672
|
// src/commands/login.ts
|
|
667
673
|
var prompts3 = __toESM(require("@clack/prompts"), 1);
|
|
@@ -807,9 +813,88 @@ async function runLogout(input, deps) {
|
|
|
807
813
|
}
|
|
808
814
|
|
|
809
815
|
// src/commands/publish.ts
|
|
810
|
-
var import_node_crypto = require("crypto");
|
|
811
816
|
var import_promises3 = require("fs/promises");
|
|
817
|
+
var import_node_path2 = require("path");
|
|
818
|
+
|
|
819
|
+
// src/drop-operations.ts
|
|
820
|
+
var import_node_crypto = require("crypto");
|
|
812
821
|
var import_node_path = require("path");
|
|
822
|
+
var MAX_BUNDLE_FILE_COUNT = 200;
|
|
823
|
+
function isFileSystemError(error2) {
|
|
824
|
+
if (!(error2 instanceof Error)) return false;
|
|
825
|
+
const code = error2.code;
|
|
826
|
+
return code === "ENOENT" || code === "ENOTDIR" || code === "EACCES" || code === "ELIMIT";
|
|
827
|
+
}
|
|
828
|
+
function mimeForPath(filePath) {
|
|
829
|
+
const ext = (0, import_node_path.extname)(filePath).toLowerCase();
|
|
830
|
+
const types = {
|
|
831
|
+
".html": "text/html",
|
|
832
|
+
".htm": "text/html",
|
|
833
|
+
".css": "text/css",
|
|
834
|
+
".js": "text/javascript",
|
|
835
|
+
".mjs": "text/javascript",
|
|
836
|
+
".json": "application/json",
|
|
837
|
+
".xml": "application/xml",
|
|
838
|
+
".svg": "image/svg+xml",
|
|
839
|
+
".txt": "text/plain",
|
|
840
|
+
".md": "text/markdown",
|
|
841
|
+
".jpg": "image/jpeg",
|
|
842
|
+
".jpeg": "image/jpeg",
|
|
843
|
+
".png": "image/png",
|
|
844
|
+
".gif": "image/gif",
|
|
845
|
+
".webp": "image/webp",
|
|
846
|
+
".ico": "image/x-icon",
|
|
847
|
+
".avif": "image/avif",
|
|
848
|
+
".pdf": "application/pdf",
|
|
849
|
+
".zip": "application/zip",
|
|
850
|
+
".woff": "font/woff",
|
|
851
|
+
".woff2": "font/woff2",
|
|
852
|
+
".ttf": "font/ttf",
|
|
853
|
+
".mp4": "video/mp4",
|
|
854
|
+
".webm": "video/webm"
|
|
855
|
+
};
|
|
856
|
+
return types[ext] ?? "application/octet-stream";
|
|
857
|
+
}
|
|
858
|
+
function withIdempotencyKey(options, prefix) {
|
|
859
|
+
return options.idempotencyKey ? options : { ...options, idempotencyKey: `cli_${prefix}_${(0, import_node_crypto.randomUUID)()}` };
|
|
860
|
+
}
|
|
861
|
+
function validateManifestFileCount(count) {
|
|
862
|
+
if (count > MAX_BUNDLE_FILE_COUNT) {
|
|
863
|
+
throw Object.assign(
|
|
864
|
+
new Error(
|
|
865
|
+
`Bundle contains ${count} files, exceeding the maximum of ${MAX_BUNDLE_FILE_COUNT}.`
|
|
866
|
+
),
|
|
867
|
+
{ code: "ELIMIT" }
|
|
868
|
+
);
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
function formatDryRunManifest(prepared, extra) {
|
|
872
|
+
const totalBytes = prepared.manifest.files.reduce(
|
|
873
|
+
(sum, f) => sum + f.sizeBytes,
|
|
874
|
+
0
|
|
875
|
+
);
|
|
876
|
+
return {
|
|
877
|
+
dryRun: true,
|
|
878
|
+
kind: "staged",
|
|
879
|
+
...extra,
|
|
880
|
+
manifest: {
|
|
881
|
+
files: prepared.manifest.files,
|
|
882
|
+
entry: prepared.manifest.entry ?? null
|
|
883
|
+
},
|
|
884
|
+
options: prepared.options,
|
|
885
|
+
...prepared.metadata ? { metadata: prepared.metadata } : {},
|
|
886
|
+
totalBytes
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
function dryRunOptionsBody(options) {
|
|
890
|
+
const result = {};
|
|
891
|
+
if (options.title) result.title = options.title;
|
|
892
|
+
if (options.visibility) result.visibility = options.visibility;
|
|
893
|
+
if (options.password !== void 0) result.password = options.password;
|
|
894
|
+
if (options.noindex !== void 0) result.noindex = options.noindex;
|
|
895
|
+
if (options.expiresAt) result.expires_at = options.expiresAt;
|
|
896
|
+
return result;
|
|
897
|
+
}
|
|
813
898
|
|
|
814
899
|
// src/options.ts
|
|
815
900
|
var import_promises = require("fs/promises");
|
|
@@ -905,14 +990,14 @@ async function readJsonObjectFile(path) {
|
|
|
905
990
|
}
|
|
906
991
|
|
|
907
992
|
// src/commands/publish.ts
|
|
908
|
-
var MAX_BUNDLE_FILE_COUNT = 200;
|
|
909
993
|
async function runPublish(input, raw, deps) {
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
994
|
+
try {
|
|
995
|
+
await requireCredential({
|
|
996
|
+
...raw.apiKey ?? deps.apiKey ? { apiKey: raw.apiKey ?? deps.apiKey } : {},
|
|
997
|
+
env: deps.env,
|
|
998
|
+
store: deps.store
|
|
999
|
+
});
|
|
1000
|
+
} catch {
|
|
916
1001
|
return writeAuthError(deps);
|
|
917
1002
|
}
|
|
918
1003
|
if (raw.dryRun) {
|
|
@@ -924,7 +1009,7 @@ async function runPublish(input, raw, deps) {
|
|
|
924
1009
|
if (raw.fromJson && singleInput) {
|
|
925
1010
|
throw new Error("Use either <input> or --from-json, not both.");
|
|
926
1011
|
}
|
|
927
|
-
const options =
|
|
1012
|
+
const options = withIdempotencyKey(await parseDropOptions(raw), "pub");
|
|
928
1013
|
const result = raw.fromJson ? await deps.client.drops.createRaw(
|
|
929
1014
|
await (deps.readJsonObject ?? readJsonObjectFile)(raw.fromJson),
|
|
930
1015
|
options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {}
|
|
@@ -980,8 +1065,10 @@ async function handlePublishDryRun(input, raw, deps) {
|
|
|
980
1065
|
throw new Error("Client does not support dry-run.");
|
|
981
1066
|
}
|
|
982
1067
|
const prepared = await deps.client.prepare(input, options);
|
|
983
|
-
const output =
|
|
984
|
-
|
|
1068
|
+
const output = formatDryRunManifest(prepared);
|
|
1069
|
+
validateManifestFileCount(
|
|
1070
|
+
output.manifest.files.length
|
|
1071
|
+
);
|
|
985
1072
|
deps.stdout(`${JSON.stringify(output, null, 2)}
|
|
986
1073
|
`);
|
|
987
1074
|
return { exitCode: 0 };
|
|
@@ -1012,18 +1099,12 @@ async function dryRunMultiFile(inputs, options, deps) {
|
|
|
1012
1099
|
);
|
|
1013
1100
|
}
|
|
1014
1101
|
files.push({
|
|
1015
|
-
path: (0,
|
|
1102
|
+
path: (0, import_node_path2.basename)(filePath),
|
|
1016
1103
|
contentType: mimeForPath(filePath),
|
|
1017
1104
|
sizeBytes: info.size
|
|
1018
1105
|
});
|
|
1019
1106
|
}
|
|
1020
|
-
|
|
1021
|
-
return writeError(
|
|
1022
|
-
deps,
|
|
1023
|
-
"local_input_error",
|
|
1024
|
-
`Bundle contains ${files.length} files, exceeding the maximum of ${MAX_BUNDLE_FILE_COUNT}.`
|
|
1025
|
-
);
|
|
1026
|
-
}
|
|
1107
|
+
validateManifestFileCount(files.length);
|
|
1027
1108
|
const entry = options.entry ?? files.find((f) => f.path === "index.html")?.path ?? files[0]?.path ?? null;
|
|
1028
1109
|
const totalBytes = files.reduce((sum, f) => sum + f.sizeBytes, 0);
|
|
1029
1110
|
const output = {
|
|
@@ -1037,92 +1118,16 @@ async function dryRunMultiFile(inputs, options, deps) {
|
|
|
1037
1118
|
`);
|
|
1038
1119
|
return { exitCode: 0 };
|
|
1039
1120
|
}
|
|
1040
|
-
function formatDryRunOutput(prepared) {
|
|
1041
|
-
const totalBytes = prepared.manifest.files.reduce(
|
|
1042
|
-
(sum, f) => sum + f.sizeBytes,
|
|
1043
|
-
0
|
|
1044
|
-
);
|
|
1045
|
-
return {
|
|
1046
|
-
dryRun: true,
|
|
1047
|
-
kind: "staged",
|
|
1048
|
-
manifest: {
|
|
1049
|
-
files: prepared.manifest.files,
|
|
1050
|
-
entry: prepared.manifest.entry ?? null
|
|
1051
|
-
},
|
|
1052
|
-
options: prepared.options,
|
|
1053
|
-
...prepared.metadata ? { metadata: prepared.metadata } : {},
|
|
1054
|
-
totalBytes
|
|
1055
|
-
};
|
|
1056
|
-
}
|
|
1057
|
-
function validateDryRunOutput(output) {
|
|
1058
|
-
if (output.kind !== "staged") return;
|
|
1059
|
-
const manifest = output.manifest;
|
|
1060
|
-
if (manifest.files.length > MAX_BUNDLE_FILE_COUNT) {
|
|
1061
|
-
throw Object.assign(
|
|
1062
|
-
new Error(
|
|
1063
|
-
`Bundle contains ${manifest.files.length} files, exceeding the maximum of ${MAX_BUNDLE_FILE_COUNT}.`
|
|
1064
|
-
),
|
|
1065
|
-
{ code: "ELIMIT" }
|
|
1066
|
-
);
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
function dryRunOptionsBody(options) {
|
|
1070
|
-
const result = {};
|
|
1071
|
-
if (options.title) result.title = options.title;
|
|
1072
|
-
if (options.visibility) result.visibility = options.visibility;
|
|
1073
|
-
if (options.password !== void 0) result.password = options.password;
|
|
1074
|
-
if (options.noindex !== void 0) result.noindex = options.noindex;
|
|
1075
|
-
if (options.expiresAt) result.expires_at = options.expiresAt;
|
|
1076
|
-
return result;
|
|
1077
|
-
}
|
|
1078
|
-
function mimeForPath(filePath) {
|
|
1079
|
-
const ext = (0, import_node_path.extname)(filePath).toLowerCase();
|
|
1080
|
-
const types = {
|
|
1081
|
-
".html": "text/html",
|
|
1082
|
-
".htm": "text/html",
|
|
1083
|
-
".css": "text/css",
|
|
1084
|
-
".js": "text/javascript",
|
|
1085
|
-
".mjs": "text/javascript",
|
|
1086
|
-
".json": "application/json",
|
|
1087
|
-
".xml": "application/xml",
|
|
1088
|
-
".svg": "image/svg+xml",
|
|
1089
|
-
".txt": "text/plain",
|
|
1090
|
-
".md": "text/markdown",
|
|
1091
|
-
".jpg": "image/jpeg",
|
|
1092
|
-
".jpeg": "image/jpeg",
|
|
1093
|
-
".png": "image/png",
|
|
1094
|
-
".gif": "image/gif",
|
|
1095
|
-
".webp": "image/webp",
|
|
1096
|
-
".ico": "image/x-icon",
|
|
1097
|
-
".avif": "image/avif",
|
|
1098
|
-
".pdf": "application/pdf",
|
|
1099
|
-
".zip": "application/zip",
|
|
1100
|
-
".woff": "font/woff",
|
|
1101
|
-
".woff2": "font/woff2",
|
|
1102
|
-
".ttf": "font/ttf",
|
|
1103
|
-
".mp4": "video/mp4",
|
|
1104
|
-
".webm": "video/webm"
|
|
1105
|
-
};
|
|
1106
|
-
return types[ext] ?? "application/octet-stream";
|
|
1107
|
-
}
|
|
1108
|
-
function isFileSystemError(error2) {
|
|
1109
|
-
if (!(error2 instanceof Error)) return false;
|
|
1110
|
-
const code = error2.code;
|
|
1111
|
-
return code === "ENOENT" || code === "ENOTDIR" || code === "EACCES" || code === "ELIMIT";
|
|
1112
|
-
}
|
|
1113
|
-
function withPublishIdempotency(options) {
|
|
1114
|
-
return options.idempotencyKey ? options : { ...options, idempotencyKey: `cli_pub_${(0, import_node_crypto.randomUUID)()}` };
|
|
1115
|
-
}
|
|
1116
1121
|
|
|
1117
1122
|
// src/commands/update.ts
|
|
1118
|
-
var import_node_crypto2 = require("crypto");
|
|
1119
1123
|
async function runUpdate(target, input, raw, deps) {
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1124
|
+
try {
|
|
1125
|
+
await requireCredential({
|
|
1126
|
+
...raw.apiKey ?? deps.apiKey ? { apiKey: raw.apiKey ?? deps.apiKey } : {},
|
|
1127
|
+
env: deps.env,
|
|
1128
|
+
store: deps.store
|
|
1129
|
+
});
|
|
1130
|
+
} catch {
|
|
1126
1131
|
return writeAuthError(deps);
|
|
1127
1132
|
}
|
|
1128
1133
|
if (raw.dryRun) {
|
|
@@ -1139,17 +1144,23 @@ async function runUpdate(target, input, raw, deps) {
|
|
|
1139
1144
|
const result = raw.fromJson ? await deps.client.deployments.createRaw(
|
|
1140
1145
|
target,
|
|
1141
1146
|
await (deps.readJsonObject ?? readJsonObjectFile)(raw.fromJson),
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1147
|
+
withIdempotencyKey(
|
|
1148
|
+
{
|
|
1149
|
+
...revisionOptions,
|
|
1150
|
+
...parsed.idempotencyKey ? { idempotencyKey: parsed.idempotencyKey } : {}
|
|
1151
|
+
},
|
|
1152
|
+
"upd"
|
|
1153
|
+
)
|
|
1146
1154
|
) : input ? await deps.client.update(
|
|
1147
1155
|
target,
|
|
1148
1156
|
input,
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1157
|
+
withIdempotencyKey(
|
|
1158
|
+
{
|
|
1159
|
+
...parsed,
|
|
1160
|
+
...revisionOptions
|
|
1161
|
+
},
|
|
1162
|
+
"upd"
|
|
1163
|
+
)
|
|
1153
1164
|
) : await deps.client.update(target, parsed, revisionOptions);
|
|
1154
1165
|
if (result.error) {
|
|
1155
1166
|
spin?.fail();
|
|
@@ -1162,8 +1173,9 @@ async function runUpdate(target, input, raw, deps) {
|
|
|
1162
1173
|
return { exitCode: 0 };
|
|
1163
1174
|
} catch (error2) {
|
|
1164
1175
|
const message = error2 instanceof Error ? error2.message : "Update failed.";
|
|
1176
|
+
const code = isFileSystemError(error2) ? "local_input_error" : "invalid_usage";
|
|
1165
1177
|
spin?.fail();
|
|
1166
|
-
return writeError(deps,
|
|
1178
|
+
return writeError(deps, code, message);
|
|
1167
1179
|
}
|
|
1168
1180
|
}
|
|
1169
1181
|
async function handleUpdateDryRun(target, input, raw, deps) {
|
|
@@ -1209,56 +1221,17 @@ async function handleUpdateDryRun(target, input, raw, deps) {
|
|
|
1209
1221
|
throw new Error("Client does not support dry-run.");
|
|
1210
1222
|
}
|
|
1211
1223
|
const prepared = await deps.client.prepare(input, options);
|
|
1212
|
-
const output =
|
|
1213
|
-
|
|
1224
|
+
const output = formatDryRunManifest(prepared, { target });
|
|
1225
|
+
validateManifestFileCount(prepared.manifest.files.length);
|
|
1214
1226
|
deps.stdout(`${JSON.stringify(output, null, 2)}
|
|
1215
1227
|
`);
|
|
1216
1228
|
return { exitCode: 0 };
|
|
1217
1229
|
} catch (error2) {
|
|
1218
|
-
const code =
|
|
1230
|
+
const code = isFileSystemError(error2) ? "local_input_error" : "invalid_usage";
|
|
1219
1231
|
const message = error2 instanceof Error ? error2.message : "Dry-run failed.";
|
|
1220
1232
|
return writeError(deps, code, message);
|
|
1221
1233
|
}
|
|
1222
1234
|
}
|
|
1223
|
-
var MAX_BUNDLE_FILE_COUNT2 = 200;
|
|
1224
|
-
function formatUpdateDryRun(target, prepared) {
|
|
1225
|
-
const totalBytes = prepared.manifest.files.reduce(
|
|
1226
|
-
(sum, f) => sum + f.sizeBytes,
|
|
1227
|
-
0
|
|
1228
|
-
);
|
|
1229
|
-
return {
|
|
1230
|
-
dryRun: true,
|
|
1231
|
-
kind: "staged",
|
|
1232
|
-
target,
|
|
1233
|
-
manifest: {
|
|
1234
|
-
files: prepared.manifest.files,
|
|
1235
|
-
entry: prepared.manifest.entry ?? null
|
|
1236
|
-
},
|
|
1237
|
-
options: prepared.options,
|
|
1238
|
-
...prepared.metadata ? { metadata: prepared.metadata } : {},
|
|
1239
|
-
totalBytes
|
|
1240
|
-
};
|
|
1241
|
-
}
|
|
1242
|
-
function validateDryRunFileCount(output) {
|
|
1243
|
-
if (output.kind !== "staged") return;
|
|
1244
|
-
const manifest = output.manifest;
|
|
1245
|
-
if (manifest.files.length > MAX_BUNDLE_FILE_COUNT2) {
|
|
1246
|
-
throw Object.assign(
|
|
1247
|
-
new Error(
|
|
1248
|
-
`Bundle contains ${manifest.files.length} files, exceeding the maximum of ${MAX_BUNDLE_FILE_COUNT2}.`
|
|
1249
|
-
),
|
|
1250
|
-
{ code: "ELIMIT" }
|
|
1251
|
-
);
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1254
|
-
function isFileSystemError2(error2) {
|
|
1255
|
-
if (!(error2 instanceof Error)) return false;
|
|
1256
|
-
const code = error2.code;
|
|
1257
|
-
return code === "ENOENT" || code === "ENOTDIR";
|
|
1258
|
-
}
|
|
1259
|
-
function withUpdateIdempotency(options) {
|
|
1260
|
-
return options.idempotencyKey ? options : { ...options, idempotencyKey: `cli_upd_${(0, import_node_crypto2.randomUUID)()}` };
|
|
1261
|
-
}
|
|
1262
1235
|
function assertDropId(target) {
|
|
1263
1236
|
if (!target.startsWith("drop_")) {
|
|
1264
1237
|
throw new Error(
|
|
@@ -1329,7 +1302,7 @@ function createContext(input) {
|
|
|
1329
1302
|
// src/storage.ts
|
|
1330
1303
|
var import_promises4 = require("fs/promises");
|
|
1331
1304
|
var import_node_os = require("os");
|
|
1332
|
-
var
|
|
1305
|
+
var import_node_path3 = require("path");
|
|
1333
1306
|
var import_keyring = require("@napi-rs/keyring");
|
|
1334
1307
|
var MemoryCredentialStore = class {
|
|
1335
1308
|
credential = null;
|
|
@@ -1406,8 +1379,8 @@ function defaultKeyringAdapter() {
|
|
|
1406
1379
|
};
|
|
1407
1380
|
}
|
|
1408
1381
|
function credentialPath(configDir) {
|
|
1409
|
-
return (0,
|
|
1410
|
-
configDir ?? (0,
|
|
1382
|
+
return (0, import_node_path3.join)(
|
|
1383
|
+
configDir ?? (0, import_node_path3.join)((0, import_node_os.homedir)(), ".config", "dropthis"),
|
|
1411
1384
|
"credentials.json"
|
|
1412
1385
|
);
|
|
1413
1386
|
}
|
|
@@ -1422,7 +1395,7 @@ async function readJsonFile(path) {
|
|
|
1422
1395
|
}
|
|
1423
1396
|
}
|
|
1424
1397
|
async function writeCredentialFile(path, credential) {
|
|
1425
|
-
await (0, import_promises4.mkdir)((0,
|
|
1398
|
+
await (0, import_promises4.mkdir)((0, import_node_path3.dirname)(path), { recursive: true });
|
|
1426
1399
|
await (0, import_promises4.writeFile)(path, `${JSON.stringify(credential, null, 2)}
|
|
1427
1400
|
`, {
|
|
1428
1401
|
mode: 384
|
|
@@ -1442,7 +1415,7 @@ function buildProgram(options = {}) {
|
|
|
1442
1415
|
` ${import_picocolors4.default.cyan("dropthis login")}`,
|
|
1443
1416
|
` ${import_picocolors4.default.cyan("dropthis publish ./dist")}`
|
|
1444
1417
|
].join("\n")
|
|
1445
|
-
).version("0.3.
|
|
1418
|
+
).version("0.3.5").configureHelp({
|
|
1446
1419
|
subcommandTerm(cmd) {
|
|
1447
1420
|
const args = cmd.registeredArguments.map((a) => {
|
|
1448
1421
|
const name = a.name();
|
|
@@ -1689,9 +1662,6 @@ function buildProgram(options = {}) {
|
|
|
1689
1662
|
const result = await runAccountGet(commandOptions, deps);
|
|
1690
1663
|
process.exitCode = result.exitCode;
|
|
1691
1664
|
});
|
|
1692
|
-
program.command("completions").description("Output shell completions for bash/zsh").action(() => {
|
|
1693
|
-
process.stdout.write(generateCompletions(program));
|
|
1694
|
-
});
|
|
1695
1665
|
program.command("doctor").description("Report CLI diagnostics").option("--json", "Force JSON output").action(async (commandOptions) => {
|
|
1696
1666
|
const deps = await commandDeps(
|
|
1697
1667
|
program,
|
|
@@ -1748,15 +1718,10 @@ function globalOptions(program, commandOptions) {
|
|
|
1748
1718
|
};
|
|
1749
1719
|
}
|
|
1750
1720
|
function toDropOptions(options) {
|
|
1751
|
-
if (options.visibility && options.visibility !== "public" && options.visibility !== "unlisted") {
|
|
1752
|
-
throw new Error(
|
|
1753
|
-
`Invalid visibility "${options.visibility}". Use "public" or "unlisted".`
|
|
1754
|
-
);
|
|
1755
|
-
}
|
|
1756
1721
|
return {
|
|
1757
1722
|
...options.slug ? { slug: options.slug } : {},
|
|
1758
1723
|
...options.title ? { title: options.title } : {},
|
|
1759
|
-
...options.visibility
|
|
1724
|
+
...options.visibility ? { visibility: options.visibility } : {},
|
|
1760
1725
|
...typeof options.password === "string" ? { password: options.password } : {},
|
|
1761
1726
|
...options.password === false || options.noPassword ? { noPassword: true } : {},
|
|
1762
1727
|
...options.noindex ? { noindex: true } : {},
|