@dropthis/cli 0.16.0 → 0.18.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 CHANGED
@@ -322,6 +322,11 @@ function writeResult(deps, link, verb, data) {
322
322
  const details = formatDropDetails(data);
323
323
  if (details) deps.stdout(`${details}
324
324
  `);
325
+ const rawUrl = data.rawUrl;
326
+ if (typeof rawUrl === "string" && rawUrl.length > 0) {
327
+ deps.stdout(`${hint(`Raw: ${url(rawUrl)}`)}
328
+ `);
329
+ }
325
330
  const warnings = data.warnings;
326
331
  if (Array.isArray(warnings)) {
327
332
  for (const w of warnings) {
@@ -697,6 +702,13 @@ var COMMAND_ANNOTATIONS = {
697
702
  auth: "required",
698
703
  examples: ["dropthis get drop_abc --json"]
699
704
  },
705
+ resolve: {
706
+ auth: "required",
707
+ examples: [
708
+ "dropthis resolve https://abc123.dropthis.app/",
709
+ "dropthis resolve abc123 --json"
710
+ ]
711
+ },
700
712
  list: {
701
713
  auth: "required",
702
714
  examples: [
@@ -904,13 +916,13 @@ async function runDoctor(_input, deps) {
904
916
  const authSource = credential?.source ?? "missing";
905
917
  const storageBackend = stored?.storage ?? "none";
906
918
  const pairs = [
907
- ["Version", "0.16.0"],
919
+ ["Version", "0.18.0"],
908
920
  ["Auth", authSource],
909
921
  ["Storage", storageBackend]
910
922
  ];
911
923
  writeKv(deps, pairs, {
912
924
  ok: true,
913
- version: "0.16.0",
925
+ version: "0.18.0",
914
926
  auth: { source: authSource },
915
927
  storage: { backend: storageBackend }
916
928
  });
@@ -1281,9 +1293,19 @@ async function resolveDropTarget(target, deps) {
1281
1293
  return {
1282
1294
  ok: true,
1283
1295
  dropId: resolved.data.id,
1284
- ...resolved.data.slug ? { slug: resolved.data.slug } : {}
1296
+ resolvedFrom: target,
1297
+ ...resolved.data.slug ? { slug: resolved.data.slug } : {},
1298
+ ...typeof resolved.data.title === "string" ? { title: resolved.data.title } : {}
1285
1299
  };
1286
1300
  }
1301
+ function writeResolvedLine(deps, resolved) {
1302
+ if (!resolved.resolvedFrom || deps.outputMode !== "human") return;
1303
+ const title = resolved.title ? ` (${resolved.title})` : "";
1304
+ deps.stdout(
1305
+ `${hint(`resolved ${resolved.resolvedFrom} \u2192 ${resolved.dropId}${title}`)}
1306
+ `
1307
+ );
1308
+ }
1287
1309
  async function runDropsList(input, deps) {
1288
1310
  try {
1289
1311
  await requireCredential({
@@ -1347,6 +1369,7 @@ async function runDropsGet(target, _input, deps) {
1347
1369
  }
1348
1370
  const resolved = await resolveDropTarget(target, deps);
1349
1371
  if (!resolved.ok) return { exitCode: resolved.exitCode };
1372
+ writeResolvedLine(deps, resolved);
1350
1373
  const result = await deps.client.drops.get(resolved.dropId);
1351
1374
  if (result.error) return writeApiError(deps, result.error);
1352
1375
  const data = result.data;
@@ -1369,6 +1392,34 @@ async function runDropsGet(target, _input, deps) {
1369
1392
  writeKv(deps, pairs, { ok: true, drop: result.data });
1370
1393
  return { exitCode: 0 };
1371
1394
  }
1395
+ async function runDropsResolve(target, _input, deps) {
1396
+ try {
1397
+ await requireCredential({
1398
+ ...deps.apiKey ? { apiKey: deps.apiKey } : {},
1399
+ env: deps.env,
1400
+ store: deps.store
1401
+ });
1402
+ } catch {
1403
+ return writeAuthError(deps);
1404
+ }
1405
+ const result = await deps.client.drops.resolve(target);
1406
+ if (result.error) return writeApiError(deps, result.error);
1407
+ if (result.data === null) {
1408
+ return writeApiError(deps, {
1409
+ code: "not_found",
1410
+ message: `No drop matching "${target}" found in your account.`,
1411
+ suggestion: "It may belong to another account or have been deleted. Run dropthis list to see your drops, or pass the full drop_\u2026 id."
1412
+ });
1413
+ }
1414
+ const drop = result.data;
1415
+ const pairs = [];
1416
+ if (drop.id) pairs.push(["ID", String(drop.id)]);
1417
+ if (drop.url) pairs.push(["URL", url(String(drop.url))]);
1418
+ if (drop.title) pairs.push(["Title", String(drop.title)]);
1419
+ if (drop.slug) pairs.push(["Slug", String(drop.slug)]);
1420
+ writeKv(deps, pairs, { ok: true, drop });
1421
+ return { exitCode: 0 };
1422
+ }
1372
1423
  async function runDropsDelete(target, input, deps) {
1373
1424
  if (!input.yes && input.interactive === false) {
1374
1425
  return writeError(
@@ -1388,6 +1439,7 @@ async function runDropsDelete(target, input, deps) {
1388
1439
  }
1389
1440
  const resolved = await resolveDropTarget(target, deps);
1390
1441
  if (!resolved.ok) return { exitCode: resolved.exitCode };
1442
+ writeResolvedLine(deps, resolved);
1391
1443
  const dropId = resolved.dropId;
1392
1444
  if (!input.yes && input.interactive !== false) {
1393
1445
  const confirmed = await prompts3.confirm({
@@ -1815,6 +1867,7 @@ async function runPull(target, input, deps) {
1815
1867
  }
1816
1868
  const resolved = await resolveDropTarget(target, deps);
1817
1869
  if (!resolved.ok) return { exitCode: resolved.exitCode };
1870
+ writeResolvedLine(deps, resolved);
1818
1871
  const dropId = resolved.dropId;
1819
1872
  const defaultDirName = resolved.slug || resolved.dropId;
1820
1873
  const spin = shouldSpin(deps.outputMode) ? createSpinner("Pulling content\u2026", deps.stderr) : void 0;
@@ -1900,22 +1953,30 @@ function contentOptions(options) {
1900
1953
  if (options.path !== void 0) out.path = options.path;
1901
1954
  return out;
1902
1955
  }
1903
- async function runUpdateContent(dropId, input, raw, deps) {
1956
+ async function runUpdateContent(target, input, raw, deps) {
1957
+ const apiKey = raw.apiKey ?? deps.apiKey;
1904
1958
  try {
1905
1959
  await requireCredential({
1906
- ...raw.apiKey ?? deps.apiKey ? { apiKey: raw.apiKey ?? deps.apiKey } : {},
1960
+ ...apiKey ? { apiKey } : {},
1907
1961
  env: deps.env,
1908
1962
  store: deps.store
1909
1963
  });
1910
1964
  } catch {
1911
1965
  return writeAuthError(deps);
1912
1966
  }
1967
+ const resolveDeps = {
1968
+ ...deps,
1969
+ ...apiKey ? { apiKey } : {}
1970
+ };
1971
+ const resolved = await resolveDropTarget(target, resolveDeps);
1972
+ if (!resolved.ok) return { exitCode: resolved.exitCode };
1973
+ const dropId = resolved.dropId;
1913
1974
  if (raw.dryRun) {
1914
1975
  return handleDryRun(dropId, input, raw, deps);
1915
1976
  }
1977
+ writeResolvedLine(deps, resolved);
1916
1978
  let spin;
1917
1979
  try {
1918
- assertDropId(dropId);
1919
1980
  const hasInput = Array.isArray(input) ? input.length > 0 : input !== void 0;
1920
1981
  if (!hasInput) {
1921
1982
  return writeError(
@@ -1962,7 +2023,6 @@ async function handleDryRun(dropId, input, raw, deps) {
1962
2023
  );
1963
2024
  }
1964
2025
  try {
1965
- assertDropId(dropId);
1966
2026
  const hasInput = Array.isArray(input) ? input.length > 0 : input !== void 0;
1967
2027
  if (!hasInput) {
1968
2028
  return writeError(
@@ -1990,34 +2050,35 @@ async function handleDryRun(dropId, input, raw, deps) {
1990
2050
  return writeError(deps, code, message);
1991
2051
  }
1992
2052
  }
1993
- function assertDropId(target) {
1994
- if (!target.startsWith("drop_")) {
1995
- throw new Error(
1996
- "update-content needs the full drop_\u2026 id from the publish response, not the URL slug, for example drop_..."
1997
- );
1998
- }
1999
- }
2000
2053
 
2001
2054
  // src/commands/update-settings.ts
2002
2055
  var prompts5 = __toESM(require("@clack/prompts"), 1);
2003
2056
  var NO_SETTINGS_MESSAGE = "Nothing to update. Provide at least one settings option.";
2004
2057
  var NO_SETTINGS_NEXT_ACTION = "Run dropthis update-settings --help, or retry with one of: --title, --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.";
2005
- async function runUpdateSettings(dropId, raw, deps) {
2058
+ async function runUpdateSettings(target, raw, deps) {
2059
+ const apiKey = raw.apiKey ?? deps.apiKey;
2006
2060
  try {
2007
2061
  await requireCredential({
2008
- ...raw.apiKey ?? deps.apiKey ? { apiKey: raw.apiKey ?? deps.apiKey } : {},
2062
+ ...apiKey ? { apiKey } : {},
2009
2063
  env: deps.env,
2010
2064
  store: deps.store
2011
2065
  });
2012
2066
  } catch {
2013
2067
  return writeAuthError(deps);
2014
2068
  }
2069
+ const resolveDeps = {
2070
+ ...deps,
2071
+ ...apiKey ? { apiKey } : {}
2072
+ };
2073
+ const resolved = await resolveDropTarget(target, resolveDeps);
2074
+ if (!resolved.ok) return { exitCode: resolved.exitCode };
2075
+ const dropId = resolved.dropId;
2015
2076
  if (raw.dryRun) {
2016
2077
  return handleDryRun2(dropId, raw, deps);
2017
2078
  }
2079
+ writeResolvedLine(deps, resolved);
2018
2080
  let spin;
2019
2081
  try {
2020
- assertDropId2(dropId);
2021
2082
  let parsed = await parseDropOptions(raw);
2022
2083
  if (!hasSettingsFields(parsed)) {
2023
2084
  if (shouldPrompt(deps)) {
@@ -2206,7 +2267,6 @@ async function handleDryRun2(dropId, raw, deps) {
2206
2267
  );
2207
2268
  }
2208
2269
  try {
2209
- assertDropId2(dropId);
2210
2270
  const options = await parseDropOptions(raw);
2211
2271
  const fields = {};
2212
2272
  if (options.title) fields.title = options.title;
@@ -2225,13 +2285,6 @@ async function handleDryRun2(dropId, raw, deps) {
2225
2285
  return writeError(deps, "invalid_usage", message);
2226
2286
  }
2227
2287
  }
2228
- function assertDropId2(target) {
2229
- if (!target.startsWith("drop_")) {
2230
- throw new Error(
2231
- "update-settings needs the full drop_\u2026 id from the publish response, not the URL slug, for example drop_..."
2232
- );
2233
- }
2234
- }
2235
2288
 
2236
2289
  // src/commands/upgrade.ts
2237
2290
  var import_node_child_process = require("child_process");
@@ -2591,7 +2644,7 @@ function buildProgram(options = {}) {
2591
2644
  ` ${import_picocolors6.default.cyan("dropthis login")}`,
2592
2645
  ` ${import_picocolors6.default.cyan("dropthis publish ./dist")}`
2593
2646
  ].join("\n")
2594
- ).version("0.16.0").configureHelp({
2647
+ ).version("0.18.0").configureHelp({
2595
2648
  subcommandTerm(cmd) {
2596
2649
  const args = cmd.registeredArguments.map((a) => {
2597
2650
  const name = a.name();
@@ -2655,6 +2708,18 @@ ${lines.map((l) => ` ${l}`).join("\n")}
2655
2708
  "dropthis publish ./report.html --domain shared # bypass the account default domain",
2656
2709
  "URL=$(dropthis publish ./dist --url)"
2657
2710
  ])
2711
+ ).addHelpText(
2712
+ "after",
2713
+ [
2714
+ `
2715
+ ${import_picocolors6.default.bold("Canonical vs raw URLs:")}`,
2716
+ " The canonical URL (the one printed) is always a branded human view, so the",
2717
+ " badge is guaranteed \u2014 hand it to people. For a single non-HTML file (e.g. a",
2718
+ " .md or .json), publish also prints a 'Raw:' line: the raw bytes at their",
2719
+ " natural path, with no wrapper \u2014 hand this to other agents. HTML drops and",
2720
+ " multi-file collections have no raw URL (the page IS the artifact / per-file",
2721
+ " paths come from the manifest)."
2722
+ ].join("\n")
2658
2723
  ).action(async (inputs, commandOptions) => {
2659
2724
  const stdinIsTTY = options.stdinIsTTY ?? process.stdin.isTTY ?? false;
2660
2725
  if (inputs.length === 0 && stdinIsTTY) {
@@ -2832,6 +2897,19 @@ ${lines.map((l) => ` ${l}`).join("\n")}
2832
2897
  const result = await runDropsGet(dropId, commandOptions, deps);
2833
2898
  process.exitCode = result.exitCode;
2834
2899
  });
2900
+ program.command("resolve <target>").description(
2901
+ "Resolve a public drop URL or slug back to its drop_\u2026 id (accepts the id too).\nWrites are id-only \u2014 use this to recover the id from a URL, then update-content/update-settings/delete by that id."
2902
+ ).option("--json", "Force JSON output").addHelpText(
2903
+ "after",
2904
+ examplesBlock([
2905
+ "dropthis resolve https://abc123.dropthis.app/ # \u2192 drop_\u2026 id + url",
2906
+ "dropthis resolve abc123 --json | jq -r .drop.id"
2907
+ ])
2908
+ ).action(async (target, commandOptions) => {
2909
+ const deps = await commandDeps(program, options, store, commandOptions);
2910
+ const result = await runDropsResolve(target, commandOptions, deps);
2911
+ process.exitCode = result.exitCode;
2912
+ });
2835
2913
  program.command("list").description("List your drops").option("--limit <n>", "Page size", parseInteger).option("--cursor <cursor>", "Pagination cursor").option("--domain <hostname>", "Only drops mounted on this custom domain").option("--json", "Force JSON output").addHelpText(
2836
2914
  "after",
2837
2915
  examplesBlock([
@@ -3136,7 +3214,7 @@ ${lines.map((l) => ` ${l}`).join("\n")}
3136
3214
  );
3137
3215
  const result = await runUpgrade(commandOptions, {
3138
3216
  ...deps,
3139
- currentVersion: "0.16.0"
3217
+ currentVersion: "0.18.0"
3140
3218
  });
3141
3219
  process.exitCode = result.exitCode;
3142
3220
  });
@@ -3379,7 +3457,7 @@ var showNotice = shouldShowNotice({
3379
3457
  if (showNotice) {
3380
3458
  const notice = noticeFromCache({
3381
3459
  cache: updateCache,
3382
- currentVersion: "0.16.0"
3460
+ currentVersion: "0.18.0"
3383
3461
  });
3384
3462
  if (notice) {
3385
3463
  process.stderr.write(`