@powersync/web 1.31.0 → 1.32.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 (110) hide show
  1. package/dist/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapp-89f0ba.index.umd.js +1867 -0
  2. package/dist/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapp-89f0ba.index.umd.js.map +1 -0
  3. package/dist/_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapps_wa-sqlite_src_example-2530150.index.umd.js +555 -0
  4. package/dist/_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapps_wa-sqlite_src_example-2530150.index.umd.js.map +1 -0
  5. package/dist/_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapps_wa-sqlite_src_example-2530151.index.umd.js +555 -0
  6. package/dist/_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapps_wa-sqlite_src_example-2530151.index.umd.js.map +1 -0
  7. package/dist/index.umd.js +4575 -43416
  8. package/dist/index.umd.js.map +1 -1
  9. package/dist/worker/SharedSyncImplementation.umd.js +402 -2053
  10. package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
  11. package/dist/worker/WASQLiteDB.umd.js +449 -2104
  12. package/dist/worker/WASQLiteDB.umd.js.map +1 -1
  13. package/dist/worker/{node_modules_bson_lib_bson_mjs.umd.js → node_modules_pnpm_bson_6_10_4_node_modules_bson_lib_bson_mjs.umd.js} +6 -6
  14. package/dist/worker/node_modules_pnpm_bson_6_10_4_node_modules_bson_lib_bson_mjs.umd.js.map +1 -0
  15. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-3a94cf.umd.js +44 -0
  16. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-3a94cf.umd.js.map +1 -0
  17. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-868779.umd.js +44 -0
  18. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-868779.umd.js.map +1 -0
  19. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_wa-sqli-f60d0d.umd.js +44 -0
  20. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_wa-sqli-f60d0d.umd.js.map +1 -0
  21. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js +44 -0
  22. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js.map +1 -0
  23. package/dist/worker/{node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js → node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-0d2437.umd.js} +24 -24
  24. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-0d2437.umd.js.map +1 -0
  25. package/dist/worker/{node_modules_journeyapps_wa-sqlite_src_examples_OPFSCoopSyncVFS_js.umd.js → node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-1d4e74.umd.js} +18 -18
  26. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-1d4e74.umd.js.map +1 -0
  27. package/dist/worker/{node_modules_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js.umd.js → node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-3622cf.umd.js} +18 -18
  28. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-3622cf.umd.js.map +1 -0
  29. package/lib/package.json +26 -22
  30. package/lib/src/db/NavigatorTriggerClaimManager.d.ts +6 -0
  31. package/lib/src/db/NavigatorTriggerClaimManager.js +20 -0
  32. package/lib/src/db/PowerSyncDatabase.d.ts +5 -2
  33. package/lib/src/db/PowerSyncDatabase.js +46 -8
  34. package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.d.ts +1 -1
  35. package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.js +1 -1
  36. package/lib/src/db/adapters/AbstractWebSQLOpenFactory.d.ts +2 -2
  37. package/lib/src/db/adapters/AbstractWebSQLOpenFactory.js +2 -2
  38. package/lib/src/db/adapters/AsyncDatabaseConnection.d.ts +1 -1
  39. package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.d.ts +4 -4
  40. package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.js +8 -4
  41. package/lib/src/db/adapters/WebDBAdapter.d.ts +5 -2
  42. package/lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.d.ts +2 -2
  43. package/lib/src/db/adapters/wa-sqlite/InternalWASQLiteDBAdapter.d.ts +12 -0
  44. package/lib/src/db/adapters/wa-sqlite/InternalWASQLiteDBAdapter.js +19 -0
  45. package/lib/src/db/adapters/wa-sqlite/WASQLiteConnection.d.ts +2 -2
  46. package/lib/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.d.ts +4 -4
  47. package/lib/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.js +6 -6
  48. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.d.ts +4 -4
  49. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +7 -7
  50. package/lib/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.d.ts +1 -1
  51. package/lib/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.js +3 -3
  52. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.d.ts +5 -5
  53. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js +5 -5
  54. package/lib/src/db/sync/WebRemote.js +1 -1
  55. package/lib/src/db/sync/WebStreamingSyncImplementation.d.ts +1 -1
  56. package/lib/src/db/sync/WebStreamingSyncImplementation.js +1 -1
  57. package/lib/src/index.d.ts +12 -12
  58. package/lib/src/index.js +12 -12
  59. package/lib/src/worker/db/SharedWASQLiteConnection.d.ts +2 -2
  60. package/lib/src/worker/db/WASQLiteDB.worker.js +3 -3
  61. package/lib/src/worker/db/WorkerWASQLiteConnection.d.ts +2 -2
  62. package/lib/src/worker/db/WorkerWASQLiteConnection.js +1 -1
  63. package/lib/src/worker/db/open-worker-database.d.ts +2 -2
  64. package/lib/src/worker/db/open-worker-database.js +1 -1
  65. package/lib/src/worker/sync/BroadcastLogger.d.ts +1 -1
  66. package/lib/src/worker/sync/SharedSyncImplementation.d.ts +4 -4
  67. package/lib/src/worker/sync/SharedSyncImplementation.js +5 -5
  68. package/lib/src/worker/sync/SharedSyncImplementation.worker.js +2 -2
  69. package/lib/src/worker/sync/WorkerClient.d.ts +1 -1
  70. package/lib/src/worker/sync/WorkerClient.js +2 -2
  71. package/lib/tsconfig.tsbuildinfo +1 -1
  72. package/package.json +21 -17
  73. package/src/db/NavigatorTriggerClaimManager.ts +23 -0
  74. package/src/db/PowerSyncDatabase.ts +53 -9
  75. package/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.ts +1 -1
  76. package/src/db/adapters/AbstractWebSQLOpenFactory.ts +3 -3
  77. package/src/db/adapters/AsyncDatabaseConnection.ts +1 -1
  78. package/src/db/adapters/LockedAsyncDatabaseAdapter.ts +13 -9
  79. package/src/db/adapters/WebDBAdapter.ts +6 -2
  80. package/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.ts +2 -2
  81. package/src/db/adapters/wa-sqlite/InternalWASQLiteDBAdapter.ts +23 -0
  82. package/src/db/adapters/wa-sqlite/WASQLiteConnection.ts +2 -2
  83. package/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.ts +8 -8
  84. package/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.ts +8 -8
  85. package/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.ts +3 -3
  86. package/src/db/sync/SharedWebStreamingSyncImplementation.ts +7 -7
  87. package/src/db/sync/WebRemote.ts +1 -1
  88. package/src/db/sync/WebStreamingSyncImplementation.ts +2 -2
  89. package/src/index.ts +12 -12
  90. package/src/worker/db/SharedWASQLiteConnection.ts +2 -2
  91. package/src/worker/db/WASQLiteDB.worker.ts +5 -5
  92. package/src/worker/db/WorkerWASQLiteConnection.ts +2 -2
  93. package/src/worker/db/open-worker-database.ts +2 -2
  94. package/src/worker/sync/BroadcastLogger.ts +1 -1
  95. package/src/worker/sync/SharedSyncImplementation.ts +9 -9
  96. package/src/worker/sync/SharedSyncImplementation.worker.ts +2 -2
  97. package/src/worker/sync/WorkerClient.ts +2 -2
  98. package/dist/worker/node_modules_bson_lib_bson_mjs.umd.js.map +0 -1
  99. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite-async_mjs.umd.js +0 -44
  100. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite-async_mjs.umd.js.map +0 -1
  101. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite_mjs.umd.js +0 -44
  102. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite_mjs.umd.js.map +0 -1
  103. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js +0 -44
  104. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js.map +0 -1
  105. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js +0 -44
  106. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js.map +0 -1
  107. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js.umd.js.map +0 -1
  108. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js.map +0 -1
  109. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_OPFSCoopSyncVFS_js.umd.js.map +0 -1
  110. /package/bin/{powersync.js → powersync.cjs} +0 -0
