@spooky-sync/core 0.0.1-canary.239 → 0.0.1-canary.240

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 (139) hide show
  1. package/coverage/lcov-report/base.css +224 -0
  2. package/coverage/lcov-report/block-navigation.js +87 -0
  3. package/coverage/lcov-report/favicon.png +0 -0
  4. package/coverage/lcov-report/index.html +476 -0
  5. package/coverage/lcov-report/prettify.css +1 -0
  6. package/coverage/lcov-report/prettify.js +2 -0
  7. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  8. package/coverage/lcov-report/sorter.js +210 -0
  9. package/coverage/lcov-report/src/boot/auth-flip.saga.ts.html +271 -0
  10. package/coverage/lcov-report/src/boot/boot.saga.ts.html +469 -0
  11. package/coverage/lcov-report/src/boot/bucket-switch.saga.ts.html +430 -0
  12. package/coverage/lcov-report/src/boot/index.html +161 -0
  13. package/coverage/lcov-report/src/boot/preload.saga.ts.html +178 -0
  14. package/coverage/lcov-report/src/client/bucket-handle.ts.html +766 -0
  15. package/coverage/lcov-report/src/client/index.html +161 -0
  16. package/coverage/lcov-report/src/client/router.ts.html +367 -0
  17. package/coverage/lcov-report/src/client/runtime.ts.html +940 -0
  18. package/coverage/lcov-report/src/client/sp00ky-client.ts.html +1531 -0
  19. package/coverage/lcov-report/src/events/index.html +116 -0
  20. package/coverage/lcov-report/src/events/index.ts.html +877 -0
  21. package/coverage/lcov-report/src/index.html +146 -0
  22. package/coverage/lcov-report/src/index.ts.html +202 -0
  23. package/coverage/lcov-report/src/kernel/constants.ts.html +247 -0
  24. package/coverage/lcov-report/src/kernel/effects.ts.html +562 -0
  25. package/coverage/lcov-report/src/kernel/events.ts.html +250 -0
  26. package/coverage/lcov-report/src/kernel/index.html +176 -0
  27. package/coverage/lcov-report/src/kernel/interpreter.ts.html +514 -0
  28. package/coverage/lcov-report/src/kernel/saga.ts.html +304 -0
  29. package/coverage/lcov-report/src/modules/app-release/index.html +116 -0
  30. package/coverage/lcov-report/src/modules/app-release/index.ts.html +712 -0
  31. package/coverage/lcov-report/src/modules/auth/events/index.html +116 -0
  32. package/coverage/lcov-report/src/modules/auth/events/index.ts.html +142 -0
  33. package/coverage/lcov-report/src/modules/auth/index.html +116 -0
  34. package/coverage/lcov-report/src/modules/auth/index.ts.html +1225 -0
  35. package/coverage/lcov-report/src/modules/crdt/crdt-field.ts.html +967 -0
  36. package/coverage/lcov-report/src/modules/crdt/index.html +146 -0
  37. package/coverage/lcov-report/src/modules/crdt/index.ts.html +1474 -0
  38. package/coverage/lcov-report/src/modules/crdt/loro-loader.ts.html +160 -0
  39. package/coverage/lcov-report/src/modules/devtools/flags.ts.html +1132 -0
  40. package/coverage/lcov-report/src/modules/devtools/index.html +161 -0
  41. package/coverage/lcov-report/src/modules/devtools/index.ts.html +2413 -0
  42. package/coverage/lcov-report/src/modules/devtools/storage-info.ts.html +589 -0
  43. package/coverage/lcov-report/src/modules/devtools/versions.ts.html +415 -0
  44. package/coverage/lcov-report/src/modules/feature-flag/index.html +116 -0
  45. package/coverage/lcov-report/src/modules/feature-flag/index.ts.html +1033 -0
  46. package/coverage/lcov-report/src/modules/index.html +116 -0
  47. package/coverage/lcov-report/src/modules/ref-tables.ts.html +349 -0
  48. package/coverage/lcov-report/src/mutation/index.html +191 -0
  49. package/coverage/lcov-report/src/mutation/jobs.ts.html +208 -0
  50. package/coverage/lcov-report/src/mutation/mutation-id.ts.html +190 -0
  51. package/coverage/lcov-report/src/mutation/push.saga.ts.html +730 -0
  52. package/coverage/lcov-report/src/mutation/rows.ts.html +1216 -0
  53. package/coverage/lcov-report/src/mutation/tray.saga.ts.html +229 -0
  54. package/coverage/lcov-report/src/mutation/write.saga.ts.html +583 -0
  55. package/coverage/lcov-report/src/otel/index.html +116 -0
  56. package/coverage/lcov-report/src/otel/index.ts.html +466 -0
  57. package/coverage/lcov-report/src/query/env.ts.html +253 -0
  58. package/coverage/lcov-report/src/query/fetch.saga.ts.html +412 -0
  59. package/coverage/lcov-report/src/query/hash.ts.html +139 -0
  60. package/coverage/lcov-report/src/query/index.html +281 -0
  61. package/coverage/lcov-report/src/query/lifecycle.saga.ts.html +388 -0
  62. package/coverage/lcov-report/src/query/materialize.saga.ts.html +310 -0
  63. package/coverage/lcov-report/src/query/materialize.ts.html +217 -0
  64. package/coverage/lcov-report/src/query/membership.saga.ts.html +709 -0
  65. package/coverage/lcov-report/src/query/membership.ts.html +559 -0
  66. package/coverage/lcov-report/src/query/register.saga.ts.html +655 -0
  67. package/coverage/lcov-report/src/query/render-set.ts.html +265 -0
  68. package/coverage/lcov-report/src/query/sql.ts.html +322 -0
  69. package/coverage/lcov-report/src/query/window-query.ts.html +670 -0
  70. package/coverage/lcov-report/src/services/blobs/blob-cache.ts.html +1894 -0
  71. package/coverage/lcov-report/src/services/blobs/blob-manifest.ts.html +766 -0
  72. package/coverage/lcov-report/src/services/blobs/blob-store.ts.html +1162 -0
  73. package/coverage/lcov-report/src/services/blobs/index.html +161 -0
  74. package/coverage/lcov-report/src/services/blobs/index.ts.html +295 -0
  75. package/coverage/lcov-report/src/services/database/cache-engine.ts.html +664 -0
  76. package/coverage/lcov-report/src/services/database/connection-supervisor.ts.html +1330 -0
  77. package/coverage/lcov-report/src/services/database/database.ts.html +658 -0
  78. package/coverage/lcov-report/src/services/database/engine-factory.ts.html +184 -0
  79. package/coverage/lcov-report/src/services/database/errors.ts.html +187 -0
  80. package/coverage/lcov-report/src/services/database/events/index.html +116 -0
  81. package/coverage/lcov-report/src/services/database/events/index.ts.html +184 -0
  82. package/coverage/lcov-report/src/services/database/index.html +386 -0
  83. package/coverage/lcov-report/src/services/database/index.ts.html +121 -0
  84. package/coverage/lcov-report/src/services/database/local-migrator.ts.html +703 -0
  85. package/coverage/lcov-report/src/services/database/local.ts.html +1633 -0
  86. package/coverage/lcov-report/src/services/database/plan-render.ts.html +409 -0
  87. package/coverage/lcov-report/src/services/database/relation-resolver.ts.html +682 -0
  88. package/coverage/lcov-report/src/services/database/remote.ts.html +1036 -0
  89. package/coverage/lcov-report/src/services/database/sqlite-cache-engine.ts.html +4132 -0
  90. package/coverage/lcov-report/src/services/database/sqlite-lock-verify.ts.html +220 -0
  91. package/coverage/lcov-report/src/services/database/sqlite-open.ts.html +577 -0
  92. package/coverage/lcov-report/src/services/database/sqlite-plan-sql.ts.html +499 -0
  93. package/coverage/lcov-report/src/services/database/sqlite-select.ts.html +478 -0
  94. package/coverage/lcov-report/src/services/database/sqlite-transport.ts.html +757 -0
  95. package/coverage/lcov-report/src/services/database/surql-translate.ts.html +1333 -0
  96. package/coverage/lcov-report/src/services/database/surreal-cache-engine.ts.html +568 -0
  97. package/coverage/lcov-report/src/services/logger/index.html +116 -0
  98. package/coverage/lcov-report/src/services/logger/index.ts.html +154 -0
  99. package/coverage/lcov-report/src/services/persistence/index.html +146 -0
  100. package/coverage/lcov-report/src/services/persistence/localstorage.ts.html +163 -0
  101. package/coverage/lcov-report/src/services/persistence/resilient.ts.html +208 -0
  102. package/coverage/lcov-report/src/services/persistence/surrealdb.ts.html +271 -0
  103. package/coverage/lcov-report/src/services/stream-processor/index.html +146 -0
  104. package/coverage/lcov-report/src/services/stream-processor/index.ts.html +3313 -0
  105. package/coverage/lcov-report/src/services/stream-processor/permissions.ts.html +244 -0
  106. package/coverage/lcov-report/src/services/stream-processor/wasm-types.ts.html +346 -0
  107. package/coverage/lcov-report/src/services/tabs/broker-client.ts.html +934 -0
  108. package/coverage/lcov-report/src/services/tabs/coordinator.ts.html +1984 -0
  109. package/coverage/lcov-report/src/services/tabs/index.html +191 -0
  110. package/coverage/lcov-report/src/services/tabs/leader-locks.ts.html +310 -0
  111. package/coverage/lcov-report/src/services/tabs/protocol.ts.html +871 -0
  112. package/coverage/lcov-report/src/services/tabs/support.ts.html +193 -0
  113. package/coverage/lcov-report/src/services/tabs/tabs-broker-worker.ts.html +2005 -0
  114. package/coverage/lcov-report/src/sp00ky.ts.html +100 -0
  115. package/coverage/lcov-report/src/state/client-state.ts.html +637 -0
  116. package/coverage/lcov-report/src/state/index.html +161 -0
  117. package/coverage/lcov-report/src/state/lifecycle.ts.html +343 -0
  118. package/coverage/lcov-report/src/state/reducers.ts.html +1471 -0
  119. package/coverage/lcov-report/src/state/selectors.ts.html +637 -0
  120. package/coverage/lcov-report/src/sync/connection.saga.ts.html +343 -0
  121. package/coverage/lcov-report/src/sync/index.html +176 -0
  122. package/coverage/lcov-report/src/sync/live.saga.ts.html +232 -0
  123. package/coverage/lcov-report/src/sync/policy.ts.html +1606 -0
  124. package/coverage/lcov-report/src/sync/poll.saga.ts.html +193 -0
  125. package/coverage/lcov-report/src/sync/tabs.saga.ts.html +361 -0
  126. package/coverage/lcov-report/src/types.ts.html +2419 -0
  127. package/coverage/lcov-report/src/utils/blurhash.ts.html +355 -0
  128. package/coverage/lcov-report/src/utils/error-classification.ts.html +244 -0
  129. package/coverage/lcov-report/src/utils/index.html +191 -0
  130. package/coverage/lcov-report/src/utils/index.ts.html +820 -0
  131. package/coverage/lcov-report/src/utils/parser.ts.html +313 -0
  132. package/coverage/lcov-report/src/utils/semver.ts.html +175 -0
  133. package/coverage/lcov-report/src/utils/surql.ts.html +667 -0
  134. package/coverage/lcov.info +19079 -0
  135. package/dist/index.js +3 -3
  136. package/dist/sqlite-open.js +20 -1
  137. package/package.json +3 -3
  138. package/src/services/database/relation-resolver.test.ts +55 -1
  139. package/src/services/database/relation-resolver.ts +0 -0
