@powersync/common 1.48.0 → 1.50.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 +270 -46
- package/dist/bundle.cjs.map +1 -1
- package/dist/bundle.mjs +265 -44
- package/dist/bundle.mjs.map +1 -1
- package/dist/bundle.node.cjs +270 -45
- package/dist/bundle.node.cjs.map +1 -1
- package/dist/bundle.node.mjs +265 -43
- package/dist/bundle.node.mjs.map +1 -1
- package/dist/index.d.cts +108 -26
- package/lib/attachments/AttachmentQueue.d.ts +10 -4
- package/lib/attachments/AttachmentQueue.js +10 -4
- package/lib/attachments/AttachmentQueue.js.map +1 -1
- package/lib/attachments/AttachmentService.js +2 -3
- package/lib/attachments/AttachmentService.js.map +1 -1
- package/lib/attachments/SyncingService.d.ts +2 -1
- package/lib/attachments/SyncingService.js +4 -5
- package/lib/attachments/SyncingService.js.map +1 -1
- package/lib/client/AbstractPowerSyncDatabase.d.ts +5 -1
- package/lib/client/AbstractPowerSyncDatabase.js +6 -2
- package/lib/client/AbstractPowerSyncDatabase.js.map +1 -1
- package/lib/client/triggers/TriggerManager.d.ts +13 -1
- package/lib/client/triggers/TriggerManagerImpl.d.ts +2 -2
- package/lib/client/triggers/TriggerManagerImpl.js +19 -7
- package/lib/client/triggers/TriggerManagerImpl.js.map +1 -1
- package/lib/db/DBAdapter.d.ts +55 -9
- package/lib/db/DBAdapter.js +126 -0
- package/lib/db/DBAdapter.js.map +1 -1
- package/lib/utils/mutex.d.ts +18 -5
- package/lib/utils/mutex.js +97 -21
- package/lib/utils/mutex.js.map +1 -1
- package/package.json +1 -2
- package/src/attachments/AttachmentQueue.ts +10 -4
- package/src/attachments/AttachmentService.ts +2 -3
- package/src/attachments/README.md +6 -4
- package/src/attachments/SyncingService.ts +4 -5
- package/src/client/AbstractPowerSyncDatabase.ts +6 -2
- package/src/client/triggers/TriggerManager.ts +15 -2
- package/src/client/triggers/TriggerManagerImpl.ts +18 -6
- package/src/db/DBAdapter.ts +167 -9
- package/src/utils/mutex.ts +121 -26
package/dist/bundle.cjs
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var asyncMutex = require('async-mutex');
|
|
4
|
-
|
|
5
3
|
// https://www.sqlite.org/lang_expr.html#castexpr
|
|
6
4
|
exports.ColumnType = void 0;
|
|
7
5
|
(function (ColumnType) {
|
|
@@ -659,7 +657,7 @@ class SyncingService {
|
|
|
659
657
|
updatedAttachments.push(downloaded);
|
|
660
658
|
break;
|
|
661
659
|
case exports.AttachmentState.QUEUED_DELETE:
|
|
662
|
-
const deleted = await this.deleteAttachment(attachment);
|
|
660
|
+
const deleted = await this.deleteAttachment(attachment, context);
|
|
663
661
|
updatedAttachments.push(deleted);
|
|
664
662
|
break;
|
|
665
663
|
}
|
|
@@ -737,17 +735,16 @@ class SyncingService {
|
|
|
737
735
|
* On failure, defers to error handler or archives.
|
|
738
736
|
*
|
|
739
737
|
* @param attachment - The attachment record to delete
|
|
738
|
+
* @param context - Attachment context for database operations
|
|
740
739
|
* @returns Updated attachment record
|
|
741
740
|
*/
|
|
742
|
-
async deleteAttachment(attachment) {
|
|
741
|
+
async deleteAttachment(attachment, context) {
|
|
743
742
|
try {
|
|
744
743
|
await this.remoteStorage.deleteFile(attachment);
|
|
745
744
|
if (attachment.localUri) {
|
|
746
745
|
await this.localStorage.deleteFile(attachment.localUri);
|
|
747
746
|
}
|
|
748
|
-
await
|
|
749
|
-
await ctx.deleteAttachment(attachment.id);
|
|
750
|
-
});
|
|
747
|
+
await context.deleteAttachment(attachment.id);
|
|
751
748
|
return {
|
|
752
749
|
...attachment,
|
|
753
750
|
state: exports.AttachmentState.ARCHIVED
|
|
@@ -785,32 +782,108 @@ class SyncingService {
|
|
|
785
782
|
}
|
|
786
783
|
|
|
787
784
|
/**
|
|
788
|
-
*
|
|
785
|
+
* An asynchronous mutex implementation.
|
|
786
|
+
*
|
|
787
|
+
* @internal This class is meant to be used in PowerSync SDKs only, and is not part of the public API.
|
|
789
788
|
*/
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
789
|
+
class Mutex {
|
|
790
|
+
inCriticalSection = false;
|
|
791
|
+
// Linked list of waiters. We don't expect the wait list to become particularly large, and this allows removing
|
|
792
|
+
// aborted waiters from the middle of the list efficiently.
|
|
793
|
+
firstWaiter;
|
|
794
|
+
lastWaiter;
|
|
795
|
+
addWaiter(onAcquire) {
|
|
796
|
+
const node = {
|
|
797
|
+
isActive: true,
|
|
798
|
+
onAcquire,
|
|
799
|
+
prev: this.lastWaiter
|
|
800
|
+
};
|
|
801
|
+
if (this.lastWaiter) {
|
|
802
|
+
this.lastWaiter.next = node;
|
|
803
|
+
this.lastWaiter = node;
|
|
804
|
+
}
|
|
805
|
+
else {
|
|
806
|
+
// First waiter
|
|
807
|
+
this.lastWaiter = this.firstWaiter = node;
|
|
808
|
+
}
|
|
809
|
+
return node;
|
|
810
|
+
}
|
|
811
|
+
deactivateWaiter(waiter) {
|
|
812
|
+
const { prev, next } = waiter;
|
|
813
|
+
waiter.isActive = false;
|
|
814
|
+
if (prev)
|
|
815
|
+
prev.next = next;
|
|
816
|
+
if (next)
|
|
817
|
+
next.prev = prev;
|
|
818
|
+
if (waiter == this.firstWaiter)
|
|
819
|
+
this.firstWaiter = next;
|
|
820
|
+
if (waiter == this.lastWaiter)
|
|
821
|
+
this.lastWaiter = prev;
|
|
822
|
+
}
|
|
823
|
+
acquire(abort) {
|
|
824
|
+
return new Promise((resolve, reject) => {
|
|
825
|
+
function rejectAborted() {
|
|
826
|
+
reject(abort?.reason ?? new Error('Mutex acquire aborted'));
|
|
808
827
|
}
|
|
809
|
-
|
|
810
|
-
|
|
828
|
+
if (abort?.aborted) {
|
|
829
|
+
return rejectAborted();
|
|
830
|
+
}
|
|
831
|
+
let holdsMutex = false;
|
|
832
|
+
const markCompleted = () => {
|
|
833
|
+
if (!holdsMutex)
|
|
834
|
+
return;
|
|
835
|
+
holdsMutex = false;
|
|
836
|
+
const waiter = this.firstWaiter;
|
|
837
|
+
if (waiter) {
|
|
838
|
+
this.deactivateWaiter(waiter);
|
|
839
|
+
// Still in critical section, but owned by next waiter now.
|
|
840
|
+
waiter.onAcquire();
|
|
841
|
+
}
|
|
842
|
+
else {
|
|
843
|
+
this.inCriticalSection = false;
|
|
844
|
+
}
|
|
845
|
+
};
|
|
846
|
+
if (!this.inCriticalSection) {
|
|
847
|
+
this.inCriticalSection = true;
|
|
848
|
+
holdsMutex = true;
|
|
849
|
+
return resolve(markCompleted);
|
|
850
|
+
}
|
|
851
|
+
else {
|
|
852
|
+
let node;
|
|
853
|
+
const onAbort = () => {
|
|
854
|
+
abort?.removeEventListener('abort', onAbort);
|
|
855
|
+
if (node.isActive) {
|
|
856
|
+
this.deactivateWaiter(node);
|
|
857
|
+
rejectAborted();
|
|
858
|
+
}
|
|
859
|
+
};
|
|
860
|
+
node = this.addWaiter(() => {
|
|
861
|
+
abort?.removeEventListener('abort', onAbort);
|
|
862
|
+
holdsMutex = true;
|
|
863
|
+
resolve(markCompleted);
|
|
864
|
+
});
|
|
865
|
+
abort?.addEventListener('abort', onAbort);
|
|
811
866
|
}
|
|
812
867
|
});
|
|
813
|
-
}
|
|
868
|
+
}
|
|
869
|
+
async runExclusive(fn, abort) {
|
|
870
|
+
const returnMutex = await this.acquire(abort);
|
|
871
|
+
try {
|
|
872
|
+
return await fn();
|
|
873
|
+
}
|
|
874
|
+
finally {
|
|
875
|
+
returnMutex();
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
function timeoutSignal(timeout) {
|
|
880
|
+
if (timeout == null)
|
|
881
|
+
return;
|
|
882
|
+
if ('timeout' in AbortSignal)
|
|
883
|
+
return AbortSignal.timeout(timeout);
|
|
884
|
+
const controller = new AbortController();
|
|
885
|
+
setTimeout(() => controller.abort(new Error('Timeout waiting for lock')), timeout);
|
|
886
|
+
return controller.signal;
|
|
814
887
|
}
|
|
815
888
|
|
|
816
889
|
/**
|
|
@@ -822,7 +895,7 @@ class AttachmentService {
|
|
|
822
895
|
db;
|
|
823
896
|
logger;
|
|
824
897
|
tableName;
|
|
825
|
-
mutex = new
|
|
898
|
+
mutex = new Mutex();
|
|
826
899
|
context;
|
|
827
900
|
constructor(db, logger, tableName = 'attachments', archivedCacheLimit = 100) {
|
|
828
901
|
this.db = db;
|
|
@@ -859,7 +932,7 @@ class AttachmentService {
|
|
|
859
932
|
* Executes a callback with exclusive access to the attachment context.
|
|
860
933
|
*/
|
|
861
934
|
async withContext(callback) {
|
|
862
|
-
return
|
|
935
|
+
return this.mutex.runExclusive(async () => {
|
|
863
936
|
return callback(this.context);
|
|
864
937
|
});
|
|
865
938
|
}
|
|
@@ -895,9 +968,15 @@ class AttachmentQueue {
|
|
|
895
968
|
tableName;
|
|
896
969
|
/** Logger instance for diagnostic information */
|
|
897
970
|
logger;
|
|
898
|
-
/** Interval in milliseconds between periodic sync operations.
|
|
971
|
+
/** Interval in milliseconds between periodic sync operations. Acts as a polling timer to retry
|
|
972
|
+
* failed uploads/downloads, especially after the app goes offline. Default: 30000 (30 seconds) */
|
|
899
973
|
syncIntervalMs = 30 * 1000;
|
|
900
|
-
/**
|
|
974
|
+
/** Throttle duration in milliseconds for the reactive watch query on the attachments table.
|
|
975
|
+
* When attachment records change, a watch query detects the change and triggers a sync.
|
|
976
|
+
* This throttle prevents the sync from firing too rapidly when many changes happen in
|
|
977
|
+
* quick succession (e.g., bulk inserts). This is distinct from syncIntervalMs — it controls
|
|
978
|
+
* how quickly the queue reacts to changes, while syncIntervalMs controls how often it polls
|
|
979
|
+
* for retries. Default: 30 (from DEFAULT_WATCH_THROTTLE_MS) */
|
|
901
980
|
syncThrottleDuration;
|
|
902
981
|
/** Whether to automatically download remote attachments. Default: true */
|
|
903
982
|
downloadAttachments = true;
|
|
@@ -921,8 +1000,8 @@ class AttachmentQueue {
|
|
|
921
1000
|
* @param options.watchAttachments - Callback for monitoring attachment changes in your data model
|
|
922
1001
|
* @param options.tableName - Name of the table to store attachment records. Default: 'ps_attachment_queue'
|
|
923
1002
|
* @param options.logger - Logger instance. Defaults to db.logger
|
|
924
|
-
* @param options.syncIntervalMs -
|
|
925
|
-
* @param options.syncThrottleDuration - Throttle duration for
|
|
1003
|
+
* @param options.syncIntervalMs - Periodic polling interval in milliseconds for retrying failed uploads/downloads. Default: 30000
|
|
1004
|
+
* @param options.syncThrottleDuration - Throttle duration in milliseconds for the reactive watch query that detects attachment changes. Prevents rapid-fire syncs during bulk changes. Default: 30
|
|
926
1005
|
* @param options.downloadAttachments - Whether to automatically download remote attachments. Default: true
|
|
927
1006
|
* @param options.archivedCacheLimit - Maximum archived attachments before cleanup. Default: 100
|
|
928
1007
|
*/
|
|
@@ -1683,6 +1762,49 @@ var Logger = /*@__PURE__*/getDefaultExportFromCjs(loggerExports);
|
|
|
1683
1762
|
* Set of generic interfaces to allow PowerSync compatibility with
|
|
1684
1763
|
* different SQLite DB implementations.
|
|
1685
1764
|
*/
|
|
1765
|
+
/**
|
|
1766
|
+
* Implements {@link DBGetUtils} on a {@link SqlRunner}.
|
|
1767
|
+
*/
|
|
1768
|
+
function DBGetUtilsDefaultMixin(Base) {
|
|
1769
|
+
return class extends Base {
|
|
1770
|
+
async getAll(sql, parameters) {
|
|
1771
|
+
const res = await this.execute(sql, parameters);
|
|
1772
|
+
return res.rows?._array ?? [];
|
|
1773
|
+
}
|
|
1774
|
+
async getOptional(sql, parameters) {
|
|
1775
|
+
const res = await this.execute(sql, parameters);
|
|
1776
|
+
return res.rows?.item(0) ?? null;
|
|
1777
|
+
}
|
|
1778
|
+
async get(sql, parameters) {
|
|
1779
|
+
const res = await this.execute(sql, parameters);
|
|
1780
|
+
const first = res.rows?.item(0);
|
|
1781
|
+
if (!first) {
|
|
1782
|
+
throw new Error('Result set is empty');
|
|
1783
|
+
}
|
|
1784
|
+
return first;
|
|
1785
|
+
}
|
|
1786
|
+
async executeBatch(query, params = []) {
|
|
1787
|
+
// If this context can run batch statements natively, use that.
|
|
1788
|
+
// @ts-ignore
|
|
1789
|
+
if (super.executeBatch) {
|
|
1790
|
+
// @ts-ignore
|
|
1791
|
+
return super.executeBatch(query, params);
|
|
1792
|
+
}
|
|
1793
|
+
// Emulate executeBatch by running statements individually.
|
|
1794
|
+
let lastInsertId;
|
|
1795
|
+
let rowsAffected = 0;
|
|
1796
|
+
for (const set of params) {
|
|
1797
|
+
const result = await this.execute(query, set);
|
|
1798
|
+
lastInsertId = result.insertId;
|
|
1799
|
+
rowsAffected += result.rowsAffected;
|
|
1800
|
+
}
|
|
1801
|
+
return {
|
|
1802
|
+
rowsAffected,
|
|
1803
|
+
insertId: lastInsertId
|
|
1804
|
+
};
|
|
1805
|
+
}
|
|
1806
|
+
};
|
|
1807
|
+
}
|
|
1686
1808
|
/**
|
|
1687
1809
|
* Update table operation numbers from SQLite
|
|
1688
1810
|
*/
|
|
@@ -1692,6 +1814,89 @@ exports.RowUpdateType = void 0;
|
|
|
1692
1814
|
RowUpdateType[RowUpdateType["SQLITE_DELETE"] = 9] = "SQLITE_DELETE";
|
|
1693
1815
|
RowUpdateType[RowUpdateType["SQLITE_UPDATE"] = 23] = "SQLITE_UPDATE";
|
|
1694
1816
|
})(exports.RowUpdateType || (exports.RowUpdateType = {}));
|
|
1817
|
+
/**
|
|
1818
|
+
* A mixin to implement {@link DBAdapter} by delegating to {@link ConnectionPool.readLock} and
|
|
1819
|
+
* {@link ConnectionPool.writeLock}.
|
|
1820
|
+
*/
|
|
1821
|
+
function DBAdapterDefaultMixin(Base) {
|
|
1822
|
+
return class extends Base {
|
|
1823
|
+
readTransaction(fn, options) {
|
|
1824
|
+
return this.readLock((ctx) => TransactionImplementation.runWith(ctx, fn), options);
|
|
1825
|
+
}
|
|
1826
|
+
writeTransaction(fn, options) {
|
|
1827
|
+
return this.writeLock((ctx) => TransactionImplementation.runWith(ctx, fn), options);
|
|
1828
|
+
}
|
|
1829
|
+
getAll(sql, parameters) {
|
|
1830
|
+
return this.readLock((ctx) => ctx.getAll(sql, parameters));
|
|
1831
|
+
}
|
|
1832
|
+
getOptional(sql, parameters) {
|
|
1833
|
+
return this.readLock((ctx) => ctx.getOptional(sql, parameters));
|
|
1834
|
+
}
|
|
1835
|
+
get(sql, parameters) {
|
|
1836
|
+
return this.readLock((ctx) => ctx.get(sql, parameters));
|
|
1837
|
+
}
|
|
1838
|
+
execute(query, params) {
|
|
1839
|
+
return this.writeLock((ctx) => ctx.execute(query, params));
|
|
1840
|
+
}
|
|
1841
|
+
executeRaw(query, params) {
|
|
1842
|
+
return this.writeLock((ctx) => ctx.executeRaw(query, params));
|
|
1843
|
+
}
|
|
1844
|
+
executeBatch(query, params) {
|
|
1845
|
+
return this.writeTransaction((tx) => tx.executeBatch(query, params));
|
|
1846
|
+
}
|
|
1847
|
+
};
|
|
1848
|
+
}
|
|
1849
|
+
class BaseTransaction {
|
|
1850
|
+
inner;
|
|
1851
|
+
finalized = false;
|
|
1852
|
+
constructor(inner) {
|
|
1853
|
+
this.inner = inner;
|
|
1854
|
+
}
|
|
1855
|
+
async commit() {
|
|
1856
|
+
if (this.finalized) {
|
|
1857
|
+
return { rowsAffected: 0 };
|
|
1858
|
+
}
|
|
1859
|
+
this.finalized = true;
|
|
1860
|
+
return this.inner.execute('COMMIT');
|
|
1861
|
+
}
|
|
1862
|
+
async rollback() {
|
|
1863
|
+
if (this.finalized) {
|
|
1864
|
+
return { rowsAffected: 0 };
|
|
1865
|
+
}
|
|
1866
|
+
this.finalized = true;
|
|
1867
|
+
return this.inner.execute('ROLLBACK');
|
|
1868
|
+
}
|
|
1869
|
+
execute(query, params) {
|
|
1870
|
+
return this.inner.execute(query, params);
|
|
1871
|
+
}
|
|
1872
|
+
executeRaw(query, params) {
|
|
1873
|
+
return this.inner.executeRaw(query, params);
|
|
1874
|
+
}
|
|
1875
|
+
executeBatch(query, params) {
|
|
1876
|
+
return this.inner.executeBatch(query, params);
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
class TransactionImplementation extends DBGetUtilsDefaultMixin(BaseTransaction) {
|
|
1880
|
+
static async runWith(ctx, fn) {
|
|
1881
|
+
let tx = new TransactionImplementation(ctx);
|
|
1882
|
+
try {
|
|
1883
|
+
await ctx.execute('BEGIN IMMEDIATE');
|
|
1884
|
+
const result = await fn(tx);
|
|
1885
|
+
await tx.commit();
|
|
1886
|
+
return result;
|
|
1887
|
+
}
|
|
1888
|
+
catch (ex) {
|
|
1889
|
+
try {
|
|
1890
|
+
await tx.rollback();
|
|
1891
|
+
}
|
|
1892
|
+
catch (ex2) {
|
|
1893
|
+
// In rare cases, a rollback may fail.
|
|
1894
|
+
// Safe to ignore.
|
|
1895
|
+
}
|
|
1896
|
+
throw ex;
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1695
1900
|
function isBatchedUpdateNotification(update) {
|
|
1696
1901
|
return 'tables' in update;
|
|
1697
1902
|
}
|
|
@@ -10457,7 +10662,7 @@ function requireDist () {
|
|
|
10457
10662
|
|
|
10458
10663
|
var distExports = requireDist();
|
|
10459
10664
|
|
|
10460
|
-
var version = "1.
|
|
10665
|
+
var version = "1.50.0";
|
|
10461
10666
|
var PACKAGE = {
|
|
10462
10667
|
version: version};
|
|
10463
10668
|
|
|
@@ -12490,7 +12695,7 @@ class TriggerManagerImpl {
|
|
|
12490
12695
|
}
|
|
12491
12696
|
async createDiffTrigger(options) {
|
|
12492
12697
|
await this.db.waitForReady();
|
|
12493
|
-
const { source, destination, columns, when, hooks,
|
|
12698
|
+
const { source, destination, columns, when, hooks, setupContext,
|
|
12494
12699
|
// Fall back to the provided default if not given on this level
|
|
12495
12700
|
useStorage = this.defaultConfig.useStorageByDefault } = options;
|
|
12496
12701
|
const operations = Object.keys(when);
|
|
@@ -12545,13 +12750,20 @@ class TriggerManagerImpl {
|
|
|
12545
12750
|
* we need to ensure we can cleanup the created resources.
|
|
12546
12751
|
* We unfortunately cannot rely on transaction rollback.
|
|
12547
12752
|
*/
|
|
12548
|
-
const cleanup = async () => {
|
|
12753
|
+
const cleanup = async (options) => {
|
|
12754
|
+
const { context } = options ?? {};
|
|
12549
12755
|
disposeWarningListener();
|
|
12550
|
-
|
|
12756
|
+
const doCleanup = async (tx) => {
|
|
12551
12757
|
await this.removeTriggers(tx, triggerIds);
|
|
12552
|
-
await tx.execute(
|
|
12758
|
+
await tx.execute(`DROP TABLE IF EXISTS ${destination};`);
|
|
12553
12759
|
await releaseStorageClaim?.();
|
|
12554
|
-
}
|
|
12760
|
+
};
|
|
12761
|
+
if (context) {
|
|
12762
|
+
await doCleanup(context);
|
|
12763
|
+
}
|
|
12764
|
+
else {
|
|
12765
|
+
await this.db.writeLock(doCleanup);
|
|
12766
|
+
}
|
|
12555
12767
|
};
|
|
12556
12768
|
const setup = async (tx) => {
|
|
12557
12769
|
// Allow user code to execute in this lock context before the trigger is created.
|
|
@@ -12625,12 +12837,17 @@ class TriggerManagerImpl {
|
|
|
12625
12837
|
}
|
|
12626
12838
|
};
|
|
12627
12839
|
try {
|
|
12628
|
-
|
|
12840
|
+
if (setupContext) {
|
|
12841
|
+
await setup(setupContext);
|
|
12842
|
+
}
|
|
12843
|
+
else {
|
|
12844
|
+
await this.db.writeLock(setup);
|
|
12845
|
+
}
|
|
12629
12846
|
return cleanup;
|
|
12630
12847
|
}
|
|
12631
12848
|
catch (error) {
|
|
12632
12849
|
try {
|
|
12633
|
-
await cleanup();
|
|
12850
|
+
await cleanup(setupContext ? { context: setupContext } : undefined);
|
|
12634
12851
|
}
|
|
12635
12852
|
catch (cleanupError) {
|
|
12636
12853
|
throw new AggregateError([error, cleanupError], 'Error during operation and cleanup');
|
|
@@ -12837,7 +13054,7 @@ class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
12837
13054
|
this._schema = schema;
|
|
12838
13055
|
this.ready = false;
|
|
12839
13056
|
this.sdkVersion = '';
|
|
12840
|
-
this.runExclusiveMutex = new
|
|
13057
|
+
this.runExclusiveMutex = new Mutex();
|
|
12841
13058
|
// Start async init
|
|
12842
13059
|
this.subscriptions = {
|
|
12843
13060
|
firstStatusMatching: (predicate, abort) => this.waitForStatus(predicate, abort),
|
|
@@ -13302,6 +13519,10 @@ SELECT * FROM crud_entries;
|
|
|
13302
13519
|
* Execute a SQL write (INSERT/UPDATE/DELETE) query
|
|
13303
13520
|
* and optionally return results.
|
|
13304
13521
|
*
|
|
13522
|
+
* When using the default client-side [JSON-based view system](https://docs.powersync.com/architecture/client-architecture#client-side-schema-and-sqlite-database-structure),
|
|
13523
|
+
* the returned result's `rowsAffected` may be `0` for successful `UPDATE` and `DELETE` statements.
|
|
13524
|
+
* Use a `RETURNING` clause and inspect `result.rows` when you need to confirm which rows changed.
|
|
13525
|
+
*
|
|
13305
13526
|
* @param sql The SQL query to execute
|
|
13306
13527
|
* @param parameters Optional array of parameters to bind to the query
|
|
13307
13528
|
* @returns The query result as an object with structured key-value pairs
|
|
@@ -13398,7 +13619,7 @@ SELECT * FROM crud_entries;
|
|
|
13398
13619
|
async readTransaction(callback, lockTimeout = DEFAULT_LOCK_TIMEOUT_MS) {
|
|
13399
13620
|
await this.waitForReady();
|
|
13400
13621
|
return this.database.readTransaction(async (tx) => {
|
|
13401
|
-
const res = await callback(
|
|
13622
|
+
const res = await callback(tx);
|
|
13402
13623
|
await tx.rollback();
|
|
13403
13624
|
return res;
|
|
13404
13625
|
}, { timeoutMs: lockTimeout });
|
|
@@ -14395,6 +14616,8 @@ exports.ControlledExecutor = ControlledExecutor;
|
|
|
14395
14616
|
exports.CrudBatch = CrudBatch;
|
|
14396
14617
|
exports.CrudEntry = CrudEntry;
|
|
14397
14618
|
exports.CrudTransaction = CrudTransaction;
|
|
14619
|
+
exports.DBAdapterDefaultMixin = DBAdapterDefaultMixin;
|
|
14620
|
+
exports.DBGetUtilsDefaultMixin = DBGetUtilsDefaultMixin;
|
|
14398
14621
|
exports.DEFAULT_CRUD_BATCH_LIMIT = DEFAULT_CRUD_BATCH_LIMIT;
|
|
14399
14622
|
exports.DEFAULT_CRUD_UPLOAD_THROTTLE_MS = DEFAULT_CRUD_UPLOAD_THROTTLE_MS;
|
|
14400
14623
|
exports.DEFAULT_INDEX_COLUMN_OPTIONS = DEFAULT_INDEX_COLUMN_OPTIONS;
|
|
@@ -14426,6 +14649,7 @@ exports.LogLevel = LogLevel;
|
|
|
14426
14649
|
exports.MAX_AMOUNT_OF_COLUMNS = MAX_AMOUNT_OF_COLUMNS;
|
|
14427
14650
|
exports.MAX_OP_ID = MAX_OP_ID;
|
|
14428
14651
|
exports.MEMORY_TRIGGER_CLAIM_MANAGER = MEMORY_TRIGGER_CLAIM_MANAGER;
|
|
14652
|
+
exports.Mutex = Mutex;
|
|
14429
14653
|
exports.OnChangeQueryProcessor = OnChangeQueryProcessor;
|
|
14430
14654
|
exports.OpType = OpType;
|
|
14431
14655
|
exports.OplogEntry = OplogEntry;
|
|
@@ -14459,9 +14683,9 @@ exports.isStreamingSyncCheckpointDiff = isStreamingSyncCheckpointDiff;
|
|
|
14459
14683
|
exports.isStreamingSyncCheckpointPartiallyComplete = isStreamingSyncCheckpointPartiallyComplete;
|
|
14460
14684
|
exports.isStreamingSyncData = isStreamingSyncData;
|
|
14461
14685
|
exports.isSyncNewCheckpointRequest = isSyncNewCheckpointRequest;
|
|
14462
|
-
exports.mutexRunExclusive = mutexRunExclusive;
|
|
14463
14686
|
exports.parseQuery = parseQuery;
|
|
14464
14687
|
exports.runOnSchemaChange = runOnSchemaChange;
|
|
14465
14688
|
exports.sanitizeSQL = sanitizeSQL;
|
|
14466
14689
|
exports.sanitizeUUID = sanitizeUUID;
|
|
14690
|
+
exports.timeoutSignal = timeoutSignal;
|
|
14467
14691
|
//# sourceMappingURL=bundle.cjs.map
|