UNPKG

@tanstack/react-optimistic

Version:

React hooks for optimistic updates

113 lines (112 loc) 3.83 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const client = require("@electric-sql/client"); const store = require("@tanstack/store"); function isUpToDateMessage(message) { return client.isControlMessage(message) && message.headers.control === `up-to-date`; } function hasTxids(message) { return `headers` in message && `txids` in message.headers && Array.isArray(message.headers.txids); } function createElectricSync(streamOptions, options) { const { primaryKey } = options; const seenTxids = new store.Store(/* @__PURE__ */ new Set()); const relationSchema = new store.Store(void 0); const hasTxid = (txid) => { return seenTxids.state.has(txid); }; const awaitTxid = async (txid, timeout = 3e4) => { if (hasTxid(txid)) { return true; } return new Promise((resolve, reject) => { const timeoutId = setTimeout(() => { unsubscribe(); reject(new Error(`Timeout waiting for txid: ${txid}`)); }, timeout); const unsubscribe = seenTxids.subscribe(() => { if (hasTxid(txid)) { clearTimeout(timeoutId); unsubscribe(); resolve(true); } }); }); }; const generateKeyFromRow = (row) => { if (!primaryKey || primaryKey.length === 0) { throw new Error(`Primary key is required for Electric sync`); } return primaryKey.map((key) => { const value = row[key]; if (value === void 0) { throw new Error(`Primary key column "${key}" not found in row`); } return String(value); }).join(`|`); }; const getSyncMetadata = () => { var _a; const schema = relationSchema.state || `public`; return { primaryKey, relation: ((_a = streamOptions.params) == null ? void 0 : _a.table) ? [schema, streamOptions.params.table] : void 0 }; }; return { sync: ({ begin, write, commit }) => { const stream = new client.ShapeStream(streamOptions); let transactionStarted = false; let newTxids = /* @__PURE__ */ new Set(); stream.subscribe((messages) => { let hasUpToDate = false; for (const message of messages) { if (hasTxids(message) && message.headers.txids) { message.headers.txids.forEach((txid) => newTxids.add(txid)); } if (client.isChangeMessage(message) && message.headers.schema) { if (typeof message.headers.schema === `string`) { const schema = message.headers.schema; relationSchema.setState(() => schema); } } if (client.isChangeMessage(message)) { if (!transactionStarted) { begin(); transactionStarted = true; } const key = message.key || generateKeyFromRow(message.value); const enhancedMetadata = { ...message.headers, primaryKey }; write({ key, type: message.headers.operation, value: message.value, metadata: enhancedMetadata }); } else if (isUpToDateMessage(message)) { hasUpToDate = true; } } if (hasUpToDate && transactionStarted) { commit(); seenTxids.setState((currentTxids) => { const clonedSeen = new Set(currentTxids); newTxids.forEach((txid) => clonedSeen.add(txid)); newTxids = /* @__PURE__ */ new Set(); return clonedSeen; }); transactionStarted = false; } }); }, // Expose the awaitTxid function awaitTxid, // Expose the getSyncMetadata function getSyncMetadata }; } exports.createElectricSync = createElectricSync; //# sourceMappingURL=electric.cjs.map