@syncular/client 0.1.3 → 0.2.0

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 (233) hide show
  1. package/README.md +227 -709
  2. package/dist/apply.d.ts +80 -0
  3. package/dist/apply.js +301 -0
  4. package/dist/blob.d.ts +127 -0
  5. package/dist/blob.js +201 -0
  6. package/dist/bun-database.d.ts +22 -0
  7. package/dist/bun-database.js +61 -0
  8. package/dist/client.d.ts +320 -69
  9. package/dist/client.js +1627 -163
  10. package/dist/content-type.d.ts +2 -0
  11. package/dist/content-type.js +2 -0
  12. package/dist/database.d.ts +35 -80
  13. package/dist/database.js +32 -947
  14. package/dist/encryption.d.ts +47 -0
  15. package/dist/encryption.js +75 -0
  16. package/dist/errors.d.ts +8 -22
  17. package/dist/errors.js +10 -207
  18. package/dist/http.d.ts +32 -0
  19. package/dist/http.js +196 -0
  20. package/dist/index.d.ts +28 -16
  21. package/dist/index.js +25 -12
  22. package/dist/invalidation.d.ts +69 -0
  23. package/dist/invalidation.js +84 -0
  24. package/dist/leader-lock.d.ts +28 -0
  25. package/dist/leader-lock.js +38 -0
  26. package/dist/multi-tab.d.ts +134 -0
  27. package/dist/multi-tab.js +399 -0
  28. package/dist/node-database.d.ts +41 -0
  29. package/dist/node-database.js +133 -0
  30. package/dist/outbox.d.ts +56 -0
  31. package/dist/outbox.js +140 -0
  32. package/dist/schema.d.ts +107 -0
  33. package/dist/schema.js +267 -0
  34. package/dist/state.d.ts +40 -0
  35. package/dist/state.js +77 -0
  36. package/dist/transport.d.ts +44 -0
  37. package/dist/transport.js +7 -0
  38. package/dist/wasm-database.d.ts +30 -0
  39. package/dist/wasm-database.js +170 -0
  40. package/dist/window.d.ts +64 -0
  41. package/dist/window.js +0 -0
  42. package/dist/worker-entry.d.ts +16 -2
  43. package/dist/worker-entry.js +300 -456
  44. package/dist/worker-host.d.ts +174 -0
  45. package/dist/worker-host.js +536 -0
  46. package/dist/worker-protocol.d.ts +173 -61
  47. package/dist/worker-protocol.js +7 -16
  48. package/package.json +45 -112
  49. package/src/apply.ts +435 -0
  50. package/src/blob.ts +333 -0
  51. package/src/bun-database.ts +75 -0
  52. package/src/client.ts +2247 -277
  53. package/src/content-type.ts +2 -0
  54. package/src/database.ts +63 -1389
  55. package/src/encryption.ts +123 -0
  56. package/src/errors.ts +11 -265
  57. package/src/http.ts +254 -0
  58. package/src/index.ts +25 -20
  59. package/src/invalidation.ts +128 -0
  60. package/src/leader-lock.ts +68 -0
  61. package/src/multi-tab.ts +550 -0
  62. package/src/node-database.ts +180 -0
  63. package/src/outbox.ts +206 -0
  64. package/src/schema.ts +397 -0
  65. package/src/state.ts +126 -0
  66. package/src/transport.ts +52 -0
  67. package/src/wasm-database.ts +279 -0
  68. package/src/window.ts +0 -0
  69. package/src/worker-entry.ts +391 -545
  70. package/src/worker-host.ts +800 -0
  71. package/src/worker-protocol.ts +204 -99
  72. package/dist/auth-leases.d.ts +0 -11
  73. package/dist/auth-leases.d.ts.map +0 -1
  74. package/dist/auth-leases.js +0 -140
  75. package/dist/auth-leases.js.map +0 -1
  76. package/dist/blob-limits.d.ts +0 -15
  77. package/dist/blob-limits.d.ts.map +0 -1
  78. package/dist/blob-limits.js +0 -66
  79. package/dist/blob-limits.js.map +0 -1
  80. package/dist/bridge-client.d.ts +0 -69
  81. package/dist/bridge-client.d.ts.map +0 -1
  82. package/dist/bridge-client.js +0 -282
  83. package/dist/bridge-client.js.map +0 -1
  84. package/dist/client-config.d.ts +0 -6
  85. package/dist/client-config.d.ts.map +0 -1
  86. package/dist/client-config.js +0 -18
  87. package/dist/client-config.js.map +0 -1
  88. package/dist/client.d.ts.map +0 -1
  89. package/dist/client.js.map +0 -1
  90. package/dist/command-history.d.ts +0 -35
  91. package/dist/command-history.d.ts.map +0 -1
  92. package/dist/command-history.js +0 -378
  93. package/dist/command-history.js.map +0 -1
  94. package/dist/console-diagnostics.d.ts +0 -33
  95. package/dist/console-diagnostics.d.ts.map +0 -1
  96. package/dist/console-diagnostics.js +0 -496
  97. package/dist/console-diagnostics.js.map +0 -1
  98. package/dist/crdt-yjs/index.d.ts +0 -4
  99. package/dist/crdt-yjs/index.d.ts.map +0 -1
  100. package/dist/crdt-yjs/index.js +0 -4
  101. package/dist/crdt-yjs/index.js.map +0 -1
  102. package/dist/crdt-yjs/webview-host-facade.d.ts +0 -126
  103. package/dist/crdt-yjs/webview-host-facade.d.ts.map +0 -1
  104. package/dist/crdt-yjs/webview-host-facade.js +0 -284
  105. package/dist/crdt-yjs/webview-host-facade.js.map +0 -1
  106. package/dist/crdt-yjs/yjs-document-field-adapter.d.ts +0 -153
  107. package/dist/crdt-yjs/yjs-document-field-adapter.d.ts.map +0 -1
  108. package/dist/crdt-yjs/yjs-document-field-adapter.js +0 -406
  109. package/dist/crdt-yjs/yjs-document-field-adapter.js.map +0 -1
  110. package/dist/crdt-yjs/yjs-prosemirror-bridge.d.ts +0 -73
  111. package/dist/crdt-yjs/yjs-prosemirror-bridge.d.ts.map +0 -1
  112. package/dist/crdt-yjs/yjs-prosemirror-bridge.js +0 -169
  113. package/dist/crdt-yjs/yjs-prosemirror-bridge.js.map +0 -1
  114. package/dist/database.d.ts.map +0 -1
  115. package/dist/database.js.map +0 -1
  116. package/dist/diagnostics.d.ts +0 -10
  117. package/dist/diagnostics.d.ts.map +0 -1
  118. package/dist/diagnostics.js +0 -83
  119. package/dist/diagnostics.js.map +0 -1
  120. package/dist/errors.d.ts.map +0 -1
  121. package/dist/errors.js.map +0 -1
  122. package/dist/generated-bridge.d.ts +0 -365
  123. package/dist/generated-bridge.d.ts.map +0 -1
  124. package/dist/generated-bridge.js +0 -250
  125. package/dist/generated-bridge.js.map +0 -1
  126. package/dist/index.d.ts.map +0 -1
  127. package/dist/index.js.map +0 -1
  128. package/dist/mutations.d.ts +0 -72
  129. package/dist/mutations.d.ts.map +0 -1
  130. package/dist/mutations.js +0 -63
  131. package/dist/mutations.js.map +0 -1
  132. package/dist/network.d.ts +0 -3
  133. package/dist/network.d.ts.map +0 -1
  134. package/dist/network.js +0 -17
  135. package/dist/network.js.map +0 -1
  136. package/dist/react/index.d.ts +0 -169
  137. package/dist/react/index.d.ts.map +0 -1
  138. package/dist/react/index.js +0 -628
  139. package/dist/react/index.js.map +0 -1
  140. package/dist/react-native/index.d.ts +0 -35
  141. package/dist/react-native/index.d.ts.map +0 -1
  142. package/dist/react-native/index.js +0 -49
  143. package/dist/react-native/index.js.map +0 -1
  144. package/dist/runtime-contract.d.ts +0 -13
  145. package/dist/runtime-contract.d.ts.map +0 -1
  146. package/dist/runtime-contract.js +0 -24
  147. package/dist/runtime-contract.js.map +0 -1
  148. package/dist/rust-client.d.ts +0 -106
  149. package/dist/rust-client.d.ts.map +0 -1
  150. package/dist/rust-client.js +0 -938
  151. package/dist/rust-client.js.map +0 -1
  152. package/dist/sentry.d.ts +0 -35
  153. package/dist/sentry.d.ts.map +0 -1
  154. package/dist/sentry.js +0 -155
  155. package/dist/sentry.js.map +0 -1
  156. package/dist/sql-safety.d.ts +0 -3
  157. package/dist/sql-safety.d.ts.map +0 -1
  158. package/dist/sql-safety.js +0 -62
  159. package/dist/sql-safety.js.map +0 -1
  160. package/dist/syncular-runtime-artifacts.json +0 -61
  161. package/dist/tauri/index.d.ts +0 -35
  162. package/dist/tauri/index.d.ts.map +0 -1
  163. package/dist/tauri/index.js +0 -114
  164. package/dist/tauri/index.js.map +0 -1
  165. package/dist/types.d.ts +0 -1096
  166. package/dist/types.d.ts.map +0 -1
  167. package/dist/types.js +0 -2
  168. package/dist/types.js.map +0 -1
  169. package/dist/wasm/.syncular-wasm-profile +0 -1
  170. package/dist/wasm/syncular-runtime-artifact.json +0 -21
  171. package/dist/wasm/syncular.d.ts +0 -207
  172. package/dist/wasm/syncular.js +0 -2341
  173. package/dist/wasm/syncular_bg.wasm +0 -0
  174. package/dist/wasm/syncular_bg.wasm.d.ts +0 -97
  175. package/dist/wasm-bindings/runtime-contract.d.ts +0 -22
  176. package/dist/wasm-bindings/runtime-contract.d.ts.map +0 -1
  177. package/dist/wasm-bindings/runtime-contract.js +0 -112
  178. package/dist/wasm-bindings/runtime-contract.js.map +0 -1
  179. package/dist/wasm-core/.syncular-wasm-profile +0 -1
  180. package/dist/wasm-core/syncular-runtime-artifact.json +0 -17
  181. package/dist/wasm-core/syncular.d.ts +0 -162
  182. package/dist/wasm-core/syncular.js +0 -1847
  183. package/dist/wasm-core/syncular_bg.wasm +0 -0
  184. package/dist/wasm-core/syncular_bg.wasm.d.ts +0 -77
  185. package/dist/wasm-perf/.syncular-wasm-profile +0 -1
  186. package/dist/wasm-perf/syncular-runtime-artifact.json +0 -21
  187. package/dist/wasm-perf/syncular.d.ts +0 -207
  188. package/dist/wasm-perf/syncular.js +0 -2341
  189. package/dist/wasm-perf/syncular_bg.wasm +0 -0
  190. package/dist/wasm-perf/syncular_bg.wasm.d.ts +0 -97
  191. package/dist/wasm-runtime.d.ts +0 -23
  192. package/dist/wasm-runtime.d.ts.map +0 -1
  193. package/dist/wasm-runtime.js +0 -69
  194. package/dist/wasm-runtime.js.map +0 -1
  195. package/dist/worker-client.d.ts +0 -123
  196. package/dist/worker-client.d.ts.map +0 -1
  197. package/dist/worker-client.js +0 -1735
  198. package/dist/worker-client.js.map +0 -1
  199. package/dist/worker-entry.d.ts.map +0 -1
  200. package/dist/worker-entry.js.map +0 -1
  201. package/dist/worker-protocol.d.ts.map +0 -1
  202. package/dist/worker-protocol.js.map +0 -1
  203. package/dist/worker-realtime.d.ts +0 -39
  204. package/dist/worker-realtime.d.ts.map +0 -1
  205. package/dist/worker-realtime.js +0 -677
  206. package/dist/worker-realtime.js.map +0 -1
  207. package/src/auth-leases.ts +0 -251
  208. package/src/blob-limits.ts +0 -98
  209. package/src/bridge-client.ts +0 -512
  210. package/src/client-config.ts +0 -29
  211. package/src/command-history.ts +0 -623
  212. package/src/console-diagnostics.ts +0 -617
  213. package/src/crdt-yjs/index.ts +0 -3
  214. package/src/crdt-yjs/webview-host-facade.ts +0 -477
  215. package/src/crdt-yjs/yjs-document-field-adapter.ts +0 -733
  216. package/src/crdt-yjs/yjs-prosemirror-bridge.ts +0 -272
  217. package/src/diagnostics.ts +0 -116
  218. package/src/generated-bridge.ts +0 -741
  219. package/src/mutations.ts +0 -168
  220. package/src/network.ts +0 -32
  221. package/src/react/index.ts +0 -1036
  222. package/src/react-native/index.ts +0 -152
  223. package/src/runtime-contract.ts +0 -48
  224. package/src/rust-client.ts +0 -1491
  225. package/src/sentry.ts +0 -215
  226. package/src/sql-safety.ts +0 -61
  227. package/src/tauri/index.ts +0 -211
  228. package/src/types.ts +0 -1397
  229. package/src/wasm-bindings/generated-wasm-bindings.d.ts +0 -70
  230. package/src/wasm-bindings/runtime-contract.ts +0 -158
  231. package/src/wasm-runtime.ts +0 -145
  232. package/src/worker-client.ts +0 -2289
  233. package/src/worker-realtime.ts +0 -843
