@robbeverhelst/do 1.90.0 → 1.91.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.
Files changed (2) hide show
  1. package/dist/do.js +78 -10
  2. package/package.json +1 -1
package/dist/do.js CHANGED
@@ -25,7 +25,8 @@ var GLOBAL_BOOLEAN_FLAGS = [
25
25
  "verbose",
26
26
  "help",
27
27
  "version",
28
- "allow-destructive"
28
+ "allow-destructive",
29
+ "dry-run"
29
30
  ];
30
31
  var SHORT_ALIASES = {
31
32
  h: "help",
@@ -24136,7 +24137,7 @@ function parseCapture2(input, now) {
24136
24137
 
24137
24138
  // src/meta.ts
24138
24139
  var CLI_NAME = "do";
24139
- var VERSION = "1.90.0";
24140
+ var VERSION = "1.91.0";
24140
24141
  var API_PREFIX = "/api/v1";
24141
24142
  var DEFAULT_API_URL = "http://localhost:3001";
24142
24143
 
@@ -24551,7 +24552,7 @@ function entityOperations(e) {
24551
24552
  if (e.write?.updateSchema)
24552
24553
  ops.push("update");
24553
24554
  if (e.write?.canDelete)
24554
- ops.push("delete");
24555
+ ops.push("delete", "archive");
24555
24556
  return ops;
24556
24557
  }
24557
24558
 
@@ -24589,6 +24590,11 @@ var GLOBAL_FLAGS = [
24589
24590
  name: "allow-destructive",
24590
24591
  type: "boolean",
24591
24592
  description: "Permit a destructive verb (delete/revoke/remove-member). Off by default \u2014 a guardrail for autonomous agents."
24593
+ },
24594
+ {
24595
+ name: "dry-run",
24596
+ type: "boolean",
24597
+ description: "Preview a create/update/delete/archive (prints before/after) without writing \u2014 for agent-driven cleanup."
24592
24598
  }
24593
24599
  ];
24594
24600
  var COMMAND_SPECS = [
@@ -25367,6 +25373,19 @@ function shortDate(iso) {
25367
25373
 
25368
25374
  // src/today.ts
25369
25375
  var OPEN_STATUSES = new Set(["todo", "in_progress"]);
25376
+ function isTaskLike(value) {
25377
+ return typeof value === "object" && value !== null && typeof value.id === "string";
25378
+ }
25379
+ function normalizeTasks(response) {
25380
+ if (Array.isArray(response))
25381
+ return response.filter(isTaskLike);
25382
+ if (response && typeof response === "object") {
25383
+ const data = response.data;
25384
+ if (Array.isArray(data))
25385
+ return data.filter(isTaskLike);
25386
+ }
25387
+ return [];
25388
+ }
25370
25389
  function toDate(value) {
25371
25390
  if (value == null)
25372
25391
  return null;
@@ -25383,7 +25402,7 @@ var pad = (n) => String(n).padStart(2, "0");
25383
25402
  function selectToday(tasks3, now) {
25384
25403
  const { start, end, label } = localDayBounds(now);
25385
25404
  const items = [];
25386
- for (const task of tasks3) {
25405
+ for (const task of normalizeTasks(tasks3)) {
25387
25406
  if (!OPEN_STATUSES.has(task.status))
25388
25407
  continue;
25389
25408
  const scheduled = toDate(task.scheduledAt);
@@ -25482,11 +25501,18 @@ async function dispatchEntity(entity, rest, flags, requireClient) {
25482
25501
  const id = requireArg(args, 0, "id");
25483
25502
  return { data: await client.get(`${entity.path}/${id}`), render: renderRecord };
25484
25503
  }
25504
+ const dryRun = flagBool(flags, "dry-run");
25485
25505
  if (op === "create") {
25486
25506
  const write = requireWrite(entity, "create");
25487
25507
  if (!write.createSchema)
25488
25508
  throw usageError(`\`${entity.name}\` cannot be created`);
25489
25509
  const body = parseInput(write.createSchema, { id: ulid3(), ...readDataFlag(flags) });
25510
+ if (dryRun) {
25511
+ return {
25512
+ data: { dryRun: true, op: "create", entity: entity.name, after: body },
25513
+ render: renderRecord
25514
+ };
25515
+ }
25490
25516
  return { data: await client.post(entity.path, body), render: renderRecord };
25491
25517
  }
25492
25518
  if (op === "update") {
@@ -25495,16 +25521,42 @@ async function dispatchEntity(entity, rest, flags, requireClient) {
25495
25521
  throw usageError(`\`${entity.name}\` cannot be updated`);
25496
25522
  const id = requireArg(args, 0, "id");
25497
25523
  const body = parseInput(write.updateSchema, readDataFlag(flags));
25524
+ if (dryRun) {
25525
+ const before = entity.canGet ? await client.get(`${entity.path}/${id}`) : null;
25526
+ return {
25527
+ data: {
25528
+ dryRun: true,
25529
+ op: "update",
25530
+ entity: entity.name,
25531
+ id,
25532
+ before,
25533
+ after: mergePreview(before, body),
25534
+ changes: body
25535
+ },
25536
+ render: renderRecord
25537
+ };
25538
+ }
25498
25539
  return { data: await client.patch(`${entity.path}/${id}`, body), render: renderRecord };
25499
25540
  }
25500
- if (op === "delete") {
25501
- const write = requireWrite(entity, "delete");
25541
+ if (op === "delete" || op === "archive") {
25542
+ const write = requireWrite(entity, op);
25502
25543
  if (!write.canDelete)
25503
- throw usageError(`\`${entity.name}\` cannot be deleted`);
25544
+ throw usageError(`\`${entity.name}\` cannot be ${op}d`);
25504
25545
  const id = requireArg(args, 0, "id");
25505
- assertDestructiveAllowed(flags, `delete ${entity.name} ${id}`);
25546
+ if (dryRun) {
25547
+ const before = entity.canGet ? await client.get(`${entity.path}/${id}`) : null;
25548
+ return {
25549
+ data: { dryRun: true, op, entity: entity.name, id, before, softDelete: true },
25550
+ render: renderRecord
25551
+ };
25552
+ }
25553
+ if (op === "delete")
25554
+ assertDestructiveAllowed(flags, `delete ${entity.name} ${id}`);
25506
25555
  await client.delete(`${entity.path}/${id}`);
25507
- return { data: { ok: true, deleted: id }, render: renderRecord };
25556
+ return {
25557
+ data: op === "archive" ? { ok: true, archived: id, softDelete: true } : { ok: true, deleted: id, softDelete: true },
25558
+ render: renderRecord
25559
+ };
25508
25560
  }
25509
25561
  throw usageError(`unknown operation for ${entity.name}: \`${op ?? ""}\` (use ${entityOperations(entity).join(", ")})`);
25510
25562
  }
@@ -25542,7 +25594,16 @@ var HANDLERS = {
25542
25594
  return { data: task, render: renderTask };
25543
25595
  },
25544
25596
  today: async ({ io, requireClient }) => {
25545
- const tasks3 = await requireClient().get("/tasks", { query: { filter: "all" } });
25597
+ const client = requireClient();
25598
+ const tasks3 = [];
25599
+ let cursor;
25600
+ do {
25601
+ const page = await client.getPage("/tasks", {
25602
+ query: { filter: "all", cursor }
25603
+ });
25604
+ tasks3.push(...page.data);
25605
+ cursor = page.nextCursor ?? undefined;
25606
+ } while (cursor);
25546
25607
  return {
25547
25608
  data: selectToday(tasks3, io.now()),
25548
25609
  render: renderToday
@@ -25949,6 +26010,13 @@ function requireWrite(entity, op) {
25949
26010
  }
25950
26011
  return entity.write;
25951
26012
  }
26013
+ function mergePreview(before, changes) {
26014
+ const patch = changes && typeof changes === "object" && !Array.isArray(changes) ? changes : {};
26015
+ if (before && typeof before === "object" && !Array.isArray(before)) {
26016
+ return { ...before, ...patch };
26017
+ }
26018
+ return changes;
26019
+ }
25952
26020
  function readDataFlag(flags) {
25953
26021
  const raw = flagString(flags, "data");
25954
26022
  if (raw === undefined)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robbeverhelst/do",
3
- "version": "1.90.0",
3
+ "version": "1.91.0",
4
4
  "private": false,
5
5
  "description": "do — the agent-drivable CLI over the public /api/v1 surface",
6
6
  "type": "module",