@powersync/web 0.0.0-dev-20251201150812 → 0.0.0-dev-20251209082930

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 (47) hide show
  1. package/dist/0b19af1befc07ce338dd.wasm +0 -0
  2. package/dist/2632c3bda9473da74fd5.wasm +0 -0
  3. package/dist/64f5351ba3784bfe2f3e.wasm +0 -0
  4. package/dist/9318ca94aac4d0fe0135.wasm +0 -0
  5. package/dist/index.umd.js +219 -115
  6. package/dist/index.umd.js.map +1 -1
  7. package/dist/worker/SharedSyncImplementation.umd.js +164 -109
  8. package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
  9. package/dist/worker/WASQLiteDB.umd.js +24 -12
  10. package/dist/worker/WASQLiteDB.umd.js.map +1 -1
  11. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite-async_mjs.umd.js +16 -3
  12. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite-async_mjs.umd.js.map +1 -1
  13. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite_mjs.umd.js +16 -3
  14. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite_mjs.umd.js.map +1 -1
  15. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js +16 -3
  16. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js.map +1 -1
  17. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js +16 -3
  18. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js.map +1 -1
  19. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_OPFSCoopSyncVFS_js.umd.js +18 -11
  20. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_OPFSCoopSyncVFS_js.umd.js.map +1 -1
  21. package/lib/package.json +2 -2
  22. package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.d.ts +4 -1
  23. package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.js +60 -29
  24. package/lib/src/db/adapters/wa-sqlite/WASQLiteConnection.js +11 -2
  25. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.d.ts +1 -1
  26. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +2 -2
  27. package/lib/src/worker/sync/SharedSyncImplementation.js +80 -68
  28. package/lib/tsconfig.tsbuildinfo +1 -1
  29. package/package.json +5 -5
  30. package/src/db/adapters/LockedAsyncDatabaseAdapter.ts +79 -48
  31. package/src/db/adapters/wa-sqlite/WASQLiteConnection.ts +11 -3
  32. package/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.ts +3 -3
  33. package/src/worker/db/WASQLiteDB.worker.ts +0 -1
  34. package/src/worker/sync/SharedSyncImplementation.ts +89 -74
  35. package/dist/1807036ae51c10ee4d23.wasm +0 -0
  36. package/dist/307d8ce2280e3bae09d5.wasm +0 -0
  37. package/dist/cd8b9e8f4c87bf81c169.wasm +0 -0
  38. package/dist/e797080f5ed0b5324166.wasm +0 -0
  39. package/lib/src/worker/sync/MockSyncService.d.ts +0 -2
  40. package/lib/src/worker/sync/MockSyncService.js +0 -3
  41. package/lib/src/worker/sync/MockSyncServiceTypes.d.ts +0 -101
  42. package/lib/src/worker/sync/MockSyncServiceTypes.js +0 -1
  43. package/lib/src/worker/sync/MockSyncServiceWorker.d.ts +0 -56
  44. package/lib/src/worker/sync/MockSyncServiceWorker.js +0 -369
  45. package/src/worker/sync/MockSyncService.ts +0 -3
  46. package/src/worker/sync/MockSyncServiceTypes.ts +0 -71
  47. package/src/worker/sync/MockSyncServiceWorker.ts +0 -406
