@dropthis/cli 0.6.0 → 0.7.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/README.md CHANGED
@@ -108,7 +108,6 @@ All publish flags:
108
108
  | `--metadata <json>` | Metadata as JSON string |
109
109
  | `--metadata-file <path>` | Metadata from a JSON file |
110
110
  | `--idempotency-key <key>` | Idempotency key |
111
- | `--from-json <path>` | Read exact POST /drops JSON request body from file |
112
111
  | `--url` | Print only the URL, nothing else |
113
112
  | `--json` | Output full JSON response |
114
113
  | `--dry-run` | Validate without publishing |
package/dist/cli.cjs CHANGED
@@ -754,13 +754,13 @@ async function runDoctor(_input, deps) {
754
754
  const authSource = credential?.source ?? "missing";
755
755
  const storageBackend = stored?.storage ?? "none";
756
756
  const pairs = [
757
- ["Version", "0.6.0"],
757
+ ["Version", "0.7.0"],
758
758
  ["Auth", authSource],
759
759
  ["Storage", storageBackend]
760
760
  ];
761
761
  writeKv(deps, pairs, {
762
762
  ok: true,
763
- version: "0.6.0",
763
+ version: "0.7.0",
764
764
  auth: { source: authSource },
765
765
  storage: { backend: storageBackend }
766
766
  });
@@ -1140,22 +1140,6 @@ function shouldSpin(outputMode) {
1140
1140
  return outputMode === "human" && process.stderr.isTTY === true && !process.env.CI;
1141
1141
  }
1142
1142
 
1143
- // src/commands/json_body.ts
1144
- var import_promises2 = require("fs/promises");
1145
- async function readJsonObjectFile(path) {
1146
- let parsed;
1147
- try {
1148
- parsed = JSON.parse(await (0, import_promises2.readFile)(path, "utf8"));
1149
- } catch (error2) {
1150
- const message = error2 instanceof Error ? error2.message : "Unknown parse error";
1151
- throw new Error(`Invalid JSON body in ${path}: ${message}`);
1152
- }
1153
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
1154
- throw new Error("JSON body must be an object.");
1155
- }
1156
- return parsed;
1157
- }
1158
-
1159
1143
  // src/commands/publish.ts
