@@ -11,34 +11,7 @@ import {
1111 SocketSyncStreamOptions
1212} from '@powersync/common' ;
1313import { serialize , type BSON } from 'bson' ;
14- import { getMockSyncService , setupMockServiceMessageHandler } from '../utils/MockSyncService' ;
15-
16- /**
17- * Check if we're running in a shared worker context
18- */
19- function isSharedWorkerContext ( ) : boolean {
20- const isSharedWorker =
21- typeof SharedWorkerGlobalScope !== 'undefined' &&
22- typeof self !== 'undefined' &&
23- ( self as any ) . constructor ?. name === 'SharedWorkerGlobalScope' ;
24- return isSharedWorker ;
25- }
26-
27- /**
28- * Mock fetch provider that returns 401 for non-stream requests
29- */
30- class MockFetchProvider extends FetchImplementationProvider {
31- getFetch ( ) : FetchImplementation {
32- // Return a mock fetch that always returns 401
33- return async ( input : RequestInfo | URL , init ?: RequestInit ) : Promise < Response > => {
34- const response = new Response ( null , {
35- status : 401 ,
36- statusText : 'Unauthorized'
37- } ) ;
38- return response ;
39- } ;
40- }
41- }
14+ import { MockSyncService , setupMockServiceMessageHandler } from '../../src/worker/sync/MockSyncServiceWorker' ;
4215
4316/**
4417 * Mock fetch provider that intercepts all requests and routes them to the mock sync service.
@@ -53,96 +26,61 @@ class MockSyncServiceFetchProvider extends FetchImplementationProvider {
5326 getFetch ( ) : FetchImplementation {
5427 return async ( input : RequestInfo | URL , init ?: RequestInit ) : Promise < Response > => {
5528 const request = new Request ( input , init ) ;
56- const mockService = getMockSyncService ( ) ;
5729
58- if ( mockService ) {
59- // Read the request body (if any)
60- let body : any = null ;
61- try {
62- if ( request . body ) {
63- const clonedRequest = request . clone ( ) ;
64- body = await clonedRequest . json ( ) . catch ( ( ) => {
65- // If JSON parsing fails, try text
66- return clonedRequest . text ( ) . catch ( ( ) => null ) ;
67- } ) ;
68- }
69- } catch ( e ) {
70- // Body might not be readable, that's okay
30+ const mockService = MockSyncService . GLOBAL_INSTANCE ;
31+
32+ // Read the request body (if any)
33+ let body : any = null ;
34+ try {
35+ if ( request . body ) {
36+ const clonedRequest = request . clone ( ) ;
37+ body = await clonedRequest . json ( ) . catch ( ( ) => {
38+ // If JSON parsing fails, try text
39+ return clonedRequest . text ( ) . catch ( ( ) => null ) ;
40+ } ) ;
7141 }
72-
73- // Extract headers from the request
74- const headers : Record < string , string > = { } ;
75- request . headers . forEach ( ( value , key ) => {
76- headers [ key ] = value ;
77- } ) ;
78-
79- // Register as a pending request and wait for client to create response
80- return await mockService . registerPendingRequest ( request . url , request . method , headers , body , request . signal ) ;
42+ } catch ( e ) {
43+ // Body might not be readable, that's okay
8144 }
8245
83- // Fallback if mock service is not available
84- return new Response ( null , {
85- status : 401 ,
86- statusText : 'Unauthorized'
46+ // Extract headers from the request
47+ const headers : Record < string , string > = { } ;
48+ request . headers . forEach ( ( value , key ) => {
49+ headers [ key ] = value ;
8750 } ) ;
51+
52+ // Register as a pending request and wait for client to create response
53+ return await mockService . registerPendingRequest ( request . url , request . method , headers , body , request . signal ) ;
8854 } ;
8955 }
9056}
9157
92- // Track if we've already set up the onconnect handler
93- let onconnectHandlerSetup = false ;
94-
9558/**
96- * Create the mock sync service globally upfront when in shared worker context.
97- * This ensures the service is available before any requests come in.
59+ * Check if we're running in a shared worker context
9860 */
99- function initializeMockSyncService ( ) {
100- if ( ! isSharedWorkerContext ( ) ) {
101- return ;
102- }
103-
104- // Create the mock service upfront (getMockSyncService creates it if it doesn't exist)
105- getMockSyncService ( ) ;
61+ function isSharedWorkerContext ( ) : boolean {
62+ const isSharedWorker =
63+ typeof SharedWorkerGlobalScope !== 'undefined' &&
64+ typeof self !== 'undefined' &&
65+ ( self as any ) . constructor ?. name === 'SharedWorkerGlobalScope' ;
66+ return isSharedWorker ;
10667}
10768
108- /**
109- * Set up the onconnect listener lazily when the first WebRemote is created.
110- * This ensures deterministic initialization order regardless of import order.
111- * The mock service is created upfront, but message handlers are only set up on connect.
112- */
113- function setupOnconnectHandlerIfNeeded ( ) {
114- if ( onconnectHandlerSetup || ! isSharedWorkerContext ( ) ) {
115- return ;
116- }
117-
118- // Create the mock sync service globally upfront
119- initializeMockSyncService ( ) ;
120-
69+ if ( isSharedWorkerContext ( ) ) {
12170 const _self : SharedWorkerGlobalScope = self as any ;
71+ console . log ( 'MockWebRemote: setting up connect listener' ) ;
12272
123- // Store the original onconnect if it exists (may be set by SharedSyncImplementation.worker.ts)
124- const originalOnConnect = _self . onconnect ;
125-
126- _self . onconnect = async function ( event : MessageEvent ) {
73+ /**
74+ * This listener should be called in tandem with the shared sync worker's listener.
75+ */
76+ _self . addEventListener ( 'connect' , async function ( event : MessageEvent ) {
77+ console . log ( 'MockWebRemote: connect listener called' ) ;
12778 const port = event . ports [ 0 ] ;
12879
129- // Get the mock service (already created upfront) and set up message handler lazily
130- const mockService = getMockSyncService ( ) ;
131- if ( mockService ) {
132- // Set up message handler for the mock service on this port
133- // Tests can create a separate SharedWorker connection to access this
134- setupMockServiceMessageHandler ( port ) ;
135- }
136-
137- // Call the original handler if it exists (this will set up WorkerClient)
138- // Note: The mock service message handler and WorkerClient can coexist
139- // since they use different message types
140- if ( originalOnConnect ) {
141- await originalOnConnect . call ( this , event ) ;
142- }
143- } ;
144-
145- onconnectHandlerSetup = true ;
80+ // Set up message handler for the mock service on this port
81+ // Tests can create a separate SharedWorker connection to access this
82+ setupMockServiceMessageHandler ( port ) ;
83+ } ) ;
14684}
14785
14886export class WebRemote extends AbstractRemote {
@@ -153,12 +91,8 @@ export class WebRemote extends AbstractRemote {
15391 protected logger : ILogger = DEFAULT_REMOTE_LOGGER ,
15492 options ?: Partial < AbstractRemoteOptions >
15593 ) {
156- // Lazy initialize the onconnect handler when the first WebRemote is created
157- // This ensures deterministic initialization order regardless of import order
158- setupOnconnectHandlerIfNeeded ( ) ;
159-
16094 // Use mock service fetch provider if we're in a shared worker context
161- const fetchProvider = isSharedWorkerContext ( ) ? new MockSyncServiceFetchProvider ( ) : new MockFetchProvider ( ) ;
95+ const fetchProvider = new MockSyncServiceFetchProvider ( ) ;
16296
16397 super ( connector , logger , {
16498 ...( options ?? { } ) ,
0 commit comments