UNPKG

@tanstack/optimistic

Version:

Core optimistic updates library

217 lines (216 loc) 6.38 kB
import { orderByWithIndex, map, topKWithIndex, orderByWithFractionalIndex, topKWithFractionalIndex, orderBy, topK } from "@electric-sql/d2ts"; import { evaluateOperandOnNestedRow } from "./extractors.js"; import { isOrderIndexFunctionCall } from "./utils.js"; 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` && 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 = (value) => { const row = value; const nestedRow = { [mainTableAlias]: row }; if (orderByItems.length > 1) { return orderByItems.map((item) => { const val = evaluateOperandOnNestedRow( nestedRow, item.operand, mainTableAlias ); return item.direction === `desc` && typeof val === `number` ? -val : item.direction === `desc` && typeof val === `string` ? String.fromCharCode( ...[...val].map((c) => 65535 - c.charCodeAt(0)) ) : val; }); } else if (orderByItems.length === 1) { const item = orderByItems[0]; const val = evaluateOperandOnNestedRow( nestedRow, item.operand, mainTableAlias ); return item.direction === `desc` && typeof val === `number` ? -val : item.direction === `desc` && typeof val === `string` ? String.fromCharCode( ...[...val].map((c) => 65535 - c.charCodeAt(0)) ) : val; } return null; }; const comparator = (a, b) => { if (typeof a === `number` && typeof b === `number`) { return a - b; } if (typeof a === `string` && typeof b === `string`) { return a.localeCompare(b); } if (typeof a === `boolean` && typeof b === `boolean`) { return a ? 1 : -1; } if (a instanceof Date && b instanceof Date) { return a.getTime() - b.getTime(); } if (a === null && b === null) { return 0; } if (Array.isArray(a) && Array.isArray(b)) { for (let i = 0; i < a.length; i++) { const result = comparator(a[i], b[i]); if (result !== 0) return result; } return 0; } if ((a === null || a === void 0) && (b === null || b === void 0)) { return 0; } return a.toString().localeCompare(b.toString()); }; let topKComparator; if (!query.keyBy) { topKComparator = (a, b) => { const aValue = valueExtractor(a); const bValue = valueExtractor(b); return comparator(aValue, bValue); }; } if (hasOrderIndexColumn) { if (orderIndexType === `numeric`) { if (query.keyBy) { resultPipeline = resultPipeline.pipe( orderByWithIndex(valueExtractor, { limit: query.limit, offset: query.offset, comparator }), map(([key, [value, index]]) => { const result = { ...value, [orderIndexAlias]: index }; return [key, result]; }) ); } else { resultPipeline = resultPipeline.pipe( map((value) => [null, value]), topKWithIndex(topKComparator, { limit: query.limit, offset: query.offset }), map(([_, [value, index]]) => { return { ...value, [orderIndexAlias]: index }; }) ); } } else { if (query.keyBy) { resultPipeline = resultPipeline.pipe( orderByWithFractionalIndex(valueExtractor, { limit: query.limit, offset: query.offset, comparator }), map(([key, [value, index]]) => { const result = { ...value, [orderIndexAlias]: index }; return [key, result]; }) ); } else { resultPipeline = resultPipeline.pipe( map((value) => [null, value]), topKWithFractionalIndex(topKComparator, { limit: query.limit, offset: query.offset }), map(([_, [value, index]]) => { return { ...value, [orderIndexAlias]: index }; }) ); } } } else { if (query.keyBy) { resultPipeline = resultPipeline.pipe( orderBy(valueExtractor, { limit: query.limit, offset: query.offset, comparator }) ); } else { resultPipeline = resultPipeline.pipe( map((value) => [null, value]), topK(topKComparator, { limit: query.limit, offset: query.offset }), map(([_, value]) => value) ); } } return resultPipeline; } function getOrderIndexType(obj) { if (!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); } } export { processOrderBy }; //# sourceMappingURL=order-by.js.map