@dropthis/cli 0.3.4 → 0.4.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 +247 -224
- package/dist/cli.cjs.map +1 -1
- package/node_modules/@dropthis/node/README.md +181 -53
- package/node_modules/@dropthis/node/dist/index.cjs +178 -157
- package/node_modules/@dropthis/node/dist/index.cjs.map +1 -1
- package/node_modules/@dropthis/node/dist/index.d.cts +87 -26
- package/node_modules/@dropthis/node/dist/index.d.ts +87 -26
- package/node_modules/@dropthis/node/dist/index.mjs +177 -157
- 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
|
@@ -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
|
}
|
|
@@ -84,11 +93,14 @@ function apiErrorEnvelope(error2) {
|
|
|
84
93
|
...error2.param ? { param: error2.param } : {},
|
|
85
94
|
...error2.currentRevision !== void 0 ? { current_revision: error2.currentRevision } : {},
|
|
86
95
|
...error2.requestId ? { request_id: error2.requestId } : {},
|
|
96
|
+
...error2.suggestion ? { suggestion: error2.suggestion } : {},
|
|
97
|
+
...error2.retryable !== void 0 && error2.retryable !== null ? { retryable: error2.retryable } : {},
|
|
87
98
|
next_action: nextActionForApiError(error2)
|
|
88
99
|
}
|
|
89
100
|
};
|
|
90
101
|
}
|
|
91
102
|
function nextActionForApiError(error2) {
|
|
103
|
+
if (error2.suggestion) return error2.suggestion;
|
|
92
104
|
const uploadNextAction = error2.code ? UPLOAD_NEXT_ACTIONS[error2.code] : void 0;
|
|
93
105
|
if (uploadNextAction) return uploadNextAction;
|
|
94
106
|
if (error2.code === "revision_conflict") {
|
|
@@ -212,8 +224,11 @@ function writeApiError(deps, details) {
|
|
|
212
224
|
if (deps.outputMode === "human") {
|
|
213
225
|
deps.stderr(`${error(details.message)}
|
|
214
226
|
`);
|
|
215
|
-
const nextAction = details
|
|
227
|
+
const nextAction = nextActionForApiError(details);
|
|
216
228
|
if (nextAction) deps.stderr(`${hint(nextAction)}
|
|
229
|
+
`);
|
|
230
|
+
if (details.requestId)
|
|
231
|
+
deps.stderr(`${import_picocolors2.default.dim(`Request ID: ${details.requestId}`)}
|
|
217
232
|
`);
|
|
218
233
|
} else {
|
|
219
234
|
deps.stderr(`${JSON.stringify(apiErrorEnvelope(details))}
|
|
@@ -251,11 +266,13 @@ function writeEmpty(deps, message, json) {
|
|
|
251
266
|
|
|
252
267
|
// src/commands/account.ts
|
|
253
268
|
async function runAccountGet(_input, deps) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
269
|
+
try {
|
|
270
|
+
await requireCredential({
|
|
271
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
272
|
+
env: deps.env,
|
|
273
|
+
store: deps.store
|
|
274
|
+
});
|
|
275
|
+
} catch {
|
|
259
276
|
return writeAuthError(deps);
|
|
260
277
|
}
|
|
261
278
|
const result = await deps.client.account.get();
|
|
@@ -273,8 +290,33 @@ async function runAccountGet(_input, deps) {
|
|
|
273
290
|
|
|
274
291
|
// src/commands/api-keys.ts
|
|
275
292
|
var prompts = __toESM(require("@clack/prompts"), 1);
|
|
293
|
+
|
|
294
|
+
// src/types.ts
|
|
295
|
+
function unwrapListData(data, ...fallbackKeys) {
|
|
296
|
+
if (data && typeof data === "object") {
|
|
297
|
+
if ("data" in data) {
|
|
298
|
+
return data.data;
|
|
299
|
+
}
|
|
300
|
+
for (const key of fallbackKeys) {
|
|
301
|
+
if (key in data) {
|
|
302
|
+
return data[key];
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return data;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// src/commands/api-keys.ts
|
|
276
310
|
async function runApiKeysCreate(input, deps) {
|
|
277
|
-
|
|
311
|
+
try {
|
|
312
|
+
await requireCredential({
|
|
313
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
314
|
+
env: deps.env,
|
|
315
|
+
store: deps.store
|
|
316
|
+
});
|
|
317
|
+
} catch {
|
|
318
|
+
return writeAuthError(deps);
|
|
319
|
+
}
|
|
278
320
|
const result = await deps.client.apiKeys.create({ label: input.label });
|
|
279
321
|
if (result.error) return writeApiErrorSimple(deps, result.error.message);
|
|
280
322
|
const data = result.data;
|
|
@@ -286,10 +328,18 @@ async function runApiKeysCreate(input, deps) {
|
|
|
286
328
|
return { exitCode: 0 };
|
|
287
329
|
}
|
|
288
330
|
async function runApiKeysList(_input, deps) {
|
|
289
|
-
|
|
331
|
+
try {
|
|
332
|
+
await requireCredential({
|
|
333
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
334
|
+
env: deps.env,
|
|
335
|
+
store: deps.store
|
|
336
|
+
});
|
|
337
|
+
} catch {
|
|
338
|
+
return writeAuthError(deps);
|
|
339
|
+
}
|
|
290
340
|
const result = await deps.client.apiKeys.list();
|
|
291
341
|
if (result.error) return writeApiErrorSimple(deps, result.error.message);
|
|
292
|
-
const raw =
|
|
342
|
+
const raw = unwrapListData(result.data, "apiKeys", "api_keys");
|
|
293
343
|
const items = Array.isArray(raw) ? raw : void 0;
|
|
294
344
|
if (deps.outputMode === "human") {
|
|
295
345
|
if (!items || items.length === 0) {
|
|
@@ -323,7 +373,15 @@ async function runApiKeysDelete(keyId, input, deps) {
|
|
|
323
373
|
return { exitCode: 0 };
|
|
324
374
|
}
|
|
325
375
|
}
|
|
326
|
-
|
|
376
|
+
try {
|
|
377
|
+
await requireCredential({
|
|
378
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
379
|
+
env: deps.env,
|
|
380
|
+
store: deps.store
|
|
381
|
+
});
|
|
382
|
+
} catch {
|
|
383
|
+
return writeAuthError(deps);
|
|
384
|
+
}
|
|
327
385
|
const result = await deps.client.apiKeys.delete(keyId);
|
|
328
386
|
if (result?.error) return writeApiErrorSimple(deps, result.error.message);
|
|
329
387
|
writeHumanOrJson(deps, success(`Deleted ${keyId}`), {
|
|
@@ -333,25 +391,9 @@ async function runApiKeysDelete(keyId, input, deps) {
|
|
|
333
391
|
});
|
|
334
392
|
return { exitCode: 0 };
|
|
335
393
|
}
|
|
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
394
|
|
|
353
|
-
// src/
|
|
354
|
-
var
|
|
395
|
+
// src/catalog.ts
|
|
396
|
+
var COMMAND_CATALOG = [
|
|
355
397
|
{
|
|
356
398
|
name: "publish",
|
|
357
399
|
description: "Publish an input and return a Dropthis URL.",
|
|
@@ -426,12 +468,14 @@ var COMMANDS = [
|
|
|
426
468
|
examples: ["dropthis commands --json"]
|
|
427
469
|
}
|
|
428
470
|
];
|
|
471
|
+
|
|
472
|
+
// src/commands/commands.ts
|
|
429
473
|
async function runCommands(_input, deps) {
|
|
430
474
|
deps.stdout(
|
|
431
475
|
`${JSON.stringify({
|
|
432
476
|
ok: true,
|
|
433
477
|
output: "JSON by default in CI, pipes, non-TTY, --json, or --quiet.",
|
|
434
|
-
commands:
|
|
478
|
+
commands: COMMAND_CATALOG
|
|
435
479
|
})}
|
|
436
480
|
`
|
|
437
481
|
);
|
|
@@ -440,7 +484,15 @@ async function runCommands(_input, deps) {
|
|
|
440
484
|
|
|
441
485
|
// src/commands/deployments.ts
|
|
442
486
|
async function runDeploymentsList(dropId, input, deps) {
|
|
443
|
-
|
|
487
|
+
try {
|
|
488
|
+
await requireCredential({
|
|
489
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
490
|
+
env: deps.env,
|
|
491
|
+
store: deps.store
|
|
492
|
+
});
|
|
493
|
+
} catch {
|
|
494
|
+
return writeAuthError(deps);
|
|
495
|
+
}
|
|
444
496
|
const params = {
|
|
445
497
|
...input.limit !== void 0 ? { limit: input.limit } : {},
|
|
446
498
|
...input.cursor ? { cursor: input.cursor } : {}
|
|
@@ -473,7 +525,15 @@ async function runDeploymentsList(dropId, input, deps) {
|
|
|
473
525
|
return { exitCode: 0 };
|
|
474
526
|
}
|
|
475
527
|
async function runDeploymentsGet(dropId, deploymentId, _input, deps) {
|
|
476
|
-
|
|
528
|
+
try {
|
|
529
|
+
await requireCredential({
|
|
530
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
531
|
+
env: deps.env,
|
|
532
|
+
store: deps.store
|
|
533
|
+
});
|
|
534
|
+
} catch {
|
|
535
|
+
return writeAuthError(deps);
|
|
536
|
+
}
|
|
477
537
|
const result = await deps.client.deployments.get(dropId, deploymentId);
|
|
478
538
|
if (result.error) {
|
|
479
539
|
return writeApiError(deps, result.error);
|
|
@@ -487,13 +547,6 @@ async function runDeploymentsGet(dropId, deploymentId, _input, deps) {
|
|
|
487
547
|
writeKv(deps, pairs, { ok: true, deployment: result.data });
|
|
488
548
|
return { exitCode: 0 };
|
|
489
549
|
}
|
|
490
|
-
async function hasCredential2(deps) {
|
|
491
|
-
return await resolveCredential({
|
|
492
|
-
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
493
|
-
env: deps.env,
|
|
494
|
-
store: deps.store
|
|
495
|
-
}) !== null;
|
|
496
|
-
}
|
|
497
550
|
function spreadData(data) {
|
|
498
551
|
return data && typeof data === "object" ? data : { data };
|
|
499
552
|
}
|
|
@@ -508,13 +561,13 @@ async function runDoctor(_input, deps) {
|
|
|
508
561
|
const authSource = credential?.source ?? "missing";
|
|
509
562
|
const storageBackend = stored?.storage ?? "none";
|
|
510
563
|
const pairs = [
|
|
511
|
-
["Version", "0.
|
|
564
|
+
["Version", "0.4.0"],
|
|
512
565
|
["Auth", authSource],
|
|
513
566
|
["Storage", storageBackend]
|
|
514
567
|
];
|
|
515
568
|
writeKv(deps, pairs, {
|
|
516
569
|
ok: true,
|
|
517
|
-
version: "0.
|
|
570
|
+
version: "0.4.0",
|
|
518
571
|
auth: { source: authSource },
|
|
519
572
|
storage: { backend: storageBackend }
|
|
520
573
|
});
|
|
@@ -524,14 +577,22 @@ async function runDoctor(_input, deps) {
|
|
|
524
577
|
// src/commands/drops.ts
|
|
525
578
|
var prompts2 = __toESM(require("@clack/prompts"), 1);
|
|
526
579
|
async function runDropsList(input, deps) {
|
|
527
|
-
|
|
580
|
+
try {
|
|
581
|
+
await requireCredential({
|
|
582
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
583
|
+
env: deps.env,
|
|
584
|
+
store: deps.store
|
|
585
|
+
});
|
|
586
|
+
} catch {
|
|
587
|
+
return writeAuthError(deps);
|
|
588
|
+
}
|
|
528
589
|
const params = {
|
|
529
590
|
...input.limit !== void 0 ? { limit: input.limit } : {},
|
|
530
591
|
...input.cursor ? { cursor: input.cursor } : {}
|
|
531
592
|
};
|
|
532
593
|
const result = await deps.client.drops.list(params);
|
|
533
594
|
if (result.error) return writeApiErrorSimple(deps, result.error.message);
|
|
534
|
-
const raw =
|
|
595
|
+
const raw = unwrapListData(result.data, "drops");
|
|
535
596
|
const items = Array.isArray(raw) ? raw : void 0;
|
|
536
597
|
if (deps.outputMode === "human") {
|
|
537
598
|
if (!items || items.length === 0) {
|
|
@@ -550,7 +611,15 @@ async function runDropsList(input, deps) {
|
|
|
550
611
|
return { exitCode: 0 };
|
|
551
612
|
}
|
|
552
613
|
async function runDropsGet(dropId, _input, deps) {
|
|
553
|
-
|
|
614
|
+
try {
|
|
615
|
+
await requireCredential({
|
|
616
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
617
|
+
env: deps.env,
|
|
618
|
+
store: deps.store
|
|
619
|
+
});
|
|
620
|
+
} catch {
|
|
621
|
+
return writeAuthError(deps);
|
|
622
|
+
}
|
|
554
623
|
const result = await deps.client.drops.get(dropId);
|
|
555
624
|
if (result.error) return writeApiErrorSimple(deps, result.error.message);
|
|
556
625
|
const data = result.data;
|
|
@@ -587,7 +656,15 @@ async function runDropsDelete(dropId, input, deps) {
|
|
|
587
656
|
return { exitCode: 0 };
|
|
588
657
|
}
|
|
589
658
|
}
|
|
590
|
-
|
|
659
|
+
try {
|
|
660
|
+
await requireCredential({
|
|
661
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
662
|
+
env: deps.env,
|
|
663
|
+
store: deps.store
|
|
664
|
+
});
|
|
665
|
+
} catch {
|
|
666
|
+
return writeAuthError(deps);
|
|
667
|
+
}
|
|
591
668
|
const result = await deps.client.drops.delete(dropId);
|
|
592
669
|
if (result?.error) return writeApiErrorSimple(deps, result.error.message);
|
|
593
670
|
writeHumanOrJson(deps, success(`Deleted ${dropId}`), {
|
|
@@ -597,22 +674,6 @@ async function runDropsDelete(dropId, input, deps) {
|
|
|
597
674
|
});
|
|
598
675
|
return { exitCode: 0 };
|
|
599
676
|
}
|
|
600
|
-
async function hasCredential3(deps) {
|
|
601
|
-
return await resolveCredential({
|
|
602
|
-
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
603
|
-
env: deps.env,
|
|
604
|
-
store: deps.store
|
|
605
|
-
}) !== null;
|
|
606
|
-
}
|
|
607
|
-
function listItems2(data) {
|
|
608
|
-
if (data && typeof data === "object" && "data" in data) {
|
|
609
|
-
return data.data;
|
|
610
|
-
}
|
|
611
|
-
if (data && typeof data === "object" && "drops" in data) {
|
|
612
|
-
return data.drops;
|
|
613
|
-
}
|
|
614
|
-
return data;
|
|
615
|
-
}
|
|
616
677
|
|
|
617
678
|
// src/commands/login.ts
|
|
618
679
|
var prompts3 = __toESM(require("@clack/prompts"), 1);
|
|
@@ -758,9 +819,88 @@ async function runLogout(input, deps) {
|
|
|
758
819
|
}
|
|
759
820
|
|
|
760
821
|
// src/commands/publish.ts
|
|
761
|
-
var import_node_crypto = require("crypto");
|
|
762
822
|
var import_promises3 = require("fs/promises");
|
|
823
|
+
var import_node_path2 = require("path");
|
|
824
|
+
|
|
825
|
+
// src/drop-operations.ts
|
|
826
|
+
var import_node_crypto = require("crypto");
|
|
763
827
|
var import_node_path = require("path");
|
|
828
|
+
var MAX_BUNDLE_FILE_COUNT = 200;
|
|
829
|
+
function isFileSystemError(error2) {
|
|
830
|
+
if (!(error2 instanceof Error)) return false;
|
|
831
|
+
const code = error2.code;
|
|
832
|
+
return code === "ENOENT" || code === "ENOTDIR" || code === "EACCES" || code === "ELIMIT";
|
|
833
|
+
}
|
|
834
|
+
function mimeForPath(filePath) {
|
|
835
|
+
const ext = (0, import_node_path.extname)(filePath).toLowerCase();
|
|
836
|
+
const types = {
|
|
837
|
+
".html": "text/html",
|
|
838
|
+
".htm": "text/html",
|
|
839
|
+
".css": "text/css",
|
|
840
|
+
".js": "text/javascript",
|
|
841
|
+
".mjs": "text/javascript",
|
|
842
|
+
".json": "application/json",
|
|
843
|
+
".xml": "application/xml",
|
|
844
|
+
".svg": "image/svg+xml",
|
|
845
|
+
".txt": "text/plain",
|
|
846
|
+
".md": "text/markdown",
|
|
847
|
+
".jpg": "image/jpeg",
|
|
848
|
+
".jpeg": "image/jpeg",
|
|
849
|
+
".png": "image/png",
|
|
850
|
+
".gif": "image/gif",
|
|
851
|
+
".webp": "image/webp",
|
|
852
|
+
".ico": "image/x-icon",
|
|
853
|
+
".avif": "image/avif",
|
|
854
|
+
".pdf": "application/pdf",
|
|
855
|
+
".zip": "application/zip",
|
|
856
|
+
".woff": "font/woff",
|
|
857
|
+
".woff2": "font/woff2",
|
|
858
|
+
".ttf": "font/ttf",
|
|
859
|
+
".mp4": "video/mp4",
|
|
860
|
+
".webm": "video/webm"
|
|
861
|
+
};
|
|
862
|
+
return types[ext] ?? "application/octet-stream";
|
|
863
|
+
}
|
|
864
|
+
function withIdempotencyKey(options, prefix) {
|
|
865
|
+
return options.idempotencyKey ? options : { ...options, idempotencyKey: `cli_${prefix}_${(0, import_node_crypto.randomUUID)()}` };
|
|
866
|
+
}
|
|
867
|
+
function validateManifestFileCount(count) {
|
|
868
|
+
if (count > MAX_BUNDLE_FILE_COUNT) {
|
|
869
|
+
throw Object.assign(
|
|
870
|
+
new Error(
|
|
871
|
+
`Bundle contains ${count} files, exceeding the maximum of ${MAX_BUNDLE_FILE_COUNT}.`
|
|
872
|
+
),
|
|
873
|
+
{ code: "ELIMIT" }
|
|
874
|
+
);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
function formatDryRunManifest(prepared, extra) {
|
|
878
|
+
const totalBytes = prepared.manifest.files.reduce(
|
|
879
|
+
(sum, f) => sum + f.sizeBytes,
|
|
880
|
+
0
|
|
881
|
+
);
|
|
882
|
+
return {
|
|
883
|
+
dryRun: true,
|
|
884
|
+
kind: "staged",
|
|
885
|
+
...extra,
|
|
886
|
+
manifest: {
|
|
887
|
+
files: prepared.manifest.files,
|
|
888
|
+
entry: prepared.manifest.entry ?? null
|
|
889
|
+
},
|
|
890
|
+
options: prepared.options,
|
|
891
|
+
...prepared.metadata ? { metadata: prepared.metadata } : {},
|
|
892
|
+
totalBytes
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
function dryRunOptionsBody(options) {
|
|
896
|
+
const result = {};
|
|
897
|
+
if (options.title) result.title = options.title;
|
|
898
|
+
if (options.visibility) result.visibility = options.visibility;
|
|
899
|
+
if (options.password !== void 0) result.password = options.password;
|
|
900
|
+
if (options.noindex !== void 0) result.noindex = options.noindex;
|
|
901
|
+
if (options.expiresAt) result.expires_at = options.expiresAt;
|
|
902
|
+
return result;
|
|
903
|
+
}
|
|
764
904
|
|
|
765
905
|
// src/options.ts
|
|
766
906
|
var import_promises = require("fs/promises");
|
|
@@ -856,14 +996,14 @@ async function readJsonObjectFile(path) {
|
|
|
856
996
|
}
|
|
857
997
|
|
|
858
998
|
// src/commands/publish.ts
|
|
859
|
-
var MAX_BUNDLE_FILE_COUNT = 200;
|
|
860
999
|
async function runPublish(input, raw, deps) {
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
1000
|
+
try {
|
|
1001
|
+
await requireCredential({
|
|
1002
|
+
...raw.apiKey ?? deps.apiKey ? { apiKey: raw.apiKey ?? deps.apiKey } : {},
|
|
1003
|
+
env: deps.env,
|
|
1004
|
+
store: deps.store
|
|
1005
|
+
});
|
|
1006
|
+
} catch {
|
|
867
1007
|
return writeAuthError(deps);
|
|
868
1008
|
}
|
|
869
1009
|
if (raw.dryRun) {
|
|
@@ -875,7 +1015,7 @@ async function runPublish(input, raw, deps) {
|
|
|
875
1015
|
if (raw.fromJson && singleInput) {
|
|
876
1016
|
throw new Error("Use either <input> or --from-json, not both.");
|
|
877
1017
|
}
|
|
878
|
-
const options =
|
|
1018
|
+
const options = withIdempotencyKey(await parseDropOptions(raw), "pub");
|
|
879
1019
|
const result = raw.fromJson ? await deps.client.drops.createRaw(
|
|
880
1020
|
await (deps.readJsonObject ?? readJsonObjectFile)(raw.fromJson),
|
|
881
1021
|
options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {}
|
|
@@ -931,8 +1071,10 @@ async function handlePublishDryRun(input, raw, deps) {
|
|
|
931
1071
|
throw new Error("Client does not support dry-run.");
|
|
932
1072
|
}
|
|
933
1073
|
const prepared = await deps.client.prepare(input, options);
|
|
934
|
-
const output =
|
|
935
|
-
|
|
1074
|
+
const output = formatDryRunManifest(prepared);
|
|
1075
|
+
validateManifestFileCount(
|
|
1076
|
+
output.manifest.files.length
|
|
1077
|
+
);
|
|
936
1078
|
deps.stdout(`${JSON.stringify(output, null, 2)}
|
|
937
1079
|
`);
|
|
938
1080
|
return { exitCode: 0 };
|
|
@@ -963,18 +1105,12 @@ async function dryRunMultiFile(inputs, options, deps) {
|
|
|
963
1105
|
);
|
|
964
1106
|
}
|
|
965
1107
|
files.push({
|
|
966
|
-
path: (0,
|
|
1108
|
+
path: (0, import_node_path2.basename)(filePath),
|
|
967
1109
|
contentType: mimeForPath(filePath),
|
|
968
1110
|
sizeBytes: info.size
|
|
969
1111
|
});
|
|
970
1112
|
}
|
|
971
|
-
|
|
972
|
-
return writeError(
|
|
973
|
-
deps,
|
|
974
|
-
"local_input_error",
|
|
975
|
-
`Bundle contains ${files.length} files, exceeding the maximum of ${MAX_BUNDLE_FILE_COUNT}.`
|
|
976
|
-
);
|
|
977
|
-
}
|
|
1113
|
+
validateManifestFileCount(files.length);
|
|
978
1114
|
const entry = options.entry ?? files.find((f) => f.path === "index.html")?.path ?? files[0]?.path ?? null;
|
|
979
1115
|
const totalBytes = files.reduce((sum, f) => sum + f.sizeBytes, 0);
|
|
980
1116
|
const output = {
|
|
@@ -988,92 +1124,16 @@ async function dryRunMultiFile(inputs, options, deps) {
|
|
|
988
1124
|
`);
|
|
989
1125
|
return { exitCode: 0 };
|
|
990
1126
|
}
|
|
991
|
-
function formatDryRunOutput(prepared) {
|
|
992
|
-
const totalBytes = prepared.manifest.files.reduce(
|
|
993
|
-
(sum, f) => sum + f.sizeBytes,
|
|
994
|
-
0
|
|
995
|
-
);
|
|
996
|
-
return {
|
|
997
|
-
dryRun: true,
|
|
998
|
-
kind: "staged",
|
|
999
|
-
manifest: {
|
|
1000
|
-
files: prepared.manifest.files,
|
|
1001
|
-
entry: prepared.manifest.entry ?? null
|
|
1002
|
-
},
|
|
1003
|
-
options: prepared.options,
|
|
1004
|
-
...prepared.metadata ? { metadata: prepared.metadata } : {},
|
|
1005
|
-
totalBytes
|
|
1006
|
-
};
|
|
1007
|
-
}
|
|
1008
|
-
function validateDryRunOutput(output) {
|
|
1009
|
-
if (output.kind !== "staged") return;
|
|
1010
|
-
const manifest = output.manifest;
|
|
1011
|
-
if (manifest.files.length > MAX_BUNDLE_FILE_COUNT) {
|
|
1012
|
-
throw Object.assign(
|
|
1013
|
-
new Error(
|
|
1014
|
-
`Bundle contains ${manifest.files.length} files, exceeding the maximum of ${MAX_BUNDLE_FILE_COUNT}.`
|
|
1015
|
-
),
|
|
1016
|
-
{ code: "ELIMIT" }
|
|
1017
|
-
);
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
|
-
function dryRunOptionsBody(options) {
|
|
1021
|
-
const result = {};
|
|
1022
|
-
if (options.title) result.title = options.title;
|
|
1023
|
-
if (options.visibility) result.visibility = options.visibility;
|
|
1024
|
-
if (options.password !== void 0) result.password = options.password;
|
|
1025
|
-
if (options.noindex !== void 0) result.noindex = options.noindex;
|
|
1026
|
-
if (options.expiresAt) result.expires_at = options.expiresAt;
|
|
1027
|
-
return result;
|
|
1028
|
-
}
|
|
1029
|
-
function mimeForPath(filePath) {
|
|
1030
|
-
const ext = (0, import_node_path.extname)(filePath).toLowerCase();
|
|
1031
|
-
const types = {
|
|
1032
|
-
".html": "text/html",
|
|
1033
|
-
".htm": "text/html",
|
|
1034
|
-
".css": "text/css",
|
|
1035
|
-
".js": "text/javascript",
|
|
1036
|
-
".mjs": "text/javascript",
|
|
1037
|
-
".json": "application/json",
|
|
1038
|
-
".xml": "application/xml",
|
|
1039
|
-
".svg": "image/svg+xml",
|
|
1040
|
-
".txt": "text/plain",
|
|
1041
|
-
".md": "text/markdown",
|
|
1042
|
-
".jpg": "image/jpeg",
|
|
1043
|
-
".jpeg": "image/jpeg",
|
|
1044
|
-
".png": "image/png",
|
|
1045
|
-
".gif": "image/gif",
|
|
1046
|
-
".webp": "image/webp",
|
|
1047
|
-
".ico": "image/x-icon",
|
|
1048
|
-
".avif": "image/avif",
|
|
1049
|
-
".pdf": "application/pdf",
|
|
1050
|
-
".zip": "application/zip",
|
|
1051
|
-
".woff": "font/woff",
|
|
1052
|
-
".woff2": "font/woff2",
|
|
1053
|
-
".ttf": "font/ttf",
|
|
1054
|
-
".mp4": "video/mp4",
|
|
1055
|
-
".webm": "video/webm"
|
|
1056
|
-
};
|
|
1057
|
-
return types[ext] ?? "application/octet-stream";
|
|
1058
|
-
}
|
|
1059
|
-
function isFileSystemError(error2) {
|
|
1060
|
-
if (!(error2 instanceof Error)) return false;
|
|
1061
|
-
const code = error2.code;
|
|
1062
|
-
return code === "ENOENT" || code === "ENOTDIR" || code === "EACCES" || code === "ELIMIT";
|
|
1063
|
-
}
|
|
1064
|
-
function withPublishIdempotency(options) {
|
|
1065
|
-
return options.idempotencyKey ? options : { ...options, idempotencyKey: `cli_pub_${(0, import_node_crypto.randomUUID)()}` };
|
|
1066
|
-
}
|
|
1067
1127
|
|
|
1068
1128
|
// src/commands/update.ts
|
|
1069
|
-
var import_node_crypto2 = require("crypto");
|
|
1070
1129
|
async function runUpdate(target, input, raw, deps) {
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1130
|
+
try {
|
|
1131
|
+
await requireCredential({
|
|
1132
|
+
...raw.apiKey ?? deps.apiKey ? { apiKey: raw.apiKey ?? deps.apiKey } : {},
|
|
1133
|
+
env: deps.env,
|
|
1134
|
+
store: deps.store
|
|
1135
|
+
});
|
|
1136
|
+
} catch {
|
|
1077
1137
|
return writeAuthError(deps);
|
|
1078
1138
|
}
|
|
1079
1139
|
if (raw.dryRun) {
|
|
@@ -1090,17 +1150,23 @@ async function runUpdate(target, input, raw, deps) {
|
|
|
1090
1150
|
const result = raw.fromJson ? await deps.client.deployments.createRaw(
|
|
1091
1151
|
target,
|
|
1092
1152
|
await (deps.readJsonObject ?? readJsonObjectFile)(raw.fromJson),
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1153
|
+
withIdempotencyKey(
|
|
1154
|
+
{
|
|
1155
|
+
...revisionOptions,
|
|
1156
|
+
...parsed.idempotencyKey ? { idempotencyKey: parsed.idempotencyKey } : {}
|
|
1157
|
+
},
|
|
1158
|
+
"upd"
|
|
1159
|
+
)
|
|
1097
1160
|
) : input ? await deps.client.update(
|
|
1098
1161
|
target,
|
|
1099
1162
|
input,
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1163
|
+
withIdempotencyKey(
|
|
1164
|
+
{
|
|
1165
|
+
...parsed,
|
|
1166
|
+
...revisionOptions
|
|
1167
|
+
},
|
|
1168
|
+
"upd"
|
|
1169
|
+
)
|
|
1104
1170
|
) : await deps.client.update(target, parsed, revisionOptions);
|
|
1105
1171
|
if (result.error) {
|
|
1106
1172
|
spin?.fail();
|
|
@@ -1113,8 +1179,9 @@ async function runUpdate(target, input, raw, deps) {
|
|
|
1113
1179
|
return { exitCode: 0 };
|
|
1114
1180
|
} catch (error2) {
|
|
1115
1181
|
const message = error2 instanceof Error ? error2.message : "Update failed.";
|
|
1182
|
+
const code = isFileSystemError(error2) ? "local_input_error" : "invalid_usage";
|
|
1116
1183
|
spin?.fail();
|
|
1117
|
-
return writeError(deps,
|
|
1184
|
+
return writeError(deps, code, message);
|
|
1118
1185
|
}
|
|
1119
1186
|
}
|
|
1120
1187
|
async function handleUpdateDryRun(target, input, raw, deps) {
|
|
@@ -1160,56 +1227,17 @@ async function handleUpdateDryRun(target, input, raw, deps) {
|
|
|
1160
1227
|
throw new Error("Client does not support dry-run.");
|
|
1161
1228
|
}
|
|
1162
1229
|
const prepared = await deps.client.prepare(input, options);
|
|
1163
|
-
const output =
|
|
1164
|
-
|
|
1230
|
+
const output = formatDryRunManifest(prepared, { target });
|
|
1231
|
+
validateManifestFileCount(prepared.manifest.files.length);
|
|
1165
1232
|
deps.stdout(`${JSON.stringify(output, null, 2)}
|
|
1166
1233
|
`);
|
|
1167
1234
|
return { exitCode: 0 };
|
|
1168
1235
|
} catch (error2) {
|
|
1169
|
-
const code =
|
|
1236
|
+
const code = isFileSystemError(error2) ? "local_input_error" : "invalid_usage";
|
|
1170
1237
|
const message = error2 instanceof Error ? error2.message : "Dry-run failed.";
|
|
1171
1238
|
return writeError(deps, code, message);
|
|
1172
1239
|
}
|
|
1173
1240
|
}
|
|
1174
|
-
var MAX_BUNDLE_FILE_COUNT2 = 200;
|
|
1175
|
-
function formatUpdateDryRun(target, prepared) {
|
|
1176
|
-
const totalBytes = prepared.manifest.files.reduce(
|
|
1177
|
-
(sum, f) => sum + f.sizeBytes,
|
|
1178
|
-
0
|
|
1179
|
-
);
|
|
1180
|
-
return {
|
|
1181
|
-
dryRun: true,
|
|
1182
|
-
kind: "staged",
|
|
1183
|
-
target,
|
|
1184
|
-
manifest: {
|
|
1185
|
-
files: prepared.manifest.files,
|
|
1186
|
-
entry: prepared.manifest.entry ?? null
|
|
1187
|
-
},
|
|
1188
|
-
options: prepared.options,
|
|
1189
|
-
...prepared.metadata ? { metadata: prepared.metadata } : {},
|
|
1190
|
-
totalBytes
|
|
1191
|
-
};
|
|
1192
|
-
}
|
|
1193
|
-
function validateDryRunFileCount(output) {
|
|
1194
|
-
if (output.kind !== "staged") return;
|
|
1195
|
-
const manifest = output.manifest;
|
|
1196
|
-
if (manifest.files.length > MAX_BUNDLE_FILE_COUNT2) {
|
|
1197
|
-
throw Object.assign(
|
|
1198
|
-
new Error(
|
|
1199
|
-
`Bundle contains ${manifest.files.length} files, exceeding the maximum of ${MAX_BUNDLE_FILE_COUNT2}.`
|
|
1200
|
-
),
|
|
1201
|
-
{ code: "ELIMIT" }
|
|
1202
|
-
);
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
1205
|
-
function isFileSystemError2(error2) {
|
|
1206
|
-
if (!(error2 instanceof Error)) return false;
|
|
1207
|
-
const code = error2.code;
|
|
1208
|
-
return code === "ENOENT" || code === "ENOTDIR";
|
|
1209
|
-
}
|
|
1210
|
-
function withUpdateIdempotency(options) {
|
|
1211
|
-
return options.idempotencyKey ? options : { ...options, idempotencyKey: `cli_upd_${(0, import_node_crypto2.randomUUID)()}` };
|
|
1212
|
-
}
|
|
1213
1241
|
function assertDropId(target) {
|
|
1214
1242
|
if (!target.startsWith("drop_")) {
|
|
1215
1243
|
throw new Error(
|
|
@@ -1280,7 +1308,7 @@ function createContext(input) {
|
|
|
1280
1308
|
// src/storage.ts
|
|
1281
1309
|
var import_promises4 = require("fs/promises");
|
|
1282
1310
|
var import_node_os = require("os");
|
|
1283
|
-
var
|
|
1311
|
+
var import_node_path3 = require("path");
|
|
1284
1312
|
var import_keyring = require("@napi-rs/keyring");
|
|
1285
1313
|
var MemoryCredentialStore = class {
|
|
1286
1314
|
credential = null;
|
|
@@ -1357,8 +1385,8 @@ function defaultKeyringAdapter() {
|
|
|
1357
1385
|
};
|
|
1358
1386
|
}
|
|
1359
1387
|
function credentialPath(configDir) {
|
|
1360
|
-
return (0,
|
|
1361
|
-
configDir ?? (0,
|
|
1388
|
+
return (0, import_node_path3.join)(
|
|
1389
|
+
configDir ?? (0, import_node_path3.join)((0, import_node_os.homedir)(), ".config", "dropthis"),
|
|
1362
1390
|
"credentials.json"
|
|
1363
1391
|
);
|
|
1364
1392
|
}
|
|
@@ -1373,7 +1401,7 @@ async function readJsonFile(path) {
|
|
|
1373
1401
|
}
|
|
1374
1402
|
}
|
|
1375
1403
|
async function writeCredentialFile(path, credential) {
|
|
1376
|
-
await (0, import_promises4.mkdir)((0,
|
|
1404
|
+
await (0, import_promises4.mkdir)((0, import_node_path3.dirname)(path), { recursive: true });
|
|
1377
1405
|
await (0, import_promises4.writeFile)(path, `${JSON.stringify(credential, null, 2)}
|
|
1378
1406
|
`, {
|
|
1379
1407
|
mode: 384
|
|
@@ -1393,7 +1421,7 @@ function buildProgram(options = {}) {
|
|
|
1393
1421
|
` ${import_picocolors4.default.cyan("dropthis login")}`,
|
|
1394
1422
|
` ${import_picocolors4.default.cyan("dropthis publish ./dist")}`
|
|
1395
1423
|
].join("\n")
|
|
1396
|
-
).version("0.
|
|
1424
|
+
).version("0.4.0").configureHelp({
|
|
1397
1425
|
subcommandTerm(cmd) {
|
|
1398
1426
|
const args = cmd.registeredArguments.map((a) => {
|
|
1399
1427
|
const name = a.name();
|
|
@@ -1696,15 +1724,10 @@ function globalOptions(program, commandOptions) {
|
|
|
1696
1724
|
};
|
|
1697
1725
|
}
|
|
1698
1726
|
function toDropOptions(options) {
|
|
1699
|
-
if (options.visibility && options.visibility !== "public" && options.visibility !== "unlisted") {
|
|
1700
|
-
throw new Error(
|
|
1701
|
-
`Invalid visibility "${options.visibility}". Use "public" or "unlisted".`
|
|
1702
|
-
);
|
|
1703
|
-
}
|
|
1704
1727
|
return {
|
|
1705
1728
|
...options.slug ? { slug: options.slug } : {},
|
|
1706
1729
|
...options.title ? { title: options.title } : {},
|
|
1707
|
-
...options.visibility
|
|
1730
|
+
...options.visibility ? { visibility: options.visibility } : {},
|
|
1708
1731
|
...typeof options.password === "string" ? { password: options.password } : {},
|
|
1709
1732
|
...options.password === false || options.noPassword ? { noPassword: true } : {},
|
|
1710
1733
|
...options.noindex ? { noindex: true } : {},
|