@syncular/client 0.15.37 → 0.15.39

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.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Preserve supervisor observation across a facade without transferring
3
+ * transport ownership or exposing the source client. Binding packages use
4
+ * this when they normalize a client into another object identity.
5
+ */
6
+ export declare function linkRealtimeSupervisorObservation<Target extends object>(target: Target, source: object): Target;
7
+ /** @internal Resolve one facade hop for the supervisor attachment lookup. */
8
+ export declare function realtimeSupervisorObservationSource(target: object): object | undefined;
@@ -0,0 +1,15 @@
1
+ const observationSources = new WeakMap();
2
+ /**
3
+ * Preserve supervisor observation across a facade without transferring
4
+ * transport ownership or exposing the source client. Binding packages use
5
+ * this when they normalize a client into another object identity.
6
+ */
7
+ export function linkRealtimeSupervisorObservation(target, source) {
8
+ if (target !== source)
9
+ observationSources.set(target, source);
10
+ return target;
11
+ }
12
+ /** @internal Resolve one facade hop for the supervisor attachment lookup. */
13
+ export function realtimeSupervisorObservationSource(target) {
14
+ return observationSources.get(target);
15
+ }
@@ -1,5 +1,6 @@
1
1
  import type { SecurityLifecycle } from './client.js';
2
2
  import type { ClientDiagnosticsConnectivity, ClientDiagnosticsListener, ClientDiagnosticsSnapshot } from './diagnostics.js';
3
+ export { linkRealtimeSupervisorObservation } from './realtime-supervisor-observation.js';
3
4
  type CancelTimer = () => void;
4
5
  export interface RealtimeSupervisorClient {
5
6
  connectRealtime(): Promise<void>;
@@ -75,4 +76,3 @@ export declare class RealtimeSupervisor {
75
76
  export declare function installRealtimeSupervisor<T extends RealtimeSupervisorClient>(client: T, options?: RealtimeSupervisorOptions): T;
76
77
  export declare function realtimeSupervisorSnapshot(client: object): RealtimeSupervisorSnapshot;
77
78
  export declare function subscribeRealtimeSupervisor(client: object, listener: () => void): () => void;
78
- export {};
@@ -1,3 +1,5 @@
1
+ import { realtimeSupervisorObservationSource } from './realtime-supervisor-observation.js';
2
+ export { linkRealtimeSupervisorObservation } from './realtime-supervisor-observation.js';
1
3
  const REALTIME_SUPERVISOR_KEY = Symbol.for('syncular.realtime-supervisor.v1');
2
4
  const DEFAULT_INITIAL_DELAY_MS = 1_000;
3
5
  const DEFAULT_MAXIMUM_DELAY_MS = 30_000;
@@ -6,11 +8,16 @@ const UNSUPPORTED_SNAPSHOT = Object.freeze({
6
8
  phase: 'unsupported',
7
9
  attempt: 0,
8
10
  });
9
- function attachment(client) {
11
+ function attachment(client, visited = new Set()) {
12
+ if (visited.has(client))
13
+ return undefined;
14
+ visited.add(client);
10
15
  const candidate = Reflect.get(client, REALTIME_SUPERVISOR_KEY);
11
- return candidate?.version === 1 && candidate.supervisor
12
- ? candidate
13
- : undefined;
16
+ if (candidate?.version === 1 && candidate.supervisor) {
17
+ return candidate;
18
+ }
19
+ const source = realtimeSupervisorObservationSource(client);
20
+ return source === undefined ? undefined : attachment(source, visited);
14
21
  }
15
22
  function scheduleTimer(callback, delayMs) {
16
23
  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.39",
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",
@@ -34,6 +34,14 @@
34
34
  "default": "./dist/index.js"
35
35
  }
36
36
  },
37
+ "./realtime-supervisor-observation": {
38
+ "bun": "./src/realtime-supervisor-observation.ts",
39
+ "browser": "./dist/realtime-supervisor-observation.js",
40
+ "import": {
41
+ "types": "./dist/realtime-supervisor-observation.d.ts",
42
+ "default": "./dist/realtime-supervisor-observation.js"
43
+ }
44
+ },
37
45
  "./bun": {
38
46
  "bun": "./src/bun-database.ts",
39
47
  "browser": "./dist/bun-database.js",
@@ -81,7 +89,7 @@
81
89
  },
82
90
  "dependencies": {
83
91
  "@sqlite.org/sqlite-wasm": "^3.53.0-build1",
84
- "@syncular/core": "0.15.37"
92
+ "@syncular/core": "0.15.39"
85
93
  },
86
94
  "peerDependencies": {
87
95
  "better-sqlite3": ">=11"
@@ -92,7 +100,7 @@
92
100
  }
93
101
  },
94
102
  "devDependencies": {
95
- "@syncular/server": "0.15.37",
103
+ "@syncular/server": "0.15.39",
96
104
  "@types/better-sqlite3": "^7.6.13",
97
105
  "better-sqlite3": "^12.11.1"
98
106
  }
@@ -0,0 +1,21 @@
1
+ const observationSources = new WeakMap<object, object>();
2
+
3
+ /**
4
+ * Preserve supervisor observation across a facade without transferring
5
+ * transport ownership or exposing the source client. Binding packages use
6
+ * this when they normalize a client into another object identity.
7
+ */
8
+ export function linkRealtimeSupervisorObservation<Target extends object>(
9
+ target: Target,
10
+ source: object,
11
+ ): Target {
12
+ if (target !== source) observationSources.set(target, source);
13
+ return target;
14
+ }
15
+
16
+ /** @internal Resolve one facade hop for the supervisor attachment lookup. */
17
+ export function realtimeSupervisorObservationSource(
18
+ target: object,
19
+ ): object | undefined {
20
+ return observationSources.get(target);
21
+ }
@@ -4,6 +4,9 @@ import type {
4
4
  ClientDiagnosticsListener,
5
5
  ClientDiagnosticsSnapshot,
6
6
  } from './diagnostics';
7
+ import { realtimeSupervisorObservationSource } from './realtime-supervisor-observation';
8
+
9
+ export { linkRealtimeSupervisorObservation } from './realtime-supervisor-observation';
7
10
 
8
11
  type CancelTimer = () => void;
9
12
 
@@ -90,13 +93,20 @@ interface RealtimeSupervisorAttachment {
90
93
  readonly supervisor: RealtimeSupervisor;
91
94
  }
92
95
 
93
- function attachment(client: object): RealtimeSupervisorAttachment | undefined {
96
+ function attachment(
97
+ client: object,
98
+ visited: Set<object> = new Set(),
99
+ ): RealtimeSupervisorAttachment | undefined {
100
+ if (visited.has(client)) return undefined;
101
+ visited.add(client);
94
102
  const candidate = Reflect.get(client, REALTIME_SUPERVISOR_KEY) as
95
103
  | Partial<RealtimeSupervisorAttachment>
96
104
  | undefined;
97
- return candidate?.version === 1 && candidate.supervisor
98
- ? (candidate as RealtimeSupervisorAttachment)
99
- : undefined;
105
+ if (candidate?.version === 1 && candidate.supervisor) {
106
+ return candidate as RealtimeSupervisorAttachment;
107
+ }
108
+ const source = realtimeSupervisorObservationSource(client);
109
+ return source === undefined ? undefined : attachment(source, visited);
100
110
  }
101
111
 
102
112
  function scheduleTimer(callback: () => void, delayMs: number): CancelTimer {