@powersync/web 1.35.0 → 1.36.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.
@@ -2475,7 +2475,8 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
2475
2475
  }
2476
2476
  this.dbGetHelpers = this.generateDBHelpers({
2477
2477
  execute: (query, params) => this.acquireLock(() => this._execute(query, params)),
2478
- executeRaw: (query, params) => this.acquireLock(() => this._executeRaw(query, params))
2478
+ executeRaw: (query, params) => this.acquireLock(() => this._executeRaw(query, params)),
2479
+ executeBatch: (query, params) => this.acquireLock(() => this._executeBatch(query, params))
2479
2480
  });
2480
2481
  this.initPromise = this._init();
2481
2482
  }
@@ -2636,14 +2637,16 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
2636
2637
  return this.dbGetHelpers.get(sql, parameters);
2637
2638
  }
2638
2639
  async readLock(fn, options) {
2639
- await this.waitForInitialized();
2640
- return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute, executeRaw: this._executeRaw })), {
2641
- timeoutMs: options?.timeoutMs ?? this.options.defaultLockTimeoutMs
2642
- });
2640
+ // Read and write locks are the same because we only have one underlying connection.
2641
+ return this.writeLock(fn, options);
2643
2642
  }
2644
2643
  async writeLock(fn, options) {
2645
2644
  await this.waitForInitialized();
2646
- return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute, executeRaw: this._executeRaw })), {
2645
+ return this.acquireLock(async () => fn(this.generateDBHelpers({
2646
+ execute: this._execute,
2647
+ executeRaw: this._executeRaw,
2648
+ executeBatch: this._executeBatch
2649
+ })), {
2647
2650
  timeoutMs: options?.timeoutMs ?? this.options.defaultLockTimeoutMs
2648
2651
  });
2649
2652
  }
@@ -4399,6 +4402,8 @@ __webpack_require__.r(__webpack_exports__);
4399
4402
  /* harmony export */ CrudBatch: () => (/* binding */ CrudBatch),
4400
4403
  /* harmony export */ CrudEntry: () => (/* binding */ CrudEntry),
4401
4404
  /* harmony export */ CrudTransaction: () => (/* binding */ CrudTransaction),
4405
+ /* harmony export */ DBAdapterDefaultMixin: () => (/* binding */ DBAdapterDefaultMixin),
4406
+ /* harmony export */ DBGetUtilsDefaultMixin: () => (/* binding */ DBGetUtilsDefaultMixin),
4402
4407
  /* harmony export */ DEFAULT_CRUD_BATCH_LIMIT: () => (/* binding */ DEFAULT_CRUD_BATCH_LIMIT),
4403
4408
  /* harmony export */ DEFAULT_CRUD_UPLOAD_THROTTLE_MS: () => (/* binding */ DEFAULT_CRUD_UPLOAD_THROTTLE_MS),
4404
4409
  /* harmony export */ DEFAULT_INDEX_COLUMN_OPTIONS: () => (/* binding */ DEFAULT_INDEX_COLUMN_OPTIONS),
@@ -6165,6 +6170,49 @@ var Logger = /*@__PURE__*/getDefaultExportFromCjs(loggerExports);
6165
6170
  * Set of generic interfaces to allow PowerSync compatibility with
6166
6171
  * different SQLite DB implementations.
6167
6172
  */
