@spooky-sync/core 0.0.1-canary.33 → 0.0.1-canary.331

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 (266) hide show
  1. package/AGENTS.md +84 -0
  2. package/README.md +56 -16
  3. package/dist/index.d.ts +2080 -142
  4. package/dist/index.js +16009 -2480
  5. package/dist/live.d.ts +149 -0
  6. package/dist/live.js +739 -0
  7. package/dist/otel/index.d.ts +1 -1
  8. package/dist/otel/index.js +3 -3
  9. package/dist/pure.d.ts +373 -0
  10. package/dist/pure.js +24 -0
  11. package/dist/sqlite-open.js +392 -0
  12. package/dist/sqlite-worker.d.ts +1 -0
  13. package/dist/sqlite-worker.js +439 -0
  14. package/dist/sw.d.ts +207 -0
  15. package/dist/sw.js +393 -0
  16. package/dist/tabs-broker-worker.d.ts +8 -0
  17. package/dist/tabs-broker-worker.js +477 -0
  18. package/dist/types.d.ts +1857 -38
  19. package/dist/worker-edges.js +480 -0
  20. package/dist/worker-impersonation.js +60 -0
  21. package/dist/worker-ref-tables.d.ts +48 -0
  22. package/dist/worker-types.d.ts +112 -0
  23. package/dist/worker-types.js +73 -0
  24. package/package.json +28 -7
  25. package/scripts/check-broker-bundle.mjs +33 -0
  26. package/scripts/check-worker-entries.mjs +173 -0
  27. package/skills/sp00ky-core/SKILL.md +32 -7
  28. package/skills/sp00ky-core/references/config.md +7 -1
  29. package/src/boot/auth-flip.saga.test.ts +135 -0
  30. package/src/boot/auth-flip.saga.ts +77 -0
  31. package/src/boot/boot.saga.test.ts +203 -0
  32. package/src/boot/boot.saga.ts +146 -0
  33. package/src/boot/bucket-switch.saga.test.ts +187 -0
  34. package/src/boot/bucket-switch.saga.ts +133 -0
  35. package/src/boot/preload.saga.test.ts +80 -0
  36. package/src/boot/preload.saga.ts +40 -0
  37. package/src/bucket-blurhash.test.ts +148 -0
  38. package/src/build-globals.d.ts +12 -0
  39. package/src/client/bucket-handle.test.ts +195 -0
  40. package/src/client/bucket-handle.ts +352 -0
  41. package/src/client/router.test.ts +58 -0
  42. package/src/client/router.ts +100 -0
  43. package/src/client/runtime.test.ts +195 -0
  44. package/src/client/runtime.ts +296 -0
  45. package/src/client/services.test.ts +74 -0
  46. package/src/client/services.ts +434 -0
  47. package/src/client/sp00ky-client.test.ts +341 -0
  48. package/src/client/sp00ky-client.ts +625 -0
  49. package/src/events/events.test.ts +2 -1
  50. package/src/events/index.ts +3 -0
  51. package/src/index.ts +69 -1
  52. package/src/kernel/constants.test.ts +19 -0
  53. package/src/kernel/constants.ts +80 -0
  54. package/src/kernel/effects.test.ts +40 -0
  55. package/src/kernel/effects.ts +167 -0
  56. package/src/kernel/events.ts +57 -0
  57. package/src/kernel/interpreter.test.ts +116 -0
  58. package/src/kernel/interpreter.ts +148 -0
  59. package/src/kernel/saga.test.ts +89 -0
  60. package/src/kernel/saga.ts +73 -0
  61. package/src/live/index.test.ts +512 -0
  62. package/src/live/index.ts +1059 -0
  63. package/src/modules/app-release/index.test.ts +125 -0
  64. package/src/modules/app-release/index.ts +209 -0
  65. package/src/modules/auth/auth.local-first.test.ts +228 -0
  66. package/src/modules/auth/events/index.ts +9 -2
  67. package/src/modules/auth/impersonation-banner.ts +443 -0
  68. package/src/modules/auth/impersonation.integration.test.ts +205 -0
  69. package/src/modules/auth/impersonation.test.ts +377 -0
  70. package/src/modules/auth/impersonation.ts +179 -0
  71. package/src/modules/auth/index.ts +476 -22
  72. package/src/modules/crdt/acceptance.ts +75 -0
  73. package/src/modules/crdt/bytes.ts +50 -0
  74. package/src/modules/crdt/crdt-field.ts +125 -0
  75. package/src/modules/crdt/crdt.test.ts +469 -0
  76. package/src/modules/crdt/hash.ts +103 -0
  77. package/src/modules/crdt/index.ts +757 -0
  78. package/src/modules/crdt/loro-loader.ts +25 -0
  79. package/src/modules/crdt/mirror.ts +37 -0
  80. package/src/modules/devtools/flags.ts +349 -0
  81. package/src/modules/devtools/index.ts +746 -95
  82. package/src/modules/devtools/mutations.test.ts +92 -0
  83. package/src/modules/devtools/mutations.ts +160 -0
  84. package/src/modules/devtools/notify-throttle.test.ts +166 -0
  85. package/src/modules/devtools/state-shape.test.ts +263 -0
  86. package/src/modules/devtools/storage-info.test.ts +79 -0
  87. package/src/modules/devtools/storage-info.ts +168 -0
  88. package/src/modules/devtools/versions.test.ts +74 -0
  89. package/src/modules/devtools/versions.ts +110 -0
  90. package/src/modules/feature-flag/index.test.ts +298 -0
  91. package/src/modules/feature-flag/index.ts +316 -0
  92. package/src/modules/ref-tables.test.ts +93 -0
  93. package/src/modules/ref-tables.ts +91 -0
  94. package/src/modules/web-push/index.test.ts +824 -0
  95. package/src/modules/web-push/index.ts +1027 -0
  96. package/src/mutation/jobs.test.ts +25 -0
  97. package/src/mutation/jobs.ts +41 -0
  98. package/src/mutation/mutation-id.test.ts +37 -0
  99. package/src/mutation/mutation-id.ts +35 -0
  100. package/src/mutation/pending-writes.integration.test.ts +175 -0
  101. package/src/mutation/push.saga.test.ts +301 -0
  102. package/src/mutation/push.saga.ts +225 -0
  103. package/src/mutation/rows.test.ts +231 -0
  104. package/src/mutation/rows.ts +427 -0
  105. package/src/mutation/tray.saga.test.ts +63 -0
  106. package/src/mutation/tray.saga.ts +48 -0
  107. package/src/mutation/write.saga.test.ts +316 -0
  108. package/src/mutation/write.saga.ts +268 -0
  109. package/src/otel/index.ts +10 -7
  110. package/src/pure.ts +66 -0
  111. package/src/push/types.ts +174 -0
  112. package/src/query/anon-query-isolation.integration.test.ts +527 -0
  113. package/src/query/env.test.ts +23 -0
  114. package/src/query/env.ts +65 -0
  115. package/src/query/fetch.saga.test.ts +199 -0
  116. package/src/query/fetch.saga.ts +120 -0
  117. package/src/query/hash.test.ts +14 -0
  118. package/src/query/hash.ts +18 -0
  119. package/src/query/id-set-plan.test.ts +132 -0
  120. package/src/query/lifecycle.saga.test.ts +274 -0
  121. package/src/query/lifecycle.saga.ts +186 -0
  122. package/src/query/list-ref-live.integration.test.ts +203 -0
  123. package/src/query/materialize.saga.test.ts +115 -0
  124. package/src/query/materialize.saga.ts +84 -0
  125. package/src/query/materialize.test.ts +58 -0
  126. package/src/query/materialize.ts +57 -0
  127. package/src/query/membership.saga.test.ts +407 -0
  128. package/src/query/membership.saga.ts +282 -0
  129. package/src/query/membership.test.ts +118 -0
  130. package/src/query/membership.ts +201 -0
  131. package/src/query/register.saga.test.ts +311 -0
  132. package/src/query/register.saga.ts +235 -0
  133. package/src/query/render-set.test.ts +47 -0
  134. package/src/query/render-set.ts +71 -0
  135. package/src/query/sql.test.ts +118 -0
  136. package/src/query/sql.ts +157 -0
  137. package/src/query/window-query.test.ts +70 -0
  138. package/src/query/window-query.ts +208 -0
  139. package/src/services/blobs/blob-cache.test.ts +359 -0
  140. package/src/services/blobs/blob-cache.ts +603 -0
  141. package/src/services/blobs/blob-manifest.ts +227 -0
  142. package/src/services/blobs/blob-store.test.ts +77 -0
  143. package/src/services/blobs/blob-store.ts +359 -0
  144. package/src/services/blobs/blob.fixture.ts +90 -0
  145. package/src/services/blobs/index.ts +70 -0
  146. package/src/services/database/cache-engine.ts +209 -0
  147. package/src/services/database/connection-supervisor.test.ts +318 -0
  148. package/src/services/database/connection-supervisor.ts +422 -0
  149. package/src/services/database/database.query-timeout.test.ts +140 -0
  150. package/src/services/database/database.responses.test.ts +43 -0
  151. package/src/services/database/database.ts +156 -61
  152. package/src/services/database/engine-factory.ts +33 -0
  153. package/src/services/database/errors.ts +34 -0
  154. package/src/services/database/events/index.ts +2 -1
  155. package/src/services/database/index.ts +7 -0
  156. package/src/services/database/landed-body-clear.integration.test.ts +236 -0
  157. package/src/services/database/local-migrator.integration.test.ts +110 -0
  158. package/src/services/database/local-migrator.ts +61 -16
  159. package/src/services/database/local.test.ts +150 -0
  160. package/src/services/database/local.ts +508 -63
  161. package/src/services/database/plan-render.test.ts +159 -0
  162. package/src/services/database/plan-render.ts +108 -0
  163. package/src/services/database/relation-resolver.test.ts +484 -0
  164. package/src/services/database/relation-resolver.ts +0 -0
  165. package/src/services/database/remote.ts +285 -6
  166. package/src/services/database/sqlite-cache-engine.test.ts +628 -0
  167. package/src/services/database/sqlite-cache-engine.timeout.test.ts +61 -0
  168. package/src/services/database/sqlite-cache-engine.ts +1401 -0
  169. package/src/services/database/sqlite-column-reset.integration.test.ts +100 -0
  170. package/src/services/database/sqlite-column-reset.ts +91 -0
  171. package/src/services/database/sqlite-devtools-queries.integration.test.ts +143 -0
  172. package/src/services/database/sqlite-devtools-queries.test.ts +154 -0
  173. package/src/services/database/sqlite-lock-verify.test.ts +33 -0
  174. package/src/services/database/sqlite-lock-verify.ts +45 -0
  175. package/src/services/database/sqlite-open.test.ts +150 -0
  176. package/src/services/database/sqlite-open.ts +164 -0
  177. package/src/services/database/sqlite-plan-sql.test.ts +164 -0
  178. package/src/services/database/sqlite-plan-sql.ts +196 -0
  179. package/src/services/database/sqlite-projection.test.ts +121 -0
  180. package/src/services/database/sqlite-select.integration.test.ts +185 -0
  181. package/src/services/database/sqlite-select.test.ts +261 -0
  182. package/src/services/database/sqlite-select.ts +131 -0
  183. package/src/services/database/sqlite-transport.fixture.ts +30 -0
  184. package/src/services/database/sqlite-transport.ts +224 -0
  185. package/src/services/database/sqlite-worker.ts +437 -0
  186. package/src/services/database/surql-translate.ts +417 -0
  187. package/src/services/database/surreal-cache-engine.ts +163 -0
  188. package/src/services/logger/index.test.ts +132 -0
  189. package/src/services/logger/index.ts +189 -7
  190. package/src/services/persistence/localstorage.ts +2 -2
  191. package/src/services/persistence/resilient.ts +10 -3
  192. package/src/services/persistence/surrealdb.ts +4 -4
  193. package/src/services/stream-processor/index.ts +806 -67
  194. package/src/services/stream-processor/permissions.test.ts +47 -0
  195. package/src/services/stream-processor/permissions.ts +53 -0
  196. package/src/services/stream-processor/stream-processor.batch.test.ts +186 -0
  197. package/src/services/stream-processor/stream-processor.prime.test.ts +234 -0
  198. package/src/services/stream-processor/stream-processor.reset.test.ts +226 -0
  199. package/src/services/stream-processor/stream-processor.test.ts +1 -1
  200. package/src/services/stream-processor/wasm-types.ts +58 -2
  201. package/src/services/tabs/broker-client.ts +284 -0
  202. package/src/services/tabs/broker.test.ts +381 -0
  203. package/src/services/tabs/coordinator.test.ts +386 -0
  204. package/src/services/tabs/coordinator.ts +646 -0
  205. package/src/services/tabs/fake-ports.fixture.ts +112 -0
  206. package/src/services/tabs/leader-locks.ts +75 -0
  207. package/src/services/tabs/protocol.ts +262 -0
  208. package/src/services/tabs/support.ts +36 -0
  209. package/src/services/tabs/tabs-broker-worker.ts +652 -0
  210. package/src/sp00ky.ts +5 -395
  211. package/src/state/client-state.ts +208 -0
  212. package/src/state/lifecycle.test.ts +141 -0
  213. package/src/state/lifecycle.ts +99 -0
  214. package/src/state/reducers.test.ts +306 -0
  215. package/src/state/reducers.ts +531 -0
  216. package/src/state/selectors.test.ts +188 -0
  217. package/src/state/selectors.ts +258 -0
  218. package/src/sw/index.test.ts +582 -0
  219. package/src/sw/index.ts +607 -0
  220. package/src/sw/store.ts +96 -0
  221. package/src/sync/connection.saga.test.ts +97 -0
  222. package/src/sync/connection.saga.ts +89 -0
  223. package/src/sync/live.saga.test.ts +178 -0
  224. package/src/sync/live.saga.ts +107 -0
  225. package/src/sync/policy.health.test.ts +56 -0
  226. package/src/sync/policy.test.ts +663 -0
  227. package/src/sync/policy.ts +515 -0
  228. package/src/sync/poll.saga.test.ts +51 -0
  229. package/src/sync/poll.saga.ts +36 -0
  230. package/src/sync/tabs.saga.test.ts +78 -0
  231. package/src/sync/tabs.saga.ts +96 -0
  232. package/src/testing/adapters.ts +137 -0
  233. package/src/testing/build.ts +63 -0
  234. package/src/testing/fake-services.ts +63 -0
  235. package/src/testing/run-pure.test.ts +92 -0
  236. package/src/testing/run-pure.ts +128 -0
  237. package/src/testing/services.ts +17 -0
  238. package/src/types.ts +633 -10
  239. package/src/utils/blurhash.ts +90 -0
  240. package/src/utils/edges.ts +39 -0
  241. package/src/utils/error-classification.test.ts +54 -0
  242. package/src/utils/error-classification.ts +25 -0
  243. package/src/utils/index.ts +89 -12
  244. package/src/utils/parser.test.ts +67 -102
  245. package/src/utils/parser.ts +64 -2
  246. package/src/utils/semver.test.ts +32 -0
  247. package/src/utils/semver.ts +30 -0
  248. package/src/utils/sha256.ts +15 -0
  249. package/src/utils/surql.ts +29 -18
  250. package/src/utils/utils.test.ts +3 -2
  251. package/tsdown.config.ts +117 -3
  252. package/vitest.config.ts +48 -0
  253. package/src/modules/cache/index.ts +0 -241
  254. package/src/modules/cache/types.ts +0 -19
  255. package/src/modules/data/data.test.ts +0 -58
  256. package/src/modules/data/index.ts +0 -879
  257. package/src/modules/sync/engine.ts +0 -173
  258. package/src/modules/sync/events/index.ts +0 -77
  259. package/src/modules/sync/index.ts +0 -3
  260. package/src/modules/sync/queue/index.ts +0 -2
  261. package/src/modules/sync/queue/queue-down.ts +0 -89
  262. package/src/modules/sync/queue/queue-up.ts +0 -223
  263. package/src/modules/sync/scheduler.ts +0 -84
  264. package/src/modules/sync/sync.ts +0 -421
  265. package/src/modules/sync/utils.test.ts +0 -311
  266. package/src/modules/sync/utils.ts +0 -167
