UNPKG

@tanstack/db

Version:

A reactive client store for building super fast apps on sync

186 lines (185 loc) 5.54 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const d2mini = require("@electric-sql/d2mini"); const extractors = require("./extractors.cjs"); const utils = require("./utils.cjs"); function processOrderBy(resultPipeline, query, mainTableAlias) { let hasOrderIndexColumn = false; let orderIndexType = `numeric`; let orderIndexAlias = ``; for (const item of query.select) { if (typeof item === `object`) { for (const [alias, expr] of Object.entries(item)) { if (typeof expr === `object` && utils.isOrderIndexFunctionCall(expr)) { hasOrderIndexColumn = true; orderIndexAlias = alias; orderIndexType = getOrderIndexType(expr); break; } } } if (hasOrderIndexColumn) break; } const orderByItems = []; if (typeof query.orderBy === `string`) { orderByItems.push({ operand: query.orderBy, direction: `asc` }); } else if (Array.isArray(query.orderBy)) { for (const item of query.orderBy) { if (typeof item === `string`) { orderByItems.push({ operand: item, direction: `asc` }); } else if (typeof item === `object`) { for (const [column, direction] of Object.entries(item)) { orderByItems.push({ operand: column, direction }); } } } } else if (typeof query.orderBy === `object`) { for (const [column, direction] of Object.entries(query.orderBy)) { orderByItems.push({ operand: column, direction }); } } const valueExtractor = (namespacedRow) => { if (orderByItems.length > 1) { return orderByItems.map( (item) => extractors.evaluateOperandOnNamespacedRow( namespacedRow, item.operand, mainTableAlias ) ); } else if (orderByItems.length === 1) { const item = orderByItems[0]; const val = extractors.evaluateOperandOnNamespacedRow( namespacedRow, item.operand, mainTableAlias ); return val; } return null; }; const ascComparator = (a, b) => { if (typeof a === `string` && typeof b === `string`) { return a.localeCompare(b); } if (Array.isArray(a) && Array.isArray(b)) { for (let i = 0; i < Math.min(a.length, b.length); i++) { const result = ascComparator(a[i], b[i]); if (result !== 0) { return result; } } return a.length - b.length; } const bothObjects = typeof a === `object` && typeof b === `object`; const bothDates = a instanceof Date && b instanceof Date; const notNull = a !== null && b !== null; if (bothObjects && !bothDates && notNull) { return a.toString().localeCompare(b.toString()); } if (a < b) return -1; if (a > b) return 1; return 0; }; const descComparator = (a, b) => { return ascComparator(b, a); }; const makeComparator = (orderByProps) => { return (a, b) => { if (orderByProps.length > 1) { const arrayA = a; const arrayB = b; for (let i = 0; i < orderByProps.length; i++) { const direction = orderByProps[i].direction; const compareFn = direction === `desc` ? descComparator : ascComparator; const result = compareFn(arrayA[i], arrayB[i]); if (result !== 0) { return result; } } return arrayA.length - arrayB.length; } if (orderByProps.length === 1) { const direction = orderByProps[0].direction; return direction === `desc` ? descComparator(a, b) : ascComparator(a, b); } return ascComparator(a, b); }; }; const comparator = makeComparator(orderByItems); if (hasOrderIndexColumn) { if (orderIndexType === `numeric`) { resultPipeline = resultPipeline.pipe( d2mini.orderByWithIndex(valueExtractor, { limit: query.limit, offset: query.offset, comparator }), d2mini.map(([key, [value, index]]) => { const result = { ...value, [mainTableAlias]: { ...value[mainTableAlias], [orderIndexAlias]: index } }; return [key, result]; }) ); } else { resultPipeline = resultPipeline.pipe( d2mini.orderByWithFractionalIndex(valueExtractor, { limit: query.limit, offset: query.offset, comparator }), d2mini.map(([key, [value, index]]) => { const result = { ...value, [mainTableAlias]: { ...value[mainTableAlias], [orderIndexAlias]: index } }; return [key, result]; }) ); } } else { resultPipeline = resultPipeline.pipe( d2mini.orderBy(valueExtractor, { limit: query.limit, offset: query.offset, comparator }) ); } return resultPipeline; } function getOrderIndexType(obj) { if (!utils.isOrderIndexFunctionCall(obj)) { throw new Error(`Not an ORDER_INDEX function call`); } const arg = obj[`ORDER_INDEX`]; if (arg === `numeric` || arg === true || arg === `default`) { return `numeric`; } else if (arg === `fractional`) { return `fractional`; } else { throw new Error(`Invalid ORDER_INDEX type: ` + arg); } } exports.processOrderBy = processOrderBy; //# sourceMappingURL=order-by.cjs.map