@dinoxx/dinox-cli 1.0.20 → 1.0.22

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 (89) hide show
  1. package/README.md +72 -139
  2. package/dist/auth/userInfo.d.ts +8 -1
  3. package/dist/auth/userInfo.js +38 -6
  4. package/dist/cli.js +1 -2
  5. package/dist/cliTypes.d.ts +1 -0
  6. package/dist/commands/auth/index.js +11 -4
  7. package/dist/commands/boxes/index.js +274 -54
  8. package/dist/commands/boxes/model.d.ts +34 -0
  9. package/dist/commands/boxes/model.js +78 -0
  10. package/dist/commands/boxes/operations.d.ts +86 -0
  11. package/dist/commands/boxes/operations.js +415 -0
  12. package/dist/commands/boxes/repo.d.ts +13 -6
  13. package/dist/commands/boxes/repo.js +272 -149
  14. package/dist/commands/boxes/store.d.ts +22 -0
  15. package/dist/commands/boxes/store.js +143 -0
  16. package/dist/commands/graph/index.js +11 -38
  17. package/dist/commands/mcp/noteContentTools.d.ts +222 -0
  18. package/dist/commands/mcp/noteContentTools.js +390 -0
  19. package/dist/commands/mcp/server.d.ts +3 -0
  20. package/dist/commands/mcp/server.js +43 -15
  21. package/dist/commands/mcp/tools.js +3 -1
  22. package/dist/commands/mcp/types.d.ts +6 -2
  23. package/dist/commands/meta/index.js +8 -24
  24. package/dist/commands/meta/repo.d.ts +0 -3
  25. package/dist/commands/meta/repo.js +1 -4
  26. package/dist/commands/notes/actions.d.ts +2 -0
  27. package/dist/commands/notes/actions.js +149 -55
  28. package/dist/commands/notes/bulk.d.ts +34 -0
  29. package/dist/commands/notes/bulk.js +204 -0
  30. package/dist/commands/notes/contentEngine.d.ts +95 -0
  31. package/dist/commands/notes/contentEngine.js +652 -0
  32. package/dist/commands/notes/contentPatch.d.ts +84 -0
  33. package/dist/commands/notes/contentPatch.js +337 -0
  34. package/dist/commands/notes/contentPatchCommand.d.ts +3 -0
  35. package/dist/commands/notes/contentPatchCommand.js +126 -0
  36. package/dist/commands/notes/descriptors.js +194 -42
  37. package/dist/commands/notes/export.d.ts +21 -0
  38. package/dist/commands/notes/export.js +224 -0
  39. package/dist/commands/notes/metadataMutation.d.ts +28 -0
  40. package/dist/commands/notes/metadataMutation.js +127 -0
  41. package/dist/commands/notes/repo.d.ts +20 -0
  42. package/dist/commands/notes/repo.js +135 -18
  43. package/dist/commands/notes/runtime.d.ts +3 -12
  44. package/dist/commands/notes/runtime.js +4 -30
  45. package/dist/commands/notes/searchSql.js +1 -1
  46. package/dist/commands/prompt/index.js +17 -47
  47. package/dist/commands/prompt/repo.js +2 -2
  48. package/dist/commands/runtime.d.ts +34 -0
  49. package/dist/commands/runtime.js +110 -0
  50. package/dist/commands/schema/globalOptions.d.ts +1 -0
  51. package/dist/commands/schema/globalOptions.js +1 -0
  52. package/dist/commands/schema/renderSkills.js +21 -7
  53. package/dist/commands/schema/spec.d.ts +1 -2
  54. package/dist/commands/schema/spec.js +2 -3
  55. package/dist/commands/schema/types.d.ts +0 -13
  56. package/dist/commands/storage/index.js +32 -62
  57. package/dist/commands/sync.js +22 -5
  58. package/dist/commands/tags/content.d.ts +32 -0
  59. package/dist/commands/tags/content.js +243 -0
  60. package/dist/commands/tags/index.js +287 -51
  61. package/dist/commands/tags/model.d.ts +38 -0
  62. package/dist/commands/tags/model.js +100 -0
  63. package/dist/commands/tags/operations.d.ts +105 -0
  64. package/dist/commands/tags/operations.js +438 -0
  65. package/dist/commands/tags/repo.d.ts +5 -1
  66. package/dist/commands/tags/repo.js +142 -218
  67. package/dist/commands/tags/store.d.ts +28 -0
  68. package/dist/commands/tags/store.js +166 -0
  69. package/dist/commands/todo/index.js +32 -63
  70. package/dist/commands/writeDryRun.d.ts +25 -0
  71. package/dist/commands/writeDryRun.js +31 -1
  72. package/dist/config/resolve.js +2 -2
  73. package/dist/daemon/index.d.ts +2 -0
  74. package/dist/daemon/index.js +176 -58
  75. package/dist/powersync/runtime.d.ts +1 -0
  76. package/dist/powersync/runtime.js +16 -0
  77. package/dist/powersync/schema/content.d.ts +2 -0
  78. package/dist/powersync/schema/content.js +2 -0
  79. package/dist/powersync/schema/index.d.ts +2 -0
  80. package/dist/powersync/syncGate.d.ts +24 -0
  81. package/dist/powersync/syncGate.js +36 -0
  82. package/dist/skills/check.d.ts +1 -1
  83. package/dist/skills/check.js +27 -2
  84. package/dist/utils/authToken.d.ts +2 -0
  85. package/dist/utils/authToken.js +7 -2
  86. package/dist/utils/noteContentEngine.d.ts +333 -0
  87. package/dist/utils/noteContentEngine.js +740 -0
  88. package/dist/utils/tiptapMarkdownSchema.js +31 -0
  89. package/package.json +4 -8