@@ -1,241 +0,0 @@
1
- import { LocalDatabaseService } from '../../services/database/index';
2
- import {
3
- StreamProcessorService,
4
- StreamUpdate,
5
- StreamUpdateReceiver,
6
- } from '../../services/stream-processor/index';
7
- import { Logger } from '../../services/logger/index';
8
- import { parseRecordIdString, encodeRecordId, surql } from '../../utils/index';
9
- import { CacheRecord, QueryConfig } from './types';
10
- import { RecordVersionArray } from '../../types';
11
-
12
- export * from './types';
13
-
14
- /**
15
- * CacheModule - Centralized storage and DBSP ingestion
16
- *
17
- * Single responsibility: Handle all local storage operations and DBSP ingestion.
18
- * This module acts as the bridge between data operations and persistence.
19
- */
20
- export class CacheModule implements StreamUpdateReceiver {
21
- private logger: Logger;
22
- private streamUpdateCallback: (update: StreamUpdate) => void;
23
- private versionLookups: Record<string, number> = {};
24
-
25
- constructor(
26
- private local: LocalDatabaseService,
27
- private streamProcessor: StreamProcessorService,
28
- streamUpdateCallback: (update: StreamUpdate) => void,
29
- logger: Logger
30
- ) {
31
- this.logger = logger.child({ service: 'CacheModule' });
32
- this.streamUpdateCallback = streamUpdateCallback;
33
- // Register as receiver for DBSP stream updates
34
- this.streamProcessor.addReceiver(this);
35
- }
36
-
37
- /**
38
- * Implements StreamUpdateReceiver interface
39
- * Called directly by StreamProcessor when views change
40
- */
41
- onStreamUpdate(update: StreamUpdate): void {
42
- this.logger.debug(
43
- {
44
- queryHash: update.queryHash,
45
- arrayLength: update.localArray?.length,
46
- Category: 'sp00ky-client::CacheModule::onStreamUpdate',
47
- },
48
- 'Stream update received'
49
- );
50
- this.streamUpdateCallback(update);
51
- }
52
-
53
- public lookup(recordId: string): number {
54
- return this.versionLookups[recordId] ?? 0;
55
- }
56
-
57
- /**
58
- * Save a single record to local DB and ingest into DBSP
59
- * Used by mutations (create/update)
60
- */
61
- async save(cacheRecord: CacheRecord, skipDbInsert: boolean = false): Promise<void> {
62
- return this.saveBatch([cacheRecord], skipDbInsert);
63
- }
64
-
65
- /**
66
- * Save multiple records in a batch
67
- * More efficient than calling save() multiple times
68
- * Used by sync operations
69
- */
70
- async saveBatch(records: CacheRecord[], skipDbInsert: boolean = false): Promise<void> {
71
- if (records.length === 0) return;
72
-
73
- this.logger.debug(
74
- {
75
- count: records.length,
76
- Category: 'sp00ky-client::CacheModule::saveBatch',
77
- },
78
- 'Saving record batch'
79
- );
80
-
81
- try {
82
- const populatedRecords = records.map((record) => {
83
- if (!record.version) throw new Error('Record version is required');
84
- return {
85
- ...record,
86
- record: {
87
- ...record.record,
88
- _00_rv: record.version,
89
- },
90
- };
91
- });
92
-
93
- if (!skipDbInsert) {
94
- const query = surql.seal<void>(
95
- surql.tx(
96
- populatedRecords.map((_, i) => {
97
- return surql.upsert(`id${i}`, `content${i}`);
98
- })
99
- )
100
- );
101
-
102
- const params = populatedRecords.reduce(
103
- (acc, record, i) => {
104
- const { id, ...content } = record.record;
105
- return {
106
- ...acc,
107
- [`id${i}`]: id,
108
- [`content${i}`]: content,
109
- };
110
- },
111
- {} as Record<string, any>
112
- );
113
-
114
- await this.local.execute(query, params);
115
- }
116
-
117
- // 2. Batch ingest into DBSP (use populatedRecords which has _00_rv set)
118
- for (const record of populatedRecords) {
119
- const recordId = encodeRecordId(record.record.id);
120
- this.versionLookups[recordId] = record.version;
121
- this.streamProcessor.ingest(record.table, record.op, recordId, record.record);
122
- }
123
-
124
- this.logger.debug(
125
- { count: records.length, Category: 'sp00ky-client::CacheModule::saveBatch' },
126
- 'Batch saved successfully'
127
- );
128
- } catch (err) {
129
- this.logger.error(
130
- { err, count: records.length, Category: 'sp00ky-client::CacheModule::saveBatch' },
131
- 'Failed to save batch'
132
- );
133
- throw err;
134
- }
135
- }
136
-
137
- /**
138
- * Delete a record from local DB and ingest deletion into DBSP
139
- */
140
- async delete(table: string, id: string, skipDbDelete: boolean = false, recordData: Record<string, any> = {}): Promise<void> {
141
- this.logger.debug(
142
- { table, id, Category: 'sp00ky-client::CacheModule::delete' },
143
- 'Deleting record'
144
- );
145
-
146
- try {
147
- // 1. Delete from local database
148
- if (!skipDbDelete) {
149
- await this.local.query('DELETE $id', { id: parseRecordIdString(id) });
150
- }
151
-
152
- // 2. Ingest deletion into DBSP (pass record data so predicates can be matched)
153
- delete this.versionLookups[id];
154
- this.streamProcessor.ingest(table, 'DELETE', id, recordData);
155
-
156
- this.logger.debug(
157
- { table, id, Category: 'sp00ky-client::CacheModule::delete' },
158
- 'Record deleted successfully'
159
- );
160
- } catch (err) {
161
- this.logger.error(
162
- { err, table, id, Category: 'sp00ky-client::CacheModule::delete' },
163
- 'Failed to delete record'
164
- );
165
- throw err;
166
- }
167
- }
168
-
169
- /**
170
- * Register a query with DBSP to create a materialized view
171
- * Returns the initial result array
172
- */
173
- registerQuery(config: QueryConfig): { localArray: RecordVersionArray } {
174
- this.logger.debug(
175
- {
176
- queryHash: config.queryHash,
177
- surql: config.surql,
178
- Category: 'sp00ky-client::CacheModule::registerQuery',
179
- },
180
- 'Registering query'
181
- );
182
-
183
- try {
184
- const update = this.streamProcessor.registerQueryPlan({
185
- queryHash: config.queryHash,
186
- surql: config.surql,
187
- params: config.params,
188
- ttl: config.ttl,
189
- lastActiveAt: config.lastActiveAt,
190
- localArray: [],
191
- remoteArray: [],
192
- meta: {
193
- tableName: '',
194
- },
195
- });
196
-
197
- if (!update) {
198
- throw new Error('Failed to register query with DBSP');
199
- }
200
-
201
- this.logger.debug(
202
- {
203
- queryHash: config.queryHash,
204
- arrayLength: update.localArray?.length,
205
- Category: 'sp00ky-client::CacheModule::registerQuery',
206
- },
207
- 'Query registered successfully'
208
- );
209
-
210
- return { localArray: update.localArray };
211
- } catch (err) {
212
- this.logger.error(
213
- { err, queryHash: config.queryHash, Category: 'sp00ky-client::CacheModule::registerQuery' },
214
- 'Failed to register query'
215
- );
216
- throw err;
217
- }
218
- }
219
-
220
- /**
221
- * Unregister a query from DBSP
222
- */
223
- unregisterQuery(queryHash: string): void {
224
- this.logger.debug(
225
- { queryHash, Category: 'sp00ky-client::CacheModule::unregisterQuery' },
226
- 'Unregistering query'
227
- );
228
- try {
229
- this.streamProcessor.unregisterQueryPlan(queryHash);
230
- this.logger.debug(
231
- { queryHash, Category: 'sp00ky-client::CacheModule::unregisterQuery' },
232
- 'Query unregistered successfully'
233
- );
234
- } catch (err) {
235
- this.logger.error(
236
- { err, queryHash, Category: 'sp00ky-client::CacheModule::unregisterQuery' },
237
- 'Failed to unregister query'
238
- );
239
- }
240
- }
241
- }
@@ -1,19 +0,0 @@
1
- import { RecordId, Duration } from 'surrealdb';
2
- import { QueryTimeToLive, RecordVersionArray } from '../../types';
3
-
4
- export type RecordWithId = Record<string, any> & { id: RecordId<string> };
5
-
6
- export interface QueryConfig {
7
- queryHash: string;
8
- surql: string;
9
- params: Record<string, any>;
10
- ttl: QueryTimeToLive | Duration;
11
- lastActiveAt: Date;
12
- }
13
-
14
- export interface CacheRecord {
15
- table: string;
16
- op: 'CREATE' | 'UPDATE' | 'DELETE';
17
- record: RecordWithId;
18
- version: number;
19
- }
@@ -1,58 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { parseUpdateOptions } from './index';
3
-
4
- describe('parseUpdateOptions', () => {
5
- it('returns empty options when no debounce', () => {
6
- const result = parseUpdateOptions('user:1', { name: 'Alice' });
7
- expect(result).toEqual({});
8
- });
9
-
10
- it('returns empty options when options is undefined', () => {
11
- const result = parseUpdateOptions('user:1', { name: 'Alice' }, undefined);
12
- expect(result).toEqual({});
13
- });
14
-
15
- it('returns empty options when debounced is false', () => {
16
- const result = parseUpdateOptions('user:1', { name: 'Alice' }, { debounced: false });
17
- expect(result).toEqual({});
18
- });
19
-
20
- it('debounced: true uses default delay (200) and key = id', () => {
21
- const result = parseUpdateOptions('user:1', { name: 'Alice' }, { debounced: true });
22
- expect(result).toEqual({
23
- debounced: {
24
- delay: 200,
25
- key: 'user:1',
26
- },
27
- });
28
- });
29
-
30
- it('supports custom delay', () => {
31
- const result = parseUpdateOptions('user:1', { name: 'Alice' }, {
32
- debounced: { delay: 500 },
33
- });
34
- expect(result.debounced?.delay).toBe(500);
35
- });
36
-
37
- it('supports custom key type recordId', () => {
38
- const result = parseUpdateOptions('user:1', { name: 'Alice', age: 30 }, {
39
- debounced: { key: 'recordId' },
40
- });
41
- expect(result.debounced?.key).toBe('user:1');
42
- });
43
-
44
- it('key: recordId_x_fields generates composite key from id + sorted field names', () => {
45
- const result = parseUpdateOptions(
46
- 'user:1',
47
- { name: 'Alice', age: 30, email: 'a@b.com' },
48
- { debounced: { key: 'recordId_x_fields' } }
49
- );
50
- expect(result.debounced?.key).toBe('user:1::age#email#name');
51
- });
52
-
53
- it('uses defaults when debounced is object with no key or delay', () => {
54
- const result = parseUpdateOptions('user:1', { name: 'Alice' }, { debounced: {} });
55
- expect(result.debounced?.delay).toBe(200);
56
- expect(result.debounced?.key).toBe('user:1');
57
- });
58
- });