@spooky-sync/core 0.0.1-canary.4 → 0.0.1-canary.41

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 (45) hide show
  1. package/dist/index.d.ts +18 -367
  2. package/dist/index.js +268 -287
  3. package/dist/otel/index.d.ts +21 -0
  4. package/dist/otel/index.js +86 -0
  5. package/dist/types.d.ts +361 -0
  6. package/package.json +34 -5
  7. package/skills/sp00ky-core/SKILL.md +258 -0
  8. package/skills/sp00ky-core/references/auth.md +98 -0
  9. package/skills/sp00ky-core/references/config.md +76 -0
  10. package/src/events/events.test.ts +2 -1
  11. package/src/index.ts +1 -1
  12. package/src/modules/auth/events/index.ts +2 -1
  13. package/src/modules/auth/index.ts +17 -20
  14. package/src/modules/cache/index.ts +23 -23
  15. package/src/modules/cache/types.ts +2 -2
  16. package/src/modules/data/index.ts +61 -43
  17. package/src/modules/devtools/index.ts +23 -20
  18. package/src/modules/sync/engine.ts +31 -21
  19. package/src/modules/sync/events/index.ts +3 -2
  20. package/src/modules/sync/queue/queue-down.ts +5 -4
  21. package/src/modules/sync/queue/queue-up.ts +14 -13
  22. package/src/modules/sync/scheduler.ts +2 -2
  23. package/src/modules/sync/sync.ts +47 -35
  24. package/src/modules/sync/utils.test.ts +2 -2
  25. package/src/modules/sync/utils.ts +15 -17
  26. package/src/otel/index.ts +127 -0
  27. package/src/services/database/database.ts +11 -11
  28. package/src/services/database/events/index.ts +2 -1
  29. package/src/services/database/local-migrator.ts +21 -21
  30. package/src/services/database/local.ts +16 -15
  31. package/src/services/database/remote.ts +13 -13
  32. package/src/services/logger/index.ts +6 -101
  33. package/src/services/persistence/localstorage.ts +2 -2
  34. package/src/services/persistence/resilient.ts +34 -0
  35. package/src/services/persistence/surrealdb.ts +9 -9
  36. package/src/services/stream-processor/index.ts +32 -31
  37. package/src/services/stream-processor/stream-processor.test.ts +1 -1
  38. package/src/services/stream-processor/wasm-types.ts +2 -2
  39. package/src/{spooky.ts → sp00ky.ts} +40 -38
  40. package/src/types.ts +18 -11
  41. package/src/utils/index.ts +10 -10
  42. package/src/utils/parser.ts +2 -1
  43. package/src/utils/surql.ts +15 -15
  44. package/src/utils/withRetry.test.ts +1 -1
  45. package/tsdown.config.ts +1 -1
