@tanstack/optimistic
Version:
Core optimistic updates library
1 lines • 9.74 kB
Source Map (JSON)
{"version":3,"file":"utils.cjs","sources":["../../../src/query/utils.ts"],"sourcesContent":["/**\n * Helper function to determine if an object is a function call with an aggregate function\n */\nexport function isAggregateFunctionCall(obj: any): boolean {\n if (!obj || typeof obj !== `object`) return false\n\n const aggregateFunctions = [\n `SUM`,\n `COUNT`,\n `AVG`,\n `MIN`,\n `MAX`,\n `MEDIAN`,\n `MODE`,\n ]\n const keys = Object.keys(obj)\n\n return keys.length === 1 && aggregateFunctions.includes(keys[0]!)\n}\n\n/**\n * Helper function to determine if an object is an ORDER_INDEX function call\n */\nexport function isOrderIndexFunctionCall(obj: any): boolean {\n if (!obj || typeof obj !== `object`) return false\n\n const keys = Object.keys(obj)\n return keys.length === 1 && keys[0] === `ORDER_INDEX`\n}\n\n/**\n * Type guard to check if a value is comparable (can be used with <, >, <=, >= operators)\n * @param value The value to check\n * @returns True if the value is comparable\n */\nexport function isComparable(\n value: unknown\n): value is number | string | Date | boolean {\n return (\n typeof value === `number` ||\n typeof value === `string` ||\n typeof value === `boolean` ||\n value instanceof Date\n )\n}\n\n/**\n * Performs a comparison between two values, ensuring they are of compatible types\n * @param left The left operand\n * @param right The right operand\n * @param operator The comparison operator\n * @returns The result of the comparison\n * @throws Error if the values are not comparable\n */\nexport function compareValues(\n left: unknown,\n right: unknown,\n operator: `<` | `<=` | `>` | `>=`\n): boolean {\n // First check if both values are comparable\n if (!isComparable(left) || !isComparable(right)) {\n throw new Error(\n `Cannot compare non-comparable values: ${typeof left} and ${typeof right}`\n )\n }\n\n // If they're different types but both are strings or numbers, convert to strings\n if (\n typeof left !== typeof right &&\n (typeof left === `string` || typeof left === `number`) &&\n (typeof right === `string` || typeof right === `number`)\n ) {\n // Convert to strings for comparison (follows JavaScript's coercion rules)\n const leftStr = String(left)\n const rightStr = String(right)\n\n switch (operator) {\n case `<`:\n return leftStr < rightStr\n case `<=`:\n return leftStr <= rightStr\n case `>`:\n return leftStr > rightStr\n case `>=`:\n return leftStr >= rightStr\n }\n }\n\n // For Date objects, convert to timestamps\n if (left instanceof Date && right instanceof Date) {\n const leftTime = left.getTime()\n const rightTime = right.getTime()\n\n switch (operator) {\n case `<`:\n return leftTime < rightTime\n case `<=`:\n return leftTime <= rightTime\n case `>`:\n return leftTime > rightTime\n case `>=`:\n return leftTime >= rightTime\n }\n }\n\n // For other cases where types match\n if (typeof left === typeof right) {\n switch (operator) {\n case `<`:\n return left < right\n case `<=`:\n return left <= right\n case `>`:\n return left > right\n case `>=`:\n return left >= right\n }\n }\n\n // If we get here, it means the values are technically comparable but not compatible\n throw new Error(\n `Cannot compare incompatible types: ${typeof left} and ${typeof right}`\n )\n}\n\n/**\n * Converts a SQL LIKE pattern to a JavaScript regex pattern\n * @param pattern The SQL LIKE pattern to convert\n * @returns A regex-compatible pattern string\n */\nexport function convertLikeToRegex(pattern: string): string {\n let finalPattern = ``\n let i = 0\n\n while (i < pattern.length) {\n const char = pattern[i]\n\n // Handle escape character\n if (char === `\\\\` && i + 1 < pattern.length) {\n // Add the next character as a literal (escaped)\n finalPattern += pattern[i + 1]\n i += 2 // Skip both the escape and the escaped character\n continue\n }\n\n // Handle SQL LIKE special characters\n switch (char) {\n case `%`:\n // % matches any sequence of characters (including empty)\n finalPattern += `.*`\n break\n case `_`:\n // _ matches any single character\n finalPattern += `.`\n break\n // Handle regex special characters\n case `.`:\n case `^`:\n case `$`:\n case `*`:\n case `+`:\n case `?`:\n case `(`:\n case `)`:\n case `[`:\n case `]`:\n case `{`:\n case `}`:\n case `|`:\n case `/`:\n // Escape regex special characters\n finalPattern += `\\\\` + char\n break\n default:\n // Regular character, just add it\n finalPattern += char\n }\n\n i++\n }\n\n return finalPattern\n}\n\n/**\n * Helper function to check if a value is in an array, with special handling for various types\n * @param value The value to check for\n * @param array The array to search in\n * @param caseInsensitive Optional flag to enable case-insensitive matching for strings (default: false)\n * @returns True if the value is found in the array\n */\nexport function isValueInArray(\n value: unknown,\n array: Array<unknown>,\n caseInsensitive: boolean = false\n): boolean {\n // Direct inclusion check first (fastest path)\n if (array.includes(value)) {\n return true\n }\n\n // Handle null/undefined\n if (value === null || value === undefined) {\n return array.some((item) => item === null || item === undefined)\n }\n\n // Handle numbers and strings with type coercion\n if (typeof value === `number` || typeof value === `string`) {\n return array.some((item) => {\n // Same type, direct comparison\n if (typeof item === typeof value) {\n if (typeof value === `string` && caseInsensitive) {\n // Case-insensitive comparison for strings (only if explicitly enabled)\n return value.toLowerCase() === (item as string).toLowerCase()\n }\n return item === value\n }\n\n // Different types, try coercion for number/string\n if (\n (typeof item === `number` || typeof item === `string`) &&\n (typeof value === `number` || typeof value === `string`)\n ) {\n // Convert both to strings for comparison\n return String(item) === String(value)\n }\n\n return false\n })\n }\n\n // Handle objects/arrays by comparing stringified versions\n if (typeof value === `object`) {\n const valueStr = JSON.stringify(value)\n return array.some((item) => {\n if (typeof item === `object` && item !== null) {\n return JSON.stringify(item) === valueStr\n }\n return false\n })\n }\n\n // Fallback\n return false\n}\n"],"names":[],"mappings":"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"}