@lapis-notes/api 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/CHANGELOG.md +304 -13
  2. package/README.md +19 -0
  3. package/dist/__tests__/fixtures/indexed-mutations.json +6862 -0
  4. package/dist/__tests__/fixtures/memory-storage.json +309 -0
  5. package/dist/__tests__/fixtures/native-facade-contract.json +3224 -0
  6. package/dist/__tests__/fixtures/projection-query.json +195 -0
  7. package/dist/__tests__/fixtures/projection-values.json +60 -0
  8. package/dist/__tests__/fixtures/search-preparation.json +1513 -0
  9. package/dist/__tests__/fixtures/search-retrieval.json +15409 -0
  10. package/dist/__tests__/fixtures/search-semantic-model.json +3691 -0
  11. package/dist/__tests__/fixtures/search-semantic-retrieval.json +6603 -0
  12. package/dist/__tests__/fixtures/search-storage.json +409 -0
  13. package/dist/__tests__/fixtures/task-projection.json +428 -0
  14. package/dist/__tests__/indexed-mutation-support.js +262 -0
  15. package/dist/__tests__/projection-query-support.js +40 -0
  16. package/dist/__tests__/search-retrieval-support.js +47 -0
  17. package/dist/app-database-host.d.ts +1 -0
  18. package/dist/app-shell-plugin-persistence.d.ts +3 -2
  19. package/dist/app-shell-plugin-persistence.js +37 -3
  20. package/dist/cache.svelte.d.ts +8 -1
  21. package/dist/cache.svelte.js +103 -5
  22. package/dist/command.svelte.js +29 -2
  23. package/dist/components/editor/editor.css +4 -0
  24. package/dist/components/editor/editor.svelte +24 -11
  25. package/dist/components/editor/embedded-editor-surface.js +3 -1
  26. package/dist/components/editor/inline-title-alignment.d.ts +3 -0
  27. package/dist/components/editor/inline-title-alignment.js +57 -0
  28. package/dist/configuration.svelte.d.ts +270 -206
  29. package/dist/configuration.svelte.js +161 -86
  30. package/dist/context.svelte.d.ts +23 -3
  31. package/dist/context.svelte.js +68 -30
  32. package/dist/diagnostics.d.ts +8 -0
  33. package/dist/diagnostics.js +6 -0
  34. package/dist/editor-save-context.d.ts +35 -0
  35. package/dist/editor-save-context.js +132 -0
  36. package/dist/editor-view-registry.d.ts +10 -0
  37. package/dist/editor-view-registry.js +44 -4
  38. package/dist/editor.svelte.d.ts +19 -1
  39. package/dist/editor.svelte.js +528 -55
  40. package/dist/embed-registry.d.ts +10 -0
  41. package/dist/embed-registry.js +15 -0
  42. package/dist/file-editing-failures.d.ts +2 -0
  43. package/dist/file-editing-failures.js +29 -0
  44. package/dist/file-editing-native-issues.d.ts +19 -0
  45. package/dist/file-editing-native-issues.js +65 -0
  46. package/dist/file-editing-sessions.d.ts +76 -0
  47. package/dist/file-editing-sessions.js +367 -0
  48. package/dist/file-manager.d.ts +9 -1
  49. package/dist/file-manager.js +45 -3
  50. package/dist/file-state-store.d.ts +5 -0
  51. package/dist/file-state-store.js +34 -0
  52. package/dist/file-text-conflicts.d.ts +25 -0
  53. package/dist/file-text-conflicts.js +35 -0
  54. package/dist/file-text-mutation.d.ts +13 -0
  55. package/dist/file-text-mutation.js +100 -0
  56. package/dist/file-text-persistence.d.ts +36 -0
  57. package/dist/file-text-persistence.js +234 -0
  58. package/dist/file-text-state-writer.d.ts +34 -0
  59. package/dist/file-text-state-writer.js +183 -0
  60. package/dist/files-configuration.d.ts +20 -0
  61. package/dist/files-configuration.js +47 -0
  62. package/dist/generated/plugin-host-modules.schema.generated.d.ts +114 -34
  63. package/dist/generated/plugin-host-modules.schema.generated.js +132 -34
  64. package/dist/glob.d.ts +3 -0
  65. package/dist/glob.js +2 -1
  66. package/dist/icons/changes.d.ts +3 -0
  67. package/dist/icons/changes.js +16 -0
  68. package/dist/icons/index.d.ts +5 -1
  69. package/dist/icons/index.js +44 -3
  70. package/dist/icons/registry.d.ts +35 -0
  71. package/dist/icons/registry.js +154 -0
  72. package/dist/icons/safe-svg.d.ts +2 -0
  73. package/dist/icons/safe-svg.js +44 -0
  74. package/dist/index.d.ts +6 -1
  75. package/dist/index.js +4 -1
  76. package/dist/lapis-extension.d.ts +6 -2
  77. package/dist/lapis-extension.js +2 -0
  78. package/dist/metadata-store.d.ts +23 -0
  79. package/dist/metadata-store.js +1 -0
  80. package/dist/metadata.svelte.js +45 -2
  81. package/dist/native-background-indexing.d.ts +48 -0
  82. package/dist/native-background-indexing.js +208 -0
  83. package/dist/native-database-protocol.d.ts +29 -0
  84. package/dist/native-database-protocol.js +1 -0
  85. package/dist/native-editing-intent-lease.d.ts +17 -0
  86. package/dist/native-editing-intent-lease.js +188 -0
  87. package/dist/native-editing-intents-protocol.d.ts +70 -0
  88. package/dist/native-editing-intents-protocol.js +1 -0
  89. package/dist/native-editing-intents.d.ts +8 -0
  90. package/dist/native-editing-intents.js +1 -0
  91. package/dist/native-editing-problems.d.ts +3 -0
  92. package/dist/native-editing-problems.js +180 -0
  93. package/dist/native-editing-recovery.d.ts +24 -0
  94. package/dist/native-editing-recovery.js +198 -0
  95. package/dist/native-editing-session.d.ts +51 -0
  96. package/dist/native-editing-session.js +251 -0
  97. package/dist/native-history-index-protocol.d.ts +80 -0
  98. package/dist/native-history-index-protocol.js +1 -0
  99. package/dist/native-history-index.d.ts +6 -0
  100. package/dist/native-history-index.js +1 -0
  101. package/dist/native-indexing-protocol.d.ts +63 -0
  102. package/dist/native-indexing-protocol.js +1 -0
  103. package/dist/native-participant-protocol.d.ts +67 -0
  104. package/dist/native-participant-protocol.js +3 -0
  105. package/dist/native-queue-protocol.d.ts +73 -0
  106. package/dist/native-queue-protocol.js +3 -0
  107. package/dist/native-tasks-protocol.d.ts +264 -0
  108. package/dist/native-tasks-protocol.js +1 -0
  109. package/dist/native-tasks.d.ts +35 -0
  110. package/dist/native-tasks.js +79 -0
  111. package/dist/native-turn-protocol.d.ts +81 -0
  112. package/dist/native-turn-protocol.js +1 -0
  113. package/dist/native-turns.d.ts +29 -0
  114. package/dist/native-turns.js +2 -0
  115. package/dist/plugin-asset-server.js +3 -2
  116. package/dist/plugin-dependency-resolver.d.ts +1 -1
  117. package/dist/plugin-distribution/compatibility.d.ts +1 -1
  118. package/dist/plugin-distribution/compatibility.js +10 -5
  119. package/dist/plugin-distribution/installed-plugin-state.js +2 -1
  120. package/dist/plugin-distribution/installer.d.ts +6 -0
  121. package/dist/plugin-distribution/installer.js +90 -37
  122. package/dist/plugin-distribution/manager.d.ts +4 -1
  123. package/dist/plugin-distribution/manager.js +12 -5
  124. package/dist/plugin-distribution/registry-cache.js +2 -1
  125. package/dist/plugin-distribution/registry-source-state.js +2 -1
  126. package/dist/plugin-distribution/schemas.d.ts +26 -8
  127. package/dist/plugin-distribution/schemas.js +2 -1
  128. package/dist/plugin-distribution/types.d.ts +4 -0
  129. package/dist/plugin-manager.d.ts +21 -5
  130. package/dist/plugin-manager.js +228 -64
  131. package/dist/plugin-runtime-entry.d.ts +1 -1
  132. package/dist/plugin-runtime-entry.js +16 -0
  133. package/dist/plugin.d.ts +19 -3
  134. package/dist/plugin.js +110 -44
  135. package/dist/registry-schema/catalog-v1.d.ts +60 -9
  136. package/dist/registry-schema/catalog-v1.js +2 -1
  137. package/dist/registry-schema/catalog-v2.d.ts +60 -9
  138. package/dist/registry-schema/catalog-v2.js +1 -1
  139. package/dist/search-result-provider.d.ts +95 -0
  140. package/dist/search-result-provider.js +42 -0
  141. package/dist/status-bar.svelte.d.ts +26 -20
  142. package/dist/status-bar.svelte.js +1 -0
  143. package/dist/storage/app-database.d.ts +9 -23
  144. package/dist/storage/app-database.js +41 -34
  145. package/dist/storage/desktop-native.d.ts +5 -3
  146. package/dist/storage/desktop-native.js +59 -6
  147. package/dist/storage/directory-watcher.d.ts +27 -0
  148. package/dist/storage/directory-watcher.js +201 -0
  149. package/dist/storage/fs.d.ts +14 -27
  150. package/dist/storage/fs.js +2 -168
  151. package/dist/storage/index-projection.js +33 -15
  152. package/dist/storage/memory-vault-adapter.d.ts +2 -0
  153. package/dist/storage/memory-vault-adapter.js +14 -1
  154. package/dist/storage/path.d.ts +6 -2
  155. package/dist/storage/path.js +8 -2
  156. package/dist/storage/projection-query-candidates.d.ts +3 -0
  157. package/dist/storage/projection-query-candidates.js +69 -0
  158. package/dist/storage/remote-app-database.d.ts +2 -2
  159. package/dist/storage/remote-app-database.js +1 -1
  160. package/dist/storage/runtime.d.ts +3 -0
  161. package/dist/storage/runtime.js +3 -0
  162. package/dist/storage/search-embedding-record.d.ts +3 -0
  163. package/dist/storage/search-embedding-record.js +18 -0
  164. package/dist/storage/turso-app-database.d.ts +2 -0
  165. package/dist/storage/turso-app-database.js +67 -30
  166. package/dist/storage/vault-listing.d.ts +3 -0
  167. package/dist/storage/vault-listing.js +36 -0
  168. package/dist/storage/vault-reconciliation.d.ts +19 -0
  169. package/dist/storage/vault-reconciliation.js +137 -0
  170. package/dist/storage/vault-session.d.ts +8 -0
  171. package/dist/storage/vault-session.js +10 -2
  172. package/dist/storage/vault.svelte.d.ts +53 -4
  173. package/dist/storage/vault.svelte.js +223 -87
  174. package/dist/sync-editor-flush.d.ts +6 -0
  175. package/dist/sync-editor-flush.js +22 -0
  176. package/dist/sync-host-local.d.ts +15 -0
  177. package/dist/sync-host-local.js +228 -0
  178. package/dist/sync-host-security.d.ts +24 -9
  179. package/dist/sync-host-security.js +47 -14
  180. package/dist/sync-host.d.ts +33 -4
  181. package/dist/sync-host.js +160 -10
  182. package/dist/sync-repository.d.ts +106 -0
  183. package/dist/sync-repository.js +18 -0
  184. package/dist/vault-change-views.d.ts +4 -0
  185. package/dist/vault-change-views.js +43 -0
  186. package/dist/vault-changes.d.ts +37 -0
  187. package/dist/vault-changes.js +228 -0
  188. package/dist/view.svelte.d.ts +182 -149
  189. package/dist/view.svelte.js +39 -21
  190. package/dist/workspace-close-guard.d.ts +3 -0
  191. package/dist/workspace-close-guard.js +35 -0
  192. package/dist/workspace-host-internal.js +10 -2
  193. package/dist/workspace-layout-normalizer.d.ts +4 -2
  194. package/dist/workspace-layout-normalizer.js +5 -5
  195. package/dist/workspace-view-document.d.ts +3 -0
  196. package/dist/workspace-view-document.js +12 -0
  197. package/dist/workspace.svelte.d.ts +13 -2
  198. package/dist/workspace.svelte.js +371 -82
  199. package/package.json +61 -8