6173
+ /**
6174
+ * Implements {@link DBGetUtils} on a {@link SqlRunner}.
6175
+ */
6176
+ function DBGetUtilsDefaultMixin(Base) {
6177
+ return class extends Base {
6178
+ async getAll(sql, parameters) {
6179
+ const res = await this.execute(sql, parameters);
6180
+ return res.rows?._array ?? [];
6181
+ }
6182
+ async getOptional(sql, parameters) {
6183
+ const res = await this.execute(sql, parameters);
6184
+ return res.rows?.item(0) ?? null;
6185
+ }
6186
+ async get(sql, parameters) {
6187
+ const res = await this.execute(sql, parameters);
6188
+ const first = res.rows?.item(0);
6189
+ if (!first) {
6190
+ throw new Error('Result set is empty');
6191
+ }
6192
+ return first;
6193
+ }
6194
+ async executeBatch(query, params = []) {
6195
+ // If this context can run batch statements natively, use that.
6196
+ // @ts-ignore
6197
+ if (super.executeBatch) {
6198
+ // @ts-ignore
6199
+ return super.executeBatch(query, params);
6200
+ }
6201
+ // Emulate executeBatch by running statements individually.
6202
+ let lastInsertId;
6203
+ let rowsAffected = 0;
6204
+ for (const set of params) {
6205
+ const result = await this.execute(query, set);
6206
+ lastInsertId = result.insertId;
6207
+ rowsAffected += result.rowsAffected;
6208
+ }
6209
+ return {
6210
+ rowsAffected,
6211
+ insertId: lastInsertId
6212
+ };
6213
+ }
6214
+ };
6215
+ }
6168
6216
  /**
6169
6217
  * Update table operation numbers from SQLite
6170
6218
  */
@@ -6174,6 +6222,89 @@ var RowUpdateType;
6174
6222
  RowUpdateType[RowUpdateType["SQLITE_DELETE"] = 9] = "SQLITE_DELETE";
6175
6223
  RowUpdateType[RowUpdateType["SQLITE_UPDATE"] = 23] = "SQLITE_UPDATE";
6176
6224
  })(RowUpdateType || (RowUpdateType = {}));
6225
+ /**
6226
+ * A mixin to implement {@link DBAdapter} by delegating to {@link ConnectionPool.readLock} and
6227
+ * {@link ConnectionPool.writeLock}.
6228
+ */
6229
+ function DBAdapterDefaultMixin(Base) {
6230
+ return class extends Base {
6231
+ readTransaction(fn, options) {
6232
+ return this.readLock((ctx) => TransactionImplementation.runWith(ctx, fn), options);
6233
+ }
6234
+ writeTransaction(fn, options) {
6235
+ return this.writeLock((ctx) => TransactionImplementation.runWith(ctx, fn), options);
6236
+ }
6237
+ getAll(sql, parameters) {
6238
+ return this.readLock((ctx) => ctx.getAll(sql, parameters));
6239
+ }
6240
+ getOptional(sql, parameters) {
6241
+ return this.readLock((ctx) => ctx.getOptional(sql, parameters));
6242
+ }
6243
+ get(sql, parameters) {
6244
+ return this.readLock((ctx) => ctx.get(sql, parameters));
6245
+ }
6246
+ execute(query, params) {
6247
+ return this.writeLock((ctx) => ctx.execute(query, params));
6248
+ }
6249
+ executeRaw(query, params) {
6250
+ return this.writeLock((ctx) => ctx.executeRaw(query, params));
6251
+ }
6252
+ executeBatch(query, params) {
6253
+ return this.writeTransaction((tx) => tx.executeBatch(query, params));
6254
+ }
6255
+ };
6256
+ }
6257
+ class BaseTransaction {
6258
+ inner;
6259
+ finalized = false;
6260
+ constructor(inner) {
6261
+ this.inner = inner;
6262
+ }
6263
+ async commit() {
6264
+ if (this.finalized) {
6265
+ return { rowsAffected: 0 };
6266
+ }
6267
+ this.finalized = true;
6268
+ return this.inner.execute('COMMIT');
6269
+ }
6270
+ async rollback() {
6271
+ if (this.finalized) {
6272
+ return { rowsAffected: 0 };
6273
+ }
6274
+ this.finalized = true;
6275
+ return this.inner.execute('ROLLBACK');
6276
+ }
6277
+ execute(query, params) {
6278
+ return this.inner.execute(query, params);
6279
+ }
6280
+ executeRaw(query, params) {
6281
+ return this.inner.executeRaw(query, params);
6282
+ }
6283
+ executeBatch(query, params) {
6284
+ return this.inner.executeBatch(query, params);
6285
+ }
6286
+ }
6287
+ class TransactionImplementation extends DBGetUtilsDefaultMixin(BaseTransaction) {
6288
+ static async runWith(ctx, fn) {
6289
+ let tx = new TransactionImplementation(ctx);
6290
+ try {
6291
+ await ctx.execute('BEGIN IMMEDIATE');
6292
+ const result = await fn(tx);
6293
+ await tx.commit();
6294
+ return result;
6295
+ }
6296
+ catch (ex) {
6297
+ try {
6298
+ await tx.rollback();
6299
+ }
6300
+ catch (ex2) {
6301
+ // In rare cases, a rollback may fail.
6302
+ // Safe to ignore.
6303
+ }
6304
+ throw ex;
6305
+ }
6306
+ }
6307
+ }
6177
6308
  function isBatchedUpdateNotification(update) {
6178
6309
  return 'tables' in update;
6179
6310
  }