@@ -0,0 +1,415 @@
1
+ import { withPowerSyncWriteTransaction } from '../../powersync/runtime.js';
2
+ import { DinoxError } from '../../utils/errors.js';
3
+ import { nowIsoUtc } from '../../utils/time.js';
4
+ import { MAX_BOX_NAME_LENGTH, MAX_BOX_PATH_LENGTH, REQUIRED_NOTE_BOX_COLUMNS, assertMaxLength, canonicalizeBoxPath, getLeafName, normalizeBoxLookupKey, parseStoredBoxIds, trimString, } from './model.js';
5
+ import { activeBoxNodes, activeNodeByPath, assertCanWriteBox, assertRequiredColumns, assertWritableBoxNodes, descendantsOf, ensureNoPathConflict, getTableColumns, isActiveBoxNode, isDescendantBoxPath, loadAllBoxNodes, requireActivePath, toBoxListItem, } from './store.js';
6
+ function buildSubtreeChanges(args) {
7
+ const newRootPath = canonicalizeBoxPath(args.newRootPath);
8
+ if (!newRootPath) {
9
+ throw new DinoxError('Target box path is required');
10
+ }
11
+ assertMaxLength('Box path', newRootPath, MAX_BOX_PATH_LENGTH);
12
+ const rootPrefix = `${args.root.path}/`;
13
+ return descendantsOf(args.nodes, args.root).map((node) => {
14
+ const suffix = node.id === args.root.id ? '' : node.path.slice(rootPrefix.length);
15
+ const toPath = suffix ? `${newRootPath}/${suffix}` : newRootPath;
16
+ return {
17
+ id: node.id,
18
+ fromPath: node.path,
19
+ toPath,
20
+ };
21
+ });
22
+ }
23
+ function parentPathOf(path) {
24
+ const segments = path.split('/');
25
+ if (segments.length <= 1) {
26
+ return null;
27
+ }
28
+ return segments.slice(0, -1).join('/');
29
+ }
30
+ function parentIdForTargetPath(args) {
31
+ const parentPath = parentPathOf(args.change.toPath);
32
+ if (!parentPath) {
33
+ return null;
34
+ }
35
+ const key = normalizeBoxLookupKey(parentPath);
36
+ const changedParent = args.changesByPath.get(key);
37
+ if (changedParent) {
38
+ return changedParent.id;
39
+ }
40
+ return args.activeNodesByPath.get(key)?.id ?? args.fallbackParentId;
41
+ }
42
+ async function applySubtreePathChanges(args) {
43
+ const changesByPath = new Map(args.changes.map((change) => [normalizeBoxLookupKey(change.toPath), change]));
44
+ const activeNodesByPath = activeNodeByPath(args.nodes);
45
+ for (const change of args.changes) {
46
+ const parentId = parentIdForTargetPath({
47
+ change,
48
+ changesByPath,
49
+ activeNodesByPath,
50
+ fallbackParentId: args.newRootParentId,
51
+ });
52
+ await args.db.execute(`
53
+ UPDATE c_zettel_box
54
+ SET name = ?, path = ?, parent_id = ?, updated_at = ?
55
+ WHERE id = ?
56
+ `, [getLeafName(change.toPath), change.toPath, parentId, args.timestamp, change.id]);
57
+ }
58
+ }
59
+ function parseRenameInput(input) {
60
+ const path = canonicalizeBoxPath(input.path);
61
+ const newName = canonicalizeBoxPath(input.newName);
62
+ const userId = trimString(input.userId);
63
+ if (!path) {
64
+ throw new DinoxError('Box path is required');
65
+ }
66
+ if (!newName || newName.includes('/')) {
67
+ throw new DinoxError('New box name must be a single path segment');
68
+ }
69
+ assertMaxLength('Box name', newName, MAX_BOX_NAME_LENGTH);
70
+ return { path, newName, userId };
71
+ }
72
+ function parseMoveInput(input) {
73
+ const path = canonicalizeBoxPath(input.path);
74
+ const to = canonicalizeBoxPath(input.to);
75
+ const userId = trimString(input.userId);
76
+ if (!path) {
77
+ throw new DinoxError('Box path is required');
78
+ }
79
+ if (!to) {
80
+ throw new DinoxError('Target parent path is required');
81
+ }
82
+ return { path, to, userId };
83
+ }
84
+ function parseMergeInput(input) {
85
+ const from = canonicalizeBoxPath(input.from);
86
+ const to = canonicalizeBoxPath(input.to);
87
+ const userId = trimString(input.userId);
88
+ if (!from) {
89
+ throw new DinoxError('Source box path is required');
90
+ }
91
+ if (!to) {
92
+ throw new DinoxError('Target box path is required');
93
+ }
94
+ return { from, to, userId };
95
+ }
96
+ export async function getBoxTree(db, input = {}) {
97
+ const nodes = activeBoxNodes(await loadAllBoxNodes(db, { userId: input.userId }));
98
+ const byId = new Map(nodes.map((node) => [node.id, { ...toBoxListItem(node), children: [] }]));
99
+ const roots = [];
100
+ for (const node of nodes) {
101
+ const treeNode = byId.get(node.id);
102
+ const parent = node.parentId ? byId.get(node.parentId) : null;
103
+ if (parent) {
104
+ parent.children.push(treeNode);
105
+ }
106
+ else {
107
+ roots.push(treeNode);
108
+ }
109
+ }
110
+ const sortTree = (items) => {
111
+ items.sort((left, right) => left.path.localeCompare(right.path));
112
+ for (const item of items) {
113
+ sortTree(item.children);
114
+ }
115
+ };
116
+ sortTree(roots);
117
+ return roots;
118
+ }
119
+ async function loadNoteBoxRows(db, userId) {
120
+ return db.getAll(`
121
+ SELECT
122
+ TRIM(COALESCE(id, '')) AS id,
123
+ title,
124
+ zettel_boxes,
125
+ is_del,
126
+ TRIM(COALESCE(user_no, '')) AS user_no
127
+ FROM c_note
128
+ WHERE TRIM(COALESCE(id, '')) <> ''
129
+ AND (is_del IS NULL OR is_del = 0)
130
+ AND (TRIM(COALESCE(user_no, '')) = ? OR TRIM(COALESCE(user_no, '')) = '')
131
+ `, [userId]);
132
+ }
133
+ async function loadNoteBoxStats(db, userId) {
134
+ const normalizedUserId = trimString(userId);
135
+ const userFilter = normalizedUserId
136
+ ? `AND (TRIM(COALESCE(n.user_no, '')) = ? OR TRIM(COALESCE(n.user_no, '')) = '')`
137
+ : '';
138
+ const rows = await db.getAll(`
139
+ SELECT
140
+ TRIM(CAST(box_item.value AS TEXT)) AS box_id,
141
+ COUNT(DISTINCT n.id) AS note_count,
142
+ MAX(COALESCE(n.updated_at, n.created_at)) AS latest_note_updated_at
143
+ FROM c_note n,
144
+ json_each(
145
+ CASE
146
+ WHEN json_valid(COALESCE(n.zettel_boxes, '')) THEN n.zettel_boxes
147
+ ELSE '[]'
148
+ END
149
+ ) box_item
150
+ WHERE (n.is_del IS NULL OR n.is_del = 0)
151
+ ${userFilter}
152
+ AND TRIM(CAST(box_item.value AS TEXT)) <> ''
153
+ GROUP BY TRIM(CAST(box_item.value AS TEXT))
154
+ `, normalizedUserId ? [normalizedUserId] : []);
155
+ const stats = new Map();
156
+ for (const row of rows) {
157
+ const id = trimString(row.box_id);
158
+ if (!id) {
159
+ continue;
160
+ }
161
+ stats.set(id, {
162
+ directNoteCount: Number(row.note_count ?? 0),
163
+ latestNoteUpdatedAt: row.latest_note_updated_at ?? null,
164
+ });
165
+ }
166
+ return stats;
167
+ }
168
+ export async function getBoxStats(db, input = {}) {
169
+ const nodes = activeBoxNodes(await loadAllBoxNodes(db, { userId: input.userId }));
170
+ const statsById = await loadNoteBoxStats(db, input.userId);
171
+ const descendantsById = new Map();
172
+ for (const node of nodes) {
173
+ descendantsById.set(node.id, descendantsOf(nodes, node));
174
+ }
175
+ const boxes = nodes.map((node) => {
176
+ const direct = statsById.get(node.id);
177
+ const descendantNodes = descendantsById.get(node.id) ?? [node];
178
+ let descendantNoteCount = 0;
179
+ let latestNoteUpdatedAt = direct?.latestNoteUpdatedAt ?? null;
180
+ for (const descendant of descendantNodes) {
181
+ const stats = statsById.get(descendant.id);
182
+ descendantNoteCount += stats?.directNoteCount ?? 0;
183
+ if (stats?.latestNoteUpdatedAt && (!latestNoteUpdatedAt || stats.latestNoteUpdatedAt > latestNoteUpdatedAt)) {
184
+ latestNoteUpdatedAt = stats.latestNoteUpdatedAt;
185
+ }
186
+ }
187
+ return {
188
+ ...toBoxListItem(node),
189
+ directNoteCount: direct?.directNoteCount ?? 0,
190
+ descendantNoteCount,
191
+ latestNoteUpdatedAt,
192
+ isEmpty: descendantNoteCount === 0,
193
+ };
194
+ });
195
+ boxes.sort((left, right) => left.path.localeCompare(right.path));
196
+ return {
197
+ totalBoxes: boxes.length,
198
+ emptyBoxes: boxes.filter((box) => box.isEmpty).length,
199
+ boxes,
200
+ };
201
+ }
202
+ export async function inspectBoxCleanup(db, input = {}) {
203
+ const nodes = await loadAllBoxNodes(db, { userId: input.userId });
204
+ const stats = await getBoxStats(db, input);
205
+ const statsById = new Map(stats.boxes.map((box) => [box.id, box]));
206
+ const active = activeBoxNodes(nodes);
207
+ const activeIds = new Set(active.map((node) => node.id));
208
+ const issues = [];
209
+ for (const node of active) {
210
+ const boxStats = statsById.get(node.id);
211
+ if (boxStats?.isEmpty) {
212
+ issues.push({
213
+ type: 'empty_box',
214
+ id: node.id,
215
+ path: node.path,
216
+ name: node.name,
217
+ parentId: node.parentId,
218
+ detail: 'Box has no notes in itself or descendants.',
219
+ });
220
+ }
221
+ if (node.parentId && !activeIds.has(node.parentId)) {
222
+ issues.push({
223
+ type: 'orphan_parent',
224
+ id: node.id,
225
+ path: node.path,
226
+ name: node.name,
227
+ parentId: node.parentId,
228
+ detail: `Parent box is missing or deleted: ${node.parentId}`,
229
+ });
230
+ }
231
+ }
232
+ const byPath = new Map();
233
+ for (const node of active) {
234
+ const key = normalizeBoxLookupKey(node.path);
235
+ byPath.set(key, [...(byPath.get(key) ?? []), node]);
236
+ }
237
+ for (const duplicates of byPath.values()) {
238
+ if (duplicates.length <= 1) {
239
+ continue;
240
+ }
241
+ for (const node of duplicates) {
242
+ issues.push({
243
+ type: 'duplicate_path',
244
+ id: node.id,
245
+ path: node.path,
246
+ name: node.name,
247
+ parentId: node.parentId,
248
+ duplicateIds: duplicates.map((item) => item.id),
249
+ detail: `Active duplicate path appears ${duplicates.length} times.`,
250
+ });
251
+ }
252
+ }
253
+ const activeChildrenByDeletedParent = new Map();
254
+ for (const child of active) {
255
+ if (!child.parentId) {
256
+ continue;
257
+ }
258
+ const parent = nodes.find((node) => node.id === child.parentId);
259
+ if (parent && !isActiveBoxNode(parent)) {
260
+ activeChildrenByDeletedParent.set(parent.id, [...(activeChildrenByDeletedParent.get(parent.id) ?? []), child]);
261
+ }
262
+ }
263
+ for (const [parentId, children] of activeChildrenByDeletedParent.entries()) {
264
+ const parent = nodes.find((node) => node.id === parentId);
265
+ issues.push({
266
+ type: 'deleted_with_active_children',
267
+ id: parent.id,
268
+ path: parent.path,
269
+ name: parent.name,
270
+ parentId: parent.parentId,
271
+ childIds: children.map((child) => child.id),
272
+ detail: 'Deleted box still has active children.',
273
+ });
274
+ }
275
+ issues.sort((left, right) => `${left.type}:${left.path}:${left.id}`.localeCompare(`${right.type}:${right.path}:${right.id}`));
276
+ return {
277
+ issues,
278
+ emptyBoxes: issues.filter((issue) => issue.type === 'empty_box').length,
279
+ duplicatePaths: issues.filter((issue) => issue.type === 'duplicate_path').length,
280
+ orphanParents: issues.filter((issue) => issue.type === 'orphan_parent').length,
281
+ deletedWithActiveChildren: issues.filter((issue) => issue.type === 'deleted_with_active_children').length,
282
+ };
283
+ }
284
+ export async function renameBox(db, input, options = {}) {
285
+ const parsed = parseRenameInput(input);
286
+ const columns = await getTableColumns(db, 'c_zettel_box');
287
+ assertCanWriteBox(columns, parsed.userId, 'update');
288
+ const nodes = await loadAllBoxNodes(db, { userId: parsed.userId });
289
+ const root = requireActivePath(nodes, parsed.path, 'Box path');
290
+ const parentPath = root.path.includes('/') ? root.path.split('/').slice(0, -1).join('/') : '';
291
+ const toPath = parentPath ? `${parentPath}/${parsed.newName}` : parsed.newName;
292
+ const changes = buildSubtreeChanges({ nodes, root, newRootPath: toPath });
293
+ ensureNoPathConflict(nodes, changes);
294
+ assertWritableBoxNodes(nodes, new Set(changes.map((change) => change.id)), parsed.userId);
295
+ if (!options.dryRun) {
296
+ await withPowerSyncWriteTransaction(db, async (tx) => {
297
+ await applySubtreePathChanges({
298
+ db: tx,
299
+ nodes,
300
+ changes,
301
+ newRootParentId: root.parentId,
302
+ timestamp: nowIsoUtc(),
303
+ });
304
+ });
305
+ }
306
+ return {
307
+ id: root.id,
308
+ fromPath: root.path,
309
+ toPath,
310
+ updatedBoxes: changes,
311
+ };
312
+ }
313
+ export async function moveBox(db, input, options = {}) {
314
+ const parsed = parseMoveInput(input);
315
+ const columns = await getTableColumns(db, 'c_zettel_box');
316
+ assertCanWriteBox(columns, parsed.userId, 'update');
317
+ const nodes = await loadAllBoxNodes(db, { userId: parsed.userId });
318
+ const root = requireActivePath(nodes, parsed.path, 'Box path');
319
+ const targetParent = requireActivePath(nodes, parsed.to, 'Target parent path');
320
+ if (root.id === targetParent.id || isDescendantBoxPath(targetParent.path, root.path)) {
321
+ throw new DinoxError('Cannot move a zettel box under itself or one of its descendants');
322
+ }
323
+ const toPath = `${targetParent.path}/${root.name}`;
324
+ const changes = buildSubtreeChanges({ nodes, root, newRootPath: toPath });
325
+ ensureNoPathConflict(nodes, changes);
326
+ assertWritableBoxNodes(nodes, new Set(changes.map((change) => change.id)), parsed.userId);
327
+ if (!options.dryRun) {
328
+ await withPowerSyncWriteTransaction(db, async (tx) => {
329
+ await applySubtreePathChanges({
330
+ db: tx,
331
+ nodes,
332
+ changes,
333
+ newRootParentId: targetParent.id,
334
+ timestamp: nowIsoUtc(),
335
+ });
336
+ });
337
+ }
338
+ return {
339
+ id: root.id,
340
+ fromPath: root.path,
341
+ toPath,
342
+ updatedBoxes: changes,
343
+ };
344
+ }
345
+ function remapNoteBoxIds(current, sourceIds, targetId) {
346
+ const next = [];
347
+ const seen = new Set();
348
+ for (const id of current) {
349
+ const mapped = sourceIds.has(id) ? targetId : id;
350
+ if (!mapped || seen.has(mapped)) {
351
+ continue;
352
+ }
353
+ seen.add(mapped);
354
+ next.push(mapped);
355
+ }
356
+ return next;
357
+ }
358
+ function sameIds(left, right) {
359
+ if (left.length !== right.length) {
360
+ return false;
361
+ }
362
+ return left.every((value, index) => value === right[index]);
363
+ }
364
+ export async function mergeBox(db, input, options = {}) {
365
+ const parsed = parseMergeInput(input);
366
+ const boxColumns = await getTableColumns(db, 'c_zettel_box');
367
+ const noteColumns = await getTableColumns(db, 'c_note');
368
+ assertCanWriteBox(boxColumns, parsed.userId, 'update');
369
+ assertRequiredColumns('c_note', noteColumns, REQUIRED_NOTE_BOX_COLUMNS);
370
+ const nodes = await loadAllBoxNodes(db, { userId: parsed.userId });
371
+ const source = requireActivePath(nodes, parsed.from, 'Source box path');
372
+ const target = requireActivePath(nodes, parsed.to, 'Target box path');
373
+ if (source.id === target.id || isDescendantBoxPath(target.path, source.path)) {
374
+ throw new DinoxError('Cannot merge a zettel box into itself or one of its descendants');
375
+ }
376
+ const sourceNodes = descendantsOf(nodes, source);
377
+ const sourceIds = new Set(sourceNodes.map((node) => node.id));
378
+ assertWritableBoxNodes(nodes, new Set([...sourceIds, target.id]), parsed.userId);
379
+ const noteRows = await loadNoteBoxRows(db, parsed.userId);
380
+ const updatedNotes = noteRows
381
+ .map((row) => {
382
+ const before = parseStoredBoxIds(row.zettel_boxes);
383
+ const after = remapNoteBoxIds(before, sourceIds, target.id);
384
+ return { id: trimString(row.id), before, after };
385
+ })
386
+ .filter((row) => row.id && !sameIds(row.before, row.after));
387
+ const softDeletedBoxIds = sourceNodes.map((node) => node.id);
388
+ if (!options.dryRun) {
389
+ await withPowerSyncWriteTransaction(db, async (tx) => {
390
+ const timestamp = nowIsoUtc();
391
+ for (const note of updatedNotes) {
392
+ await tx.execute(`
393
+ UPDATE c_note
394
+ SET zettel_boxes = ?, updated_at = ?, version = COALESCE(version, 0) + 1
395
+ WHERE id = ?
396
+ `, [JSON.stringify(note.after), timestamp, note.id]);
397
+ }
398
+ for (const boxId of softDeletedBoxIds) {
399
+ await tx.execute(`
400
+ UPDATE c_zettel_box
401
+ SET is_del = 1, updated_at = ?
402
+ WHERE id = ?
403
+ `, [timestamp, boxId]);
404
+ }
405
+ });
406
+ }
407
+ return {
408
+ fromId: source.id,
409
+ toId: target.id,
410
+ fromPath: source.path,
411
+ toPath: target.path,
412
+ softDeletedBoxIds,
413
+ updatedNotes,
414
+ };
415
+ }
@@ -1,29 +1,36 @@
1
1
  import type { AbstractPowerSyncDatabase } from '@powersync/common';
