@powersync/web 0.5.1

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 (58) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +55 -0
  3. package/lib/src/db/PowerSyncDatabase.d.ts +43 -0
  4. package/lib/src/db/PowerSyncDatabase.js +92 -0
  5. package/lib/src/db/PowerSyncDatabase.js.map +1 -0
  6. package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.d.ts +23 -0
  7. package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.js +57 -0
  8. package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.js.map +1 -0
  9. package/lib/src/db/adapters/SSRDBAdapter.d.ts +29 -0
  10. package/lib/src/db/adapters/SSRDBAdapter.js +86 -0
  11. package/lib/src/db/adapters/SSRDBAdapter.js.map +1 -0
  12. package/lib/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.d.ts +56 -0
  13. package/lib/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.js +197 -0
  14. package/lib/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.js.map +1 -0
  15. package/lib/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.d.ts +6 -0
  16. package/lib/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.js +12 -0
  17. package/lib/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.js.map +1 -0
  18. package/lib/src/db/sync/SSRWebStreamingSyncImplementation.d.ts +8 -0
  19. package/lib/src/db/sync/SSRWebStreamingSyncImplementation.js +14 -0
  20. package/lib/src/db/sync/SSRWebStreamingSyncImplementation.js.map +1 -0
  21. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.d.ts +47 -0
  22. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js +188 -0
  23. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js.map +1 -0
  24. package/lib/src/db/sync/WebRemote.d.ts +6 -0
  25. package/lib/src/db/sync/WebRemote.js +134 -0
  26. package/lib/src/db/sync/WebRemote.js.map +1 -0
  27. package/lib/src/db/sync/WebStreamingSyncImplementation.d.ts +11 -0
  28. package/lib/src/db/sync/WebStreamingSyncImplementation.js +16 -0
  29. package/lib/src/db/sync/WebStreamingSyncImplementation.js.map +1 -0
  30. package/lib/src/index.d.ts +8 -0
  31. package/lib/src/index.js +9 -0
  32. package/lib/src/index.js.map +1 -0
  33. package/lib/src/worker/db/SharedWASQLiteDB.worker.d.ts +1 -0
  34. package/lib/src/worker/db/SharedWASQLiteDB.worker.js +58 -0
  35. package/lib/src/worker/db/SharedWASQLiteDB.worker.js.map +1 -0
  36. package/lib/src/worker/db/WASQLiteDB.worker.d.ts +1 -0
  37. package/lib/src/worker/db/WASQLiteDB.worker.js +13 -0
  38. package/lib/src/worker/db/WASQLiteDB.worker.js.map +1 -0
  39. package/lib/src/worker/db/open-db.d.ts +20 -0
  40. package/lib/src/worker/db/open-db.js +193 -0
  41. package/lib/src/worker/db/open-db.js.map +1 -0
  42. package/lib/src/worker/db/open-worker-database.d.ts +11 -0
  43. package/lib/src/worker/db/open-worker-database.js +31 -0
  44. package/lib/src/worker/db/open-worker-database.js.map +1 -0
  45. package/lib/src/worker/sync/AbstractSharedSyncClientProvider.d.ts +17 -0
  46. package/lib/src/worker/sync/AbstractSharedSyncClientProvider.js +6 -0
  47. package/lib/src/worker/sync/AbstractSharedSyncClientProvider.js.map +1 -0
  48. package/lib/src/worker/sync/BroadcastLogger.d.ts +37 -0
  49. package/lib/src/worker/sync/BroadcastLogger.js +108 -0
  50. package/lib/src/worker/sync/BroadcastLogger.js.map +1 -0
  51. package/lib/src/worker/sync/SharedSyncImplementation.d.ts +88 -0
  52. package/lib/src/worker/sync/SharedSyncImplementation.js +248 -0
  53. package/lib/src/worker/sync/SharedSyncImplementation.js.map +1 -0
  54. package/lib/src/worker/sync/SharedSyncImplementation.worker.d.ts +1 -0
  55. package/lib/src/worker/sync/SharedSyncImplementation.worker.js +23 -0
  56. package/lib/src/worker/sync/SharedSyncImplementation.worker.js.map +1 -0
  57. package/lib/tsconfig.tsbuildinfo +1 -0
  58. package/package.json +58 -0
