@powersync/common 1.48.0 → 1.49.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.
@@ -1532,6 +1532,49 @@ var Logger = /*@__PURE__*/getDefaultExportFromCjs(loggerExports);
1532
1532
  * Set of generic interfaces to allow PowerSync compatibility with
1533
1533
  * different SQLite DB implementations.
1534
1534
  */
1535
+ /**
1536
+ * Implements {@link DBGetUtils} on a {@link SqlRunner}.
1537
+ */
1538
+ function DBGetUtilsDefaultMixin(Base) {
1539
+ return class extends Base {
1540
+ async getAll(sql, parameters) {
1541
+ const res = await this.execute(sql, parameters);
1542
+ return res.rows?._array ?? [];
1543
+ }
1544
+ async getOptional(sql, parameters) {
1545
+ const res = await this.execute(sql, parameters);
1546
+ return res.rows?.item(0) ?? null;
1547
+ }
1548
+ async get(sql, parameters) {
1549
+ const res = await this.execute(sql, parameters);
1550
+ const first = res.rows?.item(0);
1551
+ if (!first) {
1552
+ throw new Error('Result set is empty');
1553
+ }
1554
+ return first;
1555
+ }
1556
+ async executeBatch(query, params = []) {
1557
+ // If this context can run batch statements natively, use that.
1558
+ // @ts-ignore
1559
+ if (super.executeBatch) {
1560
+ // @ts-ignore
1561
+ return super.executeBatch(query, params);
1562
+ }
1563
+ // Emulate executeBatch by running statements individually.
1564
+ let lastInsertId;
1565
+ let rowsAffected = 0;
1566
+ for (const set of params) {
1567
+ const result = await this.execute(query, set);
1568
+ lastInsertId = result.insertId;
1569
+ rowsAffected += result.rowsAffected;
1570
+ }
1571
+ return {
1572
+ rowsAffected,
1573
+ insertId: lastInsertId
1574
+ };
1575
+ }
1576
+ };
1577
+ }
1535
1578
  /**
1536
1579
  * Update table operation numbers from SQLite
1537
1580
  */
@@ -1541,6 +1584,89 @@ exports.RowUpdateType = void 0;
1541
1584
  RowUpdateType[RowUpdateType["SQLITE_DELETE"] = 9] = "SQLITE_DELETE";
1542
1585
  RowUpdateType[RowUpdateType["SQLITE_UPDATE"] = 23] = "SQLITE_UPDATE";
1543
1586
  })(exports.RowUpdateType || (exports.RowUpdateType = {}));
1587
+ /**
1588
+ * A mixin to implement {@link DBAdapter} by delegating to {@link ConnectionPool.readLock} and
1589
+ * {@link ConnectionPool.writeLock}.
1590
+ */
1591
+ function DBAdapterDefaultMixin(Base) {
1592
+ return class extends Base {
1593
+ readTransaction(fn, options) {
1594
+ return this.readLock((ctx) => TransactionImplementation.runWith(ctx, fn), options);
1595
+ }
1596
+ writeTransaction(fn, options) {
1597
+ return this.writeLock((ctx) => TransactionImplementation.runWith(ctx, fn), options);
1598
+ }
1599
+ getAll(sql, parameters) {
1600
+ return this.readLock((ctx) => ctx.getAll(sql, parameters));
1601
+ }
1602
+ getOptional(sql, parameters) {
1603
+ return this.readLock((ctx) => ctx.getOptional(sql, parameters));
1604
+ }
1605
+ get(sql, parameters) {
1606
+ return this.readLock((ctx) => ctx.get(sql, parameters));
1607
+ }
1608
+ execute(query, params) {
1609
+ return this.writeLock((ctx) => ctx.execute(query, params));
1610
+ }
1611
+ executeRaw(query, params) {
1612
+ return this.writeLock((ctx) => ctx.executeRaw(query, params));
1613
+ }
1614
+ executeBatch(query, params) {
1615
+ return this.writeTransaction((tx) => tx.executeBatch(query, params));
1616
+ }
1617
+ };
1618
+ }
1619
+ class BaseTransaction {
1620
+ inner;
1621
+ finalized = false;
1622
+ constructor(inner) {
1623
+ this.inner = inner;
1624
+ }
1625
+ async commit() {
1626
+ if (this.finalized) {
1627
+ return { rowsAffected: 0 };
1628
+ }
1629
+ this.finalized = true;
1630
+ return this.inner.execute('COMMIT');
1631
+ }
1632
+ async rollback() {
1633
+ if (this.finalized) {
1634
+ return { rowsAffected: 0 };
1635
+ }
1636
+ this.finalized = true;
1637
+ return this.inner.execute('ROLLBACK');
1638
+ }
1639
+ execute(query, params) {
1640
+ return this.inner.execute(query, params);
1641
+ }
1642
+ executeRaw(query, params) {
1643
+ return this.inner.executeRaw(query, params);
1644
+ }
1645
+ executeBatch(query, params) {
1646
+ return this.inner.executeBatch(query, params);
1647
+ }
1648
+ }
1649
+ class TransactionImplementation extends DBGetUtilsDefaultMixin(BaseTransaction) {
1650
+ static async runWith(ctx, fn) {
1651
+ let tx = new TransactionImplementation(ctx);
1652
+ try {
1653
+ await ctx.execute('BEGIN IMMEDIATE');
1654
+ const result = await fn(tx);
1655
+ await tx.commit();
1656
+ return result;
1657
+ }
1658
+ catch (ex) {
1659
+ try {
1660
+ await tx.rollback();
1661
+ }
1662
+ catch (ex2) {
1663
+ // In rare cases, a rollback may fail.
1664
+ // Safe to ignore.
1665
+ }
1666
+ throw ex;
1667
+ }
1668
+ }
1669
+ }
1544
1670
  function isBatchedUpdateNotification(update) {
1545
1671
  return 'tables' in update;
1546
1672
  }