@@ -0,0 +1,428 @@
1
+ {
2
+ "records": [
3
+ {
4
+ "documentPath": "tasks/full.md",
5
+ "documentId": "full",
6
+ "kind": "task",
7
+ "title": "Full task",
8
+ "status": "open",
9
+ "inbox": false,
10
+ "startKind": "anytime",
11
+ "checklistTotal": 4.0,
12
+ "checklistCompleted": 1.0,
13
+ "commentCount": 2.0,
14
+ "projectionVersion": 4.0,
15
+ "priority": "high",
16
+ "startDate": null,
17
+ "planDate": "2026-10-24",
18
+ "planKind": "time",
19
+ "planTime": "09:30",
20
+ "durationMinutes": 45.0,
21
+ "deadline": "2026-10-30",
22
+ "completedAt": null,
23
+ "repeat": {
24
+ "start": "2026-10-01",
25
+ "rrule": "FREQ=WEEKLY;BYDAY=MO,FR",
26
+ "anchor": "schedule",
27
+ "missed": "carry",
28
+ "rdate": ["2026-11-01"],
29
+ "exdate": ["2026-11-02"],
30
+ "resetChecklist": true,
31
+ "paused": false,
32
+ "pausedSince": "2026-10-02",
33
+ "pauseRanges": [
34
+ {
35
+ "start": "2026-10-02",
36
+ "end": "2026-10-03"
37
+ }
38
+ ],
39
+ "lastCompletedAt": "2026-10-20T12:00:00Z",
40
+ "completionCount": 3.0
41
+ },
42
+ "tracking": {
43
+ "type": "count",
44
+ "unit": "pages",
45
+ "target": 20.0
46
+ },
47
+ "effectiveOccurrenceDate": "2026-10-24",
48
+ "effectiveOccurrenceState": "current",
49
+ "effectiveForDate": "2026-10-24",
50
+ "repeatStrategy": null,
51
+ "repeatFrequency": "weekly",
52
+ "repeatInterval": 2.0,
53
+ "repeatAnchor": "schedule",
54
+ "structure": {
55
+ "version": 1.0,
56
+ "sourceHash": "hash",
57
+ "entries": [
58
+ {
59
+ "sourceDocumentId": "full",
60
+ "sourceDocumentPath": "tasks/full.md",
61
+ "targetDocumentId": "child",
62
+ "targetDocumentPath": "tasks/child.md",
63
+ "kind": "task-entry",
64
+ "headingPath": ["Tasks"],
65
+ "headingLevel": 2.0,
66
+ "headingText": "Tasks",
67
+ "runId": "run",
68
+ "positionInRun": 0.0,
69
+ "sourceStart": 10.0,
70
+ "sourceEnd": 30.0,
71
+ "authoredLabel": "Child",
72
+ "authoredHref": "child.md"
73
+ }
74
+ ],
75
+ "runs": [
76
+ {
77
+ "id": "run",
78
+ "documentId": "full",
79
+ "documentPath": "tasks/full.md",
80
+ "headingPath": ["Tasks"],
81
+ "headingLevel": null,
82
+ "headingText": null,
83
+ "listDepth": 0.0,
84
+ "startOffset": 10.0,
85
+ "endOffset": 30.0,
86
+ "entryCount": 1.0
87
+ }
88
+ ],
89
+ "diagnostics": [
90
+ {
91
+ "code": "sample",
92
+ "message": "retained",
93
+ "sourceStart": 10.0,
94
+ "sourceEnd": 30.0,
95
+ "target": "child"
96
+ }
97
+ ]
98
+ }
99
+ },
100
+ {
101
+ "documentPath": "tasks/inbox.md",
102
+ "documentId": "inbox",
103
+ "kind": "task",
104
+ "title": "inbox",
105
+ "status": "open",
106
+ "inbox": true,
107
+ "startKind": "anytime",
108
+ "checklistTotal": 4.0,
109
+ "checklistCompleted": 1.0,
110
+ "commentCount": 2.0,
111
+ "projectionVersion": 4.0
112
+ },
113
+ {
114
+ "documentPath": "tasks/overdue.md",
115
+ "documentId": "overdue",
116
+ "kind": "task",
117
+ "title": "overdue",
118
+ "status": "open",
119
+ "inbox": false,
120
+ "startKind": "anytime",
121
+ "checklistTotal": 4.0,
122
+ "checklistCompleted": 1.0,
123
+ "commentCount": 2.0,
124
+ "projectionVersion": 4.0,
125
+ "planDate": "2026-10-01",
126
+ "effectiveOccurrenceState": "overdue",
127
+ "effectiveOccurrenceDate": "2026-10-23",
128
+ "effectiveForDate": "2026-10-24"
129
+ },
130
+ {
131
+ "documentPath": "tasks/future.md",
132
+ "documentId": "future",
133
+ "kind": "task",
134
+ "title": "future",
135
+ "status": "open",
136
+ "inbox": false,
137
+ "startKind": "anytime",
138
+ "checklistTotal": 4.0,
139
+ "checklistCompleted": 1.0,
140
+ "commentCount": 2.0,
141
+ "projectionVersion": 4.0,
142
+ "planDate": "2026-10-01",
143
+ "effectiveOccurrenceState": "future",
144
+ "effectiveOccurrenceDate": "2026-10-26",
145
+ "effectiveForDate": "2026-10-24"
146
+ },
147
+ {
148
+ "documentPath": "tasks/carried.md",
149
+ "documentId": "carried",
150
+ "kind": "task",
151
+ "title": "carried",
152
+ "status": "open",
153
+ "inbox": false,
154
+ "startKind": "date",
155
+ "checklistTotal": 4.0,
156
+ "checklistCompleted": 1.0,
157
+ "commentCount": 2.0,
158
+ "projectionVersion": 4.0,
159
+ "planDate": "2026-10-20",
160
+ "startDate": "2026-10-01"
161
+ },
162
+ {
163
+ "documentPath": "tasks/someday.md",
164
+ "documentId": "someday",
165
+ "kind": "task",
166
+ "title": "someday",
167
+ "status": "open",
168
+ "inbox": false,
169
+ "startKind": "someday",
170
+ "checklistTotal": 4.0,
171
+ "checklistCompleted": 1.0,
172
+ "commentCount": 2.0,
173
+ "projectionVersion": 4.0
174
+ },
175
+ {
176
+ "documentPath": "tasks/completed.md",
177
+ "documentId": "completed",
178
+ "kind": "task",
179
+ "title": "completed",
180
+ "status": "completed",
181
+ "inbox": false,
182
+ "startKind": "anytime",
183
+ "checklistTotal": 4.0,
184
+ "checklistCompleted": 1.0,
185
+ "commentCount": 2.0,
186
+ "projectionVersion": 4.0,
187
+ "completedAt": "2026-10-22"
188
+ },
189
+ {
190
+ "documentPath": "tasks/list.md",
191
+ "documentId": "list",
192
+ "kind": "task-list",
193
+ "title": "list",
194
+ "status": "active",
195
+ "inbox": false,
196
+ "startKind": "anytime",
197
+ "checklistTotal": 4.0,
198
+ "checklistCompleted": 1.0,
199
+ "commentCount": 2.0,
200
+ "projectionVersion": 4.0
201
+ },
202
+ {
203
+ "documentPath": "tasks/deadline.md",
204
+ "documentId": "deadline",
205
+ "kind": "task",
206
+ "title": "deadline",
207
+ "status": "open",
208
+ "inbox": false,
209
+ "startKind": "date",
210
+ "checklistTotal": 4.0,
211
+ "checklistCompleted": 1.0,
212
+ "commentCount": 2.0,
213
+ "projectionVersion": 4.0,
214
+ "deadline": "2026-10-23",
215
+ "startDate": "2026-10-30"
216
+ }
217
+ ],
218
+ "cases": [
219
+ {
220
+ "query": {
221
+ "view": "inbox",
222
+ "today": "2026-10-24"
223
+ },
224
+ "ids": ["inbox"]
225
+ },
226
+ {
227
+ "query": {
228
+ "view": "today",
229
+ "today": "2026-10-24"
230
+ },
231
+ "ids": ["carried", "deadline", "full"]
232
+ },
233
+ {
234
+ "query": {
235
+ "view": "anytime",
236
+ "today": "2026-10-24"
237
+ },
238
+ "ids": ["inbox"]
239
+ },
240
+ {
241
+ "query": {
242
+ "view": "upcoming",
243
+ "today": "2026-10-24"
244
+ },
245
+ "ids": ["deadline", "full", "future"]
246
+ },
247
+ {
248
+ "query": {
249
+ "view": "someday",
250
+ "today": "2026-10-24"
251
+ },
252
+ "ids": ["someday"]
253
+ },
254
+ {
255
+ "query": {
256
+ "view": "completed",
257
+ "today": "2026-10-24"
258
+ },
259
+ "ids": ["completed"]
260
+ },
261
+ {
262
+ "query": {
263
+ "view": "review",
264
+ "today": "2026-10-24"
265
+ },
266
+ "ids": ["carried", "overdue"]
267
+ },
268
+ {
269
+ "query": {
270
+ "documentId": "full"
271
+ },
272
+ "ids": ["full"]
273
+ },
274
+ {
275
+ "query": {
276
+ "documentPath": "tasks/full.md",
277
+ "kind": "task"
278
+ },
279
+ "ids": ["full"]
280
+ },
281
+ {
282
+ "query": {
283
+ "kind": "task-list"
284
+ },
285
+ "ids": ["list"]
286
+ },
287
+ {
288
+ "query": {
289
+ "view": "today",
290
+ "today": "2026-10-24",
291
+ "limit": 1
292
+ },
293
+ "ids": ["carried"]
294
+ }
295
+ ],
296
+ "fields": {
297
+ "documentPath": {
298
+ "type": "path",
299
+ "indexed": true,
300
+ "sortable": true
301
+ },
302
+ "documentId": {
303
+ "type": "string",
304
+ "indexed": true,
305
+ "unique": true
306
+ },
307
+ "kind": {
308
+ "type": "string",
309
+ "indexed": true
310
+ },
311
+ "title": {
312
+ "type": "string",
313
+ "indexed": true,
314
+ "sortable": true
315
+ },
316
+ "status": {
317
+ "type": "string",
318
+ "indexed": true,
319
+ "sortable": true
320
+ },
321
+ "priority": {
322
+ "type": "string",
323
+ "indexed": true,
324
+ "sortable": true
325
+ },
326
+ "inbox": {
327
+ "type": "boolean",
328
+ "indexed": true
329
+ },
330
+ "startKind": {
331
+ "type": "string",
332
+ "indexed": true
333
+ },
334
+ "startDate": {
335
+ "type": "date",
336
+ "indexed": true,
337
+ "sortable": true
338
+ },
339
+ "planDate": {
340
+ "type": "date",
341
+ "indexed": true,
342
+ "sortable": true
343
+ },
344
+ "planKind": {
345
+ "type": "string",
346
+ "indexed": true
347
+ },
348
+ "planTime": {
349
+ "type": "string",
350
+ "indexed": true,
351
+ "sortable": true
352
+ },
353
+ "durationMinutes": {
354
+ "type": "number",
355
+ "indexed": true,
356
+ "sortable": true
357
+ },
358
+ "deadline": {
359
+ "type": "date",
360
+ "indexed": true,
361
+ "sortable": true
362
+ },
363
+ "completedAt": {
364
+ "type": "string",
365
+ "indexed": true
366
+ },
367
+ "repeat": {
368
+ "type": "json"
369
+ },
370
+ "repeatStart": {
371
+ "type": "date",
372
+ "indexed": true,
373
+ "sortable": true
374
+ },
375
+ "repeatRRule": {
376
+ "type": "string",
377
+ "indexed": true
378
+ },
379
+ "repeatAnchor": {
380
+ "type": "string",
381
+ "indexed": true
382
+ },
383
+ "repeatMissed": {
384
+ "type": "string",
385
+ "indexed": true
386
+ },
387
+ "repeatPaused": {
388
+ "type": "boolean",
389
+ "indexed": true
390
+ },
391
+ "repeatPausedSince": {
392
+ "type": "date",
393
+ "indexed": true,
394
+ "sortable": true
395
+ },
396
+ "tracking": {
397
+ "type": "json"
398
+ },
399
+ "effectiveOccurrenceDate": {
400
+ "type": "date",
401
+ "indexed": true,
402
+ "sortable": true
403
+ },
404
+ "effectiveOccurrenceState": {
405
+ "type": "string",
406
+ "indexed": true,
407
+ "sortable": true
408
+ },
409
+ "effectiveForDate": {
410
+ "type": "date",
411
+ "indexed": true,
412
+ "sortable": true
413
+ },
414
+ "checklistTotal": {
415
+ "type": "number"
416
+ },
417
+ "checklistCompleted": {
418
+ "type": "number"
419
+ },
420
+ "commentCount": {
421
+ "type": "number",
422
+ "indexed": true
423
+ },
424
+ "structure": {
425
+ "type": "json"
426
+ }
427
+ }
428
+ }
@@ -0,0 +1,262 @@
1
+ import { connect } from "@tursodatabase/database";
2
+ import { TursoAppDatabase, } from "../storage/turso-app-database";
3
+ import tasks from "./fixtures/task-projection.json";
4
+ export const oldPath = "Notes/Öld.md";
5
+ export const newPath = "Archive/新.md";
6
+ export const refPath = "Links.md";
7
+ export function record(path, task = false) {
8
+ return {
9
+ file: {
10
+ path,
11
+ normalizedPath: path,
12
+ extension: ".MD",
13
+ mtime: 1,
14
+ size: 12,
15
+ hash: "hash-1",
16
+ indexed: true,
17
+ },
18
+ metadata: {
19
+ path,
20
+ hash: "hash-1",
21
+ parserVersion: "fixture",
22
+ metadata: { title: "Fixture 🪨" },
23
+ },
24
+ links: [
25
+ {
26
+ sourcePath: path,
27
+ targetText: "Old",
28
+ resolvedTargetPath: path === refPath ? oldPath : refPath,
29
+ type: "link",
30
+ count: 1,
31
+ kind: "reference",
32
+ },
33
+ ],
34
+ tags: [
35
+ {
36
+ path,
37
+ tag: "#Work/Notes",
38
+ parts: ["Work", "Notes"],
39
+ hierarchy: ["Work", "Work/Notes"],
40
+ },
41
+ ],
42
+ properties: [{ path, name: "Score", inferredType: "number", value: 1 }],
43
+ ...(task
44
+ ? {
45
+ task: {
46
+ ...tasks.records[0],
47
+ documentPath: path,
48
+ },
49
+ }
50
+ : {}),
51
+ };
52
+ }
53
+ export function scenarios() {
54
+ const changed = record(oldPath);
55
+ changed.file.hash = changed.metadata.hash = "changed";
56
+ changed.properties[0].value = 2;
57
+ const updated = record(oldPath, true);
58
+ updated.task.title = "Updated task";
59
+ return [
60
+ {
61
+ name: "omitted task preserves task",
62
+ steps: [{ kind: "upsert", record: changed }],
63
+ },
64
+ {
65
+ name: "task record updates stages",
66
+ steps: [{ kind: "upsert", record: updated }],
67
+ },
68
+ {
69
+ name: "null task removes only task projection",
70
+ steps: [{ kind: "upsert", record: { ...record(oldPath), task: null } }],
71
+ },
72
+ {
73
+ name: "rename all source domains and incoming references",
74
+ steps: [{ kind: "rename", oldPath, newPath }],
75
+ },
76
+ {
77
+ name: "delete all source-owned domains",
78
+ steps: [{ kind: "delete", path: oldPath }],
79
+ },
80
+ {
81
+ name: "missing rename is a no-op",
82
+ steps: [{ kind: "rename", oldPath: "Missing.md", newPath }],
83
+ },
84
+ {
85
+ name: "missing delete still commits domains",
86
+ steps: [{ kind: "delete", path: "Missing.md" }],
87
+ },
88
+ {
89
+ name: "rename then delete",
90
+ steps: [
91
+ { kind: "rename", oldPath, newPath },
92
+ { kind: "delete", path: newPath },
93
+ ],
94
+ },
95
+ {
96
+ name: "rename projection collision rolls back",
97
+ collision: true,
98
+ steps: [{ kind: "rename", oldPath, newPath }],
99
+ },
100
+ {
101
+ name: "same-path rename retains data",
102
+ steps: [{ kind: "rename", oldPath, newPath: oldPath }],
103
+ },
104
+ ];
105
+ }
106
+ export function seedInputs(collision = false) {
107
+ return {
108
+ indexed: [
109
+ record(oldPath, true),
110
+ record(refPath),
111
+ ...(collision ? [record(newPath)] : []),
112
+ ],
113
+ notebook: {
114
+ sourcePath: oldPath,
115
+ mtime: 1,
116
+ updatedAt: 2,
117
+ cells: {
118
+ a: {
119
+ state: "complete",
120
+ outputs: [{ kind: "text", value: "retained" }],
121
+ },
122
+ },
123
+ },
124
+ search: {
125
+ path: oldPath,
126
+ name: "Original",
127
+ extension: "md",
128
+ checksum: "hash-1",
129
+ content: "Retained search 🪨",
130
+ tags: ["work"],
131
+ tagParts: ["work"],
132
+ tagHierarchy: ["work"],
133
+ chunks: [
134
+ {
135
+ id: `${oldPath}#main`,
136
+ text: "Retained search 🪨",
137
+ startOffset: 0,
138
+ endOffset: 18,
139
+ embedding: {
140
+ status: "ready",
141
+ modelId: "fixture",
142
+ vector: [1, 0],
143
+ dimensions: 2,
144
+ updatedAt: 2,
145
+ },
146
+ },
147
+ ],
148
+ },
149
+ definition: {
150
+ projectionId: "fixture/items",
151
+ ownerPluginId: "fixture",
152
+ schemaVersion: 1,
153
+ configHash: "fixture-1",
154
+ visibility: "public",
155
+ fields: { label: { type: "string", sortable: true } },
156
+ active: true,
157
+ updatedAt: 1,
158
+ },
159
+ sources: [
160
+ [oldPath, "main"],
161
+ [refPath, "ref"],
162
+ ...(collision ? [[newPath, "destination"]] : []),
163
+ ].map(([path, id]) => ({
164
+ projectionId: "fixture/items",
165
+ sourcePath: path,
166
+ sourceHash: "hash-1",
167
+ rows: [{ id, kind: "item", data: { label: id } }],
168
+ edges: id === "ref"
169
+ ? [
170
+ {
171
+ sourceRowId: id,
172
+ relation: "reference",
173
+ targetPath: oldPath,
174
+ ordinal: 0,
175
+ },
176
+ ]
177
+ : [],
178
+ })),
179
+ };
180
+ }
181
+ export async function seed(db, input) {
182
+ for (const row of input.indexed)
183
+ await db.upsertIndexedFile(row);
184
+ await db.setNotebookState(input.notebook.sourcePath, input.notebook);
185
+ await db.upsertSearchDocument(input.search);
186
+ await db.registerProjectionDefinition(input.definition);
187
+ for (const row of input.sources)
188
+ await db.replaceProjectionSource(row);
189
+ }
190
+ export async function database(collision = false) {
191
+ const db = new TursoAppDatabase("indexed-mutations", {
192
+ kind: "turso-native",
193
+ transport: "native",
194
+ connectionFactory: async () => (await connect(":memory:", {
195
+ experimental: ["index_method"],
196
+ })),
197
+ });
198
+ await db.open();
199
+ await seed(db, seedInputs(collision));
200
+ return db;
201
+ }
202
+ export async function snapshot(db) {
203
+ const paths = await Promise.all([oldPath, newPath, refPath].map(async (path) => ({
204
+ path,
205
+ indexed: (await db.getIndexedFile(path)) ?? null,
206
+ notebook: (await db.getNotebookState(path)) ?? null,
207
+ task: (await db.getTaskRow({ path })) ?? null,
208
+ search: (await db.getSearchDocument(path)) ?? null,
209
+ incoming: await db.queryMetadataLinks({ direction: "incoming", path }),
210
+ })));
211
+ return JSON.parse(JSON.stringify({
212
+ paths,
213
+ manifest: await db.listIndexedFileManifest(),
214
+ searchManifest: await db.listSearchDocumentManifest(),
215
+ searchStats: await db.getSearchIndexStats(),
216
+ projection: await db.queryProjection("fixture/items", {
217
+ orderBy: [{ field: "id" }],
218
+ }),
219
+ stale: await db.queryProjection("fixture/items", {
220
+ includeStale: true,
221
+ orderBy: [{ field: "id" }],
222
+ }),
223
+ related: await db.queryRelated({
224
+ projectionId: "fixture/items",
225
+ rowId: "ref",
226
+ relation: "reference",
227
+ }),
228
+ revision: await db.getChangeRevision(),
229
+ }));
230
+ }
231
+ export async function run(db, steps) {
232
+ const before = await db.getChangeRevision();
233
+ const events = [];
234
+ const release = db.subscribeToChanges((change) => events.push({
235
+ revision: change.revision - before,
236
+ domains: change.domains,
237
+ paths: change.paths ?? [],
238
+ renamed: change.renamed ?? null,
239
+ }));
240
+ const states = [];
241
+ try {
242
+ for (const step of steps) {
243
+ let failed = false;
244
+ try {
245
+ if (step.kind === "upsert")
246
+ await db.upsertIndexedFile(step.record);
247
+ else if (step.kind === "rename")
248
+ await db.renameIndexedFile(step.oldPath, step.newPath);
249
+ else
250
+ await db.deleteIndexedFile(step.path);
251
+ }
252
+ catch {
253
+ failed = true;
254
+ }
255
+ states.push({ failed, state: await snapshot(db) });
256
+ }
257
+ return { events, states };
258
+ }
259
+ finally {
260
+ release();
261
+ }
262
+ }