UNPKG

@tanstack/db

Version:

A reactive client store for building super fast apps on sync

180 lines (179 loc) 5.99 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const dbIvm = require("@tanstack/db-ivm"); const expressions = require("../compiler/expressions.cjs"); const index = require("../builder/index.cjs"); function extractCollectionsFromQuery(query) { const collections = {}; function extractFromSource(source) { if (source.type === `collectionRef`) { collections[source.collection.id] = source.collection; } else if (source.type === `queryRef`) { extractFromQuery(source.query); } } function extractFromQuery(q) { if (q.from) { extractFromSource(q.from); } if (q.join && Array.isArray(q.join)) { for (const joinClause of q.join) { if (joinClause.from) { extractFromSource(joinClause.from); } } } } extractFromQuery(query); return collections; } function extractCollectionFromSource(query) { const from = query.from; if (from.type === `collectionRef`) { return from.collection; } else if (from.type === `queryRef`) { return extractCollectionFromSource(from.query); } throw new Error( `Failed to extract collection. Invalid FROM clause: ${JSON.stringify(query)}` ); } function extractCollectionAliases(query) { const aliasesById = /* @__PURE__ */ new Map(); function recordAlias(source) { if (!source) return; if (source.type === `collectionRef`) { const { id } = source.collection; const existing = aliasesById.get(id); if (existing) { existing.add(source.alias); } else { aliasesById.set(id, /* @__PURE__ */ new Set([source.alias])); } } else if (source.type === `queryRef`) { traverse(source.query); } } function traverse(q) { if (!q) return; recordAlias(q.from); if (q.join) { for (const joinClause of q.join) { recordAlias(joinClause.from); } } } traverse(query); return aliasesById; } function buildQueryFromConfig(config) { if (typeof config.query === `function`) { return index.buildQuery(config.query); } return index.getQueryIR(config.query); } function sendChangesToInput(input, changes, getKey) { const multiSetArray = []; for (const change of changes) { const key = getKey(change.value); if (change.type === `insert`) { multiSetArray.push([[key, change.value], 1]); } else if (change.type === `update`) { multiSetArray.push([[key, change.previousValue], -1]); multiSetArray.push([[key, change.value], 1]); } else { multiSetArray.push([[key, change.value], -1]); } } if (multiSetArray.length !== 0) { input.sendData(new dbIvm.MultiSet(multiSetArray)); } return multiSetArray.length; } function* splitUpdates(changes) { for (const change of changes) { if (change.type === `update`) { yield { type: `delete`, key: change.key, value: change.previousValue }; yield { type: `insert`, key: change.key, value: change.value }; } else { yield change; } } } function filterDuplicateInserts(changes, sentKeys) { const filtered = []; for (const change of changes) { if (change.type === `insert`) { if (sentKeys.has(change.key)) { continue; } sentKeys.add(change.key); } else if (change.type === `delete`) { sentKeys.delete(change.key); } filtered.push(change); } return filtered; } function trackBiggestSentValue(changes, current, sentKeys, comparator) { let biggest = current; let shouldResetLoadKey = false; for (const change of changes) { if (change.type === `delete`) continue; const isNewKey = !sentKeys.has(change.key); if (biggest === void 0) { biggest = change.value; shouldResetLoadKey = true; } else if (comparator(biggest, change.value) < 0) { biggest = change.value; shouldResetLoadKey = true; } else if (isNewKey) { shouldResetLoadKey = true; } } return { biggest, shouldResetLoadKey }; } function computeSubscriptionOrderByHints(query, alias) { const { orderBy, limit, offset } = query; const effectiveLimit = limit !== void 0 && offset !== void 0 ? limit + offset : limit; const normalizedOrderBy = orderBy ? expressions.normalizeOrderByPaths(orderBy, alias) : void 0; const canPassOrderBy = normalizedOrderBy?.every((clause) => { const exp = clause.expression; if (exp.type !== `ref`) return false; const path = exp.path; return Array.isArray(path) && path.length === 1; }) ?? false; return { orderBy: canPassOrderBy ? normalizedOrderBy : void 0, limit: canPassOrderBy ? effectiveLimit : void 0 }; } function computeOrderedLoadCursor(orderByInfo, biggestSentRow, lastLoadRequestKey, alias, limit) { const { orderBy, valueExtractorForRawRow, offset } = orderByInfo; const extractedValues = biggestSentRow ? valueExtractorForRawRow(biggestSentRow) : void 0; let minValues; if (extractedValues !== void 0) { minValues = Array.isArray(extractedValues) ? extractedValues : [extractedValues]; } const loadRequestKey = dbIvm.serializeValue({ minValues: minValues ?? null, offset, limit }); if (lastLoadRequestKey === loadRequestKey) { return void 0; } const normalizedOrderBy = expressions.normalizeOrderByPaths(orderBy, alias); return { minValues, normalizedOrderBy, loadRequestKey }; } exports.buildQueryFromConfig = buildQueryFromConfig; exports.computeOrderedLoadCursor = computeOrderedLoadCursor; exports.computeSubscriptionOrderByHints = computeSubscriptionOrderByHints; exports.extractCollectionAliases = extractCollectionAliases; exports.extractCollectionFromSource = extractCollectionFromSource; exports.extractCollectionsFromQuery = extractCollectionsFromQuery; exports.filterDuplicateInserts = filterDuplicateInserts; exports.sendChangesToInput = sendChangesToInput; exports.splitUpdates = splitUpdates; exports.trackBiggestSentValue = trackBiggestSentValue; //# sourceMappingURL=utils.cjs.map