things-api 0.10.0 → 0.12.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 +50 -13
- package/dist/audit/schema.d.ts +7 -0
- package/dist/audit/schema.js.map +1 -1
- package/dist/cli/clock.d.ts +8 -0
- package/dist/cli/clock.js +24 -0
- package/dist/cli/clock.js.map +1 -0
- package/dist/cli/commands/area.d.ts +18 -11
- package/dist/cli/commands/area.js +61 -74
- package/dist/cli/commands/area.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +1 -2
- package/dist/cli/commands/doctor.js +11 -1
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/install-skill.d.ts +60 -0
- package/dist/cli/commands/install-skill.js +256 -0
- package/dist/cli/commands/install-skill.js.map +1 -0
- package/dist/cli/commands/mcp.js +9 -0
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/project.d.ts +1 -0
- package/dist/cli/commands/project.js +27 -34
- package/dist/cli/commands/project.js.map +1 -1
- package/dist/cli/commands/reads.d.ts +15 -2
- package/dist/cli/commands/reads.js +144 -44
- package/dist/cli/commands/reads.js.map +1 -1
- package/dist/cli/commands/setup.js +7 -2
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/show.js +38 -14
- package/dist/cli/commands/show.js.map +1 -1
- package/dist/cli/commands/todo.js +15 -9
- package/dist/cli/commands/todo.js.map +1 -1
- package/dist/cli/commands/writes.js +797 -174
- package/dist/cli/commands/writes.js.map +1 -1
- package/dist/cli/did-you-mean.d.ts +14 -3
- package/dist/cli/did-you-mean.js +26 -3
- package/dist/cli/did-you-mean.js.map +1 -1
- package/dist/cli/glyphs.d.ts +32 -2
- package/dist/cli/glyphs.js +83 -12
- package/dist/cli/glyphs.js.map +1 -1
- package/dist/cli/help.js +121 -16
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/main.js +33 -2
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/move-hint.d.ts +46 -0
- package/dist/cli/move-hint.js +196 -0
- package/dist/cli/move-hint.js.map +1 -0
- package/dist/cli/period.d.ts +2 -8
- package/dist/cli/period.js +44 -30
- package/dist/cli/period.js.map +1 -1
- package/dist/cli/read-driver.d.ts +43 -5
- package/dist/cli/read-driver.js +91 -15
- package/dist/cli/read-driver.js.map +1 -1
- package/dist/cli/render.d.ts +19 -8
- package/dist/cli/render.js +70 -27
- package/dist/cli/render.js.map +1 -1
- package/dist/cli/resolve-invocation.d.ts +2 -2
- package/dist/cli/resolve-invocation.js +3 -3
- package/dist/cli/resolve-invocation.js.map +1 -1
- package/dist/cli/skill-check.d.ts +27 -0
- package/dist/cli/skill-check.js +99 -0
- package/dist/cli/skill-check.js.map +1 -0
- package/dist/cli/skill.d.ts +70 -0
- package/dist/cli/skill.js +152 -0
- package/dist/cli/skill.js.map +1 -0
- package/dist/cli/tag-filters.d.ts +6 -2
- package/dist/cli/tag-filters.js +8 -6
- package/dist/cli/tag-filters.js.map +1 -1
- package/dist/cli/verb-hint.js +28 -3
- package/dist/cli/verb-hint.js.map +1 -1
- package/dist/cli/version.d.ts +4 -0
- package/dist/cli/version.js +18 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/client.d.ts +171 -27
- package/dist/client.js +279 -40
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +66 -2
- package/dist/config.js +120 -12
- package/dist/config.js.map +1 -1
- package/dist/contracts.d.ts +186 -28
- package/dist/contracts.js +22 -1
- package/dist/contracts.js.map +1 -1
- package/dist/diagnose.d.ts +34 -2
- package/dist/diagnose.js +36 -1
- package/dist/diagnose.js.map +1 -1
- package/dist/index.d.ts +25 -9
- package/dist/index.js +22 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +9 -0
- package/dist/mcp/server.js +1157 -684
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/clock.d.ts +61 -0
- package/dist/model/clock.js +71 -0
- package/dist/model/clock.js.map +1 -0
- package/dist/model/dates.d.ts +26 -3
- package/dist/model/dates.js +84 -3
- package/dist/model/dates.js.map +1 -1
- package/dist/model/entities.d.ts +60 -3
- package/dist/model/entities.js.map +1 -1
- package/dist/model/mappers.d.ts +4 -2
- package/dist/model/mappers.js +66 -9
- package/dist/model/mappers.js.map +1 -1
- package/dist/model/recurrence.d.ts +8 -1
- package/dist/model/recurrence.js.map +1 -1
- package/dist/read/area-filter.d.ts +76 -0
- package/dist/read/area-filter.js +59 -0
- package/dist/read/area-filter.js.map +1 -0
- package/dist/read/area-view.d.ts +12 -12
- package/dist/read/area-view.js +58 -34
- package/dist/read/area-view.js.map +1 -1
- package/dist/read/detail.d.ts +1 -1
- package/dist/read/detail.js +26 -12
- package/dist/read/detail.js.map +1 -1
- package/dist/read/log-boundary.d.ts +1 -1
- package/dist/read/log-boundary.js +13 -3
- package/dist/read/log-boundary.js.map +1 -1
- package/dist/read/predicates.d.ts +18 -0
- package/dist/read/predicates.js +19 -0
- package/dist/read/predicates.js.map +1 -1
- package/dist/read/project-view.d.ts +32 -16
- package/dist/read/project-view.js +80 -45
- package/dist/read/project-view.js.map +1 -1
- package/dist/read/pseudo-area.d.ts +29 -0
- package/dist/read/pseudo-area.js +27 -0
- package/dist/read/pseudo-area.js.map +1 -0
- package/dist/read/queries.d.ts +108 -19
- package/dist/read/queries.js +212 -35
- package/dist/read/queries.js.map +1 -1
- package/dist/read/scope.d.ts +126 -0
- package/dist/read/scope.js +162 -0
- package/dist/read/scope.js.map +1 -0
- package/dist/read/search-rank.d.ts +2 -5
- package/dist/read/shape.d.ts +162 -0
- package/dist/read/shape.js +686 -0
- package/dist/read/shape.js.map +1 -0
- package/dist/read/show-target.d.ts +9 -1
- package/dist/read/show-target.js +45 -4
- package/dist/read/show-target.js.map +1 -1
- package/dist/read/snapshot.d.ts +1 -1
- package/dist/read/snapshot.js +9 -2
- package/dist/read/snapshot.js.map +1 -1
- package/dist/read/stage.d.ts +199 -0
- package/dist/read/stage.js +125 -0
- package/dist/read/stage.js.map +1 -0
- package/dist/read/truncation.d.ts +8 -6
- package/dist/read/truncation.js +35 -10
- package/dist/read/truncation.js.map +1 -1
- package/dist/read/views.d.ts +61 -20
- package/dist/read/views.js +240 -82
- package/dist/read/views.js.map +1 -1
- package/dist/surface-copy.d.ts +9 -0
- package/dist/surface-copy.js +9 -0
- package/dist/surface-copy.js.map +1 -1
- package/dist/write/accessibility-probe.d.ts +1 -1
- package/dist/write/accessibility-probe.js +8 -0
- package/dist/write/accessibility-probe.js.map +1 -1
- package/dist/write/automation-probe.d.ts +1 -1
- package/dist/write/automation-probe.js +8 -0
- package/dist/write/automation-probe.js.map +1 -1
- package/dist/write/batch.d.ts +49 -10
- package/dist/write/batch.js +423 -70
- package/dist/write/batch.js.map +1 -1
- package/dist/write/commands.d.ts +1 -1
- package/dist/write/commands.js +316 -66
- package/dist/write/commands.js.map +1 -1
- package/dist/write/guards.d.ts +1 -1
- package/dist/write/guards.js +94 -10
- package/dist/write/guards.js.map +1 -1
- package/dist/write/heading.d.ts +10 -1
- package/dist/write/heading.js +35 -5
- package/dist/write/heading.js.map +1 -1
- package/dist/write/make-repeating-project.d.ts +2 -2
- package/dist/write/make-repeating-project.js +9 -9
- package/dist/write/make-repeating-project.js.map +1 -1
- package/dist/write/move.d.ts +130 -0
- package/dist/write/move.js +1533 -0
- package/dist/write/move.js.map +1 -0
- package/dist/write/operations.d.ts +105 -19
- package/dist/write/operations.js +56 -7
- package/dist/write/operations.js.map +1 -1
- package/dist/write/opid.d.ts +31 -0
- package/dist/write/opid.js +30 -0
- package/dist/write/opid.js.map +1 -0
- package/dist/write/pipeline.d.ts +122 -3
- package/dist/write/pipeline.js +309 -52
- package/dist/write/pipeline.js.map +1 -1
- package/dist/write/planner.js +8 -1
- package/dist/write/planner.js.map +1 -1
- package/dist/write/pre-state.d.ts +197 -6
- package/dist/write/pre-state.js +427 -20
- package/dist/write/pre-state.js.map +1 -1
- package/dist/write/recurrence-rule-blob.d.ts +65 -0
- package/dist/write/recurrence-rule-blob.js +150 -0
- package/dist/write/recurrence-rule-blob.js.map +1 -0
- package/dist/write/reorder.d.ts +23 -3
- package/dist/write/reorder.js +1871 -85
- package/dist/write/reorder.js.map +1 -1
- package/dist/write/reversibility.js +19 -7
- package/dist/write/reversibility.js.map +1 -1
- package/dist/write/scope-guard.d.ts +31 -0
- package/dist/write/scope-guard.js +162 -0
- package/dist/write/scope-guard.js.map +1 -0
- package/dist/write/undo.js +120 -13
- package/dist/write/undo.js.map +1 -1
- package/dist/write/vectors/applescript.js +16 -7
- package/dist/write/vectors/applescript.js.map +1 -1
- package/dist/write/vectors/registry.d.ts +5 -7
- package/dist/write/vectors/registry.js +49 -2
- package/dist/write/vectors/registry.js.map +1 -1
- package/dist/write/vectors/shortcuts.js +1 -1
- package/dist/write/vectors/shortcuts.js.map +1 -1
- package/dist/write/vectors/simulator.d.ts +44 -0
- package/dist/write/vectors/simulator.js +1192 -0
- package/dist/write/vectors/simulator.js.map +1 -0
- package/dist/write/vectors/types.d.ts +46 -0
- package/dist/write/vectors/ui-certification.d.ts +10 -4
- package/dist/write/vectors/ui-certification.js +43 -10
- package/dist/write/vectors/ui-certification.js.map +1 -1
- package/dist/write/vectors/ui-drag.d.ts +21 -1
- package/dist/write/vectors/ui-drag.js +138 -27
- package/dist/write/vectors/ui-drag.js.map +1 -1
- package/dist/write/vectors/ui-recipes.d.ts +34 -1
- package/dist/write/vectors/ui-recipes.js +217 -6
- package/dist/write/vectors/ui-recipes.js.map +1 -1
- package/dist/write/vectors/ui.d.ts +40 -1
- package/dist/write/vectors/ui.js +196 -39
- package/dist/write/vectors/ui.js.map +1 -1
- package/dist/write/verify/delta.d.ts +127 -2
- package/dist/write/verify/delta.js +255 -16
- package/dist/write/verify/delta.js.map +1 -1
- package/dist/write/verify/poller.d.ts +7 -1
- package/dist/write/verify/poller.js +20 -1
- package/dist/write/verify/poller.js.map +1 -1
- package/package.json +24 -3
- package/schema/envelope.schema.json +383 -0
- package/skills/things-cli/SKILL.md +70 -0
- package/skills/things-cli/references/banner.md +35 -0
- package/skills/things-cli/references/contracts.md +62 -0
- package/skills/things-cli/references/errors.md +49 -0
- package/skills/things-cli/references/gui.md +11 -0
- package/skills/things-cli/references/model.md +60 -0
- package/skills/things-cli/references/ordering.md +71 -0
package/dist/read/area-view.js
CHANGED
|
@@ -3,6 +3,7 @@ import { mapProject, mapTodo } from "../model/mappers.js";
|
|
|
3
3
|
import { fetchTagsForTasks, fetchTaskRows, makeRefResolver, resolveAreaUuid } from "./queries.js";
|
|
4
4
|
import { logBoundary, markLogged } from "./log-boundary.js";
|
|
5
5
|
import { OVERDUE } from "./predicates.js";
|
|
6
|
+
import { isLooseRef } from "./pseudo-area.js";
|
|
6
7
|
import { areaTags } from "./tags.js";
|
|
7
8
|
import { tagFilter } from "./views.js";
|
|
8
9
|
// The area card splits its open projects into three display buckets by their
|
|
@@ -19,24 +20,56 @@ export const isScheduledProjectRow = (p, todayIso) => p.status === "open" && p.s
|
|
|
19
20
|
/** An active project row — everything that is neither someday nor future-scheduled. */
|
|
20
21
|
export const isActiveProjectRow = (p, todayIso) => !isSomedayProjectRow(p) && !isScheduledProjectRow(p, todayIso);
|
|
21
22
|
/** Resolves by uuid or unique (case-insensitive) title; throws like the ref resolvers. */
|
|
22
|
-
export function areaView(db, ref, now, filter = {}) {
|
|
23
|
+
export function areaView(db, ref, now, filter = {}, zone) {
|
|
23
24
|
const overdue = filter.overdue === true;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
25
|
+
// The reserved `loose` ref addresses the NULL area (area-less items) as a
|
|
26
|
+
// pseudo-area: `area === null`, and the per-kind area predicates swap to the
|
|
27
|
+
// NULL-area membership rule (projects with no area; direct to-dos with no area
|
|
28
|
+
// AND no project AND not in the Inbox). Every other filter/section behaves
|
|
29
|
+
// identically, so the two paths differ ONLY in the area clause + the synthetic
|
|
30
|
+
// null area object.
|
|
31
|
+
const loose = isLooseRef(ref);
|
|
32
|
+
let area;
|
|
33
|
+
// The per-kind area membership: PROJECTS filter on the area FK; DIRECT to-dos
|
|
34
|
+
// additionally exclude project-nested rows and Inbox captures (start=0) — a
|
|
35
|
+
// real area's `t.area = ?` gets those exclusions for free (an inbox/nested row
|
|
36
|
+
// carries no area FK), so they only appear in the NULL-area branch.
|
|
37
|
+
let projectAreaSql;
|
|
38
|
+
let projectAreaBinds;
|
|
39
|
+
let todoAreaSql;
|
|
40
|
+
let todoAreaBinds;
|
|
41
|
+
if (loose) {
|
|
42
|
+
area = null;
|
|
43
|
+
projectAreaSql = "t.area IS NULL";
|
|
44
|
+
projectAreaBinds = [];
|
|
45
|
+
todoAreaSql = "t.area IS NULL AND t.project IS NULL AND t.start != 0";
|
|
46
|
+
todoAreaBinds = [];
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const uuid = resolveAreaUuid(db, ref);
|
|
50
|
+
const row = db
|
|
51
|
+
.prepare(`SELECT uuid, title, visible, "index" FROM TMArea WHERE uuid = ?`)
|
|
52
|
+
.get(uuid);
|
|
53
|
+
if (row === undefined)
|
|
54
|
+
throw new Error(`no area with uuid ${uuid}`);
|
|
55
|
+
area = {
|
|
56
|
+
uuid: row.uuid,
|
|
57
|
+
title: row.title ?? "",
|
|
58
|
+
visible: row.visible !== 0,
|
|
59
|
+
// Area tags by NAME only (tag uuids are internal).
|
|
60
|
+
tags: areaTags(db, uuid).map((t) => ({ title: t.title })),
|
|
61
|
+
};
|
|
62
|
+
projectAreaSql = "t.area = ?";
|
|
63
|
+
projectAreaBinds = [uuid];
|
|
64
|
+
todoAreaSql = "t.area = ?";
|
|
65
|
+
todoAreaBinds = [uuid];
|
|
66
|
+
}
|
|
37
67
|
const refs = makeRefResolver(db);
|
|
38
68
|
const tagsOf = (rows) => fetchTagsForTasks(db, rows.map((r) => r.uuid));
|
|
39
|
-
const boundary = logBoundary(db, now);
|
|
69
|
+
const boundary = logBoundary(db, now, zone);
|
|
70
|
+
// The view's injected clock — gates `todaySection` to Today members in the
|
|
71
|
+
// mapper AND drives the scheduled/overdue bucketing below.
|
|
72
|
+
const packedToday = encodePackedDate(localToday(now, zone));
|
|
40
73
|
// OWN-DEADLINE UNIFORM: `--overdue` filters BOTH displayed row kinds by each
|
|
41
74
|
// row's OWN deadline (open, strictly before today) via the shared OVERDUE
|
|
42
75
|
// predicate — the area's child PROJECTS by the project's own deadline AND the
|
|
@@ -44,7 +77,7 @@ export function areaView(db, ref, now, filter = {}) {
|
|
|
44
77
|
// overdue to-do inside a non-overdue project never surfaces here — that is
|
|
45
78
|
// `project show --overdue`). Sections with no surviving rows collapse.
|
|
46
79
|
const overdueSql = overdue ? ` AND ${OVERDUE}` : "";
|
|
47
|
-
const overdueBinds = overdue ? [encodePackedDate(localToday(now))] : [];
|
|
80
|
+
const overdueBinds = overdue ? [encodePackedDate(localToday(now, zone))] : [];
|
|
48
81
|
// Tag scope (§9a): BOTH displayed row kinds — the child PROJECTS and the
|
|
49
82
|
// loose to-dos — are filtered by a tag carried DIRECTLY on the row (the
|
|
50
83
|
// container semantics). The area's own tags are inherited by every row it
|
|
@@ -58,39 +91,31 @@ export function areaView(db, ref, now, filter = {}) {
|
|
|
58
91
|
// Open projects PLUS closed ones the log-move sweep has not passed — the
|
|
59
92
|
// GUI keeps those checked in place (completion ≠ logged). Under --overdue the
|
|
60
93
|
// OVERDUE predicate's own `status = 0` narrows this to open overdue projects.
|
|
61
|
-
const projectRows = fetchTaskRows(db, `t.type = 1 AND
|
|
62
|
-
AND (t.status = 0 OR t.stopDate > ?)${overdueSql}${tf.sql} ORDER BY t."index" ASC`, [
|
|
94
|
+
const projectRows = fetchTaskRows(db, `t.type = 1 AND ${projectAreaSql} AND t.trashed = 0
|
|
95
|
+
AND (t.status = 0 OR t.stopDate > ?)${overdueSql}${tf.sql} ORDER BY t."index" ASC`, [...projectAreaBinds, boundary.getTime() / 1000, ...overdueBinds, ...tf.binds]);
|
|
63
96
|
const projectTags = tagsOf(projectRows);
|
|
64
|
-
const projects = markLogged(projectRows.map((r) => mapProject(r, refs, projectTags.get(r.uuid) ?? [])), boundary);
|
|
65
|
-
const todoRows = fetchTaskRows(db, `t.type = 0 AND t.
|
|
97
|
+
const projects = markLogged(projectRows.map((r) => mapProject(r, refs, projectTags.get(r.uuid) ?? [], packedToday)), boundary);
|
|
98
|
+
const todoRows = fetchTaskRows(db, `t.type = 0 AND t.trashed = 0 AND ${todoAreaSql}${overdueSql}${tf.sql} ORDER BY t."index" ASC`, [...todoAreaBinds, ...overdueBinds, ...tf.binds]);
|
|
66
99
|
const todoTags = tagsOf(todoRows);
|
|
67
100
|
const todos = todoRows.map((r) => ({
|
|
68
101
|
row: r,
|
|
69
|
-
todo: mapTodo(r, refs, todoTags.get(r.uuid) ?? []),
|
|
102
|
+
todo: mapTodo(r, refs, todoTags.get(r.uuid) ?? [], packedToday),
|
|
70
103
|
}));
|
|
71
104
|
markLogged(todos.map((t) => t.todo), boundary);
|
|
72
|
-
const packedToday = encodePackedDate(localToday(now));
|
|
73
105
|
const active = [];
|
|
74
106
|
const scheduledRows = [];
|
|
75
107
|
const repeating = [];
|
|
76
108
|
const someday = [];
|
|
77
|
-
const logged = [];
|
|
78
|
-
const trashed = [];
|
|
79
109
|
for (const { row: todoRow, todo } of todos) {
|
|
80
|
-
if (todoRow.trashed === 1) {
|
|
81
|
-
trashed.push(todo);
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
110
|
if (todo.repeating.isTemplate) {
|
|
85
111
|
repeating.push(todo);
|
|
86
112
|
continue;
|
|
87
113
|
}
|
|
88
114
|
if (todoRow.status !== 0) {
|
|
89
115
|
// Completion ≠ logged: closed-but-unswept items stay checked in the
|
|
90
|
-
// active block, like the GUI.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
else
|
|
116
|
+
// active block, like the GUI. Logged rows (past the log boundary) are
|
|
117
|
+
// NOT a view section — they live in `things logbook --area <ref>`.
|
|
118
|
+
if (!todo.logged)
|
|
94
119
|
active.push(todo);
|
|
95
120
|
continue;
|
|
96
121
|
}
|
|
@@ -108,7 +133,6 @@ export function areaView(db, ref, now, filter = {}) {
|
|
|
108
133
|
}
|
|
109
134
|
active.push(todo);
|
|
110
135
|
}
|
|
111
|
-
logged.sort((a, b) => (b.stopped?.getTime() ?? 0) - (a.stopped?.getTime() ?? 0));
|
|
112
136
|
const scheduled = [];
|
|
113
137
|
// Within a day the UI sorts by todayIndex ASC (Upcoming drag order).
|
|
114
138
|
for (const { date, todo } of scheduledRows.toSorted((a, b) => a.date.localeCompare(b.date) || a.ti - b.ti)) {
|
|
@@ -118,6 +142,6 @@ export function areaView(db, ref, now, filter = {}) {
|
|
|
118
142
|
else
|
|
119
143
|
scheduled.push({ date, items: [todo] });
|
|
120
144
|
}
|
|
121
|
-
return { area, active, projects,
|
|
145
|
+
return { area, active, projects, scheduled, someday, repeating };
|
|
122
146
|
}
|
|
123
147
|
//# sourceMappingURL=area-view.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"area-view.js","sourceRoot":"","sources":["../../src/read/area-view.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"area-view.js","sourceRoot":"","sources":["../../src/read/area-view.ts"],"names":[],"mappings":"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"}
|
package/dist/read/detail.d.ts
CHANGED
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { DatabaseSync } from "node:sqlite";
|
|
6
6
|
import type { AnyTask, ChecklistItem } from "../model/entities.ts";
|
|
7
|
-
export declare function byUuid(db: DatabaseSync, uuid: string): AnyTask | null;
|
|
7
|
+
export declare function byUuid(db: DatabaseSync, uuid: string, now?: Date, zone?: string): AnyTask | null;
|
|
8
8
|
export declare function checklistFor(db: DatabaseSync, taskUuid: string): ChecklistItem[];
|
package/dist/read/detail.js
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
import { mapChecklistItem, mapHeading, mapProject, mapTodo, } from "../model/mappers.js";
|
|
2
2
|
import { decodeRecurrenceRule } from "../model/recurrence.js";
|
|
3
|
-
import {
|
|
3
|
+
import { encodePackedDate, localToday } from "../model/dates.js";
|
|
4
|
+
import { fetchChecklistRows, fetchTagsForTasks, fetchTaskByUuid, latestInstanceUuid, makeHeadingProjectResolver, makeRefResolver, } from "./queries.js";
|
|
4
5
|
import { logBoundary, markLogged } from "./log-boundary.js";
|
|
5
6
|
import { inheritedTagsFor } from "./tags.js";
|
|
6
|
-
|
|
7
|
+
// `now`/`zone` supply the evaluation clock used to gate `todaySection` to
|
|
8
|
+
// Today members (see mappers.mapTodaySection). They default to the host clock —
|
|
9
|
+
// matching this module's existing logBoundary default; the client facade passes
|
|
10
|
+
// the injected clock so a pinned-clock `show` reads under the consumer's Today.
|
|
11
|
+
export function byUuid(db, uuid, now = new Date(), zone) {
|
|
7
12
|
const row = fetchTaskByUuid(db, uuid);
|
|
8
13
|
if (!row)
|
|
9
14
|
return null;
|
|
10
|
-
return materializeOne(db, row);
|
|
15
|
+
return materializeOne(db, row, encodePackedDate(localToday(now, zone)));
|
|
11
16
|
}
|
|
12
|
-
function materializeOne(db, row) {
|
|
17
|
+
function materializeOne(db, row, packedToday) {
|
|
13
18
|
const refs = makeRefResolver(db);
|
|
14
19
|
if (row.type === 2)
|
|
15
20
|
return mapHeading(row, refs);
|
|
16
21
|
const tags = fetchTagsForTasks(db, [row.uuid]).get(row.uuid) ?? [];
|
|
17
|
-
const entity = row.type === 1
|
|
22
|
+
const entity = row.type === 1
|
|
23
|
+
? mapProject(row, refs, tags, packedToday)
|
|
24
|
+
: mapTodo(row, refs, tags, packedToday);
|
|
18
25
|
markLogged([entity], logBoundary(db));
|
|
19
26
|
entity.inheritedTags = inheritedTagsFor(db, row);
|
|
20
27
|
if (entity.type === "to-do") {
|
|
@@ -27,14 +34,21 @@ function materializeOne(db, row) {
|
|
|
27
34
|
entity.headingProject = p;
|
|
28
35
|
}
|
|
29
36
|
}
|
|
30
|
-
if (entity.repeating.isTemplate
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
if (entity.repeating.isTemplate) {
|
|
38
|
+
if (row.rt1_recurrenceRule !== null) {
|
|
39
|
+
try {
|
|
40
|
+
entity.repeating.rule = decodeRecurrenceRule(row.rt1_recurrenceRule);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// Unknown rule schema (future Things build) — surface the template
|
|
44
|
+
// without a decoded rule rather than failing the whole read.
|
|
45
|
+
}
|
|
37
46
|
}
|
|
47
|
+
// The GUI "Show Latest" pick (SL1) — detail-only; the shaper emits it NESTED
|
|
48
|
+
// inside the wire `repeating` object. Omitted when the template has none.
|
|
49
|
+
const latest = latestInstanceUuid(db, row.uuid);
|
|
50
|
+
if (latest !== null)
|
|
51
|
+
entity.repeating.latestInstance = latest;
|
|
38
52
|
}
|
|
39
53
|
return entity;
|
|
40
54
|
}
|
package/dist/read/detail.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detail.js","sourceRoot":"","sources":["../../src/read/detail.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,OAAO,GAER,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,UAAU,MAAM,
|
|
1
|
+
{"version":3,"file":"detail.js","sourceRoot":"","sources":["../../src/read/detail.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* FORWARD past the interval's own edge.
|
|
21
21
|
*/
|
|
22
22
|
import type { DatabaseSync } from "node:sqlite";
|
|
23
|
-
export declare function logBoundary(db: DatabaseSync, now?: Date): Date;
|
|
23
|
+
export declare function logBoundary(db: DatabaseSync, now?: Date, zone?: string): Date;
|
|
24
24
|
/** Stamp `logged` on mapped entities (closed AND at/before the boundary). */
|
|
25
25
|
export declare function markLogged<T extends {
|
|
26
26
|
status: string;
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
import { dayBoundInstant, localToday } from "../model/dates.js";
|
|
2
|
+
// `zone` (optional IANA zone) is threaded so the daily/weekly/monthly sweep
|
|
3
|
+
// edge is the CONSUMER'S local midnight, not the host's — byte-identical to a
|
|
4
|
+
// bare `new Date(now); setHours(0,…)` when absent. logInterval=0 (immediately,
|
|
5
|
+
// the golden default) is zone-independent (the boundary is `now`).
|
|
6
|
+
export function logBoundary(db, now = new Date(), zone) {
|
|
2
7
|
const row = db.prepare("SELECT logInterval, manualLogDate FROM TMSettings").get();
|
|
3
8
|
const manual = row?.manualLogDate != null ? new Date(row.manualLogDate * 1000) : null;
|
|
4
|
-
const startOfDay =
|
|
5
|
-
|
|
9
|
+
const startOfDay = zone === undefined
|
|
10
|
+
? (() => {
|
|
11
|
+
const d = new Date(now);
|
|
12
|
+
d.setHours(0, 0, 0, 0);
|
|
13
|
+
return d;
|
|
14
|
+
})()
|
|
15
|
+
: dayBoundInstant(localToday(now, zone), "start", zone);
|
|
6
16
|
let auto;
|
|
7
17
|
switch (row?.logInterval ?? 0) {
|
|
8
18
|
case 0:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-boundary.js","sourceRoot":"","sources":["../../src/read/log-boundary.ts"],"names":[],"mappings":"AAuBA,MAAM,UAAU,WAAW,CAAC,EAAgB,EAAE,GAAG,GAAG,IAAI,IAAI,EAAE;
|
|
1
|
+
{"version":3,"file":"log-boundary.js","sourceRoot":"","sources":["../../src/read/log-boundary.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEhE,4EAA4E;AAC5E,8EAA8E;AAC9E,+EAA+E;AAC/E,mEAAmE;AACnE,MAAM,UAAU,WAAW,CAAC,EAAgB,EAAE,GAAG,GAAG,IAAI,IAAI,EAAE,EAAE,IAAa;IAC3E,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,mDAAmD,CAAC,CAAC,GAAG,EAElE,CAAC;IACd,MAAM,MAAM,GAAG,GAAG,EAAE,aAAa,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACtF,MAAM,UAAU,GACd,IAAI,KAAK,SAAS;QAChB,CAAC,CAAC,CAAC,GAAS,EAAE;YACV,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;YACxB,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACvB,OAAO,CAAC,CAAC;QACX,CAAC,CAAC,EAAE;QACN,CAAC,CAAC,eAAe,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC5D,IAAI,IAAU,CAAC;IACf,QAAQ,GAAG,EAAE,WAAW,IAAI,CAAC,EAAE,CAAC;QAC9B,KAAK,CAAC;YACJ,IAAI,GAAG,GAAG,CAAC;YACX,MAAM;QACR,KAAK,CAAC;YACJ,IAAI,GAAG,UAAU,CAAC;YAClB,MAAM;QACR,KAAK,CAAC,CAAC,CAAC,CAAC;YACP,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC;YAC/B,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;YACpC,IAAI,GAAG,CAAC,CAAC;YACT,MAAM;QACR,CAAC;QACD,KAAK,CAAC,CAAC,CAAC,CAAC;YACP,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC;YAC/B,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACb,IAAI,GAAG,CAAC,CAAC;YACT,MAAM;QACR,CAAC;QACD;YACE,IAAI,GAAG,MAAM,IAAI,GAAG,CAAC;IACzB,CAAC;IACD,OAAO,MAAM,KAAK,IAAI,IAAI,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1D,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,UAAU,CACxB,KAAU,EACV,QAAc;IAEd,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,QAAQ,CAAC;IAC5F,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -34,6 +34,24 @@ export declare const OPEN_OR_UNSWEPT = "t.type IN (0, 1) AND t.trashed = 0 AND (
|
|
|
34
34
|
export declare const OVERDUE = "t.deadline IS NOT NULL AND t.deadline < ? AND t.status = 0";
|
|
35
35
|
/** An item's own anytime membership: unscheduled-active, or dated <= today. */
|
|
36
36
|
export declare const ANYTIME_SELF: (col: string) => string;
|
|
37
|
+
/**
|
|
38
|
+
* The Today DEADLINE-PULL arm (BANNER1 / BANNER1b, docs/lab/banner1-research.md):
|
|
39
|
+
* an UNDATED row (startDate NULL) that a due/overdue, un-dismissed deadline pulls
|
|
40
|
+
* into Today — even from the Inbox or Someday, while its raw `start` still reads
|
|
41
|
+
* 0/2. This is the EXACT second arm {@link todayView} uses; it is written ONCE
|
|
42
|
+
* here so the three GUI-faithful memberships that turn on it can never drift from
|
|
43
|
+
* the pull the Today view claims (BANNER1 law L-A):
|
|
44
|
+
* - `todayView` INCLUDES it (a deadline pulls the row into Today);
|
|
45
|
+
* - `anytimeView` INCLUDES it (Anytime ⊇ Today's to-dos — the pull re-files the
|
|
46
|
+
* row into Anytime, BANNER1b);
|
|
47
|
+
* - `somedayView` / `inboxView` EXCLUDE it (the GUI removes a pulled row from
|
|
48
|
+
* Someday/Inbox even before it materializes, BANNER1 Q1b).
|
|
49
|
+
* The `startDate IS NULL` clause scopes it to UNMATERIALIZED pulls; the
|
|
50
|
+
* suppression guard drops a dismissed nag (supp == deadline) and lets a re-armed
|
|
51
|
+
* one (supp < deadline) through (oddities §8e). ONE bind: today as a packed-date
|
|
52
|
+
* int (encodePackedDate(localToday(now))), the same injected clock every view uses.
|
|
53
|
+
*/
|
|
54
|
+
export declare const DEADLINE_PULLED = "(t.deadline IS NOT NULL AND t.deadline <= ? AND t.startDate IS NULL\n AND (t.deadlineSuppressionDate IS NULL OR t.deadlineSuppressionDate < t.deadline))";
|
|
37
55
|
/**
|
|
38
56
|
* The item's effective project: its own link, or its heading's project for
|
|
39
57
|
* headed children (heading rows carry the project link).
|
package/dist/read/predicates.js
CHANGED
|
@@ -45,6 +45,25 @@ export const OVERDUE = `t.deadline IS NOT NULL AND t.deadline < ? AND t.status =
|
|
|
45
45
|
/** An item's own anytime membership: unscheduled-active, or dated <= today. */
|
|
46
46
|
export const ANYTIME_SELF = (col) => `((${col}.start = 1 AND (${col}.startDate IS NULL OR ${col}.startDate <= ?))
|
|
47
47
|
OR (${col}.start = 2 AND ${col}.startDate IS NOT NULL AND ${col}.startDate <= ?))`;
|
|
48
|
+
/**
|
|
49
|
+
* The Today DEADLINE-PULL arm (BANNER1 / BANNER1b, docs/lab/banner1-research.md):
|
|
50
|
+
* an UNDATED row (startDate NULL) that a due/overdue, un-dismissed deadline pulls
|
|
51
|
+
* into Today — even from the Inbox or Someday, while its raw `start` still reads
|
|
52
|
+
* 0/2. This is the EXACT second arm {@link todayView} uses; it is written ONCE
|
|
53
|
+
* here so the three GUI-faithful memberships that turn on it can never drift from
|
|
54
|
+
* the pull the Today view claims (BANNER1 law L-A):
|
|
55
|
+
* - `todayView` INCLUDES it (a deadline pulls the row into Today);
|
|
56
|
+
* - `anytimeView` INCLUDES it (Anytime ⊇ Today's to-dos — the pull re-files the
|
|
57
|
+
* row into Anytime, BANNER1b);
|
|
58
|
+
* - `somedayView` / `inboxView` EXCLUDE it (the GUI removes a pulled row from
|
|
59
|
+
* Someday/Inbox even before it materializes, BANNER1 Q1b).
|
|
60
|
+
* The `startDate IS NULL` clause scopes it to UNMATERIALIZED pulls; the
|
|
61
|
+
* suppression guard drops a dismissed nag (supp == deadline) and lets a re-armed
|
|
62
|
+
* one (supp < deadline) through (oddities §8e). ONE bind: today as a packed-date
|
|
63
|
+
* int (encodePackedDate(localToday(now))), the same injected clock every view uses.
|
|
64
|
+
*/
|
|
65
|
+
export const DEADLINE_PULLED = `(t.deadline IS NOT NULL AND t.deadline <= ? AND t.startDate IS NULL
|
|
66
|
+
AND (t.deadlineSuppressionDate IS NULL OR t.deadlineSuppressionDate < t.deadline))`;
|
|
48
67
|
/**
|
|
49
68
|
* The item's effective project: its own link, or its heading's project for
|
|
50
69
|
* headed children (heading rows carry the project link).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"predicates.js","sourceRoot":"","sources":["../../src/read/predicates.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,oFAAoF;AACpF,MAAM,CAAC,MAAM,IAAI,GAAG,0CAA0C,YAAY,EAAE,CAAC;AAE7E,yDAAyD;AACzD,MAAM,CAAC,MAAM,IAAI,GAAG,GAAG,IAAI,mBAAmB,CAAC;AAE/C;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,IAAI,8EAA8E,CAAC;AAErH;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,4DAA4D,CAAC;AAEpF,+EAA+E;AAC/E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAAU,EAAE,CAClD,KAAK,GAAG,mBAAmB,GAAG,yBAAyB,GAAG;UAClD,GAAG,kBAAkB,GAAG,8BAA8B,GAAG,mBAAmB,CAAC;AAEvF;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,gFAAgF,CAAC;AAE5G;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,WAAW;6CACR,WAAW;8CACV,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;AAEpE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;;QAE3B,WAAW;+CAC4B,WAAW,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"predicates.js","sourceRoot":"","sources":["../../src/read/predicates.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,oFAAoF;AACpF,MAAM,CAAC,MAAM,IAAI,GAAG,0CAA0C,YAAY,EAAE,CAAC;AAE7E,yDAAyD;AACzD,MAAM,CAAC,MAAM,IAAI,GAAG,GAAG,IAAI,mBAAmB,CAAC;AAE/C;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,IAAI,8EAA8E,CAAC;AAErH;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,4DAA4D,CAAC;AAEpF,+EAA+E;AAC/E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAAU,EAAE,CAClD,KAAK,GAAG,mBAAmB,GAAG,yBAAyB,GAAG;UAClD,GAAG,kBAAkB,GAAG,8BAA8B,GAAG,mBAAmB,CAAC;AAEvF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;uFACwD,CAAC;AAExF;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,gFAAgF,CAAC;AAE5G;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,WAAW;6CACR,WAAW;8CACV,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;AAEpE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;;QAE3B,WAAW;+CAC4B,WAAW,uBAAuB,CAAC"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Composite project view mirroring the native UI (validated T17 + "later
|
|
3
3
|
* items" findings): active items, headings with their children, later
|
|
4
|
-
* (scheduled by date / repeating templates / someday), logged
|
|
4
|
+
* (scheduled by date / repeating templates / someday), logged. Trashed
|
|
5
|
+
* children are excluded entirely (GUI-faithful — the app filters trashed
|
|
6
|
+
* children out of the project view, §6½/PLOG1-a).
|
|
5
7
|
*
|
|
6
8
|
* Child membership: `project = ? OR heading IN (project's headings)` — the
|
|
7
9
|
* DB invariant is that headed to-dos have project = NULL (atlas §TMTask).
|
|
@@ -10,24 +12,38 @@
|
|
|
10
12
|
import type { DatabaseSync } from "node:sqlite";
|
|
11
13
|
import type { Heading, IsoDateGroup, Project, Todo } from "../model/entities.ts";
|
|
12
14
|
import { type ViewFilter } from "./views.ts";
|
|
15
|
+
/**
|
|
16
|
+
* A heading group inside a project view. Mirrors the GUI: the heading owns its
|
|
17
|
+
* OWN display sub-buckets (§1 of the demotion/move design) — the anytime/current
|
|
18
|
+
* `items`, its future-dated `scheduled` children grouped per day, its resting
|
|
19
|
+
* `repeating` templates, and its `someday` children. The project-level buckets
|
|
20
|
+
* (below) hold ONLY the UNHEADED members; a headed child lives here, under its
|
|
21
|
+
* heading, never pooled at the project level.
|
|
22
|
+
*/
|
|
23
|
+
export interface ProjectHeadingGroup {
|
|
24
|
+
heading: Heading;
|
|
25
|
+
/** Open/current children under this heading, by index. */
|
|
26
|
+
items: Todo[];
|
|
27
|
+
/** This heading's future-dated children grouped by date ascending. */
|
|
28
|
+
scheduled: IsoDateGroup<Todo>[];
|
|
29
|
+
/** This heading's someday (incubated, undated) children. */
|
|
30
|
+
someday: Todo[];
|
|
31
|
+
/** This heading's repeating template rows (invisible in list views). */
|
|
32
|
+
repeating: Todo[];
|
|
33
|
+
}
|
|
13
34
|
export interface ProjectView {
|
|
14
35
|
project: Project;
|
|
15
|
-
/** Open, unscheduled/current children
|
|
36
|
+
/** Open, unscheduled/current UNHEADED children, by index. */
|
|
16
37
|
active: Todo[];
|
|
17
|
-
/** Headings in project order, each with its
|
|
18
|
-
headings:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
/** Repeating template rows owned by this project (invisible in list views). */
|
|
26
|
-
repeating: Todo[];
|
|
27
|
-
someday: Todo[];
|
|
28
|
-
};
|
|
38
|
+
/** Headings in project order, each with its own sub-buckets. */
|
|
39
|
+
headings: ProjectHeadingGroup[];
|
|
40
|
+
/** UNHEADED future-dated children grouped by date ascending. */
|
|
41
|
+
scheduled: IsoDateGroup<Todo>[];
|
|
42
|
+
/** UNHEADED someday (incubated, undated) children. */
|
|
43
|
+
someday: Todo[];
|
|
44
|
+
/** UNHEADED repeating template rows owned by this project (invisible in list views). */
|
|
45
|
+
repeating: Todo[];
|
|
29
46
|
logged: Todo[];
|
|
30
|
-
trashed: Todo[];
|
|
31
47
|
/**
|
|
32
48
|
* PLOG1 (additive): count of untrashed OPEN (status=0) children this project
|
|
33
49
|
* still holds while it is ITSELF completed or canceled — including once swept
|
|
@@ -42,4 +58,4 @@ export interface ProjectView {
|
|
|
42
58
|
export declare class ProjectNotFoundError extends Error {
|
|
43
59
|
constructor(uuid: string);
|
|
44
60
|
}
|
|
45
|
-
export declare function projectView(db: DatabaseSync, uuid: string, now?: Date, filter?: ViewFilter): ProjectView;
|
|
61
|
+
export declare function projectView(db: DatabaseSync, uuid: string, now?: Date, filter?: ViewFilter, zone?: string): ProjectView;
|