@tanstack/db
Version:
A reactive client store for building super fast apps on sync
142 lines (141 loc) • 4.72 kB
JavaScript
;
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const refProxy = require("./query/builder/ref-proxy.cjs");
const evaluators = require("./query/compiler/evaluators.cjs");
const indexOptimization = require("./utils/index-optimization.cjs");
function currentStateAsChanges(collection, options = {}) {
const collectFilteredResults = (filterFn) => {
const result = [];
for (const [key, value] of collection.entries()) {
if ((filterFn == null ? void 0 : filterFn(value)) ?? true) {
result.push({
type: `insert`,
key,
value
});
}
}
return result;
};
if (!options.where && !options.whereExpression) {
return collectFilteredResults();
}
try {
let expression;
if (options.whereExpression) {
expression = options.whereExpression;
} else if (options.where) {
const singleRowRefProxy = refProxy.createSingleRowRefProxy();
const whereExpression = options.where(singleRowRefProxy);
expression = refProxy.toExpression(whereExpression);
} else {
return [];
}
const optimizationResult = indexOptimization.optimizeExpressionWithIndexes(
expression,
collection.indexes
);
if (optimizationResult.canOptimize) {
const result = [];
for (const key of optimizationResult.matchingKeys) {
const value = collection.get(key);
if (value !== void 0) {
result.push({
type: `insert`,
key,
value
});
}
}
return result;
} else {
const filterFn = options.where ? createFilterFunction(options.where) : createFilterFunctionFromExpression(expression);
return collectFilteredResults(filterFn);
}
} catch (error) {
console.warn(
`Error processing where clause, falling back to full scan:`,
error
);
const filterFn = options.where ? createFilterFunction(options.where) : createFilterFunctionFromExpression(options.whereExpression);
return collectFilteredResults(filterFn);
}
}
function createFilterFunction(whereCallback) {
return (item) => {
try {
const singleRowRefProxy = refProxy.createSingleRowRefProxy();
const whereExpression = whereCallback(singleRowRefProxy);
const expression = refProxy.toExpression(whereExpression);
const evaluator = evaluators.compileSingleRowExpression(expression);
const result = evaluator(item);
return result;
} catch {
try {
const simpleProxy = new Proxy(item, {
get(target, prop) {
return target[prop];
}
});
const result = whereCallback(simpleProxy);
return result;
} catch {
return false;
}
}
};
}
function createFilterFunctionFromExpression(expression) {
return (item) => {
try {
const evaluator = evaluators.compileSingleRowExpression(expression);
const result = evaluator(item);
return Boolean(result);
} catch {
return false;
}
};
}
function createFilteredCallback(originalCallback, options) {
const filterFn = options.whereExpression ? createFilterFunctionFromExpression(options.whereExpression) : createFilterFunction(options.where);
return (changes) => {
const filteredChanges = [];
for (const change of changes) {
if (change.type === `insert`) {
if (filterFn(change.value)) {
filteredChanges.push(change);
}
} else if (change.type === `update`) {
const newValueMatches = filterFn(change.value);
const oldValueMatches = change.previousValue ? filterFn(change.previousValue) : false;
if (newValueMatches && oldValueMatches) {
filteredChanges.push(change);
} else if (newValueMatches && !oldValueMatches) {
filteredChanges.push({
...change,
type: `insert`
});
} else if (!newValueMatches && oldValueMatches) {
filteredChanges.push({
...change,
type: `delete`,
value: change.previousValue
// Use the previous value for the delete
});
}
} else {
if (filterFn(change.value)) {
filteredChanges.push(change);
}
}
}
if (filteredChanges.length > 0 || changes.length === 0) {
originalCallback(filteredChanges);
}
};
}
exports.createFilterFunction = createFilterFunction;
exports.createFilterFunctionFromExpression = createFilterFunctionFromExpression;
exports.createFilteredCallback = createFilteredCallback;
exports.currentStateAsChanges = currentStateAsChanges;
//# sourceMappingURL=change-events.cjs.map