@@ -7935,7 +8061,7 @@ function requireDist () {
7935
8061
 
7936
8062
  var distExports = requireDist();
7937
8063
 
7938
- var version = "1.48.0";
8064
+ var version = "1.49.0";
7939
8065
  var PACKAGE = {
7940
8066
  version: version};
7941
8067
 
@@ -9968,7 +10094,7 @@ class TriggerManagerImpl {
9968
10094
  }
9969
10095
  async createDiffTrigger(options) {
9970
10096
  await this.db.waitForReady();
9971
- const { source, destination, columns, when, hooks,
10097
+ const { source, destination, columns, when, hooks, setupContext,
9972
10098
  // Fall back to the provided default if not given on this level
9973
10099
  useStorage = this.defaultConfig.useStorageByDefault } = options;
9974
10100
  const operations = Object.keys(when);
@@ -10023,13 +10149,20 @@ class TriggerManagerImpl {
10023
10149
  * we need to ensure we can cleanup the created resources.
10024
10150
  * We unfortunately cannot rely on transaction rollback.
10025
10151
  */
10026
- const cleanup = async () => {
10152
+ const cleanup = async (options) => {
10153
+ const { context } = options ?? {};
10027
10154
  disposeWarningListener();
10028
- return this.db.writeLock(async (tx) => {
10155
+ const doCleanup = async (tx) => {
10029
10156
  await this.removeTriggers(tx, triggerIds);
10030
- await tx.execute(/* sql */ `DROP TABLE IF EXISTS ${destination};`);
10157
+ await tx.execute(`DROP TABLE IF EXISTS ${destination};`);
10031
10158
  await releaseStorageClaim?.();
10032
- });
10159
+ };
10160
+ if (context) {
10161
+ await doCleanup(context);
10162
+ }
10163
+ else {
10164
+ await this.db.writeLock(doCleanup);
10165
+ }
10033
10166
  };
10034
10167
  const setup = async (tx) => {
10035
10168
  // Allow user code to execute in this lock context before the trigger is created.
@@ -10103,12 +10236,17 @@ class TriggerManagerImpl {
10103
10236
  }
10104
10237
  };
10105
10238
  try {
10106
- await this.db.writeLock(setup);
10239
+ if (setupContext) {
10240
+ await setup(setupContext);
10241
+ }
10242
+ else {
10243
+ await this.db.writeLock(setup);
10244
+ }
10107
10245
  return cleanup;
10108
10246
  }
10109
10247
  catch (error) {
10110
10248
  try {
10111
- await cleanup();
10249
+ await cleanup(setupContext ? { context: setupContext } : undefined);
10112
10250
  }
10113
10251
  catch (cleanupError) {
10114
10252
  throw new AggregateError([error, cleanupError], 'Error during operation and cleanup');
@@ -11873,6 +12011,8 @@ exports.ControlledExecutor = ControlledExecutor;
11873
12011
  exports.CrudBatch = CrudBatch;
11874
12012
  exports.CrudEntry = CrudEntry;
11875
12013
  exports.CrudTransaction = CrudTransaction;
12014
+ exports.DBAdapterDefaultMixin = DBAdapterDefaultMixin;
12015
+ exports.DBGetUtilsDefaultMixin = DBGetUtilsDefaultMixin;
11876
12016
  exports.DEFAULT_CRUD_BATCH_LIMIT = DEFAULT_CRUD_BATCH_LIMIT;
11877
12017
  exports.DEFAULT_CRUD_UPLOAD_THROTTLE_MS = DEFAULT_CRUD_UPLOAD_THROTTLE_MS;
11878
12018
  exports.DEFAULT_INDEX_COLUMN_OPTIONS = DEFAULT_INDEX_COLUMN_OPTIONS;