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