@react-native-replicache/react-native-expo-sqlite
Version:
> Plug-in React Native compatibility bindings for [Replicache](https://replicache.dev/).
102 lines (101 loc) • 3.83 kB
JavaScript
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
import { ReplicacheGenericSQLiteTransaction } from "@react-native-replicache/replicache-generic-sqlite";
export class ReplicacheExpoSQLiteTransaction extends ReplicacheGenericSQLiteTransaction {
constructor(db) {
super();
this.db = db;
_defineProperty(this, "_tx", null);
_defineProperty(this, "_transactionCommittedSubscriptions", new Set());
_defineProperty(this, "_txCommitted", false);
_defineProperty(this, "_transactionEndedSubscriptions", new Set());
_defineProperty(this, "_txEnded", false);
}
// expo-sqlite doesn't support readonly
async start() {
return await new Promise((resolve, reject) => {
let didResolve = false;
try {
this.db.withExclusiveTransactionAsync(async tx => {
didResolve = true;
this._tx = tx;
resolve();
try {
// expo-sqlite auto-commits our transaction when this callback ends.
// Lets artificially keep it open until we commit.
await this._waitForTransactionCommitted();
this._setTransactionEnded(false);
} catch {
this._setTransactionEnded(true);
}
});
} catch {
if (!didResolve) {
reject(new Error("Did not resolve"));
}
}
});
}
async execute(sqlStatement, args) {
const tx = this.assertTransactionReady();
const statement = await tx.prepareAsync(sqlStatement);
let allRows;
let result;
try {
result = await statement.executeAsync(...(args ?? []));
allRows = await result.getAllAsync();
} finally {
await statement.finalizeAsync();
}
return {
item: idx => allRows[idx],
length: allRows.length
};
}
async commit() {
// Transaction is committed automatically.
this._txCommitted = true;
for (const resolver of this._transactionCommittedSubscriptions) {
resolver();
}
this._transactionCommittedSubscriptions.clear();
}
waitForTransactionEnded() {
if (this._txEnded) return;
return new Promise((resolve, reject) => {
this._transactionEndedSubscriptions.add({
resolve,
reject
});
});
}
assertTransactionReady() {
if (this._tx === null) throw new Error("Transaction is not ready.");
if (this._txCommitted) throw new Error("Transaction already committed.");
if (this._txEnded) throw new Error("Transaction already ended.");
return this._tx;
}
_waitForTransactionCommitted() {
if (this._txCommitted) return;
return new Promise(resolve => {
this._transactionCommittedSubscriptions.add(resolve);
});
}
_setTransactionEnded() {
let errored = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
this._txEnded = true;
for (const {
resolve,
reject
} of this._transactionEndedSubscriptions) {
if (errored) {
reject();
} else {
resolve();
}
}
this._transactionEndedSubscriptions.clear();
}
}
//# sourceMappingURL=replicache-expo-sqlite-transaction.js.map