1160
1144
  async function runPublish(input, raw, deps) {
1161
1145
  let credential;
@@ -1192,14 +1176,9 @@ async function runPublish(input, raw, deps) {
1192
1176
  const hasInput = Array.isArray(input) ? input.length > 0 : input !== void 0;
1193
1177
  const spin = shouldSpin(deps.outputMode) ? createSpinner("Publishing\u2026", deps.stderr) : void 0;
1194
1178
  try {
1195
- if (raw.fromJson && hasInput) {
1196
- throw new Error("Use either <input> or --from-json, not both.");
1197
- }
1198
1179
  const options = withIdempotencyKey(await parseDropOptions(raw), "pub");
1199
- const jsonBody = raw.fromJson ? await (deps.readJsonObject ?? readJsonObjectFile)(raw.fromJson) : void 0;
1200
- const idempotencyOpt = options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {};
1201
- const doPublish = (c) => jsonBody ? c.drops.createRaw(jsonBody, idempotencyOpt) : hasInput ? c.publish(input, options) : (() => {
1202
- throw new Error("Publish requires <input> or --from-json.");
1180
+ const doPublish = (c) => hasInput ? c.publish(input, options) : (() => {
1181
+ throw new Error("Publish requires <input>.");
1203
1182
  })();
1204
1183
  const result = await doPublish(client);
1205
1184
  if (result.error) {
@@ -1259,20 +1238,8 @@ async function handlePublishDryRun(input, raw, deps, client) {
1259
1238
  );
1260
1239
  }
1261
1240
  try {
1262
- if (raw.fromJson) {
1263
- if (input)
1264
- throw new Error("Use either <input> or --from-json, not both.");
1265
- const body = await (deps.readJsonObject ?? readJsonObjectFile)(
1266
- raw.fromJson
1267
- );
1268
- deps.stdout(
1269
- `${JSON.stringify({ ok: true, dryRun: true, kind: "raw_json", endpoint: "POST /drops", body }, null, 2)}
1270
- `
1271
- );
1272
- return { exitCode: 0 };
1273
- }
1274
1241
  if (!input || Array.isArray(input) && input.length === 0) {
1275
- throw new Error("Publish requires <input> or --from-json.");
1242
+ throw new Error("Publish requires <input>.");
1276
1243
  }
1277
1244
  const options = await parseDropOptions(raw);
1278
1245
  if (!client.prepare) {
@@ -1297,6 +1264,27 @@ async function handlePublishDryRun(input, raw, deps, client) {
1297
1264
  var prompts4 = __toESM(require("@clack/prompts"), 1);
1298
1265
  var NO_UPDATE_MESSAGE = "Nothing to update. Provide an input path or at least one update option.";
1299
1266
  var NO_UPDATE_NEXT_ACTION = "Run dropthis drops update --help, or retry with an input path (for example, dropthis drops update <dropId> ./dist) or one of: --title, --slug, --visibility, --password, --no-password, --noindex, --index, --expires-at, or --metadata.";
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) {
1282
+ const out = {};
1283
+ if (options.entry !== void 0) out.entry = options.entry;
1284
+ if (options.contentType !== void 0) out.contentType = options.contentType;
1285
+ if (options.path !== void 0) out.path = options.path;
1286
+ return out;
1287
+ }
1300
1288
  async function runUpdate(target, input, raw, deps) {
1301
1289
  try {
1302
1290
  await requireCredential({
@@ -1313,12 +1301,9 @@ async function runUpdate(target, input, raw, deps) {
1313
1301
  let spin;
1314
1302
  try {
1315
1303
  assertDropId(target);
1316
- if (raw.fromJson && input) {
1317
- throw new Error("Use either [input] or --from-json, not both.");
1318
- }
1319
1304
  let updateInput = input;
1320
1305
  let parsed = await parseDropOptions(raw);
1321
- if (!updateInput && !raw.fromJson && !hasUpdateFields(parsed)) {
1306
+ if (!updateInput && !hasUpdateFields(parsed)) {
1322
1307
  if (shouldPromptForUpdate(deps)) {
1323
1308
  const prompted = await promptForUpdate(target, deps.prompts ?? prompts4);
1324
1309
  if (!prompted) return { exitCode: 0 };
@@ -1333,22 +1318,23 @@ async function runUpdate(target, input, raw, deps) {
1333
1318
  );
1334
1319
  }
1335
1320
  }
1321
+ if (updateInput && hasSettingsFields(parsed)) {
1322
+ return writeError(
1323
+ deps,
1324
+ "invalid_usage",
1325
+ DEPLOY_REJECTS_SETTINGS,
1326
+ DEPLOY_SETTINGS_NEXT_ACTION
1327
+ );
1328
+ }
1336
1329
  const revisionOptions = raw.ifRevision !== void 0 ? { ifRevision: Number(raw.ifRevision) } : {};
1337
1330
  spin = shouldSpin(deps.outputMode) ? createSpinner("Updating\u2026", deps.stderr) : void 0;
1338
- const result = raw.fromJson ? await deps.client.deployments.createRaw(
1331
+ const result = updateInput ? await deps.client.deploy(
1339
1332
  target,
1340
- await (deps.readJsonObject ?? readJsonObjectFile)(raw.fromJson),
1333
+ updateInput,
1341
1334
  withIdempotencyKey(
1342
- {
1343
- ...revisionOptions,
1344
- ...parsed.idempotencyKey ? { idempotencyKey: parsed.idempotencyKey } : {}
1345
- },
1335
+ { ...contentDeployOptions(parsed), ...revisionOptions },
1346
1336
  "upd"
1347
1337
  )
1348
- ) : updateInput ? await deps.client.deploy(
1349
- target,
1350
- updateInput,
1351
- withIdempotencyKey({ ...parsed, ...revisionOptions }, "upd")
1352
1338
  ) : await deps.client.update(
1353
1339
  target,
1354
1340
  withIdempotencyKey({ ...parsed, ...revisionOptions }, "upd")
@@ -1536,18 +1522,6 @@ async function handleUpdateDryRun(target, input, raw, deps) {
1536
1522
  }
1537
1523
  try {
1538
1524
  assertDropId(target);
1539
- if (raw.fromJson) {
1540
- if (input)
1541
- throw new Error("Use either [input] or --from-json, not both.");
1542
- const body = await (deps.readJsonObject ?? readJsonObjectFile)(
1543
- raw.fromJson
1544
- );
1545
- deps.stdout(
1546
- `${JSON.stringify({ ok: true, dryRun: true, kind: "raw_json", endpoint: `POST /drops/${target}/deployments`, body }, null, 2)}
1547
- `
1548
- );
1549
- return { exitCode: 0 };
1550
- }
1551
1525
  const options = await parseDropOptions(raw);
1552
1526
  if (!input) {
1553
1527
  const fields = {};
@@ -1663,7 +1637,7 @@ function createContext(input) {
1663
1637
  }
1664
1638
 
1665
1639
  // src/storage.ts
1666
- var import_promises3 = require("fs/promises");
1640
+ var import_promises2 = require("fs/promises");
1667
1641
  var import_node_os = require("os");
1668
1642
  var import_node_path = require("path");
1669
1643
  var import_keyring = require("@napi-rs/keyring");
@@ -1697,7 +1671,7 @@ var InsecureFileCredentialStore = class {
1697
1671
  });
1698
1672
  }
1699
1673
  async clear() {
1700
- await (0, import_promises3.rm)(this.filePath, { force: true });
1674
+ await (0, import_promises2.rm)(this.filePath, { force: true });
1701
1675
  }
1702
1676
  };
1703
1677
  var KeyringCredentialStore = class {
@@ -1724,7 +1698,7 @@ var KeyringCredentialStore = class {
1724
1698
  }
1725
1699
  async clear() {
1726
1700
  await this.keyring.deletePassword();
1727
- await (0, import_promises3.rm)(this.filePath, { force: true });
1701
+ await (0, import_promises2.rm)(this.filePath, { force: true });
1728
1702
  }
1729
1703
  };
1730
1704
  function createCredentialStore(options = {}) {
@@ -1749,7 +1723,7 @@ function credentialPath(configDir) {
1749
1723
  }
1750
1724
  async function readJsonFile(path) {
1751
1725
  try {
1752
- return JSON.parse(await (0, import_promises3.readFile)(path, "utf8"));
1726
+ return JSON.parse(await (0, import_promises2.readFile)(path, "utf8"));
1753
1727
  } catch (error2) {
1754
1728
  if (error2 && typeof error2 === "object" && "code" in error2 && error2.code === "ENOENT") {
1755
1729
  return null;
@@ -1758,14 +1732,14 @@ async function readJsonFile(path) {
1758
1732
  }
1759
1733
  }
1760
1734
  async function writeCredentialFile(path, credential) {
1761
- await (0, import_promises3.mkdir)((0, import_node_path.dirname)(path), { recursive: true });
1735
+ await (0, import_promises2.mkdir)((0, import_node_path.dirname)(path), { recursive: true });
1762
1736
  const tmpPath = `${path}.${process.pid}.tmp`;
1763
- await (0, import_promises3.writeFile)(tmpPath, `${JSON.stringify(credential, null, 2)}
1737
+ await (0, import_promises2.writeFile)(tmpPath, `${JSON.stringify(credential, null, 2)}
1764
1738
  `, {
1765
1739
  mode: 384
1766
1740
  });
1767
- await (0, import_promises3.chmod)(tmpPath, 384);
1768
- await (0, import_promises3.rename)(tmpPath, path);
1741
+ await (0, import_promises2.chmod)(tmpPath, 384);
1742
+ await (0, import_promises2.rename)(tmpPath, path);
1769
1743
  }
1770
1744
 
1771
1745
  // src/program.ts
@@ -1794,7 +1768,7 @@ function buildProgram(options = {}) {
1794
1768
  ` ${import_picocolors4.default.cyan("dropthis login")}`,
1795
1769
  ` ${import_picocolors4.default.cyan("dropthis publish ./dist")}`
1796
1770
  ].join("\n")
1797
- ).version("0.6.0").configureHelp({
1771
+ ).version("0.7.0").configureHelp({
1798
1772
  subcommandTerm(cmd) {
1799
1773
  const args = cmd.registeredArguments.map((a) => {
1800
1774
  const name = a.name();
@@ -1827,12 +1801,12 @@ function buildProgram(options = {}) {
1827
1801
  ).option("--metadata-file <path>", "Read metadata JSON from a file").option("--path <name>", "Set filename when publishing from stdin").option("--url", "Print only the published URL (no JSON envelope)").option(
1828
1802
  "--dry-run",
1829
1803
  "Show what would be published without publishing (JSON; cannot combine with --url)"
1830
- ).option("--json", "Force JSON output").option("--from-json <path>", "Send raw API request body from a JSON file").option(
1804
+ ).option("--json", "Force JSON output").option(
1831
1805
  "--idempotency-key <key>",
1832
1806
  "Prevent duplicate publishes on retry (auto-generated)"
1833
1807
  ).action(async (inputs, commandOptions) => {
1834
1808
  const stdinIsTTY = options.stdinIsTTY ?? process.stdin.isTTY ?? false;
1835
- if (inputs.length === 0 && stdinIsTTY && !commandOptions.fromJson) {
1809
+ if (inputs.length === 0 && stdinIsTTY) {
1836
1810
  program.outputHelp();
1837
1811
  return;
1838
1812
  }
@@ -1896,9 +1870,6 @@ function buildProgram(options = {}) {
1896
1870
  "--dry-run",
1897
1871
  "Show what would be updated without updating (JSON; cannot combine with --url)"
1898
1872
  ).option("--json", "Force JSON output").option(
1899
- "--from-json <path>",
1900
- "Send raw API deployment body from a JSON file"
1901
- ).option(
1902
1873
  "--idempotency-key <key>",
1903
1874
  "Prevent duplicate updates on retry (auto-generated)"
1904
1875
  ).action(
@@ -2212,7 +2183,6 @@ function toDropOptions(options) {
2212
2183
  ...options.quiet !== void 0 ? { quiet: options.quiet } : {},
2213
2184
  ...options.url !== void 0 ? { url: options.url } : {},
2214
2185
  ...options.ifRevision !== void 0 ? { ifRevision: options.ifRevision } : {},
2215
- ...options.fromJson ? { fromJson: options.fromJson } : {},
2216
2186
  ...options.dryRun ? { dryRun: options.dryRun } : {}
2217
2187
  };
2218
2188
  }