@syncular/client 0.15.37 → 0.15.38

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.
@@ -53,6 +53,12 @@ export interface DocumentLifecycleSignalOptions {
53
53
  readonly visibilityState?: string;
54
54
  };
55
55
  }
56
+ /**
57
+ * Preserve supervisor observation across a facade without transferring
58
+ * transport ownership or exposing the source client. Binding packages use
59
+ * this when they normalize a client into another object identity.
60
+ */
61
+ export declare function linkRealtimeSupervisorObservation<Target extends object>(target: Target, source: object): Target;
56
62
  /** Browser/Tauri-webview connectivity evidence without importing DOM types. */
57
63
  export declare function browserConnectivitySignal(options?: BrowserConnectivitySignalOptions): RealtimeSupervisorSignal<ClientDiagnosticsConnectivity>;
58
64
  /** Browser/Tauri-webview visibility evidence without importing DOM types. */
@@ -6,11 +6,27 @@ const UNSUPPORTED_SNAPSHOT = Object.freeze({
6
6
  phase: 'unsupported',
7
7
  attempt: 0,
8
8
  });
9
- function attachment(client) {
9
+ const observationSources = new WeakMap();
10
+ function attachment(client, visited = new Set()) {
11
+ if (visited.has(client))
12
+ return undefined;
13
+ visited.add(client);
10
14
  const candidate = Reflect.get(client, REALTIME_SUPERVISOR_KEY);
11
- return candidate?.version === 1 && candidate.supervisor
12
- ? candidate
13
- : undefined;
15
+ if (candidate?.version === 1 && candidate.supervisor) {
16
+ return candidate;
17
+ }
18
+ const source = observationSources.get(client);
19
+ return source === undefined ? undefined : attachment(source, visited);
20
+ }
21
+ /**
22
+ * Preserve supervisor observation across a facade without transferring
23
+ * transport ownership or exposing the source client. Binding packages use
24
+ * this when they normalize a client into another object identity.
25
+ */
26
+ export function linkRealtimeSupervisorObservation(target, source) {
27
+ if (target !== source)
28
+ observationSources.set(target, source);
29
+ return target;
14
30
  }
15
31
  function scheduleTimer(callback, delayMs) {
16
32
  const timer = globalThis.setTimeout(callback, delayMs);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syncular/client",
3
- "version": "0.15.37",
3
+ "version": "0.15.38",
4
4
  "description": "Syncular TypeScript client core — offline-first sync over SQLite (WASM/OPFS, Bun, Node)",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Benjamin Kniffler",
@@ -81,7 +81,7 @@
81
81
  },
82
82
  "dependencies": {
83
83
  "@sqlite.org/sqlite-wasm": "^3.53.0-build1",
84
- "@syncular/core": "0.15.37"
84
+ "@syncular/core": "0.15.38"
85
85
  },
86
86
  "peerDependencies": {
87
87
  "better-sqlite3": ">=11"
@@ -92,7 +92,7 @@
92
92
  }
93
93
  },
94
94
  "devDependencies": {
95
- "@syncular/server": "0.15.37",
95
+ "@syncular/server": "0.15.38",
96
96
  "@types/better-sqlite3": "^7.6.13",
97
97
  "better-sqlite3": "^12.11.1"
98
98
  }
@@ -90,13 +90,35 @@ interface RealtimeSupervisorAttachment {
90
90
  readonly supervisor: RealtimeSupervisor;
91
91
  }
92
92
 
93
- function attachment(client: object): RealtimeSupervisorAttachment | undefined {
93
+ const observationSources = new WeakMap<object, object>();
94
+
95
+ function attachment(
96
+ client: object,
97
+ visited: Set<object> = new Set(),
98
+ ): RealtimeSupervisorAttachment | undefined {
99
+ if (visited.has(client)) return undefined;
100
+ visited.add(client);
94
101
  const candidate = Reflect.get(client, REALTIME_SUPERVISOR_KEY) as
95
102
  | Partial<RealtimeSupervisorAttachment>
96
103
  | undefined;
97
- return candidate?.version === 1 && candidate.supervisor
98
- ? (candidate as RealtimeSupervisorAttachment)
99
- : undefined;
104
+ if (candidate?.version === 1 && candidate.supervisor) {
105
+ return candidate as RealtimeSupervisorAttachment;
106
+ }
107
+ const source = observationSources.get(client);
108
+ return source === undefined ? undefined : attachment(source, visited);
109
+ }
110
+
111
+ /**
112
+ * Preserve supervisor observation across a facade without transferring
113
+ * transport ownership or exposing the source client. Binding packages use
114
+ * this when they normalize a client into another object identity.
115
+ */
116
+ export function linkRealtimeSupervisorObservation<Target extends object>(
117
+ target: Target,
118
+ source: object,
119
+ ): Target {
120
+ if (target !== source) observationSources.set(target, source);
121
+ return target;
100
122
  }
101
123
 
102
124
  function scheduleTimer(callback: () => void, delayMs: number): CancelTimer {