@dropthis/cli 0.8.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +275 -177
- package/dist/cli.cjs.map +1 -1
- package/node_modules/@dropthis/node/README.md +18 -18
- package/node_modules/@dropthis/node/dist/{drops-CWGyF-x1.d.cts → drops-C8-OQkbF.d.cts} +34 -8
- package/node_modules/@dropthis/node/dist/{drops-CWGyF-x1.d.ts → drops-C8-OQkbF.d.ts} +34 -8
- package/node_modules/@dropthis/node/dist/edge.cjs +33 -26
- package/node_modules/@dropthis/node/dist/edge.cjs.map +1 -1
- package/node_modules/@dropthis/node/dist/edge.d.cts +2 -6
- package/node_modules/@dropthis/node/dist/edge.d.ts +2 -6
- package/node_modules/@dropthis/node/dist/edge.mjs +33 -26
- package/node_modules/@dropthis/node/dist/edge.mjs.map +1 -1
- package/node_modules/@dropthis/node/dist/index.cjs +48 -42
- package/node_modules/@dropthis/node/dist/index.cjs.map +1 -1
- package/node_modules/@dropthis/node/dist/index.d.cts +4 -7
- package/node_modules/@dropthis/node/dist/index.d.ts +4 -7
- package/node_modules/@dropthis/node/dist/index.mjs +48 -42
- 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
|
@@ -210,7 +210,7 @@ function nextActionForApiError(error2) {
|
|
|
210
210
|
return "Fetch the drop, merge your changes, and retry with the current revision.";
|
|
211
211
|
}
|
|
212
212
|
if (error2.statusCode === 404 || error2.code === "not_found") {
|
|
213
|
-
return "Check the drop id or slug and retry; list your drops with dropthis
|
|
213
|
+
return "Check the drop id or slug and retry; list your drops with dropthis list.";
|
|
214
214
|
}
|
|
215
215
|
if (error2.statusCode === 401 || error2.code === "missing_api_key") {
|
|
216
216
|
return "Authenticate with dropthis login or set DROPTHIS_API_KEY.";
|
|
@@ -591,21 +591,36 @@ var COMMAND_ANNOTATIONS = {
|
|
|
591
591
|
publish: {
|
|
592
592
|
auth: "required",
|
|
593
593
|
examples: [
|
|
594
|
-
"dropthis ./
|
|
594
|
+
"dropthis ./report.html",
|
|
595
595
|
"dropthis publish ./site --json",
|
|
596
596
|
"dropthis publish ./site --url",
|
|
597
597
|
"dropthis publish ./dist --dry-run"
|
|
598
598
|
]
|
|
599
599
|
},
|
|
600
|
-
|
|
600
|
+
"update-content": {
|
|
601
601
|
auth: "required",
|
|
602
|
-
examples: [
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
]
|
|
602
|
+
examples: ["dropthis update-content drop_abc ./site --json"]
|
|
603
|
+
},
|
|
604
|
+
"update-settings": {
|
|
605
|
+
auth: "required",
|
|
606
|
+
examples: ["dropthis update-settings drop_abc --title 'Launch' --json"]
|
|
607
|
+
},
|
|
608
|
+
get: {
|
|
609
|
+
auth: "required",
|
|
610
|
+
examples: ["dropthis get drop_abc --json"]
|
|
611
|
+
},
|
|
612
|
+
list: {
|
|
613
|
+
auth: "required",
|
|
614
|
+
examples: ["dropthis list --json"]
|
|
615
|
+
},
|
|
616
|
+
delete: {
|
|
617
|
+
auth: "required",
|
|
618
|
+
examples: ["dropthis delete drop_abc --yes --json"]
|
|
619
|
+
},
|
|
620
|
+
deployments: {
|
|
621
|
+
auth: "required",
|
|
622
|
+
examples: ["dropthis deployments drop_abc --json"]
|
|
607
623
|
},
|
|
608
|
-
deployments: { auth: "required" },
|
|
609
624
|
"deployments list": {
|
|
610
625
|
auth: "required",
|
|
611
626
|
examples: ["dropthis deployments list drop_abc --json"]
|
|
@@ -754,13 +769,13 @@ async function runDoctor(_input, deps) {
|
|
|
754
769
|
const authSource = credential?.source ?? "missing";
|
|
755
770
|
const storageBackend = stored?.storage ?? "none";
|
|
756
771
|
const pairs = [
|
|
757
|
-
["Version", "0.
|
|
772
|
+
["Version", "0.9.1"],
|
|
758
773
|
["Auth", authSource],
|
|
759
774
|
["Storage", storageBackend]
|
|
760
775
|
];
|
|
761
776
|
writeKv(deps, pairs, {
|
|
762
777
|
ok: true,
|
|
763
|
-
version: "0.
|
|
778
|
+
version: "0.9.1",
|
|
764
779
|
auth: { source: authSource },
|
|
765
780
|
storage: { backend: storageBackend }
|
|
766
781
|
});
|
|
@@ -1177,7 +1192,7 @@ async function runPublish(input, raw, deps) {
|
|
|
1177
1192
|
const spin = shouldSpin(deps.outputMode) ? createSpinner("Publishing\u2026", deps.stderr) : void 0;
|
|
1178
1193
|
try {
|
|
1179
1194
|
const options = withIdempotencyKey(await parseDropOptions(raw), "pub");
|
|
1180
|
-
const doPublish = (c) => hasInput ? c.publish(input, options) : (() => {
|
|
1195
|
+
const doPublish = (c) => hasInput ? c.drops.publish(input, options) : (() => {
|
|
1181
1196
|
throw new Error("Publish requires <input>.");
|
|
1182
1197
|
})();
|
|
1183
1198
|
const result = await doPublish(client);
|
|
@@ -1260,32 +1275,17 @@ async function handlePublishDryRun(input, raw, deps, client) {
|
|
|
1260
1275
|
}
|
|
1261
1276
|
}
|
|
1262
1277
|
|
|
1263
|
-
// src/commands/update.ts
|
|
1264
|
-
var
|
|
1265
|
-
var
|
|
1266
|
-
|
|
1267
|
-
var DEPLOY_REJECTS_SETTINGS = "A deployment changes content only \u2014 it can't change settings in the same call.";
|
|
1268
|
-
var DEPLOY_SETTINGS_NEXT_ACTION = "Deploy the new content first (dropthis drops update <dropId> ./dist), then change settings separately (dropthis drops update <dropId> --title ... --visibility ...). Settings on an existing drop never require re-uploading content.";
|
|
1269
|
-
var SETTINGS_KEYS = [
|
|
1270
|
-
"slug",
|
|
1271
|
-
"title",
|
|
1272
|
-
"visibility",
|
|
1273
|
-
"password",
|
|
1274
|
-
"noindex",
|
|
1275
|
-
"expiresAt",
|
|
1276
|
-
"metadata"
|
|
1277
|
-
];
|
|
1278
|
-
function hasSettingsFields(options) {
|
|
1279
|
-
return SETTINGS_KEYS.some((key) => options[key] !== void 0);
|
|
1280
|
-
}
|
|
1281
|
-
function contentDeployOptions(options) {
|
|
1278
|
+
// src/commands/update-content.ts
|
|
1279
|
+
var NO_CONTENT_MESSAGE = "update-content requires content. Provide a file, folder, URL, or text to ship a new deployment.";
|
|
1280
|
+
var NO_CONTENT_NEXT_ACTION = "Pass an input, e.g. dropthis update-content <dropId> ./dist. To change title, visibility, password, slug, expiry, or metadata, use dropthis update-settings <dropId> instead.";
|
|
1281
|
+
function contentOptions(options) {
|
|
1282
1282
|
const out = {};
|
|
1283
1283
|
if (options.entry !== void 0) out.entry = options.entry;
|
|
1284
1284
|
if (options.contentType !== void 0) out.contentType = options.contentType;
|
|
1285
1285
|
if (options.path !== void 0) out.path = options.path;
|
|
1286
1286
|
return out;
|
|
1287
1287
|
}
|
|
1288
|
-
async function
|
|
1288
|
+
async function runUpdateContent(dropId, input, raw, deps) {
|
|
1289
1289
|
try {
|
|
1290
1290
|
await requireCredential({
|
|
1291
1291
|
...raw.apiKey ?? deps.apiKey ? { apiKey: raw.apiKey ?? deps.apiKey } : {},
|
|
@@ -1296,48 +1296,30 @@ async function runUpdate(target, input, raw, deps) {
|
|
|
1296
1296
|
return writeAuthError(deps);
|
|
1297
1297
|
}
|
|
1298
1298
|
if (raw.dryRun) {
|
|
1299
|
-
return
|
|
1299
|
+
return handleDryRun(dropId, input, raw, deps);
|
|
1300
1300
|
}
|
|
1301
1301
|
let spin;
|
|
1302
1302
|
try {
|
|
1303
|
-
assertDropId(
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
if (!updateInput && !hasUpdateFields(parsed)) {
|
|
1307
|
-
if (shouldPromptForUpdate(deps)) {
|
|
1308
|
-
const prompted = await promptForUpdate(target, deps.prompts ?? prompts4);
|
|
1309
|
-
if (!prompted) return { exitCode: 0 };
|
|
1310
|
-
updateInput = prompted.input;
|
|
1311
|
-
parsed = { ...parsed, ...prompted.options };
|
|
1312
|
-
} else {
|
|
1313
|
-
return writeError(
|
|
1314
|
-
deps,
|
|
1315
|
-
"invalid_usage",
|
|
1316
|
-
NO_UPDATE_MESSAGE,
|
|
1317
|
-
NO_UPDATE_NEXT_ACTION
|
|
1318
|
-
);
|
|
1319
|
-
}
|
|
1320
|
-
}
|
|
1321
|
-
if (updateInput && hasSettingsFields(parsed)) {
|
|
1303
|
+
assertDropId(dropId);
|
|
1304
|
+
const hasInput = Array.isArray(input) ? input.length > 0 : input !== void 0;
|
|
1305
|
+
if (!hasInput) {
|
|
1322
1306
|
return writeError(
|
|
1323
1307
|
deps,
|
|
1324
1308
|
"invalid_usage",
|
|
1325
|
-
|
|
1326
|
-
|
|
1309
|
+
NO_CONTENT_MESSAGE,
|
|
1310
|
+
NO_CONTENT_NEXT_ACTION
|
|
1327
1311
|
);
|
|
1328
1312
|
}
|
|
1313
|
+
const parsed = await parseDropOptions(raw);
|
|
1329
1314
|
const revisionOptions = raw.ifRevision !== void 0 ? { ifRevision: Number(raw.ifRevision) } : {};
|
|
1330
|
-
spin = shouldSpin(deps.outputMode) ? createSpinner("Updating\u2026", deps.stderr) : void 0;
|
|
1331
|
-
const result =
|
|
1332
|
-
|
|
1333
|
-
|
|
1315
|
+
spin = shouldSpin(deps.outputMode) ? createSpinner("Updating content\u2026", deps.stderr) : void 0;
|
|
1316
|
+
const result = await deps.client.drops.updateContent(
|
|
1317
|
+
dropId,
|
|
1318
|
+
input,
|
|
1334
1319
|
withIdempotencyKey(
|
|
1335
|
-
{ ...
|
|
1320
|
+
{ ...contentOptions(parsed), ...revisionOptions },
|
|
1336
1321
|
"upd"
|
|
1337
1322
|
)
|
|
1338
|
-
) : await deps.client.update(
|
|
1339
|
-
target,
|
|
1340
|
-
withIdempotencyKey({ ...parsed, ...revisionOptions }, "upd")
|
|
1341
1323
|
);
|
|
1342
1324
|
if (result.error) {
|
|
1343
1325
|
spin?.fail();
|
|
@@ -1355,24 +1337,130 @@ async function runUpdate(target, input, raw, deps) {
|
|
|
1355
1337
|
return writeError(deps, code, message);
|
|
1356
1338
|
}
|
|
1357
1339
|
}
|
|
1358
|
-
function
|
|
1359
|
-
|
|
1360
|
-
|
|
1340
|
+
async function handleDryRun(dropId, input, raw, deps) {
|
|
1341
|
+
if (raw.url) {
|
|
1342
|
+
return writeError(
|
|
1343
|
+
deps,
|
|
1344
|
+
"invalid_usage",
|
|
1345
|
+
"--url and --dry-run cannot be combined.",
|
|
1346
|
+
"Remove --url; dry-run outputs JSON describing what would be published."
|
|
1347
|
+
);
|
|
1348
|
+
}
|
|
1349
|
+
try {
|
|
1350
|
+
assertDropId(dropId);
|
|
1351
|
+
const hasInput = Array.isArray(input) ? input.length > 0 : input !== void 0;
|
|
1352
|
+
if (!hasInput) {
|
|
1353
|
+
return writeError(
|
|
1354
|
+
deps,
|
|
1355
|
+
"invalid_usage",
|
|
1356
|
+
NO_CONTENT_MESSAGE,
|
|
1357
|
+
NO_CONTENT_NEXT_ACTION
|
|
1358
|
+
);
|
|
1359
|
+
}
|
|
1360
|
+
const options = await parseDropOptions(raw);
|
|
1361
|
+
if (!deps.client.prepare) {
|
|
1362
|
+
throw new Error("Client does not support dry-run.");
|
|
1363
|
+
}
|
|
1364
|
+
const prepared = await deps.client.prepare(input, options);
|
|
1365
|
+
const output = formatDryRunManifest(prepared, { target: dropId });
|
|
1366
|
+
if (prepared.kind === "staged") {
|
|
1367
|
+
validateManifestFileCount(prepared.manifest.files.length);
|
|
1368
|
+
}
|
|
1369
|
+
deps.stdout(`${JSON.stringify(output, null, 2)}
|
|
1370
|
+
`);
|
|
1371
|
+
return { exitCode: 0 };
|
|
1372
|
+
} catch (error2) {
|
|
1373
|
+
const code = isFileSystemError(error2) ? "local_input_error" : "invalid_usage";
|
|
1374
|
+
const message = error2 instanceof Error ? error2.message : "Dry-run failed.";
|
|
1375
|
+
return writeError(deps, code, message);
|
|
1376
|
+
}
|
|
1361
1377
|
}
|
|
1362
|
-
function
|
|
1378
|
+
function assertDropId(target) {
|
|
1379
|
+
if (!target.startsWith("drop_")) {
|
|
1380
|
+
throw new Error(
|
|
1381
|
+
"update-content needs the full drop_\u2026 id from the publish response, not the URL slug, for example drop_..."
|
|
1382
|
+
);
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
// src/commands/update-settings.ts
|
|
1387
|
+
var prompts4 = __toESM(require("@clack/prompts"), 1);
|
|
1388
|
+
var NO_SETTINGS_MESSAGE = "Nothing to update. Provide at least one settings option.";
|
|
1389
|
+
var NO_SETTINGS_NEXT_ACTION = "Run dropthis update-settings --help, or retry with one of: --title, --slug, --visibility, --password, --no-password, --noindex, --index, --expires-at, --metadata, or --metadata-file. To replace the content at the URL instead, use dropthis update-content <dropId> ./dist.";
|
|
1390
|
+
async function runUpdateSettings(dropId, raw, deps) {
|
|
1391
|
+
try {
|
|
1392
|
+
await requireCredential({
|
|
1393
|
+
...raw.apiKey ?? deps.apiKey ? { apiKey: raw.apiKey ?? deps.apiKey } : {},
|
|
1394
|
+
env: deps.env,
|
|
1395
|
+
store: deps.store
|
|
1396
|
+
});
|
|
1397
|
+
} catch {
|
|
1398
|
+
return writeAuthError(deps);
|
|
1399
|
+
}
|
|
1400
|
+
if (raw.dryRun) {
|
|
1401
|
+
return handleDryRun2(dropId, raw, deps);
|
|
1402
|
+
}
|
|
1403
|
+
let spin;
|
|
1404
|
+
try {
|
|
1405
|
+
assertDropId2(dropId);
|
|
1406
|
+
let parsed = await parseDropOptions(raw);
|
|
1407
|
+
if (!hasSettingsFields(parsed)) {
|
|
1408
|
+
if (shouldPrompt(deps)) {
|
|
1409
|
+
const prompted = await promptForSettings(
|
|
1410
|
+
dropId,
|
|
1411
|
+
deps.prompts ?? prompts4
|
|
1412
|
+
);
|
|
1413
|
+
if (!prompted) return { exitCode: 0 };
|
|
1414
|
+
parsed = { ...parsed, ...prompted };
|
|
1415
|
+
} else {
|
|
1416
|
+
return writeError(
|
|
1417
|
+
deps,
|
|
1418
|
+
"invalid_usage",
|
|
1419
|
+
NO_SETTINGS_MESSAGE,
|
|
1420
|
+
NO_SETTINGS_NEXT_ACTION
|
|
1421
|
+
);
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
const revisionOptions = raw.ifRevision !== void 0 ? { ifRevision: Number(raw.ifRevision) } : {};
|
|
1425
|
+
spin = shouldSpin(deps.outputMode) ? createSpinner("Updating settings\u2026", deps.stderr) : void 0;
|
|
1426
|
+
const result = await deps.client.drops.updateSettings(
|
|
1427
|
+
dropId,
|
|
1428
|
+
withIdempotencyKey({ ...parsed, ...revisionOptions }, "upd")
|
|
1429
|
+
);
|
|
1430
|
+
if (result.error) {
|
|
1431
|
+
spin?.fail();
|
|
1432
|
+
return writeApiError(deps, result.error);
|
|
1433
|
+
}
|
|
1434
|
+
spin?.stop();
|
|
1435
|
+
if (raw.url) deps.stdout(`${result.data.url}
|
|
1436
|
+
`);
|
|
1437
|
+
else writeResult(deps, result.data.url, "Updated", result.data);
|
|
1438
|
+
return { exitCode: 0 };
|
|
1439
|
+
} catch (error2) {
|
|
1440
|
+
const message = error2 instanceof Error ? error2.message : "Update failed.";
|
|
1441
|
+
spin?.fail();
|
|
1442
|
+
return writeError(deps, "invalid_usage", message);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
function hasSettingsFields(options) {
|
|
1446
|
+
const {
|
|
1447
|
+
idempotencyKey: _,
|
|
1448
|
+
entry: __,
|
|
1449
|
+
contentType: ___,
|
|
1450
|
+
path: ____,
|
|
1451
|
+
...settings
|
|
1452
|
+
} = options;
|
|
1453
|
+
return Object.values(settings).some((value) => value !== void 0);
|
|
1454
|
+
}
|
|
1455
|
+
function shouldPrompt(deps) {
|
|
1363
1456
|
return deps.outputMode === "human" && deps.interactive === true;
|
|
1364
1457
|
}
|
|
1365
|
-
async function
|
|
1366
|
-
prompt.intro(`Update ${target}`);
|
|
1458
|
+
async function promptForSettings(target, prompt) {
|
|
1459
|
+
prompt.intro(`Update settings for ${target}`);
|
|
1367
1460
|
const fields = await prompt.multiselect({
|
|
1368
|
-
message: "What do you want to
|
|
1461
|
+
message: "What do you want to change?",
|
|
1369
1462
|
required: true,
|
|
1370
1463
|
options: [
|
|
1371
|
-
{
|
|
1372
|
-
value: "content",
|
|
1373
|
-
label: "Content",
|
|
1374
|
-
hint: "replace files, folder, URL, or text"
|
|
1375
|
-
},
|
|
1376
1464
|
{ value: "title", label: "Title", hint: "--title" },
|
|
1377
1465
|
{ value: "slug", label: "Slug", hint: "--slug" },
|
|
1378
1466
|
{ value: "visibility", label: "Visibility", hint: "--visibility" },
|
|
@@ -1396,21 +1484,12 @@ async function promptForUpdate(target, prompt) {
|
|
|
1396
1484
|
}
|
|
1397
1485
|
const selected = new Set(fields);
|
|
1398
1486
|
const options = {};
|
|
1399
|
-
let input;
|
|
1400
|
-
if (selected.has("content")) {
|
|
1401
|
-
const value = await prompt.text({
|
|
1402
|
-
message: "Content path, URL, or text",
|
|
1403
|
-
validate: requireNonEmpty("Enter content or a path.")
|
|
1404
|
-
});
|
|
1405
|
-
if (prompt.isCancel(value)) return cancelUpdate(prompt);
|
|
1406
|
-
input = value.trim();
|
|
1407
|
-
}
|
|
1408
1487
|
if (selected.has("title")) {
|
|
1409
1488
|
const value = await prompt.text({
|
|
1410
1489
|
message: "Title",
|
|
1411
1490
|
validate: requireNonEmpty("Enter a title.")
|
|
1412
1491
|
});
|
|
1413
|
-
if (prompt.isCancel(value)) return
|
|
1492
|
+
if (prompt.isCancel(value)) return cancel2(prompt);
|
|
1414
1493
|
options.title = value.trim();
|
|
1415
1494
|
}
|
|
1416
1495
|
if (selected.has("slug")) {
|
|
@@ -1418,7 +1497,7 @@ async function promptForUpdate(target, prompt) {
|
|
|
1418
1497
|
message: "Slug",
|
|
1419
1498
|
validate: requireNonEmpty("Enter a slug.")
|
|
1420
1499
|
});
|
|
1421
|
-
if (prompt.isCancel(value)) return
|
|
1500
|
+
if (prompt.isCancel(value)) return cancel2(prompt);
|
|
1422
1501
|
options.slug = value.trim();
|
|
1423
1502
|
}
|
|
1424
1503
|
if (selected.has("visibility")) {
|
|
@@ -1429,7 +1508,7 @@ async function promptForUpdate(target, prompt) {
|
|
|
1429
1508
|
{ value: "unlisted", label: "Unlisted" }
|
|
1430
1509
|
]
|
|
1431
1510
|
});
|
|
1432
|
-
if (prompt.isCancel(value)) return
|
|
1511
|
+
if (prompt.isCancel(value)) return cancel2(prompt);
|
|
1433
1512
|
options.visibility = value;
|
|
1434
1513
|
}
|
|
1435
1514
|
if (selected.has("password")) {
|
|
@@ -1440,13 +1519,13 @@ async function promptForUpdate(target, prompt) {
|
|
|
1440
1519
|
{ value: "remove", label: "Remove password" }
|
|
1441
1520
|
]
|
|
1442
1521
|
});
|
|
1443
|
-
if (prompt.isCancel(action)) return
|
|
1522
|
+
if (prompt.isCancel(action)) return cancel2(prompt);
|
|
1444
1523
|
if (action === "set") {
|
|
1445
1524
|
const value = await prompt.password({
|
|
1446
1525
|
message: "Password",
|
|
1447
1526
|
validate: requireNonEmpty("Enter a password.")
|
|
1448
1527
|
});
|
|
1449
|
-
if (prompt.isCancel(value)) return
|
|
1528
|
+
if (prompt.isCancel(value)) return cancel2(prompt);
|
|
1450
1529
|
options.password = value;
|
|
1451
1530
|
} else {
|
|
1452
1531
|
options.password = null;
|
|
@@ -1460,7 +1539,7 @@ async function promptForUpdate(target, prompt) {
|
|
|
1460
1539
|
{ value: "index", label: "Allow indexing" }
|
|
1461
1540
|
]
|
|
1462
1541
|
});
|
|
1463
|
-
if (prompt.isCancel(value)) return
|
|
1542
|
+
if (prompt.isCancel(value)) return cancel2(prompt);
|
|
1464
1543
|
options.noindex = value === "noindex";
|
|
1465
1544
|
}
|
|
1466
1545
|
if (selected.has("expiresAt")) {
|
|
@@ -1469,7 +1548,7 @@ async function promptForUpdate(target, prompt) {
|
|
|
1469
1548
|
placeholder: "2025-12-31T23:59:59Z",
|
|
1470
1549
|
validate: validateIsoDate
|
|
1471
1550
|
});
|
|
1472
|
-
if (prompt.isCancel(value)) return
|
|
1551
|
+
if (prompt.isCancel(value)) return cancel2(prompt);
|
|
1473
1552
|
options.expiresAt = value.trim();
|
|
1474
1553
|
}
|
|
1475
1554
|
if (selected.has("metadata")) {
|
|
@@ -1478,12 +1557,12 @@ async function promptForUpdate(target, prompt) {
|
|
|
1478
1557
|
placeholder: '{"source":"cli"}',
|
|
1479
1558
|
validate: validateJsonObject
|
|
1480
1559
|
});
|
|
1481
|
-
if (prompt.isCancel(value)) return
|
|
1560
|
+
if (prompt.isCancel(value)) return cancel2(prompt);
|
|
1482
1561
|
options.metadata = parseJsonObject2(value);
|
|
1483
1562
|
}
|
|
1484
|
-
return
|
|
1563
|
+
return options;
|
|
1485
1564
|
}
|
|
1486
|
-
function
|
|
1565
|
+
function cancel2(prompt) {
|
|
1487
1566
|
prompt.cancel("Update cancelled.");
|
|
1488
1567
|
return void 0;
|
|
1489
1568
|
}
|
|
@@ -1511,54 +1590,40 @@ function parseJsonObject2(value) {
|
|
|
1511
1590
|
}
|
|
1512
1591
|
return parsed;
|
|
1513
1592
|
}
|
|
1514
|
-
async function
|
|
1593
|
+
async function handleDryRun2(dropId, raw, deps) {
|
|
1515
1594
|
if (raw.url) {
|
|
1516
1595
|
return writeError(
|
|
1517
1596
|
deps,
|
|
1518
1597
|
"invalid_usage",
|
|
1519
1598
|
"--url and --dry-run cannot be combined.",
|
|
1520
|
-
"Remove --url; dry-run outputs JSON describing what would
|
|
1599
|
+
"Remove --url; dry-run outputs JSON describing what would change."
|
|
1521
1600
|
);
|
|
1522
1601
|
}
|
|
1523
1602
|
try {
|
|
1524
|
-
|
|
1603
|
+
assertDropId2(dropId);
|
|
1525
1604
|
const options = await parseDropOptions(raw);
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
`${JSON.stringify({ ok: true, dryRun: true, kind: "options_update", target, fields }, null, 2)}
|
|
1605
|
+
const fields = {};
|
|
1606
|
+
if (options.slug) fields.slug = options.slug;
|
|
1607
|
+
if (options.title) fields.title = options.title;
|
|
1608
|
+
if (options.visibility) fields.visibility = options.visibility;
|
|
1609
|
+
if (options.password !== void 0) fields.password = options.password;
|
|
1610
|
+
if (options.noindex !== void 0) fields.noindex = options.noindex;
|
|
1611
|
+
if (options.expiresAt) fields.expires_at = options.expiresAt;
|
|
1612
|
+
if (options.metadata) fields.metadata = options.metadata;
|
|
1613
|
+
deps.stdout(
|
|
1614
|
+
`${JSON.stringify({ ok: true, dryRun: true, kind: "settings_update", target: dropId, fields }, null, 2)}
|
|
1537
1615
|
`
|
|
1538
|
-
|
|
1539
|
-
return { exitCode: 0 };
|
|
1540
|
-
}
|
|
1541
|
-
if (!deps.client.prepare) {
|
|
1542
|
-
throw new Error("Client does not support dry-run.");
|
|
1543
|
-
}
|
|
1544
|
-
const prepared = await deps.client.prepare(input, options);
|
|
1545
|
-
const output = formatDryRunManifest(prepared, { target });
|
|
1546
|
-
if (prepared.kind === "staged") {
|
|
1547
|
-
validateManifestFileCount(prepared.manifest.files.length);
|
|
1548
|
-
}
|
|
1549
|
-
deps.stdout(`${JSON.stringify(output, null, 2)}
|
|
1550
|
-
`);
|
|
1616
|
+
);
|
|
1551
1617
|
return { exitCode: 0 };
|
|
1552
1618
|
} catch (error2) {
|
|
1553
|
-
const code = isFileSystemError(error2) ? "local_input_error" : "invalid_usage";
|
|
1554
1619
|
const message = error2 instanceof Error ? error2.message : "Dry-run failed.";
|
|
1555
|
-
return writeError(deps,
|
|
1620
|
+
return writeError(deps, "invalid_usage", message);
|
|
1556
1621
|
}
|
|
1557
1622
|
}
|
|
1558
|
-
function
|
|
1623
|
+
function assertDropId2(target) {
|
|
1559
1624
|
if (!target.startsWith("drop_")) {
|
|
1560
1625
|
throw new Error(
|
|
1561
|
-
"
|
|
1626
|
+
"update-settings needs the full drop_\u2026 id from the publish response, not the URL slug, for example drop_..."
|
|
1562
1627
|
);
|
|
1563
1628
|
}
|
|
1564
1629
|
}
|
|
@@ -1768,7 +1833,7 @@ function buildProgram(options = {}) {
|
|
|
1768
1833
|
` ${import_picocolors4.default.cyan("dropthis login")}`,
|
|
1769
1834
|
` ${import_picocolors4.default.cyan("dropthis publish ./dist")}`
|
|
1770
1835
|
].join("\n")
|
|
1771
|
-
).version("0.
|
|
1836
|
+
).version("0.9.1").configureHelp({
|
|
1772
1837
|
subcommandTerm(cmd) {
|
|
1773
1838
|
const args = cmd.registeredArguments.map((a) => {
|
|
1774
1839
|
const name = a.name();
|
|
@@ -1788,7 +1853,7 @@ function buildProgram(options = {}) {
|
|
|
1788
1853
|
program.option("-q, --quiet", "Suppress status output and imply JSON");
|
|
1789
1854
|
program.option("--no-interactive", "Disable interactive prompts");
|
|
1790
1855
|
program.command("publish [input...]", { isDefault: true }).description(
|
|
1791
|
-
"Publish
|
|
1856
|
+
"Publish content to a permanent public URL (also: share, post, put online, make public, get a link).\nFiles, folders, URLs, strings, or stdin; multiple files bundle into one drop. Use - for stdin, or pipe without args.\nCreates a NEW drop each run \u2014 to change one you already published, use update-content (the files) or update-settings (title/visibility/password/slug/expiry/metadata) with its drop_\u2026 id, not publish again."
|
|
1792
1857
|
).option("--title <title>", "Drop title").option("--visibility <v>", "public or unlisted (default: public)").option("--password <password>", "Require password to view").option("--noindex", "Prevent search-engine indexing").option("--expires-at <datetime>", "Auto-delete after this ISO 8601 date").option(
|
|
1793
1858
|
"--content-type <mime>",
|
|
1794
1859
|
"Override MIME type (auto-detected from extension)"
|
|
@@ -1840,46 +1905,35 @@ function buildProgram(options = {}) {
|
|
|
1840
1905
|
const result = await runPublish(publishInput, dropOpts, deps);
|
|
1841
1906
|
process.exitCode = result.exitCode;
|
|
1842
1907
|
});
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
async (commandOptions) => {
|
|
1846
|
-
const deps = await commandDeps(program, options, store, commandOptions);
|
|
1847
|
-
const result = await runDropsList(commandOptions, deps);
|
|
1848
|
-
process.exitCode = result.exitCode;
|
|
1849
|
-
}
|
|
1850
|
-
);
|
|
1851
|
-
drops.command("get <dropId>").description("Show drop details").option("--json", "Force JSON output").action(async (dropId, commandOptions) => {
|
|
1852
|
-
const deps = await commandDeps(program, options, store, commandOptions);
|
|
1853
|
-
const result = await runDropsGet(dropId, commandOptions, deps);
|
|
1854
|
-
process.exitCode = result.exitCode;
|
|
1855
|
-
});
|
|
1856
|
-
drops.command("update <dropId> [input]").description("Update content or metadata").option("--slug <slug>", "Change the vanity slug").option("--title <title>", "Change title").option("--visibility <v>", "Set to public or unlisted").option("--password <password>", "Require password to view").option("--no-password", "Remove password protection").option("--noindex", "Prevent search-engine indexing").option("--index", "Allow search-engine indexing").option("--expires-at <datetime>", "Auto-delete after this ISO 8601 date").option(
|
|
1857
|
-
"--content-type <mime>",
|
|
1858
|
-
"Override MIME type (auto-detected from extension)"
|
|
1908
|
+
program.command("update-content <dropId> [input...]").description(
|
|
1909
|
+
"Replace a drop's content, same URL (pass the full drop_\u2026 id, not the slug).\nShips a new deployment. Settings stay unchanged \u2014 use update-settings for title, visibility, password, slug, expiry, or metadata."
|
|
1859
1910
|
).option(
|
|
1860
1911
|
"--entry <path>",
|
|
1861
1912
|
"Entry file for multi-file bundles (default: index.html)"
|
|
1862
1913
|
).option(
|
|
1863
|
-
"--
|
|
1864
|
-
|
|
1865
|
-
).option("--
|
|
1914
|
+
"--content-type <mime>",
|
|
1915
|
+
"Override MIME type (auto-detected from extension)"
|
|
1916
|
+
).option("--path <name>", "Set filename for stdin content").option(
|
|
1866
1917
|
"--if-revision <n>",
|
|
1867
1918
|
"Fail if current revision doesn't match (optimistic lock)",
|
|
1868
1919
|
parseInteger
|
|
1869
1920
|
).option("--url", "Print only the published URL (no JSON envelope)").option(
|
|
1870
1921
|
"--dry-run",
|
|
1871
|
-
"Show what would be
|
|
1922
|
+
"Show what would be shipped without updating (JSON; cannot combine with --url)"
|
|
1872
1923
|
).option("--json", "Force JSON output").option(
|
|
1873
1924
|
"--idempotency-key <key>",
|
|
1874
1925
|
"Prevent duplicate updates on retry (auto-generated)"
|
|
1875
1926
|
).action(
|
|
1876
|
-
async (dropId,
|
|
1877
|
-
const stdinIsTTY = options.stdinIsTTY ?? process.stdin.isTTY ?? false;
|
|
1878
|
-
const global = globalOptions(program, commandOptions);
|
|
1927
|
+
async (dropId, inputs, commandOptions) => {
|
|
1879
1928
|
const deps = await commandDeps(program, options, store, commandOptions);
|
|
1929
|
+
const stdinIsTTY = options.stdinIsTTY ?? process.stdin.isTTY ?? false;
|
|
1880
1930
|
let updateInput;
|
|
1881
1931
|
try {
|
|
1882
|
-
updateInput =
|
|
1932
|
+
updateInput = await resolvePublishInputs(
|
|
1933
|
+
inputs,
|
|
1934
|
+
options.stdin,
|
|
1935
|
+
stdinIsTTY
|
|
1936
|
+
);
|
|
1883
1937
|
} catch (err) {
|
|
1884
1938
|
const msg = err instanceof Error ? err.message : "Invalid input.";
|
|
1885
1939
|
process.exitCode = writeError(
|
|
@@ -1897,14 +1951,63 @@ function buildProgram(options = {}) {
|
|
|
1897
1951
|
process.exitCode = writeError(deps, "invalid_usage", msg).exitCode;
|
|
1898
1952
|
return;
|
|
1899
1953
|
}
|
|
1900
|
-
const result = await
|
|
1954
|
+
const result = await runUpdateContent(
|
|
1955
|
+
dropId,
|
|
1956
|
+
updateInput,
|
|
1957
|
+
dropOpts,
|
|
1958
|
+
deps
|
|
1959
|
+
);
|
|
1960
|
+
process.exitCode = result.exitCode;
|
|
1961
|
+
}
|
|
1962
|
+
);
|
|
1963
|
+
program.command("update-settings <dropId>").description(
|
|
1964
|
+
"Change a drop's title, visibility, password, vanity slug, expiry, or metadata (pass the full drop_\u2026 id, not the slug).\nContent stays unchanged \u2014 use update-content to replace the files at the URL."
|
|
1965
|
+
).option("--slug <slug>", "Change the vanity slug").option("--title <title>", "Change title").option("--visibility <v>", "Set to public or unlisted").option("--password <password>", "Require password to view").option("--no-password", "Remove password protection").option("--noindex", "Prevent search-engine indexing").option("--index", "Allow search-engine indexing").option("--expires-at <datetime>", "Auto-delete after this ISO 8601 date").option(
|
|
1966
|
+
"--metadata <json>",
|
|
1967
|
+
`Attach JSON key-value pairs, e.g. '{"source":"ci"}'`
|
|
1968
|
+
).option("--metadata-file <path>", "Read metadata JSON from a file").option(
|
|
1969
|
+
"--if-revision <n>",
|
|
1970
|
+
"Fail if current revision doesn't match (optimistic lock)",
|
|
1971
|
+
parseInteger
|
|
1972
|
+
).option("--url", "Print only the published URL (no JSON envelope)").option(
|
|
1973
|
+
"--dry-run",
|
|
1974
|
+
"Show what would change without updating (JSON; cannot combine with --url)"
|
|
1975
|
+
).option("--json", "Force JSON output").option(
|
|
1976
|
+
"--idempotency-key <key>",
|
|
1977
|
+
"Prevent duplicate updates on retry (auto-generated)"
|
|
1978
|
+
).action(
|
|
1979
|
+
async (dropId, commandOptions) => {
|
|
1980
|
+
const stdinIsTTY = options.stdinIsTTY ?? process.stdin.isTTY ?? false;
|
|
1981
|
+
const global = globalOptions(program, commandOptions);
|
|
1982
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
1983
|
+
let dropOpts;
|
|
1984
|
+
try {
|
|
1985
|
+
dropOpts = toDropOptions(commandOptions);
|
|
1986
|
+
} catch (err) {
|
|
1987
|
+
const msg = err instanceof Error ? err.message : "Invalid option.";
|
|
1988
|
+
process.exitCode = writeError(deps, "invalid_usage", msg).exitCode;
|
|
1989
|
+
return;
|
|
1990
|
+
}
|
|
1991
|
+
const result = await runUpdateSettings(dropId, dropOpts, {
|
|
1901
1992
|
...deps,
|
|
1902
1993
|
interactive: isInteractive(stdinIsTTY, deps.env, global)
|
|
1903
1994
|
});
|
|
1904
1995
|
process.exitCode = result.exitCode;
|
|
1905
1996
|
}
|
|
1906
1997
|
);
|
|
1907
|
-
|
|
1998
|
+
program.command("get <dropId>").description("Show drop details (pass the full drop_\u2026 id)").option("--json", "Force JSON output").action(async (dropId, commandOptions) => {
|
|
1999
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
2000
|
+
const result = await runDropsGet(dropId, commandOptions, deps);
|
|
2001
|
+
process.exitCode = result.exitCode;
|
|
2002
|
+
});
|
|
2003
|
+
program.command("list").description("List your drops").option("--limit <n>", "Page size", parseInteger).option("--cursor <cursor>", "Pagination cursor").option("--json", "Force JSON output").action(
|
|
2004
|
+
async (commandOptions) => {
|
|
2005
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
2006
|
+
const result = await runDropsList(commandOptions, deps);
|
|
2007
|
+
process.exitCode = result.exitCode;
|
|
2008
|
+
}
|
|
2009
|
+
);
|
|
2010
|
+
program.command("delete <dropId>").description("Delete a drop (pass the full drop_\u2026 id)").option("--yes", "Confirm deletion").option("--json", "Force JSON output").action(
|
|
1908
2011
|
async (dropId, commandOptions) => {
|
|
1909
2012
|
const stdinIsTTY = options.stdinIsTTY ?? process.stdin.isTTY ?? false;
|
|
1910
2013
|
const global = globalOptions(program, commandOptions);
|
|
@@ -1920,6 +2023,26 @@ function buildProgram(options = {}) {
|
|
|
1920
2023
|
process.exitCode = result.exitCode;
|
|
1921
2024
|
}
|
|
1922
2025
|
);
|
|
2026
|
+
const deployments = program.command("deployments").description("View deployment history");
|
|
2027
|
+
deployments.command("list <dropId>").description("List deployments for a drop").option("--limit <n>", "Page size", parseInteger).option("--cursor <cursor>", "Pagination cursor").option("--json", "Force JSON output").action(
|
|
2028
|
+
async (dropId, commandOptions) => {
|
|
2029
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
2030
|
+
const result = await runDeploymentsList(dropId, commandOptions, deps);
|
|
2031
|
+
process.exitCode = result.exitCode;
|
|
2032
|
+
}
|
|
2033
|
+
);
|
|
2034
|
+
deployments.command("get <dropId> <deploymentId>").description("Show deployment details").option("--json", "Force JSON output").action(
|
|
2035
|
+
async (dropId, deploymentId, commandOptions) => {
|
|
2036
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
2037
|
+
const result = await runDeploymentsGet(
|
|
2038
|
+
dropId,
|
|
2039
|
+
deploymentId,
|
|
2040
|
+
commandOptions,
|
|
2041
|
+
deps
|
|
2042
|
+
);
|
|
2043
|
+
process.exitCode = result.exitCode;
|
|
2044
|
+
}
|
|
2045
|
+
);
|
|
1923
2046
|
const apiKeys = program.command("api-keys").description("Manage API keys");
|
|
1924
2047
|
apiKeys.command("create").description("Create an API key").option("--label <label>", "API key label", "CLI").option("--json", "Force JSON output").action(async (commandOptions) => {
|
|
1925
2048
|
const deps = await commandDeps(program, options, store, commandOptions);
|
|
@@ -1947,26 +2070,6 @@ function buildProgram(options = {}) {
|
|
|
1947
2070
|
process.exitCode = result.exitCode;
|
|
1948
2071
|
}
|
|
1949
2072
|
);
|
|
1950
|
-
const deployments = program.command("deployments").description("View deployment history");
|
|
1951
|
-
deployments.command("list <dropId>").description("List deployments for a drop").option("--limit <n>", "Page size", parseInteger).option("--cursor <cursor>", "Pagination cursor").option("--json", "Force JSON output").action(
|
|
1952
|
-
async (dropId, commandOptions) => {
|
|
1953
|
-
const deps = await commandDeps(program, options, store, commandOptions);
|
|
1954
|
-
const result = await runDeploymentsList(dropId, commandOptions, deps);
|
|
1955
|
-
process.exitCode = result.exitCode;
|
|
1956
|
-
}
|
|
1957
|
-
);
|
|
1958
|
-
deployments.command("get <dropId> <deploymentId>").description("Show deployment details").option("--json", "Force JSON output").action(
|
|
1959
|
-
async (dropId, deploymentId, commandOptions) => {
|
|
1960
|
-
const deps = await commandDeps(program, options, store, commandOptions);
|
|
1961
|
-
const result = await runDeploymentsGet(
|
|
1962
|
-
dropId,
|
|
1963
|
-
deploymentId,
|
|
1964
|
-
commandOptions,
|
|
1965
|
-
deps
|
|
1966
|
-
);
|
|
1967
|
-
process.exitCode = result.exitCode;
|
|
1968
|
-
}
|
|
1969
|
-
);
|
|
1970
2073
|
program.command("login").description("Authenticate with email OTP").option("--email <email>", "Email address").option("--otp <otp>", "One-time passcode").option("--json", "Force JSON output").action(
|
|
1971
2074
|
async (commandOptions) => {
|
|
1972
2075
|
if (!commandOptions.email || !commandOptions.otp) {
|
|
@@ -2191,11 +2294,6 @@ function parseInteger(value) {
|
|
|
2191
2294
|
if (Number.isNaN(n)) throw new import_commander.InvalidArgumentError("Expected an integer.");
|
|
2192
2295
|
return n;
|
|
2193
2296
|
}
|
|
2194
|
-
async function resolveCommandInput(input, stdin) {
|
|
2195
|
-
if (input !== "-") return input;
|
|
2196
|
-
const buf = await readStdinBytes(stdin ?? process.stdin);
|
|
2197
|
-
return buf.toString("utf8");
|
|
2198
|
-
}
|
|
2199
2297
|
async function resolvePublishInputs(inputs, stdin, stdinIsTTY) {
|
|
2200
2298
|
if (inputs.length === 0) {
|
|
2201
2299
|
if (stdinIsTTY) return void 0;
|