@robbeverhelst/do 1.87.0 → 1.88.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 +110 -20
  2. package/package.json +1 -1
package/dist/do.js CHANGED
@@ -4371,6 +4371,7 @@ var userSettings = pgTable("user_settings", {
4371
4371
  density: settingsDensity("density").notNull().default("comfortable"),
4372
4372
  accent: settingsAccent("accent").notNull().default("teal"),
4373
4373
  enabledModules: text("enabled_modules").array().notNull().default([]),
4374
+ autoRollOverdue: boolean("auto_roll_overdue").notNull().default(false),
4374
4375
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
4375
4376
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
4376
4377
  }, (t) => [unique("user_settings_tenant_user_uniq").on(t.tenantId, t.userId)]);
@@ -4479,7 +4480,8 @@ var notificationType = pgEnum("notification_type", [
4479
4480
  "contact_date_due",
4480
4481
  "automation",
4481
4482
  "streak_at_risk",
4482
- "reflection_nudge"
4483
+ "reflection_nudge",
4484
+ "shutdown_nudge"
4483
4485
  ]);
4484
4486
  var notifications = pgTable("notifications", {
4485
4487
  id: text("id").primaryKey(),
@@ -19740,6 +19742,11 @@ var linkGoogleInputSchema = exports_external.object({
19740
19742
  code: exports_external.string().min(1),
19741
19743
  state: exports_external.string().min(1)
19742
19744
  });
19745
+ // ../../packages/schema/src/contracts/pagination.ts
19746
+ var paginationQuerySchema = exports_external.object({
19747
+ limit: exports_external.coerce.number().int().positive().optional(),
19748
+ cursor: exports_external.string().min(1).optional()
19749
+ });
19743
19750
  // ../../packages/schema/src/contracts/value-sets.ts
19744
19751
  var areaColorSchema = exports_external.enum(areaColor.enumValues);
19745
19752
  var reviewCadenceSchema = exports_external.enum(reviewCadence.enumValues);
@@ -20421,7 +20428,8 @@ var updateUserSettingsInputSchema = createUpdateSchema(userSettings, {
20421
20428
  theme: settingsThemeSchema.optional(),
20422
20429
  density: settingsDensitySchema.optional(),
20423
20430
  accent: settingsAccentSchema.optional(),
20424
- enabledModules: exports_external.array(exports_external.string().trim().min(1)).transform(normalizeEnabledModules).optional()
20431
+ enabledModules: exports_external.array(exports_external.string().trim().min(1)).transform(normalizeEnabledModules).optional(),
20432
+ autoRollOverdue: exports_external.boolean().optional()
20425
20433
  }).omit({ id: true, tenantId: true, userId: true, createdAt: true, updatedAt: true }).strict();
20426
20434
  // ../../packages/schema/src/contracts/notifications.ts
20427
20435
  var notificationSchema = createSelectSchema(notifications, {
@@ -20451,6 +20459,19 @@ var todayResponseSchema = exports_external.object({
20451
20459
  overdueTasks: exports_external.array(taskViewSchema),
20452
20460
  overdueOccurrences: exports_external.array(occurrenceViewSchema)
20453
20461
  });
20462
+ var rolloverInputSchema = exports_external.object({
20463
+ taskIds: exports_external.array(exports_external.string().min(1)).default([]),
20464
+ occurrenceIds: exports_external.array(exports_external.string().min(1)).default([]),
20465
+ action: exports_external.enum(["reschedule", "drop"]),
20466
+ to: exports_external.coerce.date().optional()
20467
+ }).refine((v) => v.action !== "reschedule" || v.to !== undefined, {
20468
+ message: "`to` is required when action is `reschedule`",
20469
+ path: ["to"]
20470
+ });
20471
+ var rolloverResultSchema = exports_external.object({
20472
+ tasks: exports_external.number().int().nonnegative(),
20473
+ occurrences: exports_external.number().int().nonnegative()
20474
+ });
20454
20475
  var reviewDayStatSchema = exports_external.object({
20455
20476
  date: exports_external.string(),
20456
20477
  completedTasks: exports_external.number().int().nonnegative(),
@@ -24468,7 +24489,7 @@ function parseCapture2(input, now) {
24468
24489
 
24469
24490
  // src/meta.ts
24470
24491
  var CLI_NAME = "do";
24471
- var VERSION = "1.87.0";
24492
+ var VERSION = "1.88.0";
24472
24493
  var API_PREFIX = "/api/v1";
24473
24494
  var DEFAULT_API_URL = "http://localhost:3001";
24474
24495
 
@@ -24502,6 +24523,16 @@ class DoClient {
24502
24523
  delete(path) {
24503
24524
  return this.request("DELETE", path, {});
24504
24525
  }
24526
+ async getPage(path, opts = {}) {
24527
+ const res = await this.send("GET", path, opts);
24528
+ if (res.status === 204)
24529
+ return { data: [], nextCursor: null };
24530
+ const text2 = await res.text();
24531
+ const parsed = text2.length > 0 ? safeJson(text2) : undefined;
24532
+ if (!res.ok)
24533
+ throw httpError(res.status, parsed);
24534
+ return normalizePage(parsed);
24535
+ }
24505
24536
  url(path, query) {
24506
24537
  const origin = this.opts.apiUrl.replace(/\/+$/, "");
24507
24538
  const url2 = new URL(`${origin}${API_PREFIX}${path}`);
@@ -24550,6 +24581,16 @@ function unwrapEnvelope(body) {
24550
24581
  }
24551
24582
  return body;
24552
24583
  }
24584
+ function normalizePage(body) {
24585
+ if (typeof body === "object" && body !== null && !Array.isArray(body) && "nextCursor" in body) {
24586
+ const record2 = body;
24587
+ if (Array.isArray(record2.data)) {
24588
+ const nextCursor = typeof record2.nextCursor === "string" ? record2.nextCursor : null;
24589
+ return { data: record2.data, nextCursor };
24590
+ }
24591
+ }
24592
+ return { data: Array.isArray(body) ? body : [], nextCursor: null };
24593
+ }
24553
24594
  function safeJson(text2) {
24554
24595
  try {
24555
24596
  return JSON.parse(text2);
@@ -24964,6 +25005,14 @@ function entityOperations(e) {
24964
25005
  }
24965
25006
 
24966
25007
  // src/registry.ts
25008
+ var PAGINATION_FLAGS = [
25009
+ { name: "limit", type: "string", description: "Max rows to return (1\u2013100)." },
25010
+ {
25011
+ name: "cursor",
25012
+ type: "string",
25013
+ description: "Opaque keyset cursor from a previous page's nextCursor."
25014
+ }
25015
+ ];
24967
25016
  var GLOBAL_FLAGS = [
24968
25017
  { name: "json", type: "boolean", description: "Emit JSON (automatic when stdout is piped)." },
24969
25018
  { name: "quiet", type: "boolean", description: "Suppress human output (errors still report)." },
@@ -25151,7 +25200,8 @@ var COMMAND_SPECS = [
25151
25200
  type: "string",
25152
25201
  description: "Filter to one Status (want|have|doing|done|dropped)."
25153
25202
  },
25154
- { name: "tag", type: "string", description: "Filter to Items carrying this tag." }
25203
+ { name: "tag", type: "string", description: "Filter to Items carrying this tag." },
25204
+ ...PAGINATION_FLAGS
25155
25205
  ],
25156
25206
  scopes: ["collections:read"],
25157
25207
  returns: "CollectionItemView"
@@ -25523,11 +25573,18 @@ function buildManifest() {
25523
25573
  }
25524
25574
  } : {},
25525
25575
  returns: e.returns,
25526
- listFlags: e.listFlags.map((f) => ({
25527
- name: f.name,
25528
- description: f.description,
25529
- required: f.required ?? false
25530
- }))
25576
+ listFlags: [
25577
+ ...e.listFlags.map((f) => ({
25578
+ name: f.name,
25579
+ description: f.description,
25580
+ required: f.required ?? false
25581
+ })),
25582
+ ...PAGINATION_FLAGS.map((f) => ({
25583
+ name: f.name,
25584
+ description: f.description,
25585
+ required: false
25586
+ }))
25587
+ ]
25531
25588
  })),
25532
25589
  exitCodes: {
25533
25590
  success: EXIT.OK,
@@ -25647,17 +25704,35 @@ function renderWhoami(data, mode) {
25647
25704
  `);
25648
25705
  }
25649
25706
  function renderList(data, mode) {
25650
- if (!Array.isArray(data))
25707
+ const page = asPage(data);
25708
+ if (page === undefined)
25651
25709
  return renderRecord(data, mode);
25652
- if (data.length === 0)
25653
- return paint(mode, "dim", "(no records)");
25654
- const lines = data.map((row) => {
25655
- const label = labelOf(row);
25656
- const id = idOf(row);
25657
- return id ? ` ${label} ${paint(mode, "dim", id)}` : ` ${label}`;
25658
- });
25659
- return [`${data.length} record(s):`, ...lines].join(`
25710
+ const { rows, nextCursor } = page;
25711
+ const body = rows.length === 0 ? paint(mode, "dim", "(no records)") : [
25712
+ `${rows.length} record(s):`,
25713
+ ...rows.map((row) => {
25714
+ const label = labelOf(row);
25715
+ const id = idOf(row);
25716
+ return id ? ` ${label} ${paint(mode, "dim", id)}` : ` ${label}`;
25717
+ })
25718
+ ].join(`
25660
25719
  `);
25720
+ if (nextCursor === null)
25721
+ return body;
25722
+ return `${body}
25723
+ ${paint(mode, "dim", `\u2026 more \u2014 rerun with --cursor ${nextCursor}`)}`;
25724
+ }
25725
+ function asPage(data) {
25726
+ if (Array.isArray(data))
25727
+ return { rows: data, nextCursor: null };
25728
+ if (data !== null && typeof data === "object" && "nextCursor" in data) {
25729
+ const record2 = data;
25730
+ if (Array.isArray(record2.data)) {
25731
+ const nextCursor = typeof record2.nextCursor === "string" ? record2.nextCursor : null;
25732
+ return { rows: record2.data, nextCursor };
25733
+ }
25734
+ }
25735
+ return;
25661
25736
  }
25662
25737
  function renderRecord(data, mode) {
25663
25738
  if (data === null || typeof data !== "object")
@@ -25847,7 +25922,8 @@ async function dispatchEntity(entity, rest, flags, requireClient) {
25847
25922
  else if (f.required)
25848
25923
  throw usageError(`\`${entity.name} list\` requires --${f.name}`);
25849
25924
  }
25850
- return { data: await client.get(entity.path, { query }), render: renderList };
25925
+ applyPageFlags(query, flags);
25926
+ return { data: await client.getPage(entity.path, { query }), render: renderList };
25851
25927
  }
25852
25928
  if (op === "get") {
25853
25929
  if (!entity.canGet)
@@ -26015,7 +26091,8 @@ var HANDLERS = {
26015
26091
  status: flagString(flags, "status"),
26016
26092
  tag: flagString(flags, "tag")
26017
26093
  };
26018
- return { data: await requireClient().get("/collection", { query }), render: renderList };
26094
+ applyPageFlags(query, flags);
26095
+ return { data: await requireClient().getPage("/collection", { query }), render: renderList };
26019
26096
  },
26020
26097
  "collection add": async ({ args, flags, requireClient }) => {
26021
26098
  const { title, tags: tags2 } = parseTitleTags(args);
@@ -26229,6 +26306,19 @@ var HANDLERS = {
26229
26306
  render: () => `${CLI_NAME} ${VERSION}`
26230
26307
  })
26231
26308
  };
26309
+ function applyPageFlags(query, flags) {
26310
+ const limit = flagString(flags, "limit");
26311
+ if (limit !== undefined) {
26312
+ const n = Number(limit);
26313
+ if (!Number.isInteger(n) || n <= 0) {
26314
+ throw usageError("--limit must be a positive integer");
26315
+ }
26316
+ query.limit = String(n);
26317
+ }
26318
+ const cursor = flagString(flags, "cursor");
26319
+ if (cursor !== undefined)
26320
+ query.cursor = cursor;
26321
+ }
26232
26322
  async function setModuleVisibility(args, requireClient, on) {
26233
26323
  const key = requireArg(args, 0, "module key");
26234
26324
  if (!isModuleKey(key)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robbeverhelst/do",
3
- "version": "1.87.0",
3
+ "version": "1.88.0",
4
4
  "private": false,
5
5
  "description": "do — the agent-drivable CLI over the public /api/v1 surface",
6
6
  "type": "module",