@@ -1,369 +0,0 @@
1
- /**
2
- * Mock sync service implementation for shared worker environments.
3
- * This allows tests to mock sync responses when using enableMultipleTabs: true.
4
- * Requests are kept pending until a client explicitly creates a response.
5
- */
6
- export class MockSyncService {
7
- pendingRequests = new Map();
8
- activeResponses = new Map();
9
- nextId = 0;
10
- automaticResponse = null;
11
- /**
12
- * A Static instance of the mock sync service.
13
- * This can be used directly for non-worker environments.
14
- * A proxy is required for worker environments.
15
- */
16
- static GLOBAL_INSTANCE = new MockSyncService();
17
- /**
18
- * Register a new pending request (called by WebRemote when a sync stream is requested).
19
- * Returns a promise that resolves when a client creates a response for this request.
20
- */
21
- registerPendingRequest(url, method, headers, body, signal) {
22
- const id = `pending-${++this.nextId}`;
23
- let resolveResponse;
24
- let rejectResponse;
25
- const responsePromise = new Promise((resolve, reject) => {
26
- resolveResponse = resolve;
27
- rejectResponse = reject;
28
- });
29
- const pendingRequest = {
30
- id,
31
- url,
32
- method,
33
- headers,
34
- body,
35
- responsePromise: {
36
- resolve: resolveResponse,
37
- reject: rejectResponse
38
- }
39
- };
40
- this.pendingRequests.set(id, pendingRequest);
41
- signal?.addEventListener('abort', () => {
42
- this.pendingRequests.delete(id);
43
- rejectResponse(new Error('Request aborted'));
44
- // if already in active responses, remove it
45
- if (this.activeResponses.has(id)) {
46
- const response = this.activeResponses.get(id);
47
- if (response) {
48
- response.stream.close();
49
- }
50
- this.activeResponses.delete(id);
51
- }
52
- });
53
- // If automatic response is configured, apply it immediately
54
- if (this.automaticResponse) {
55
- // Use setTimeout to ensure the response is created asynchronously
56
- // This prevents issues if the response creation happens synchronously
57
- setTimeout(() => {
58
- try {
59
- // Create response with automatic config
60
- this.createResponse(id, this.automaticResponse.status, this.automaticResponse.headers);
61
- // Push body lines if provided
62
- if (this.automaticResponse.bodyLines) {
63
- for (const line of this.automaticResponse.bodyLines) {
64
- const lineStr = `${JSON.stringify(line)}\n`;
65
- const encoder = new TextEncoder();
66
- this.pushBodyData(id, encoder.encode(lineStr));
67
- }
68
- }
69
- // Complete the response
70
- this.completeResponse(id);
71
- }
72
- catch (e) {
73
- // If automatic response fails, reject the promise
74
- rejectResponse(e instanceof Error ? e : new Error(String(e)));
75
- }
76
- }, 0);
77
- }
78
- // Return the promise - it will resolve when createResponse is called (or immediately if auto-response is set)
79
- return responsePromise;
80
- }
81
- /**
82
- * Get all pending requests
83
- */
84
- getPendingRequestsSync() {
85
- return Array.from(this.pendingRequests.values()).map((pr) => ({
86
- id: pr.id,
87
- url: pr.url,
88
- method: pr.method,
89
- headers: pr.headers,
90
- body: pr.body
91
- }));
92
- }
93
- /**
94
- * Create a response for a pending request.
95
- * This resolves the response promise and allows pushing body lines.
96
- */
97
- createResponse(pendingRequestId, status, headers) {
98
- const pendingRequest = this.pendingRequests.get(pendingRequestId);
99
- if (!pendingRequest) {
100
- throw new Error(`Pending request ${pendingRequestId} not found`);
101
- }
102
- // Create a readable stream that the mock service can control
103
- // Response.body is always ReadableStream<Uint8Array>, so we use Uint8Array
104
- const stream = new ReadableStream({
105
- start: (controller) => {
106
- // Store the active response once the controller is available
107
- // The start callback is called synchronously, so this is safe
108
- const activeResponse = {
109
- id: pendingRequestId,
110
- status,
111
- headers,
112
- stream: controller
113
- };
114
- this.activeResponses.set(pendingRequestId, activeResponse);
115
- },
116
- cancel: () => {
117
- // Remove response when stream is cancelled
118
- this.activeResponses.delete(pendingRequestId);
119
- this.pendingRequests.delete(pendingRequestId);
120
- }
121
- });
122
- // Create the Response object
123
- const response = new Response(stream, {
124
- status,
125
- headers
126
- });
127
- // Resolve the pending request's promise
128
- pendingRequest.responsePromise.resolve(response);
129
- // Remove from pending (it's now active)
130
- this.pendingRequests.delete(pendingRequestId);
131
- }
132
- /**
133
- * Push body data to an active response.
134
- * Accepts either text (string) or binary data (ArrayBuffer or Uint8Array).
135
- * All data is encoded to Uint8Array before enqueueing (required by ReadableStream<Uint8Array>).
136
- */
137
- pushBodyData(pendingRequestId, data) {
138
- const activeResponse = this.activeResponses.get(pendingRequestId);
139
- if (!activeResponse) {
140
- throw new Error(`Active response ${pendingRequestId} not found`);
141
- }
142
- try {
143
- let encoded;
144
- if (typeof data === 'string') {
145
- // Encode string to Uint8Array (required by ReadableStream<Uint8Array>)
146
- const encoder = new TextEncoder();
147
- encoded = encoder.encode(data);
148
- }
149
- else if (data instanceof ArrayBuffer) {
150
- // Convert ArrayBuffer to Uint8Array
151
- encoded = new Uint8Array(data);
152
- }
153
- else {
154
- // Already Uint8Array, use directly
155
- encoded = data;
156
- }
157
- activeResponse.stream.enqueue(encoded);
158
- }
159
- catch (e) {
160
- // Stream might be closed, remove it
161
- this.activeResponses.delete(pendingRequestId);
162
- throw new Error(`Failed to push data to response ${pendingRequestId}: ${e}`);
163
- }
164
- }
165
- /**
166
- * Complete an active response (close the stream)
167
- */
168
- completeResponse(pendingRequestId) {
169
- const activeResponse = this.activeResponses.get(pendingRequestId);
170
- if (!activeResponse) {
171
- throw new Error(`Active response ${pendingRequestId} not found`);
172
- }
173
- try {
174
- activeResponse.stream.close();
175
- }
176
- catch (e) {
177
- // Stream might already be closed
178
- }
179
- finally {
180
- this.activeResponses.delete(pendingRequestId);
181
- }
182
- }
183
- /**
184
- * Set the automatic response configuration.
185
- * When set, this will be used to automatically reply to all pending requests.
186
- */
187
- setAutomaticResponse(config) {
188
- this.automaticResponse = config;
189
- }
190
- /**
191
- * Automatically reply to all pending requests using the automatic response configuration.
192
- * Returns the number of requests that were replied to.
193
- */
194
- replyToAllPendingRequests() {
195
- if (!this.automaticResponse) {
196
- throw new Error('Automatic response not set. Call setAutomaticResponse first.');
197
- }
198
- const pendingRequestIds = Array.from(this.pendingRequests.keys());
199
- let count = 0;
200
- for (const requestId of pendingRequestIds) {
201
- try {
202
- // Create response with automatic config
203
- this.createResponse(requestId, this.automaticResponse.status, this.automaticResponse.headers);
204
- // Push body lines if provided
205
- if (this.automaticResponse.bodyLines) {
206
- for (const line of this.automaticResponse.bodyLines) {
207
- const lineStr = `${JSON.stringify(line)}\n`;
208
- const encoder = new TextEncoder();
209
- this.pushBodyData(requestId, encoder.encode(lineStr));
210
- }
211
- }
212
- // Complete the response
213
- this.completeResponse(requestId);
214
- count++;
215
- }
216
- catch (e) {
217
- // Skip requests that fail (might already be handled)
218
- continue;
219
- }
220
- }
221
- return count;
222
- }
223
- }
224
- /**
225
- * Set up message handler for the mock service on a MessagePort
226
- */
227
- export function setupMockServiceMessageHandler(port) {
228
- port.addEventListener('message', (event) => {
229
- const message = event.data;
230
- if (!message || typeof message !== 'object' || !('type' in message)) {
231
- return;
232
- }
233
- const service = MockSyncService.GLOBAL_INSTANCE;
234
- try {
235
- switch (message.type) {
236
- case 'getPendingRequests': {
237
- try {
238
- const requests = service.getPendingRequestsSync();
239
- port.postMessage({
240
- type: 'getPendingRequests',
241
- requestId: message.requestId,
242
- requests
243
- });
244
- }
245
- catch (error) {
246
- port.postMessage({
247
- type: 'error',
248
- requestId: message.requestId,
249
- error: error instanceof Error ? error.message : String(error)
250
- });
251
- }
252
- break;
253
- }
254
- case 'createResponse': {
255
- try {
256
- service.createResponse(message.pendingRequestId, message.status, message.headers);
257
- port.postMessage({
258
- type: 'createResponse',
259
- requestId: message.requestId,
260
- success: true
261
- });
262
- }
263
- catch (error) {
264
- port.postMessage({
265
- type: 'error',
266
- requestId: message.requestId,
267
- error: error instanceof Error ? error.message : String(error)
268
- });
269
- }
270
- break;
271
- }
272
- case 'pushBodyData': {
273
- try {
274
- service.pushBodyData(message.pendingRequestId, message.data);
275
- port.postMessage({
276
- type: 'pushBodyData',
277
- requestId: message.requestId,
278
- success: true
279
- });
280
- }
281
- catch (error) {
282
- port.postMessage({
283
- type: 'error',
284
- requestId: message.requestId,
285
- error: error instanceof Error ? error.message : String(error)
286
- });
287
- }
288
- break;
289
- }
290
- case 'completeResponse': {
291
- try {
292
- service.completeResponse(message.pendingRequestId);
293
- port.postMessage({
294
- type: 'completeResponse',
295
- requestId: message.requestId,
296
- success: true
297
- });
298
- }
299
- catch (error) {
300
- port.postMessage({
301
- type: 'error',
302
- requestId: message.requestId,
303
- error: error instanceof Error ? error.message : String(error)
304
- });
305
- }
306
- break;
307
- }
308
- case 'setAutomaticResponse': {
309
- try {
310
- service.setAutomaticResponse(message.config);
311
- port.postMessage({
312
- type: 'setAutomaticResponse',
313
- requestId: message.requestId,
314
- success: true
315
- });
316
- }
317
- catch (error) {
318
- port.postMessage({
319
- type: 'error',
320
- requestId: message.requestId,
321
- error: error instanceof Error ? error.message : String(error)
322
- });
323
- }
324
- break;
325
- }
326
- case 'replyToAllPendingRequests': {
327
- try {
328
- const count = service.replyToAllPendingRequests();
329
- port.postMessage({
330
- type: 'replyToAllPendingRequests',
331
- requestId: message.requestId,
332
- success: true,
333
- count
334
- });
335
- }
336
- catch (error) {
337
- port.postMessage({
338
- type: 'error',
339
- requestId: message.requestId,
340
- error: error instanceof Error ? error.message : String(error)
341
- });
342
- }
343
- break;
344
- }
345
- default: {
346
- const requestId = 'requestId' in message && typeof message === 'object' && message !== null
347
- ? message.requestId
348
- : undefined;
349
- port.postMessage({
350
- type: 'error',
351
- requestId,
352
- error: `Unknown message type: ${message.type}`
353
- });
354
- break;
355
- }
356
- }
357
- }
358
- catch (error) {
359
- // Fallback for any unexpected errors
360
- const requestId = 'requestId' in message ? message.requestId : undefined;
361
- port.postMessage({
362
- type: 'error',
363
- requestId,
364
- error: error instanceof Error ? error.message : String(error)
365
- });
366
- }
367
- });
368
- port.start();
369
- }
@@ -1,3 +0,0 @@
1
- // Re-export types and worker-side implementation
2
- export * from './MockSyncServiceTypes';
3
- export * from './MockSyncServiceWorker';
@@ -1,71 +0,0 @@
1
- /**
2
- * Representation of a pending request
3
- */
4
- export interface PendingRequest {
5
- id: string;
6
- url: string;
7
- method: string;
8
- headers: Record<string, string>;
9
- body: any;
10
- }
11
-
12
- /**
13
- * Automatic response configuration
14
- */
15
- export interface AutomaticResponseConfig {
16
- status: number;
17
- headers: Record<string, string>;
18
- bodyLines?: any[];
19
- }
20
-
21
- /**
22
- * Message types for communication via MessagePort
23
- */
24
- export type MockSyncServiceMessage =
25
- | { type: 'getPendingRequests'; requestId: string }
26
- | {
27
- type: 'createResponse';
28
- requestId: string;
29
- pendingRequestId: string;
30
- status: number;
31
- headers: Record<string, string>;
32
- }
33
- | { type: 'pushBodyData'; requestId: string; pendingRequestId: string; data: string | ArrayBuffer | Uint8Array }
34
- | { type: 'completeResponse'; requestId: string; pendingRequestId: string }
35
- | { type: 'setAutomaticResponse'; requestId: string; config: AutomaticResponseConfig | null }
36
- | { type: 'replyToAllPendingRequests'; requestId: string };
37
-
38
- export type MockSyncServiceResponse =
39
- | { type: 'getPendingRequests'; requestId: string; requests: PendingRequest[] }
40
- | { type: 'createResponse'; requestId: string; success: boolean }
41
- | { type: 'pushBodyData'; requestId: string; success: boolean }
42
- | { type: 'completeResponse'; requestId: string; success: boolean }
43
- | { type: 'setAutomaticResponse'; requestId: string; success: boolean }
44
- | { type: 'replyToAllPendingRequests'; requestId: string; success: boolean; count: number }
45
- | { type: 'error'; requestId?: string; error: string };
46
-
47
- /**
48
- * Internal representation of a pending request with response promise
49
- */
50
- export interface PendingRequestInternal {
51
- id: string;
52
- url: string;
53
- method: string;
54
- headers: Record<string, string>;
55
- body: any;
56
- responsePromise: {
57
- resolve: (response: Response) => void;
58
- reject: (error: Error) => void;
59
- };
60
- streamController?: ReadableStreamDefaultController<Uint8Array>;
61
- }
62
-
63
- /**
64
- * Internal representation of an active response
65
- */
66
- export interface ActiveResponse {
67
- id: string;
68
- status: number;
69
- headers: Record<string, string>;
70
- stream: ReadableStreamDefaultController<Uint8Array>;
71
- }