2
- export type BoxListItem = {
3
- id: string;
4
- name: string;
5
- description: string;
6
- };
2
+ import type { BoxListItem } from './model.js';
3
+ export { canonicalizeBoxPath } from './model.js';
7
4
  export type AddBoxInput = {
8
5
  name: string;
9
6
  userId: string;
10
7
  description?: string;
11
8
  color?: string;
12
9
  };
10
+ export type ListBoxesInput = {
11
+ userId?: string;
12
+ };
13
13
  export type AddBoxResult = {
14
14
  id: string;
15
15
  name: string;
16
+ path: string;
17
+ parentId: string | null;
16
18
  description: string;
17
19
  color: string;
18
20
  restored: boolean;
21
+ createdNodes: number;
22
+ restoredNodes: number;
19
23
  };
20
24
  export type InspectAddBoxResult = {
21
25
  name: string;
26
+ path: string;
22
27
  description: string;
23
28
  color: string;
24
29
  restored: boolean;
30
+ createdPaths: string[];
31
+ restoredPaths: string[];
25
32
  existingId?: string;
26
33
  };
27
- export declare function listBoxes(db: AbstractPowerSyncDatabase): Promise<BoxListItem[]>;
34
+ export declare function listBoxes(db: AbstractPowerSyncDatabase, input?: ListBoxesInput): Promise<BoxListItem[]>;
28
35
  export declare function addBox(db: AbstractPowerSyncDatabase, input: AddBoxInput): Promise<AddBoxResult>;
29
36
  export declare function inspectAddBox(db: AbstractPowerSyncDatabase, input: AddBoxInput): Promise<InspectAddBoxResult>;