@@ -0,0 +1,1867 @@
1
+ (function webpackUniversalModuleDefinition(root, factory) {
2
+ if(typeof exports === 'object' && typeof module === 'object')
3
+ module.exports = factory(require("@powersync/common"), require("async-mutex"), require("comlink"), require("@journeyapps/wa-sqlite"), require("@journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js"), require("@journeyapps/wa-sqlite/src/examples/AccessHandlePoolVFS.js"), require("@journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js"));
4
+ else if(typeof define === 'function' && define.amd)
5
+ define(["@powersync/common", "async-mutex", "comlink", "@journeyapps/wa-sqlite", "@journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js", "@journeyapps/wa-sqlite/src/examples/AccessHandlePoolVFS.js", "@journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js"], factory);
6
+ else if(typeof exports === 'object')
7
+ exports["sdk_web"] = factory(require("@powersync/common"), require("async-mutex"), require("comlink"), require("@journeyapps/wa-sqlite"), require("@journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js"), require("@journeyapps/wa-sqlite/src/examples/AccessHandlePoolVFS.js"), require("@journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js"));
8
+ else
9
+ root["sdk_web"] = factory(root["@powersync/common"], root["async-mutex"], root["comlink"], root["@journeyapps/wa-sqlite"], root["@journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js"], root["@journeyapps/wa-sqlite/src/examples/AccessHandlePoolVFS.js"], root["@journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js"]);
10
+ })(self, (__WEBPACK_EXTERNAL_MODULE__powersync_common__, __WEBPACK_EXTERNAL_MODULE_async_mutex__, __WEBPACK_EXTERNAL_MODULE_comlink__, __WEBPACK_EXTERNAL_MODULE__journeyapps_wa_sqlite__, __WEBPACK_EXTERNAL_MODULE__journeyapps_wa_sqlite_src_examples_OPFSCoopSyncVFS_js__, __WEBPACK_EXTERNAL_MODULE__journeyapps_wa_sqlite_src_examples_AccessHandlePoolVFS_js__, __WEBPACK_EXTERNAL_MODULE__journeyapps_wa_sqlite_src_examples_IDBBatchAtomicVFS_js__) => {
11
+ return /******/ (() => { // webpackBootstrap
12
+ /******/ "use strict";
13
+ /******/ var __webpack_modules__ = ({
14
+
15
+ /***/ "./lib/src/db/adapters/LockedAsyncDatabaseAdapter.js"
16
+ /*!***********************************************************!*\
17
+ !*** ./lib/src/db/adapters/LockedAsyncDatabaseAdapter.js ***!
18
+ \***********************************************************/
19
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
20
+
21
+ __webpack_require__.r(__webpack_exports__);
22
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
23
+ /* harmony export */ LockedAsyncDatabaseAdapter: () => (/* binding */ LockedAsyncDatabaseAdapter)
24
+ /* harmony export */ });
25
+ /* harmony import */ var _powersync_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @powersync/common */ "@powersync/common");
26
+ /* harmony import */ var _shared_navigator_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../shared/navigator.js */ "./lib/src/shared/navigator.js");
27
+ /* harmony import */ var _WorkerWrappedAsyncDatabaseConnection_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./WorkerWrappedAsyncDatabaseConnection.js */ "./lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js");
28
+ /* harmony import */ var _wa_sqlite_WASQLiteConnection_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./wa-sqlite/WASQLiteConnection.js */ "./lib/src/db/adapters/wa-sqlite/WASQLiteConnection.js");
29
+
30
+
31
+
32
+
33
+ /**
34
+ * @internal
35
+ * Wraps a {@link AsyncDatabaseConnection} and provides exclusive locking functions in
36
+ * order to implement {@link DBAdapter}.
37
+ */
38
+ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MODULE_0__.BaseObserver {
39
+ options;
40
+ logger;
41
+ dbGetHelpers;
42
+ debugMode;
43
+ _dbIdentifier;
44
+ initPromise;
45
+ _db = null;
46
+ _disposeTableChangeListener = null;
47
+ _config = null;
48
+ pendingAbortControllers;
49
+ requiresHolds;
50
+ databaseOpenPromise = null;
51
+ closing;
52
+ closed;
53
+ constructor(options) {
54
+ super();
55
+ this.options = options;
56
+ this._dbIdentifier = options.name;
57
+ this.logger = options.logger ?? (0,_powersync_common__WEBPACK_IMPORTED_MODULE_0__.createLogger)(`LockedAsyncDatabaseAdapter - ${this._dbIdentifier}`);
58
+ this.pendingAbortControllers = new Set();
59
+ this.closed = false;
60
+ this.closing = false;
61
+ this.requiresHolds = null;
62
+ // Set the name if provided. We can query for the name if not available yet
63
+ this.debugMode = options.debugMode ?? false;
64
+ if (this.debugMode) {
65
+ const originalExecute = this._execute.bind(this);
66
+ this._execute = async (sql, bindings) => {
67
+ const start = performance.now();
68
+ try {
69
+ const r = await originalExecute(sql, bindings);
70
+ performance.measure(`[SQL] ${sql}`, { start });
71
+ return r;
72
+ }
73
+ catch (e) {
74
+ performance.measure(`[SQL] [ERROR: ${e.message}] ${sql}`, { start });
75
+ throw e;
76
+ }
77
+ };
78
+ }
79
+ this.dbGetHelpers = this.generateDBHelpers({
80
+ execute: (query, params) => this.acquireLock(() => this._execute(query, params)),
81
+ executeRaw: (query, params) => this.acquireLock(() => this._executeRaw(query, params))
82
+ });
83
+ this.initPromise = this._init();
84
+ }
85
+ get baseDB() {
86
+ if (!this._db) {
87
+ throw new Error(`Initialization has not completed yet. Cannot access base db`);
88
+ }
89
+ return this._db;
90
+ }
91
+ get name() {
92
+ return this._dbIdentifier;
93
+ }
94
+ /**
95
+ * Init is automatic, this helps catch errors or explicitly await initialization
96
+ */
97
+ async init() {
98
+ return this.initPromise;
99
+ }
100
+ async openInternalDB() {
101
+ /**
102
+ * Execute opening of the db in a lock in order not to interfere with other operations.
103
+ */
104
+ return this._acquireLock(async () => {
105
+ // Dispose any previous table change listener.
106
+ this._disposeTableChangeListener?.();
107
+ this._disposeTableChangeListener = null;
108
+ this._db?.close().catch((ex) => this.logger.warn(`Error closing database before opening new instance`, ex));
109
+ const isReOpen = !!this._db;
110
+ this._db = null;
111
+ this._db = await this.options.openConnection();
112
+ await this._db.init();
113
+ this._config = await this._db.getConfig();
114
+ await this.registerOnChangeListener(this._db);
115
+ if (isReOpen) {
116
+ this.iterateListeners((cb) => cb.databaseReOpened?.());
117
+ }
118
+ /**
119
+ * This is only required for the long-lived shared IndexedDB connections.
120
+ */
121
+ this.requiresHolds = this._config.vfs == _wa_sqlite_WASQLiteConnection_js__WEBPACK_IMPORTED_MODULE_3__.WASQLiteVFS.IDBBatchAtomicVFS;
122
+ });
123
+ }
124
+ _reOpen() {
125
+ this.databaseOpenPromise = this.openInternalDB().finally(() => {
126
+ this.databaseOpenPromise = null;
127
+ });
128
+ return this.databaseOpenPromise;
129
+ }
130
+ /**
131
+ * Re-opens the underlying database.
132
+ * Returns a pending operation if one is already in progress.
133
+ */
134
+ async reOpenInternalDB() {
135
+ if (!this.options.reOpenOnConnectionClosed) {
136
+ throw new Error(`Cannot re-open underlying database, reOpenOnConnectionClosed is not enabled`);
137
+ }
138
+ if (this.databaseOpenPromise) {
139
+ return this.databaseOpenPromise;
140
+ }
141
+ return this._reOpen();
142
+ }
143
+ async _init() {
144
+ /**
145
+ * For OPFS, we can see this open call sometimes fail due to NoModificationAllowedError.
146
+ * We should be able to recover from this by re-opening the database.
147
+ */
148
+ const maxAttempts = 3;
149
+ for (let count = 0; count < maxAttempts; count++) {
150
+ try {
151
+ await this.openInternalDB();
152
+ break;
153
+ }
154
+ catch (ex) {
155
+ if (count == maxAttempts - 1) {
156
+ throw ex;
157
+ }
158
+ this.logger.warn(`Attempt ${count + 1} of ${maxAttempts} to open database failed, retrying in 1 second...`, ex);
159
+ await new Promise((resolve) => setTimeout(resolve, 1000));
160
+ }
161
+ }
162
+ this.iterateListeners((cb) => cb.initialized?.());
163
+ }
164
+ getConfiguration() {
165
+ if (!this._config) {
166
+ throw new Error(`Cannot get config before initialization is completed`);
167
+ }
168
+ return {
169
+ ...this._config,
170
+ // This can be overridden by the adapter later
171
+ requiresPersistentTriggers: false
172
+ };
173
+ }
174
+ async waitForInitialized() {
175
+ // Awaiting this will expose errors on function calls like .execute etc
176
+ await this.initPromise;
177
+ }
178
+ async shareConnection() {
179
+ if (false == this._db instanceof _WorkerWrappedAsyncDatabaseConnection_js__WEBPACK_IMPORTED_MODULE_2__.WorkerWrappedAsyncDatabaseConnection) {
180
+ throw new Error(`Only worker connections can be shared`);
181
+ }
182
+ return this._db.shareConnection();
183
+ }
184
+ /**
185
+ * Registers a table change notification callback with the base database.
186
+ * This can be extended by custom implementations in order to handle proxy events.
187
+ */
188
+ async registerOnChangeListener(db) {
189
+ this._disposeTableChangeListener = await db.registerOnTableChange((event) => {
190
+ this.iterateListeners((cb) => cb.tablesUpdated?.(event));
191
+ });
192
+ }
193
+ /**
194
+ * This is currently a no-op on web
195
+ */
196
+ async refreshSchema() { }
197
+ async execute(query, params) {
198
+ return this.writeLock((ctx) => ctx.execute(query, params));
199
+ }
200
+ async executeRaw(query, params) {
201
+ return this.writeLock((ctx) => ctx.executeRaw(query, params));
202
+ }
203
+ async executeBatch(query, params) {
204
+ return this.writeLock((ctx) => this._executeBatch(query, params));
205
+ }
206
+ /**
207
+ * Attempts to close the connection.
208
+ * Shared workers might not actually close the connection if other
209
+ * tabs are still using it.
210
+ */
211
+ async close() {
212
+ this.closing = true;
213
+ /**
214
+ * Note that we obtain a reference to the callback to avoid calling the callback with `this` as the context.
215
+ * This is to avoid Comlink attempting to clone `this` when calling the method.
216
+ */
217
+ const dispose = this._disposeTableChangeListener;
218
+ if (dispose) {
219
+ dispose();
220
+ }
221
+ this.pendingAbortControllers.forEach((controller) => controller.abort('Closed'));
222
+ await this.baseDB?.close?.();
223
+ this.closed = true;
224
+ }
225
+ async getAll(sql, parameters) {
226
+ await this.waitForInitialized();
227
+ return this.dbGetHelpers.getAll(sql, parameters);
228
+ }
229
+ async getOptional(sql, parameters) {
230
+ await this.waitForInitialized();
231
+ return this.dbGetHelpers.getOptional(sql, parameters);
232
+ }
233
+ async get(sql, parameters) {
234
+ await this.waitForInitialized();
235
+ return this.dbGetHelpers.get(sql, parameters);
236
+ }
237
+ async readLock(fn, options) {
238
+ await this.waitForInitialized();
239
+ return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute, executeRaw: this._executeRaw })), {
240
+ timeoutMs: options?.timeoutMs ?? this.options.defaultLockTimeoutMs
241
+ });
242
+ }
243
+ async writeLock(fn, options) {
244
+ await this.waitForInitialized();
245
+ return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute, executeRaw: this._executeRaw })), {
246
+ timeoutMs: options?.timeoutMs ?? this.options.defaultLockTimeoutMs
247
+ });
248
+ }
249
+ async _acquireLock(callback, options) {
250
+ if (this.closing) {
251
+ throw new Error(`Cannot acquire lock, the database is closing`);
252
+ }
253
+ const abortController = new AbortController();
254
+ this.pendingAbortControllers.add(abortController);
255
+ const { timeoutMs } = options ?? {};
256
+ const timeoutId = timeoutMs
257
+ ? setTimeout(() => {
258
+ abortController.abort(`Timeout after ${timeoutMs}ms`);
259
+ this.pendingAbortControllers.delete(abortController);
260
+ }, timeoutMs)
261
+ : null;
262
+ return (0,_shared_navigator_js__WEBPACK_IMPORTED_MODULE_1__.getNavigatorLocks)().request(`db-lock-${this._dbIdentifier}`, { signal: abortController.signal }, async () => {
263
+ this.pendingAbortControllers.delete(abortController);
264
+ if (timeoutId) {
265
+ clearTimeout(timeoutId);
266
+ }
267
+ return await callback();
268
+ });
269
+ }
270
+ async acquireLock(callback, options) {
271
+ await this.waitForInitialized();
272
+ // The database is being opened in the background. Wait for it here.
273
+ if (this.databaseOpenPromise) {
274
+ await this.databaseOpenPromise;
275
+ }
276
+ return this._acquireLock(async () => {
277
+ let holdId = null;
278
+ try {
279
+ /**
280
+ * We can't await this since it uses the same lock as we're in now.
281
+ * If there is a pending open, this call will throw.
282
+ * If there is no pending open, but there is also no database - the open
283
+ * might have failed. We need to re-open the database.
284
+ */
285
+ if (this.databaseOpenPromise || !this._db) {
286
+ throw new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.ConnectionClosedError('Connection is busy re-opening');
287
+ }
288
+ holdId = this.requiresHolds ? await this.baseDB.markHold() : null;
289
+ return await callback();
290
+ }
291
+ catch (ex) {
292
+ if (_powersync_common__WEBPACK_IMPORTED_MODULE_0__.ConnectionClosedError.MATCHES(ex)) {
293
+ if (this.options.reOpenOnConnectionClosed && !this.databaseOpenPromise && !this.closing) {
294
+ // Immediately re-open the database. We need to miss as little table updates as possible.
295
+ // Note, don't await this since it uses the same lock as we're in now.
296
+ this.reOpenInternalDB();
297
+ }
298
+ }
299
+ throw ex;
300
+ }
301
+ finally {
302
+ if (holdId) {
303
+ await this.baseDB.releaseHold(holdId);
304
+ }
305
+ }
306
+ }, options);
307
+ }
308
+ async readTransaction(fn, options) {
309
+ return this.readLock(this.wrapTransaction(fn));
310
+ }
311
+ writeTransaction(fn, options) {
312
+ return this.writeLock(this.wrapTransaction(fn, true));
313
+ }
314
+ generateDBHelpers(tx) {
315
+ return {
316
+ ...tx,
317
+ /**
318
+ * Execute a read-only query and return results
319
+ */
320
+ async getAll(sql, parameters) {
321
+ const res = await tx.execute(sql, parameters);
322
+ return res.rows?._array ?? [];
323
+ },
324
+ /**
325
+ * Execute a read-only query and return the first result, or null if the ResultSet is empty.
326
+ */
327
+ async getOptional(sql, parameters) {
328
+ const res = await tx.execute(sql, parameters);
329
+ return res.rows?.item(0) ?? null;
330
+ },
331
+ /**
332
+ * Execute a read-only query and return the first result, error if the ResultSet is empty.
333
+ */
334
+ async get(sql, parameters) {
335
+ const res = await tx.execute(sql, parameters);
336
+ const first = res.rows?.item(0);
337
+ if (!first) {
338
+ throw new Error('Result set is empty');
339
+ }
340
+ return first;
341
+ }
342
+ };
343
+ }
344
+ /**
345
+ * Wraps a lock context into a transaction context
346
+ */
347
+ wrapTransaction(cb, write = false) {
348
+ return async (tx) => {
349
+ await this._execute(write ? 'BEGIN EXCLUSIVE' : 'BEGIN');
350
+ let finalized = false;
351
+ const commit = async () => {
352
+ if (finalized) {
353
+ return { rowsAffected: 0 };
354
+ }
355
+ finalized = true;
356
+ return this._execute('COMMIT');
357
+ };
358
+ const rollback = () => {
359
+ finalized = true;
360
+ return this._execute('ROLLBACK');
361
+ };
362
+ try {
363
+ const result = await cb({
364
+ ...tx,
365
+ commit,
366
+ rollback
367
+ });
368
+ if (!finalized) {
369
+ await commit();
370
+ }
371
+ return result;
372
+ }
373
+ catch (ex) {
374
+ this.logger.debug('Caught ex in transaction', ex);
375
+ try {
376
+ await rollback();
377
+ }
378
+ catch (ex2) {
379
+ // In rare cases, a rollback may fail.
380
+ // Safe to ignore.
381
+ }
382
+ throw ex;
383
+ }
384
+ };
385
+ }
386
+ /**
387
+ * Wraps the worker execute function, awaiting for it to be available
388
+ */
389
+ _execute = async (sql, bindings) => {
390
+ await this.waitForInitialized();
391
+ const result = await this.baseDB.execute(sql, bindings);
392
+ return {
393
+ ...result,
394
+ rows: {
395
+ ...result.rows,
396
+ item: (idx) => result.rows._array[idx]
397
+ }
398
+ };
399
+ };
400
+ /**
401
+ * Wraps the worker executeRaw function, awaiting for it to be available
402
+ */
403
+ _executeRaw = async (sql, bindings) => {
404
+ await this.waitForInitialized();
405
+ return await this.baseDB.executeRaw(sql, bindings);
406
+ };
407
+ /**
408
+ * Wraps the worker executeBatch function, awaiting for it to be available
409
+ */
410
+ _executeBatch = async (query, params) => {
411
+ await this.waitForInitialized();
412
+ const result = await this.baseDB.executeBatch(query, params);
413
+ return {
414
+ ...result,
415
+ rows: undefined
416
+ };
417
+ };
418
+ }
419
+
420
+
421
+ /***/ },
422
+
423
+ /***/ "./lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js"
424
+ /*!*********************************************************************!*\
425
+ !*** ./lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js ***!
426
+ \*********************************************************************/
427
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
428
+
429
+ __webpack_require__.r(__webpack_exports__);
430
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
431
+ /* harmony export */ WorkerWrappedAsyncDatabaseConnection: () => (/* binding */ WorkerWrappedAsyncDatabaseConnection)
432
+ /* harmony export */ });
433
+ /* harmony import */ var _powersync_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @powersync/common */ "@powersync/common");
434
+ /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! comlink */ "comlink");
435
+
436
+
437
+ /**
438
+ * Wraps a provided instance of {@link AsyncDatabaseConnection}, providing necessary proxy
439
+ * functions for worker listeners.
440
+ */
441
+ class WorkerWrappedAsyncDatabaseConnection extends _powersync_common__WEBPACK_IMPORTED_MODULE_0__.BaseObserver {
442
+ options;
443
+ lockAbortController = new AbortController();
444
+ notifyRemoteClosed;
445
+ constructor(options) {
446
+ super();
447
+ this.options = options;
448
+ if (options.remoteCanCloseUnexpectedly) {
449
+ this.notifyRemoteClosed = new AbortController();
450
+ }
451
+ }
452
+ get baseConnection() {
453
+ return this.options.baseConnection;
454
+ }
455
+ init() {
456
+ return this.baseConnection.init();
457
+ }
458
+ /**
459
+ * Marks the remote as closed.
460
+ *
461
+ * This can sometimes happen outside of our control, e.g. when a shared worker requests a connection from a tab. When
462
+ * it happens, all methods on the {@link baseConnection} would never resolve. To avoid livelocks in this scenario, we
463
+ * throw on all outstanding promises and forbid new calls.
464
+ */
465
+ markRemoteClosed() {
466
+ // Can non-null assert here because this function is only supposed to be called when remoteCanCloseUnexpectedly was
467
+ // set.
468
+ this.notifyRemoteClosed.abort();
469
+ }
470
+ markHold() {
471
+ return this.withRemote(() => this.baseConnection.markHold());
472
+ }
473
+ releaseHold(holdId) {
474
+ return this.withRemote(() => this.baseConnection.releaseHold(holdId));
475
+ }
476
+ isAutoCommit() {
477
+ return this.withRemote(() => this.baseConnection.isAutoCommit());
478
+ }
479
+ withRemote(workerPromise, fireActionOnAbort = false) {
480
+ const controller = this.notifyRemoteClosed;
481
+ if (controller) {
482
+ return new Promise((resolve, reject) => {
483
+ if (controller.signal.aborted) {
484
+ reject(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.ConnectionClosedError('Called operation on closed remote'));
485
+ if (!fireActionOnAbort) {
486
+ // Don't run the operation if we're going to reject
487
+ // We might want to fire-and-forget the operation in some cases (like a close operation)
488
+ return;
489
+ }
490
+ }
491
+ function handleAbort() {
492
+ reject(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.ConnectionClosedError('Remote peer closed with request in flight'));
493
+ }
494
+ function completePromise(action) {
495
+ controller.signal.removeEventListener('abort', handleAbort);
496
+ action();
497
+ }
498
+ controller.signal.addEventListener('abort', handleAbort);
499
+ workerPromise()
500
+ .then((data) => completePromise(() => resolve(data)))
501
+ .catch((e) => completePromise(() => reject(e)));
502
+ });
503
+ }
504
+ else {
505
+ // Can't close, so just return the inner worker promise unguarded.
506
+ return workerPromise();
507
+ }
508
+ }
509
+ /**
510
+ * Get a MessagePort which can be used to share the internals of this connection.
511
+ */
512
+ async shareConnection() {
513
+ const { identifier, remote } = this.options;
514
+ /**
515
+ * Hold a navigator lock in order to avoid features such as Chrome's frozen tabs,
516
+ * or Edge's sleeping tabs from pausing the thread for this connection.
517
+ * This promise resolves once a lock is obtained.
518
+ * This lock will be held as long as this connection is open.
519
+ * The `shareConnection` method should not be called on multiple tabs concurrently.
520
+ */
521
+ await new Promise((resolve, reject) => navigator.locks
522
+ .request(`shared-connection-${this.options.identifier}-${Date.now()}-${Math.round(Math.random() * 10000)}`, {
523
+ signal: this.lockAbortController.signal
524
+ }, async () => {
525
+ resolve();
526
+ // Free the lock when the connection is already closed.
527
+ if (this.lockAbortController.signal.aborted) {
528
+ return;
529
+ }
530
+ // Hold the lock while the shared connection is in use.
531
+ await new Promise((releaseLock) => {
532
+ this.lockAbortController.signal.addEventListener('abort', () => {
533
+ releaseLock();
534
+ });
535
+ });
536
+ })
537
+ // We aren't concerned with abort errors here
538
+ .catch((ex) => {
539
+ if (ex.name == 'AbortError') {
540
+ resolve();
541
+ }
542
+ else {
543
+ reject(ex);
544
+ }
545
+ }));
546
+ const newPort = await remote[comlink__WEBPACK_IMPORTED_MODULE_1__.createEndpoint]();
547
+ return { port: newPort, identifier };
548
+ }
549
+ /**
550
+ * Registers a table change notification callback with the base database.
551
+ * This can be extended by custom implementations in order to handle proxy events.
552
+ */
553
+ async registerOnTableChange(callback) {
554
+ return this.baseConnection.registerOnTableChange(comlink__WEBPACK_IMPORTED_MODULE_1__.proxy(callback));
555
+ }
556
+ async close() {
557
+ // Abort any pending lock requests.
558
+ this.lockAbortController.abort();
559
+ try {
560
+ // fire and forget the close operation
561
+ await this.withRemote(() => this.baseConnection.close(), true);
562
+ }
563
+ finally {
564
+ this.options.remote[comlink__WEBPACK_IMPORTED_MODULE_1__.releaseProxy]();
565
+ this.options.onClose?.();
566
+ this.iterateListeners((l) => l.closing?.());
567
+ }
568
+ }
569
+ execute(sql, params) {
570
+ return this.withRemote(() => this.baseConnection.execute(sql, params));
571
+ }
572
+ executeRaw(sql, params) {
573
+ return this.withRemote(() => this.baseConnection.executeRaw(sql, params));
574
+ }
575
+ executeBatch(sql, params) {
576
+ return this.withRemote(() => this.baseConnection.executeBatch(sql, params));
577
+ }
578
+ getConfig() {
579
+ return this.withRemote(() => this.baseConnection.getConfig());
580
+ }
581
+ }
582
+
583
+
584
+ /***/ },
585
+
586
+ /***/ "./lib/src/db/sync/WebRemote.js"
587
+ /*!**************************************!*\
588
+ !*** ./lib/src/db/sync/WebRemote.js ***!
589
+ \**************************************/
590
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
591
+
592
+ __webpack_require__.r(__webpack_exports__);
593
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
594
+ /* harmony export */ WebRemote: () => (/* binding */ WebRemote)
595
+ /* harmony export */ });
596
+ /* harmony import */ var _powersync_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @powersync/common */ "@powersync/common");
597
+ /* harmony import */ var _userAgent_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./userAgent.js */ "./lib/src/db/sync/userAgent.js");
598
+
599
+
600
+ /*
601
+ * Depends on browser's implementation of global fetch.
602
+ */
603
+ class WebFetchProvider extends _powersync_common__WEBPACK_IMPORTED_MODULE_0__.FetchImplementationProvider {
604
+ getFetch() {
605
+ return fetch.bind(globalThis);
606
+ }
607
+ }
608
+ class WebRemote extends _powersync_common__WEBPACK_IMPORTED_MODULE_0__.AbstractRemote {
609
+ connector;
610
+ logger;
611
+ _bson;
612
+ constructor(connector, logger = _powersync_common__WEBPACK_IMPORTED_MODULE_0__.DEFAULT_REMOTE_LOGGER, options) {
613
+ super(connector, logger, {
614
+ ...(options ?? {}),
615
+ fetchImplementation: options?.fetchImplementation ?? new WebFetchProvider()
616
+ });
617
+ this.connector = connector;
618
+ this.logger = logger;
619
+ }
620
+ getUserAgent() {
621
+ let ua = [super.getUserAgent(), `powersync-web`];
622
+ try {
623
+ ua.push(...(0,_userAgent_js__WEBPACK_IMPORTED_MODULE_1__.getUserAgentInfo)());
624
+ }
625
+ catch (e) {
626
+ this.logger.warn('Failed to get user agent info', e);
627
+ }
628
+ return ua.join(' ');
629
+ }
630
+ async getBSON() {
631
+ if (this._bson) {
632
+ return this._bson;
633
+ }
634
+ /**
635
+ * Dynamic import to be used only when needed.
636
+ */
637
+ const { BSON } = await Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! bson */ "../../node_modules/.pnpm/bson@6.10.4/node_modules/bson/lib/bson.mjs"));
638
+ this._bson = BSON;
639
+ return this._bson;
640
+ }
641
+ }
642
+
643
+
644
+ /***/ },
645
+
646
+ /***/ "./lib/src/db/sync/WebStreamingSyncImplementation.js"
647
+ /*!***********************************************************!*\
648
+ !*** ./lib/src/db/sync/WebStreamingSyncImplementation.js ***!
649
+ \***********************************************************/
650
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
651
+
652
+ __webpack_require__.r(__webpack_exports__);
653
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
654
+ /* harmony export */ WebStreamingSyncImplementation: () => (/* binding */ WebStreamingSyncImplementation)
655
+ /* harmony export */ });
656
+ /* harmony import */ var _powersync_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @powersync/common */ "@powersync/common");
657
+ /* harmony import */ var _shared_navigator_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../shared/navigator.js */ "./lib/src/shared/navigator.js");
658
+
659
+
660
+ class WebStreamingSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODULE_0__.AbstractStreamingSyncImplementation {
661
+ constructor(options) {
662
+ // Super will store and provide default values for options
663
+ super(options);
664
+ }
665
+ get webOptions() {
666
+ return this.options;
667
+ }
668
+ async obtainLock(lockOptions) {
669
+ const identifier = `streaming-sync-${lockOptions.type}-${this.webOptions.identifier}`;
670
+ if (lockOptions.type == _powersync_common__WEBPACK_IMPORTED_MODULE_0__.LockType.SYNC) {
671
+ this.logger.debug('requesting lock for ', identifier);
672
+ }
673
+ return (0,_shared_navigator_js__WEBPACK_IMPORTED_MODULE_1__.getNavigatorLocks)().request(identifier, { signal: lockOptions.signal }, lockOptions.callback);
674
+ }
675
+ }
676
+
677
+
678
+ /***/ },
679
+
680
+ /***/ "./lib/src/db/sync/userAgent.js"
681
+ /*!**************************************!*\
682
+ !*** ./lib/src/db/sync/userAgent.js ***!
683
+ \**************************************/
684
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
685
+
686
+ __webpack_require__.r(__webpack_exports__);
687
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
688
+ /* harmony export */ getUserAgentInfo: () => (/* binding */ getUserAgentInfo)
689
+ /* harmony export */ });
690
+ /**
691
+ * Get a minimal representation of browser, version and operating system.
692
+ *
693
+ * The goal is to get enough environemnt info to reproduce issues, but no
694
+ * more.
695
+ */
696
+ function getUserAgentInfo(nav) {
697
+ nav ??= navigator;
698
+ const browser = getBrowserInfo(nav);
699
+ const os = getOsInfo(nav);
700
+ // The cast below is to cater for TypeScript < 5.5.0
701
+ return [browser, os].filter((v) => v != null);
702
+ }
703
+ function getBrowserInfo(nav) {
704
+ const brands = nav.userAgentData?.brands;
705
+ if (brands != null) {
706
+ const tests = [
707
+ { name: 'Google Chrome', value: 'Chrome' },
708
+ { name: 'Opera', value: 'Opera' },
709
+ { name: 'Edge', value: 'Edge' },
710
+ { name: 'Chromium', value: 'Chromium' }
711
+ ];
712
+ for (let { name, value } of tests) {
713
+ const brand = brands.find((b) => b.brand == name);
714
+ if (brand != null) {
715
+ return `${value}/${brand.version}`;
716
+ }
717
+ }
718
+ }
719
+ const ua = nav.userAgent;
720
+ const regexps = [
721
+ { re: /(?:firefox|fxios)\/(\d+)/i, value: 'Firefox' },
722
+ { re: /(?:edg|edge|edga|edgios)\/(\d+)/i, value: 'Edge' },
723
+ { re: /opr\/(\d+)/i, value: 'Opera' },
724
+ { re: /(?:chrome|chromium|crios)\/(\d+)/i, value: 'Chrome' },
725
+ { re: /version\/(\d+).*safari/i, value: 'Safari' }
726
+ ];
727
+ for (let { re, value } of regexps) {
728
+ const match = re.exec(ua);
729
+ if (match != null) {
730
+ return `${value}/${match[1]}`;
731
+ }
732
+ }
733
+ return null;
734
+ }
735
+ function getOsInfo(nav) {
736
+ if (nav.userAgentData?.platform != null) {
737
+ return nav.userAgentData.platform.toLowerCase();
738
+ }
739
+ const ua = nav.userAgent;
740
+ const regexps = [
741
+ { re: /windows/i, value: 'windows' },
742
+ { re: /android/i, value: 'android' },
743
+ { re: /linux/i, value: 'linux' },
744
+ { re: /iphone|ipad|ipod/i, value: 'ios' },
745
+ { re: /macintosh|mac os x/i, value: 'macos' }
746
+ ];
747
+ for (let { re, value } of regexps) {
748
+ if (re.test(ua)) {
749
+ return value;
750
+ }
751
+ }
752
+ return null;
753
+ }
754
+
755
+
756
+ /***/ },
757
+
758
+ /***/ "./lib/src/worker/sync/BroadcastLogger.js"
759
+ /*!************************************************!*\
760
+ !*** ./lib/src/worker/sync/BroadcastLogger.js ***!
761
+ \************************************************/
762
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
763
+
764
+ __webpack_require__.r(__webpack_exports__);
765
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
766
+ /* harmony export */ BroadcastLogger: () => (/* binding */ BroadcastLogger)
767
+ /* harmony export */ });
768
+ /* harmony import */ var _powersync_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @powersync/common */ "@powersync/common");
769
+
770
+ /**
771
+ * Broadcasts logs to all clients
772
+ */
773
+ class BroadcastLogger {
774
+ clients;
775
+ TRACE;
776
+ DEBUG;
777
+ INFO;
778
+ TIME;
779
+ WARN;
780
+ ERROR;
781
+ OFF;
782
+ currentLevel = _powersync_common__WEBPACK_IMPORTED_MODULE_0__.LogLevel.INFO;
783
+ constructor(clients) {
784
+ this.clients = clients;
785
+ this.TRACE = _powersync_common__WEBPACK_IMPORTED_MODULE_0__.LogLevel.TRACE;
786
+ this.DEBUG = _powersync_common__WEBPACK_IMPORTED_MODULE_0__.LogLevel.DEBUG;
787
+ this.INFO = _powersync_common__WEBPACK_IMPORTED_MODULE_0__.LogLevel.INFO;
788
+ this.TIME = _powersync_common__WEBPACK_IMPORTED_MODULE_0__.LogLevel.TIME;
789
+ this.WARN = _powersync_common__WEBPACK_IMPORTED_MODULE_0__.LogLevel.WARN;
790
+ this.ERROR = _powersync_common__WEBPACK_IMPORTED_MODULE_0__.LogLevel.ERROR;
791
+ this.OFF = _powersync_common__WEBPACK_IMPORTED_MODULE_0__.LogLevel.OFF;
792
+ }
793
+ trace(...x) {
794
+ if (!this.enabledFor(this.TRACE))
795
+ return;
796
+ console.trace(...x);
797
+ const sanitized = this.sanitizeArgs(x);
798
+ this.iterateClients((client) => client.clientProvider.trace(...sanitized));
799
+ }
800
+ debug(...x) {
801
+ if (!this.enabledFor(this.DEBUG))
802
+ return;
803
+ console.debug(...x);
804
+ const sanitized = this.sanitizeArgs(x);
805
+ this.iterateClients((client) => client.clientProvider.debug(...sanitized));
806
+ }
807
+ info(...x) {
808
+ if (!this.enabledFor(this.INFO))
809
+ return;
810
+ console.info(...x);
811
+ const sanitized = this.sanitizeArgs(x);
812
+ this.iterateClients((client) => client.clientProvider.info(...sanitized));
813
+ }
814
+ log(...x) {
815
+ if (!this.enabledFor(this.INFO))
816
+ return;
817
+ console.log(...x);
818
+ const sanitized = this.sanitizeArgs(x);
819
+ this.iterateClients((client) => client.clientProvider.log(...sanitized));
820
+ }
821
+ warn(...x) {
822
+ if (!this.enabledFor(this.WARN))
823
+ return;
824
+ console.warn(...x);
825
+ const sanitized = this.sanitizeArgs(x);
826
+ this.iterateClients((client) => client.clientProvider.warn(...sanitized));
827
+ }
828
+ error(...x) {
829
+ if (!this.enabledFor(this.ERROR))
830
+ return;
831
+ console.error(...x);
832
+ const sanitized = this.sanitizeArgs(x);
833
+ this.iterateClients((client) => client.clientProvider.error(...sanitized));
834
+ }
835
+ time(label) {
836
+ if (!this.enabledFor(this.TIME))
837
+ return;
838
+ console.time(label);
839
+ this.iterateClients((client) => client.clientProvider.time(label));
840
+ }
841
+ timeEnd(label) {
842
+ if (!this.enabledFor(this.TIME))
843
+ return;
844
+ console.timeEnd(label);
845
+ this.iterateClients((client) => client.clientProvider.timeEnd(label));
846
+ }
847
+ /**
848
+ * Set the global log level.
849
+ */
850
+ setLevel(level) {
851
+ this.currentLevel = level;
852
+ }
853
+ /**
854
+ * Get the current log level.
855
+ */
856
+ getLevel() {
857
+ return this.currentLevel;
858
+ }
859
+ /**
860
+ * Returns true if the given level is enabled.
861
+ */
862
+ enabledFor(level) {
863
+ return level.value >= this.currentLevel.value;
864
+ }
865
+ /**
866
+ * Iterates all clients, catches individual client exceptions
867
+ * and proceeds to execute for all clients.
868
+ */
869
+ async iterateClients(callback) {
870
+ for (const client of this.clients) {
871
+ try {
872
+ await callback(client);
873
+ }
874
+ catch (ex) {
875
+ console.error('Caught exception when iterating client', ex);
876
+ }
877
+ }
878
+ }
879
+ /**
880
+ * Guards against any logging errors.
881
+ * We don't want a logging exception to cause further issues upstream
882
+ */
883
+ sanitizeArgs(x) {
884
+ const sanitizedParams = x.map((param) => {
885
+ try {
886
+ // Try and clone here first. If it fails it won't be passable over a MessagePort
887
+ return structuredClone(param);
888
+ }
889
+ catch (ex) {
890
+ console.error(ex);
891
+ return 'Could not serialize log params. Check shared worker logs for more details.';
892
+ }
893
+ });
894
+ return sanitizedParams;
895
+ }
896
+ }
897
+
898
+
899
+ /***/ },
900
+
901
+ /***/ "./lib/src/worker/sync/SharedSyncImplementation.js"
902
+ /*!*********************************************************!*\
903
+ !*** ./lib/src/worker/sync/SharedSyncImplementation.js ***!
904
+ \*********************************************************/
905
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
906
+
907
+ __webpack_require__.r(__webpack_exports__);
908
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
909
+ /* harmony export */ SharedSyncClientEvent: () => (/* binding */ SharedSyncClientEvent),
910
+ /* harmony export */ SharedSyncImplementation: () => (/* binding */ SharedSyncImplementation)
911
+ /* harmony export */ });
912
+ /* harmony import */ var _powersync_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @powersync/common */ "@powersync/common");
913
+ /* harmony import */ var async_mutex__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! async-mutex */ "async-mutex");
914
+ /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! comlink */ "comlink");
915
+ /* harmony import */ var _db_sync_WebRemote_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../db/sync/WebRemote.js */ "./lib/src/db/sync/WebRemote.js");
916
+ /* harmony import */ var _db_sync_WebStreamingSyncImplementation_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../db/sync/WebStreamingSyncImplementation.js */ "./lib/src/db/sync/WebStreamingSyncImplementation.js");
917
+ /* harmony import */ var _db_adapters_LockedAsyncDatabaseAdapter_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../db/adapters/LockedAsyncDatabaseAdapter.js */ "./lib/src/db/adapters/LockedAsyncDatabaseAdapter.js");
918
+ /* harmony import */ var _db_adapters_WorkerWrappedAsyncDatabaseConnection_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../db/adapters/WorkerWrappedAsyncDatabaseConnection.js */ "./lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js");
919
+ /* harmony import */ var _BroadcastLogger_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./BroadcastLogger.js */ "./lib/src/worker/sync/BroadcastLogger.js");
920
+
921
+
922
+
923
+
924
+
925
+
926
+
927
+
928
+ /**
929
+ * @internal
930
+ * Manual message events for shared sync clients
931
+ */
932
+ var SharedSyncClientEvent;
933
+ (function (SharedSyncClientEvent) {
934
+ /**
935
+ * This client requests the shared sync manager should
936
+ * close it's connection to the client.
937
+ */
938
+ SharedSyncClientEvent["CLOSE_CLIENT"] = "close-client";
939
+ SharedSyncClientEvent["CLOSE_ACK"] = "close-ack";
940
+ })(SharedSyncClientEvent || (SharedSyncClientEvent = {}));
941
+ /**
942
+ * HACK: The shared implementation wraps and provides its own
943
+ * PowerSyncBackendConnector when generating the streaming sync implementation.
944
+ * We provide this unused placeholder when connecting with the ConnectionManager.
945
+ */
946
+ const CONNECTOR_PLACEHOLDER = {};
947
+ /**
948
+ * @internal
949
+ * Shared sync implementation which runs inside a shared webworker
950
+ */
951
+ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODULE_0__.BaseObserver {
952
+ ports;
953
+ isInitialized;
954
+ statusListener;
955
+ fetchCredentialsController;
956
+ uploadDataController;
957
+ syncParams;
958
+ logger;
959
+ lastConnectOptions;
960
+ portMutex;
961
+ subscriptions = [];
962
+ connectionManager;
963
+ syncStatus;
964
+ broadCastLogger;
965
+ distributedDB;
966
+ constructor() {
967
+ super();
968
+ this.ports = [];
969
+ this.syncParams = null;
970
+ this.logger = (0,_powersync_common__WEBPACK_IMPORTED_MODULE_0__.createLogger)('shared-sync');
971
+ this.lastConnectOptions = undefined;
972
+ this.portMutex = new async_mutex__WEBPACK_IMPORTED_MODULE_1__.Mutex();
973
+ this.isInitialized = new Promise((resolve) => {
974
+ const callback = this.registerListener({
975
+ initialized: () => {
976
+ resolve();
977
+ callback?.();
978
+ }
979
+ });
980
+ });
981
+ // Should be configured once we get params
982
+ this.distributedDB = null;
983
+ this.syncStatus = new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SyncStatus({});
984
+ this.broadCastLogger = new _BroadcastLogger_js__WEBPACK_IMPORTED_MODULE_7__.BroadcastLogger(this.ports);
985
+ this.connectionManager = new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.ConnectionManager({
986
+ createSyncImplementation: async () => {
987
+ await this.waitForReady();
988
+ const sync = this.generateStreamingImplementation();
989
+ const onDispose = sync.registerListener({
990
+ statusChanged: (status) => {
991
+ this.updateAllStatuses(status.toJSON());
992
+ }
993
+ });
994
+ return {
995
+ sync,
996
+ onDispose
997
+ };
998
+ },
999
+ logger: this.logger
1000
+ });
1001
+ }
1002
+ get lastSyncedAt() {
1003
+ return this.connectionManager.syncStreamImplementation?.lastSyncedAt;
1004
+ }
1005
+ get isConnected() {
1006
+ return this.connectionManager.syncStreamImplementation?.isConnected ?? false;
1007
+ }
1008
+ /**
1009
+ * Gets the last client port which we know is safe from unexpected closes.
1010
+ */
1011
+ async getLastWrappedPort() {
1012
+ // Find the last port which is not closing
1013
+ return await this.portMutex.runExclusive(() => {
1014
+ for (let i = this.ports.length - 1; i >= 0; i--) {
1015
+ if (!this.ports[i].isClosing) {
1016
+ return this.ports[i];
1017
+ }
1018
+ }
1019
+ return;
1020
+ });
1021
+ }
1022
+ /**
1023
+ * In some very rare cases a specific tab might not respond to requests.
1024
+ * This returns a random port which is not closing.
1025
+ */
1026
+ async getRandomWrappedPort() {
1027
+ return await this.portMutex.runExclusive(() => {
1028
+ const nonClosingPorts = this.ports.filter((p) => !p.isClosing);
1029
+ return nonClosingPorts[Math.floor(Math.random() * nonClosingPorts.length)];
1030
+ });
1031
+ }
1032
+ async waitForStatus(status) {
1033
+ return this.withSyncImplementation(async (sync) => {
1034
+ return sync.waitForStatus(status);
1035
+ });
1036
+ }
1037
+ async waitUntilStatusMatches(predicate) {
1038
+ return this.withSyncImplementation(async (sync) => {
1039
+ return sync.waitUntilStatusMatches(predicate);
1040
+ });
1041
+ }
1042
+ async waitForReady() {
1043
+ return this.isInitialized;
1044
+ }
1045
+ collectActiveSubscriptions() {
1046
+ this.logger.debug('Collecting active stream subscriptions across tabs');
1047
+ const active = new Map();
1048
+ for (const port of this.ports) {
1049
+ for (const stream of port.currentSubscriptions) {
1050
+ const serializedKey = JSON.stringify(stream);
1051
+ active.set(serializedKey, stream);
1052
+ }
1053
+ }
1054
+ this.subscriptions = [...active.values()];
1055
+ this.logger.debug('Collected stream subscriptions', this.subscriptions);
1056
+ this.connectionManager.syncStreamImplementation?.updateSubscriptions(this.subscriptions);
1057
+ }
1058
+ updateSubscriptions(port, subscriptions) {
1059
+ port.currentSubscriptions = subscriptions;
1060
+ this.collectActiveSubscriptions();
1061
+ }
1062
+ setLogLevel(level) {
1063
+ this.logger.setLevel(level);
1064
+ this.broadCastLogger.setLevel(level);
1065
+ }
1066
+ /**
1067
+ * Configures the DBAdapter connection and a streaming sync client.
1068
+ */
1069
+ async setParams(params) {
1070
+ await this.portMutex.runExclusive(async () => {
1071
+ this.collectActiveSubscriptions();
1072
+ });
1073
+ if (this.syncParams) {
1074
+ // Cannot modify already existing sync implementation params
1075
+ return;
1076
+ }
1077
+ // First time setting params
1078
+ this.syncParams = params;
1079
+ if (params.streamOptions?.flags?.broadcastLogs) {
1080
+ this.logger = this.broadCastLogger;
1081
+ }
1082
+ const lockedAdapter = new _db_adapters_LockedAsyncDatabaseAdapter_js__WEBPACK_IMPORTED_MODULE_5__.LockedAsyncDatabaseAdapter({
1083
+ name: params.dbParams.dbFilename,
1084
+ openConnection: async () => {
1085
+ // Gets a connection from the clients when a new connection is requested.
1086
+ const db = await this.openInternalDB();
1087
+ db.registerListener({
1088
+ closing: () => {
1089
+ lockedAdapter.reOpenInternalDB();
1090
+ }
1091
+ });
1092
+ return db;
1093
+ },
1094
+ logger: this.logger,
1095
+ reOpenOnConnectionClosed: true
1096
+ });
1097
+ this.distributedDB = lockedAdapter;
1098
+ await lockedAdapter.init();
1099
+ lockedAdapter.registerListener({
1100
+ databaseReOpened: () => {
1101
+ // We may have missed some table updates while the database was closed.
1102
+ // We can poke the crud in case we missed any updates.
1103
+ this.connectionManager.syncStreamImplementation?.triggerCrudUpload();
1104
+ /**
1105
+ * FIXME or IMPROVE ME
1106
+ * The Rust client implementation stores sync state on the connection level.
1107
+ * Reopening the database causes a state machine error which should cause the
1108
+ * StreamingSyncImplementation to reconnect. It would be nicer if we could trigger
1109
+ * this reconnect earlier.
1110
+ * This reconnect is not required for IndexedDB.
1111
+ */
1112
+ }
1113
+ });
1114
+ self.onerror = (event) => {
1115
+ // Share any uncaught events on the broadcast logger
1116
+ this.logger.error('Uncaught exception in PowerSync shared sync worker', event);
1117
+ };
1118
+ this.iterateListeners((l) => l.initialized?.());
1119
+ }
1120
+ async dispose() {
1121
+ await this.waitForReady();
1122
+ this.statusListener?.();
1123
+ return this.connectionManager.close();
1124
+ }
1125
+ /**
1126
+ * Connects to the PowerSync backend instance.
1127
+ * Multiple tabs can safely call this in their initialization.
1128
+ * The connection will simply be reconnected whenever a new tab
1129
+ * connects.
1130
+ */
1131
+ async connect(options) {
1132
+ this.lastConnectOptions = options;
1133
+ return this.connectionManager.connect(CONNECTOR_PLACEHOLDER, options ?? {});
1134
+ }
1135
+ async disconnect() {
1136
+ return this.connectionManager.disconnect();
1137
+ }
1138
+ /**
1139
+ * Adds a new client tab's message port to the list of connected ports
1140
+ */
1141
+ async addPort(port) {
1142
+ return await this.portMutex.runExclusive(() => {
1143
+ const portProvider = {
1144
+ port,
1145
+ clientProvider: comlink__WEBPACK_IMPORTED_MODULE_2__.wrap(port),
1146
+ currentSubscriptions: [],
1147
+ closeListeners: [],
1148
+ isClosing: false
1149
+ };
1150
+ this.ports.push(portProvider);
1151
+ // Give the newly connected client the latest status
1152
+ const status = this.connectionManager.syncStreamImplementation?.syncStatus;
1153
+ if (status) {
1154
+ portProvider.clientProvider.statusChanged(status.toJSON());
1155
+ }
1156
+ return portProvider;
1157
+ });
1158
+ }
1159
+ /**
1160
+ * Removes a message port client from this manager's managed
1161
+ * clients.
1162
+ */
1163
+ async removePort(port) {
1164
+ // Ports might be removed faster than we can process them.
1165
+ port.isClosing = true;
1166
+ // Remove the port within a mutex context.
1167
+ // Warns if the port is not found. This should not happen in practice.
1168
+ // We return early if the port is not found.
1169
+ return await this.portMutex.runExclusive(async () => {
1170
+ const index = this.ports.findIndex((p) => p == port);
1171
+ if (index < 0) {
1172
+ this.logger.warn(`Could not remove port ${port} since it is not present in active ports.`);
1173
+ return () => { };
1174
+ }
1175
+ const trackedPort = this.ports[index];
1176
+ // Remove from the list of active ports
1177
+ this.ports.splice(index, 1);
1178
+ /**
1179
+ * The port might currently be in use. Any active functions might
1180
+ * not resolve. Abort them here.
1181
+ */
1182
+ [this.fetchCredentialsController, this.uploadDataController].forEach((abortController) => {
1183
+ if (abortController?.activePort == port) {
1184
+ abortController.controller.abort(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.AbortOperation('Closing pending requests after client port is removed'));
1185
+ }
1186
+ });
1187
+ // Close the worker wrapped database connection, we can't accurately rely on this connection
1188
+ for (const closeListener of trackedPort.closeListeners) {
1189
+ await closeListener();
1190
+ }
1191
+ this.collectActiveSubscriptions();
1192
+ return () => trackedPort.clientProvider[comlink__WEBPACK_IMPORTED_MODULE_2__.releaseProxy]();
1193
+ });
1194
+ }
1195
+ triggerCrudUpload() {
1196
+ this.withSyncImplementation(async (sync) => {
1197
+ sync.triggerCrudUpload();
1198
+ });
1199
+ }
1200
+ async hasCompletedSync() {
1201
+ return this.withSyncImplementation(async (sync) => {
1202
+ return sync.hasCompletedSync();
1203
+ });
1204
+ }
1205
+ async getWriteCheckpoint() {
1206
+ return this.withSyncImplementation(async (sync) => {
1207
+ return sync.getWriteCheckpoint();
1208
+ });
1209
+ }
1210
+ async withSyncImplementation(callback) {
1211
+ await this.waitForReady();
1212
+ if (this.connectionManager.syncStreamImplementation) {
1213
+ return callback(this.connectionManager.syncStreamImplementation);
1214
+ }
1215
+ const sync = await new Promise((resolve) => {
1216
+ const dispose = this.connectionManager.registerListener({
1217
+ syncStreamCreated: (sync) => {
1218
+ resolve(sync);
1219
+ dispose?.();
1220
+ }
1221
+ });
1222
+ });
1223
+ return callback(sync);
1224
+ }
1225
+ generateStreamingImplementation() {
1226
+ // This should only be called after initialization has completed
1227
+ const syncParams = this.syncParams;
1228
+ // Create a new StreamingSyncImplementation for each connect call. This is usually done is all SDKs.
1229
+ return new _db_sync_WebStreamingSyncImplementation_js__WEBPACK_IMPORTED_MODULE_4__.WebStreamingSyncImplementation({
1230
+ adapter: new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SqliteBucketStorage(this.distributedDB, this.logger),
1231
+ remote: new _db_sync_WebRemote_js__WEBPACK_IMPORTED_MODULE_3__.WebRemote({
1232
+ invalidateCredentials: async () => {
1233
+ const lastPort = await this.getLastWrappedPort();
1234
+ if (!lastPort) {
1235
+ throw new Error('No client port found to invalidate credentials');
1236
+ }
1237
+ try {
1238
+ this.logger.log('calling the last port client provider to invalidate credentials');
1239
+ lastPort.clientProvider.invalidateCredentials();
1240
+ }
1241
+ catch (ex) {
1242
+ this.logger.error('error invalidating credentials', ex);
1243
+ }
1244
+ },
1245
+ fetchCredentials: async () => {
1246
+ const lastPort = await this.getLastWrappedPort();
1247
+ if (!lastPort) {
1248
+ throw new Error('No client port found to fetch credentials');
1249
+ }
1250
+ return new Promise(async (resolve, reject) => {
1251
+ const abortController = new AbortController();
1252
+ this.fetchCredentialsController = {
1253
+ controller: abortController,
1254
+ activePort: lastPort
1255
+ };
1256
+ abortController.signal.onabort = reject;
1257
+ try {
1258
+ this.logger.log('calling the last port client provider for credentials');
1259
+ resolve(await lastPort.clientProvider.fetchCredentials());
1260
+ }
1261
+ catch (ex) {
1262
+ reject(ex);
1263
+ }
1264
+ finally {
1265
+ this.fetchCredentialsController = undefined;
1266
+ }
1267
+ });
1268
+ }
1269
+ }, this.logger),
1270
+ uploadCrud: async () => {
1271
+ const lastPort = await this.getLastWrappedPort();
1272
+ if (!lastPort) {
1273
+ throw new Error('No client port found to upload crud');
1274
+ }
1275
+ return new Promise(async (resolve, reject) => {
1276
+ const abortController = new AbortController();
1277
+ this.uploadDataController = {
1278
+ controller: abortController,
1279
+ activePort: lastPort
1280
+ };
1281
+ // Resolving will make it retry
1282
+ abortController.signal.onabort = () => resolve();
1283
+ try {
1284
+ resolve(await lastPort.clientProvider.uploadCrud());
1285
+ }
1286
+ catch (ex) {
1287
+ reject(ex);
1288
+ }
1289
+ finally {
1290
+ this.uploadDataController = undefined;
1291
+ }
1292
+ });
1293
+ },
1294
+ ...syncParams.streamOptions,
1295
+ subscriptions: this.subscriptions,
1296
+ // Logger cannot be transferred just yet
1297
+ logger: this.logger
1298
+ });
1299
+ }
1300
+ /**
1301
+ * Opens a worker wrapped database connection. Using the last connected client port.
1302
+ */
1303
+ async openInternalDB() {
1304
+ const client = await this.getRandomWrappedPort();
1305
+ if (!client) {
1306
+ // Should not really happen in practice
1307
+ throw new Error(`Could not open DB connection since no client is connected.`);
1308
+ }
1309
+ // Fail-safe timeout for opening a database connection.
1310
+ const timeout = setTimeout(() => {
1311
+ abortController.abort();
1312
+ }, 10_000);
1313
+ /**
1314
+ * Handle cases where the client might close while opening a connection.
1315
+ */
1316
+ const abortController = new AbortController();
1317
+ const closeListener = () => {
1318
+ abortController.abort();
1319
+ };
1320
+ const removeCloseListener = () => {
1321
+ const index = client.closeListeners.indexOf(closeListener);
1322
+ if (index >= 0) {
1323
+ client.closeListeners.splice(index, 1);
1324
+ }
1325
+ };
1326
+ client.closeListeners.push(closeListener);
1327
+ const workerPort = await withAbort({
1328
+ action: () => client.clientProvider.getDBWorkerPort(),
1329
+ signal: abortController.signal,
1330
+ cleanupOnAbort: (port) => {
1331
+ port.close();
1332
+ }
1333
+ }).catch((ex) => {
1334
+ removeCloseListener();
1335
+ throw ex;
1336
+ });
1337
+ const remote = comlink__WEBPACK_IMPORTED_MODULE_2__.wrap(workerPort);
1338
+ const identifier = this.syncParams.dbParams.dbFilename;
1339
+ /**
1340
+ * The open could fail if the tab is closed while we're busy opening the database.
1341
+ * This operation is typically executed inside an exclusive portMutex lock.
1342
+ * We typically execute the closeListeners using the portMutex in a different context.
1343
+ * We can't rely on the closeListeners to abort the operation if the tab is closed.
1344
+ */
1345
+ const db = await withAbort({
1346
+ action: () => remote(this.syncParams.dbParams),
1347
+ signal: abortController.signal,
1348
+ cleanupOnAbort: (db) => {
1349
+ db.close();
1350
+ }
1351
+ }).finally(() => {
1352
+ // We can remove the close listener here since we no longer need it past this point.
1353
+ removeCloseListener();
1354
+ });
1355
+ clearTimeout(timeout);
1356
+ const wrapped = new _db_adapters_WorkerWrappedAsyncDatabaseConnection_js__WEBPACK_IMPORTED_MODULE_6__.WorkerWrappedAsyncDatabaseConnection({
1357
+ remote,
1358
+ baseConnection: db,
1359
+ identifier,
1360
+ // It's possible for this worker to outlive the client hosting the database for us. We need to be prepared for
1361
+ // that and ensure pending requests are aborted when the tab is closed.
1362
+ remoteCanCloseUnexpectedly: true
1363
+ });
1364
+ client.closeListeners.push(async () => {
1365
+ this.logger.info('Aborting open connection because associated tab closed.');
1366
+ /**
1367
+ * Don't await this close operation. It might never resolve if the tab is closed.
1368
+ * We mark the remote as closed first, this will reject any pending requests.
1369
+ * We then call close. The close operation is configured to fire-and-forget, the main promise will reject immediately.
1370
+ */
1371
+ wrapped.markRemoteClosed();
1372
+ wrapped.close().catch((ex) => this.logger.warn('error closing database connection', ex));
1373
+ });
1374
+ return wrapped;
1375
+ }
1376
+ /**
1377
+ * A method to update the all shared statuses for each
1378
+ * client.
1379
+ */
1380
+ updateAllStatuses(status) {
1381
+ this.syncStatus = new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SyncStatus(status);
1382
+ this.ports.forEach((p) => p.clientProvider.statusChanged(status));
1383
+ }
1384
+ }
1385
+ /**
1386
+ * Runs the action with an abort controller.
1387
+ */
1388
+ function withAbort(options) {
1389
+ const { action, signal, cleanupOnAbort } = options;
1390
+ return new Promise((resolve, reject) => {
1391
+ if (signal.aborted) {
1392
+ reject(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.AbortOperation('Operation aborted by abort controller'));
1393
+ return;
1394
+ }
1395
+ function handleAbort() {
1396
+ signal.removeEventListener('abort', handleAbort);
1397
+ reject(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.AbortOperation('Operation aborted by abort controller'));
1398
+ }
1399
+ signal.addEventListener('abort', handleAbort, { once: true });
1400
+ function completePromise(action) {
1401
+ signal.removeEventListener('abort', handleAbort);
1402
+ action();
1403
+ }
1404
+ action()
1405
+ .then((data) => {
1406
+ // We already rejected due to the abort, allow for cleanup
1407
+ if (signal.aborted) {
1408
+ return completePromise(() => cleanupOnAbort?.(data));
1409
+ }
1410
+ completePromise(() => resolve(data));
1411
+ })
1412
+ .catch((e) => completePromise(() => reject(e)));
1413
+ });
1414
+ }
1415
+
1416
+
1417
+ /***/ },
1418
+
1419
+ /***/ "./lib/src/worker/sync/SharedSyncImplementation.worker.js"
1420
+ /*!****************************************************************!*\
1421
+ !*** ./lib/src/worker/sync/SharedSyncImplementation.worker.js ***!
1422
+ \****************************************************************/
1423
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
1424
+
1425
+ __webpack_require__.r(__webpack_exports__);
1426
+ /* harmony import */ var _powersync_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @powersync/common */ "@powersync/common");
1427
+ /* harmony import */ var _SharedSyncImplementation_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./SharedSyncImplementation.js */ "./lib/src/worker/sync/SharedSyncImplementation.js");
1428
+ /* harmony import */ var _WorkerClient_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./WorkerClient.js */ "./lib/src/worker/sync/WorkerClient.js");
1429
+
1430
+
1431
+
1432
+ const _self = self;
1433
+ const logger = (0,_powersync_common__WEBPACK_IMPORTED_MODULE_0__.createBaseLogger)();
1434
+ logger.useDefaults();
1435
+ const sharedSyncImplementation = new _SharedSyncImplementation_js__WEBPACK_IMPORTED_MODULE_1__.SharedSyncImplementation();
1436
+ _self.onconnect = async function (event) {
1437
+ const port = event.ports[0];
1438
+ new _WorkerClient_js__WEBPACK_IMPORTED_MODULE_2__.WorkerClient(sharedSyncImplementation, port);
1439
+ };
1440
+
1441
+
1442
+ /***/ },
1443
+
1444
+ /***/ "./lib/src/worker/sync/WorkerClient.js"
1445
+ /*!*********************************************!*\
1446
+ !*** ./lib/src/worker/sync/WorkerClient.js ***!
1447
+ \*********************************************/
1448
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
1449
+
1450
+ __webpack_require__.r(__webpack_exports__);
1451
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
1452
+ /* harmony export */ WorkerClient: () => (/* binding */ WorkerClient)
1453
+ /* harmony export */ });
1454
+ /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! comlink */ "comlink");
1455
+ /* harmony import */ var _shared_navigator_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../shared/navigator.js */ "./lib/src/shared/navigator.js");
1456
+ /* harmony import */ var _SharedSyncImplementation_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./SharedSyncImplementation.js */ "./lib/src/worker/sync/SharedSyncImplementation.js");
1457
+
1458
+
1459
+
1460
+ /**
1461
+ * A client to the shared sync worker.
1462
+ *
1463
+ * The shared sync implementation needs a per-client view of subscriptions so that subscriptions of closed tabs can
1464
+ * automatically be evicted later.
1465
+ */
1466
+ class WorkerClient {
1467
+ sync;
1468
+ port;
1469
+ resolvedPort = null;
1470
+ resolvedPortPromise = null;
1471
+ constructor(sync, port) {
1472
+ this.sync = sync;
1473
+ this.port = port;
1474
+ comlink__WEBPACK_IMPORTED_MODULE_0__.expose(this, this.port);
1475
+ /**
1476
+ * Adds an extra listener which can remove this port
1477
+ * from the list of monitored ports.
1478
+ */
1479
+ this.port.addEventListener('message', async (event) => {
1480
+ const payload = event.data;
1481
+ if (payload?.event == _SharedSyncImplementation_js__WEBPACK_IMPORTED_MODULE_2__.SharedSyncClientEvent.CLOSE_CLIENT) {
1482
+ await this.removePort();
1483
+ }
1484
+ });
1485
+ }
1486
+ async removePort() {
1487
+ if (this.resolvedPort) {
1488
+ const resolved = this.resolvedPort;
1489
+ this.resolvedPort = null;
1490
+ const release = await this.sync.removePort(resolved);
1491
+ this.resolvedPort = null;
1492
+ this.port.postMessage({
1493
+ event: _SharedSyncImplementation_js__WEBPACK_IMPORTED_MODULE_2__.SharedSyncClientEvent.CLOSE_ACK,
1494
+ data: {}
1495
+ });
1496
+ release?.();
1497
+ }
1498
+ }
1499
+ /**
1500
+ * Called by a client after obtaining a lock with a random name.
1501
+ *
1502
+ * When the client tab is closed, its lock will be returned. So when the shared worker attempts to acquire the lock,
1503
+ * it can consider the connection to be closed.
1504
+ */
1505
+ async addLockBasedCloseSignal(name) {
1506
+ // Only add the port once the lock has been obtained on the client.
1507
+ this.resolvedPort = await this.sync.addPort(this.port);
1508
+ // Don't await this lock request
1509
+ (0,_shared_navigator_js__WEBPACK_IMPORTED_MODULE_1__.getNavigatorLocks)().request(name, async () => {
1510
+ await this.removePort();
1511
+ });
1512
+ }
1513
+ setLogLevel(level) {
1514
+ this.sync.setLogLevel(level);
1515
+ }
1516
+ triggerCrudUpload() {
1517
+ return this.sync.triggerCrudUpload();
1518
+ }
1519
+ setParams(params, subscriptions) {
1520
+ this.resolvedPort.currentSubscriptions = subscriptions;
1521
+ return this.sync.setParams(params);
1522
+ }
1523
+ getWriteCheckpoint() {
1524
+ return this.sync.getWriteCheckpoint();
1525
+ }
1526
+ hasCompletedSync() {
1527
+ return this.sync.hasCompletedSync();
1528
+ }
1529
+ connect(options) {
1530
+ return this.sync.connect(options);
1531
+ }
1532
+ updateSubscriptions(subscriptions) {
1533
+ if (this.resolvedPort) {
1534
+ this.sync.updateSubscriptions(this.resolvedPort, subscriptions);
1535
+ }
1536
+ }
1537
+ disconnect() {
1538
+ return this.sync.disconnect();
1539
+ }
1540
+ }
1541
+
1542
+
1543
+ /***/ },
1544
+
1545
+ /***/ "@journeyapps/wa-sqlite"
1546
+ /*!*****************************************!*\
1547
+ !*** external "@journeyapps/wa-sqlite" ***!
1548
+ \*****************************************/
1549
+ (module) {
1550
+
1551
+ module.exports = __WEBPACK_EXTERNAL_MODULE__journeyapps_wa_sqlite__;
1552
+
1553
+ /***/ },
1554
+
1555
+ /***/ "@journeyapps/wa-sqlite/src/examples/AccessHandlePoolVFS.js"
1556
+ /*!*****************************************************************************!*\
1557
+ !*** external "@journeyapps/wa-sqlite/src/examples/AccessHandlePoolVFS.js" ***!
1558
+ \*****************************************************************************/
1559
+ (module) {
1560
+
1561
+ module.exports = __WEBPACK_EXTERNAL_MODULE__journeyapps_wa_sqlite_src_examples_AccessHandlePoolVFS_js__;
1562
+
1563
+ /***/ },
1564
+
1565
+ /***/ "@journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js"
1566
+ /*!***************************************************************************!*\
1567
+ !*** external "@journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js" ***!
1568
+ \***************************************************************************/
1569
+ (module) {
1570
+
1571
+ module.exports = __WEBPACK_EXTERNAL_MODULE__journeyapps_wa_sqlite_src_examples_IDBBatchAtomicVFS_js__;
1572
+
1573
+ /***/ },
1574
+
1575
+ /***/ "@journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js"
1576
+ /*!*************************************************************************!*\
1577
+ !*** external "@journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js" ***!
1578
+ \*************************************************************************/
1579
+ (module) {
1580
+
1581
+ module.exports = __WEBPACK_EXTERNAL_MODULE__journeyapps_wa_sqlite_src_examples_OPFSCoopSyncVFS_js__;
1582
+
1583
+ /***/ },
1584
+
1585
+ /***/ "@powersync/common"
1586
+ /*!************************************!*\
1587
+ !*** external "@powersync/common" ***!
1588
+ \************************************/
1589
+ (module) {
1590
+
1591
+ module.exports = __WEBPACK_EXTERNAL_MODULE__powersync_common__;
1592
+
1593
+ /***/ },
1594
+
1595
+ /***/ "async-mutex"
1596
+ /*!******************************!*\
1597
+ !*** external "async-mutex" ***!
1598
+ \******************************/
1599
+ (module) {
1600
+
1601
+ module.exports = __WEBPACK_EXTERNAL_MODULE_async_mutex__;
1602
+
1603
+ /***/ },
1604
+
1605
+ /***/ "comlink"
1606
+ /*!**************************!*\
1607
+ !*** external "comlink" ***!
1608
+ \**************************/
1609
+ (module) {
1610
+
1611
+ module.exports = __WEBPACK_EXTERNAL_MODULE_comlink__;
1612
+
1613
+ /***/ }
1614
+
1615
+ /******/ });
1616
+ /************************************************************************/
1617
+ /******/ // The module cache
1618
+ /******/ var __webpack_module_cache__ = {};
1619
+ /******/
1620
+ /******/ // The require function
1621
+ /******/ function __webpack_require__(moduleId) {
1622
+ /******/ // Check if module is in cache
1623
+ /******/ var cachedModule = __webpack_module_cache__[moduleId];
1624
+ /******/ if (cachedModule !== undefined) {
1625
+ /******/ return cachedModule.exports;
1626
+ /******/ }
1627
+ /******/ // Check if module exists (development only)
1628
+ /******/ if (__webpack_modules__[moduleId] === undefined) {
1629
+ /******/ var e = new Error("Cannot find module '" + moduleId + "'");
1630
+ /******/ e.code = 'MODULE_NOT_FOUND';
1631
+ /******/ throw e;
1632
+ /******/ }
1633
+ /******/ // Create a new module (and put it into the cache)
1634
+ /******/ var module = __webpack_module_cache__[moduleId] = {
1635
+ /******/ // no module.id needed
1636
+ /******/ // no module.loaded needed
1637
+ /******/ exports: {}
1638
+ /******/ };
1639
+ /******/
1640
+ /******/ // Execute the module function
1641
+ /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
1642
+ /******/
1643
+ /******/ // Return the exports of the module
1644
+ /******/ return module.exports;
1645
+ /******/ }
1646
+ /******/
1647
+ /******/ // expose the modules object (__webpack_modules__)
1648
+ /******/ __webpack_require__.m = __webpack_modules__;
1649
+ /******/
1650
+ /******/ // the startup function
1651
+ /******/ __webpack_require__.x = () => {
1652
+ /******/ // Load entry module and return exports
1653
+ /******/ // This entry module depends on other loaded chunks and execution need to be delayed
1654
+ /******/ var __webpack_exports__ = __webpack_require__.O(undefined, ["main"], () => (__webpack_require__("./lib/src/worker/sync/SharedSyncImplementation.worker.js")))
1655
+ /******/ __webpack_exports__ = __webpack_require__.O(__webpack_exports__);
1656
+ /******/ return __webpack_exports__;
1657
+ /******/ };
1658
+ /******/
1659
+ /************************************************************************/
1660
+ /******/ /* webpack/runtime/chunk loaded */
1661
+ /******/ (() => {
1662
+ /******/ var deferred = [];
1663
+ /******/ __webpack_require__.O = (result, chunkIds, fn, priority) => {
1664
+ /******/ if(chunkIds) {
1665
+ /******/ priority = priority || 0;
1666
+ /******/ for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
1667
+ /******/ deferred[i] = [chunkIds, fn, priority];
1668
+ /******/ return;
1669
+ /******/ }
1670
+ /******/ var notFulfilled = Infinity;
1671
+ /******/ for (var i = 0; i < deferred.length; i++) {
1672
+ /******/ var [chunkIds, fn, priority] = deferred[i];
1673
+ /******/ var fulfilled = true;
1674
+ /******/ for (var j = 0; j < chunkIds.length; j++) {
1675
+ /******/ if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
1676
+ /******/ chunkIds.splice(j--, 1);
1677
+ /******/ } else {
1678
+ /******/ fulfilled = false;
1679
+ /******/ if(priority < notFulfilled) notFulfilled = priority;
1680
+ /******/ }
1681
+ /******/ }
1682
+ /******/ if(fulfilled) {
1683
+ /******/ deferred.splice(i--, 1)
1684
+ /******/ var r = fn();
1685
+ /******/ if (r !== undefined) result = r;
1686
+ /******/ }
1687
+ /******/ }
1688
+ /******/ return result;
1689
+ /******/ };
1690
+ /******/ })();
1691
+ /******/
1692
+ /******/ /* webpack/runtime/create fake namespace object */
1693
+ /******/ (() => {
1694
+ /******/ var getProto = Object.getPrototypeOf ? (obj) => (Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__);
1695
+ /******/ var leafPrototypes;
1696
+ /******/ // create a fake namespace object
1697
+ /******/ // mode & 1: value is a module id, require it
1698
+ /******/ // mode & 2: merge all properties of value into the ns
1699
+ /******/ // mode & 4: return value when already ns object
1700
+ /******/ // mode & 16: return value when it's Promise-like
1701
+ /******/ // mode & 8|1: behave like require
1702
+ /******/ __webpack_require__.t = function(value, mode) {
1703
+ /******/ if(mode & 1) value = this(value);
1704
+ /******/ if(mode & 8) return value;
1705
+ /******/ if(typeof value === 'object' && value) {
1706
+ /******/ if((mode & 4) && value.__esModule) return value;
1707
+ /******/ if((mode & 16) && typeof value.then === 'function') return value;
1708
+ /******/ }
1709
+ /******/ var ns = Object.create(null);
1710
+ /******/ __webpack_require__.r(ns);
1711
+ /******/ var def = {};
1712
+ /******/ leafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)];
1713
+ /******/ for(var current = mode & 2 && value; (typeof current == 'object' || typeof current == 'function') && !~leafPrototypes.indexOf(current); current = getProto(current)) {
1714
+ /******/ Object.getOwnPropertyNames(current).forEach((key) => (def[key] = () => (value[key])));
1715
+ /******/ }
1716
+ /******/ def['default'] = () => (value);
1717
+ /******/ __webpack_require__.d(ns, def);
1718
+ /******/ return ns;
1719
+ /******/ };
1720
+ /******/ })();
1721
+ /******/
1722
+ /******/ /* webpack/runtime/define property getters */
1723
+ /******/ (() => {
1724
+ /******/ // define getter functions for harmony exports
1725
+ /******/ __webpack_require__.d = (exports, definition) => {
1726
+ /******/ for(var key in definition) {
1727
+ /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
1728
+ /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
1729
+ /******/ }
1730
+ /******/ }
1731
+ /******/ };
1732
+ /******/ })();
1733
+ /******/
1734
+ /******/ /* webpack/runtime/ensure chunk */
1735
+ /******/ (() => {
1736
+ /******/ __webpack_require__.f = {};
1737
+ /******/ // This file contains only the entry chunk.
1738
+ /******/ // The chunk loading function for additional chunks
1739
+ /******/ __webpack_require__.e = (chunkId) => {
1740
+ /******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
1741
+ /******/ __webpack_require__.f[key](chunkId, promises);
1742
+ /******/ return promises;
1743
+ /******/ }, []));
1744
+ /******/ };
1745
+ /******/ })();
1746
+ /******/
1747
+ /******/ /* webpack/runtime/get javascript chunk filename */
1748
+ /******/ (() => {
1749
+ /******/ // This function allow to reference async chunks and chunks that the entrypoint depends on
1750
+ /******/ __webpack_require__.u = (chunkId) => {
1751
+ /******/ // return url for filenames based on template
1752
+ /******/ return undefined;
1753
+ /******/ };
1754
+ /******/ })();
1755
+ /******/
1756
+ /******/ /* webpack/runtime/global */
1757
+ /******/ (() => {
1758
+ /******/ __webpack_require__.g = (function() {
1759
+ /******/ if (typeof globalThis === 'object') return globalThis;
1760
+ /******/ try {
1761
+ /******/ return this || new Function('return this')();
1762
+ /******/ } catch (e) {
1763
+ /******/ if (typeof window === 'object') return window;
1764
+ /******/ }
1765
+ /******/ })();
1766
+ /******/ })();
1767
+ /******/
1768
+ /******/ /* webpack/runtime/hasOwnProperty shorthand */
1769
+ /******/ (() => {
1770
+ /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
1771
+ /******/ })();
1772
+ /******/
1773
+ /******/ /* webpack/runtime/make namespace object */
1774
+ /******/ (() => {
1775
+ /******/ // define __esModule on exports
1776
+ /******/ __webpack_require__.r = (exports) => {
1777
+ /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
1778
+ /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1779
+ /******/ }
1780
+ /******/ Object.defineProperty(exports, '__esModule', { value: true });
1781
+ /******/ };
1782
+ /******/ })();
1783
+ /******/
1784
+ /******/ /* webpack/runtime/publicPath */
1785
+ /******/ (() => {
1786
+ /******/ var scriptUrl;
1787
+ /******/ if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + "";
1788
+ /******/ var document = __webpack_require__.g.document;
1789
+ /******/ if (!scriptUrl && document) {
1790
+ /******/ if (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT')
1791
+ /******/ scriptUrl = document.currentScript.src;
1792
+ /******/ if (!scriptUrl) {
1793
+ /******/ var scripts = document.getElementsByTagName("script");
1794
+ /******/ if(scripts.length) {
1795
+ /******/ var i = scripts.length - 1;
1796
+ /******/ while (i > -1 && (!scriptUrl || !/^http(s?):/.test(scriptUrl))) scriptUrl = scripts[i--].src;
1797
+ /******/ }
1798
+ /******/ }
1799
+ /******/ }
1800
+ /******/ // When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration
1801
+ /******/ // or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic.
1802
+ /******/ if (!scriptUrl) throw new Error("Automatic publicPath is not supported in this browser");
1803
+ /******/ scriptUrl = scriptUrl.replace(/^blob:/, "").replace(/#.*$/, "").replace(/\?.*$/, "").replace(/\/[^\/]+$/, "/");
1804
+ /******/ __webpack_require__.p = scriptUrl;
1805
+ /******/ })();
1806
+ /******/
1807
+ /******/ /* webpack/runtime/importScripts chunk loading */
1808
+ /******/ (() => {
1809
+ /******/ __webpack_require__.b = self.location + "";
1810
+ /******/
1811
+ /******/ // object to store loaded chunks
1812
+ /******/ // "1" means "already loaded"
1813
+ /******/ var installedChunks = {
1814
+ /******/ "_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapp-89f0ba": 1
1815
+ /******/ };
1816
+ /******/
1817
+ /******/ // importScripts chunk loading
1818
+ /******/ var installChunk = (data) => {
1819
+ /******/ var [chunkIds, moreModules, runtime] = data;
1820
+ /******/ for(var moduleId in moreModules) {
1821
+ /******/ if(__webpack_require__.o(moreModules, moduleId)) {
1822
+ /******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
1823
+ /******/ }
1824
+ /******/ }
1825
+ /******/ if(runtime) runtime(__webpack_require__);
1826
+ /******/ while(chunkIds.length)
1827
+ /******/ installedChunks[chunkIds.pop()] = 1;
1828
+ /******/ parentChunkLoadingFunction(data);
1829
+ /******/ };
1830
+ /******/ __webpack_require__.f.i = (chunkId, promises) => {
1831
+ /******/ // "1" is the signal for "already loaded"
1832
+ /******/ if(!installedChunks[chunkId]) {
1833
+ /******/ if(true) { // all chunks have JS
1834
+ /******/ importScripts(__webpack_require__.p + __webpack_require__.u(chunkId));
1835
+ /******/ }
1836
+ /******/ }
1837
+ /******/ };
1838
+ /******/
1839
+ /******/ var chunkLoadingGlobal = self["webpackChunksdk_web"] = self["webpackChunksdk_web"] || [];
1840
+ /******/ var parentChunkLoadingFunction = chunkLoadingGlobal.push.bind(chunkLoadingGlobal);
1841
+ /******/ chunkLoadingGlobal.push = installChunk;
1842
+ /******/
1843
+ /******/ // no HMR
1844
+ /******/
1845
+ /******/ // no HMR manifest
1846
+ /******/ })();
1847
+ /******/
1848
+ /******/ /* webpack/runtime/startup chunk dependencies */
1849
+ /******/ (() => {
1850
+ /******/ var next = __webpack_require__.x;
1851
+ /******/ __webpack_require__.x = () => {
1852
+ /******/ return Promise.all([
1853
+ /******/
1854
+ /******/ ]).then(next);
1855
+ /******/ };
1856
+ /******/ })();
1857
+ /******/
1858
+ /************************************************************************/
1859
+ /******/
1860
+ /******/ // run startup
1861
+ /******/ var __webpack_exports__ = __webpack_require__.x();
1862
+ /******/
1863
+ /******/ return __webpack_exports__;
1864
+ /******/ })()
1865
+ ;
1866
+ });
1867
+ //# sourceMappingURL=_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapp-89f0ba.index.umd.js.map