@tanstack/db
Version:
A reactive client store for building super fast apps on sync
122 lines (121 loc) • 4.36 kB
JavaScript
;
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const transactions = require("./transactions.cjs");
const error = require("./utils/error.cjs");
const errors = require("./errors.cjs");
function createPacedMutations(config) {
const { onMutate, mutationFn, strategy, ...transactionConfig } = config;
let activeTransaction = null;
const strategyCommits = /* @__PURE__ */ new WeakMap();
let optimisticFrame;
function getTransaction(isolated = false) {
if (!isolated && activeTransaction?.state === `pending`)
return activeTransaction;
const transaction = transactions.createTransaction({
...transactionConfig,
mutationFn,
autoCommit: false
});
strategyCommits.set(transaction, transaction.commit.bind(transaction));
transaction.commit = () => {
throw new errors.PacedTransactionManualCommitError();
};
if (!isolated) activeTransaction = transaction;
return transaction;
}
function commit(transaction, onStarted) {
if (activeTransaction === transaction) activeTransaction = null;
if (transaction.state === `failed`) return transaction;
if (transaction.state !== `pending`) {
throw new Error(
`Strategy callback called but transaction is in state "${transaction.state}". Expected "pending".`
);
}
const strategyCommit = strategyCommits.get(transaction);
if (!strategyCommit)
throw new Error(`Paced transaction has no strategy-owned commit`);
const completion = strategyCommit();
onStarted?.(completion);
completion.catch(() => {
});
return transaction;
}
function applyOptimistic(transaction, variables, newlyCreated) {
const parent = optimisticFrame;
if (parent?.transaction === transaction) parent.admittedNestedCall = true;
const frame = { transaction, admittedNestedCall: false };
optimisticFrame = frame;
try {
transaction.mutate(() => onMutate(variables));
} catch (error$1) {
if (newlyCreated || frame.admittedNestedCall) {
void transaction.isPersisted.promise.catch(() => {
});
transaction.rollback({
error: error.normalizeError(error$1),
isSecondaryRollback: !frame.admittedNestedCall
});
if (activeTransaction === transaction) activeTransaction = null;
}
throw error$1;
} finally {
optimisticFrame = parent;
}
}
function mutate(variables) {
if (strategy._type === `debounce` || strategy._type === `throttle`) {
let transaction2;
let completion;
const onAdmit = () => {
if (transaction2) return transaction2;
const previous2 = activeTransaction;
transaction2 = getTransaction();
applyOptimistic(transaction2, variables, transaction2 !== previous2);
return transaction2;
};
const admitted = strategy.execute(
() => {
return commit(onAdmit(), (started) => {
completion = started;
});
},
onAdmit,
() => completion
);
if (admitted !== false) return onAdmit();
const dropped = getTransaction(true);
applyOptimistic(dropped, variables, true);
dropped.rollback({
error: strategy._type === `debounce` ? new errors.DebounceCallDroppedError() : new errors.ThrottleCallDroppedError(),
isSecondaryRollback: true
});
return dropped;
}
const previous = activeTransaction;
const transaction = getTransaction(strategy._type === `queue`);
applyOptimistic(transaction, variables, transaction !== previous);
try {
let completion;
const admitted = strategy.execute(
() => commit(transaction, (started) => {
completion = started;
}),
void 0,
() => completion
);
if (strategy._type === `queue` && admitted === false) {
transaction.rollback({
error: new errors.QueueCapacityExceededError(),
isSecondaryRollback: true
});
}
} catch (error2) {
if (!(error2 instanceof errors.QueueDisposedError)) throw error2;
transaction.rollback({ error: error2, isSecondaryRollback: true });
}
return transaction;
}
return mutate;
}
exports.createPacedMutations = createPacedMutations;
//# sourceMappingURL=paced-mutations.cjs.map