package/dist/index.js CHANGED
@@ -2,12 +2,7 @@ import { DateTime, Duration, RecordId, Surreal, Uuid, applyDiagnostics, createRe
2
2
  import { QueryBuilder, RecordId as RecordId$1 } from "@spooky-sync/query-builder";
3
3
  import { createWasmWorkerEngines } from "@surrealdb/wasm";
4
4
  import pino from "pino";
5
- import { BatchLogRecordProcessor, LoggerProvider } from "@opentelemetry/sdk-logs";
6
- import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-proto";
7
- import { resourceFromAttributes } from "@opentelemetry/resources";
8
- import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
9
- import { createContextKey } from "@opentelemetry/api";
10
- import init, { SpookyProcessor } from "@spooky-sync/ssp-wasm";
5
+ import init, { Sp00kyProcessor } from "@spooky-sync/ssp-wasm";
11
6
 
12
7
  //#region src/utils/surql.ts
13
8
  const surql = {
@@ -33,7 +28,7 @@ const surql = {
33
28
  return `SELECT ${returnValues.join(",")} FROM ONLY $${idVar}`;
34
29
  },
35
30
  selectByFieldsAnd(table, whereVar, returnValues) {
36
- return `SELECT ${returnValues.map((returnValues) => typeof returnValues === "string" ? returnValues : `${returnValues.field} as ${returnValues.alias}`).join(",")} FROM ${table} WHERE ${whereVar.map((whereVar) => typeof whereVar === "string" ? `${whereVar} = $${whereVar}` : `${whereVar.field} = $${whereVar.variable}`).join(" AND ")}`;
31
+ return `SELECT ${returnValues.map((rv) => typeof rv === "string" ? rv : `${rv.field} as ${rv.alias}`).join(",")} FROM ${table} WHERE ${whereVar.map((wv) => typeof wv === "string" ? `${wv} = $${wv}` : `${wv.field} = $${wv.variable}`).join(" AND ")}`;
37
32
  },
38
33
  create(idVar, dataVar) {
39
34
  return `CREATE ONLY $${idVar} CONTENT $${dataVar}`;
@@ -48,7 +43,7 @@ const surql = {
48
43
  return `UPDATE ONLY $${idVar} MERGE $${dataVar}`;
49
44
  },
50
45
  updateSet(idVar, keyDataVar) {
51
- return `UPDATE $${idVar} SET ${keyDataVar.map((keyDataVar) => typeof keyDataVar === "string" ? `${keyDataVar} = $${keyDataVar}` : "statement" in keyDataVar ? keyDataVar.statement : `${keyDataVar.key} = $${keyDataVar.variable}`).join(", ")}`;
46
+ return `UPDATE $${idVar} SET ${keyDataVar.map((kdv) => typeof kdv === "string" ? `${kdv} = $${kdv}` : "statement" in kdv ? kdv.statement : `${kdv.key} = $${kdv.variable}`).join(", ")}`;
52
47
  },
53
48
  delete(idVar) {
54
49
  return `DELETE $${idVar}`;
@@ -162,7 +157,7 @@ function parseDuration(duration) {
162
157
  if (typeof duration !== "string") return 6e5;
163
158
  const match = duration.match(/^(\d+)([smh])$/);
164
159
  if (!match) return 6e5;
165
- const val = parseInt(match[1], 10);
160
+ const val = Number.parseInt(match[1], 10);
166
161
  switch (match[2]) {
167
162
  case "s": return val * 1e3;
168
163
  case "h": return val * 36e5;
@@ -188,7 +183,7 @@ async function withRetry(logger, operation, retries = 3, delayMs = 100) {
188
183
  attempt: i + 1,
189
184
  retries,
190
185
  error: msg,
191
- Category: "spooky-client::utils::withRetry"
186
+ Category: "sp00ky-client::utils::withRetry"
192
187
  }, "Retrying DB operation");
193
188
  await new Promise((res) => setTimeout(res, delayMs * (i + 1)));
194
189
  continue;
@@ -221,7 +216,7 @@ var DataModule = class {
221
216
  this.logger = logger.child({ service: "DataModule" });
222
217
  }
223
218
  async init() {
224
- this.logger.info({ Category: "spooky-client::DataModule::init" }, "DataModule initialized");
219
+ this.logger.info({ Category: "sp00ky-client::DataModule::init" }, "DataModule initialized");
225
220
  }
226
221
  /**
227
222
  * Register a query and return its hash for subscriptions
@@ -233,27 +228,27 @@ var DataModule = class {
233
228
  });
234
229
  this.logger.debug({
235
230
  hash,
236
- Category: "spooky-client::DataModule::query"
231
+ Category: "sp00ky-client::DataModule::query"
237
232
  }, "Query Initialization: started");
238
- const recordId = new RecordId("_spooky_query", hash);
233
+ const recordId = new RecordId("_00_query", hash);
239
234
  if (this.activeQueries.has(hash)) {
240
235
  this.logger.debug({
241
236
  hash,
242
- Category: "spooky-client::DataModule::query"
237
+ Category: "sp00ky-client::DataModule::query"
243
238
  }, "Query Initialization: exists, returning");
244
239
  return hash;
245
240
  }
246
241
  if (this.pendingQueries.has(hash)) {
247
242
  this.logger.debug({
248
243
  hash,
249
- Category: "spooky-client::DataModule::query"
244
+ Category: "sp00ky-client::DataModule::query"
250
245
  }, "Query Initialization: pending, waiting for existing creation");
251
246
  await this.pendingQueries.get(hash);
252
247
  return hash;
253
248
  }
254
249
  this.logger.debug({
255
250
  hash,
256
- Category: "spooky-client::DataModule::query"
251
+ Category: "sp00ky-client::DataModule::query"
257
252
  }, "Query Initialization: not found, creating new query");
258
253
  const promise = this.createAndRegisterQuery(hash, recordId, surqlString, params, ttl, tableName);
259
254
  this.pendingQueries.set(hash, promise);
@@ -311,7 +306,7 @@ var DataModule = class {
311
306
  if (!queryState) {
312
307
  this.logger.warn({
313
308
  queryHash,
314
- Category: "spooky-client::DataModule::onStreamUpdate"
309
+ Category: "sp00ky-client::DataModule::onStreamUpdate"
315
310
  }, "Received update for unknown query. Skipping...");
316
311
  return;
317
312
  }
@@ -329,7 +324,7 @@ var DataModule = class {
329
324
  if (prevJson === newJson) {
330
325
  this.logger.debug({
331
326
  queryHash,
332
- Category: "spooky-client::DataModule::onStreamUpdate"
327
+ Category: "sp00ky-client::DataModule::onStreamUpdate"
333
328
  }, "Query records unchanged, skipping notification");
334
329
  return;
335
330
  }
@@ -339,13 +334,13 @@ var DataModule = class {
339
334
  this.logger.debug({
340
335
  queryHash,
341
336
  recordCount: records?.length,
342
- Category: "spooky-client::DataModule::onStreamUpdate"
337
+ Category: "sp00ky-client::DataModule::onStreamUpdate"
343
338
  }, "Query updated from stream");
344
339
  } catch (err) {
345
340
  this.logger.error({
346
341
  err,
347
342
  queryHash,
348
- Category: "spooky-client::DataModule::onStreamUpdate"
343
+ Category: "sp00ky-client::DataModule::onStreamUpdate"
349
344
  }, "Failed to fetch records for stream update");
350
345
  }
351
346
  }
@@ -372,7 +367,7 @@ var DataModule = class {
372
367
  if (!queryState) {
373
368
  this.logger.warn({
374
369
  id,
375
- Category: "spooky-client::DataModule::updateQueryLocalArray"
370
+ Category: "sp00ky-client::DataModule::updateQueryLocalArray"
376
371
  }, "Query to update local array not found");
377
372
  return;
378
373
  }
@@ -387,7 +382,7 @@ var DataModule = class {
387
382
  if (!queryState) {
388
383
  this.logger.warn({
389
384
  hash,
390
- Category: "spooky-client::DataModule::updateQueryRemoteArray"
385
+ Category: "sp00ky-client::DataModule::updateQueryRemoteArray"
391
386
  }, "Query to update remote array not found");
392
387
  return;
393
388
  }
@@ -431,6 +426,7 @@ var DataModule = class {
431
426
  max_retries: options?.max_retries ?? 3,
432
427
  retry_strategy: options?.retry_strategy ?? "linear"
433
428
  };
429
+ if (options?.timeout != null) record.timeout = options.timeout;
434
430
  if (options?.assignedTo) record.assigned_to = options.assignedTo;
435
431
  const recordId = `${tableName}:${generateId()}`;
436
432
  await this.create(recordId, record);
@@ -444,7 +440,7 @@ var DataModule = class {
444
440
  if (!tableSchema) throw new Error(`Table ${tableName} not found`);
445
441
  const rid = parseRecordIdString(id);
446
442
  const params = parseParams(tableSchema.columns, data);
447
- const mutationId = parseRecordIdString(`_spooky_pending_mutations:${Date.now()}`);
443
+ const mutationId = parseRecordIdString(`_00_pending_mutations:${Date.now()}`);
448
444
  const dataKeys = Object.keys(params).map((key) => ({
449
445
  key,
450
446
  variable: `data_${key}`
@@ -474,7 +470,7 @@ var DataModule = class {
474
470
  for (const callback of this.mutationCallbacks) callback([mutationEvent]);
475
471
  this.logger.debug({
476
472
  id,
477
- Category: "spooky-client::DataModule::create"
473
+ Category: "sp00ky-client::DataModule::create"
478
474
  }, "Record created");
479
475
  return target;
480
476
  }
@@ -487,10 +483,10 @@ var DataModule = class {
487
483
  if (!tableSchema) throw new Error(`Table ${tableName} not found`);
488
484
  const rid = parseRecordIdString(id);
489
485
  const params = parseParams(tableSchema.columns, data);
490
- const mutationId = parseRecordIdString(`_spooky_pending_mutations:${Date.now()}`);
486
+ const mutationId = parseRecordIdString(`_00_pending_mutations:${Date.now()}`);
491
487
  const [beforeRecord] = await withRetry(this.logger, () => this.local.query("SELECT * FROM ONLY $id", { id: rid }));
492
488
  const query = surql.seal(surql.tx([
493
- surql.updateSet("id", [{ statement: "spooky_rv += 1" }]),
489
+ surql.updateSet("id", [{ statement: "_00_rv += 1" }]),
494
490
  surql.let("updated", surql.updateMerge("id", "data")),
495
491
  surql.createMutation("update", "mid", "id", "data"),
496
492
  surql.returnObject([{
@@ -505,14 +501,14 @@ var DataModule = class {
505
501
  }));
506
502
  const updatedFields = { id: target.id };
507
503
  for (const key of Object.keys(data)) if (key in target) updatedFields[key] = target[key];
508
- if ("spooky_rv" in target) updatedFields.spooky_rv = target.spooky_rv;
504
+ if ("_00_rv" in target) updatedFields._00_rv = target._00_rv;
509
505
  this.replaceRecordInQueries(updatedFields);
510
506
  const parsedRecord = parseParams(tableSchema.columns, target);
511
507
  await this.cache.save({
512
508
  table,
513
509
  op: "UPDATE",
514
510
  record: parsedRecord,
515
- version: target.spooky_rv
511
+ version: target._00_rv
516
512
  }, true);
517
513
  const pushEventOptions = parseUpdateOptions(id, data, options);
518
514
  const mutationEvent = {
@@ -527,7 +523,7 @@ var DataModule = class {
527
523
  for (const callback of this.mutationCallbacks) callback([mutationEvent]);
528
524
  this.logger.debug({
529
525
  id,
530
- Category: "spooky-client::DataModule::update"
526
+ Category: "sp00ky-client::DataModule::update"
531
527
  }, "Record updated");
532
528
  return target;
533
529
  }
@@ -538,13 +534,16 @@ var DataModule = class {
538
534
  const tableName = extractTablePart(id);
539
535
  if (!this.schema.tables.find((t) => t.name === tableName)) throw new Error(`Table ${tableName} not found`);
540
536
  const rid = parseRecordIdString(id);
541
- const mutationId = parseRecordIdString(`_spooky_pending_mutations:${Date.now()}`);
537
+ const mutationId = parseRecordIdString(`_00_pending_mutations:${Date.now()}`);
538
+ const [beforeRecords] = await this.local.query("SELECT * FROM ONLY $id", { id: rid });
539
+ const beforeRecord = beforeRecords ?? {};
542
540
  const query = surql.seal(surql.tx([surql.delete("id"), surql.createMutation("delete", "mid", "id")]));
543
541
  await withRetry(this.logger, () => this.local.execute(query, {
544
542
  id: rid,
545
543
  mid: mutationId
546
544
  }));
547
- await this.cache.delete(table, id, true);
545
+ await this.cache.delete(table, id, true, beforeRecord);
546
+ for (const [queryHash, queryState] of this.activeQueries) if (queryState.config.tableName === tableName) await this.notifyQuerySynced(queryHash);
548
547
  const mutationEvent = {
549
548
  type: "delete",
550
549
  mutation_id: mutationId,
@@ -553,7 +552,7 @@ var DataModule = class {
553
552
  for (const callback of this.mutationCallbacks) callback([mutationEvent]);
554
553
  this.logger.debug({
555
554
  id,
556
- Category: "spooky-client::DataModule::delete"
555
+ Category: "sp00ky-client::DataModule::delete"
557
556
  }, "Record deleted");
558
557
  }
559
558
  /**
@@ -568,14 +567,14 @@ var DataModule = class {
568
567
  this.logger.info({
569
568
  id,
570
569
  tableName,
571
- Category: "spooky-client::DataModule::rollbackCreate"
570
+ Category: "sp00ky-client::DataModule::rollbackCreate"
572
571
  }, "Rolled back optimistic create");
573
572
  } catch (err) {
574
573
  this.logger.error({
575
574
  err,
576
575
  id,
577
576
  tableName,
578
- Category: "spooky-client::DataModule::rollbackCreate"
577
+ Category: "sp00ky-client::DataModule::rollbackCreate"
579
578
  }, "Failed to rollback create");
580
579
  }
581
580
  }
@@ -596,20 +595,20 @@ var DataModule = class {
596
595
  table: tableName,
597
596
  op: "UPDATE",
598
597
  record: parsedRecord,
599
- version: beforeRecord.spooky_rv || 1
598
+ version: beforeRecord._00_rv || 1
600
599
  }, true);
601
600
  await this.replaceRecordInQueries(beforeRecord);
602
601
  this.logger.info({
603
602
  id,
604
603
  tableName,
605
- Category: "spooky-client::DataModule::rollbackUpdate"
604
+ Category: "sp00ky-client::DataModule::rollbackUpdate"
606
605
  }, "Rolled back optimistic update");
607
606
  } catch (err) {
608
607
  this.logger.error({
609
608
  err,
610
609
  id,
611
610
  tableName,
612
- Category: "spooky-client::DataModule::rollbackUpdate"
611
+ Category: "sp00ky-client::DataModule::rollbackUpdate"
613
612
  }, "Failed to rollback update");
614
613
  }
615
614
  }
@@ -654,7 +653,7 @@ var DataModule = class {
654
653
  hash,
655
654
  tableName,
656
655
  recordCount: queryState.records.length,
657
- Category: "spooky-client::DataModule::query"
656
+ Category: "sp00ky-client::DataModule::query"
658
657
  }, "Query registered");
659
658
  return hash;
660
659
  }
@@ -689,7 +688,7 @@ var DataModule = class {
689
688
  } catch (err) {
690
689
  this.logger.warn({
691
690
  err,
692
- Category: "spooky-client::DataModule::createNewQuery"
691
+ Category: "sp00ky-client::DataModule::createNewQuery"
693
692
  }, "Failed to load initial cached records");
694
693
  }
695
694
  return {
@@ -712,7 +711,7 @@ var DataModule = class {
712
711
  queryState.ttlTimer = setTimeout(() => {
713
712
  this.logger.debug({
714
713
  id: encodeRecordId(queryState.config.id),
715
- Category: "spooky-client::DataModule::startTTLHeartbeat"
714
+ Category: "sp00ky-client::DataModule::startTTLHeartbeat"
716
715
  }, "TTL heartbeat");
717
716
  this.startTTLHeartbeat(queryState);
718
717
  }, heartbeatTime);
@@ -744,7 +743,7 @@ function parseUpdateOptions(id, data, options) {
744
743
  let pushEventOptions = {};
745
744
  if (options?.debounced) pushEventOptions = { debounced: {
746
745
  delay: options.debounced !== true ? options.debounced?.delay ?? 200 : 200,
747
- key: (options.debounced !== true ? options.debounced?.key ?? id : id) === "recordId_x_fields" ? `${id}::${Object.keys(data).sort().join("#")}` : id
746
+ key: (options.debounced !== true ? options.debounced?.key ?? id : id) === "recordId_x_fields" ? `${id}::${Object.keys(data).toSorted().join("#")}` : id
748
747
  } };
749
748
  return pushEventOptions;
750
749
  }
@@ -781,7 +780,7 @@ var AbstractDatabaseService = class {
781
780
  this.logger.debug({
782
781
  query,
783
782
  vars,
784
- Category: "spooky-client::Database::query"
783
+ Category: "sp00ky-client::Database::query"
785
784
  }, "Executing query");
786
785
  const result = await this.client.query(query, vars);
787
786
  const duration = performance.now() - startTime;
@@ -796,7 +795,7 @@ var AbstractDatabaseService = class {
796
795
  this.logger.trace({
797
796
  query,
798
797
  result,
799
- Category: "spooky-client::Database::query"
798
+ Category: "sp00ky-client::Database::query"
800
799
  }, "Query executed successfully");
801
800
  } catch (err) {
802
801
  const duration = performance.now() - startTime;
@@ -812,7 +811,7 @@ var AbstractDatabaseService = class {
812
811
  query,
813
812
  vars,
814
813
  err,
815
- Category: "spooky-client::Database::query"
814
+ Category: "sp00ky-client::Database::query"
816
815
  }, "Query execution failed");
817
816
  reject(err);
818
817
  }
@@ -824,7 +823,7 @@ var AbstractDatabaseService = class {
824
823
  return query.extract(raw);
825
824
  }
826
825
  async close() {
827
- this.logger.info({ Category: "spooky-client::Database::close" }, "Closing database connection");
826
+ this.logger.info({ Category: "sp00ky-client::Database::close" }, "Closing database connection");
828
827
  await this.client.close();
829
828
  }
830
829
  };
@@ -1004,7 +1003,7 @@ var LocalDatabaseService = class extends AbstractDatabaseService {
1004
1003
  type,
1005
1004
  phase,
1006
1005
  service: "surrealdb:local",
1007
- Category: "spooky-client::LocalDatabaseService::diagnostics"
1006
+ Category: "sp00ky-client::LocalDatabaseService::diagnostics"
1008
1007
  }, `Local SurrealDB diagnostics captured ${type}:${phase}`);
1009
1008
  })
1010
1009
  }), logger, events);
@@ -1018,30 +1017,30 @@ var LocalDatabaseService = class extends AbstractDatabaseService {
1018
1017
  this.logger.info({
1019
1018
  namespace,
1020
1019
  database,
1021
- Category: "spooky-client::LocalDatabaseService::connect"
1020
+ Category: "sp00ky-client::LocalDatabaseService::connect"
1022
1021
  }, "Connecting to local database");
1023
1022
  try {
1024
- const storeUrl = (this.getConfig().store ?? "memory") === "memory" ? "mem://" : "indxdb://spooky";
1023
+ const storeUrl = (this.getConfig().store ?? "memory") === "memory" ? "mem://" : "indxdb://sp00ky";
1025
1024
  this.logger.debug({
1026
1025
  storeUrl,
1027
- Category: "spooky-client::LocalDatabaseService::connect"
1026
+ Category: "sp00ky-client::LocalDatabaseService::connect"
1028
1027
  }, "[LocalDatabaseService] Calling client.connect");
1029
1028
  await this.client.connect(storeUrl, {});
1030
1029
  this.logger.debug({
1031
1030
  namespace,
1032
1031
  database,
1033
- Category: "spooky-client::LocalDatabaseService::connect"
1032
+ Category: "sp00ky-client::LocalDatabaseService::connect"
1034
1033
  }, "[LocalDatabaseService] client.connect returned. Calling client.use");
1035
1034
  await this.client.use({
1036
1035
  namespace,
1037
1036
  database
1038
1037
  });
1039
- this.logger.debug({ Category: "spooky-client::LocalDatabaseService::connect" }, "[LocalDatabaseService] client.use returned");
1040
- this.logger.info({ Category: "spooky-client::LocalDatabaseService::connect" }, "Connected to local database");
1038
+ this.logger.debug({ Category: "sp00ky-client::LocalDatabaseService::connect" }, "[LocalDatabaseService] client.use returned");
1039
+ this.logger.info({ Category: "sp00ky-client::LocalDatabaseService::connect" }, "Connected to local database");
1041
1040
  } catch (err) {
1042
1041
  this.logger.error({
1043
1042
  err,
1044
- Category: "spooky-client::LocalDatabaseService::connect"
1043
+ Category: "sp00ky-client::LocalDatabaseService::connect"
1045
1044
  }, "Failed to connect to local database");
1046
1045
  throw err;
1047
1046
  }
@@ -1062,7 +1061,7 @@ var RemoteDatabaseService = class extends AbstractDatabaseService {
1062
1061
  type,
1063
1062
  phase,
1064
1063
  service: "surrealdb:remote",
1065
- Category: "spooky-client::RemoteDatabaseService::diagnostics"
1064
+ Category: "sp00ky-client::RemoteDatabaseService::diagnostics"
1066
1065
  }, `Remote SurrealDB diagnostics captured ${type}:${phase}`);
1067
1066
  }) }), logger, events);
1068
1067
  this.config = config;
@@ -1077,7 +1076,7 @@ var RemoteDatabaseService = class extends AbstractDatabaseService {
1077
1076
  endpoint,
1078
1077
  namespace,
1079
1078
  database,
1080
- Category: "spooky-client::RemoteDatabaseService::connect"
1079
+ Category: "sp00ky-client::RemoteDatabaseService::connect"
1081
1080
  }, "Connecting to remote database");
1082
1081
  try {
1083
1082
  await this.client.connect(endpoint);
@@ -1086,18 +1085,18 @@ var RemoteDatabaseService = class extends AbstractDatabaseService {
1086
1085
  database
1087
1086
  });
1088
1087
  if (token) {
1089
- this.logger.debug({ Category: "spooky-client::RemoteDatabaseService::connect" }, "Authenticating with token");
1088
+ this.logger.debug({ Category: "sp00ky-client::RemoteDatabaseService::connect" }, "Authenticating with token");
1090
1089
  await this.client.authenticate(token);
1091
1090
  }
1092
- this.logger.info({ Category: "spooky-client::RemoteDatabaseService::connect" }, "Connected to remote database");
1091
+ this.logger.info({ Category: "sp00ky-client::RemoteDatabaseService::connect" }, "Connected to remote database");
1093
1092
  } catch (err) {
1094
1093
  this.logger.error({
1095
1094
  err,
1096
- Category: "spooky-client::RemoteDatabaseService::connect"
1095
+ Category: "sp00ky-client::RemoteDatabaseService::connect"
1097
1096
  }, "Failed to connect to remote database");
1098
1097
  throw err;
1099
1098
  }
1100
- } else this.logger.warn({ Category: "spooky-client::RemoteDatabaseService::connect" }, "No endpoint configured for remote database");
1099
+ } else this.logger.warn({ Category: "sp00ky-client::RemoteDatabaseService::connect" }, "No endpoint configured for remote database");
1101
1100
  }
1102
1101
  async signin(params) {
1103
1102
  return this.client.signin(params);
@@ -1115,70 +1114,14 @@ var RemoteDatabaseService = class extends AbstractDatabaseService {
1115
1114
 
1116
1115
  //#endregion
1117
1116
  //#region src/services/logger/index.ts
1118
- createContextKey("Category");
1119
- function mapLevelToSeverityNumber(level) {
1120
- switch (level) {
1121
- case "trace": return 1;
1122
- case "debug": return 5;
1123
- case "info": return 9;
1124
- case "warn": return 13;
1125
- case "error": return 17;
1126
- case "fatal": return 21;
1127
- default: return 9;
1128
- }
1129
- }
1130
- function createLogger(level = "info", otelEndpoint) {
1117
+ function createLogger(level = "info", transmit) {
1131
1118
  const browserConfig = {
1132
1119
  asObject: true,
1133
1120
  write: (o) => {
1134
1121
  console.log(JSON.stringify(o));
1135
1122
  }
1136
1123
  };
1137
- if (otelEndpoint) {
1138
- const loggerProvider = new LoggerProvider({
1139
- resource: resourceFromAttributes({ [ATTR_SERVICE_NAME]: "spooky-client" }),
1140
- processors: [new BatchLogRecordProcessor(new OTLPLogExporter({ url: otelEndpoint }))]
1141
- });
1142
- const otelLogger = {};
1143
- const getOtelLogger = (category) => {
1144
- if (!otelLogger[category]) otelLogger[category] = loggerProvider.getLogger(category);
1145
- return otelLogger[category];
1146
- };
1147
- browserConfig.transmit = {
1148
- level,
1149
- send: (levelLabel, logEvent) => {
1150
- try {
1151
- const messages = [...logEvent.messages];
1152
- const severityNumber = mapLevelToSeverityNumber(levelLabel);
1153
- let body = "";
1154
- const msg = messages.pop();
1155
- if (typeof msg === "string") body = msg;
1156
- else if (msg) body = JSON.stringify(msg);
1157
- let category = "spooky-client::unknown";
1158
- const attributes = {};
1159
- for (const msg of messages) if (typeof msg === "object") {
1160
- if (msg.Category) {
1161
- category = msg.Category;
1162
- delete msg.Category;
1163
- }
1164
- Object.assign(attributes, msg);
1165
- }
1166
- getOtelLogger(category).emit({
1167
- severityNumber,
1168
- severityText: levelLabel.toUpperCase(),
1169
- body,
1170
- attributes: {
1171
- ...logEvent.bindings[0],
1172
- ...attributes
1173
- },
1174
- timestamp: new Date(logEvent.ts)
1175
- });
1176
- } catch (e) {
1177
- console.warn("Failed to transmit log to OTEL endpoint", e);
1178
- }
1179
- }
1180
- };
1181
- }
1124
+ if (transmit) browserConfig.transmit = transmit;
1182
1125
  return pino({
1183
1126
  level,
1184
1127
  browser: browserConfig
@@ -1203,25 +1146,25 @@ var LocalMigrator = class {
1203
1146
  const hash = await sha1(schemaSurql);
1204
1147
  const { database } = this.localDb.getConfig();
1205
1148
  if (await this.isSchemaUpToDate(hash)) {
1206
- this.logger.info({ Category: "spooky-client::LocalMigrator::provision" }, "[Provisioning] Schema is up to date, skipping migration");
1149
+ this.logger.info({ Category: "sp00ky-client::LocalMigrator::provision" }, "[Provisioning] Schema is up to date, skipping migration");
1207
1150
  return;
1208
1151
  }
1209
1152
  await this.recreateDatabase(database);
1210
- const fullSchema = schemaSurql + "\n\n DEFINE TABLE IF NOT EXISTS _spooky_stream_processor_state SCHEMALESS PERMISSIONS FOR select, create, update, delete WHERE true;\n DEFINE TABLE IF NOT EXISTS _spooky_query SCHEMALESS PERMISSIONS FOR select, create, update, delete WHERE true;\n DEFINE TABLE IF NOT EXISTS _spooky_schema SCHEMALESS PERMISSIONS FOR select, create, update, delete WHERE true;\n DEFINE TABLE IF NOT EXISTS _spooky_pending_mutations SCHEMALESS PERMISSIONS FOR select, create, update, delete WHERE true;\n ";
1153
+ const fullSchema = schemaSurql + "\n\n DEFINE TABLE IF NOT EXISTS _00_stream_processor_state SCHEMALESS PERMISSIONS FOR select, create, update, delete WHERE true;\n DEFINE TABLE IF NOT EXISTS _00_query SCHEMALESS PERMISSIONS FOR select, create, update, delete WHERE true;\n DEFINE TABLE IF NOT EXISTS _00_schema SCHEMALESS PERMISSIONS FOR select, create, update, delete WHERE true;\n DEFINE TABLE IF NOT EXISTS _00_pending_mutations SCHEMALESS PERMISSIONS FOR select, create, update, delete WHERE true;\n ";
1211
1154
  const statements = this.splitStatements(fullSchema);
1212
1155
  for (let i = 0; i < statements.length; i++) {
1213
1156
  const statement = statements[i];
1214
1157
  const cleanStatement = statement.replace(/--.*/g, "").trim();
1215
1158
  if (cleanStatement.toUpperCase().startsWith("DEFINE INDEX")) {
1216
- this.logger.warn({ Category: "spooky-client::LocalMigrator::provision" }, `[Provisioning] Skipping index definition (WASM hang avoidance): ${cleanStatement.substring(0, 50)}...`);
1159
+ this.logger.warn({ Category: "sp00ky-client::LocalMigrator::provision" }, `[Provisioning] Skipping index definition (WASM hang avoidance): ${cleanStatement.substring(0, 50)}...`);
1217
1160
  continue;
1218
1161
  }
1219
1162
  try {
1220
- this.logger.info({ Category: "spooky-client::LocalMigrator::provision" }, `[Provisioning] (${i + 1}/${statements.length}) Executing: ${statement.substring(0, 50)}...`);
1163
+ this.logger.info({ Category: "sp00ky-client::LocalMigrator::provision" }, `[Provisioning] (${i + 1}/${statements.length}) Executing: ${statement.substring(0, 50)}...`);
1221
1164
  await this.localDb.query(statement);
1222
- this.logger.info({ Category: "spooky-client::LocalMigrator::provision" }, `[Provisioning] (${i + 1}/${statements.length}) Done`);
1165
+ this.logger.info({ Category: "sp00ky-client::LocalMigrator::provision" }, `[Provisioning] (${i + 1}/${statements.length}) Done`);
1223
1166
  } catch (e) {
1224
- this.logger.error({ Category: "spooky-client::LocalMigrator::provision" }, `[Provisioning] (${i + 1}/${statements.length}) Error executing statement: ${statement}`);
1167
+ this.logger.error({ Category: "sp00ky-client::LocalMigrator::provision" }, `[Provisioning] (${i + 1}/${statements.length}) Error executing statement: ${statement}`);
1225
1168
  throw e;
1226
1169
  }
1227
1170
  }
@@ -1229,22 +1172,22 @@ var LocalMigrator = class {
1229
1172
  }
1230
1173
  async isSchemaUpToDate(hash) {
1231
1174
  try {
1232
- const [lastSchemaRecord] = await this.localDb.query(`SELECT hash, created_at FROM ONLY _spooky_schema ORDER BY created_at DESC LIMIT 1;`);
1175
+ const [lastSchemaRecord] = await this.localDb.query(`SELECT hash, created_at FROM ONLY _00_schema ORDER BY created_at DESC LIMIT 1;`);
1233
1176
  return lastSchemaRecord?.hash === hash;
1234
- } catch (error) {
1177
+ } catch (_error) {
1235
1178
  return false;
1236
1179
  }
1237
1180
  }
1238
1181
  async recreateDatabase(database) {
1239
1182
  try {
1240
- await this.localDb.query(`DEFINE DATABASE _spooky_temp;`);
1241
- } catch (e) {}
1183
+ await this.localDb.query(`DEFINE DATABASE _00_temp;`);
1184
+ } catch (_e) {}
1242
1185
  try {
1243
1186
  await this.localDb.query(`
1244
- USE DB _spooky_temp;
1187
+ USE DB _00_temp;
1245
1188
  REMOVE DATABASE ${database};
1246
1189
  `);
1247
- } catch (e) {}
1190
+ } catch (_e) {}
1248
1191
  await this.localDb.query(`
1249
1192
  DEFINE DATABASE ${database};
1250
1193
  USE DB ${database};
@@ -1302,7 +1245,7 @@ var LocalMigrator = class {
1302
1245
  return statements;
1303
1246
  }
1304
1247
  async createHashRecord(hash) {
1305
- await this.localDb.query(`UPSERT _spooky_schema SET hash = $hash, created_at = time::now() WHERE hash = $hash;`, { hash });
1248
+ await this.localDb.query(`UPSERT _00_schema SET hash = $hash, created_at = time::now() WHERE hash = $hash;`, { hash });
1306
1249
  }
1307
1250
  };
1308
1251
 
@@ -1394,7 +1337,7 @@ var UpQueue = class {
1394
1337
  this.logger.error({
1395
1338
  error,
1396
1339
  event,
1397
- Category: "spooky-client::UpQueue::next"
1340
+ Category: "sp00ky-client::UpQueue::next"
1398
1341
  }, "Network error processing mutation, re-queuing");
1399
1342
  this.queue.unshift(event);
1400
1343
  throw error;
@@ -1402,7 +1345,7 @@ var UpQueue = class {
1402
1345
  this.logger.error({
1403
1346
  error,
1404
1347
  event,
1405
- Category: "spooky-client::UpQueue::next"
1348
+ Category: "sp00ky-client::UpQueue::next"
1406
1349
  }, "Application error processing mutation, rolling back");
1407
1350
  try {
1408
1351
  await this.removeEventFromDatabase(event.mutation_id);
@@ -1410,7 +1353,7 @@ var UpQueue = class {
1410
1353
  this.logger.error({
1411
1354
  error: removeError,
1412
1355
  event,
1413
- Category: "spooky-client::UpQueue::next"
1356
+ Category: "sp00ky-client::UpQueue::next"
1414
1357
  }, "Failed to remove rolled-back mutation from database");
1415
1358
  }
1416
1359
  if (onRollback) try {
@@ -1419,7 +1362,7 @@ var UpQueue = class {
1419
1362
  this.logger.error({
1420
1363
  error: rollbackError,
1421
1364
  event,
1422
- Category: "spooky-client::UpQueue::next"
1365
+ Category: "sp00ky-client::UpQueue::next"
1423
1366
  }, "Rollback handler failed");
1424
1367
  }
1425
1368
  this._events.addEvent({
@@ -1434,7 +1377,7 @@ var UpQueue = class {
1434
1377
  this.logger.error({
1435
1378
  error,
1436
1379
  event,
1437
- Category: "spooky-client::UpQueue::next"
1380
+ Category: "sp00ky-client::UpQueue::next"
1438
1381
  }, "Failed to remove mutation from database after successful processing");
1439
1382
  }
1440
1383
  this._events.addEvent({
@@ -1448,7 +1391,7 @@ var UpQueue = class {
1448
1391
  }
1449
1392
  async loadFromDatabase() {
1450
1393
  try {
1451
- const [records] = await this.local.query(`SELECT * FROM _spooky_pending_mutations ORDER BY created_at ASC`);
1394
+ const [records] = await this.local.query(`SELECT * FROM _00_pending_mutations ORDER BY created_at ASC`);
1452
1395
  this.queue = records.map((r) => {
1453
1396
  switch (r.mutationType) {
1454
1397
  case "create": return {
@@ -1474,7 +1417,7 @@ var UpQueue = class {
1474
1417
  this.logger.warn({
1475
1418
  mutationType: r.mutationType,
1476
1419
  record: r,
1477
- Category: "spooky-client::UpQueue::loadFromDatabase"
1420
+ Category: "sp00ky-client::UpQueue::loadFromDatabase"
1478
1421
  }, "Unknown mutation type");
1479
1422
  return null;
1480
1423
  }
@@ -1482,7 +1425,7 @@ var UpQueue = class {
1482
1425
  } catch (error) {
1483
1426
  this.logger.error({
1484
1427
  error,
1485
- Category: "spooky-client::UpQueue::loadFromDatabase"
1428
+ Category: "sp00ky-client::UpQueue::loadFromDatabase"
1486
1429
  }, "Failed to load pending mutations from database");
1487
1430
  }
1488
1431
  }
@@ -1523,7 +1466,7 @@ var DownQueue = class {
1523
1466
  this.logger.error({
1524
1467
  error,
1525
1468
  event,
1526
- Category: "spooky-client::DownQueue::next"
1469
+ Category: "sp00ky-client::DownQueue::next"
1527
1470
  }, "Failed to process query");
1528
1471
  this.queue.unshift(event);
1529
1472
  throw error;
@@ -1538,8 +1481,8 @@ var ArraySyncer = class {
1538
1481
  remoteArray;
1539
1482
  needsSort = false;
1540
1483
  constructor(localArray, remoteArray) {
1541
- this.remoteArray = remoteArray.sort((a, b) => a[0].localeCompare(b[0]));
1542
- this.localArray = localArray.sort((a, b) => a[0].localeCompare(b[0]));
1484
+ this.remoteArray = remoteArray.toSorted((a, b) => a[0].localeCompare(b[0]));
1485
+ this.localArray = localArray.toSorted((a, b) => a[0].localeCompare(b[0]));
1543
1486
  }
1544
1487
  /**
1545
1488
  * Inserts an item into the local array
@@ -1575,7 +1518,6 @@ var ArraySyncer = class {
1575
1518
  this.localArray.sort((a, b) => a[0].localeCompare(b[0]));
1576
1519
  this.needsSort = false;
1577
1520
  }
1578
- console.log("xxxx555", this.localArray, this.remoteArray);
1579
1521
  return diffRecordVersionArray(this.localArray, this.remoteArray);
1580
1522
  }
1581
1523
  };
@@ -1606,14 +1548,12 @@ function diffRecordVersionArray(local, remote) {
1606
1548
  };
1607
1549
  }
1608
1550
  function createDiffFromDbOp(op, recordId, version, versions) {
1609
- if (op !== "DELETE") {
1610
- const old = versions?.find((record) => record[0] === encodeRecordId(recordId));
1611
- if (old && old[1] >= version) return {
1612
- added: [],
1613
- updated: [],
1614
- removed: []
1615
- };
1616
- }
1551
+ const old = versions?.find((record) => record[0] === encodeRecordId(recordId));
1552
+ if (old && old[1] >= version) return {
1553
+ added: [],
1554
+ updated: [],
1555
+ removed: []
1556
+ };
1617
1557
  if (op === "CREATE") return {
1618
1558
  added: [{
1619
1559
  id: recordId,
@@ -1643,7 +1583,7 @@ function createDiffFromDbOp(op, recordId, version, versions) {
1643
1583
  * SyncEngine handles the core sync operations: fetching remote records,
1644
1584
  * caching them locally, and ingesting into DBSP.
1645
1585
  *
1646
- * This is extracted from SpookySync to separate "how to sync" from "when to sync".
1586
+ * This is extracted from Sp00kySync to separate "how to sync" from "when to sync".
1647
1587
  */
1648
1588
  var SyncEngine = class {
1649
1589
  logger;
@@ -1652,7 +1592,7 @@ var SyncEngine = class {
1652
1592
  this.remote = remote;
1653
1593
  this.cache = cache;
1654
1594
  this.schema = schema;
1655
- this.logger = logger.child({ service: "SpookySync:SyncEngine" });
1595
+ this.logger = logger.child({ service: "Sp00kySync:SyncEngine" });
1656
1596
  }
1657
1597
  /**
1658
1598
  * Sync missing/updated/removed records between local and remote.
@@ -1665,33 +1605,36 @@ var SyncEngine = class {
1665
1605
  added,
1666
1606
  updated,
1667
1607
  removed,
1668
- Category: "spooky-client::SyncEngine::syncRecords"
1608
+ Category: "sp00ky-client::SyncEngine::syncRecords"
1669
1609
  }, "SyncEngine.syncRecords diff");
1670
1610
  if (removed.length > 0) await this.handleRemovedRecords(removed);
1671
- const idsToFetch = [...added, ...updated].map((x) => x.id);
1611
+ const toFetch = [...added, ...updated];
1612
+ const idsToFetch = toFetch.map((x) => x.id);
1672
1613
  if (idsToFetch.length === 0) return;
1673
- const [remoteResults] = await this.remote.query("SELECT (SELECT * FROM ONLY <record>$parent.id) AS record, (SELECT version FROM ONLY _spooky_version WHERE record_id = <record>$parent.id)['version'] as spooky_rv FROM $idsToFetch", { idsToFetch });
1674
- console.log("remoteResults>", remoteResults);
1614
+ const versionMap = /* @__PURE__ */ new Map();
1615
+ for (const item of toFetch) versionMap.set(encodeRecordId(item.id), item.version);
1616
+ const [remoteResults] = await this.remote.query("SELECT * FROM $idsToFetch", { idsToFetch });
1675
1617
  const cacheBatch = [];
1676
- for (const { spooky_rv, record } of remoteResults) {
1618
+ for (const record of remoteResults) {
1677
1619
  if (!record?.id) {
1678
1620
  this.logger.warn({
1679
1621
  record,
1680
1622
  idsToFetch,
1681
- Category: "spooky-client::SyncEngine::syncRecords"
1682
- }, "Remote record has no id. Skipping record");
1623
+ Category: "sp00ky-client::SyncEngine::syncRecords"
1624
+ }, "Remote record has no id (possibly deleted). Skipping record");
1683
1625
  continue;
1684
1626
  }
1685
1627
  const fullId = encodeRecordId(record.id);
1686
1628
  const table = record.id.table.toString();
1687
1629
  const isAdded = added.some((item) => encodeRecordId(item.id) === fullId);
1630
+ const version = versionMap.get(fullId) ?? 0;
1688
1631
  const localVersion = this.cache.lookup(fullId);
1689
- if (localVersion && spooky_rv <= localVersion) {
1632
+ if (localVersion && version <= localVersion) {
1690
1633
  this.logger.info({
1691
1634
  recordId: fullId,
1692
- version: spooky_rv,
1635
+ version,
1693
1636
  localVersion,
1694
- Category: "spooky-client::SyncEngine::syncRecords"
1637
+ Category: "sp00ky-client::SyncEngine::syncRecords"
1695
1638
  }, "Local version is higher than remote version. Skipping record");
1696
1639
  continue;
1697
1640
  }
@@ -1701,7 +1644,7 @@ var SyncEngine = class {
1701
1644
  table,
1702
1645
  op: isAdded ? "CREATE" : "UPDATE",
1703
1646
  record: cleanedRecord,
1704
- version: spooky_rv
1647
+ version
1705
1648
  });
1706
1649
  }
1707
1650
  if (cacheBatch.length > 0) await this.cache.saveBatch(cacheBatch);
@@ -1713,21 +1656,21 @@ var SyncEngine = class {
1713
1656
  async handleRemovedRecords(removed) {
1714
1657
  this.logger.debug({
1715
1658
  removed: removed.map((r) => r.toString()),
1716
- Category: "spooky-client::SyncEngine::handleRemovedRecords"
1659
+ Category: "sp00ky-client::SyncEngine::handleRemovedRecords"
1717
1660
  }, "Checking removed records");
1718
1661
  let existingRemoteIds = /* @__PURE__ */ new Set();
1719
1662
  try {
1720
1663
  const [existingRemote] = await this.remote.query("SELECT id FROM $ids", { ids: removed });
1721
1664
  existingRemoteIds = new Set(existingRemote.map((r) => encodeRecordId(r.id)));
1722
1665
  } catch {
1723
- this.logger.debug({ Category: "spooky-client::SyncEngine::handleRemovedRecords" }, "Remote existence check failed, proceeding with deletion");
1666
+ this.logger.debug({ Category: "sp00ky-client::SyncEngine::handleRemovedRecords" }, "Remote existence check failed, proceeding with deletion");
1724
1667
  }
1725
1668
  for (const recordId of removed) {
1726
1669
  const recordIdStr = encodeRecordId(recordId);
1727
1670
  if (!existingRemoteIds.has(recordIdStr)) {
1728
1671
  this.logger.debug({
1729
1672
  recordId: recordIdStr,
1730
- Category: "spooky-client::SyncEngine::handleRemovedRecords"
1673
+ Category: "sp00ky-client::SyncEngine::handleRemovedRecords"
1731
1674
  }, "Deleting confirmed removed record");
1732
1675
  await this.cache.delete(recordId.table.name, recordIdStr);
1733
1676
  }
@@ -1806,12 +1749,12 @@ var SyncScheduler = class {
1806
1749
  //#endregion
1807
1750
  //#region src/modules/sync/sync.ts
1808
1751
  /**
1809
- * The main synchronization engine for Spooky.
1752
+ * The main synchronization engine for Sp00ky.
1810
1753
  * Handles the bidirectional synchronization between the local database and the remote backend.
1811
1754
  * Uses a queue-based architecture with 'up' (local to remote) and 'down' (remote to local) queues.
1812
1755
  * @template S The schema structure type.
1813
1756
  */
1814
- var SpookySync = class {
1757
+ var Sp00kySync = class {
1815
1758
  clientId = "";
1816
1759
  upQueue;
1817
1760
  downQueue;
@@ -1840,7 +1783,7 @@ var SpookySync = class {
1840
1783
  this.cache = cache;
1841
1784
  this.dataModule = dataModule;
1842
1785
  this.schema = schema;
1843
- this.logger = logger.child({ service: "SpookySync" });
1786
+ this.logger = logger.child({ service: "Sp00kySync" });
1844
1787
  this.upQueue = new UpQueue(this.local, this.logger);
1845
1788
  this.downQueue = new DownQueue(this.local, this.logger);
1846
1789
  this.syncEngine = new SyncEngine(this.remote, this.cache, this.schema, this.logger);
@@ -1853,7 +1796,7 @@ var SpookySync = class {
1853
1796
  * @throws Error if already initialized.
1854
1797
  */
1855
1798
  async init(clientId) {
1856
- if (this.isInit) throw new Error("SpookySync is already initialized");
1799
+ if (this.isInit) throw new Error("Sp00kySync is already initialized");
1857
1800
  this.clientId = clientId;
1858
1801
  this.isInit = true;
1859
1802
  await this.scheduler.init();
@@ -1865,29 +1808,37 @@ var SpookySync = class {
1865
1808
  async startRefLiveQueries() {
1866
1809
  this.logger.debug({
1867
1810
  clientId: this.clientId,
1868
- Category: "spooky-client::SpookySync::startRefLiveQueries"
1811
+ Category: "sp00ky-client::Sp00kySync::startRefLiveQueries"
1869
1812
  }, "Starting ref live queries");
1870
- const [queryUuid] = await this.remote.query("LIVE SELECT * FROM _spooky_list_ref");
1813
+ const [queryUuid] = await this.remote.query("LIVE SELECT * FROM _00_list_ref");
1871
1814
  (await this.remote.getClient().liveOf(queryUuid)).subscribe((message) => {
1872
1815
  this.logger.debug({
1873
1816
  message,
1874
- Category: "spooky-client::SpookySync::startRefLiveQueries"
1817
+ Category: "sp00ky-client::Sp00kySync::startRefLiveQueries"
1875
1818
  }, "Live update received");
1876
1819
  if (message.action === "KILLED") return;
1877
1820
  this.handleRemoteListRefChange(message.action, message.value.in, message.value.out, message.value.version).catch((err) => {
1878
1821
  this.logger.error({
1879
1822
  err,
1880
- Category: "spooky-client::SpookySync::startRefLiveQueries"
1823
+ Category: "sp00ky-client::Sp00kySync::startRefLiveQueries"
1881
1824
  }, "Error handling remote list ref change");
1882
1825
  });
1883
1826
  });
1884
1827
  }
1885
1828
  async handleRemoteListRefChange(action, queryId, recordId, version) {
1829
+ if (action === "DELETE") {
1830
+ this.logger.debug({
1831
+ queryId: queryId.toString(),
1832
+ recordId: recordId.toString(),
1833
+ Category: "sp00ky-client::Sp00kySync::handleRemoteListRefChange"
1834
+ }, "Ignoring DELETE on list_ref — should not happen");
1835
+ return;
1836
+ }
1886
1837
  const existing = this.dataModule.getQueryById(queryId);
1887
1838
  if (!existing) {
1888
1839
  this.logger.warn({
1889
1840
  queryId: queryId.toString(),
1890
- Category: "spooky-client::SpookySync::handleRemoteListRefChange"
1841
+ Category: "sp00ky-client::Sp00kySync::handleRemoteListRefChange"
1891
1842
  }, "Received remote update for unknown local query");
1892
1843
  return;
1893
1844
  }
@@ -1898,7 +1849,7 @@ var SpookySync = class {
1898
1849
  recordId,
1899
1850
  version,
1900
1851
  localArray,
1901
- Category: "spooky-client::SpookySync::handleRemoteListRefChange"
1852
+ Category: "sp00ky-client::Sp00kySync::handleRemoteListRefChange"
1902
1853
  }, "Live update is being processed");
1903
1854
  const diff = createDiffFromDbOp(action, recordId, version, localArray);
1904
1855
  await this.syncEngine.syncRecords(diff);
@@ -1913,9 +1864,8 @@ var SpookySync = class {
1913
1864
  async processUpEvent(event) {
1914
1865
  this.logger.debug({
1915
1866
  event,
1916
- Category: "spooky-client::SpookySync::processUpEvent"
1867
+ Category: "sp00ky-client::Sp00kySync::processUpEvent"
1917
1868
  }, "Processing up event");
1918
- console.log("xx1", event);
1919
1869
  switch (event.type) {
1920
1870
  case "create":
1921
1871
  const dataKeys = Object.keys(event.data).map((key) => ({
@@ -1941,7 +1891,7 @@ var SpookySync = class {
1941
1891
  default:
1942
1892
  this.logger.error({
1943
1893
  event,
1944
- Category: "spooky-client::SpookySync::processUpEvent"
1894
+ Category: "sp00ky-client::Sp00kySync::processUpEvent"
1945
1895
  }, "processUpEvent unknown event type");
1946
1896
  return;
1947
1897
  }
@@ -1954,7 +1904,7 @@ var SpookySync = class {
1954
1904
  recordId,
1955
1905
  tableName,
1956
1906
  error: error.message,
1957
- Category: "spooky-client::SpookySync::handleRollback"
1907
+ Category: "sp00ky-client::Sp00kySync::handleRollback"
1958
1908
  }, "Rolling back failed mutation");
1959
1909
  switch (event.type) {
1960
1910
  case "create":
@@ -1964,13 +1914,13 @@ var SpookySync = class {
1964
1914
  if (event.beforeRecord) await this.dataModule.rollbackUpdate(event.record_id, tableName, event.beforeRecord);
1965
1915
  else this.logger.warn({
1966
1916
  recordId,
1967
- Category: "spooky-client::SpookySync::handleRollback"
1917
+ Category: "sp00ky-client::Sp00kySync::handleRollback"
1968
1918
  }, "Cannot rollback update: no beforeRecord available. Down-sync will reconcile.");
1969
1919
  break;
1970
1920
  case "delete":
1971
1921
  this.logger.warn({
1972
1922
  recordId,
1973
- Category: "spooky-client::SpookySync::handleRollback"
1923
+ Category: "sp00ky-client::Sp00kySync::handleRollback"
1974
1924
  }, "Delete rollback not implemented. Down-sync will reconcile.");
1975
1925
  break;
1976
1926
  }
@@ -1983,7 +1933,7 @@ var SpookySync = class {
1983
1933
  async processDownEvent(event) {
1984
1934
  this.logger.debug({
1985
1935
  event,
1986
- Category: "spooky-client::SpookySync::processDownEvent"
1936
+ Category: "sp00ky-client::Sp00kySync::processDownEvent"
1987
1937
  }, "Processing down event");
1988
1938
  switch (event.type) {
1989
1939
  case "register": return this.registerQuery(event.payload.hash);
@@ -2002,7 +1952,7 @@ var SpookySync = class {
2002
1952
  if (!queryState) {
2003
1953
  this.logger.warn({
2004
1954
  hash,
2005
- Category: "spooky-client::SpookySync::syncQuery"
1955
+ Category: "sp00ky-client::Sp00kySync::syncQuery"
2006
1956
  }, "Query not found");
2007
1957
  return;
2008
1958
  }
@@ -2021,7 +1971,7 @@ var SpookySync = class {
2021
1971
  try {
2022
1972
  this.logger.debug({
2023
1973
  queryHash,
2024
- Category: "spooky-client::SpookySync::registerQuery"
1974
+ Category: "sp00ky-client::Sp00kySync::registerQuery"
2025
1975
  }, "Register Query state");
2026
1976
  await this.createRemoteQuery(queryHash);
2027
1977
  await this.syncQuery(queryHash);
@@ -2029,7 +1979,7 @@ var SpookySync = class {
2029
1979
  } catch (e) {
2030
1980
  this.logger.error({
2031
1981
  err: e,
2032
- Category: "spooky-client::SpookySync::registerQuery"
1982
+ Category: "sp00ky-client::Sp00kySync::registerQuery"
2033
1983
  }, "registerQuery error");
2034
1984
  throw e;
2035
1985
  }
@@ -2039,7 +1989,7 @@ var SpookySync = class {
2039
1989
  if (!queryState) {
2040
1990
  this.logger.warn({
2041
1991
  queryHash,
2042
- Category: "spooky-client::SpookySync::createRemoteQuery"
1992
+ Category: "sp00ky-client::Sp00kySync::createRemoteQuery"
2043
1993
  }, "Query to register not found");
2044
1994
  throw new Error("Query to register not found");
2045
1995
  }
@@ -2050,17 +2000,17 @@ var SpookySync = class {
2050
2000
  params: queryState.config.params,
2051
2001
  ttl: queryState.config.ttl
2052
2002
  } });
2053
- const [items] = await this.remote.query(surql.selectByFieldsAnd("_spooky_list_ref", ["in"], ["out", "version"]), { in: queryState.config.id });
2003
+ const [items] = await this.remote.query(surql.selectByFieldsAnd("_00_list_ref", ["in"], ["out", "version"]), { in: queryState.config.id });
2054
2004
  this.logger.trace({
2055
2005
  queryId: encodeRecordId(queryState.config.id),
2056
2006
  items,
2057
- Category: "spooky-client::SpookySync::createRemoteQuery"
2007
+ Category: "sp00ky-client::Sp00kySync::createRemoteQuery"
2058
2008
  }, "Got query record version array from remote");
2059
2009
  const array = items.map((item) => [encodeRecordId(item.out), item.version]);
2060
2010
  this.logger.debug({
2061
2011
  queryId: encodeRecordId(queryState.config.id),
2062
2012
  array,
2063
- Category: "spooky-client::SpookySync::createRemoteQuery"
2013
+ Category: "sp00ky-client::Sp00kySync::createRemoteQuery"
2064
2014
  }, "createdRemoteQuery");
2065
2015
  if (array) await this.dataModule.updateQueryRemoteArray(queryHash, array);
2066
2016
  }
@@ -2069,7 +2019,7 @@ var SpookySync = class {
2069
2019
  if (!queryState) {
2070
2020
  this.logger.warn({
2071
2021
  queryHash,
2072
- Category: "spooky-client::SpookySync::heartbeatQuery"
2022
+ Category: "sp00ky-client::Sp00kySync::heartbeatQuery"
2073
2023
  }, "Query to register not found");
2074
2024
  throw new Error("Query to register not found");
2075
2025
  }
@@ -2080,7 +2030,7 @@ var SpookySync = class {
2080
2030
  if (!queryState) {
2081
2031
  this.logger.warn({
2082
2032
  queryHash,
2083
- Category: "spooky-client::SpookySync::cleanupQuery"
2033
+ Category: "sp00ky-client::Sp00kySync::cleanupQuery"
2084
2034
  }, "Query to register not found");
2085
2035
  throw new Error("Query to register not found");
2086
2036
  }
@@ -2112,7 +2062,7 @@ var DevToolsService = class {
2112
2062
  this.authService.eventSystem.subscribe(AuthEventTypes.AuthStateChanged, () => {
2113
2063
  this.notifyDevTools();
2114
2064
  });
2115
- this.logger.debug({ Category: "spooky-client::DevToolsService::init" }, "Service initialized");
2065
+ this.logger.debug({ Category: "sp00ky-client::DevToolsService::init" }, "Service initialized");
2116
2066
  }
2117
2067
  getActiveQueries() {
2118
2068
  const result = /* @__PURE__ */ new Map();
@@ -2138,7 +2088,7 @@ var DevToolsService = class {
2138
2088
  onQueryInitialized(payload) {
2139
2089
  this.logger.debug({
2140
2090
  payload,
2141
- Category: "spooky-client::DevToolsService::onQueryInitialized"
2091
+ Category: "sp00ky-client::DevToolsService::onQueryInitialized"
2142
2092
  }, "QueryInitialized");
2143
2093
  const queryHash = this.hashString(payload.queryId.toString());
2144
2094
  this.addEvent("QUERY_REQUEST_INIT", {
@@ -2151,7 +2101,7 @@ var DevToolsService = class {
2151
2101
  onQueryUpdated(payload) {
2152
2102
  this.logger.debug({
2153
2103
  id: payload.queryId?.toString(),
2154
- Category: "spooky-client::DevToolsService::onQueryUpdated"
2104
+ Category: "sp00ky-client::DevToolsService::onQueryUpdated"
2155
2105
  }, "QueryUpdated");
2156
2106
  const queryHash = this.hashString(payload.queryId.toString());
2157
2107
  this.addEvent("QUERY_UPDATED", {
@@ -2163,7 +2113,7 @@ var DevToolsService = class {
2163
2113
  onStreamUpdate(update) {
2164
2114
  this.logger.debug({
2165
2115
  update,
2166
- Category: "spooky-client::DevToolsService::onStreamUpdate"
2116
+ Category: "sp00ky-client::DevToolsService::onStreamUpdate"
2167
2117
  }, "StreamUpdate");
2168
2118
  this.addEvent("STREAM_UPDATE", { updates: [update] });
2169
2119
  this.notifyDevTools();
@@ -2218,8 +2168,8 @@ var DevToolsService = class {
2218
2168
  }
2219
2169
  notifyDevTools() {
2220
2170
  if (typeof window !== "undefined") window.postMessage({
2221
- type: "SPOOKY_STATE_CHANGED",
2222
- source: "spooky-devtools-page",
2171
+ type: "SP00KY_STATE_CHANGED",
2172
+ source: "sp00ky-devtools-page",
2223
2173
  state: this.getState()
2224
2174
  }, "*");
2225
2175
  }
@@ -2245,7 +2195,7 @@ var DevToolsService = class {
2245
2195
  }
2246
2196
  exposeToWindow() {
2247
2197
  if (typeof window !== "undefined") {
2248
- window.__SPOOKY__ = {
2198
+ window.__00__ = {
2249
2199
  version: this.version,
2250
2200
  getState: () => this.getState(),
2251
2201
  clearHistory: () => {
@@ -2266,7 +2216,7 @@ var DevToolsService = class {
2266
2216
  } catch (e) {
2267
2217
  this.logger.error({
2268
2218
  err: e,
2269
- Category: "spooky-client::DevToolsService::exposeToWindow"
2219
+ Category: "sp00ky-client::DevToolsService::exposeToWindow"
2270
2220
  }, "Failed to get table data");
2271
2221
  return [];
2272
2222
  }
@@ -2298,7 +2248,7 @@ var DevToolsService = class {
2298
2248
  this.logger.debug({
2299
2249
  query,
2300
2250
  target,
2301
- Category: "spooky-client::DevToolsService::runQuery"
2251
+ Category: "sp00ky-client::DevToolsService::runQuery"
2302
2252
  }, "Running query (START)");
2303
2253
  const service = target === "remote" ? this.remoteDatabaseService : this.databaseService;
2304
2254
  const startTime = Date.now();
@@ -2309,7 +2259,7 @@ var DevToolsService = class {
2309
2259
  time: queryTime,
2310
2260
  resultType: typeof result,
2311
2261
  isArray: Array.isArray(result),
2312
- Category: "spooky-client::DevToolsService::runQuery"
2262
+ Category: "sp00ky-client::DevToolsService::runQuery"
2313
2263
  }, "Database returned result");
2314
2264
  const serializeStart = Date.now();
2315
2265
  const serialized = this.serializeForDevTools(result);
@@ -2317,7 +2267,7 @@ var DevToolsService = class {
2317
2267
  this.logger.debug({
2318
2268
  serializeTime,
2319
2269
  serializedLength: JSON.stringify(serialized).length,
2320
- Category: "spooky-client::DevToolsService::runQuery"
2270
+ Category: "sp00ky-client::DevToolsService::runQuery"
2321
2271
  }, "Serialization complete");
2322
2272
  return {
2323
2273
  success: true,
@@ -2329,7 +2279,7 @@ var DevToolsService = class {
2329
2279
  err: e,
2330
2280
  query,
2331
2281
  target,
2332
- Category: "spooky-client::DevToolsService::runQuery"
2282
+ Category: "sp00ky-client::DevToolsService::runQuery"
2333
2283
  }, "Query execution failed");
2334
2284
  return {
2335
2285
  success: false,
@@ -2339,13 +2289,14 @@ var DevToolsService = class {
2339
2289
  }
2340
2290
  };
2341
2291
  window.postMessage({
2342
- type: "SPOOKY_DETECTED",
2343
- source: "spooky-devtools-page",
2292
+ type: "SP00KY_DETECTED",
2293
+ source: "sp00ky-devtools-page",
2344
2294
  data: {
2345
2295
  version: this.version,
2346
2296
  detected: true
2347
2297
  }
2348
2298
  }, "*");
2299
+ window.dispatchEvent(new CustomEvent("sp00ky:init"));
2349
2300
  }
2350
2301
  }
2351
2302
  };
@@ -2396,9 +2347,9 @@ var AuthService = class {
2396
2347
  async check(accessToken) {
2397
2348
  this.isLoading = true;
2398
2349
  try {
2399
- const token = accessToken || await this.persistenceClient.get("spooky_auth_token");
2350
+ const token = accessToken || await this.persistenceClient.get("sp00ky_auth_token");
2400
2351
  if (!token) {
2401
- this.logger.debug({ Category: "spooky-client::AuthService::check" }, "No token found in storage or arguments");
2352
+ this.logger.debug({ Category: "sp00ky-client::AuthService::check" }, "No token found in storage or arguments");
2402
2353
  this.isLoading = false;
2403
2354
  this.isAuthenticated = false;
2404
2355
  this.notifyListeners();
@@ -2411,22 +2362,22 @@ var AuthService = class {
2411
2362
  if (user && user.id) {
2412
2363
  this.logger.info({
2413
2364
  user,
2414
- Category: "spooky-client::AuthService::check"
2365
+ Category: "sp00ky-client::AuthService::check"
2415
2366
  }, "Auth check complete (via $auth.id)");
2416
2367
  await this.setSession(token, user);
2417
2368
  } else {
2418
- this.logger.warn({ Category: "spooky-client::AuthService::check" }, "$auth.id empty, attempting manual user fetch");
2369
+ this.logger.warn({ Category: "sp00ky-client::AuthService::check" }, "$auth.id empty, attempting manual user fetch");
2419
2370
  const manualResult = await this.remote.query("SELECT * FROM user WHERE id = $auth.id LIMIT 1");
2420
2371
  const manualItems = Array.isArray(manualResult) && Array.isArray(manualResult[0]) ? manualResult[0] : manualResult;
2421
2372
  const manualUser = Array.isArray(manualItems) ? manualItems[0] : manualItems;
2422
2373
  if (manualUser && manualUser.id) {
2423
2374
  this.logger.info({
2424
2375
  user: manualUser,
2425
- Category: "spooky-client::AuthService::check"
2376
+ Category: "sp00ky-client::AuthService::check"
2426
2377
  }, "Auth check complete (via manual fetch)");
2427
2378
  await this.setSession(token, manualUser);
2428
2379
  } else {
2429
- this.logger.warn({ Category: "spooky-client::AuthService::check" }, "Token valid but user not found via fallback");
2380
+ this.logger.warn({ Category: "sp00ky-client::AuthService::check" }, "Token valid but user not found via fallback");
2430
2381
  await this.signOut();
2431
2382
  }
2432
2383
  }
@@ -2434,7 +2385,7 @@ var AuthService = class {
2434
2385
  this.logger.error({
2435
2386
  error,
2436
2387
  stack: error.stack,
2437
- Category: "spooky-client::AuthService::check"
2388
+ Category: "sp00ky-client::AuthService::check"
2438
2389
  }, "Auth check failed");
2439
2390
  await this.signOut();
2440
2391
  } finally {
@@ -2448,17 +2399,17 @@ var AuthService = class {
2448
2399
  this.token = null;
2449
2400
  this.currentUser = null;
2450
2401
  this.isAuthenticated = false;
2451
- await this.persistenceClient.remove("spooky_auth_token");
2402
+ await this.persistenceClient.remove("sp00ky_auth_token");
2452
2403
  try {
2453
2404
  await this.remote.getClient().invalidate();
2454
- } catch (e) {}
2405
+ } catch (_e) {}
2455
2406
  this.notifyListeners();
2456
2407
  }
2457
2408
  async setSession(token, user) {
2458
2409
  this.token = token;
2459
2410
  this.currentUser = user;
2460
2411
  this.isAuthenticated = true;
2461
- await this.persistenceClient.set("spooky_auth_token", token);
2412
+ await this.persistenceClient.set("sp00ky_auth_token", token);
2462
2413
  this.notifyListeners();
2463
2414
  }
2464
2415
  async signUp(accessName, params) {
@@ -2470,13 +2421,13 @@ var AuthService = class {
2470
2421
  this.logger.info({
2471
2422
  accessName,
2472
2423
  runtimeParams,
2473
- Category: "spooky-client::AuthService::signUp"
2424
+ Category: "sp00ky-client::AuthService::signUp"
2474
2425
  }, "Attempting signup");
2475
2426
  const { access } = await this.remote.getClient().signup({
2476
2427
  access: accessName,
2477
2428
  variables: runtimeParams
2478
2429
  });
2479
- this.logger.info({ Category: "spooky-client::AuthService::signUp" }, "Signup successful, token received");
2430
+ this.logger.info({ Category: "sp00ky-client::AuthService::signUp" }, "Signup successful, token received");
2480
2431
  await this.check(access);
2481
2432
  }
2482
2433
  async signIn(accessName, params) {
@@ -2487,7 +2438,7 @@ var AuthService = class {
2487
2438
  if (missingParams.length > 0) throw new Error(`Missing required signin params for '${accessName}': ${missingParams.join(", ")}`);
2488
2439
  this.logger.info({
2489
2440
  accessName,
2490
- Category: "spooky-client::AuthService::signIn"
2441
+ Category: "sp00ky-client::AuthService::signIn"
2491
2442
  }, "Attempting signin");
2492
2443
  const { access } = await this.remote.getClient().signin({
2493
2444
  access: accessName,
@@ -2526,17 +2477,17 @@ var StreamProcessorService = class {
2526
2477
  */
2527
2478
  async init() {
2528
2479
  if (this.isInitialized) return;
2529
- this.logger.info({ Category: "spooky-client::StreamProcessorService::init" }, "Initializing WASM...");
2480
+ this.logger.info({ Category: "sp00ky-client::StreamProcessorService::init" }, "Initializing WASM...");
2530
2481
  try {
2531
2482
  await init();
2532
- this.processor = new SpookyProcessor();
2483
+ this.processor = new Sp00kyProcessor();
2533
2484
  await this.loadState();
2534
2485
  this.isInitialized = true;
2535
- this.logger.info({ Category: "spooky-client::StreamProcessorService::init" }, "Initialized successfully");
2486
+ this.logger.info({ Category: "sp00ky-client::StreamProcessorService::init" }, "Initialized successfully");
2536
2487
  } catch (e) {
2537
2488
  this.logger.error({
2538
2489
  error: e,
2539
- Category: "spooky-client::StreamProcessorService::init"
2490
+ Category: "sp00ky-client::StreamProcessorService::init"
2540
2491
  }, "Failed to initialize");
2541
2492
  throw e;
2542
2493
  }
@@ -2544,20 +2495,20 @@ var StreamProcessorService = class {
2544
2495
  async loadState() {
2545
2496
  if (!this.processor) return;
2546
2497
  try {
2547
- const result = await this.persistenceClient.get("_spooky_stream_processor_state");
2498
+ const result = await this.persistenceClient.get("_00_stream_processor_state");
2548
2499
  if (Array.isArray(result) && result.length > 0 && Array.isArray(result[0]) && result[0].length > 0 && result[0][0]?.state) {
2549
2500
  const state = result[0][0].state;
2550
2501
  this.logger.info({
2551
2502
  stateLength: state.length,
2552
- Category: "spooky-client::StreamProcessorService::loadState"
2503
+ Category: "sp00ky-client::StreamProcessorService::loadState"
2553
2504
  }, "Loading state from DB");
2554
2505
  if (typeof this.processor.load_state === "function") this.processor.load_state(state);
2555
- else this.logger.warn({ Category: "spooky-client::StreamProcessorService::loadState" }, "load_state method not found on processor");
2556
- } else this.logger.info({ Category: "spooky-client::StreamProcessorService::loadState" }, "No saved state found");
2506
+ else this.logger.warn({ Category: "sp00ky-client::StreamProcessorService::loadState" }, "load_state method not found on processor");
2507
+ } else this.logger.info({ Category: "sp00ky-client::StreamProcessorService::loadState" }, "No saved state found");
2557
2508
  } catch (e) {
2558
2509
  this.logger.error({
2559
2510
  error: e,
2560
- Category: "spooky-client::StreamProcessorService::loadState"
2511
+ Category: "sp00ky-client::StreamProcessorService::loadState"
2561
2512
  }, "Failed to load state");
2562
2513
  }
2563
2514
  }
@@ -2567,14 +2518,14 @@ var StreamProcessorService = class {
2567
2518
  if (typeof this.processor.save_state === "function") {
2568
2519
  const state = this.processor.save_state();
2569
2520
  if (state) {
2570
- await this.persistenceClient.set("_spooky_stream_processor_state", state);
2571
- this.logger.trace({ Category: "spooky-client::StreamProcessorService::saveState" }, "State saved");
2521
+ await this.persistenceClient.set("_00_stream_processor_state", state);
2522
+ this.logger.trace({ Category: "sp00ky-client::StreamProcessorService::saveState" }, "State saved");
2572
2523
  }
2573
2524
  }
2574
2525
  } catch (e) {
2575
2526
  this.logger.error({
2576
2527
  error: e,
2577
- Category: "spooky-client::StreamProcessorService::saveState"
2528
+ Category: "sp00ky-client::StreamProcessorService::saveState"
2578
2529
  }, "Failed to save state");
2579
2530
  }
2580
2531
  }
@@ -2588,10 +2539,10 @@ var StreamProcessorService = class {
2588
2539
  table,
2589
2540
  op,
2590
2541
  id,
2591
- Category: "spooky-client::StreamProcessorService::ingest"
2542
+ Category: "sp00ky-client::StreamProcessorService::ingest"
2592
2543
  }, "Ingesting into ssp");
2593
2544
  if (!this.processor) {
2594
- this.logger.warn({ Category: "spooky-client::StreamProcessorService::ingest" }, "Not initialized, skipping ingest");
2545
+ this.logger.warn({ Category: "sp00ky-client::StreamProcessorService::ingest" }, "Not initialized, skipping ingest");
2595
2546
  return [];
2596
2547
  }
2597
2548
  try {
@@ -2602,7 +2553,7 @@ var StreamProcessorService = class {
2602
2553
  op,
2603
2554
  id,
2604
2555
  rawUpdates: rawUpdates.length,
2605
- Category: "spooky-client::StreamProcessorService::ingest"
2556
+ Category: "sp00ky-client::StreamProcessorService::ingest"
2606
2557
  }, "Ingesting into ssp done");
2607
2558
  if (rawUpdates && Array.isArray(rawUpdates) && rawUpdates.length > 0) {
2608
2559
  const updates = rawUpdates.map((u) => ({
@@ -2617,7 +2568,7 @@ var StreamProcessorService = class {
2617
2568
  } catch (e) {
2618
2569
  this.logger.error({
2619
2570
  error: e,
2620
- Category: "spooky-client::StreamProcessorService::ingest"
2571
+ Category: "sp00ky-client::StreamProcessorService::ingest"
2621
2572
  }, "Ingesting into ssp failed");
2622
2573
  }
2623
2574
  return [];
@@ -2628,14 +2579,14 @@ var StreamProcessorService = class {
2628
2579
  */
2629
2580
  registerQueryPlan(queryPlan) {
2630
2581
  if (!this.processor) {
2631
- this.logger.warn({ Category: "spooky-client::StreamProcessorService::registerQueryPlan" }, "Not initialized, skipping registration");
2582
+ this.logger.warn({ Category: "sp00ky-client::StreamProcessorService::registerQueryPlan" }, "Not initialized, skipping registration");
2632
2583
  return;
2633
2584
  }
2634
2585
  this.logger.debug({
2635
2586
  queryHash: queryPlan.queryHash,
2636
2587
  surql: queryPlan.surql,
2637
2588
  params: queryPlan.params,
2638
- Category: "spooky-client::StreamProcessorService::registerQueryPlan"
2589
+ Category: "sp00ky-client::StreamProcessorService::registerQueryPlan"
2639
2590
  }, "Registering query plan");
2640
2591
  try {
2641
2592
  const normalizedParams = this.normalizeValue(queryPlan.params);
@@ -2649,7 +2600,7 @@ var StreamProcessorService = class {
2649
2600
  });
2650
2601
  this.logger.debug({
2651
2602
  initialUpdate,
2652
- Category: "spooky-client::StreamProcessorService::registerQueryPlan"
2603
+ Category: "sp00ky-client::StreamProcessorService::registerQueryPlan"
2653
2604
  }, "register_view result");
2654
2605
  if (!initialUpdate) throw new Error("Failed to register query plan");
2655
2606
  const update = {
@@ -2661,13 +2612,13 @@ var StreamProcessorService = class {
2661
2612
  queryHash: queryPlan.queryHash,
2662
2613
  surql: queryPlan.surql,
2663
2614
  params: queryPlan.params,
2664
- Category: "spooky-client::StreamProcessorService::registerQueryPlan"
2615
+ Category: "sp00ky-client::StreamProcessorService::registerQueryPlan"
2665
2616
  }, "Registered query plan");
2666
2617
  return update;
2667
2618
  } catch (e) {
2668
2619
  this.logger.error({
2669
2620
  error: e,
2670
- Category: "spooky-client::StreamProcessorService::registerQueryPlan"
2621
+ Category: "sp00ky-client::StreamProcessorService::registerQueryPlan"
2671
2622
  }, "Error registering query plan");
2672
2623
  throw e;
2673
2624
  }
@@ -2683,7 +2634,7 @@ var StreamProcessorService = class {
2683
2634
  } catch (e) {
2684
2635
  this.logger.error({
2685
2636
  error: e,
2686
- Category: "spooky-client::StreamProcessorService::unregisterQueryPlan"
2637
+ Category: "sp00ky-client::StreamProcessorService::unregisterQueryPlan"
2687
2638
  }, "Error unregistering query plan");
2688
2639
  }
2689
2640
  }
@@ -2698,7 +2649,7 @@ var StreamProcessorService = class {
2698
2649
  const result = value.toString();
2699
2650
  this.logger.trace({
2700
2651
  result,
2701
- Category: "spooky-client::StreamProcessorService::normalizeValue"
2652
+ Category: "sp00ky-client::StreamProcessorService::normalizeValue"
2702
2653
  }, "RecordId detected");
2703
2654
  return result;
2704
2655
  }
@@ -2741,7 +2692,7 @@ var CacheModule = class {
2741
2692
  this.logger.debug({
2742
2693
  queryHash: update.queryHash,
2743
2694
  arrayLength: update.localArray?.length,
2744
- Category: "spooky-client::CacheModule::onStreamUpdate"
2695
+ Category: "sp00ky-client::CacheModule::onStreamUpdate"
2745
2696
  }, "Stream update received");
2746
2697
  this.streamUpdateCallback(update);
2747
2698
  }
@@ -2764,7 +2715,7 @@ var CacheModule = class {
2764
2715
  if (records.length === 0) return;
2765
2716
  this.logger.debug({
2766
2717
  count: records.length,
2767
- Category: "spooky-client::CacheModule::saveBatch"
2718
+ Category: "sp00ky-client::CacheModule::saveBatch"
2768
2719
  }, "Saving record batch");
2769
2720
  try {
2770
2721
  const populatedRecords = records.map((record) => {
@@ -2773,7 +2724,7 @@ var CacheModule = class {
2773
2724
  ...record,
2774
2725
  record: {
2775
2726
  ...record.record,
2776
- spooky_rv: record.version
2727
+ _00_rv: record.version
2777
2728
  }
2778
2729
  };
2779
2730
  });
@@ -2798,13 +2749,13 @@ var CacheModule = class {
2798
2749
  }
2799
2750
  this.logger.debug({
2800
2751
  count: records.length,
2801
- Category: "spooky-client::CacheModule::saveBatch"
2752
+ Category: "sp00ky-client::CacheModule::saveBatch"
2802
2753
  }, "Batch saved successfully");
2803
2754
  } catch (err) {
2804
2755
  this.logger.error({
2805
2756
  err,
2806
2757
  count: records.length,
2807
- Category: "spooky-client::CacheModule::saveBatch"
2758
+ Category: "sp00ky-client::CacheModule::saveBatch"
2808
2759
  }, "Failed to save batch");
2809
2760
  throw err;
2810
2761
  }
@@ -2812,27 +2763,27 @@ var CacheModule = class {
2812
2763
  /**
2813
2764
  * Delete a record from local DB and ingest deletion into DBSP
2814
2765
  */
2815
- async delete(table, id, skipDbDelete = false) {
2766
+ async delete(table, id, skipDbDelete = false, recordData = {}) {
2816
2767
  this.logger.debug({
2817
2768
  table,
2818
2769
  id,
2819
- Category: "spooky-client::CacheModule::delete"
2770
+ Category: "sp00ky-client::CacheModule::delete"
2820
2771
  }, "Deleting record");
2821
2772
  try {
2822
2773
  if (!skipDbDelete) await this.local.query("DELETE $id", { id: parseRecordIdString(id) });
2823
2774
  delete this.versionLookups[id];
2824
- await this.streamProcessor.ingest(table, "DELETE", id, {});
2775
+ this.streamProcessor.ingest(table, "DELETE", id, recordData);
2825
2776
  this.logger.debug({
2826
2777
  table,
2827
2778
  id,
2828
- Category: "spooky-client::CacheModule::delete"
2779
+ Category: "sp00ky-client::CacheModule::delete"
2829
2780
  }, "Record deleted successfully");
2830
2781
  } catch (err) {
2831
2782
  this.logger.error({
2832
2783
  err,
2833
2784
  table,
2834
2785
  id,
2835
- Category: "spooky-client::CacheModule::delete"
2786
+ Category: "sp00ky-client::CacheModule::delete"
2836
2787
  }, "Failed to delete record");
2837
2788
  throw err;
2838
2789
  }
@@ -2845,7 +2796,7 @@ var CacheModule = class {
2845
2796
  this.logger.debug({
2846
2797
  queryHash: config.queryHash,
2847
2798
  surql: config.surql,
2848
- Category: "spooky-client::CacheModule::registerQuery"
2799
+ Category: "sp00ky-client::CacheModule::registerQuery"
2849
2800
  }, "Registering query");
2850
2801
  try {
2851
2802
  const update = this.streamProcessor.registerQueryPlan({
@@ -2862,14 +2813,14 @@ var CacheModule = class {
2862
2813
  this.logger.debug({
2863
2814
  queryHash: config.queryHash,
2864
2815
  arrayLength: update.localArray?.length,
2865
- Category: "spooky-client::CacheModule::registerQuery"
2816
+ Category: "sp00ky-client::CacheModule::registerQuery"
2866
2817
  }, "Query registered successfully");
2867
2818
  return { localArray: update.localArray };
2868
2819
  } catch (err) {
2869
2820
  this.logger.error({
2870
2821
  err,
2871
2822
  queryHash: config.queryHash,
2872
- Category: "spooky-client::CacheModule::registerQuery"
2823
+ Category: "sp00ky-client::CacheModule::registerQuery"
2873
2824
  }, "Failed to register query");
2874
2825
  throw err;
2875
2826
  }
@@ -2880,19 +2831,19 @@ var CacheModule = class {
2880
2831
  unregisterQuery(queryHash) {
2881
2832
  this.logger.debug({
2882
2833
  queryHash,
2883
- Category: "spooky-client::CacheModule::unregisterQuery"
2834
+ Category: "sp00ky-client::CacheModule::unregisterQuery"
2884
2835
  }, "Unregistering query");
2885
2836
  try {
2886
2837
  this.streamProcessor.unregisterQueryPlan(queryHash);
2887
2838
  this.logger.debug({
2888
2839
  queryHash,
2889
- Category: "spooky-client::CacheModule::unregisterQuery"
2840
+ Category: "sp00ky-client::CacheModule::unregisterQuery"
2890
2841
  }, "Query unregistered successfully");
2891
2842
  } catch (err) {
2892
2843
  this.logger.error({
2893
2844
  err,
2894
2845
  queryHash,
2895
- Category: "spooky-client::CacheModule::unregisterQuery"
2846
+ Category: "sp00ky-client::CacheModule::unregisterQuery"
2896
2847
  }, "Failed to unregister query");
2897
2848
  }
2898
2849
  }
@@ -2930,7 +2881,7 @@ var SurrealDBPersistenceClient = class {
2930
2881
  }
2931
2882
  async set(key, val) {
2932
2883
  try {
2933
- const id = parseRecordIdString(`_spooky_kv:${key}`);
2884
+ const id = parseRecordIdString(`_00_kv:${key}`);
2934
2885
  await this.db.query(surql.seal(surql.upsert("id", "data")), {
2935
2886
  id,
2936
2887
  data: { val }
@@ -2938,40 +2889,69 @@ var SurrealDBPersistenceClient = class {
2938
2889
  } catch (error) {
2939
2890
  this.logger.error({
2940
2891
  error,
2941
- Category: "spooky-client::SurrealDBPersistenceClient::set"
2892
+ Category: "sp00ky-client::SurrealDBPersistenceClient::set"
2942
2893
  }, "Failed to set KV");
2943
2894
  throw error;
2944
2895
  }
2945
2896
  }
2946
2897
  async get(key) {
2947
2898
  try {
2948
- const id = parseRecordIdString(`_spooky_kv:${key}`);
2899
+ const id = parseRecordIdString(`_00_kv:${key}`);
2949
2900
  const [result] = await this.db.query(surql.seal(surql.selectById("id", ["val"])), { id });
2950
2901
  if (!result?.val) return null;
2951
2902
  return result.val;
2952
2903
  } catch (error) {
2953
2904
  this.logger.warn({
2954
2905
  error,
2955
- Category: "spooky-client::SurrealDBPersistenceClient::get"
2906
+ Category: "sp00ky-client::SurrealDBPersistenceClient::get"
2956
2907
  }, "Failed to get KV");
2957
2908
  return null;
2958
2909
  }
2959
2910
  }
2960
2911
  async remove(key) {
2961
2912
  try {
2962
- const id = parseRecordIdString(`_spooky_kv:${key}`);
2913
+ const id = parseRecordIdString(`_00_kv:${key}`);
2963
2914
  await this.db.query(surql.seal(surql.delete("id")), { id });
2964
2915
  } catch (err) {
2965
2916
  this.logger.info({
2966
2917
  err,
2967
- Category: "spooky-client::SurrealDBPersistenceClient::remove"
2918
+ Category: "sp00ky-client::SurrealDBPersistenceClient::remove"
2968
2919
  }, "Failed to delete KV");
2969
2920
  }
2970
2921
  }
2971
2922
  };
2972
2923
 
2973
2924
  //#endregion
2974
- //#region src/spooky.ts
2925
+ //#region src/services/persistence/resilient.ts
2926
+ var ResilientPersistenceClient = class {
2927
+ logger;
2928
+ constructor(inner, logger) {
2929
+ this.inner = inner;
2930
+ this.logger = logger.child({ service: "ResilientPersistenceClient" });
2931
+ }
2932
+ set(key, value) {
2933
+ return this.inner.set(key, value);
2934
+ }
2935
+ async get(key) {
2936
+ try {
2937
+ return await this.inner.get(key);
2938
+ } catch (e) {
2939
+ this.logger.warn({
2940
+ key,
2941
+ error: e,
2942
+ Category: "sp00ky-client::ResilientPersistenceClient::get"
2943
+ }, "Persistence read failed, dropping key");
2944
+ await this.inner.remove(key).catch(() => {});
2945
+ return null;
2946
+ }
2947
+ }
2948
+ remove(key) {
2949
+ return this.inner.remove(key);
2950
+ }
2951
+ };
2952
+
2953
+ //#endregion
2954
+ //#region src/sp00ky.ts
2975
2955
  var BucketHandle = class {
2976
2956
  constructor(bucketName, remote) {
2977
2957
  this.bucketName = bucketName;
@@ -3007,7 +2987,7 @@ var BucketHandle = class {
3007
2987
  return result;
3008
2988
  }
3009
2989
  };
3010
- var SpookyClient = class {
2990
+ var Sp00kyClient = class {
3011
2991
  local;
3012
2992
  remote;
3013
2993
  persistenceClient;
@@ -3033,20 +3013,21 @@ var SpookyClient = class {
3033
3013
  }
3034
3014
  constructor(config) {
3035
3015
  this.config = config;
3036
- const logger = createLogger(config.logLevel ?? "info", config.otelEndpoint);
3037
- this.logger = logger.child({ service: "SpookyClient" });
3016
+ const logger = createLogger(config.logLevel ?? "info", config.otelTransmit);
3017
+ this.logger = logger.child({ service: "Sp00kyClient" });
3038
3018
  this.logger.info({
3039
3019
  config: {
3040
3020
  ...config,
3041
3021
  schema: "[SchemaStructure]"
3042
3022
  },
3043
- Category: "spooky-client::SpookyClient::constructor"
3044
- }, "SpookyClient initialized");
3023
+ Category: "sp00ky-client::Sp00kyClient::constructor"
3024
+ }, "Sp00kyClient initialized");
3045
3025
  this.local = new LocalDatabaseService(this.config.database, logger);
3046
3026
  this.remote = new RemoteDatabaseService(this.config.database, logger);
3047
3027
  if (config.persistenceClient === "surrealdb") this.persistenceClient = new SurrealDBPersistenceClient(this.local, logger);
3048
3028
  else if (config.persistenceClient === "localstorage" || !config.persistenceClient) this.persistenceClient = new LocalStoragePersistenceClient(logger);
3049
3029
  else this.persistenceClient = config.persistenceClient;
3030
+ this.persistenceClient = new ResilientPersistenceClient(this.persistenceClient, logger);
3050
3031
  this.streamProcessor = new StreamProcessorService(new EventSystem(["stream_update"]), this.local, this.persistenceClient, logger);
3051
3032
  this.migrator = new LocalMigrator(this.local, logger);
3052
3033
  this.cache = new CacheModule(this.local, this.streamProcessor, (update) => {
@@ -3054,7 +3035,7 @@ var SpookyClient = class {
3054
3035
  }, logger);
3055
3036
  this.dataModule = new DataModule(this.cache, this.local, this.config.schema, logger, this.config.streamDebounceTime);
3056
3037
  this.auth = new AuthService(this.config.schema, this.remote, this.persistenceClient, logger);
3057
- this.sync = new SpookySync(this.local, this.remote, this.cache, this.dataModule, this.config.schema, this.logger);
3038
+ this.sync = new Sp00kySync(this.local, this.remote, this.cache, this.dataModule, this.config.schema, this.logger);
3058
3039
  this.devTools = new DevToolsService(this.local, this.remote, logger, this.config.schema, this.auth, this.dataModule);
3059
3040
  this.streamProcessor.addReceiver(this.devTools);
3060
3041
  this.setupCallbacks();
@@ -3078,34 +3059,34 @@ var SpookyClient = class {
3078
3059
  });
3079
3060
  }
3080
3061
  async init() {
3081
- this.logger.info({ Category: "spooky-client::SpookyClient::init" }, "SpookyClient initialization started");
3062
+ this.logger.info({ Category: "sp00ky-client::Sp00kyClient::init" }, "Sp00kyClient initialization started");
3082
3063
  try {
3083
3064
  const clientId = this.config.clientId ?? await this.loadOrGenerateClientId();
3084
3065
  this.persistClientId(clientId);
3085
3066
  this.logger.debug({
3086
3067
  clientId,
3087
- Category: "spooky-client::SpookyClient::init"
3068
+ Category: "sp00ky-client::Sp00kyClient::init"
3088
3069
  }, "Client ID loaded");
3089
3070
  await this.local.connect();
3090
- this.logger.debug({ Category: "spooky-client::SpookyClient::init" }, "Local database connected");
3071
+ this.logger.debug({ Category: "sp00ky-client::Sp00kyClient::init" }, "Local database connected");
3091
3072
  await this.migrator.provision(this.config.schemaSurql);
3092
- this.logger.debug({ Category: "spooky-client::SpookyClient::init" }, "Schema provisioned");
3073
+ this.logger.debug({ Category: "sp00ky-client::Sp00kyClient::init" }, "Schema provisioned");
3093
3074
  await this.remote.connect();
3094
- this.logger.debug({ Category: "spooky-client::SpookyClient::init" }, "Remote database connected");
3075
+ this.logger.debug({ Category: "sp00ky-client::Sp00kyClient::init" }, "Remote database connected");
3095
3076
  await this.streamProcessor.init();
3096
- this.logger.debug({ Category: "spooky-client::SpookyClient::init" }, "StreamProcessor initialized");
3077
+ this.logger.debug({ Category: "sp00ky-client::Sp00kyClient::init" }, "StreamProcessor initialized");
3097
3078
  await this.auth.init();
3098
- this.logger.debug({ Category: "spooky-client::SpookyClient::init" }, "Auth initialized");
3079
+ this.logger.debug({ Category: "sp00ky-client::Sp00kyClient::init" }, "Auth initialized");
3099
3080
  await this.dataModule.init();
3100
- this.logger.debug({ Category: "spooky-client::SpookyClient::init" }, "DataModule initialized");
3081
+ this.logger.debug({ Category: "sp00ky-client::Sp00kyClient::init" }, "DataModule initialized");
3101
3082
  await this.sync.init(clientId);
3102
- this.logger.debug({ Category: "spooky-client::SpookyClient::init" }, "Sync initialized");
3103
- this.logger.info({ Category: "spooky-client::SpookyClient::init" }, "SpookyClient initialization completed successfully");
3083
+ this.logger.debug({ Category: "sp00ky-client::Sp00kyClient::init" }, "Sync initialized");
3084
+ this.logger.info({ Category: "sp00ky-client::Sp00kyClient::init" }, "Sp00kyClient initialization completed successfully");
3104
3085
  } catch (e) {
3105
3086
  this.logger.error({
3106
3087
  error: e,
3107
- Category: "spooky-client::SpookyClient::init"
3108
- }, "SpookyClient initialization failed");
3088
+ Category: "sp00ky-client::Sp00kyClient::init"
3089
+ }, "Sp00kyClient initialization failed");
3109
3090
  throw e;
3110
3091
  }
3111
3092
  }
@@ -3159,16 +3140,16 @@ var SpookyClient = class {
3159
3140
  }
3160
3141
  persistClientId(id) {
3161
3142
  try {
3162
- this.persistenceClient.set("spooky_client_id", id);
3143
+ this.persistenceClient.set("sp00ky_client_id", id);
3163
3144
  } catch (e) {
3164
3145
  this.logger.warn({
3165
3146
  error: e,
3166
- Category: "spooky-client::SpookyClient::persistClientId"
3147
+ Category: "sp00ky-client::Sp00kyClient::persistClientId"
3167
3148
  }, "Failed to persist client ID");
3168
3149
  }
3169
3150
  }
3170
3151
  async loadOrGenerateClientId() {
3171
- const clientId = await this.persistenceClient.get("spooky_client_id");
3152
+ const clientId = await this.persistenceClient.get("sp00ky_client_id");
3172
3153
  if (clientId) return clientId;
3173
3154
  const newId = generateId();
3174
3155
  await this.persistClientId(newId);
@@ -3177,4 +3158,4 @@ var SpookyClient = class {
3177
3158
  };
3178
3159
 
3179
3160
  //#endregion
3180
- export { AuthEventTypes, AuthService, BucketHandle, SpookyClient, createAuthEventSystem, fileToUint8Array };
3161
+ export { AuthEventTypes, AuthService, BucketHandle, Sp00kyClient, createAuthEventSystem, fileToUint8Array };