@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.
package/dist/bundle.cjs CHANGED
@@ -1683,6 +1683,49 @@ var Logger = /*@__PURE__*/getDefaultExportFromCjs(loggerExports);
1683
1683
  * Set of generic interfaces to allow PowerSync compatibility with
1684
1684
  * different SQLite DB implementations.
1685
1685
  */
1686
+ /**
1687
+ * Implements {@link DBGetUtils} on a {@link SqlRunner}.
1688
+ */
1689
+ function DBGetUtilsDefaultMixin(Base) {
1690
+ return class extends Base {
1691
+ async getAll(sql, parameters) {
1692
+ const res = await this.execute(sql, parameters);
1693
+ return res.rows?._array ?? [];
1694
+ }
1695
+ async getOptional(sql, parameters) {
1696
+ const res = await this.execute(sql, parameters);
1697
+ return res.rows?.item(0) ?? null;
1698
+ }
1699
+ async get(sql, parameters) {
1700
+ const res = await this.execute(sql, parameters);
1701
+ const first = res.rows?.item(0);
1702
+ if (!first) {
1703
+ throw new Error('Result set is empty');
1704
+ }
1705
+ return first;
1706
+ }
1707
+ async executeBatch(query, params = []) {
1708
+ // If this context can run batch statements natively, use that.
1709
+ // @ts-ignore
1710
+ if (super.executeBatch) {
1711
+ // @ts-ignore
1712
+ return super.executeBatch(query, params);
1713
+ }
1714
+ // Emulate executeBatch by running statements individually.
1715
+ let lastInsertId;
1716
+ let rowsAffected = 0;
1717
+ for (const set of params) {
1718
+ const result = await this.execute(query, set);
1719
+ lastInsertId = result.insertId;
1720
+ rowsAffected += result.rowsAffected;
1721
+ }
1722
+ return {
1723
+ rowsAffected,
1724
+ insertId: lastInsertId
1725
+ };
1726
+ }
1727
+ };
1728
+ }
1686
1729
  /**
1687
1730
  * Update table operation numbers from SQLite
1688
1731
  */
@@ -1692,6 +1735,89 @@ exports.RowUpdateType = void 0;
1692
1735
  RowUpdateType[RowUpdateType["SQLITE_DELETE"] = 9] = "SQLITE_DELETE";
1693
1736
  RowUpdateType[RowUpdateType["SQLITE_UPDATE"] = 23] = "SQLITE_UPDATE";
1694
1737
  })(exports.RowUpdateType || (exports.RowUpdateType = {}));
1738
+ /**
1739
+ * A mixin to implement {@link DBAdapter} by delegating to {@link ConnectionPool.readLock} and
1740
+ * {@link ConnectionPool.writeLock}.
1741
+ */
1742
+ function DBAdapterDefaultMixin(Base) {
1743
+ return class extends Base {
1744
+ readTransaction(fn, options) {
1745
+ return this.readLock((ctx) => TransactionImplementation.runWith(ctx, fn), options);
1746
+ }
1747
+ writeTransaction(fn, options) {
1748
+ return this.writeLock((ctx) => TransactionImplementation.runWith(ctx, fn), options);
1749
+ }
1750
+ getAll(sql, parameters) {
1751
+ return this.readLock((ctx) => ctx.getAll(sql, parameters));
1752
+ }
1753
+ getOptional(sql, parameters) {
1754
+ return this.readLock((ctx) => ctx.getOptional(sql, parameters));
1755
+ }
1756
+ get(sql, parameters) {
1757
+ return this.readLock((ctx) => ctx.get(sql, parameters));
1758
+ }
1759
+ execute(query, params) {
1760
+ return this.writeLock((ctx) => ctx.execute(query, params));
1761
+ }
1762
+ executeRaw(query, params) {
1763
+ return this.writeLock((ctx) => ctx.executeRaw(query, params));
1764
+ }
1765
+ executeBatch(query, params) {
1766
+ return this.writeTransaction((tx) => tx.executeBatch(query, params));
1767
+ }
1768
+ };
1769
+ }
1770
+ class BaseTransaction {
1771
+ inner;
1772
+ finalized = false;
1773
+ constructor(inner) {
1774
+ this.inner = inner;
1775
+ }
1776
+ async commit() {
1777
+ if (this.finalized) {
1778
+ return { rowsAffected: 0 };
1779
+ }
1780
+ this.finalized = true;
1781
+ return this.inner.execute('COMMIT');
1782
+ }
1783
+ async rollback() {
1784
+ if (this.finalized) {
1785
+ return { rowsAffected: 0 };
1786
+ }
1787
+ this.finalized = true;
1788
+ return this.inner.execute('ROLLBACK');
1789
+ }
1790
+ execute(query, params) {
1791
+ return this.inner.execute(query, params);
1792
+ }
1793
+ executeRaw(query, params) {
1794
+ return this.inner.executeRaw(query, params);
1795
+ }
1796
+ executeBatch(query, params) {
1797
+ return this.inner.executeBatch(query, params);
1798
+ }
1799
+ }
1800
+ class TransactionImplementation extends DBGetUtilsDefaultMixin(BaseTransaction) {
1801
+ static async runWith(ctx, fn) {
1802
+ let tx = new TransactionImplementation(ctx);
1803
+ try {
1804
+ await ctx.execute('BEGIN IMMEDIATE');
1805
+ const result = await fn(tx);
1806
+ await tx.commit();
1807
+ return result;
1808
+ }
1809
+ catch (ex) {
1810
+ try {
1811
+ await tx.rollback();
1812
+ }
1813
+ catch (ex2) {
1814
+ // In rare cases, a rollback may fail.
1815
+ // Safe to ignore.
1816
+ }
1817
+ throw ex;
1818
+ }
1819
+ }
1820
+ }
1695
1821
  function isBatchedUpdateNotification(update) {
1696
1822
  return 'tables' in update;
1697
1823
  }