package/dist/index.js CHANGED
@@ -8387,8 +8387,8 @@ function selfAllowlistedVariant(flag, userId) {
8387
8387
 
8388
8388
  //#endregion
8389
8389
  //#region src/modules/devtools/index.ts
8390
- const CORE_VERSION = "0.0.1-canary.239";
8391
- const WASM_VERSION = "0.0.1-canary.239";
8390
+ const CORE_VERSION = "0.0.1-canary.240";
8391
+ const WASM_VERSION = "0.0.1-canary.240";
8392
8392
  const SURREAL_VERSION = "3.0.3";
8393
8393
  var DevToolsService = class DevToolsService {
8394
8394
  eventsHistory = [];
@@ -13417,7 +13417,7 @@ var Sp00kyClient = class {
13417
13417
  return new TabsCoordinator({
13418
13418
  tabId,
13419
13419
  fingerprint: computeTabsFingerprint({
13420
- coreVersion: "0.0.1-canary.239",
13420
+ coreVersion: "0.0.1-canary.240",
13421
13421
  schemaHash: hash53(this.config.schemaSurql),
13422
13422
  endpoint: this.config.database.endpoint ?? "",
13423
13423
  namespace: this.config.database.namespace,
@@ -46,6 +46,7 @@ async function resolveOne(parents, relation, fetcher, depth, path) {
46
46
  for (const parent of parents) {
47
47
  const key = parentKeyOf(parent);
48
48
  if (key == null) continue;
49
+ if (isOne && !looksLikeRecordId(key)) continue;
49
50
  const k = stableKey(key);
50
51
  if (!keySet.has(k)) keySet.set(k, key);
51
52
  }
@@ -72,10 +73,28 @@ async function resolveOne(parents, relation, fetcher, depth, path) {
72
73
  let bucket = key == null ? [] : grouped.get(stableKey(key)) ?? [];
73
74
  if (relation.orderBy && relation.orderBy.length > 0) bucket = sortRows(bucket, relation.orderBy);
74
75
  if (relation.limit !== void 0) bucket = bucket.slice(0, relation.limit);
75
- parent[relation.alias] = isOne ? bucket[0] ?? null : bucket;
76
+ if (isOne) {
77
+ const raw = parent[relation.alias];
78
+ const keepRaw = relation.alias === relation.foreignKeyField && raw != null && !looksLikeRecordId(raw);
79
+ parent[relation.alias] = bucket[0] ?? (keepRaw ? raw : null);
80
+ } else parent[relation.alias] = bucket;
76
81
  }
77
82
  }
78
83
  /**
84
+ * Whether a correlation value can address a record: a RecordId (duck-typed) or
85
+ * a `table:id` string. Anything else (a plain display string, a number) cannot
86
+ * be the target of a to-one relation and is skipped rather than fetched.
87
+ */
88
+ function looksLikeRecordId(value) {
89
+ if (value == null) return false;
90
+ if (typeof value === "string") return /^[A-Za-z_][A-Za-z0-9_]*:.+/.test(value);
91
+ if (typeof value === "object") {
92
+ const rid = value;
93
+ return rid.tb !== void 0 && rid.id !== void 0;
94
+ }
95
+ return false;
96
+ }
97
+ /**
79
98
  * Stable grouping key for a correlation value. A `RecordId` (duck-typed to
80
99
  * avoid a hard surrealdb dependency here) and its `table:id` string form must
81
100
  * collapse to the same key so a parent FK stored either way matches the child.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spooky-sync/core",
3
- "version": "0.0.1-canary.239",
3
+ "version": "0.0.1-canary.240",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -60,8 +60,8 @@
60
60
  }
61
61
  },
62
62
  "dependencies": {
63
- "@spooky-sync/query-builder": "0.0.1-canary.239",
64
- "@spooky-sync/ssp-wasm": "0.0.1-canary.239",
63
+ "@spooky-sync/query-builder": "0.0.1-canary.240",
64
+ "@spooky-sync/ssp-wasm": "0.0.1-canary.240",
65
65
  "@sqlite.org/sqlite-wasm": "3.53.0-build1",
66
66
  "@surrealdb/wasm": "^3.0.3",
67
67
  "blurhash": "^2.0.5",
@@ -1,6 +1,6 @@
1
1
  import { describe, it, expect } from 'vitest';
2
2
  import type { RelationPlan, WhereNode } from '@spooky-sync/query-builder';
3
- import { resolveRelations, sortRows, stableKey } from './relation-resolver';
3
+ import { looksLikeRecordId, resolveRelations, sortRows, stableKey } from './relation-resolver';
4
4
  import {
5
5
  RelationCycleError,
6
6
  type RelationFetch,
@@ -411,3 +411,57 @@ describe('resolveRelations — property: batched == naive over random trees', ()
411
411
  }
412
412
  });
413
413
  });
414
+
415
+ describe('to-one relations over a `string | record` column', () => {
416
+ const rel = (alias: string, fk: string): RelationPlan => ({
417
+ table: 'player_name',
418
+ alias,
419
+ cardinality: 'one',
420
+ foreignKeyField: fk,
421
+ });
422
+
423
+ it('keeps a legacy plain string when the alias is the foreign-key column', async () => {
424
+ const store = new MemStore({
425
+ player_name: [{ id: 'player_name:PN_1', name: 'Magnus' }],
426
+ });
427
+ const rows: Row[] = [
428
+ { id: 'game:1', white: 'player_name:PN_1' },
429
+ { id: 'game:2', white: 'Hikaru' }, // pre-normalization row: not a link
430
+ { id: 'game:3', white: 'player_name:PN_gone' }, // dangling link
431
+ ];
432
+ await resolveRelations(rows, [rel('white', 'white')], store);
433
+ expect(rows[0].white).toEqual({ id: 'player_name:PN_1', name: 'Magnus' });
434
+ expect(rows[1].white).toBe('Hikaru');
435
+ // A dangling LINK is null, like SurrealQL's `(SELECT …)[0] AS white`.
436
+ expect(rows[2].white).toBeNull();
437
+ });
438
+
439
+ it('never sends a non-record value as a correlation key', async () => {
440
+ const seen: unknown[][] = [];
441
+ const store: RowFetcher = {
442
+ fetchRelation: async (req) => {
443
+ seen.push(req.keys);
444
+ return [];
445
+ },
446
+ };
447
+ const rows: Row[] = [{ id: 'game:1', white: 'Hikaru' }, { id: 'game:2', white: 'player_name:PN_2' }];
448
+ await resolveRelations(rows, [rel('white', 'white')], store);
449
+ expect(seen).toEqual([['player_name:PN_2']]);
450
+ });
451
+
452
+ it('nulls a distinct alias when nothing resolves', async () => {
453
+ const store = new MemStore({ player_name: [] });
454
+ const rows: Row[] = [{ id: 'game:1', white: 'player_name:PN_gone' }];
455
+ await resolveRelations(rows, [rel('whiteRow', 'white')], store);
456
+ expect(rows[0].whiteRow).toBeNull();
457
+ expect(rows[0].white).toBe('player_name:PN_gone');
458
+ });
459
+
460
+ it('looksLikeRecordId accepts table:id strings and RecordId shapes only', () => {
461
+ expect(looksLikeRecordId('player_name:PN_1')).toBe(true);
462
+ expect(looksLikeRecordId({ tb: 'player_name', id: 'PN_1' })).toBe(true);
463
+ expect(looksLikeRecordId('Magnus')).toBe(false);
464
+ expect(looksLikeRecordId(42)).toBe(false);
465
+ expect(looksLikeRecordId(null)).toBe(false);
466
+ });
467
+ });