@tanstack/db
Version:
A reactive client store for building super fast apps on sync
141 lines (140 loc) • 3.96 kB
JavaScript
import { followRef, PropRef } from "../ir.js";
function getLazyLoadTargets(rawQuery, lazyFrom, lazyAlias, lazySourceExpr, lazySource, aliasRemapping) {
if (lazyFrom.type === `unionFrom`) {
return getTargetsFromExpression(rawQuery, lazySourceExpr);
}
if (lazyFrom.type === `queryRef` && containsUnionFrom(lazyFrom.query.from)) {
const targets = getTargetsFromQueryRef(
lazyFrom.query,
lazyAlias,
lazySourceExpr
);
return dedupeLazyLoadTargets(targets);
}
if (!lazySource) {
return [];
}
const lazySourceRef = toPropRef(lazySourceExpr);
if (!lazySourceRef) {
return [];
}
const followRefResult = followRef(rawQuery, lazySourceRef, lazySource);
if (!followRefResult) {
return [];
}
return [
{
alias: aliasRemapping[lazyAlias] || lazyAlias,
collection: followRefResult.collection,
path: followRefResult.path
}
];
}
function containsUnionFrom(from) {
if (from.type === `unionFrom`) {
return true;
}
if (from.type === `queryRef`) {
return containsUnionFrom(from.query.from);
}
if (from.type === `unionAll`) {
return from.queries.some((query) => containsUnionFrom(query.from));
}
return false;
}
function getTargetsFromQueryRef(query, outerAlias, expr) {
if (!expr || typeof expr !== `object` || !(`type` in expr)) {
return [];
}
const expression = expr;
if (expression.type === `func` && expression.name === `coalesce`) {
return dedupeLazyLoadTargets(
expression.args.flatMap(
(arg) => getTargetsFromQueryRef(query, outerAlias, arg)
)
);
}
const ref = toPropRef(expression);
if (!ref || ref.path[0] !== outerAlias) {
return [];
}
return getTargetsFromPropRef(query, new PropRef(ref.path.slice(1)));
}
function getTargetsFromExpression(query, expr) {
if (!expr || typeof expr !== `object` || !(`type` in expr)) {
return [];
}
const expression = expr;
if (expression.type === `ref`) {
return getTargetsFromPropRef(query, expression);
}
if (expression.type === `func` && expression.name === `coalesce`) {
return dedupeLazyLoadTargets(
expression.args.flatMap((arg) => getTargetsFromExpression(query, arg))
);
}
return [];
}
function getTargetsFromPropRef(query, ref) {
if (ref.path.length === 0) {
return [];
}
if (ref.path.length === 1) {
const field = ref.path[0];
const selectedField = query.select?.[field];
if (selectedField) {
return getTargetsFromExpression(query, selectedField);
}
return [];
}
const [alias, ...path] = ref.path;
const source = getSourceFromAlias(query, alias);
if (!source) {
return [];
}
if (source.type === `collectionRef`) {
return [{ alias: source.alias, collection: source.collection, path }];
}
if (source.query.limit || source.query.offset) {
return [];
}
return getTargetsFromQueryRef(source.query, source.alias, ref);
}
function getSourceFromAlias(query, alias) {
if (query.join) {
for (const join of query.join) {
if (join.from.alias === alias) {
return join.from;
}
}
}
const from = query.from;
const sources = from.type === `unionFrom` ? from.sources : from.type === `unionAll` ? [] : [from];
return sources.find((source) => source.alias === alias);
}
function dedupeLazyLoadTargets(targets) {
const seen = /* @__PURE__ */ new Set();
const deduped = [];
for (const target of targets) {
const key = `${target.alias}:${target.path.join(`.`)}`;
if (!seen.has(key)) {
seen.add(key);
deduped.push(target);
}
}
return deduped;
}
function toPropRef(expr) {
if (expr instanceof PropRef) {
return expr;
}
if (expr && typeof expr === `object` && `type` in expr && expr.type === `ref` && Array.isArray(expr.path)) {
return new PropRef(expr.path);
}
return void 0;
}
export {
containsUnionFrom,
getLazyLoadTargets
};
//# sourceMappingURL=lazy-targets.js.map