@dinoxx/dinox-cli 1.0.22 → 1.1.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 +29 -9
- package/dist/auth/userInfo.d.ts +2 -0
- package/dist/auth/userInfo.js +55 -14
- package/dist/cli.js +36 -2
- package/dist/commands/auth/index.d.ts +35 -0
- package/dist/commands/auth/index.js +382 -83
- package/dist/commands/boxes/index.js +2 -6
- package/dist/commands/boxes/model.d.ts +3 -0
- package/dist/commands/boxes/model.js +16 -1
- package/dist/commands/boxes/operations.js +18 -8
- package/dist/commands/boxes/repo.js +13 -11
- package/dist/commands/boxes/store.js +1 -1
- package/dist/commands/config/index.js +7 -5
- package/dist/commands/descriptor/register.js +9 -0
- package/dist/commands/doctor.d.ts +123 -0
- package/dist/commands/doctor.js +539 -0
- package/dist/commands/graph/index.d.ts +1 -1
- package/dist/commands/graph/index.js +35 -21
- package/dist/commands/graph/repo.js +92 -17
- package/dist/commands/meta/index.js +4 -4
- package/dist/commands/meta/repo.js +4 -3
- package/dist/commands/notes/actions.d.ts +1 -1
- package/dist/commands/notes/actions.js +121 -78
- package/dist/commands/notes/bulk.d.ts +1 -0
- package/dist/commands/notes/bulk.js +23 -17
- package/dist/commands/notes/contentEngine.js +69 -11
- package/dist/commands/notes/contentPatch.d.ts +4 -1
- package/dist/commands/notes/contentPatch.js +105 -41
- package/dist/commands/notes/contentPatchCommand.js +28 -11
- package/dist/commands/notes/descriptors.js +50 -20
- package/dist/commands/notes/dryRun.d.ts +1 -0
- package/dist/commands/notes/dryRun.js +4 -7
- package/dist/commands/notes/export.d.ts +6 -0
- package/dist/commands/notes/export.js +26 -6
- package/dist/commands/notes/metadataMutation.d.ts +1 -0
- package/dist/commands/notes/metadataMutation.js +14 -3
- package/dist/commands/notes/repo.d.ts +46 -4
- package/dist/commands/notes/repo.js +113 -28
- package/dist/commands/notes/runtime.d.ts +2 -1
- package/dist/commands/notes/runtime.js +17 -1
- package/dist/commands/notes/searchSql.js +13 -6
- package/dist/commands/notes/writeReceipt.d.ts +20 -0
- package/dist/commands/notes/writeReceipt.js +82 -0
- package/dist/commands/prompt/index.js +3 -3
- package/dist/commands/prompt/repo.d.ts +4 -1
- package/dist/commands/prompt/repo.js +17 -7
- package/dist/commands/runtime.d.ts +14 -2
- package/dist/commands/runtime.js +74 -15
- package/dist/commands/schema/renderSkills.js +5 -2
- package/dist/commands/schema/spec.js +4 -0
- package/dist/commands/storage/index.js +8 -2
- package/dist/commands/storage/repo.d.ts +4 -0
- package/dist/commands/storage/repo.js +356 -92
- package/dist/commands/sync.js +16 -12
- package/dist/commands/tags/content.js +9 -0
- package/dist/commands/tags/index.js +2 -6
- package/dist/commands/tags/operations.js +15 -10
- package/dist/commands/tags/repo.d.ts +2 -0
- package/dist/commands/tags/repo.js +18 -5
- package/dist/commands/tags/store.js +1 -1
- package/dist/commands/todo/contentModel.d.ts +4 -3
- package/dist/commands/todo/contentModel.js +78 -28
- package/dist/commands/todo/dryRun.d.ts +1 -0
- package/dist/commands/todo/dryRun.js +17 -13
- package/dist/commands/todo/index.d.ts +6 -0
- package/dist/commands/todo/index.js +89 -123
- package/dist/commands/todo/repo.d.ts +36 -1
- package/dist/commands/todo/repo.js +146 -37
- package/dist/commands/todo/taskIdentity.d.ts +2 -0
- package/dist/commands/todo/taskIdentity.js +64 -0
- package/dist/commands/todo/taskModel.js +27 -17
- package/dist/commands/update.d.ts +13 -1
- package/dist/commands/update.js +135 -23
- package/dist/commands/writeDryRun.d.ts +3 -2
- package/dist/commands/writeDryRun.js +4 -3
- package/dist/commands/writeDurability.d.ts +5 -0
- package/dist/commands/writeDurability.js +22 -0
- package/dist/config/paths.js +6 -1
- package/dist/config/resolve.d.ts +2 -0
- package/dist/config/resolve.js +23 -9
- package/dist/config/store.d.ts +3 -0
- package/dist/config/store.js +61 -14
- package/dist/config/types.d.ts +4 -0
- package/dist/daemon/client.d.ts +26 -1
- package/dist/daemon/client.js +236 -12
- package/dist/daemon/ensure.js +74 -12
- package/dist/daemon/index.d.ts +42 -0
- package/dist/daemon/index.js +202 -52
- package/dist/daemon/lifecycle.d.ts +42 -0
- package/dist/daemon/lifecycle.js +115 -0
- package/dist/daemon/pid.d.ts +19 -6
- package/dist/daemon/pid.js +147 -13
- package/dist/daemon/route.d.ts +14 -0
- package/dist/daemon/route.js +40 -0
- package/dist/daemon/server.d.ts +11 -0
- package/dist/daemon/server.js +201 -50
- package/dist/daemon/types.d.ts +29 -1
- package/dist/daemon/types.js +1 -0
- package/dist/dinox.js +25 -1
- package/dist/powersync/connector.js +31 -16
- package/dist/powersync/exclusiveRuntime.d.ts +19 -0
- package/dist/powersync/exclusiveRuntime.js +42 -0
- package/dist/powersync/runtime.d.ts +24 -4
- package/dist/powersync/runtime.js +234 -36
- package/dist/powersync/syncGate.d.ts +3 -1
- package/dist/powersync/syncGate.js +7 -1
- package/dist/powersync/tokenIndex.d.ts +11 -0
- package/dist/powersync/tokenIndex.js +159 -22
- package/dist/powersync/uploader.js +107 -52
- package/dist/utils/abort.js +0 -4
- package/dist/utils/asyncRelease.d.ts +2 -0
- package/dist/utils/asyncRelease.js +25 -0
- package/dist/utils/bidlinkCanonicalization.js +3 -0
- package/dist/utils/dryRun.d.ts +1 -1
- package/dist/utils/errors.d.ts +15 -1
- package/dist/utils/errors.js +223 -5
- package/dist/utils/output.d.ts +1 -0
- package/dist/utils/output.js +51 -15
- package/dist/utils/redact.js +1 -1
- package/dist/utils/sqliteLease.d.ts +8 -0
- package/dist/utils/sqliteLease.js +59 -0
- package/dist/utils/syncTimeout.d.ts +7 -1
- package/dist/utils/syncTimeout.js +8 -7
- package/dist/utils/terminalSanitization.js +6 -2
- package/dist/utils/tiptapMarkdown.js +49 -3
- package/dist/utils/tiptapMarkdownSyntax.d.ts +9 -0
- package/dist/utils/tiptapMarkdownSyntax.js +249 -0
- package/dist/utils/tokenize.js +24 -2
- package/dist/utils/updateNotice.js +60 -12
- package/package.json +12 -10
- package/dist/commands/mcp/auth.d.ts +0 -4
- package/dist/commands/mcp/auth.js +0 -75
- package/dist/commands/mcp/index.d.ts +0 -2
- package/dist/commands/mcp/index.js +0 -86
- package/dist/commands/mcp/noteContentTools.d.ts +0 -222
- package/dist/commands/mcp/noteContentTools.js +0 -390
- package/dist/commands/mcp/server.d.ts +0 -34
- package/dist/commands/mcp/server.js +0 -424
- package/dist/commands/mcp/tools.d.ts +0 -2
- package/dist/commands/mcp/tools.js +0 -32
- package/dist/commands/mcp/types.d.ts +0 -39
- package/dist/commands/mcp/types.js +0 -1
- package/dist/utils/noteContentEngine.d.ts +0 -333
- package/dist/utils/noteContentEngine.js +0 -740
|
@@ -1,20 +1,31 @@
|
|
|
1
1
|
import { resolveAuthIdentity } from '../../auth/userInfo.js';
|
|
2
2
|
import { registerCommandGroup } from '../descriptor/register.js';
|
|
3
3
|
import { FORMAT_OPTIONS, OFFLINE_OPTIONS, REQUIRE_SYNC_OPTIONS, SYNC_TIMEOUT_OPTIONS } from '../schema/globalOptions.js';
|
|
4
|
+
import { WRITE_DURABILITY_OPTION } from '../writeDurability.js';
|
|
4
5
|
import { readStringOrFile } from '../../utils/argValue.js';
|
|
5
6
|
import { printDryRunPreview } from '../../utils/dryRun.js';
|
|
6
7
|
import { DinoxError } from '../../utils/errors.js';
|
|
7
8
|
import { printSuccess } from '../../utils/output.js';
|
|
8
|
-
import { commandStale,
|
|
9
|
+
import { commandStale, resolveWriteDurabilityForRuntime, syncBeforeCommand, waitForMutationUpload, withCommandRuntime, } from '../runtime.js';
|
|
10
|
+
import { readNoteWriteReceipt } from '../notes/writeReceipt.js';
|
|
11
|
+
import { parseCreatedAtRange } from '../notes/searchTime.js';
|
|
9
12
|
import { buildTodoAppendDryRunPreview, buildTodoCreateDryRunPreview, buildTodoUpdateDryRunPreview, } from './dryRun.js';
|
|
10
|
-
import { appendTodoTasks, createTodoNote, normalizeTaskTexts,
|
|
11
|
-
|
|
12
|
-
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
13
|
+
import { appendTodoTasks, createTodoNote, executeTodoSearch, normalizeTaskTexts, toTodoSearchWire, updateTodoTaskStatus, } from './repo.js';
|
|
14
|
+
import { routeRead } from '../../daemon/route.js';
|
|
13
15
|
const DEFAULT_TASK_LIMIT = 50;
|
|
14
16
|
const DEFAULT_NOTE_SCAN_LIMIT = 200;
|
|
15
17
|
const MAX_TASK_LIMIT = 500;
|
|
16
18
|
const MAX_NOTE_SCAN_LIMIT = 5000;
|
|
17
19
|
const TODO_GLOBAL_OPTIONS = [...FORMAT_OPTIONS, ...OFFLINE_OPTIONS, ...REQUIRE_SYNC_OPTIONS, ...SYNC_TIMEOUT_OPTIONS];
|
|
20
|
+
const TODO_WRITE_RECEIPT_FIELDS = [
|
|
21
|
+
'durability',
|
|
22
|
+
'upload_queue_remaining',
|
|
23
|
+
'version',
|
|
24
|
+
'updated_at',
|
|
25
|
+
'content_hash',
|
|
26
|
+
'changed',
|
|
27
|
+
'stale',
|
|
28
|
+
];
|
|
18
29
|
function parseTaskStatus(value) {
|
|
19
30
|
const normalized = typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
20
31
|
if (normalized === 'all' || normalized === 'completed' || normalized === 'uncompleted') {
|
|
@@ -56,85 +67,14 @@ function parsePositiveIntegerOption(value, optionName, fallback, max) {
|
|
|
56
67
|
}
|
|
57
68
|
return Math.trunc(parsed);
|
|
58
69
|
}
|
|
59
|
-
function
|
|
60
|
-
const
|
|
61
|
-
if (!
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
const year = Number(match[1]);
|
|
65
|
-
const month = Number(match[2]);
|
|
66
|
-
const day = Number(match[3]);
|
|
67
|
-
const parsed = new Date(year, month - 1, day, 0, 0, 0, 0);
|
|
68
|
-
if (parsed.getFullYear() !== year ||
|
|
69
|
-
parsed.getMonth() !== month - 1 ||
|
|
70
|
-
parsed.getDate() !== day) {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
return parsed;
|
|
74
|
-
}
|
|
75
|
-
function parseDateInput(value, optionName) {
|
|
76
|
-
if (typeof value !== 'string') {
|
|
77
|
-
return undefined;
|
|
78
|
-
}
|
|
79
|
-
const raw = value.trim();
|
|
80
|
-
if (!raw) {
|
|
81
|
-
throw new DinoxError(`${optionName} requires a non-empty date value`);
|
|
82
|
-
}
|
|
83
|
-
const isDateOnly = DATE_ONLY_RE.test(raw);
|
|
84
|
-
const dateOnly = parseLocalDateOnly(raw);
|
|
85
|
-
if (dateOnly) {
|
|
86
|
-
return dateOnly;
|
|
87
|
-
}
|
|
88
|
-
if (isDateOnly) {
|
|
89
|
-
throw new DinoxError(`${optionName} must be a valid date (YYYY-MM-DD or ISO datetime)`);
|
|
90
|
-
}
|
|
91
|
-
const parsed = new Date(raw);
|
|
92
|
-
if (Number.isNaN(parsed.getTime())) {
|
|
93
|
-
throw new DinoxError(`${optionName} must be a valid date (YYYY-MM-DD or ISO datetime)`);
|
|
94
|
-
}
|
|
95
|
-
return parsed;
|
|
96
|
-
}
|
|
97
|
-
function parseDaysInput(value) {
|
|
98
|
-
if (value === undefined || value === null || value === '') {
|
|
99
|
-
return undefined;
|
|
100
|
-
}
|
|
101
|
-
if (typeof value !== 'string') {
|
|
102
|
-
throw new DinoxError('--days must be a positive integer');
|
|
103
|
-
}
|
|
104
|
-
const trimmed = value.trim();
|
|
105
|
-
if (!/^\d+$/.test(trimmed)) {
|
|
106
|
-
throw new DinoxError('--days must be a positive integer');
|
|
107
|
-
}
|
|
108
|
-
const parsed = Number(trimmed);
|
|
109
|
-
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
110
|
-
throw new DinoxError('--days must be a positive integer');
|
|
111
|
-
}
|
|
112
|
-
return Math.trunc(parsed);
|
|
113
|
-
}
|
|
114
|
-
function parseTaskDateRange(input, now = new Date()) {
|
|
115
|
-
const from = parseDateInput(input.from, '--from');
|
|
116
|
-
const to = parseDateInput(input.to, '--to');
|
|
117
|
-
const days = parseDaysInput(input.days);
|
|
118
|
-
if (days !== undefined && (from || to)) {
|
|
119
|
-
throw new DinoxError('--days cannot be used together with --from/--to');
|
|
120
|
-
}
|
|
121
|
-
if (days !== undefined) {
|
|
122
|
-
const end = new Date(now);
|
|
123
|
-
const start = new Date(now.getTime() - (days - 1) * DAY_MS);
|
|
124
|
-
return {
|
|
125
|
-
startDate: start,
|
|
126
|
-
endDate: end,
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
if (!from && !to) {
|
|
70
|
+
export function parseTaskDateRange(input, now = new Date()) {
|
|
71
|
+
const { createdAtFrom, createdAtTo } = parseCreatedAtRange(input, now);
|
|
72
|
+
if (!createdAtFrom && !createdAtTo) {
|
|
130
73
|
return undefined;
|
|
131
74
|
}
|
|
132
|
-
if (from && to && from.getTime() > to.getTime()) {
|
|
133
|
-
throw new DinoxError('--from must be earlier than or equal to --to');
|
|
134
|
-
}
|
|
135
75
|
return {
|
|
136
|
-
startDate:
|
|
137
|
-
endDate:
|
|
76
|
+
startDate: createdAtFrom ? new Date(createdAtFrom) : undefined,
|
|
77
|
+
endDate: createdAtTo ? new Date(createdAtTo) : undefined,
|
|
138
78
|
};
|
|
139
79
|
}
|
|
140
80
|
function parseListInput(raw, optionName) {
|
|
@@ -190,41 +130,45 @@ async function parseTaskInput(args) {
|
|
|
190
130
|
return normalizeTaskTexts(merged);
|
|
191
131
|
}
|
|
192
132
|
async function withTodoDatabase(globals, run) {
|
|
193
|
-
|
|
133
|
+
return withCommandRuntime(globals, run);
|
|
194
134
|
}
|
|
195
135
|
async function runTodoSearch({ args, globals, options }) {
|
|
196
136
|
const searchOptions = options;
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
limit,
|
|
218
|
-
scanLimit,
|
|
219
|
-
});
|
|
220
|
-
printSuccess({ stale: commandStale(runtime), ...result });
|
|
137
|
+
// Parse here; the db-touching scan runs through executeTodoSearch — locally or on the daemon.
|
|
138
|
+
const keyword = args.query?.trim() ?? '';
|
|
139
|
+
const taskStatus = parseTaskStatus(searchOptions.status);
|
|
140
|
+
const taskTagFilter = typeof searchOptions.tags === 'string'
|
|
141
|
+
? await parseTagFilterInput(searchOptions.tags)
|
|
142
|
+
: [];
|
|
143
|
+
const taskDateRange = parseTaskDateRange({
|
|
144
|
+
from: searchOptions.from,
|
|
145
|
+
to: searchOptions.to,
|
|
146
|
+
days: searchOptions.days,
|
|
147
|
+
});
|
|
148
|
+
const limit = parsePositiveIntegerOption(searchOptions.limit, '--limit', DEFAULT_TASK_LIMIT, MAX_TASK_LIMIT);
|
|
149
|
+
const scanLimit = parsePositiveIntegerOption(searchOptions.scanLimit, '--scan-limit', DEFAULT_NOTE_SCAN_LIMIT, MAX_NOTE_SCAN_LIMIT);
|
|
150
|
+
const wire = toTodoSearchWire(keyword, {
|
|
151
|
+
includeDeleted: Boolean(searchOptions.includeDeleted),
|
|
152
|
+
taskStatus,
|
|
153
|
+
taskTagFilter,
|
|
154
|
+
taskDateRange,
|
|
155
|
+
limit,
|
|
156
|
+
scanLimit,
|
|
221
157
|
});
|
|
158
|
+
const result = await routeRead(globals, 'todo.search', wire, () => withTodoDatabase(globals, async (runtime) => {
|
|
159
|
+
await syncBeforeCommand(runtime);
|
|
160
|
+
const local = await executeTodoSearch(runtime.db, wire);
|
|
161
|
+
return { ...local, stale: commandStale(runtime) };
|
|
162
|
+
}));
|
|
163
|
+
const { stale, ...response } = result;
|
|
164
|
+
printSuccess({ stale: stale ?? false, ...response });
|
|
222
165
|
}
|
|
223
166
|
async function runTodoAppend({ args, globals, options }) {
|
|
224
167
|
const appendOptions = options;
|
|
225
168
|
await withTodoDatabase(globals, async (runtime) => {
|
|
226
169
|
const { db, config, offline } = runtime;
|
|
227
170
|
await syncBeforeCommand(runtime);
|
|
171
|
+
const durability = resolveWriteDurabilityForRuntime(runtime, appendOptions.durability);
|
|
228
172
|
const taskTexts = await parseTaskInput({
|
|
229
173
|
positionalTask: args.task,
|
|
230
174
|
tasksOption: typeof appendOptions.tasks === 'string' ? appendOptions.tasks : undefined,
|
|
@@ -245,9 +189,13 @@ async function runTodoAppend({ args, globals, options }) {
|
|
|
245
189
|
noteId: typeof appendOptions.noteId === 'string' ? appendOptions.noteId : undefined,
|
|
246
190
|
taskTexts,
|
|
247
191
|
});
|
|
248
|
-
|
|
249
|
-
await
|
|
250
|
-
|
|
192
|
+
const upload = await waitForMutationUpload(runtime, { durability });
|
|
193
|
+
const receipt = await readNoteWriteReceipt(db, result.note_id, {
|
|
194
|
+
changed: ['content_json', 'image_detail', 'content_md', 'content_text'],
|
|
195
|
+
upload,
|
|
196
|
+
stale: commandStale(runtime),
|
|
197
|
+
});
|
|
198
|
+
printSuccess({ ok: true, ...receipt, ...result });
|
|
251
199
|
});
|
|
252
200
|
}
|
|
253
201
|
async function runTodoCreate({ args, globals, options }) {
|
|
@@ -255,6 +203,7 @@ async function runTodoCreate({ args, globals, options }) {
|
|
|
255
203
|
await withTodoDatabase(globals, async (runtime) => {
|
|
256
204
|
const { db, config, offline } = runtime;
|
|
257
205
|
await syncBeforeCommand(runtime);
|
|
206
|
+
const durability = resolveWriteDurabilityForRuntime(runtime, createOptions.durability);
|
|
258
207
|
const taskTexts = await parseTaskInput({
|
|
259
208
|
positionalTask: args.task,
|
|
260
209
|
tasksOption: typeof createOptions.tasks === 'string' ? createOptions.tasks : undefined,
|
|
@@ -276,9 +225,13 @@ async function runTodoCreate({ args, globals, options }) {
|
|
|
276
225
|
title: typeof createOptions.title === 'string' ? createOptions.title : undefined,
|
|
277
226
|
userId: identity.userId,
|
|
278
227
|
});
|
|
279
|
-
|
|
280
|
-
await
|
|
281
|
-
|
|
228
|
+
const upload = await waitForMutationUpload(runtime, { durability });
|
|
229
|
+
const receipt = await readNoteWriteReceipt(db, result.note_id, {
|
|
230
|
+
changed: ['title', 'type', 'content_json', 'image_detail', 'content_md', 'content_text'],
|
|
231
|
+
upload,
|
|
232
|
+
stale: commandStale(runtime),
|
|
233
|
+
});
|
|
234
|
+
printSuccess({ ok: true, ...receipt, ...result });
|
|
282
235
|
});
|
|
283
236
|
}
|
|
284
237
|
async function runTodoUpdate({ args, globals, options }) {
|
|
@@ -286,6 +239,7 @@ async function runTodoUpdate({ args, globals, options }) {
|
|
|
286
239
|
await withTodoDatabase(globals, async (runtime) => {
|
|
287
240
|
const { db, config, offline } = runtime;
|
|
288
241
|
await syncBeforeCommand(runtime);
|
|
242
|
+
const durability = resolveWriteDurabilityForRuntime(runtime, updateOptions.durability);
|
|
289
243
|
const taskId = args.taskId;
|
|
290
244
|
if (!taskId) {
|
|
291
245
|
throw new DinoxError('taskId is required');
|
|
@@ -297,6 +251,7 @@ async function runTodoUpdate({ args, globals, options }) {
|
|
|
297
251
|
config,
|
|
298
252
|
offline,
|
|
299
253
|
taskId,
|
|
254
|
+
noteId: typeof updateOptions.noteId === 'string' ? updateOptions.noteId : undefined,
|
|
300
255
|
checked,
|
|
301
256
|
});
|
|
302
257
|
printDryRunPreview(preview);
|
|
@@ -304,11 +259,18 @@ async function runTodoUpdate({ args, globals, options }) {
|
|
|
304
259
|
}
|
|
305
260
|
const result = await updateTodoTaskStatus(db, {
|
|
306
261
|
taskId,
|
|
262
|
+
noteId: typeof updateOptions.noteId === 'string' ? updateOptions.noteId : undefined,
|
|
307
263
|
checked,
|
|
308
264
|
});
|
|
309
|
-
|
|
310
|
-
await
|
|
311
|
-
|
|
265
|
+
const upload = await waitForMutationUpload(runtime, { durability });
|
|
266
|
+
const receipt = await readNoteWriteReceipt(db, result.note_id, {
|
|
267
|
+
changed: result.updated
|
|
268
|
+
? ['content_json', 'image_detail', 'content_md', 'content_text']
|
|
269
|
+
: [],
|
|
270
|
+
upload,
|
|
271
|
+
stale: commandStale(runtime),
|
|
272
|
+
});
|
|
273
|
+
printSuccess({ ok: true, ...receipt, ...result });
|
|
312
274
|
});
|
|
313
275
|
}
|
|
314
276
|
const todoSearchCommand = {
|
|
@@ -339,7 +301,7 @@ const todoSearchCommand = {
|
|
|
339
301
|
type: 'structured',
|
|
340
302
|
summary: 'Todo search payload with metadata and task list',
|
|
341
303
|
fields: ['tasks.task_id', 'tasks.task_key', 'tasks.note_id', 'tasks.note_title', 'tasks.status', 'tasks.depth', 'tasks.parent_id', 'tasks.tags'],
|
|
342
|
-
metaFields: ['stale', 'meta.query', 'meta.returned_count', 'meta.
|
|
304
|
+
metaFields: ['stale', 'meta.query', 'meta.returned_count', 'meta.total_count', 'meta.total_count_is_lower_bound', 'meta.matched_note_count', 'meta.limit', 'meta.scan_limit', 'meta.scanned_note_count', 'meta.scan_truncated', 'meta.truncated', 'meta.applied_filters.status', 'meta.applied_filters.tags', 'meta.applied_filters.include_deleted', 'meta.applied_filters.date_range'],
|
|
343
305
|
},
|
|
344
306
|
examples: ['dino todo search "报销" --status uncompleted --format json', 'dino todo search --days 7 --format json'],
|
|
345
307
|
},
|
|
@@ -363,6 +325,7 @@ const todoAppendCommand = {
|
|
|
363
325
|
},
|
|
364
326
|
{ flags: '--tasks <string|@file>', description: 'Task list (JSON array or comma/newline-separated)' },
|
|
365
327
|
{ flags: '--note-id <id>', description: 'Target note id; omitted means latest eligible note' },
|
|
328
|
+
WRITE_DURABILITY_OPTION,
|
|
366
329
|
{ flags: '--dry-run', description: 'Preview the write without executing it' },
|
|
367
330
|
],
|
|
368
331
|
schema: {
|
|
@@ -372,10 +335,10 @@ const todoAppendCommand = {
|
|
|
372
335
|
globalOptions: TODO_GLOBAL_OPTIONS,
|
|
373
336
|
output: {
|
|
374
337
|
type: 'structured',
|
|
375
|
-
summary: 'Append result with target note
|
|
376
|
-
fields: ['
|
|
338
|
+
summary: 'Append result with target note, appended task count, and write receipt',
|
|
339
|
+
fields: ['note_id', 'appended_count', 'source', ...TODO_WRITE_RECEIPT_FIELDS],
|
|
377
340
|
},
|
|
378
|
-
examples: ['dino todo append --note-id <id> --task "补交报销单" --format json'],
|
|
341
|
+
examples: ['dino todo append --note-id <id> --task "补交报销单" --durability uploaded --format json'],
|
|
379
342
|
},
|
|
380
343
|
action: runTodoAppend,
|
|
381
344
|
};
|
|
@@ -397,6 +360,7 @@ const todoCreateCommand = {
|
|
|
397
360
|
},
|
|
398
361
|
{ flags: '--tasks <string|@file>', description: 'Task list (JSON array or comma/newline-separated)' },
|
|
399
362
|
{ flags: '--title <string>', description: 'Optional note title' },
|
|
363
|
+
WRITE_DURABILITY_OPTION,
|
|
400
364
|
{ flags: '--dry-run', description: 'Preview the write without executing it' },
|
|
401
365
|
],
|
|
402
366
|
schema: {
|
|
@@ -406,8 +370,8 @@ const todoCreateCommand = {
|
|
|
406
370
|
globalOptions: TODO_GLOBAL_OPTIONS,
|
|
407
371
|
output: {
|
|
408
372
|
type: 'structured',
|
|
409
|
-
summary: 'Creation result with new note id
|
|
410
|
-
fields: ['
|
|
373
|
+
summary: 'Creation result with new note id, created task count, and write receipt',
|
|
374
|
+
fields: ['note_id', 'created_count', 'title', ...TODO_WRITE_RECEIPT_FIELDS],
|
|
411
375
|
},
|
|
412
376
|
examples: ['dino todo create --task "补交报销单" --task "整理发票" --format json'],
|
|
413
377
|
},
|
|
@@ -428,6 +392,8 @@ const todoUpdateCommand = {
|
|
|
428
392
|
description: 'Target status: completed|uncompleted|done|undone|true|false|1|0',
|
|
429
393
|
required: true,
|
|
430
394
|
},
|
|
395
|
+
{ flags: '--note-id <id>', description: 'Restrict task lookup to one exact note id' },
|
|
396
|
+
WRITE_DURABILITY_OPTION,
|
|
431
397
|
{ flags: '--dry-run', description: 'Preview the write without executing it' },
|
|
432
398
|
],
|
|
433
399
|
schema: {
|
|
@@ -437,10 +403,10 @@ const todoUpdateCommand = {
|
|
|
437
403
|
globalOptions: TODO_GLOBAL_OPTIONS,
|
|
438
404
|
output: {
|
|
439
405
|
type: 'structured',
|
|
440
|
-
summary: 'Mutation result with updated status
|
|
441
|
-
fields: ['
|
|
406
|
+
summary: 'Mutation result with updated status, target note id, and write receipt',
|
|
407
|
+
fields: ['task_id', 'checked', 'updated', 'note_id', ...TODO_WRITE_RECEIPT_FIELDS],
|
|
442
408
|
},
|
|
443
|
-
examples: ['dino todo update <taskId> --status completed --format json'],
|
|
409
|
+
examples: ['dino todo update <taskId> --note-id <noteId> --status completed --format json'],
|
|
444
410
|
},
|
|
445
411
|
action: runTodoUpdate,
|
|
446
412
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AbstractPowerSyncDatabase } from '@powersync/common';
|
|
2
|
+
import { parseTiptapDocFromDb } from './contentModel.js';
|
|
2
3
|
import { type TaskDateRangeFilter, type TaskStatusFilter, type TaskTimePoint } from './taskModel.js';
|
|
3
4
|
export type SearchTodoOptions = {
|
|
4
5
|
includeDeleted: boolean;
|
|
@@ -31,6 +32,7 @@ export type CreateTodoNoteResult = {
|
|
|
31
32
|
export type UpdateTodoTaskStatusOptions = {
|
|
32
33
|
taskId: string;
|
|
33
34
|
checked: boolean;
|
|
35
|
+
noteId?: string;
|
|
34
36
|
};
|
|
35
37
|
export type UpdateTodoTaskStatusResult = {
|
|
36
38
|
note_id: string;
|
|
@@ -64,6 +66,9 @@ export type SearchedTodoResponse = {
|
|
|
64
66
|
matched_note_count: number;
|
|
65
67
|
limit: number;
|
|
66
68
|
scan_limit: number;
|
|
69
|
+
scanned_note_count: number;
|
|
70
|
+
scan_truncated: boolean;
|
|
71
|
+
total_count_is_lower_bound: boolean;
|
|
67
72
|
truncated: boolean;
|
|
68
73
|
applied_filters: {
|
|
69
74
|
status: TaskStatusFilter;
|
|
@@ -86,11 +91,41 @@ type TodoMutableNoteRow = {
|
|
|
86
91
|
content_md: string | null;
|
|
87
92
|
is_del: number | null;
|
|
88
93
|
created_at?: string | null;
|
|
94
|
+
version: number | string | null;
|
|
95
|
+
};
|
|
96
|
+
export declare function validateTodoAppendTarget(target: TodoMutableNoteRow): {
|
|
97
|
+
currentDoc: ReturnType<typeof parseTiptapDocFromDb>;
|
|
98
|
+
noteId: string;
|
|
99
|
+
expectedVersion: number;
|
|
89
100
|
};
|
|
101
|
+
/**
|
|
102
|
+
* JSON-safe todo-search request. {@link SearchTodoOptions.taskDateRange} carries `Date`
|
|
103
|
+
* objects, which cannot cross the daemon wire intact, so the range is transported as ISO
|
|
104
|
+
* strings here and reconstructed inside {@link executeTodoSearch}.
|
|
105
|
+
*/
|
|
106
|
+
export type TodoSearchWire = {
|
|
107
|
+
query: string;
|
|
108
|
+
includeDeleted: boolean;
|
|
109
|
+
taskStatus: TaskStatusFilter;
|
|
110
|
+
taskTagFilter: string[];
|
|
111
|
+
limit: number;
|
|
112
|
+
scanLimit: number;
|
|
113
|
+
startDate?: string;
|
|
114
|
+
endDate?: string;
|
|
115
|
+
};
|
|
116
|
+
/** Serialize parsed todo-search options into a JSON-safe wire payload. */
|
|
117
|
+
export declare function toTodoSearchWire(query: string, options: SearchTodoOptions): TodoSearchWire;
|
|
118
|
+
/**
|
|
119
|
+
* Run a todo search from a wire payload. Shared by the local command path and the daemon
|
|
120
|
+
* RPC handler so both produce identical results from one implementation.
|
|
121
|
+
*/
|
|
122
|
+
export declare function executeTodoSearch(db: AbstractPowerSyncDatabase, wire: TodoSearchWire): Promise<SearchedTodoResponse>;
|
|
90
123
|
export declare function searchTodoTasks(db: AbstractPowerSyncDatabase, query: string, options: SearchTodoOptions): Promise<SearchedTodoResponse>;
|
|
91
124
|
export declare function appendTodoTasks(db: AbstractPowerSyncDatabase, options: AppendTodoTasksOptions): Promise<AppendTodoTasksResult>;
|
|
92
125
|
export declare function createTodoNote(db: AbstractPowerSyncDatabase, options: CreateTodoNoteOptions): Promise<CreateTodoNoteResult>;
|
|
93
126
|
export declare function updateTodoTaskStatus(db: AbstractPowerSyncDatabase, options: UpdateTodoTaskStatusOptions): Promise<UpdateTodoTaskStatusResult>;
|
|
94
127
|
export declare function getTodoAppendTargetById(db: AbstractPowerSyncDatabase, noteId: string): Promise<TodoMutableNoteRow | null>;
|
|
95
128
|
export declare function getLatestTodoAppendTarget(db: AbstractPowerSyncDatabase): Promise<TodoMutableNoteRow | null>;
|
|
96
|
-
export declare function loadTodoTaskCandidatesByTaskId(db: AbstractPowerSyncDatabase, taskId: string
|
|
129
|
+
export declare function loadTodoTaskCandidatesByTaskId(db: AbstractPowerSyncDatabase, taskId: string, options?: {
|
|
130
|
+
noteId?: string;
|
|
131
|
+
}): Promise<TodoMutableNoteRow[]>;
|