donebear 0.3.5 → 0.3.6

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.mjs CHANGED
@@ -435,6 +435,8 @@ const TASK_FIELDS = `
435
435
  teamId
436
436
  assigneeId
437
437
  headingId
438
+ repeatRule
439
+ repeatTemplateId
438
440
  `;
439
441
  const TASKS_QUERY = `
440
442
  query DonebearTasks($first: Int!, $after: String, $workspaceId: ID!) {
@@ -641,6 +643,8 @@ const toTaskRecord = (value) => {
641
643
  headingId: typeof row.headingId === "string" ? row.headingId : null,
642
644
  id: row.id,
643
645
  projectId: typeof row.projectId === "string" ? row.projectId : null,
646
+ repeatRule: typeof row.repeatRule === "string" ? row.repeatRule : null,
647
+ repeatTemplateId: typeof row.repeatTemplateId === "string" ? row.repeatTemplateId : null,
644
648
  start: row.start,
645
649
  startBucket: row.startBucket,
646
650
  startDate: toNullableNumber(row.startDate),
@@ -666,6 +670,8 @@ const toTaskRecordFromGraphqlNode = (node) => ({
666
670
  headingId: node.headingId,
667
671
  id: node.id,
668
672
  projectId: node.projectId,
673
+ repeatRule: node.repeatRule,
674
+ repeatTemplateId: node.repeatTemplateId,
669
675
  start: node.start,
670
676
  startBucket: node.startBucket,
671
677
  startDate: parseApiDateOnlyToEpoch(node.startDate),
@@ -1626,14 +1632,24 @@ const getTaskState = (task) => {
1626
1632
  if (task.completedAt !== null) return "done";
1627
1633
  return "open";
1628
1634
  };
1635
+ /**
1636
+ * Determine which view a task belongs to.
1637
+ * Matches the frontend logic in manage-frontend/lib/tasks/task-status.ts
1638
+ */
1629
1639
  const resolveTaskView = (task) => {
1630
- if (task.start === "not_started") return "inbox";
1631
- if (task.start === "someday") return "someday";
1632
- if (task.startDate !== null) {
1633
- if (task.startDate <= dateOnlyEpochFromLocalDate()) return "today";
1634
- return "upcoming";
1635
- }
1636
- return "anytime";
1640
+ if (task.repeatRule !== null && task.repeatTemplateId === null) return null;
1641
+ if (task.archivedAt !== null) return "trash";
1642
+ if (task.completedAt !== null) return "logbook";
1643
+ const { start, startDate, deadlineAt } = task;
1644
+ const today = dateOnlyEpochFromLocalDate();
1645
+ const tomorrow = today + DAY_MS;
1646
+ const hasDeadlineToday = deadlineAt !== null && deadlineAt >= today && deadlineAt < tomorrow;
1647
+ if (start === "not_started") return hasDeadlineToday ? "today" : "inbox";
1648
+ if (start === "someday") return hasDeadlineToday ? "today" : "someday";
1649
+ if (start !== "started") return null;
1650
+ if (startDate === null) return hasDeadlineToday ? "today" : "anytime";
1651
+ if (startDate < tomorrow || hasDeadlineToday) return "today";
1652
+ return "upcoming";
1637
1653
  };
1638
1654
  const formatEpochDate = (epochMs) => formatInstantEpoch(epochMs);
1639
1655
  //#endregion
@@ -4297,7 +4313,9 @@ const VALID_TASK_VIEWS = new Set([
4297
4313
  "anytime",
4298
4314
  "today",
4299
4315
  "upcoming",
4300
- "someday"
4316
+ "someday",
4317
+ "logbook",
4318
+ "trash"
4301
4319
  ]);
4302
4320
  const parseTaskView = (value) => {
4303
4321
  const normalized = value.trim().toLowerCase();
@@ -4338,7 +4356,10 @@ const resolveTaskReference = async (context, options) => {
4338
4356
  throw new Error(`Task prefix "${taskRef}" is ambiguous (${matches.length} matches). Use the full id.`);
4339
4357
  };
4340
4358
  const filterTasks = (tasks, options) => {
4341
- const stateFiltered = options.state === "all" ? tasks : tasks.filter((task) => getTaskState(task) === options.state);
4359
+ let effectiveState = options.state;
4360
+ if (options.view === "logbook") effectiveState = "done";
4361
+ else if (options.view === "trash") effectiveState = "archived";
4362
+ const stateFiltered = effectiveState === "all" ? tasks : tasks.filter((task) => getTaskState(task) === effectiveState);
4342
4363
  const viewFiltered = options.view ? stateFiltered.filter((task) => resolveTaskView(task) === options.view) : stateFiltered;
4343
4364
  if (!options.search) return viewFiltered;
4344
4365
  const query = options.search.trim().toLowerCase();
@@ -4795,7 +4816,7 @@ Agent tip: run "donebear spec task add" for full option reference
4795
4816
  }, workspaceOverride);
4796
4817
  });
4797
4818
  });
4798
- task.command("list").alias("ls").description("List tasks").option("-w, --workspace <workspace>", "Workspace id, slug, or exact name").option("-s, --state <state>", "open|done|archived|all", "open").option("-n, --limit <count>", "Maximum number of tasks", (value) => parsePositiveInteger(value, "Limit"), DEFAULT_TASK_LIST_LIMIT).option("-q, --search <query>", "Filter by title or notes").option("-v, --view <view>", "Filter by view bucket (inbox|anytime|today|upcoming|someday)").addHelpText("after", `
4819
+ task.command("list").alias("ls").description("List tasks").option("-w, --workspace <workspace>", "Workspace id, slug, or exact name").option("-s, --state <state>", "open|done|archived|all", "open").option("-n, --limit <count>", "Maximum number of tasks", (value) => parsePositiveInteger(value, "Limit"), DEFAULT_TASK_LIST_LIMIT).option("-q, --search <query>", "Filter by title or notes").option("-v, --view <view>", "Filter by view (inbox|anytime|today|upcoming|someday|logbook|trash)").addHelpText("after", `
4799
4820
  Examples:
4800
4821
  donebear task list --json
4801
4822
  donebear task list --state done --json
@@ -4803,7 +4824,7 @@ Examples:
4803
4824
  donebear task list --search "login" --limit 50 --json
4804
4825
 
4805
4826
  States: open (default) | done | archived | all
4806
- Views: inbox | anytime | today | upcoming | someday
4827
+ Views: inbox | anytime | today | upcoming | someday | logbook | trash
4807
4828
  `).action(async (options, command) => {
4808
4829
  const context = contextFromCommand(command);
4809
4830
  await runWithErrorHandling(context, async () => {
@@ -6191,7 +6212,7 @@ Examples:
6191
6212
  //#endregion
6192
6213
  //#region src/commands/today.ts
6193
6214
  const DEFAULT_TODAY_LIMIT = 20;
6194
- const filterToday = (tasks) => tasks.filter((task) => task.todayIndexReferenceDate !== null && task.completedAt === null && task.archivedAt === null);
6215
+ const filterToday = (tasks) => tasks.filter((task) => resolveTaskView(task) === "today");
6195
6216
  const runToday = async (context, options, workspaceOverride) => {
6196
6217
  const commandContext = await resolveCommandContext(context);
6197
6218
  const scope = await resolveWorkspaceScope(context, {