@@ -10457,7 +10583,7 @@ function requireDist () {
10457
10583
 
10458
10584
  var distExports = requireDist();
10459
10585
 
10460
- var version = "1.48.0";
10586
+ var version = "1.49.0";
10461
10587
  var PACKAGE = {
10462
10588
  version: version};
10463
10589
 
@@ -12490,7 +12616,7 @@ class TriggerManagerImpl {
12490
12616
  }
12491
12617
  async createDiffTrigger(options) {
12492
12618
  await this.db.waitForReady();
12493
- const { source, destination, columns, when, hooks,
12619
+ const { source, destination, columns, when, hooks, setupContext,
12494
12620
  // Fall back to the provided default if not given on this level
12495
12621
  useStorage = this.defaultConfig.useStorageByDefault } = options;
12496
12622
  const operations = Object.keys(when);
@@ -12545,13 +12671,20 @@ class TriggerManagerImpl {
12545
12671
  * we need to ensure we can cleanup the created resources.
12546
12672
  * We unfortunately cannot rely on transaction rollback.
12547
12673
  */
12548
- const cleanup = async () => {
12674
+ const cleanup = async (options) => {
12675
+ const { context } = options ?? {};
12549
12676
  disposeWarningListener();
12550
- return this.db.writeLock(async (tx) => {
12677
+ const doCleanup = async (tx) => {
12551
12678
  await this.removeTriggers(tx, triggerIds);
12552
- await tx.execute(/* sql */ `DROP TABLE IF EXISTS ${destination};`);
12679
+ await tx.execute(`DROP TABLE IF EXISTS ${destination};`);
12553
12680
  await releaseStorageClaim?.();
12554
- });
12681
+ };
12682
+ if (context) {
12683
+ await doCleanup(context);
12684
+ }
12685
+ else {
12686
+ await this.db.writeLock(doCleanup);
12687
+ }
12555
12688
  };
12556
12689
  const setup = async (tx) => {
12557
12690
  // Allow user code to execute in this lock context before the trigger is created.
@@ -12625,12 +12758,17 @@ class TriggerManagerImpl {
12625
12758
  }
12626
12759
  };
12627
12760
  try {
12628
- await this.db.writeLock(setup);
12761
+ if (setupContext) {
12762
+ await setup(setupContext);
12763
+ }
12764
+ else {
12765
+ await this.db.writeLock(setup);
12766
+ }
12629
12767
  return cleanup;
12630
12768
  }
12631
12769
  catch (error) {
12632
12770
  try {
12633
- await cleanup();
12771
+ await cleanup(setupContext ? { context: setupContext } : undefined);
12634
12772
  }
12635
12773
  catch (cleanupError) {
12636
12774
  throw new AggregateError([error, cleanupError], 'Error during operation and cleanup');
@@ -14395,6 +14533,8 @@ exports.ControlledExecutor = ControlledExecutor;
14395
14533
  exports.CrudBatch = CrudBatch;
14396
14534
  exports.CrudEntry = CrudEntry;
14397
14535
  exports.CrudTransaction = CrudTransaction;
14536
+ exports.DBAdapterDefaultMixin = DBAdapterDefaultMixin;
14537
+ exports.DBGetUtilsDefaultMixin = DBGetUtilsDefaultMixin;
14398
14538
  exports.DEFAULT_CRUD_BATCH_LIMIT = DEFAULT_CRUD_BATCH_LIMIT;
14399
14539
  exports.DEFAULT_CRUD_UPLOAD_THROTTLE_MS = DEFAULT_CRUD_UPLOAD_THROTTLE_MS;
14400
14540
  exports.DEFAULT_INDEX_COLUMN_OPTIONS = DEFAULT_INDEX_COLUMN_OPTIONS;