@@ -14939,7 +15070,7 @@ function requireDist () {
14939
15070
 
14940
15071
  var distExports = requireDist();
14941
15072
 
14942
- var version = "1.48.0";
15073
+ var version = "1.49.0";
14943
15074
  var PACKAGE = {
14944
15075
  version: version};
14945
15076
 
@@ -16972,7 +17103,7 @@ class TriggerManagerImpl {
16972
17103
  }
16973
17104
  async createDiffTrigger(options) {
16974
17105
  await this.db.waitForReady();
16975
- const { source, destination, columns, when, hooks,
17106
+ const { source, destination, columns, when, hooks, setupContext,
16976
17107
  // Fall back to the provided default if not given on this level
16977
17108
  useStorage = this.defaultConfig.useStorageByDefault } = options;
16978
17109
  const operations = Object.keys(when);
@@ -17027,13 +17158,20 @@ class TriggerManagerImpl {
17027
17158
  * we need to ensure we can cleanup the created resources.
17028
17159
  * We unfortunately cannot rely on transaction rollback.
17029
17160
  */
17030
- const cleanup = async () => {
17161
+ const cleanup = async (options) => {
17162
+ const { context } = options ?? {};
17031
17163
  disposeWarningListener();
17032
- return this.db.writeLock(async (tx) => {
17164
+ const doCleanup = async (tx) => {
17033
17165
  await this.removeTriggers(tx, triggerIds);
17034
- await tx.execute(/* sql */ `DROP TABLE IF EXISTS ${destination};`);
17166
+ await tx.execute(`DROP TABLE IF EXISTS ${destination};`);
17035
17167
  await releaseStorageClaim?.();
17036
- });
17168
+ };
17169
+ if (context) {
17170
+ await doCleanup(context);
17171
+ }
17172
+ else {
17173
+ await this.db.writeLock(doCleanup);
17174
+ }
17037
17175
  };
17038
17176
  const setup = async (tx) => {
17039
17177
  // Allow user code to execute in this lock context before the trigger is created.
@@ -17107,12 +17245,17 @@ class TriggerManagerImpl {
17107
17245
  }
17108
17246
  };
17109
17247
  try {
17110
- await this.db.writeLock(setup);
17248
+ if (setupContext) {
17249
+ await setup(setupContext);
17250
+ }
17251
+ else {
17252
+ await this.db.writeLock(setup);
17253
+ }
17111
17254
  return cleanup;
17112
17255
  }
17113
17256
  catch (error) {
17114
17257
  try {
17115
- await cleanup();
17258
+ await cleanup(setupContext ? { context: setupContext } : undefined);
17116
17259
  }
17117
17260
  catch (cleanupError) {
17118
17261
  throw new AggregateError([error, cleanupError], 'Error during operation and cleanup');