@@ -0,0 +1,108 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import Logger from 'js-logger';
11
+ /**
12
+ * Broadcasts logs to all clients
13
+ */
14
+ export class BroadcastLogger {
15
+ constructor(clients) {
16
+ this.clients = clients;
17
+ this.TRACE = Logger.TRACE;
18
+ this.DEBUG = Logger.DEBUG;
19
+ this.INFO = Logger.INFO;
20
+ this.TIME = Logger.TIME;
21
+ this.WARN = Logger.WARN;
22
+ this.ERROR = Logger.ERROR;
23
+ this.OFF = Logger.OFF;
24
+ }
25
+ trace(...x) {
26
+ console.trace(...x);
27
+ const sanitized = this.sanitizeArgs(x);
28
+ this.iterateClients((client) => client.clientProvider.trace(...sanitized));
29
+ }
30
+ debug(...x) {
31
+ console.debug(...x);
32
+ const sanitized = this.sanitizeArgs(x);
33
+ this.iterateClients((client) => client.clientProvider.debug(...sanitized));
34
+ }
35
+ info(...x) {
36
+ console.info(...x);
37
+ const sanitized = this.sanitizeArgs(x);
38
+ this.iterateClients((client) => client.clientProvider.info(...sanitized));
39
+ }
40
+ log(...x) {
41
+ console.log(...x);
42
+ const sanitized = this.sanitizeArgs(x);
43
+ this.iterateClients((client) => client.clientProvider.log(...sanitized));
44
+ }
45
+ warn(...x) {
46
+ console.warn(...x);
47
+ const sanitized = this.sanitizeArgs(x);
48
+ this.iterateClients((client) => client.clientProvider.warn(...sanitized));
49
+ }
50
+ error(...x) {
51
+ console.error(...x);
52
+ const sanitized = this.sanitizeArgs(x);
53
+ this.iterateClients((client) => client.clientProvider.error(...sanitized));
54
+ }
55
+ time(label) {
56
+ console.time(label);
57
+ this.iterateClients((client) => client.clientProvider.time(label));
58
+ }
59
+ timeEnd(label) {
60
+ console.timeEnd(label);
61
+ this.iterateClients((client) => client.clientProvider.timeEnd(label));
62
+ }
63
+ setLevel(level) {
64
+ // Levels are not adjustable on this level.
65
+ }
66
+ getLevel() {
67
+ // Levels are not adjustable on this level.
68
+ return Logger.INFO;
69
+ }
70
+ enabledFor(level) {
71
+ // Levels are not adjustable on this level.
72
+ return true;
73
+ }
74
+ /**
75
+ * Iterates all clients, catches individual client exceptions
76
+ * and proceeds to execute for all clients.
77
+ */
78
+ iterateClients(callback) {
79
+ return __awaiter(this, void 0, void 0, function* () {
80
+ for (let client of this.clients) {
81
+ try {
82
+ yield callback(client);
83
+ }
84
+ catch (ex) {
85
+ console.error('Caught exception when iterating client', ex);
86
+ }
87
+ }
88
+ });
89
+ }
90
+ /**
91
+ * Guards against any logging errors.
92
+ * We don't want a logging exception to cause further issues upstream
93
+ */
94
+ sanitizeArgs(x) {
95
+ const sanitizedParams = x.map((param) => {
96
+ try {
97
+ // Try and clone here first. If it fails it won't be passable over a MessagePort
98
+ return structuredClone(param);
99
+ }
100
+ catch (ex) {
101
+ console.error(ex);
102
+ return 'Could not serialize log params. Check shared worker logs for more details.';
103
+ }
104
+ });
105
+ return sanitizedParams;
106
+ }
107
+ }
108
+ //# sourceMappingURL=BroadcastLogger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BroadcastLogger.js","sourceRoot":"","sources":["../../../../src/worker/sync/BroadcastLogger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ import * as Comlink from 'comlink';
2
+ import { ILogger } from 'js-logger';
3
+ import { AbstractStreamingSyncImplementation, StreamingSyncImplementation, BaseObserver, LockOptions, StreamingSyncImplementationListener, SyncStatus, SyncStatusOptions } from '@powersync/common';
4
+ import { WebStreamingSyncImplementationOptions } from '../../db/sync/WebStreamingSyncImplementation';
5
+ import { AbstractSharedSyncClientProvider } from './AbstractSharedSyncClientProvider';
6
+ /**
7
+ * Manual message events for shared sync clients
8
+ */
9
+ export declare enum SharedSyncClientEvent {
10
+ /**
11
+ * This client requests the shared sync manager should
12
+ * close it's connection to the client.
13
+ */
14
+ CLOSE_CLIENT = "close-client"
15
+ }
16
+ export type ManualSharedSyncPayload = {
17
+ event: SharedSyncClientEvent;
18
+ data: any;
19
+ };
20
+ export type SharedSyncInitOptions = {
21
+ dbName: string;
22
+ streamOptions: Omit<WebStreamingSyncImplementationOptions, 'adapter' | 'uploadCrud' | 'remote'>;
23
+ };
24
+ export interface SharedSyncImplementationListener extends StreamingSyncImplementationListener {
25
+ initialized: () => void;
26
+ }
27
+ export type WrappedSyncPort = {
28
+ port: MessagePort;
29
+ clientProvider: Comlink.Remote<AbstractSharedSyncClientProvider>;
30
+ };
31
+ export type RemoteOperationAbortController = {
32
+ controller: AbortController;
33
+ activePort: WrappedSyncPort;
34
+ };
35
+ /**
36
+ * Shared sync implementation which runs inside a shared webworker
37
+ */
38
+ export declare class SharedSyncImplementation extends BaseObserver<SharedSyncImplementationListener> implements StreamingSyncImplementation {
39
+ protected ports: WrappedSyncPort[];
40
+ protected syncStreamClient?: AbstractStreamingSyncImplementation;
41
+ protected isInitialized: Promise<void>;
42
+ protected statusListener?: () => void;
43
+ protected fetchCredentialsController?: RemoteOperationAbortController;
44
+ protected uploadDataController?: RemoteOperationAbortController;
45
+ syncStatus: SyncStatus;
46
+ broadCastLogger: ILogger;
47
+ constructor();
48
+ waitForStatus(status: SyncStatusOptions): Promise<void>;
49
+ get lastSyncedAt(): Date | undefined;
50
+ get isConnected(): boolean;
51
+ waitForReady(): Promise<void>;
52
+ /**
53
+ * Configures the DBAdapter connection and a streaming sync client.
54
+ */
55
+ init(dbWorkerPort: MessagePort, params: SharedSyncInitOptions): Promise<void>;
56
+ dispose(): Promise<void | undefined>;
57
+ /**
58
+ * Connects to the PowerSync backend instance.
59
+ * Multiple tabs can safely call this in their initialization.
60
+ * The connection will simply be reconnected whenever a new tab
61
+ * connects.
62
+ */
63
+ connect(): Promise<any>;
64
+ disconnect(): Promise<any>;
65
+ /**
66
+ * Adds a new client tab's message port to the list of connected ports
67
+ */
68
+ addPort(port: MessagePort): void;
69
+ /**
70
+ * Removes a message port client from this manager's managed
71
+ * clients.
72
+ */
73
+ removePort(port: MessagePort): void;
74
+ triggerCrudUpload(): void;
75
+ obtainLock<T>(lockOptions: LockOptions<T>): Promise<T>;
76
+ hasCompletedSync(): Promise<boolean>;
77
+ getWriteCheckpoint(): Promise<string>;
78
+ /**
79
+ * A method to update the all shared statuses for each
80
+ * client.
81
+ */
82
+ private updateAllStatuses;
83
+ /**
84
+ * A function only used for unit tests which updates the internal
85
+ * sync stream client and all tab client's sync status
86
+ */
87
+ private _testUpdateAllStatuses;
88
+ }
@@ -0,0 +1,248 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import * as Comlink from 'comlink';
11
+ import Logger from 'js-logger';
12
+ import { BaseObserver, SqliteBucketStorage, SyncStatus, AbortOperation } from '@powersync/common';
13
+ import { WebStreamingSyncImplementation } from '../../db/sync/WebStreamingSyncImplementation';
14
+ import { Mutex } from 'async-mutex';
15
+ import { WebRemote } from '../../db/sync/WebRemote';
16
+ import { WASQLiteDBAdapter } from '../../db/adapters/wa-sqlite/WASQLiteDBAdapter';
17
+ import { BroadcastLogger } from './BroadcastLogger';
18
+ /**
19
+ * Manual message events for shared sync clients
20
+ */
21
+ export var SharedSyncClientEvent;
22
+ (function (SharedSyncClientEvent) {
23
+ /**
24
+ * This client requests the shared sync manager should
25
+ * close it's connection to the client.
26
+ */
27
+ SharedSyncClientEvent["CLOSE_CLIENT"] = "close-client";
28
+ })(SharedSyncClientEvent || (SharedSyncClientEvent = {}));
29
+ /**
30
+ * Shared sync implementation which runs inside a shared webworker
31
+ */
32
+ export class SharedSyncImplementation extends BaseObserver {
33
+ constructor() {
34
+ super();
35
+ this.ports = [];
36
+ this.isInitialized = new Promise((resolve) => {
37
+ const callback = this.registerListener({
38
+ initialized: () => {
39
+ resolve();
40
+ callback === null || callback === void 0 ? void 0 : callback();
41
+ }
42
+ });
43
+ });
44
+ this.syncStatus = new SyncStatus({});
45
+ this.broadCastLogger = new BroadcastLogger(this.ports);
46
+ }
47
+ waitForStatus(status) {
48
+ return __awaiter(this, void 0, void 0, function* () {
49
+ yield this.waitForReady();
50
+ return this.syncStreamClient.waitForStatus(status);
51
+ });
52
+ }
53
+ get lastSyncedAt() {
54
+ var _a;
55
+ return (_a = this.syncStreamClient) === null || _a === void 0 ? void 0 : _a.lastSyncedAt;
56
+ }
57
+ get isConnected() {
58
+ var _a, _b;
59
+ return (_b = (_a = this.syncStreamClient) === null || _a === void 0 ? void 0 : _a.isConnected) !== null && _b !== void 0 ? _b : false;
60
+ }
61
+ waitForReady() {
62
+ return __awaiter(this, void 0, void 0, function* () {
63
+ return this.isInitialized;
64
+ });
65
+ }
66
+ /**
67
+ * Configures the DBAdapter connection and a streaming sync client.
68
+ */
69
+ init(dbWorkerPort, params) {
70
+ return __awaiter(this, void 0, void 0, function* () {
71
+ var _a, _b;
72
+ if (this.syncStreamClient) {
73
+ // Cannot modify already existing sync implementation
74
+ return;
75
+ }
76
+ const logger = ((_b = (_a = params.streamOptions) === null || _a === void 0 ? void 0 : _a.flags) === null || _b === void 0 ? void 0 : _b.broadcastLogs) ? this.broadCastLogger : Logger.get('shared-sync');
77
+ self.onerror = (event) => {
78
+ // Share any uncaught events on the broadcast logger
79
+ logger.error('Uncaught exception in PowerSync shared sync worker', event);
80
+ };
81
+ this.syncStreamClient = new WebStreamingSyncImplementation(Object.assign(Object.assign({ adapter: new SqliteBucketStorage(new WASQLiteDBAdapter({
82
+ dbFilename: params.dbName,
83
+ workerPort: dbWorkerPort,
84
+ flags: { enableMultiTabs: true },
85
+ logger
86
+ }), new Mutex(), logger), remote: new WebRemote({
87
+ fetchCredentials: () => __awaiter(this, void 0, void 0, function* () {
88
+ const lastPort = this.ports[this.ports.length - 1];
89
+ return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
90
+ const abortController = new AbortController();
91
+ this.fetchCredentialsController = {
92
+ controller: abortController,
93
+ activePort: lastPort
94
+ };
95
+ abortController.signal.onabort = reject;
96
+ try {
97
+ resolve(yield lastPort.clientProvider.fetchCredentials());
98
+ }
99
+ catch (ex) {
100
+ reject(ex);
101
+ }
102
+ finally {
103
+ this.fetchCredentialsController = undefined;
104
+ }
105
+ }));
106
+ })
107
+ }), uploadCrud: () => __awaiter(this, void 0, void 0, function* () {
108
+ const lastPort = this.ports[this.ports.length - 1];
109
+ return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
110
+ const abortController = new AbortController();
111
+ this.uploadDataController = {
112
+ controller: abortController,
113
+ activePort: lastPort
114
+ };
115
+ // Resolving will make it retry
116
+ abortController.signal.onabort = () => resolve();
117
+ try {
118
+ resolve(yield lastPort.clientProvider.uploadCrud());
119
+ }
120
+ catch (ex) {
121
+ reject(ex);
122
+ }
123
+ finally {
124
+ this.uploadDataController = undefined;
125
+ }
126
+ }));
127
+ }) }, params.streamOptions), {
128
+ // Logger cannot be transferred just yet
129
+ logger }));
130
+ this.syncStreamClient.registerListener({
131
+ statusChanged: (status) => {
132
+ this.updateAllStatuses(status.toJSON());
133
+ }
134
+ });
135
+ this.iterateListeners((l) => { var _a; return (_a = l.initialized) === null || _a === void 0 ? void 0 : _a.call(l); });
136
+ });
137
+ }
138
+ dispose() {
139
+ return __awaiter(this, void 0, void 0, function* () {
140
+ var _a, _b;
141
+ yield this.waitForReady();
142
+ (_a = this.statusListener) === null || _a === void 0 ? void 0 : _a.call(this);
143
+ return (_b = this.syncStreamClient) === null || _b === void 0 ? void 0 : _b.dispose();
144
+ });
145
+ }
146
+ /**
147
+ * Connects to the PowerSync backend instance.
148
+ * Multiple tabs can safely call this in their initialization.
149
+ * The connection will simply be reconnected whenever a new tab
150
+ * connects.
151
+ */
152
+ connect() {
153
+ return __awaiter(this, void 0, void 0, function* () {
154
+ yield this.waitForReady();
155
+ // This effectively queues connect and disconnect calls. Ensuring multiple tabs' requests are synchronized
156
+ return navigator.locks.request('shared-sync-connect', () => { var _a; return (_a = this.syncStreamClient) === null || _a === void 0 ? void 0 : _a.connect(); });
157
+ });
158
+ }
159
+ disconnect() {
160
+ return __awaiter(this, void 0, void 0, function* () {
161
+ yield this.waitForReady();
162
+ // This effectively queues connect and disconnect calls. Ensuring multiple tabs' requests are synchronized
163
+ return navigator.locks.request('shared-sync-connect', () => { var _a; return (_a = this.syncStreamClient) === null || _a === void 0 ? void 0 : _a.disconnect(); });
164
+ });
165
+ }
166
+ /**
167
+ * Adds a new client tab's message port to the list of connected ports
168
+ */
169
+ addPort(port) {
170
+ var _a;
171
+ const portProvider = {
172
+ port,
173
+ clientProvider: Comlink.wrap(port)
174
+ };
175
+ this.ports.push(portProvider);
176
+ // Give the newly connected client the latest status
177
+ const status = (_a = this.syncStreamClient) === null || _a === void 0 ? void 0 : _a.syncStatus;
178
+ if (status) {
179
+ portProvider.clientProvider.statusChanged(status.toJSON());
180
+ }
181
+ }
182
+ /**
183
+ * Removes a message port client from this manager's managed
184
+ * clients.
185
+ */
186
+ removePort(port) {
187
+ const index = this.ports.findIndex((p) => p.port == port);
188
+ if (index < 0) {
189
+ console.warn(`Could not remove port ${port} since it is not present in active ports.`);
190
+ return;
191
+ }
192
+ const trackedPort = this.ports[index];
193
+ // Release proxy
194
+ trackedPort.clientProvider[Comlink.releaseProxy]();
195
+ this.ports.splice(index, 1);
196
+ /**
197
+ * The port might currently be in use. Any active functions might
198
+ * not resolve. Abort them here.
199
+ */
200
+ [this.fetchCredentialsController, this.uploadDataController].forEach((abortController) => {
201
+ if ((abortController === null || abortController === void 0 ? void 0 : abortController.activePort.port) == port) {
202
+ abortController.controller.abort(new AbortOperation('Closing pending requests after client port is removed'));
203
+ }
204
+ });
205
+ }
206
+ triggerCrudUpload() {
207
+ this.waitForReady().then(() => { var _a; return (_a = this.syncStreamClient) === null || _a === void 0 ? void 0 : _a.triggerCrudUpload(); });
208
+ }
209
+ obtainLock(lockOptions) {
210
+ return __awaiter(this, void 0, void 0, function* () {
211
+ yield this.waitForReady();
212
+ return this.syncStreamClient.obtainLock(lockOptions);
213
+ });
214
+ }
215
+ hasCompletedSync() {
216
+ return __awaiter(this, void 0, void 0, function* () {
217
+ yield this.waitForReady();
218
+ return this.syncStreamClient.hasCompletedSync();
219
+ });
220
+ }
221
+ getWriteCheckpoint() {
222
+ return __awaiter(this, void 0, void 0, function* () {
223
+ yield this.waitForReady();
224
+ return this.syncStreamClient.getWriteCheckpoint();
225
+ });
226
+ }
227
+ /**
228
+ * A method to update the all shared statuses for each
229
+ * client.
230
+ */
231
+ updateAllStatuses(status) {
232
+ this.syncStatus = new SyncStatus(status);
233
+ this.ports.forEach((p) => p.clientProvider.statusChanged(status));
234
+ }
235
+ /**
236
+ * A function only used for unit tests which updates the internal
237
+ * sync stream client and all tab client's sync status
238
+ */
239
+ _testUpdateAllStatuses(status) {
240
+ if (!this.syncStreamClient) {
241
+ console.warn('no stream client has been initialized yet');
242
+ }
243
+ // Only assigning, don't call listeners for this test
244
+ this.syncStreamClient.syncStatus = new SyncStatus(status);
245
+ this.updateAllStatuses(status);
246
+ }
247
+ }
248
+ //# sourceMappingURL=SharedSyncImplementation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SharedSyncImplementation.js","sourceRoot":"","sources":["../../../../src/worker/sync/SharedSyncImplementation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import * as Comlink from 'comlink';
2
+ import { SharedSyncImplementation, SharedSyncClientEvent } from './SharedSyncImplementation';
3
+ import Logger from 'js-logger';
4
+ const _self = self;
5
+ Logger.useDefaults();
6
+ const sharedSyncImplementation = new SharedSyncImplementation();
7
+ _self.onconnect = function (event) {
8
+ const port = event.ports[0];
9
+ /**
10
+ * Adds an extra listener which can remove this port
11
+ * from the list of monitored ports.
12
+ */
13
+ port.addEventListener('message', (event) => {
14
+ const payload = event.data;
15
+ if ((payload === null || payload === void 0 ? void 0 : payload.event) == SharedSyncClientEvent.CLOSE_CLIENT) {
16
+ console.log('closing shared for port', port);
17
+ sharedSyncImplementation.removePort(port);
18
+ }
19
+ });
20
+ Comlink.expose(sharedSyncImplementation, port);
21
+ sharedSyncImplementation.addPort(port);
22
+ };
23
+ //# sourceMappingURL=SharedSyncImplementation.worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SharedSyncImplementation.worker.js","sourceRoot":"","sources":["../../../../src/worker/sync/SharedSyncImplementation.worker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,wBAAwB,EAAE,qBAAqB,EAA2B,MAAM,4BAA4B,CAAC;AACtH,OAAO,MAAM,MAAM,WAAW,CAAC;AAE/B,MAAM,KAAK,GAA4B,IAAW,CAAC;AACnD,MAAM,CAAC,WAAW,EAAE,CAAC;AACrB,MAAM,wBAAwB,GAAG,IAAI,wBAAwB,EAAE,CAAC;AAEhE,KAAK,CAAC,SAAS,GAAG,UAAU,KAA2B;IACrD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAE5B;;;OAGG;IACH,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;QACzC,MAAM,OAAO,GAAG,KAAK,CAAC,IAA+B,CAAC;QACtD,IAAI,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,KAAK,KAAI,qBAAqB,CAAC,YAAY,EAAE,CAAC;YACzD,OAAO,CAAC,GAAG,CAAC,yBAAyB,EAAE,IAAI,CAAC,CAAC;YAC7C,wBAAwB,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,MAAM,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC;IAC/C,wBAAwB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC,CAAC"}