@@ -1,109 +1,214 @@
1
- import { SYNCULAR_ERROR_DEFINITIONS } from '@syncular/core';
2
- import type { SyncularGeneratedWorkerRequest } from './generated-bridge';
1
+ /**
2
+ * The worker RPC protocol (Direction decision 2, 2026-07-03): the whole
3
+ * client core runs in a Web Worker; the UI thread talks to it through
4
+ * this thin, multiplexed postMessage protocol. Exactly SIX message types
5
+ * (`init`, `call`, `ready`, `result`, `error`, `event`) — every logical
6
+ * API method multiplexes over `call`, every notification over `event`.
7
+ *
8
+ * Both sides derive their typing from ONE shared shape: `WorkerApi`.
9
+ * The worker implements it (`worker-entry.ts`); the handle projects it
10
+ * to promises (`worker-host.ts`). Everything crossing the boundary is
11
+ * structured-clone data — no functions, no class instances.
12
+ *
13
+ * Scheduling note (SPEC §8.4): the sync-needed signal is host-driven,
14
+ * and in worker mode the HOST LOOP LIVES IN THE WORKER — wake-ups
15
+ * coalesce into jittered `syncUntilIdle` rounds there (`autoSync`),
16
+ * so the UI thread never has to react to keep data flowing. Events are
17
+ * still forwarded to the handle for visibility.
18
+ */
19
+ import type { WakeReason } from '@syncular/core';
20
+ import type { BlobRef, CachedBlob } from './blob';
3
21
  import type {
4
- SyncularBootstrapStatus,
5
- SyncularDiagnosticEvent,
6
- SyncularErrorCategory,
7
- SyncularErrorCode,
8
- SyncularErrorRecommendedAction,
9
- SyncularLiveQueryEvent,
10
- SyncularRealtimeConnectionState,
11
- SyncularRowsChangedEvent,
12
- } from './types';
13
-
14
- export const SYNCULAR_WORKER_PROTOCOL_VERSION = 2;
15
-
16
- export interface SyncularWorkerErrorPayload {
17
- code: SyncularErrorCode;
18
- message: string;
19
- category?: SyncularErrorCategory;
20
- retryable?: boolean;
21
- recommendedAction?: SyncularErrorRecommendedAction;
22
- name?: string;
23
- stack?: string;
24
- details?: unknown;
22
+ ConflictRecord,
23
+ LeaseState,
24
+ MutationInput,
25
+ PresencePeer,
26
+ RejectionRecord,
27
+ SchemaFloor,
28
+ SubscribeInput,
29
+ SyncClientLimits,
30
+ SyncSummary,
31
+ WindowState,
32
+ } from './client';
33
+ import type { SqlRow, SqlValue } from './database';
34
+ import type { InvalidationEvent } from './invalidation';
35
+ import type { OutboxCommit } from './outbox';
36
+ import type { ClientSchema } from './schema';
37
+ import type { SubscriptionRecord } from './state';
38
+ import type { WindowBase } from './window';
39
+
40
+ // ---------------------------------------------------------------------------
41
+ // Client-local error codes (never wire codes; §10 stays server-owned)
42
+ // ---------------------------------------------------------------------------
43
+
44
+ /** The handle exists but this tab lost the leader election (TODO 3.2). */
45
+ export const NOT_LEADER_CODE = 'client.not_leader';
46
+ /** The worker (or its RPC channel) failed outside protocol semantics. */
47
+ export const WORKER_FAILED_CODE = 'client.worker_failed';
48
+
49
+ // ---------------------------------------------------------------------------
50
+ // Init configuration (structured-clone safe)
51
+ // ---------------------------------------------------------------------------
52
+
53
+ export type WorkerDatabaseInit =
54
+ | {
55
+ /** THE persistent mode: opfs-sahpool, named database. */
56
+ readonly mode: 'persistent';
57
+ readonly name: string;
58
+ /** Optional pool directory override (default `.syncular/<name>`). */
59
+ readonly directory?: string;
60
+ }
61
+ | {
62
+ /**
63
+ * Bootstrap-provided database (tests inject bun:sqlite here). The
64
+ * worker entry MUST have an `openDatabase` override or init fails.
65
+ */
66
+ readonly mode: 'custom';
67
+ readonly options?: unknown;
68
+ };
69
+
70
+ export interface WorkerEndpoints {
71
+ /** POST target for SSP2 sync rounds (§1.1). */
72
+ readonly syncUrl: string;
73
+ /** Segment download base URL; omit when segments are not served. */
74
+ readonly segmentsUrl?: string;
75
+ /** Blob upload/download base URL (§5.9); omit when blobs are unused. */
76
+ readonly blobsUrl?: string;
77
+ /**
78
+ * WebSocket URL for §8 realtime. The literal placeholder `{clientId}`
79
+ * is substituted with the (possibly persisted) client id after start.
80
+ */
81
+ readonly realtimeUrl?: string;
25
82
  }
26
83
 
27
- export function createSyncularWorkerErrorPayload(
28
- code: SyncularErrorCode,
29
- message?: string,
30
- options: {
31
- name?: string;
32
- stack?: string;
33
- details?: unknown;
34
- } = {}
35
- ): SyncularWorkerErrorPayload {
36
- const definition = SYNCULAR_ERROR_DEFINITIONS[code];
37
- return {
38
- code,
39
- message: message ?? definition.message,
40
- category: definition.category,
41
- retryable: definition.retryable,
42
- recommendedAction: definition.recommendedAction,
43
- ...(options.name ? { name: options.name } : {}),
44
- ...(options.stack ? { stack: options.stack } : {}),
45
- ...(options.details !== undefined ? { details: options.details } : {}),
46
- };
84
+ export interface WorkerInitConfig {
85
+ readonly schema: ClientSchema;
86
+ readonly database: WorkerDatabaseInit;
87
+ readonly endpoints: WorkerEndpoints;
88
+ readonly clientId?: string;
89
+ readonly limits?: SyncClientLimits;
90
+ /**
91
+ * Worker-side host loop (§8.4): coalesce wake-ups into jittered
92
+ * `syncUntilIdle` rounds inside the worker. Default true.
93
+ */
94
+ readonly autoSync?: boolean;
95
+ /** Max jitter before a coalesced auto-sync round (default 200 ms). */
96
+ readonly wakeJitterMs?: number;
97
+ }
98
+
99
+ /** Successful init reply. */
100
+ export interface WorkerInitResult {
101
+ readonly clientId: string;
47
102
  }
48
103
 
49
- export type {
50
- SyncularWorkerRealtimeOptions,
51
- SyncularWorkerRuntimeArtifact,
52
- } from './generated-bridge';
53
- export type SyncularWorkerRequest = SyncularGeneratedWorkerRequest;
104
+ // ---------------------------------------------------------------------------
105
+ // The logical API — the one shared shape (worker implements, handle projects)
106
+ // ---------------------------------------------------------------------------
54
107
 
55
- interface SyncularWorkerResponseBase {
56
- id: number;
57
- protocolVersion: typeof SYNCULAR_WORKER_PROTOCOL_VERSION;
108
+ export interface WorkerApi {
109
+ subscribe(input: SubscribeInput): void;
110
+ unsubscribe(id: string): void;
111
+ /** §4.8 windowed subscriptions: set the live units for a window base. */
112
+ setWindow(base: WindowBase, units: readonly string[]): Promise<void>;
113
+ /** §4.8 completeness oracle (I3): the windowed-in units for a base. */
114
+ windowState(base: WindowBase): WindowState;
115
+ mutate(mutations: readonly MutationInput[]): string;
116
+ sync(): Promise<SyncSummary>;
117
+ syncUntilIdle(maxRounds?: number): Promise<SyncSummary>;
118
+ query(sql: string, params?: readonly SqlValue[]): SqlRow[];
119
+ conflicts(): readonly ConflictRecord[];
120
+ rejections(): readonly RejectionRecord[];
121
+ schemaFloor(): SchemaFloor | undefined;
122
+ /** §7.3.5: the opaque auth-lease state, or undefined. */
123
+ leaseState(): LeaseState | undefined;
124
+ /** §7.4.5: true while a schema-bump reset + first re-bootstrap runs. */
125
+ upgrading(): boolean;
126
+ syncNeeded(): boolean;
127
+ pendingCommits(): OutboxCommit[];
128
+ subscriptions(): SubscriptionRecord[];
129
+ subscription(id: string): SubscriptionRecord | undefined;
130
+ connectRealtime(): Promise<void>;
131
+ disconnectRealtime(): void;
132
+ /** §8.6 presence: publish/clear a scope-keyed presence document. */
133
+ setPresence(scopeKey: string, doc: Record<string, unknown> | null): void;
134
+ /** §8.6 presence: the peers currently present on a scope key. */
135
+ presence(scopeKey: string): readonly PresencePeer[];
136
+ /** §5.9 blobs: stage bytes (returns the canonical ref) / resolve bytes. */
137
+ uploadBlob(
138
+ bytes: Uint8Array,
139
+ options?: { readonly mediaType?: string; readonly name?: string },
140
+ ): Promise<BlobRef>;
141
+ fetchBlob(blobIdOrRef: string): Promise<CachedBlob>;
142
+ /** Sever/restore the transport + realtime (offline simulation, demos). */
143
+ setOffline(offline: boolean): void;
144
+ close(): Promise<void>;
58
145
  }
59
146
 
60
- interface SyncularWorkerEventBase {
61
- protocolVersion: typeof SYNCULAR_WORKER_PROTOCOL_VERSION;
147
+ export type WorkerMethod = keyof WorkerApi;
148
+
149
+ // ---------------------------------------------------------------------------
150
+ // Messages (6 types total)
151
+ // ---------------------------------------------------------------------------
152
+
153
+ /** `call` for method M, with args typed straight off `WorkerApi`. */
154
+ export type WorkerCallMessage = {
155
+ [M in WorkerMethod]: {
156
+ readonly t: 'call';
157
+ readonly id: number;
158
+ readonly method: M;
159
+ readonly args: Parameters<WorkerApi[M]>;
160
+ };
161
+ }[WorkerMethod];
162
+
163
+ export type MainToWorkerMessage =
164
+ | {
165
+ readonly t: 'init';
166
+ readonly id: number;
167
+ readonly config: WorkerInitConfig;
168
+ }
169
+ | WorkerCallMessage;
170
+
171
+ export interface WorkerErrorShape {
172
+ readonly code: string;
173
+ readonly message: string;
174
+ readonly retryable: boolean;
62
175
  }
63
176
 
64
- export type SyncularWorkerResponse =
65
- | (SyncularWorkerResponseBase & { ok: true; value?: unknown })
66
- | (SyncularWorkerResponseBase & {
67
- ok: false;
68
- error: SyncularWorkerErrorPayload;
69
- });
70
-
71
- export type SyncularWorkerEvent =
72
- | (SyncularWorkerEventBase & {
73
- type: 'liveQueryEvents';
74
- events: Array<SyncularLiveQueryEvent<Record<string, unknown>>>;
75
- })
76
- | (SyncularWorkerEventBase &
77
- SyncularRowsChangedEvent & {
78
- type: 'rowsChanged';
79
- })
80
- | (SyncularWorkerEventBase & {
81
- type: 'bootstrapChanged';
82
- bootstrap: SyncularBootstrapStatus;
83
- })
84
- | (SyncularWorkerEventBase & {
85
- type: 'realtimeState';
86
- state: SyncularRealtimeConnectionState;
87
- })
88
- | (SyncularWorkerEventBase & {
89
- type: 'presenceEvent';
90
- action: 'join' | 'leave' | 'update' | 'snapshot';
91
- scopeKey: string;
92
- clientId?: string;
93
- actorId?: string;
94
- metadata?: Record<string, unknown>;
95
- entries?: Array<{
96
- clientId: string;
97
- actorId: string;
98
- joinedAt: number;
99
- metadata?: Record<string, unknown>;
100
- }>;
101
- })
102
- | (SyncularWorkerEventBase & {
103
- type: 'diagnostic';
104
- event: SyncularDiagnosticEvent;
105
- });
106
-
107
- export type SyncularWorkerOutboundMessage =
108
- | SyncularWorkerResponse
109
- | SyncularWorkerEvent;
177
+ export type SyncWorkerEvent =
178
+ | { readonly kind: 'sync-needed'; readonly reason: 'hello' | WakeReason }
179
+ | { readonly kind: 'conflict'; readonly conflict: ConflictRecord }
180
+ | {
181
+ /** An autoSync round finished (or failed) inside the worker. */
182
+ readonly kind: 'synced';
183
+ readonly summary?: SyncSummary;
184
+ readonly error?: WorkerErrorShape;
185
+ }
186
+ | {
187
+ /** §7.4.5: the schema-bump `upgrading` state changed in the worker. */
188
+ readonly kind: 'upgrading';
189
+ readonly upgrading: boolean;
190
+ }
191
+ | {
192
+ /** §8.6: presence on a scope key changed inside the worker. */
193
+ readonly kind: 'presence';
194
+ readonly scopeKey: string;
195
+ }
196
+ | {
197
+ /**
198
+ * TODO 3.1 / I1: one coalesced apply-batch invalidation. `Set`s
199
+ * structured-clone across the worker boundary, so the event crosses
200
+ * verbatim — the handle re-emits it to `onInvalidate` listeners.
201
+ */
202
+ readonly kind: 'invalidate';
203
+ readonly event: InvalidationEvent;
204
+ };
205
+
206
+ export type WorkerToMainMessage =
207
+ | { readonly t: 'ready' }
208
+ | { readonly t: 'result'; readonly id: number; readonly value: unknown }
209
+ | {
210
+ readonly t: 'error';
211
+ readonly id: number;
212
+ readonly error: WorkerErrorShape;
213
+ }
214
+ | { readonly t: 'event'; readonly event: SyncWorkerEvent };
@@ -1,11 +0,0 @@
1
- import { type SyncAuthLeaseIssueRequest } from '@syncular/core';
2
- import type { SyncularAppSchema, SyncularAuthHeaders, SyncularAuthLeaseRecord } from './types';
3
- export declare function issueSyncularAuthLease(args: {
4
- baseUrl: string;
5
- headers: SyncularAuthHeaders;
6
- request: SyncAuthLeaseIssueRequest;
7
- appSchema?: SyncularAppSchema;
8
- fetchImpl?: typeof fetch;
9
- nowMs?: number;
10
- }): Promise<SyncularAuthLeaseRecord>;
11
- //# sourceMappingURL=auth-leases.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth-leases.d.ts","sourceRoot":"","sources":["../src/auth-leases.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,yBAAyB,EAE/B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EACV,iBAAiB,EACjB,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAEjB,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,mBAAmB,CAAC;IAC7B,OAAO,EAAE,yBAAyB,CAAC;IACnC,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAiCnC"}
@@ -1,140 +0,0 @@
1
- import { resolveUrlFromBase, } from '@syncular/core';
2
- export async function issueSyncularAuthLease(args) {
3
- if (args.appSchema) {
4
- validateSyncularAuthLeaseIssueRequestAgainstAppSchema(args.request, args.appSchema);
5
- }
6
- const fetchImpl = args.fetchImpl ?? fetch;
7
- const headers = new Headers(args.headers);
8
- headers.set('accept', 'application/json');
9
- headers.set('content-type', 'application/json');
10
- const response = await fetchImpl(resolveUrlFromBase(args.baseUrl, 'auth-leases/issue'), {
11
- method: 'POST',
12
- headers,
13
- body: JSON.stringify(args.request),
14
- });
15
- if (!response.ok) {
16
- throw await authLeaseIssueHttpError(response);
17
- }
18
- const issueResponse = assertAuthLeaseIssueResponse(await response.json());
19
- if (args.appSchema) {
20
- validateSyncularAuthLeaseIssueResponseAgainstAppSchema(issueResponse, args.request.schemaVersion, args.appSchema);
21
- }
22
- return syncularAuthLeaseRecordFromIssueResponse(issueResponse, args.nowMs);
23
- }
24
- function validateSyncularAuthLeaseIssueRequestAgainstAppSchema(request, appSchema) {
25
- validateSyncularAuthLeaseSchemaVersion(request.schemaVersion, appSchema, 'auth lease request');
26
- if (request.ttlMs != null && request.ttlMs <= 0) {
27
- throw new Error('auth lease request ttlMs must be positive');
28
- }
29
- validateSyncularAuthLeaseScopesAgainstAppSchema(request.scopes, appSchema, 'auth lease request');
30
- }
31
- function validateSyncularAuthLeaseIssueResponseAgainstAppSchema(response, requestSchemaVersion, appSchema) {
32
- if (response.payload.schemaVersion !== requestSchemaVersion) {
33
- throw new Error(`auth lease response schemaVersion ${response.payload.schemaVersion} does not match request schemaVersion ${requestSchemaVersion}`);
34
- }
35
- validateSyncularAuthLeaseSchemaVersion(response.payload.schemaVersion, appSchema, 'auth lease payload');
36
- validateSyncularAuthLeaseScopesAgainstAppSchema(response.payload.scopes, appSchema, 'auth lease payload');
37
- }
38
- function validateSyncularAuthLeaseSchemaVersion(schemaVersion, appSchema, source) {
39
- if (schemaVersion === appSchema.schemaVersion)
40
- return;
41
- throw new Error(`${source} schemaVersion ${schemaVersion} does not match generated app schema version ${appSchema.schemaVersion}`);
42
- }
43
- function validateSyncularAuthLeaseScopesAgainstAppSchema(scopes, appSchema, source) {
44
- if (scopes.length === 0) {
45
- throw new Error(`${source} must contain at least one generated table scope`);
46
- }
47
- for (const scope of scopes) {
48
- validateSyncularAuthLeaseScopeAgainstAppSchema(scope, appSchema, source);
49
- }
50
- }
51
- function validateSyncularAuthLeaseScopeAgainstAppSchema(scope, appSchema, source) {
52
- if (scope.subscriptionId.trim() === '') {
53
- throw new Error(`${source} scope subscriptionId must not be empty`);
54
- }
55
- const tableName = scope.table.trim();
56
- if (tableName === '') {
57
- throw new Error(`${source} scope table must not be empty`);
58
- }
59
- const table = appSchema.tables.find((table) => table.name === tableName);
60
- if (!table) {
61
- throw new Error(`${source} scope references unknown generated table ${tableName}`);
62
- }
63
- if (scope.operations.length === 0) {
64
- throw new Error(`${source} scope for table ${tableName} must include at least one operation`);
65
- }
66
- for (const operation of scope.operations) {
67
- const operationName = operation;
68
- if (operationName !== 'upsert' && operationName !== 'delete') {
69
- throw new Error(`${source} scope for table ${tableName} references unsupported operation ${operationName}`);
70
- }
71
- }
72
- const scopeKeys = new Set(table.scopes.map((scope) => scope.name));
73
- for (const key of Object.keys(scope.values)) {
74
- if (!scopeKeys.has(key)) {
75
- throw new Error(`${source} scope for table ${tableName} references unknown generated scope ${key}`);
76
- }
77
- }
78
- for (const generatedScope of table.scopes) {
79
- if (generatedScope.required && !(generatedScope.name in scope.values)) {
80
- throw new Error(`${source} scope for table ${tableName} is missing required generated scope ${generatedScope.name}`);
81
- }
82
- }
83
- for (const [key, value] of Object.entries(scope.values)) {
84
- validateSyncularAuthLeaseScopeValue(source, tableName, key, value);
85
- }
86
- }
87
- function validateSyncularAuthLeaseScopeValue(source, table, key, value) {
88
- if (typeof value === 'string' && value.length > 0)
89
- return;
90
- if (Array.isArray(value) &&
91
- value.length > 0 &&
92
- value.every((entry) => typeof entry === 'string' && entry.length > 0)) {
93
- return;
94
- }
95
- throw new Error(`${source} scope ${table}.${key} must be a non-empty string or non-empty string array`);
96
- }
97
- function syncularAuthLeaseRecordFromIssueResponse(response, nowMs = Date.now()) {
98
- return {
99
- leaseId: response.payload.leaseId,
100
- kid: response.protectedHeader.kid,
101
- actorId: response.payload.actorId,
102
- issuedAtMs: response.payload.issuedAtMs,
103
- notBeforeMs: response.payload.notBeforeMs,
104
- expiresAtMs: response.payload.expiresAtMs,
105
- schemaVersion: response.payload.schemaVersion,
106
- payloadJson: JSON.stringify(response.payload),
107
- token: response.token,
108
- status: 'active',
109
- lastValidationError: null,
110
- createdAtMs: response.payload.issuedAtMs,
111
- updatedAtMs: Math.trunc(nowMs),
112
- };
113
- }
114
- async function authLeaseIssueHttpError(response) {
115
- const body = await response.text().catch(() => '');
116
- return new Error(`Syncular auth lease issue failed with HTTP ${response.status}: ${body}`);
117
- }
118
- function assertAuthLeaseIssueResponse(value) {
119
- if (!value || typeof value !== 'object') {
120
- throw new Error('Syncular auth lease issue returned invalid JSON');
121
- }
122
- const response = value;
123
- const payload = response.payload;
124
- const protectedHeader = response.protectedHeader;
125
- if (response.ok !== true ||
126
- typeof response.token !== 'string' ||
127
- !payload ||
128
- typeof payload.leaseId !== 'string' ||
129
- typeof payload.actorId !== 'string' ||
130
- typeof payload.issuedAtMs !== 'number' ||
131
- typeof payload.notBeforeMs !== 'number' ||
132
- typeof payload.expiresAtMs !== 'number' ||
133
- typeof payload.schemaVersion !== 'number' ||
134
- !protectedHeader ||
135
- typeof protectedHeader.kid !== 'string') {
136
- throw new Error('Syncular auth lease issue returned an invalid lease');
137
- }
138
- return response;
139
- }
140
- //# sourceMappingURL=auth-leases.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth-leases.js","sourceRoot":"","sources":["../src/auth-leases.ts"],"names":[],"mappings":"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"}
@@ -1,15 +0,0 @@
1
- import type { SyncularBlobLimits, SyncularBlobStoreOptions, SyncularDiagnosticSink } from './types';
2
- export declare const DEFAULT_SYNCULAR_BROWSER_MAX_BLOB_PAYLOAD_BYTES: number;
3
- export type SyncularBlobLimitOperation = 'store' | 'retrieve';
4
- export type SyncularBlobLimitInput = Blob | File | Uint8Array;
5
- export declare function resolveSyncularBlobLimits(limits: SyncularBlobLimits | undefined): Required<SyncularBlobLimits>;
6
- export declare function syncularBlobInputSize(data: SyncularBlobLimitInput): number;
7
- export declare function assertSyncularBlobPayloadLimit(args: {
8
- operation: SyncularBlobLimitOperation;
9
- size: number;
10
- limits: SyncularBlobLimits | undefined;
11
- options?: SyncularBlobStoreOptions;
12
- refHash?: string;
13
- diagnostics?: SyncularDiagnosticSink;
14
- }): void;
15
- //# sourceMappingURL=blob-limits.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"blob-limits.d.ts","sourceRoot":"","sources":["../src/blob-limits.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,kBAAkB,EAClB,wBAAwB,EAExB,sBAAsB,EACvB,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,+CAA+C,QAAmB,CAAC;AAEhF,MAAM,MAAM,0BAA0B,GAAG,OAAO,GAAG,UAAU,CAAC;AAE9D,MAAM,MAAM,sBAAsB,GAAG,IAAI,GAAG,IAAI,GAAG,UAAU,CAAC;AAE9D,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,kBAAkB,GAAG,SAAS,GACrC,QAAQ,CAAC,kBAAkB,CAAC,CAO9B;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,sBAAsB,GAAG,MAAM,CAI1E;AAED,wBAAgB,8BAA8B,CAAC,IAAI,EAAE;IACnD,SAAS,EAAE,0BAA0B,CAAC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACvC,OAAO,CAAC,EAAE,wBAAwB,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,sBAAsB,CAAC;CACtC,GAAG,IAAI,CAYP"}
@@ -1,66 +0,0 @@
1
- import { SYNCULAR_ERROR_DEFINITIONS } from '@syncular/core';
2
- import { SyncularClientError } from './errors.js';
3
- export const DEFAULT_SYNCULAR_BROWSER_MAX_BLOB_PAYLOAD_BYTES = 64 * 1024 * 1024;
4
- export function resolveSyncularBlobLimits(limits) {
5
- return {
6
- maxPayloadBytes: normalizeLimit(limits?.maxPayloadBytes, DEFAULT_SYNCULAR_BROWSER_MAX_BLOB_PAYLOAD_BYTES),
7
- };
8
- }
9
- export function syncularBlobInputSize(data) {
10
- if (data instanceof Uint8Array)
11
- return data.byteLength;
12
- const maybeSized = data;
13
- return typeof maybeSized.size === 'number' ? maybeSized.size : 0;
14
- }
15
- export function assertSyncularBlobPayloadLimit(args) {
16
- const limits = resolveSyncularBlobLimits(args.limits);
17
- if (args.size <= limits.maxPayloadBytes)
18
- return;
19
- const error = createSyncularBlobTooLargeError({
20
- operation: args.operation,
21
- size: args.size,
22
- maxPayloadBytes: limits.maxPayloadBytes,
23
- options: args.options,
24
- refHash: args.refHash,
25
- });
26
- args.diagnostics?.(createSyncularBlobLimitDiagnostic(error));
27
- throw error;
28
- }
29
- function createSyncularBlobTooLargeError(args) {
30
- const definition = SYNCULAR_ERROR_DEFINITIONS['blob.too_large'];
31
- return new SyncularClientError({
32
- code: 'blob.too_large',
33
- category: definition.category,
34
- retryable: definition.retryable,
35
- recommendedAction: definition.recommendedAction,
36
- message: `Syncular blob ${args.operation} payload is ${args.size} bytes; max is ${args.maxPayloadBytes} bytes.`,
37
- details: {
38
- operation: args.operation,
39
- size: args.size,
40
- maxPayloadBytes: args.maxPayloadBytes,
41
- ...(args.refHash ? { hash: args.refHash } : {}),
42
- ...(args.options?.mimeType ? { mimeType: args.options.mimeType } : {}),
43
- ...(args.options?.immediate !== undefined
44
- ? { immediate: args.options.immediate }
45
- : {}),
46
- },
47
- });
48
- }
49
- function createSyncularBlobLimitDiagnostic(error) {
50
- return {
51
- at: Date.now(),
52
- level: 'warn',
53
- source: 'blob',
54
- code: error.code,
55
- message: error.message,
56
- details: error.details,
57
- };
58
- }
59
- function normalizeLimit(value, fallback) {
60
- if (value === undefined)
61
- return fallback;
62
- if (!Number.isFinite(value) || value < 0)
63
- return fallback;
64
- return Math.floor(value);
65
- }
66
- //# sourceMappingURL=blob-limits.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"blob-limits.js","sourceRoot":"","sources":["../src/blob-limits.ts"],"names":[],"mappings":"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"}
@@ -1,69 +0,0 @@
1
- import { type SyncAuthLeaseIssueRequest, type SyncOperation } from '@syncular/core';
2
- import { type Dialect } from 'kysely';
3
- import type { SyncularBlobClientLike, SyncularClientLike } from './client';
4
- import { type MutationReceipt } from './mutations';
5
- import type { SyncularAuthLeaseRecord, SyncularClientEventSink, SyncularClientEventType, SyncularConflictResolution, SyncularConflictStats, SyncularConflictSummary, SyncularConnectionState, SyncularDiagnosticSnapshot, SyncularLifecycleState, SyncularOutboxStats, SyncularPresenceEntry, SyncularPresenceSink, SyncularSubscriptionSpec, SyncularSyncRequestOptions, SyncularSyncResult } from './types';
6
- export interface SyncularBridgeQueryRequest {
7
- sql: string;
8
- parameters: readonly unknown[];
9
- }
10
- export interface SyncularBridgeQueryResult<Row extends Record<string, unknown> = Record<string, unknown>> {
11
- rows: Row[];
12
- numAffectedRows?: bigint | number | string;
13
- insertId?: bigint | number | string | null;
14
- }
15
- export interface SyncularBridgeMutationBatch {
16
- operations: SyncOperation[];
17
- }
18
- export interface SyncularBridgeStatus {
19
- lifecycle?: SyncularLifecycleState;
20
- connection?: SyncularConnectionState;
21
- outbox?: SyncularOutboxStats | null;
22
- conflicts?: SyncularConflictStats | null;
23
- }
24
- export interface SyncularBridgePresence {
25
- get<TMetadata = Record<string, unknown>>(scopeKey: string): SyncularPresenceEntry<TMetadata>[];
26
- join(scopeKey: string, metadata?: Record<string, unknown>): void;
27
- leave(scopeKey: string): void;
28
- updateMetadata(scopeKey: string, metadata: Record<string, unknown>): void;
29
- onChange<TMetadata = Record<string, unknown>>(listener: SyncularPresenceSink<TMetadata>): () => void;
30
- }
31
- export interface SyncularBridgeConflicts {
32
- list(): Promise<SyncularConflictSummary[]>;
33
- retryKeepLocal(id: string): Promise<string>;
34
- resolve(id: string, resolution: SyncularConflictResolution): Promise<void>;
35
- }
36
- export interface SyncularBridge {
37
- open?(): Promise<void> | void;
38
- close?(): Promise<void> | void;
39
- executeSql<Row extends Record<string, unknown> = Record<string, unknown>>(request: SyncularBridgeQueryRequest): Promise<SyncularBridgeQueryResult<Row>> | SyncularBridgeQueryResult<Row>;
40
- applyMutationsCommit(batch: SyncularBridgeMutationBatch): Promise<string | MutationReceipt> | string | MutationReceipt;
41
- applyLeasedMutationsCommit?(batch: SyncularBridgeMutationBatch): Promise<string | MutationReceipt> | string | MutationReceipt;
42
- sync?(): Promise<SyncularSyncResult>;
43
- resumeFromBackground?(options?: SyncularSyncRequestOptions): Promise<SyncularSyncResult>;
44
- start?(): Promise<void>;
45
- stop?(): Promise<void>;
46
- setSubscriptions?(subscriptions: readonly SyncularSubscriptionSpec[]): Promise<void>;
47
- getStatus?(): Promise<SyncularBridgeStatus> | SyncularBridgeStatus;
48
- issueAuthLease?(request: SyncAuthLeaseIssueRequest): Promise<SyncularAuthLeaseRecord>;
49
- upsertAuthLease?(lease: SyncularAuthLeaseRecord): Promise<void>;
50
- authLease?(leaseId: string): Promise<SyncularAuthLeaseRecord | null>;
51
- activeAuthLeases?(actorId?: string | null, nowMs?: number): Promise<SyncularAuthLeaseRecord[]>;
52
- diagnosticSnapshot?(): Promise<SyncularDiagnosticSnapshot>;
53
- on?<T extends SyncularClientEventType>(event: T, listener: SyncularClientEventSink<T>): () => void;
54
- presence?: SyncularBridgePresence;
55
- conflicts?: SyncularBridgeConflicts;
56
- blobs?: Partial<SyncularBlobClientLike>;
57
- }
58
- export interface CreateSyncularBridgeClientOptions {
59
- bridge: SyncularBridge;
60
- sync?: {
61
- autoSyncAfterMutation?: boolean;
62
- };
63
- idColumn?: string;
64
- versionColumn?: string | null;
65
- omitColumns?: readonly string[];
66
- }
67
- export declare function createSyncularBridgeDialect(bridge: SyncularBridge): Dialect;
68
- export declare function createSyncularBridgeClient<DB>(options: CreateSyncularBridgeClientOptions): Promise<SyncularClientLike<DB>>;
69
- //# sourceMappingURL=bridge-client.d.ts.map