@wcs-colab/plugin-qps 3.1.16-custom.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +13 -0
- package/README.md +29 -0
- package/dist/index.cjs +12 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.global.js +12 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../orama/src/components/tokenizer/languages.ts","../../orama/src/utils.ts","../../orama/src/errors.ts","../../orama/src/components/defaults.ts","../../orama/src/components/internal-document-id-store.ts","../../orama/src/components/index.ts","../../orama/src/trees/avl.ts","../../orama/src/trees/flat.ts","../../orama/src/trees/radix.ts","../../orama/src/components/levenshtein.ts","../../orama/src/trees/bkd.ts","../../orama/src/trees/bool.ts","../../orama/src/components/algorithms.ts","../../orama/src/trees/vector.ts","../../orama/src/components/tokenizer/english-stemmer.ts","../src/algorithm.ts","../src/index.ts"],"sourcesContent":["export const STEMMERS: Record<string, string> = {\n arabic: 'ar',\n armenian: 'am',\n bulgarian: 'bg',\n czech: 'cz',\n danish: 'dk',\n dutch: 'nl',\n english: 'en',\n finnish: 'fi',\n french: 'fr',\n german: 'de',\n greek: 'gr',\n hungarian: 'hu',\n indian: 'in',\n indonesian: 'id',\n irish: 'ie',\n italian: 'it',\n lithuanian: 'lt',\n nepali: 'np',\n norwegian: 'no',\n portuguese: 'pt',\n romanian: 'ro',\n russian: 'ru',\n serbian: 'rs',\n slovenian: 'ru',\n spanish: 'es',\n swedish: 'se',\n tamil: 'ta',\n turkish: 'tr',\n ukrainian: 'uk',\n sanskrit: 'sk'\n}\n\nexport const SPLITTERS: Record<Language, RegExp> = {\n dutch: /[^A-Za-zàèéìòóù0-9_'-]+/gim,\n english: /[^A-Za-zàèéìòóù0-9_'-]+/gim,\n french: /[^a-z0-9äâàéèëêïîöôùüûœç-]+/gim,\n italian: /[^A-Za-zàèéìòóù0-9_'-]+/gim,\n norwegian: /[^a-z0-9_æøåÆØÅäÄöÖüÜ]+/gim,\n portuguese: /[^a-z0-9à-úÀ-Ú]/gim,\n russian: /[^a-z0-9а-яА-ЯёЁ]+/gim,\n spanish: /[^a-z0-9A-Zá-úÁ-ÚñÑüÜ]+/gim,\n swedish: /[^a-z0-9_åÅäÄöÖüÜ-]+/gim,\n german: /[^a-z0-9A-ZäöüÄÖÜß]+/gim,\n finnish: /[^a-z0-9äöÄÖ]+/gim,\n danish: /[^a-z0-9æøåÆØÅ]+/gim,\n hungarian: /[^a-z0-9áéíóöőúüűÁÉÍÓÖŐÚÜŰ]+/gim,\n romanian: /[^a-z0-9ăâîșțĂÂÎȘȚ]+/gim,\n serbian: /[^a-z0-9čćžšđČĆŽŠĐ]+/gim,\n turkish: /[^a-z0-9çÇğĞıİöÖşŞüÜ]+/gim,\n lithuanian: /[^a-z0-9ąčęėįšųūžĄČĘĖĮŠŲŪŽ]+/gim,\n arabic: /[^a-z0-9أ-ي]+/gim,\n nepali: /[^a-z0-9अ-ह]+/gim,\n irish: /[^a-z0-9áéíóúÁÉÍÓÚ]+/gim,\n indian: /[^a-z0-9अ-ह]+/gim,\n armenian: /[^a-z0-9ա-ֆ]+/gim,\n greek: /[^a-z0-9α-ωά-ώ]+/gim,\n indonesian: /[^a-z0-9]+/gim,\n ukrainian: /[^a-z0-9а-яА-ЯіїєІЇЄ]+/gim,\n slovenian: /[^a-z0-9螚ȎŠ]+/gim,\n bulgarian: /[^a-z0-9а-яА-Я]+/gim,\n tamil: /[^a-z0-9அ-ஹ]+/gim,\n sanskrit: /[^a-z0-9A-Zāīūṛḷṃṁḥśṣṭḍṇṅñḻḹṝ]+/gim,\n czech: /[^A-Z0-9a-zěščřžýáíéúůóťďĚŠČŘŽÝÁÍÉÓÚŮŤĎ-]+/gim\n}\n\nexport const SUPPORTED_LANGUAGES = Object.keys(STEMMERS)\n\nexport function getLocale(language: string | undefined) {\n return language !== undefined && SUPPORTED_LANGUAGES.includes(language) ? STEMMERS[language] : undefined\n}\n\nexport type Language = (typeof SUPPORTED_LANGUAGES)[number]\n","import type { AnyDocument, GeosearchDistanceUnit, Optional, Results, SearchableValue, TokenScore } from './types.js'\nimport { createError } from './errors.js'\n\nconst baseId = Date.now().toString().slice(5)\nlet lastId = 0\n\nconst k = 1024\nconst nano = BigInt(1e3)\nconst milli = BigInt(1e6)\nconst second = BigInt(1e9)\n\nexport const isServer = typeof window === 'undefined'\n\n/**\n * This value can be increased up to 100_000\n * But i don't know if this value change from nodejs to nodejs\n * So I will keep a safer value here.\n */\nexport const MAX_ARGUMENT_FOR_STACK = 65535\n\n/**\n * This method is needed to used because of issues like: https://github.com/oramasearch/orama/issues/301\n * that issue is caused because the array that is pushed is huge (>100k)\n *\n * @example\n * ```ts\n * safeArrayPush(myArray, [1, 2])\n * ```\n */\nexport function safeArrayPush<T>(arr: T[], newArr: T[]): void {\n if (newArr.length < MAX_ARGUMENT_FOR_STACK) {\n Array.prototype.push.apply(arr, newArr)\n } else {\n const newArrLength = newArr.length\n for (let i = 0; i < newArrLength; i += MAX_ARGUMENT_FOR_STACK) {\n Array.prototype.push.apply(arr, newArr.slice(i, i + MAX_ARGUMENT_FOR_STACK))\n }\n }\n}\n\nexport function sprintf(template: string, ...args: Array<string | number>): string {\n return template.replace(\n /%(?:(?<position>\\d+)\\$)?(?<width>-?\\d*\\.?\\d*)(?<type>[dfs])/g,\n function (...replaceArgs: Array<string | number | Record<string, string>>): string {\n const groups = replaceArgs[replaceArgs.length - 1] as Record<string, string>\n const { width: rawWidth, type, position } = groups\n\n const replacement = position ? args[Number.parseInt(position) - 1]! : args.shift()!\n const width = rawWidth === '' ? 0 : Number.parseInt(rawWidth)\n\n switch (type) {\n case 'd':\n return replacement.toString().padStart(width, '0')\n case 'f': {\n let value = replacement\n const [padding, precision] = rawWidth.split('.').map((w) => Number.parseFloat(w))\n\n if (typeof precision === 'number' && precision >= 0) {\n value = (value as number).toFixed(precision)\n }\n\n return typeof padding === 'number' && padding >= 0 ? value.toString().padStart(width, '0') : value.toString()\n }\n case 's':\n return width < 0\n ? (replacement as string).toString().padEnd(-width, ' ')\n : (replacement as string).toString().padStart(width, ' ')\n\n default:\n return replacement as string\n }\n }\n )\n}\n\nexport function formatBytes(bytes: number, decimals = 2): string {\n if (bytes === 0) {\n return '0 Bytes'\n }\n const dm = decimals < 0 ? 0 : decimals\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`\n}\n\nexport function isInsideWebWorker(): boolean {\n // @ts-expect-error - WebWorker global scope\n return typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope\n}\n\nexport function isInsideNode(): boolean {\n return typeof process !== 'undefined' && process.release && process.release.name === 'node'\n}\n\nexport function getNanosecondTimeViaPerformance() {\n return BigInt(Math.floor(performance.now() * 1e6))\n}\n\nexport function formatNanoseconds(value: number | bigint): string {\n if (typeof value === 'number') {\n value = BigInt(value)\n }\n\n if (value < nano) {\n return `${value}ns`\n } else if (value < milli) {\n return `${value / nano}μs`\n } else if (value < second) {\n return `${value / milli}ms`\n }\n\n return `${value / second}s`\n}\n\nexport function getNanosecondsTime(): bigint {\n if (isInsideWebWorker()) {\n return getNanosecondTimeViaPerformance()\n }\n\n if (isInsideNode()) {\n return process.hrtime.bigint()\n }\n\n if (typeof process !== 'undefined' && typeof process?.hrtime?.bigint === 'function') {\n return process.hrtime.bigint()\n }\n\n if (typeof performance !== 'undefined') {\n return getNanosecondTimeViaPerformance()\n }\n\n // @todo: fallback to V8 native method to get microtime\n return BigInt(0)\n}\n\nexport function uniqueId(): string {\n return `${baseId}-${lastId++}`\n}\n\nexport function getOwnProperty<T = unknown>(object: Record<string, T>, property: string): T | undefined {\n // Checks if `hasOwn` method is defined avoiding errors with older Node.js versions\n if (Object.hasOwn === undefined) {\n return Object.prototype.hasOwnProperty.call(object, property) ? object[property] : undefined\n }\n\n return Object.hasOwn(object, property) ? object[property] : undefined\n}\n\nexport function getTokenFrequency(token: string, tokens: string[]): number {\n let count = 0\n\n for (const t of tokens) {\n if (t === token) {\n count++\n }\n }\n\n return count\n}\n\nexport function insertSortedValue(\n arr: TokenScore[],\n el: TokenScore,\n compareFn = sortTokenScorePredicate\n): TokenScore[] {\n let low = 0\n let high = arr.length\n let mid\n\n while (low < high) {\n mid = (low + high) >>> 1\n if (compareFn(el, arr[mid]) < 0) {\n high = mid\n } else {\n low = mid + 1\n }\n }\n\n arr.splice(low, 0, el)\n\n return arr\n}\n\nexport function sortTokenScorePredicate(a: TokenScore, b: TokenScore): number {\n if (b[1] === a[1]) {\n return a[0] - b[0]\n }\n\n return b[1] - a[1]\n}\n\n// Intersection function taken from https://github.com/lovasoa/fast_array_intersect.\n// MIT Licensed at the time of writing.\nexport function intersect<T>(arrays: Array<readonly T[]>): T[] {\n if (arrays.length === 0) {\n return []\n } else if (arrays.length === 1) {\n return arrays[0] as T[]\n }\n\n for (let i = 1; i < arrays.length; i++) {\n if (arrays[i].length < arrays[0].length) {\n const tmp = arrays[0]\n arrays[0] = arrays[i]\n arrays[i] = tmp\n }\n }\n\n const set = new Map()\n for (const elem of arrays[0]) {\n set.set(elem, 1)\n }\n for (let i = 1; i < arrays.length; i++) {\n let found = 0\n for (const elem of arrays[i]) {\n const count = set.get(elem)\n if (count === i) {\n set.set(elem, count + 1)\n found++\n }\n }\n if (found === 0) return []\n }\n\n return arrays[0].filter((e) => {\n const count = set.get(e)\n if (count !== undefined) set.set(e, 0)\n return count === arrays.length\n })\n}\n\nexport function getDocumentProperties(doc: AnyDocument, paths: string[]): Record<string, SearchableValue> {\n const properties: Record<string, SearchableValue> = {}\n\n const pathsLength = paths.length\n for (let i = 0; i < pathsLength; i++) {\n const path = paths[i]\n const pathTokens = path.split('.')\n\n let current: SearchableValue | AnyDocument | undefined = doc\n const pathTokensLength = pathTokens.length\n for (let j = 0; j < pathTokensLength; j++) {\n current = current[pathTokens[j]!]\n\n // We found an object but we were supposed to be done\n if (typeof current === 'object') {\n if (\n current !== null &&\n 'lat' in current &&\n 'lon' in current &&\n typeof current.lat === 'number' &&\n typeof current.lon === 'number'\n ) {\n current = properties[path] = current as SearchableValue\n break\n } else if (!Array.isArray(current) && current !== null && j === pathTokensLength - 1) {\n current = undefined\n break\n }\n } else if ((current === null || typeof current !== 'object') && j < pathTokensLength - 1) {\n // We can't recurse anymore but we were supposed to\n current = undefined\n break\n }\n }\n\n if (typeof current !== 'undefined') {\n properties[path] = current as SearchableValue\n }\n }\n\n return properties\n}\n\nexport function getNested<T = SearchableValue>(obj: object, path: string): Optional<T> {\n const props = getDocumentProperties(obj as AnyDocument, [path])\n\n return props[path] as T | undefined\n}\n\nexport function flattenObject(obj: object, prefix = ''): AnyDocument {\n const result: AnyDocument = {}\n\n for (const key in obj) {\n const prop = `${prefix}${key}`\n const objKey = (obj as AnyDocument)[key]\n\n if (typeof objKey === 'object' && objKey !== null) {\n Object.assign(result, flattenObject(objKey, `${prop}.`))\n } else {\n result[prop] = objKey\n }\n }\n return result\n}\n\nconst mapDistanceToMeters = {\n cm: 0.01,\n m: 1,\n km: 1000,\n ft: 0.3048,\n yd: 0.9144,\n mi: 1609.344\n}\n\nexport function convertDistanceToMeters(distance: number, unit: GeosearchDistanceUnit): number {\n const ratio = mapDistanceToMeters[unit]\n\n if (ratio === undefined) {\n throw new Error(createError('INVALID_DISTANCE_SUFFIX', distance).message)\n }\n\n return distance * ratio\n}\n\nexport function removeVectorsFromHits(searchResult: Results<AnyDocument>, vectorProperties: string[]): void {\n searchResult.hits = searchResult.hits.map((result) => ({\n ...result,\n document: {\n ...result.document,\n // Remove embeddings from the result\n ...vectorProperties.reduce((acc, prop) => {\n const path = prop.split('.')\n const lastKey = path.pop()!\n let obj = acc\n for (const key of path) {\n obj[key] = obj[key] ?? {}\n obj = obj[key] as any\n }\n obj[lastKey] = null\n return acc\n }, result.document)\n }\n }))\n}\n\nexport function isPromise(obj: any): obj is Promise<unknown> {\n return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function'\n}\n\n/**\n * Checks if the provided input is an async function or if the input is an array\n * containing at least one async function.\n *\n * @param func - A single function or an array of functions to check.\n * Non-function values are ignored.\n * @returns `true` if the input is an async function or an array containing at least\n * one async function, otherwise `false`.\n */\nexport function isAsyncFunction(func: any): boolean {\n if (Array.isArray(func)) {\n return func.some((item) => isAsyncFunction(item))\n }\n\n return func?.constructor?.name === 'AsyncFunction'\n}\n\nconst withIntersection = 'intersection' in new Set()\n\nexport function setIntersection<V>(...sets: Set<V>[]): Set<V> {\n // Fast path 1\n if (sets.length === 0) {\n return new Set()\n }\n // Fast path 2\n if (sets.length === 1) {\n return sets[0]\n }\n // Fast path 3\n if (sets.length === 2) {\n const set1 = sets[0]\n const set2 = sets[1]\n\n if (withIntersection) {\n return set1.intersection(set2)\n }\n const result = new Set<V>()\n const base = set1.size < set2.size ? set1 : set2\n const other = base === set1 ? set2 : set1\n for (const value of base) {\n if (other.has(value)) {\n result.add(value)\n }\n }\n return result\n }\n\n // Slow path\n // Find the smallest set\n const min = {\n index: 0,\n size: sets[0].size\n }\n for (let i = 1; i < sets.length; i++) {\n if (sets[i].size < min.size) {\n min.index = i\n min.size = sets[i].size\n }\n }\n\n if (withIntersection) {\n let base = sets[min.index]\n for (let i = 0; i < sets.length; i++) {\n if (i === min.index) {\n continue\n }\n base = base.intersection(sets[i])\n }\n\n return base\n }\n\n // manual implementation:\n // intersect all sets with the smallest set\n const base = sets[min.index]\n for (let i = 0; i < sets.length; i++) {\n if (i === min.index) {\n continue\n }\n const other = sets[i]\n for (const value of base) {\n if (!other.has(value)) {\n base.delete(value)\n }\n }\n }\n\n return base\n}\n\nconst withUnion = 'union' in new Set()\nexport function setUnion<V>(set1: Set<V> | undefined, set2: Set<V>) {\n if (withUnion) {\n if (set1) {\n return set1.union(set2)\n }\n return set2\n }\n\n if (!set1) {\n return new Set(set2)\n }\n return new Set([...set1, ...set2])\n}\n\nexport function setDifference<V>(set1: Set<V>, set2: Set<V>): Set<V> {\n const result = new Set<V>()\n for (const value of set1) {\n if (!set2.has(value)) {\n result.add(value)\n }\n }\n return result\n}\n\n// This code is taken from https://github.com/davidmarkclements/atomic-sleep, MIT licensed at the time of commit b8149d3ca276c84a54fa8fa1478f9cc79aabc15a.\n// All credits go to the original author (David Mark Clements, https://github.com/davidmarkclements).\nexport function sleep(ms: number) {\n if (typeof SharedArrayBuffer !== 'undefined' && typeof Atomics !== 'undefined') {\n const nil = new Int32Array(new SharedArrayBuffer(4))\n const valid = ms > 0 && ms < Infinity\n if (valid === false) {\n if (typeof ms !== 'number' && typeof ms !== 'bigint') {\n throw TypeError('sleep: ms must be a number')\n }\n throw RangeError('sleep: ms must be a number that is greater than 0 but less than Infinity')\n }\n\n Atomics.wait(nil, 0, 0, Number(ms))\n } else {\n const valid = ms > 0 && ms < Infinity\n if (valid === false) {\n if (typeof ms !== 'number' && typeof ms !== 'bigint') {\n throw TypeError('sleep: ms must be a number')\n }\n throw RangeError('sleep: ms must be a number that is greater than 0 but less than Infinity')\n }\n const target = Date.now() + Number(ms)\n while (target > Date.now()) {\n /* empty */\n }\n }\n}\n","import { SUPPORTED_LANGUAGES } from './components/tokenizer/languages.js'\nimport { sprintf } from './utils.js'\n\nconst allLanguages = SUPPORTED_LANGUAGES.join('\\n - ')\n\nconst errors = {\n NO_LANGUAGE_WITH_CUSTOM_TOKENIZER: 'Do not pass the language option to create when using a custom tokenizer.',\n LANGUAGE_NOT_SUPPORTED: `Language \"%s\" is not supported.\\nSupported languages are:\\n - ${allLanguages}`,\n INVALID_STEMMER_FUNCTION_TYPE: `config.stemmer property must be a function.`,\n MISSING_STEMMER: `As of version 1.0.0 @orama/orama does not ship non English stemmers by default. To solve this, please explicitly import and specify the \"%s\" stemmer from the package @orama/stemmers. See https://docs.orama.com/docs/orama-js/text-analysis/stemming for more information.`,\n CUSTOM_STOP_WORDS_MUST_BE_FUNCTION_OR_ARRAY: 'Custom stop words array must only contain strings.',\n UNSUPPORTED_COMPONENT: `Unsupported component \"%s\".`,\n COMPONENT_MUST_BE_FUNCTION: `The component \"%s\" must be a function.`,\n COMPONENT_MUST_BE_FUNCTION_OR_ARRAY_FUNCTIONS: `The component \"%s\" must be a function or an array of functions.`,\n INVALID_SCHEMA_TYPE: `Unsupported schema type \"%s\" at \"%s\". Expected \"string\", \"boolean\" or \"number\" or array of them.`,\n DOCUMENT_ID_MUST_BE_STRING: `Document id must be of type \"string\". Got \"%s\" instead.`,\n DOCUMENT_ALREADY_EXISTS: `A document with id \"%s\" already exists.`,\n DOCUMENT_DOES_NOT_EXIST: `A document with id \"%s\" does not exists.`,\n MISSING_DOCUMENT_PROPERTY: `Missing searchable property \"%s\".`,\n INVALID_DOCUMENT_PROPERTY: `Invalid document property \"%s\": expected \"%s\", got \"%s\"`,\n UNKNOWN_INDEX: `Invalid property name \"%s\". Expected a wildcard string (\"*\") or array containing one of the following properties: %s`,\n INVALID_BOOST_VALUE: `Boost value must be a number greater than, or less than 0.`,\n INVALID_FILTER_OPERATION: `You can only use one operation per filter, you requested %d.`,\n SCHEMA_VALIDATION_FAILURE: `Cannot insert document due schema validation failure on \"%s\" property.`,\n INVALID_SORT_SCHEMA_TYPE: `Unsupported sort schema type \"%s\" at \"%s\". Expected \"string\" or \"number\".`,\n CANNOT_SORT_BY_ARRAY: `Cannot configure sort for \"%s\" because it is an array (%s).`,\n UNABLE_TO_SORT_ON_UNKNOWN_FIELD: `Unable to sort on unknown field \"%s\". Allowed fields: %s`,\n SORT_DISABLED: `Sort is disabled. Please read the documentation at https://docs.orama.com/docs/orama-js for more information.`,\n UNKNOWN_GROUP_BY_PROPERTY: `Unknown groupBy property \"%s\".`,\n INVALID_GROUP_BY_PROPERTY: `Invalid groupBy property \"%s\". Allowed types: \"%s\", but given \"%s\".`,\n UNKNOWN_FILTER_PROPERTY: `Unknown filter property \"%s\".`,\n UNKNOWN_VECTOR_PROPERTY: `Unknown vector property \"%s\". Make sure the property exists in the schema and is configured as a vector.`,\n INVALID_VECTOR_SIZE: `Vector size must be a number greater than 0. Got \"%s\" instead.`,\n INVALID_VECTOR_VALUE: `Vector value must be a number greater than 0. Got \"%s\" instead.`,\n INVALID_INPUT_VECTOR: `Property \"%s\" was declared as a %s-dimensional vector, but got a %s-dimensional vector instead.\\nInput vectors must be of the size declared in the schema, as calculating similarity between vectors of different sizes can lead to unexpected results.`,\n WRONG_SEARCH_PROPERTY_TYPE: `Property \"%s\" is not searchable. Only \"string\" properties are searchable.`,\n FACET_NOT_SUPPORTED: `Facet doens't support the type \"%s\".`,\n INVALID_DISTANCE_SUFFIX: `Invalid distance suffix \"%s\". Valid suffixes are: cm, m, km, mi, yd, ft.`,\n INVALID_SEARCH_MODE: `Invalid search mode \"%s\". Valid modes are: \"fulltext\", \"vector\", \"hybrid\".`,\n MISSING_VECTOR_AND_SECURE_PROXY: `No vector was provided and no secure proxy was configured. Please provide a vector or configure an Orama Secure Proxy to perform hybrid search.`,\n MISSING_TERM: `\"term\" is a required parameter when performing hybrid search. Please provide a search term.`,\n INVALID_VECTOR_INPUT: `Invalid \"vector\" property. Expected an object with \"value\" and \"property\" properties, but got \"%s\" instead.`,\n PLUGIN_CRASHED: `A plugin crashed during initialization. Please check the error message for more information:`,\n PLUGIN_SECURE_PROXY_NOT_FOUND: `Could not find '@orama/secure-proxy-plugin' installed in your Orama instance.\\nPlease install it before proceeding with creating an answer session.\\nRead more at https://docs.orama.com/docs/orama-js/plugins/plugin-secure-proxy#plugin-secure-proxy\\n`,\n PLUGIN_SECURE_PROXY_MISSING_CHAT_MODEL: `Could not find a chat model defined in the secure proxy plugin configuration.\\nPlease provide a chat model before proceeding with creating an answer session.\\nRead more at https://docs.orama.com/docs/orama-js/plugins/plugin-secure-proxy#plugin-secure-proxy\\n`,\n ANSWER_SESSION_LAST_MESSAGE_IS_NOT_ASSISTANT: `The last message in the session is not an assistant message. Cannot regenerate non-assistant messages.`,\n PLUGIN_COMPONENT_CONFLICT: `The component \"%s\" is already defined. The plugin \"%s\" is trying to redefine it.`\n}\n\nexport type ErrorCode = keyof typeof errors\n\nexport interface OramaError extends Error {\n code: string\n}\n\nexport function createError(code: ErrorCode, ...args: Array<string | number>): OramaError {\n const error = new Error(sprintf(errors[code] ?? `Unsupported Orama Error code: ${code}`, ...args)) as OramaError\n error.code = code\n if ('captureStackTrace' in Error.prototype) {\n Error.captureStackTrace(error)\n }\n\n return error\n}\n","import type { Optional } from '../types.js'\nimport { createError } from '../errors.js'\nimport { Point } from '../trees/bkd.js'\nimport {\n AnyDocument,\n AnyOrama,\n ArraySearchableType,\n ElapsedTime,\n ScalarSearchableType,\n SearchableType,\n TypedDocument,\n Vector\n} from '../types.js'\nimport { formatNanoseconds, uniqueId } from '../utils.js'\n\nexport { getDocumentProperties } from '../utils.js'\n\nexport function formatElapsedTime(n: bigint): ElapsedTime {\n return {\n raw: Number(n),\n formatted: formatNanoseconds(n)\n }\n}\n\nexport function getDocumentIndexId(doc: AnyDocument): string {\n if (doc.id) {\n if (typeof doc.id !== 'string') {\n throw createError('DOCUMENT_ID_MUST_BE_STRING', typeof doc.id)\n }\n\n return doc.id\n }\n\n return uniqueId()\n}\n\nexport function validateSchema<T extends AnyOrama, ResultDocument extends TypedDocument<T>>(\n doc: ResultDocument,\n schema: T['schema']\n): Optional<string> {\n for (const [prop, type] of Object.entries(schema)) {\n const value = doc[prop]\n\n if (typeof value === 'undefined') {\n continue\n }\n\n if (\n type === 'geopoint' &&\n typeof value === 'object' &&\n typeof value.lon === 'number' &&\n typeof value.lat === 'number'\n ) {\n continue\n }\n\n if (type === 'enum' && (typeof value === 'string' || typeof value === 'number')) {\n continue\n }\n if (type === 'enum[]' && Array.isArray(value)) {\n const valueLength = value.length\n for (let i = 0; i < valueLength; i++) {\n if (typeof value[i] !== 'string' && typeof value[i] !== 'number') {\n return prop + '.' + i\n }\n }\n continue\n }\n\n if (isVectorType(type)) {\n const vectorSize = getVectorSize(type)\n if (!Array.isArray(value) || value.length !== vectorSize) {\n throw createError('INVALID_INPUT_VECTOR', prop, vectorSize, value.length)\n }\n continue\n }\n\n if (isArrayType(type)) {\n if (!Array.isArray(value)) {\n return prop\n }\n const expectedType = getInnerType(type)\n\n const valueLength = value.length\n for (let i = 0; i < valueLength; i++) {\n if (typeof value[i] !== expectedType) {\n return prop + '.' + i\n }\n }\n\n continue\n }\n\n if (typeof type === 'object') {\n if (!value || typeof value !== 'object') {\n return prop\n }\n\n // using as ResultDocument is not exactly right but trying to be type-safe here is not useful\n const subProp = validateSchema(value as ResultDocument, type)\n if (subProp) {\n return prop + '.' + subProp\n }\n continue\n }\n\n if (typeof value !== type) {\n return prop\n }\n }\n\n return undefined\n}\n\nconst IS_ARRAY_TYPE: Record<SearchableType, boolean> = {\n string: false,\n number: false,\n boolean: false,\n enum: false,\n geopoint: false,\n 'string[]': true,\n 'number[]': true,\n 'boolean[]': true,\n 'enum[]': true\n}\n\nconst INNER_TYPE: Record<ArraySearchableType, ScalarSearchableType> = {\n 'string[]': 'string',\n 'number[]': 'number',\n 'boolean[]': 'boolean',\n 'enum[]': 'enum'\n}\n\nexport function isGeoPointType(type: unknown): type is Point {\n return type === 'geopoint'\n}\n\nexport function isVectorType(type: unknown): type is Vector {\n return typeof type === 'string' && /^vector\\[\\d+\\]$/.test(type)\n}\n\nexport function isArrayType(type: unknown): type is ArraySearchableType {\n return typeof type === 'string' && IS_ARRAY_TYPE[type]\n}\n\nexport function getInnerType(type: ArraySearchableType): ScalarSearchableType {\n return INNER_TYPE[type]\n}\n\nexport function getVectorSize(type: string): number {\n const size = Number(type.slice(7, -1))\n\n switch (true) {\n case isNaN(size):\n throw createError('INVALID_VECTOR_VALUE', type)\n case size <= 0:\n throw createError('INVALID_VECTOR_SIZE', type)\n default:\n return size\n }\n}\n","import { AnyOrama } from '../types.js'\n\nexport type DocumentID = string | number\nexport type InternalDocumentID = number\n\nexport type InternalDocumentIDStore = {\n idToInternalId: Map<string, number>\n internalIdToId: string[]\n save: (store: InternalDocumentIDStore) => unknown\n load: <T extends AnyOrama>(orama: T, raw: unknown) => void\n}\n\nexport function createInternalDocumentIDStore(): InternalDocumentIDStore {\n return {\n idToInternalId: new Map(),\n internalIdToId: [],\n save,\n load\n }\n}\n\nexport function save(store: InternalDocumentIDStore): unknown {\n return {\n internalIdToId: store.internalIdToId\n }\n}\n\nexport function load<T extends AnyOrama>(orama: T, raw: unknown): void {\n const { internalIdToId } = raw as InternalDocumentIDStore\n\n orama.internalDocumentIDStore.idToInternalId.clear()\n orama.internalDocumentIDStore.internalIdToId = []\n const internalIdToIdLength = internalIdToId.length\n\n for (let i = 0; i < internalIdToIdLength; i++) {\n const internalIdItem = internalIdToId[i]\n orama.internalDocumentIDStore.idToInternalId.set(internalIdItem, i + 1)\n orama.internalDocumentIDStore.internalIdToId.push(internalIdItem)\n }\n}\n\nexport function getInternalDocumentId(store: InternalDocumentIDStore, id: DocumentID): InternalDocumentID {\n if (typeof id === 'string') {\n const internalId = store.idToInternalId.get(id)\n\n if (internalId) {\n return internalId\n }\n\n const currentId = store.idToInternalId.size + 1\n\n store.idToInternalId.set(id, currentId)\n store.internalIdToId.push(id)\n\n return currentId\n }\n\n if (id > store.internalIdToId.length) {\n return getInternalDocumentId(store, id.toString())\n }\n\n return id\n}\n\nexport function getDocumentIdFromInternalId(store: InternalDocumentIDStore, internalId: InternalDocumentID): string {\n if (store.internalIdToId.length < internalId) {\n throw new Error(`Invalid internalId ${internalId}`)\n }\n\n return store.internalIdToId[internalId - 1]\n}\n","import type {\n AnyIndexStore,\n AnyOrama,\n ArraySearchableType,\n BM25Params,\n ComparisonOperator,\n EnumArrComparisonOperator,\n EnumComparisonOperator,\n GeosearchOperation,\n GeosearchPolygonOperator,\n GeosearchRadiusOperator,\n IIndex,\n ScalarSearchableType,\n SearchableType,\n SearchableValue,\n Tokenizer,\n TokenScore,\n WhereCondition\n} from '../types.js'\nimport type { InsertOptions } from '../methods/insert.js'\nimport type { Point as BKDGeoPoint } from '../trees/bkd.js'\nimport type { Point } from '../trees/bkd.js'\nimport { FindResult, RadixNode } from '../trees/radix.js'\nimport { createError } from '../errors.js'\nimport { AVLTree } from '../trees/avl.js'\nimport { FlatTree } from '../trees/flat.js'\nimport { RadixTree } from '../trees/radix.js'\nimport { BKDTree } from '../trees/bkd.js'\nimport { BoolNode } from '../trees/bool.js'\n\nimport { convertDistanceToMeters, setIntersection, setUnion, setDifference } from '../utils.js'\nimport { BM25 } from './algorithms.js'\nimport { getInnerType, getVectorSize, isArrayType, isVectorType } from './defaults.js'\nimport {\n DocumentID,\n getInternalDocumentId,\n InternalDocumentID,\n InternalDocumentIDStore\n} from './internal-document-id-store.js'\nimport { VectorIndex, VectorType } from '../trees/vector.js'\n\nexport type FrequencyMap = {\n [property: string]: {\n [documentID: InternalDocumentID]:\n | {\n [token: string]: number\n }\n | undefined\n }\n}\n\nexport type TreeType = 'AVL' | 'Radix' | 'Bool' | 'Flat' | 'BKD'\n\nexport type TTree<T = TreeType, N = unknown> = {\n type: T\n node: N\n isArray: boolean\n}\n\nexport type Tree =\n | TTree<'Radix', RadixNode>\n | TTree<'AVL', AVLTree<number, InternalDocumentID>>\n | TTree<'Bool', BoolNode<InternalDocumentID>>\n | TTree<'Flat', FlatTree>\n | TTree<'BKD', BKDTree>\n\nexport interface Index extends AnyIndexStore {\n sharedInternalDocumentStore: InternalDocumentIDStore\n indexes: Record<string, Tree>\n // vectorIndexes: Record<string, TTree<'Vector', VectorIndex>>\n searchableProperties: string[]\n searchablePropertiesWithTypes: Record<string, SearchableType>\n frequencies: FrequencyMap\n tokenOccurrences: Record<string, Record<string, number>>\n avgFieldLength: Record<string, number>\n fieldLengths: Record<string, Record<InternalDocumentID, number | undefined>>\n}\n\nexport function insertDocumentScoreParameters(\n index: Index,\n prop: string,\n id: DocumentID,\n tokens: string[],\n docsCount: number\n): void {\n const internalId = getInternalDocumentId(index.sharedInternalDocumentStore, id)\n\n index.avgFieldLength[prop] = ((index.avgFieldLength[prop] ?? 0) * (docsCount - 1) + tokens.length) / docsCount\n index.fieldLengths[prop][internalId] = tokens.length\n index.frequencies[prop][internalId] = {}\n}\n\nexport function insertTokenScoreParameters(\n index: Index,\n prop: string,\n id: DocumentID,\n tokens: string[],\n token: string\n): void {\n let tokenFrequency = 0\n\n for (const t of tokens) {\n if (t === token) {\n tokenFrequency++\n }\n }\n\n const internalId = getInternalDocumentId(index.sharedInternalDocumentStore, id)\n const tf = tokenFrequency / tokens.length\n\n index.frequencies[prop][internalId]![token] = tf\n\n if (!(token in index.tokenOccurrences[prop])) {\n index.tokenOccurrences[prop][token] = 0\n }\n\n // increase a token counter that may not yet exist\n index.tokenOccurrences[prop][token] = (index.tokenOccurrences[prop][token] ?? 0) + 1\n}\n\nexport function removeDocumentScoreParameters(index: Index, prop: string, id: DocumentID, docsCount: number): void {\n const internalId = getInternalDocumentId(index.sharedInternalDocumentStore, id)\n\n if (docsCount > 1) {\n index.avgFieldLength[prop] =\n (index.avgFieldLength[prop] * docsCount - index.fieldLengths[prop][internalId]!) / (docsCount - 1)\n } else {\n index.avgFieldLength[prop] = undefined as unknown as number\n }\n index.fieldLengths[prop][internalId] = undefined\n index.frequencies[prop][internalId] = undefined\n}\n\nexport function removeTokenScoreParameters(index: Index, prop: string, token: string): void {\n index.tokenOccurrences[prop][token]--\n}\n\nexport function create<T extends AnyOrama, TSchema extends T['schema']>(\n orama: T,\n sharedInternalDocumentStore: T['internalDocumentIDStore'],\n schema: TSchema,\n index?: Index,\n prefix = ''\n): Index {\n if (!index) {\n index = {\n sharedInternalDocumentStore,\n indexes: {},\n vectorIndexes: {},\n searchableProperties: [],\n searchablePropertiesWithTypes: {},\n frequencies: {},\n tokenOccurrences: {},\n avgFieldLength: {},\n fieldLengths: {}\n }\n }\n\n for (const [prop, type] of Object.entries<SearchableType>(schema)) {\n const path = `${prefix}${prefix ? '.' : ''}${prop}`\n\n if (typeof type === 'object' && !Array.isArray(type)) {\n // Nested\n create(orama, sharedInternalDocumentStore, type, index, path)\n continue\n }\n\n if (isVectorType(type)) {\n index.searchableProperties.push(path)\n index.searchablePropertiesWithTypes[path] = type\n index.vectorIndexes[path] = {\n type: 'Vector',\n node: new VectorIndex(getVectorSize(type)),\n isArray: false\n }\n } else {\n const isArray = /\\[/.test(type as string)\n switch (type) {\n case 'boolean':\n case 'boolean[]':\n index.indexes[path] = { type: 'Bool', node: new BoolNode(), isArray }\n break\n case 'number':\n case 'number[]':\n index.indexes[path] = { type: 'AVL', node: new AVLTree<number, InternalDocumentID>(0, []), isArray }\n break\n case 'string':\n case 'string[]':\n index.indexes[path] = { type: 'Radix', node: new RadixTree(), isArray }\n index.avgFieldLength[path] = 0\n index.frequencies[path] = {}\n index.tokenOccurrences[path] = {}\n index.fieldLengths[path] = {}\n break\n case 'enum':\n case 'enum[]':\n index.indexes[path] = { type: 'Flat', node: new FlatTree(), isArray }\n break\n case 'geopoint':\n index.indexes[path] = { type: 'BKD', node: new BKDTree(), isArray }\n break\n default:\n throw createError('INVALID_SCHEMA_TYPE', Array.isArray(type) ? 'array' : type, path)\n }\n\n index.searchableProperties.push(path)\n index.searchablePropertiesWithTypes[path] = type\n }\n }\n\n return index\n}\n\nfunction insertScalarBuilder(\n implementation: IIndex<Index>,\n index: Index,\n prop: string,\n internalId: InternalDocumentID,\n language: string | undefined,\n tokenizer: Tokenizer,\n docsCount: number,\n options?: InsertOptions\n) {\n return (value: SearchableValue) => {\n const { type, node } = index.indexes[prop]\n switch (type) {\n case 'Bool': {\n node[value ? 'true' : 'false'].add(internalId)\n break\n }\n case 'AVL': {\n const avlRebalanceThreshold = options?.avlRebalanceThreshold ?? 1\n node.insert(value as number, internalId, avlRebalanceThreshold)\n break\n }\n case 'Radix': {\n const tokens = tokenizer.tokenize(value as string, language, prop, false)\n implementation.insertDocumentScoreParameters(index, prop, internalId, tokens, docsCount)\n\n for (const token of tokens) {\n implementation.insertTokenScoreParameters(index, prop, internalId, tokens, token)\n\n node.insert(token, internalId)\n }\n\n break\n }\n case 'Flat': {\n node.insert(value as ScalarSearchableType, internalId)\n break\n }\n case 'BKD': {\n node.insert(value as unknown as BKDGeoPoint, [internalId])\n break\n }\n }\n }\n}\n\nexport function insert(\n implementation: IIndex<Index>,\n index: Index,\n prop: string,\n id: DocumentID,\n internalId: InternalDocumentID,\n value: SearchableValue,\n schemaType: SearchableType,\n language: string | undefined,\n tokenizer: Tokenizer,\n docsCount: number,\n options?: InsertOptions\n): void {\n if (isVectorType(schemaType)) {\n return insertVector(index, prop, value as number[] | Float32Array, id, internalId)\n }\n\n const insertScalar = insertScalarBuilder(\n implementation,\n index,\n prop,\n internalId,\n language,\n tokenizer,\n docsCount,\n options\n )\n\n if (!isArrayType(schemaType)) {\n return insertScalar(value)\n }\n\n const elements = value as Array<string | number | boolean>\n const elementsLength = elements.length\n for (let i = 0; i < elementsLength; i++) {\n insertScalar(elements[i])\n }\n}\n\nexport function insertVector(\n index: AnyIndexStore,\n prop: string,\n value: number[] | VectorType,\n id: DocumentID,\n internalDocumentId: InternalDocumentID\n): void {\n index.vectorIndexes[prop].node.add(internalDocumentId, value)\n}\n\nfunction removeScalar(\n implementation: IIndex<Index>,\n index: Index,\n prop: string,\n id: DocumentID,\n internalId: InternalDocumentID,\n value: SearchableValue,\n schemaType: ScalarSearchableType,\n language: string | undefined,\n tokenizer: Tokenizer,\n docsCount: number\n): boolean {\n if (isVectorType(schemaType)) {\n index.vectorIndexes[prop].node.remove(internalId)\n return true\n }\n\n const { type, node } = index.indexes[prop]\n switch (type) {\n case 'AVL': {\n node.removeDocument(value as number, internalId)\n return true\n }\n case 'Bool': {\n node[value ? 'true' : 'false'].delete(internalId)\n return true\n }\n case 'Radix': {\n const tokens = tokenizer.tokenize(value as string, language, prop)\n\n implementation.removeDocumentScoreParameters(index, prop, id, docsCount)\n\n for (const token of tokens) {\n implementation.removeTokenScoreParameters(index, prop, token)\n node.removeDocumentByWord(token, internalId)\n }\n\n return true\n }\n case 'Flat': {\n node.removeDocument(internalId, value as ScalarSearchableType)\n return true\n }\n case 'BKD': {\n node.removeDocByID(value as unknown as BKDGeoPoint, internalId)\n return false\n }\n }\n}\n\nexport function remove(\n implementation: IIndex<Index>,\n index: Index,\n prop: string,\n id: DocumentID,\n internalId: InternalDocumentID,\n value: SearchableValue,\n schemaType: SearchableType,\n language: string | undefined,\n tokenizer: Tokenizer,\n docsCount: number\n): boolean {\n if (!isArrayType(schemaType)) {\n return removeScalar(\n implementation,\n index,\n prop,\n id,\n internalId,\n value,\n schemaType as ScalarSearchableType,\n language,\n tokenizer,\n docsCount\n )\n }\n\n const innerSchemaType = getInnerType(schemaType as ArraySearchableType)\n\n const elements = value as Array<string | number | boolean>\n const elementsLength = elements.length\n for (let i = 0; i < elementsLength; i++) {\n removeScalar(\n implementation,\n index,\n prop,\n id,\n internalId,\n elements[i],\n innerSchemaType,\n language,\n tokenizer,\n docsCount\n )\n }\n\n return true\n}\n\nexport function calculateResultScores(\n index: Index,\n prop: string,\n term: string,\n ids: InternalDocumentID[],\n docsCount: number,\n bm25Relevance: Required<BM25Params>,\n resultsMap: Map<number, number>,\n boostPerProperty: number,\n whereFiltersIDs: Set<InternalDocumentID> | undefined,\n keywordMatchesMap: Map<InternalDocumentID, Map<string, number>>\n) {\n const documentIDs = Array.from(ids)\n\n const avgFieldLength = index.avgFieldLength[prop]\n const fieldLengths = index.fieldLengths[prop]\n const oramaOccurrences = index.tokenOccurrences[prop]\n const oramaFrequencies = index.frequencies[prop]\n\n // oramaOccurrences[term] can be undefined, 0, string, or { [k: string]: number }\n const termOccurrences = typeof oramaOccurrences[term] === 'number' ? (oramaOccurrences[term] ?? 0) : 0\n\n // Calculate TF-IDF value for each term, in each document, for each index.\n const documentIDsLength = documentIDs.length\n for (let k = 0; k < documentIDsLength; k++) {\n const internalId = documentIDs[k]\n if (whereFiltersIDs && !whereFiltersIDs.has(internalId)) {\n continue\n }\n\n // Track keyword matches per property\n if (!keywordMatchesMap.has(internalId)) {\n keywordMatchesMap.set(internalId, new Map())\n }\n const propertyMatches = keywordMatchesMap.get(internalId)!\n propertyMatches.set(prop, (propertyMatches.get(prop) || 0) + 1)\n\n const tf = oramaFrequencies?.[internalId]?.[term] ?? 0\n\n const bm25 = BM25(tf, termOccurrences, docsCount, fieldLengths[internalId]!, avgFieldLength, bm25Relevance)\n\n if (resultsMap.has(internalId)) {\n resultsMap.set(internalId, resultsMap.get(internalId)! + bm25 * boostPerProperty)\n } else {\n resultsMap.set(internalId, bm25 * boostPerProperty)\n }\n }\n}\n\nexport function search(\n index: Index,\n term: string,\n tokenizer: Tokenizer,\n language: string | undefined,\n propertiesToSearch: string[],\n exact: boolean,\n tolerance: number,\n boost: Record<string, number>,\n relevance: Required<BM25Params>,\n docsCount: number,\n whereFiltersIDs: Set<InternalDocumentID> | undefined,\n threshold = 0\n): TokenScore[] {\n const tokens = tokenizer.tokenize(term, language)\n const keywordsCount = tokens.length || 1\n\n // Track keyword matches per document and property\n const keywordMatchesMap = new Map<InternalDocumentID, Map<string, number>>()\n // Track which tokens were found in the search\n const tokenFoundMap = new Map<string, boolean>()\n const resultsMap = new Map<number, number>()\n\n for (const prop of propertiesToSearch) {\n if (!(prop in index.indexes)) {\n continue\n }\n\n const tree = index.indexes[prop]\n const { type } = tree\n if (type !== 'Radix') {\n throw createError('WRONG_SEARCH_PROPERTY_TYPE', prop)\n }\n const boostPerProperty = boost[prop] ?? 1\n if (boostPerProperty <= 0) {\n throw createError('INVALID_BOOST_VALUE', boostPerProperty)\n }\n\n // if the tokenizer returns an empty array, we returns all the documents\n if (tokens.length === 0 && !term) {\n tokens.push('')\n }\n\n // Process each token in the search term\n const tokenLength = tokens.length\n for (let i = 0; i < tokenLength; i++) {\n const token = tokens[i]\n const searchResult = tree.node.find({ term: token, exact, tolerance })\n\n // See if this token was found (for threshold=0 filtering)\n const termsFound = Object.keys(searchResult)\n if (termsFound.length > 0) {\n tokenFoundMap.set(token, true)\n }\n\n // Process each matching term\n const termsFoundLength = termsFound.length\n for (let j = 0; j < termsFoundLength; j++) {\n const word = termsFound[j]\n const ids = searchResult[word]\n calculateResultScores(\n index,\n prop,\n word,\n ids,\n docsCount,\n relevance,\n resultsMap,\n boostPerProperty,\n whereFiltersIDs,\n keywordMatchesMap\n )\n }\n }\n }\n\n // Convert to array and sort by score\n const results = Array.from(resultsMap.entries())\n .map(([id, score]): TokenScore => [id, score])\n .sort((a, b) => b[1] - a[1])\n\n if (results.length === 0) {\n return []\n }\n\n // If threshold is 1, return all results\n if (threshold === 1) {\n return results\n }\n\n // For threshold=0, check if all tokens were found\n if (threshold === 0) {\n // Quick return for single tokens - already validated\n if (keywordsCount === 1) {\n return results\n }\n\n // For multiple tokens, verify that ALL tokens were found\n // If any token wasn't found, return an empty result\n for (const token of tokens) {\n if (!tokenFoundMap.get(token)) {\n return []\n }\n }\n\n // Find documents that have all keywords in at least one property\n const fullMatches = results.filter(([id]) => {\n const propertyMatches = keywordMatchesMap.get(id)\n if (!propertyMatches) return false\n\n // Check if any property has all keywords\n return Array.from(propertyMatches.values()).some((matches) => matches === keywordsCount)\n })\n\n return fullMatches\n }\n\n // Find documents that have all keywords in at least one property\n const fullMatches = results.filter(([id]) => {\n const propertyMatches = keywordMatchesMap.get(id)\n if (!propertyMatches) return false\n\n // Check if any property has all keywords\n return Array.from(propertyMatches.values()).some((matches) => matches === keywordsCount)\n })\n\n // If we have full matches and threshold < 1, return full matches plus a percentage of partial matches\n if (fullMatches.length > 0) {\n const remainingResults = results.filter(([id]) => !fullMatches.some(([fid]) => fid === id))\n const additionalResults = Math.ceil(remainingResults.length * threshold)\n return [...fullMatches, ...remainingResults.slice(0, additionalResults)]\n }\n\n // If no full matches, return all results\n return results\n}\n\nexport function searchByWhereClause<T extends AnyOrama>(\n index: Index,\n tokenizer: Tokenizer,\n filters: Partial<WhereCondition<T['schema']>>,\n language: string | undefined\n): Set<InternalDocumentID> {\n // Handle logical operators\n if ('and' in filters && filters.and && Array.isArray(filters.and)) {\n const andFilters = filters.and\n if (andFilters.length === 0) {\n return new Set()\n }\n\n const results = andFilters.map((filter) => searchByWhereClause(index, tokenizer, filter, language))\n return setIntersection(...results)\n }\n\n if ('or' in filters && filters.or && Array.isArray(filters.or)) {\n const orFilters = filters.or\n if (orFilters.length === 0) {\n return new Set()\n }\n\n const results = orFilters.map((filter) => searchByWhereClause(index, tokenizer, filter, language))\n // Use reduce to union all sets\n return results.reduce((acc, set) => setUnion(acc, set), new Set<InternalDocumentID>())\n }\n\n if ('not' in filters && filters.not) {\n const notFilter = filters.not\n // Get all document IDs from the internal document store\n const allDocs = new Set<InternalDocumentID>()\n\n // Get all document IDs from the internal document store\n const docsStore = index.sharedInternalDocumentStore\n for (let i = 1; i <= docsStore.internalIdToId.length; i++) {\n allDocs.add(i)\n }\n\n const notResult = searchByWhereClause(index, tokenizer, notFilter, language)\n return setDifference(allDocs, notResult)\n }\n\n // Handle regular property filters (existing logic)\n const filterKeys = Object.keys(filters)\n\n const filtersMap: Record<string, Set<InternalDocumentID>> = filterKeys.reduce(\n (acc, key) => ({\n [key]: new Set(),\n ...acc\n }),\n {}\n )\n\n for (const param of filterKeys) {\n const operation = filters[param]!\n\n if (typeof index.indexes[param] === 'undefined') {\n throw createError('UNKNOWN_FILTER_PROPERTY', param)\n }\n\n const { node, type, isArray } = index.indexes[param]\n\n if (type === 'Bool') {\n const idx = node\n const filteredIDs = operation ? idx.true : idx.false\n filtersMap[param] = setUnion(filtersMap[param], filteredIDs)\n continue\n }\n\n if (type === 'BKD') {\n let reqOperation: 'radius' | 'polygon'\n\n if ('radius' in (operation as GeosearchOperation)) {\n reqOperation = 'radius'\n } else if ('polygon' in (operation as GeosearchOperation)) {\n reqOperation = 'polygon'\n } else {\n throw new Error(`Invalid operation ${operation}`)\n }\n\n if (reqOperation === 'radius') {\n const {\n value,\n coordinates,\n unit = 'm',\n inside = true,\n highPrecision = false\n } = operation[reqOperation] as GeosearchRadiusOperator['radius']\n const distanceInMeters = convertDistanceToMeters(value, unit)\n const ids = node.searchByRadius(coordinates as BKDGeoPoint, distanceInMeters, inside, undefined, highPrecision)\n filtersMap[param] = addGeoResult(filtersMap[param], ids)\n } else {\n const {\n coordinates,\n inside = true,\n highPrecision = false\n } = operation[reqOperation] as GeosearchPolygonOperator['polygon']\n const ids = node.searchByPolygon(coordinates as BKDGeoPoint[], inside, undefined, highPrecision)\n filtersMap[param] = addGeoResult(filtersMap[param], ids)\n }\n\n continue\n }\n\n if (type === 'Radix' && (typeof operation === 'string' || Array.isArray(operation))) {\n for (const raw of [operation].flat()) {\n const term = tokenizer.tokenize(raw, language, param)\n for (const t of term) {\n const filteredIDsResults = node.find({ term: t, exact: true })\n filtersMap[param] = addFindResult(filtersMap[param], filteredIDsResults)\n }\n }\n\n continue\n }\n\n const operationKeys = Object.keys(operation)\n\n if (operationKeys.length > 1) {\n throw createError('INVALID_FILTER_OPERATION', operationKeys.length)\n }\n\n if (type === 'Flat') {\n const results = new Set(\n isArray\n ? node.filterArr(operation as EnumArrComparisonOperator)\n : node.filter(operation as EnumComparisonOperator)\n )\n\n filtersMap[param] = setUnion(filtersMap[param], results)\n\n continue\n }\n\n if (type === 'AVL') {\n const operationOpt = operationKeys[0] as keyof ComparisonOperator\n const operationValue = (operation as ComparisonOperator)[operationOpt]\n let filteredIDs: Set<InternalDocumentID>\n\n switch (operationOpt) {\n case 'gt': {\n filteredIDs = node.greaterThan(operationValue as number, false)\n break\n }\n case 'gte': {\n filteredIDs = node.greaterThan(operationValue as number, true)\n break\n }\n case 'lt': {\n filteredIDs = node.lessThan(operationValue as number, false)\n break\n }\n case 'lte': {\n filteredIDs = node.lessThan(operationValue as number, true)\n break\n }\n case 'eq': {\n const ret = node.find(operationValue as number)\n filteredIDs = ret ?? new Set()\n break\n }\n case 'between': {\n const [min, max] = operationValue as number[]\n filteredIDs = node.rangeSearch(min, max)\n break\n }\n default:\n throw createError('INVALID_FILTER_OPERATION', operationOpt)\n }\n\n filtersMap[param] = setUnion(filtersMap[param], filteredIDs)\n }\n }\n\n // AND operation: calculate the intersection between all the IDs in filterMap\n return setIntersection(...Object.values(filtersMap))\n}\n\nexport function getSearchableProperties(index: Index): string[] {\n return index.searchableProperties\n}\n\nexport function getSearchablePropertiesWithTypes(index: Index): Record<string, SearchableType> {\n return index.searchablePropertiesWithTypes\n}\n\nexport function load<R = unknown>(sharedInternalDocumentStore: InternalDocumentIDStore, raw: R): Index {\n const {\n indexes: rawIndexes,\n vectorIndexes: rawVectorIndexes,\n searchableProperties,\n searchablePropertiesWithTypes,\n frequencies,\n tokenOccurrences,\n avgFieldLength,\n fieldLengths\n } = raw as Index\n\n const indexes: Index['indexes'] = {}\n const vectorIndexes: Index['vectorIndexes'] = {}\n\n for (const prop of Object.keys(rawIndexes)) {\n const { node, type, isArray } = rawIndexes[prop]\n\n switch (type) {\n case 'Radix':\n indexes[prop] = {\n type: 'Radix',\n node: RadixTree.fromJSON(node),\n isArray\n }\n break\n case 'Flat':\n indexes[prop] = {\n type: 'Flat',\n node: FlatTree.fromJSON(node),\n isArray\n }\n break\n case 'AVL':\n indexes[prop] = {\n type: 'AVL',\n node: AVLTree.fromJSON(node),\n isArray\n }\n break\n case 'BKD':\n indexes[prop] = {\n type: 'BKD',\n node: BKDTree.fromJSON(node),\n isArray\n }\n break\n case 'Bool':\n indexes[prop] = {\n type: 'Bool',\n node: BoolNode.fromJSON(node),\n isArray\n }\n break\n default:\n indexes[prop] = rawIndexes[prop]\n }\n }\n\n for (const idx of Object.keys(rawVectorIndexes)) {\n vectorIndexes[idx] = {\n type: 'Vector',\n isArray: false,\n node: VectorIndex.fromJSON(rawVectorIndexes[idx])\n }\n }\n\n return {\n sharedInternalDocumentStore,\n indexes,\n vectorIndexes,\n searchableProperties,\n searchablePropertiesWithTypes,\n frequencies,\n tokenOccurrences,\n avgFieldLength,\n fieldLengths\n }\n}\n\nexport function save<R = unknown>(index: Index): R {\n const {\n indexes,\n vectorIndexes,\n searchableProperties,\n searchablePropertiesWithTypes,\n frequencies,\n tokenOccurrences,\n avgFieldLength,\n fieldLengths\n } = index\n\n const dumpVectorIndexes: Record<string, unknown> = {}\n for (const idx of Object.keys(vectorIndexes)) {\n dumpVectorIndexes[idx] = vectorIndexes[idx].node.toJSON()\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const savedIndexes: any = {}\n for (const name of Object.keys(indexes)) {\n const { type, node, isArray } = indexes[name]\n if (type === 'Flat' || type === 'Radix' || type === 'AVL' || type === 'BKD' || type === 'Bool') {\n savedIndexes[name] = {\n type,\n node: node.toJSON(),\n isArray\n }\n } else {\n savedIndexes[name] = indexes[name]\n savedIndexes[name].node = savedIndexes[name].node.toJSON()\n }\n }\n\n return {\n indexes: savedIndexes,\n vectorIndexes: dumpVectorIndexes,\n searchableProperties,\n searchablePropertiesWithTypes,\n frequencies,\n tokenOccurrences,\n avgFieldLength,\n fieldLengths\n } as R\n}\n\nexport function createIndex(): IIndex<Index> {\n return {\n create,\n insert,\n remove,\n insertDocumentScoreParameters,\n insertTokenScoreParameters,\n removeDocumentScoreParameters,\n removeTokenScoreParameters,\n calculateResultScores,\n search,\n searchByWhereClause,\n getSearchableProperties,\n getSearchablePropertiesWithTypes,\n load,\n save\n }\n}\n\nfunction addGeoResult(\n set: Set<InternalDocumentID> | undefined,\n ids: Array<{ docIDs: InternalDocumentID[] }>\n): Set<InternalDocumentID> {\n if (!set) {\n set = new Set()\n }\n\n const idsLength = ids.length\n for (let i = 0; i < idsLength; i++) {\n const entry = ids[i].docIDs\n const idsLength = entry.length\n for (let j = 0; j < idsLength; j++) {\n set.add(entry[j])\n }\n }\n\n return set\n}\n\nfunction createGeoTokenScores(\n ids: Array<{ point: Point; docIDs: InternalDocumentID[] }>,\n centerPoint: Point,\n highPrecision = false\n): TokenScore[] {\n const distanceFn = highPrecision ? BKDTree.vincentyDistance : BKDTree.haversineDistance\n const results: TokenScore[] = []\n\n // Calculate distances for all results to find the maximum\n const distances: number[] = []\n for (const { point } of ids) {\n distances.push(distanceFn(centerPoint, point))\n }\n const maxDistance = Math.max(...distances)\n\n // Create results with inverse distance scores (higher score = closer)\n let index = 0\n for (const { docIDs } of ids) {\n const distance = distances[index]\n // Use inverse score: closer points get higher scores\n // Add 1 to avoid division by zero for points at exact center\n const score = maxDistance - distance + 1\n for (const docID of docIDs) {\n results.push([docID, score])\n }\n index++\n }\n\n // Sort by score (higher first - closer points)\n results.sort((a, b) => b[1] - a[1])\n return results\n}\n\nfunction isGeosearchOnlyQuery<T extends AnyOrama>(\n filters: Partial<WhereCondition<T['schema']>>,\n index: Index\n): { isGeoOnly: boolean; geoProperty?: string; geoOperation?: any } {\n const filterKeys = Object.keys(filters)\n\n if (filterKeys.length !== 1) {\n return { isGeoOnly: false }\n }\n\n const param = filterKeys[0]\n const operation = filters[param]\n\n if (typeof index.indexes[param] === 'undefined') {\n return { isGeoOnly: false }\n }\n\n const { type } = index.indexes[param]\n\n if (type === 'BKD' && operation && ('radius' in operation || 'polygon' in operation)) {\n return { isGeoOnly: true, geoProperty: param, geoOperation: operation }\n }\n\n return { isGeoOnly: false }\n}\n\nexport function searchByGeoWhereClause<T extends AnyOrama>(\n index: AnyIndexStore,\n filters: Partial<WhereCondition<T['schema']>>\n): TokenScore[] | null {\n const indexTyped = index as Index\n const geoInfo = isGeosearchOnlyQuery(filters, indexTyped)\n\n if (!geoInfo.isGeoOnly || !geoInfo.geoProperty || !geoInfo.geoOperation) {\n return null\n }\n\n const { node } = indexTyped.indexes[geoInfo.geoProperty]\n const operation = geoInfo.geoOperation\n\n // Cast node to BKDTree since we already verified it's type 'BKD'\n const bkdNode = node as BKDTree\n\n let results: Array<{ point: Point; docIDs: InternalDocumentID[] }>\n\n if ('radius' in operation) {\n const {\n value,\n coordinates,\n unit = 'm',\n inside = true,\n highPrecision = false\n } = operation.radius as GeosearchRadiusOperator['radius']\n\n const centerPoint = coordinates as Point\n const distanceInMeters = convertDistanceToMeters(value, unit)\n results = bkdNode.searchByRadius(centerPoint, distanceInMeters, inside, 'asc', highPrecision)\n\n return createGeoTokenScores(results, centerPoint, highPrecision)\n } else if ('polygon' in operation) {\n const {\n coordinates,\n inside = true,\n highPrecision = false\n } = operation.polygon as GeosearchPolygonOperator['polygon']\n\n results = bkdNode.searchByPolygon(coordinates as Point[], inside, 'asc', highPrecision)\n const centroid = BKDTree.calculatePolygonCentroid(coordinates as Point[])\n\n return createGeoTokenScores(results, centroid, highPrecision)\n }\n\n return null\n}\n\nfunction addFindResult(\n set: Set<InternalDocumentID> | undefined,\n filteredIDsResults: FindResult\n): Set<InternalDocumentID> {\n if (!set) {\n set = new Set()\n }\n\n const keys = Object.keys(filteredIDsResults)\n const keysLength = keys.length\n for (let i = 0; i < keysLength; i++) {\n const ids = filteredIDsResults[keys[i]]\n const idsLength = ids.length\n for (let j = 0; j < idsLength; j++) {\n set.add(ids[j])\n }\n }\n\n return set\n}\n","/* eslint-disable no-extra-semi */\n/* eslint-disable @typescript-eslint/no-this-alias */\nimport { Nullable } from '../types.js'\n\nexport class AVLNode<K, V> {\n public k: K\n public v: Set<V>\n public l: Nullable<AVLNode<K, V>> = null\n public r: Nullable<AVLNode<K, V>> = null\n public h: number = 1\n\n constructor(key: K, value: V[]) {\n this.k = key\n this.v = new Set(value)\n }\n\n public updateHeight(): void {\n this.h = Math.max(AVLNode.getHeight(this.l), AVLNode.getHeight(this.r)) + 1\n }\n\n public static getHeight<K, V>(node: Nullable<AVLNode<K, V>>): number {\n return node ? node.h : 0\n }\n\n public getBalanceFactor(): number {\n return AVLNode.getHeight(this.l) - AVLNode.getHeight(this.r)\n }\n\n public rotateLeft(): AVLNode<K, V> {\n const newRoot = this.r as AVLNode<K, V>\n this.r = newRoot.l\n newRoot.l = this\n this.updateHeight()\n newRoot.updateHeight()\n return newRoot\n }\n\n public rotateRight(): AVLNode<K, V> {\n const newRoot = this.l as AVLNode<K, V>\n this.l = newRoot.r\n newRoot.r = this\n this.updateHeight()\n newRoot.updateHeight()\n return newRoot\n }\n\n public toJSON(): object {\n return {\n k: this.k,\n v: Array.from(this.v),\n l: this.l ? this.l.toJSON() : null,\n r: this.r ? this.r.toJSON() : null,\n h: this.h\n }\n }\n\n public static fromJSON<K, V>(json: any): AVLNode<K, V> {\n const node = new AVLNode<K, V>(json.k, json.v)\n node.l = json.l ? AVLNode.fromJSON<K, V>(json.l) : null\n node.r = json.r ? AVLNode.fromJSON<K, V>(json.r) : null\n node.h = json.h\n return node\n }\n}\n\nexport class AVLTree<K, V> {\n public root: Nullable<AVLNode<K, V>> = null\n private insertCount = 0\n\n constructor(key?: K, value?: V[]) {\n if (key !== undefined && value !== undefined) {\n this.root = new AVLNode(key, value)\n }\n }\n\n public insert(key: K, value: V, rebalanceThreshold = 1000): void {\n this.root = this.insertNode(this.root, key, value, rebalanceThreshold)\n }\n\n public insertMultiple(key: K, value: V[], rebalanceThreshold = 1000): void {\n for (const v of value) {\n this.insert(key, v, rebalanceThreshold)\n }\n }\n\n // Rebalance the tree if the insert count reaches the threshold.\n // This will improve insertion performance since we won't be rebalancing the tree on every insert.\n // When inserting docs using `insertMultiple`, the threshold will be set to the number of docs being inserted.\n // We can force rebalancing the tree by setting the threshold to 1 (default).\n public rebalance() {\n if (this.root) {\n this.root = this.rebalanceNode(this.root!)\n }\n }\n\n public toJSON(): object {\n return {\n root: this.root ? this.root.toJSON() : null,\n insertCount: this.insertCount\n }\n }\n\n public static fromJSON<K, V>(json: any): AVLTree<K, V> {\n const tree = new AVLTree<K, V>()\n tree.root = json.root ? AVLNode.fromJSON<K, V>(json.root) : null\n tree.insertCount = json.insertCount || 0\n return tree\n }\n\n private insertNode(node: Nullable<AVLNode<K, V>>, key: K, value: V, rebalanceThreshold: number): AVLNode<K, V> {\n if (node === null) {\n return new AVLNode(key, [value])\n }\n\n const path: Array<{ parent: Nullable<AVLNode<K, V>>; node: AVLNode<K, V> }> = []\n let current = node\n let parent: Nullable<AVLNode<K, V>> = null\n\n while (current !== null) {\n path.push({ parent, node: current })\n\n if (key < current.k) {\n if (current.l === null) {\n current.l = new AVLNode(key, [value])\n path.push({ parent: current, node: current.l })\n break\n } else {\n parent = current\n current = current.l\n }\n } else if (key > current.k) {\n if (current.r === null) {\n current.r = new AVLNode(key, [value])\n path.push({ parent: current, node: current.r })\n break\n } else {\n parent = current\n current = current.r\n }\n } else {\n // Key already exists\n current.v.add(value)\n /*\n if (Array.isArray(current.v)) {\n if (Array.isArray(value)) {\n ;(current.v as any[]).push(...(value as V[]))\n } else {\n ;(current.v as any[]).push(value)\n }\n } else {\n current.v = new Set([value])\n }\n */\n return node\n }\n }\n\n // Update heights and rebalance if necessary\n let needRebalance = false\n if (this.insertCount++ % rebalanceThreshold === 0) {\n needRebalance = true\n }\n\n for (let i = path.length - 1; i >= 0; i--) {\n const { parent, node: currentNode } = path[i]\n currentNode.updateHeight()\n\n if (needRebalance) {\n const rebalancedNode = this.rebalanceNode(currentNode)\n if (parent) {\n if (parent.l === currentNode) {\n parent.l = rebalancedNode\n } else if (parent.r === currentNode) {\n parent.r = rebalancedNode\n }\n } else {\n // This is the root node\n node = rebalancedNode\n }\n }\n }\n\n return node\n }\n\n private rebalanceNode(node: AVLNode<K, V>): AVLNode<K, V> {\n const balanceFactor = node.getBalanceFactor()\n\n if (balanceFactor > 1) {\n // Left heavy\n if (node.l && node.l.getBalanceFactor() >= 0) {\n // Left Left Case\n return node.rotateRight()\n } else if (node.l) {\n // Left Right Case\n node.l = node.l.rotateLeft()\n return node.rotateRight()\n }\n }\n\n if (balanceFactor < -1) {\n // Right heavy\n if (node.r && node.r.getBalanceFactor() <= 0) {\n // Right Right Case\n return node.rotateLeft()\n } else if (node.r) {\n // Right Left Case\n node.r = node.r.rotateRight()\n return node.rotateLeft()\n }\n }\n\n return node\n }\n\n public find(key: K): Nullable<Set<V>> {\n const node = this.findNodeByKey(key)\n return node ? node.v : null\n }\n\n public contains(key: K): boolean {\n return this.find(key) !== null\n }\n\n public getSize(): number {\n let count = 0\n const stack: Array<Nullable<AVLNode<K, V>>> = []\n let current = this.root\n\n while (current || stack.length > 0) {\n while (current) {\n stack.push(current)\n current = current.l\n }\n current = stack.pop()!\n count++\n current = current.r\n }\n\n return count\n }\n\n public isBalanced(): boolean {\n if (!this.root) return true\n\n const stack: Array<AVLNode<K, V>> = [this.root]\n\n while (stack.length > 0) {\n const node = stack.pop()!\n const balanceFactor = node.getBalanceFactor()\n if (Math.abs(balanceFactor) > 1) {\n return false\n }\n\n if (node.l) stack.push(node.l)\n if (node.r) stack.push(node.r)\n }\n\n return true\n }\n\n public remove(key: K): void {\n this.root = this.removeNode(this.root, key)\n }\n\n public removeDocument(key: K, id: V) {\n const node = this.findNodeByKey(key)\n\n if (!node) {\n return\n }\n\n if (node.v.size === 1) {\n this.root = this.removeNode(this.root, key)\n } else {\n node.v = new Set([...node.v.values()].filter((v) => v !== id))\n }\n }\n\n private findNodeByKey(key: K): Nullable<AVLNode<K, V>> {\n let node = this.root\n while (node) {\n if (key < node.k) {\n node = node.l\n } else if (key > node.k) {\n node = node.r\n } else {\n return node\n }\n }\n return null\n }\n\n private removeNode(node: Nullable<AVLNode<K, V>>, key: K): Nullable<AVLNode<K, V>> {\n if (node === null) return null\n\n const path: Array<AVLNode<K, V>> = []\n let current = node\n\n while (current !== null && current.k !== key) {\n path.push(current)\n if (key < current.k) {\n current = current.l!\n } else {\n current = current.r!\n }\n }\n\n if (current === null) {\n // Key not found\n return node\n }\n\n // Node with only one child or no child\n if (current.l === null || current.r === null) {\n const child = current.l ? current.l : current.r\n\n if (path.length === 0) {\n // Node to be deleted is root\n node = child\n } else {\n const parent = path[path.length - 1]\n if (parent.l === current) {\n parent.l = child\n } else {\n parent.r = child\n }\n }\n } else {\n // Node with two children: Get the inorder successor\n let successorParent = current\n let successor = current.r\n\n while (successor.l !== null) {\n successorParent = successor\n successor = successor.l\n }\n\n // Copy the successor's content to current node\n current.k = successor.k\n current.v = successor.v\n\n // Delete the successor\n if (successorParent.l === successor) {\n successorParent.l = successor.r\n } else {\n successorParent.r = successor.r\n }\n\n current = successorParent\n }\n\n // Update heights and rebalance\n path.push(current)\n for (let i = path.length - 1; i >= 0; i--) {\n const currentNode = path[i]\n currentNode.updateHeight()\n const rebalancedNode = this.rebalanceNode(currentNode)\n if (i > 0) {\n const parent = path[i - 1]\n if (parent.l === currentNode) {\n parent.l = rebalancedNode\n } else if (parent.r === currentNode) {\n parent.r = rebalancedNode\n }\n } else {\n // Root node\n node = rebalancedNode\n }\n }\n\n return node\n }\n\n public rangeSearch(min: K, max: K): Set<V> {\n const result: Set<V> = new Set()\n const stack: Array<AVLNode<K, V>> = []\n let current = this.root\n\n while (current || stack.length > 0) {\n while (current) {\n stack.push(current)\n current = current.l\n }\n current = stack.pop()!\n if (current.k >= min && current.k <= max) {\n for (const value of current.v) {\n result.add(value)\n }\n }\n if (current.k > max) {\n break\n }\n current = current.r\n }\n\n return result\n }\n\n public greaterThan(key: K, inclusive = false): Set<V> {\n const result: Set<V> = new Set()\n const stack: Array<AVLNode<K, V>> = []\n let current = this.root\n\n while (current || stack.length > 0) {\n while (current) {\n stack.push(current)\n current = current.r // Traverse right subtree first\n }\n current = stack.pop()!\n if ((inclusive && current.k >= key) || (!inclusive && current.k > key)) {\n for (const value of current.v) {\n result.add(value)\n }\n } else if (current.k <= key) {\n break // Since we're traversing in descending order, we can break early\n }\n current = current.l\n }\n\n return result\n }\n\n public lessThan(key: K, inclusive = false): Set<V> {\n const result: Set<V> = new Set()\n const stack: Array<AVLNode<K, V>> = []\n let current = this.root\n\n while (current || stack.length > 0) {\n while (current) {\n stack.push(current)\n current = current.l\n }\n current = stack.pop()!\n if ((inclusive && current.k <= key) || (!inclusive && current.k < key)) {\n for (const value of current.v) {\n result.add(value)\n }\n } else if (current.k > key) {\n break // Since we're traversing in ascending order, we can break early\n }\n current = current.r\n }\n\n return result\n }\n}\n","import { InternalDocumentID } from '../components/internal-document-id-store.js'\nimport { EnumArrComparisonOperator, EnumComparisonOperator, Nullable, ScalarSearchableValue } from '../types.js'\n\nexport class FlatTree {\n numberToDocumentId: Map<ScalarSearchableValue, Set<InternalDocumentID>>\n\n constructor() {\n this.numberToDocumentId = new Map()\n }\n\n insert(key: ScalarSearchableValue, value: InternalDocumentID): void {\n if (this.numberToDocumentId.has(key)) {\n this.numberToDocumentId.get(key)!.add(value)\n } else {\n this.numberToDocumentId.set(key, new Set([value]))\n }\n }\n\n find(key: ScalarSearchableValue): Nullable<InternalDocumentID[]> {\n const idSet = this.numberToDocumentId.get(key)\n return idSet ? Array.from(idSet) : null\n }\n\n remove(key: ScalarSearchableValue): void {\n this.numberToDocumentId.delete(key)\n }\n\n removeDocument(id: InternalDocumentID, key: ScalarSearchableValue): void {\n const idSet = this.numberToDocumentId.get(key)\n if (idSet) {\n idSet.delete(id)\n if (idSet.size === 0) {\n this.numberToDocumentId.delete(key)\n }\n }\n }\n\n contains(key: ScalarSearchableValue): boolean {\n return this.numberToDocumentId.has(key)\n }\n\n getSize(): number {\n let size = 0\n for (const idSet of this.numberToDocumentId.values()) {\n size += idSet.size\n }\n return size\n }\n\n filter(operation: EnumComparisonOperator): InternalDocumentID[] {\n const operationKeys = Object.keys(operation)\n\n if (operationKeys.length !== 1) {\n throw new Error('Invalid operation')\n }\n\n const operationType = operationKeys[0] as keyof EnumComparisonOperator\n\n switch (operationType) {\n case 'eq': {\n const value = operation[operationType]!\n const idSet = this.numberToDocumentId.get(value)\n return idSet ? Array.from(idSet) : []\n }\n case 'in': {\n const values = operation[operationType]!\n const resultSet: Set<InternalDocumentID> = new Set()\n for (const value of values) {\n const idSet = this.numberToDocumentId.get(value)\n if (idSet) {\n for (const id of idSet) {\n resultSet.add(id)\n }\n }\n }\n return Array.from(resultSet)\n }\n case 'nin': {\n const excludeValues = new Set<ScalarSearchableValue>(operation[operationType]!)\n const resultSet: Set<InternalDocumentID> = new Set()\n for (const [key, idSet] of this.numberToDocumentId.entries()) {\n if (!excludeValues.has(key)) {\n for (const id of idSet) {\n resultSet.add(id)\n }\n }\n }\n return Array.from(resultSet)\n }\n default:\n throw new Error('Invalid operation')\n }\n }\n\n filterArr(operation: EnumArrComparisonOperator): InternalDocumentID[] {\n const operationKeys = Object.keys(operation)\n\n if (operationKeys.length !== 1) {\n throw new Error('Invalid operation')\n }\n\n const operationType = operationKeys[0] as keyof EnumArrComparisonOperator\n\n switch (operationType) {\n case 'containsAll': {\n const values = operation[operationType]!\n const idSets = values.map((value) => this.numberToDocumentId.get(value) ?? new Set())\n if (idSets.length === 0) return []\n const intersection = idSets.reduce((prev, curr) => {\n return new Set([...prev].filter((id) => curr.has(id)))\n })\n return Array.from(intersection) as InternalDocumentID[]\n }\n case 'containsAny': {\n const values = operation[operationType]!\n const idSets = values.map((value) => this.numberToDocumentId.get(value) ?? new Set())\n if (idSets.length === 0) return []\n const union = idSets.reduce((prev, curr) => {\n return new Set([...prev, ...curr])\n })\n return Array.from(union) as InternalDocumentID[]\n }\n default:\n throw new Error('Invalid operation')\n }\n }\n\n static fromJSON(json: any): FlatTree {\n if (!json.numberToDocumentId) {\n throw new Error('Invalid Flat Tree JSON')\n }\n\n const tree = new FlatTree()\n for (const [key, ids] of json.numberToDocumentId) {\n tree.numberToDocumentId.set(key, new Set(ids))\n }\n return tree\n }\n\n toJSON(): any {\n return {\n numberToDocumentId: Array.from(this.numberToDocumentId.entries()).map(([key, idSet]) => [key, Array.from(idSet)])\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-this-alias */\r\nimport { syncBoundedLevenshtein } from '../components/levenshtein.js'\r\nimport { InternalDocumentID } from '../components/internal-document-id-store.js'\r\nimport { getOwnProperty } from '../utils.js'\r\n\r\ninterface FindParams {\r\n term: string\r\n exact?: boolean\r\n tolerance?: number\r\n}\r\n\r\nexport type FindResult = Record<string, InternalDocumentID[]>\r\n\r\nexport class RadixNode {\r\n // Node key\r\n public k: string\r\n // Node subword\r\n public s: string\r\n // Node children\r\n public c: Map<string, RadixNode> = new Map()\r\n // Node documents\r\n public d: Set<InternalDocumentID> = new Set()\r\n // Node end\r\n public e: boolean\r\n // Node word\r\n public w = ''\r\n\r\n constructor(key: string, subWord: string, end: boolean) {\r\n this.k = key\r\n this.s = subWord\r\n this.e = end\r\n }\r\n\r\n public updateParent(parent: RadixNode): void {\r\n this.w = parent.w + this.s\r\n }\r\n\r\n public addDocument(docID: InternalDocumentID): void {\r\n this.d.add(docID)\r\n }\r\n\r\n public removeDocument(docID: InternalDocumentID): boolean {\r\n return this.d.delete(docID)\r\n }\r\n\r\n public findAllWords(output: FindResult, term: string, exact?: boolean, tolerance?: number): FindResult {\r\n const stack: RadixNode[] = [this]\r\n while (stack.length > 0) {\r\n const node = stack.pop()!\r\n\r\n if (node.e) {\r\n const { w, d: docIDs } = node\r\n\r\n if (exact && w !== term) {\r\n continue\r\n }\r\n\r\n // check if _output[w] exists and then add the doc to it\r\n // always check in own property to prevent access to inherited properties\r\n // fix https://github.com/oramasearch/orama/issues/137\r\n if (getOwnProperty(output, w) !== null) {\r\n if (tolerance) {\r\n const difference = Math.abs(term.length - w.length)\r\n\r\n if (difference <= tolerance && syncBoundedLevenshtein(term, w, tolerance).isBounded) {\r\n output[w] = []\r\n } else {\r\n continue\r\n }\r\n } else {\r\n output[w] = []\r\n }\r\n }\r\n\r\n // check if _output[w] exists and then add the doc to it\r\n // always check in own property to prevent access to inherited properties\r\n // fix https://github.com/oramasearch/orama/issues/137\r\n if (getOwnProperty(output, w) != null && docIDs.size > 0) {\r\n const docs = output[w]\r\n for (const docID of docIDs) {\r\n if (!docs.includes(docID)) {\r\n docs.push(docID)\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (node.c.size > 0) {\r\n stack.push(...node.c.values())\r\n }\r\n }\r\n return output\r\n }\r\n\r\n public insert(word: string, docId: InternalDocumentID): void {\r\n let node: RadixNode = this\r\n let i = 0\r\n const wordLength = word.length\r\n\r\n while (i < wordLength) {\r\n const currentCharacter = word[i]\r\n const childNode = node.c.get(currentCharacter)\r\n\r\n if (childNode) {\r\n const edgeLabel = childNode.s\r\n const edgeLabelLength = edgeLabel.length\r\n let j = 0\r\n\r\n // Find the common prefix length between edgeLabel and the remaining word\r\n while (j < edgeLabelLength && i + j < wordLength && edgeLabel[j] === word[i + j]) {\r\n j++\r\n }\r\n\r\n if (j === edgeLabelLength) {\r\n // Edge label fully matches; proceed to the child node\r\n node = childNode\r\n i += j\r\n if (i === wordLength) {\r\n // The word is a prefix of an existing word\r\n if (!childNode.e) {\r\n childNode.e = true\r\n }\r\n childNode.addDocument(docId)\r\n return\r\n }\r\n continue\r\n }\r\n\r\n // Split the edgeLabel at the common prefix\r\n const commonPrefix = edgeLabel.slice(0, j)\r\n const newEdgeLabel = edgeLabel.slice(j)\r\n const newWordLabel = word.slice(i + j)\r\n\r\n // Create an intermediate node for the common prefix\r\n const inbetweenNode = new RadixNode(commonPrefix[0], commonPrefix, false)\r\n node.c.set(commonPrefix[0], inbetweenNode)\r\n inbetweenNode.updateParent(node)\r\n\r\n // Update the existing childNode\r\n childNode.s = newEdgeLabel\r\n childNode.k = newEdgeLabel[0]\r\n inbetweenNode.c.set(newEdgeLabel[0], childNode)\r\n childNode.updateParent(inbetweenNode)\r\n\r\n if (newWordLabel) {\r\n // Create a new node for the remaining part of the word\r\n const newNode = new RadixNode(newWordLabel[0], newWordLabel, true)\r\n newNode.addDocument(docId)\r\n inbetweenNode.c.set(newWordLabel[0], newNode)\r\n newNode.updateParent(inbetweenNode)\r\n } else {\r\n // The word ends at the inbetweenNode\r\n inbetweenNode.e = true\r\n inbetweenNode.addDocument(docId)\r\n }\r\n return\r\n } else {\r\n // No matching child; create a new node\r\n const newNode = new RadixNode(currentCharacter, word.slice(i), true)\r\n newNode.addDocument(docId)\r\n node.c.set(currentCharacter, newNode)\r\n newNode.updateParent(node)\r\n return\r\n }\r\n }\r\n\r\n // If we reach here, the word already exists in the tree\r\n if (!node.e) {\r\n node.e = true\r\n }\r\n node.addDocument(docId)\r\n }\r\n\r\n private _findLevenshtein(\r\n term: string,\r\n index: number,\r\n tolerance: number,\r\n originalTolerance: number,\r\n output: FindResult\r\n ) {\r\n const stack: Array<{ node: RadixNode; index: number; tolerance: number }> = [{ node: this, index, tolerance }]\r\n\r\n while (stack.length > 0) {\r\n const { node, index, tolerance } = stack.pop()!\r\n\r\n // Prefix optimization: if the node's word starts with the search term,\r\n // we can find all words in the subtree. BUT exclude exact matches to avoid\r\n // the bug where exact matches return wrong results with tolerance > 0.\r\n if (node.w.startsWith(term) && node.w !== term) {\r\n console.log('[RADIX FIX] Prefix optimization triggered for:', node.w, 'term:', term);\r\n node.findAllWords(output, term, false, 0)\r\n continue\r\n }\r\n \r\n // Log when exact match is excluded from prefix optimization\r\n if (node.w.startsWith(term) && node.w === term) {\r\n console.log('[RADIX FIX] Exact match excluded from prefix optimization:', term);\r\n }\r\n\r\n if (tolerance < 0) {\r\n continue\r\n }\r\n\r\n if (node.e) {\r\n const { w, d: docIDs } = node\r\n if (w) {\r\n if (syncBoundedLevenshtein(term, w, originalTolerance).isBounded) {\r\n output[w] = []\r\n }\r\n if (getOwnProperty(output, w) !== undefined && docIDs.size > 0) {\r\n const docs = new Set(output[w])\r\n\r\n for (const docID of docIDs) {\r\n docs.add(docID)\r\n }\r\n output[w] = Array.from(docs)\r\n }\r\n }\r\n }\r\n\r\n if (index >= term.length) {\r\n continue\r\n }\r\n\r\n const currentChar = term[index]\r\n\r\n // 1. If node has child matching term[index], push { node: childNode, index +1, tolerance }\r\n if (node.c.has(currentChar)) {\r\n const childNode = node.c.get(currentChar)!\r\n stack.push({ node: childNode, index: index + 1, tolerance })\r\n }\r\n\r\n // 2. Push { node, index +1, tolerance -1 } (Delete operation)\r\n stack.push({ node: node, index: index + 1, tolerance: tolerance - 1 })\r\n\r\n // 3. For each child:\r\n for (const [character, childNode] of node.c) {\r\n // a) Insert operation\r\n stack.push({ node: childNode, index: index, tolerance: tolerance - 1 })\r\n\r\n // b) Substitute operation\r\n if (character !== currentChar) {\r\n stack.push({ node: childNode, index: index + 1, tolerance: tolerance - 1 })\r\n }\r\n }\r\n }\r\n }\r\n\r\n public find(params: FindParams): FindResult {\r\n const { term, exact, tolerance } = params\r\n if (tolerance && !exact) {\r\n const output: FindResult = {}\r\n this._findLevenshtein(term, 0, tolerance, tolerance, output)\r\n return output\r\n } else {\r\n let node: RadixNode = this\r\n let i = 0\r\n const termLength = term.length\r\n\r\n while (i < termLength) {\r\n const character = term[i]\r\n const childNode = node.c.get(character)\r\n\r\n if (childNode) {\r\n const edgeLabel = childNode.s\r\n const edgeLabelLength = edgeLabel.length\r\n let j = 0\r\n\r\n // Compare edge label with the term starting from position i\r\n while (j < edgeLabelLength && i + j < termLength && edgeLabel[j] === term[i + j]) {\r\n j++\r\n }\r\n\r\n if (j === edgeLabelLength) {\r\n // Full match of edge label; proceed to the child node\r\n node = childNode\r\n i += j\r\n } else if (i + j === termLength) {\r\n // The term ends in the middle of the edge label - FIX: this handles prefix matches like 'p' matching 'phone'\r\n // Check if the term matches from the beginning of the edge label\r\n if (j === termLength - i) {\r\n // Term is a prefix of the edge label\r\n if (exact) {\r\n // Exact match required but term doesn't end at a node\r\n return {}\r\n } else {\r\n // Partial match; collect words starting from this node\r\n const output: FindResult = {}\r\n // Just call findAllWords on the child node to collect all words in this subtree\r\n childNode.findAllWords(output, term, exact, tolerance)\r\n return output\r\n }\r\n } else {\r\n // Mismatch found\r\n return {}\r\n }\r\n } else {\r\n // Mismatch found\r\n return {}\r\n }\r\n } else {\r\n // No matching child node\r\n return {}\r\n }\r\n }\r\n\r\n // Term fully matched; collect words starting from this node\r\n const output: FindResult = {}\r\n node.findAllWords(output, term, exact, tolerance)\r\n return output\r\n }\r\n }\r\n\r\n public contains(term: string): boolean {\r\n let node: RadixNode = this\r\n let i = 0\r\n const termLength = term.length\r\n\r\n while (i < termLength) {\r\n const character = term[i]\r\n const childNode = node.c.get(character)\r\n\r\n if (childNode) {\r\n const edgeLabel = childNode.s\r\n const edgeLabelLength = edgeLabel.length\r\n let j = 0\r\n\r\n while (j < edgeLabelLength && i + j < termLength && edgeLabel[j] === term[i + j]) {\r\n j++\r\n }\r\n\r\n if (j < edgeLabelLength) {\r\n return false\r\n }\r\n\r\n i += edgeLabelLength\r\n node = childNode\r\n } else {\r\n return false\r\n }\r\n }\r\n return true\r\n }\r\n\r\n public removeWord(term: string): boolean {\r\n if (!term) {\r\n return false\r\n }\r\n\r\n let node: RadixNode = this\r\n const termLength = term.length\r\n const stack: { parent: RadixNode; character: string }[] = []\r\n for (let i = 0; i < termLength; i++) {\r\n const character = term[i]\r\n if (node.c.has(character)) {\r\n const childNode = node.c.get(character)!\r\n stack.push({ parent: node, character })\r\n i += childNode.s.length - 1\r\n node = childNode\r\n } else {\r\n return false\r\n }\r\n }\r\n\r\n // Remove documents from the node\r\n node.d.clear()\r\n node.e = false\r\n\r\n // Clean up any nodes that no longer lead to a word\r\n while (stack.length > 0 && node.c.size === 0 && !node.e && node.d.size === 0) {\r\n const { parent, character } = stack.pop()!\r\n parent.c.delete(character)\r\n node = parent\r\n }\r\n\r\n return true\r\n }\r\n\r\n public removeDocumentByWord(term: string, docID: InternalDocumentID, exact = true): boolean {\r\n if (!term) {\r\n return true\r\n }\r\n\r\n let node: RadixNode = this\r\n const termLength = term.length\r\n for (let i = 0; i < termLength; i++) {\r\n const character = term[i]\r\n if (node.c.has(character)) {\r\n const childNode = node.c.get(character)!\r\n i += childNode.s.length - 1\r\n node = childNode\r\n\r\n if (exact && node.w !== term) {\r\n // Do nothing if the exact condition is not met.\r\n } else {\r\n node.removeDocument(docID)\r\n }\r\n } else {\r\n return false\r\n }\r\n }\r\n return true\r\n }\r\n\r\n private static getCommonPrefix(a: string, b: string): string {\r\n const len = Math.min(a.length, b.length)\r\n let i = 0\r\n while (i < len && a.charCodeAt(i) === b.charCodeAt(i)) {\r\n i++\r\n }\r\n return a.slice(0, i)\r\n }\r\n\r\n public toJSON(): object {\r\n return {\r\n w: this.w,\r\n s: this.s,\r\n e: this.e,\r\n k: this.k,\r\n d: Array.from(this.d),\r\n c: Array.from(this.c?.entries())?.map(([key, node]) => [key, node.toJSON()])\r\n }\r\n }\r\n\r\n public static fromJSON(json: any): RadixNode {\r\n const node = new RadixNode(json.k, json.s, json.e)\r\n node.w = json.w\r\n node.d = new Set(json.d)\r\n node.c = new Map(json?.c?.map(([key, nodeJson]: [string, any]) => [key, RadixNode.fromJSON(nodeJson)]) || [])\r\n return node\r\n }\r\n}\r\n\r\nexport class RadixTree extends RadixNode {\r\n constructor() {\r\n super('', '', false)\r\n }\r\n\r\n public static fromJSON(json: any): RadixTree {\r\n const tree = new RadixTree()\r\n tree.w = json.w\r\n tree.s = json.s\r\n tree.e = json.e\r\n tree.k = json.k\r\n tree.d = new Set(json.d)\r\n tree.c = new Map(json?.c?.map(([key, nodeJson]: [string, any]) => [key, RadixNode.fromJSON(nodeJson)]) || [])\r\n return tree\r\n }\r\n\r\n public toJSON(): object {\r\n return super.toJSON()\r\n }\r\n}\r\n","export type BoundedMetric = {\n isBounded: boolean\n distance: number\n}\n\n/**\n * Inspired by:\n * https://github.com/Yomguithereal/talisman/blob/86ae55cbd040ff021d05e282e0e6c71f2dde21f8/src/metrics/levenshtein.js#L218-L340\n */\nfunction _boundedLevenshtein(term: string, word: string, tolerance: number): number {\n // Handle base cases\n if (tolerance < 0) return -1\n if (term === word) return 0\n\n const m = term.length\n const n = word.length\n\n // Special case for empty strings\n if (m === 0) return n <= tolerance ? n : -1\n if (n === 0) return m <= tolerance ? m : -1\n\n // term = term.toLowerCase()\n // word = word.toLowerCase()\n\n const diff = Math.abs(m - n)\n // Special case for prefixes\n // If the searching word starts with the indexed word, return early.\n if (term.startsWith(word)) {\n // We just check if the remaining characters are within the tolerance\n return diff <= tolerance ? diff : -1\n }\n // If the indexed word starts with the searching word, return early.\n if (word.startsWith(term)) {\n // any prefixed word is within the tolerance\n return 0\n }\n\n // If the length difference is greater than the tolerance, return early\n if (diff > tolerance) return -1\n\n // Initialize the matrix\n const matrix: number[][] = []\n for (let i = 0; i <= m; i++) {\n matrix[i] = [i]\n for (let j = 1; j <= n; j++) {\n matrix[i][j] = i === 0 ? j : 0\n }\n }\n\n // Fill the matrix\n for (let i = 1; i <= m; i++) {\n let rowMin = Infinity\n for (let j = 1; j <= n; j++) {\n if (term[i - 1] === word[j - 1]) {\n matrix[i][j] = matrix[i - 1][j - 1]\n } else {\n matrix[i][j] = Math.min(\n matrix[i - 1][j] + 1, // deletion\n matrix[i][j - 1] + 1, // insertion\n matrix[i - 1][j - 1] + 1 // substitution\n )\n }\n rowMin = Math.min(rowMin, matrix[i][j])\n }\n\n // Early termination if all values in this row exceed tolerance\n if (rowMin > tolerance) {\n return -1\n }\n }\n\n return matrix[m][n] <= tolerance ? matrix[m][n] : -1\n}\n\n/**\n * Computes the Levenshtein distance between two strings (a, b), returning early with -1 if the distance\n * is greater than the given tolerance.\n * It assumes that:\n * - tolerance >= ||a| - |b|| >= 0\n */\nexport function boundedLevenshtein(term: string, w: string, tolerance: number): BoundedMetric {\n const distance = _boundedLevenshtein(term, w, tolerance)\n return {\n distance,\n isBounded: distance >= 0\n }\n}\n\n// This is only used internally, keep in sync with the previous one\nexport function syncBoundedLevenshtein(term: string, w: string, tolerance: number): BoundedMetric {\n const distance = _boundedLevenshtein(term, w, tolerance)\n return {\n distance,\n isBounded: distance >= 0\n }\n}\n\nexport function levenshtein(a: string, b: string): number {\n /* c8 ignore next 3 */\n if (!a.length) {\n return b.length\n }\n\n /* c8 ignore next 3 */\n if (!b.length) {\n return a.length\n }\n\n const swap = a\n if (a.length > b.length) {\n a = b\n b = swap\n }\n\n const row = Array.from({ length: a.length + 1 }, (_, i) => i)\n let val = 0\n\n for (let i = 1; i <= b.length; i++) {\n let prev = i\n\n for (let j = 1; j <= a.length; j++) {\n if (b[i - 1] === a[j - 1]) {\n val = row[j - 1]\n } else {\n val = Math.min(row[j - 1] + 1, Math.min(prev + 1, row[j] + 1))\n }\n\n row[j - 1] = prev\n prev = val\n }\n row[a.length] = prev\n }\n\n return row[a.length]\n}\n","import type { Nullable, GenericSorting } from '../types.js'\nimport type { InternalDocumentID } from '../components/internal-document-id-store.js'\n\nexport interface Point {\n lon: number\n lat: number\n}\n\nexport interface GeoSearchResult {\n point: Point\n docIDs: InternalDocumentID[]\n}\n\nexport type SortGeoPoints = Nullable<GenericSorting>\n\ntype SearchTask = {\n node: Nullable<BKDNode>\n depth: number\n}\n\nconst K = 2 // 2D points\nconst EARTH_RADIUS = 6371e3 // Earth radius in meters\n\nclass BKDNode {\n point: Point\n docIDs: Set<InternalDocumentID>\n left: Nullable<BKDNode>\n right: Nullable<BKDNode>\n parent: Nullable<BKDNode>\n\n constructor(point: Point, docIDs?: InternalDocumentID[]) {\n this.point = point\n this.docIDs = new Set(docIDs)\n this.left = null\n this.right = null\n this.parent = null\n }\n\n toJSON(): any {\n return {\n point: this.point,\n docIDs: Array.from(this.docIDs),\n left: this.left ? this.left.toJSON() : null,\n right: this.right ? this.right.toJSON() : null\n }\n }\n\n static fromJSON(json: any, parent: Nullable<BKDNode> = null): BKDNode {\n const node = new BKDNode(json.point, json.docIDs)\n node.parent = parent\n if (json.left) {\n node.left = BKDNode.fromJSON(json.left, node)\n }\n if (json.right) {\n node.right = BKDNode.fromJSON(json.right, node)\n }\n return node\n }\n}\n\nexport class BKDTree {\n root: Nullable<BKDNode>\n nodeMap: Map<string, BKDNode>\n\n constructor() {\n this.root = null\n this.nodeMap = new Map()\n }\n\n private getPointKey(point: Point): string {\n return `${point.lon},${point.lat}`\n }\n\n insert(point: Point, docIDs: InternalDocumentID[]): void {\n const pointKey = this.getPointKey(point)\n const existingNode = this.nodeMap.get(pointKey)\n if (existingNode) {\n docIDs.forEach((id) => existingNode.docIDs.add(id))\n return\n }\n\n const newNode = new BKDNode(point, docIDs)\n this.nodeMap.set(pointKey, newNode)\n\n if (this.root == null) {\n this.root = newNode\n return\n }\n\n let node = this.root\n let depth = 0\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const axis = depth % K\n\n if (axis === 0) {\n if (point.lon < node.point.lon) {\n if (node.left == null) {\n node.left = newNode\n newNode.parent = node\n return\n }\n node = node.left\n } else {\n if (node.right == null) {\n node.right = newNode\n newNode.parent = node\n return\n }\n node = node.right\n }\n } else {\n if (point.lat < node.point.lat) {\n if (node.left == null) {\n node.left = newNode\n newNode.parent = node\n return\n }\n node = node.left\n } else {\n if (node.right == null) {\n node.right = newNode\n newNode.parent = node\n return\n }\n node = node.right\n }\n }\n\n depth++\n }\n }\n\n contains(point: Point): boolean {\n const pointKey = this.getPointKey(point)\n return this.nodeMap.has(pointKey)\n }\n\n getDocIDsByCoordinates(point: Point): Nullable<InternalDocumentID[]> {\n const pointKey = this.getPointKey(point)\n const node = this.nodeMap.get(pointKey)\n if (node) {\n return Array.from(node.docIDs)\n }\n return null\n }\n\n removeDocByID(point: Point, docID: InternalDocumentID): void {\n const pointKey = this.getPointKey(point)\n const node = this.nodeMap.get(pointKey)\n if (node) {\n node.docIDs.delete(docID)\n if (node.docIDs.size === 0) {\n this.nodeMap.delete(pointKey)\n this.deleteNode(node)\n }\n }\n }\n\n private deleteNode(node: BKDNode): void {\n const parent = node.parent\n const child = node.left ? node.left : node.right\n if (child) {\n child.parent = parent\n }\n\n if (parent) {\n if (parent.left === node) {\n parent.left = child\n } else if (parent.right === node) {\n parent.right = child\n }\n } else {\n this.root = child\n if (this.root) {\n this.root.parent = null\n }\n }\n }\n\n searchByRadius(\n center: Point,\n radius: number,\n inclusive = true,\n sort: SortGeoPoints = 'asc',\n highPrecision = false\n ): GeoSearchResult[] {\n const distanceFn = highPrecision ? BKDTree.vincentyDistance : BKDTree.haversineDistance\n const stack: Array<{ node: Nullable<BKDNode>; depth: number }> = [{ node: this.root, depth: 0 }]\n const result: GeoSearchResult[] = []\n\n while (stack.length > 0) {\n const { node, depth } = stack.pop()!\n if (node == null) continue\n\n const dist = distanceFn(center, node.point)\n\n if (inclusive ? dist <= radius : dist > radius) {\n result.push({ point: node.point, docIDs: Array.from(node.docIDs) })\n }\n\n if (node.left != null) {\n stack.push({ node: node.left, depth: depth + 1 })\n }\n if (node.right != null) {\n stack.push({ node: node.right, depth: depth + 1 })\n }\n }\n\n if (sort) {\n result.sort((a, b) => {\n const distA = distanceFn(center, a.point)\n const distB = distanceFn(center, b.point)\n return sort.toLowerCase() === 'asc' ? distA - distB : distB - distA\n })\n }\n\n return result\n }\n\n searchByPolygon(\n polygon: Point[],\n inclusive = true,\n sort: SortGeoPoints = null,\n highPrecision = false\n ): GeoSearchResult[] {\n const stack: SearchTask[] = [{ node: this.root, depth: 0 }]\n const result: GeoSearchResult[] = []\n\n while (stack.length > 0) {\n const { node, depth } = stack.pop()!\n if (node == null) continue\n\n if (node.left != null) {\n stack.push({ node: node.left, depth: depth + 1 })\n }\n if (node.right != null) {\n stack.push({ node: node.right, depth: depth + 1 })\n }\n\n const isInsidePolygon = BKDTree.isPointInPolygon(polygon, node.point)\n\n if ((isInsidePolygon && inclusive) || (!isInsidePolygon && !inclusive)) {\n result.push({ point: node.point, docIDs: Array.from(node.docIDs) })\n }\n }\n\n const centroid = BKDTree.calculatePolygonCentroid(polygon)\n\n if (sort) {\n const distanceFn = highPrecision ? BKDTree.vincentyDistance : BKDTree.haversineDistance\n result.sort((a, b) => {\n const distA = distanceFn(centroid, a.point)\n const distB = distanceFn(centroid, b.point)\n return sort!.toLowerCase() === 'asc' ? distA - distB : distB - distA\n })\n }\n\n return result\n }\n\n toJSON(): any {\n return {\n root: this.root ? this.root.toJSON() : null\n }\n }\n\n static fromJSON(json: any): BKDTree {\n const tree = new BKDTree()\n if (json.root) {\n tree.root = BKDNode.fromJSON(json.root)\n tree.buildNodeMap(tree.root)\n }\n return tree\n }\n\n private buildNodeMap(node: Nullable<BKDNode>): void {\n if (node == null) return\n const pointKey = this.getPointKey(node.point)\n this.nodeMap.set(pointKey, node)\n if (node.left) {\n this.buildNodeMap(node.left)\n }\n if (node.right) {\n this.buildNodeMap(node.right)\n }\n }\n\n static calculatePolygonCentroid(polygon: Point[]): Point {\n let totalArea = 0\n let centroidX = 0\n let centroidY = 0\n\n const polygonLength = polygon.length\n for (let i = 0, j = polygonLength - 1; i < polygonLength; j = i++) {\n const xi = polygon[i].lon\n const yi = polygon[i].lat\n const xj = polygon[j].lon\n const yj = polygon[j].lat\n\n const areaSegment = xi * yj - xj * yi\n totalArea += areaSegment\n\n centroidX += (xi + xj) * areaSegment\n centroidY += (yi + yj) * areaSegment\n }\n\n totalArea /= 2\n const centroidCoordinate = 6 * totalArea\n\n centroidX /= centroidCoordinate\n centroidY /= centroidCoordinate\n\n return { lon: centroidX, lat: centroidY }\n }\n\n static isPointInPolygon(polygon: Point[], point: Point): boolean {\n let isInside = false\n const x = point.lon\n const y = point.lat\n const polygonLength = polygon.length\n for (let i = 0, j = polygonLength - 1; i < polygonLength; j = i++) {\n const xi = polygon[i].lon\n const yi = polygon[i].lat\n const xj = polygon[j].lon\n const yj = polygon[j].lat\n\n const intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi\n if (intersect) isInside = !isInside\n }\n\n return isInside\n }\n\n static haversineDistance(coord1: Point, coord2: Point): number {\n const P = Math.PI / 180\n const lat1 = coord1.lat * P\n const lat2 = coord2.lat * P\n const deltaLat = (coord2.lat - coord1.lat) * P\n const deltaLon = (coord2.lon - coord1.lon) * P\n\n const a =\n Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +\n Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2)\n const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))\n\n return EARTH_RADIUS * c\n }\n\n static vincentyDistance(coord1: Point, coord2: Point): number {\n const a = 6378137\n const f = 1 / 298.257223563\n const b = (1 - f) * a\n\n const P = Math.PI / 180\n const lat1 = coord1.lat * P\n const lat2 = coord2.lat * P\n const deltaLon = (coord2.lon - coord1.lon) * P\n\n const U1 = Math.atan((1 - f) * Math.tan(lat1))\n const U2 = Math.atan((1 - f) * Math.tan(lat2))\n\n const sinU1 = Math.sin(U1)\n const cosU1 = Math.cos(U1)\n const sinU2 = Math.sin(U2)\n const cosU2 = Math.cos(U2)\n\n let lambda = deltaLon\n let prevLambda\n let iterationLimit = 1000\n let sinSigma\n let cosSigma\n let sigma\n let sinAlpha\n let cos2Alpha\n let cos2SigmaM\n\n do {\n const sinLambda = Math.sin(lambda)\n const cosLambda = Math.cos(lambda)\n\n sinSigma = Math.sqrt(\n cosU2 * sinLambda * (cosU2 * sinLambda) +\n (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda)\n )\n\n if (sinSigma === 0) return 0 // co-incident points\n\n cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda\n sigma = Math.atan2(sinSigma, cosSigma)\n\n sinAlpha = (cosU1 * cosU2 * sinLambda) / sinSigma\n cos2Alpha = 1 - sinAlpha * sinAlpha\n cos2SigmaM = cosSigma - (2 * sinU1 * sinU2) / cos2Alpha\n\n if (isNaN(cos2SigmaM)) cos2SigmaM = 0\n\n const C = (f / 16) * cos2Alpha * (4 + f * (4 - 3 * cos2Alpha))\n prevLambda = lambda\n lambda =\n deltaLon +\n (1 - C) *\n f *\n sinAlpha *\n (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)))\n } while (Math.abs(lambda - prevLambda) > 1e-12 && --iterationLimit > 0)\n\n if (iterationLimit === 0) {\n return NaN\n }\n\n const uSquared = (cos2Alpha * (a * a - b * b)) / (b * b)\n const A = 1 + (uSquared / 16384) * (4096 + uSquared * (-768 + uSquared * (320 - 175 * uSquared)))\n const B = (uSquared / 1024) * (256 + uSquared * (-128 + uSquared * (74 - 47 * uSquared)))\n\n const deltaSigma =\n B *\n sinSigma *\n (cos2SigmaM +\n (B / 4) *\n (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -\n (B / 6) * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)))\n\n const s = b * A * (sigma - deltaSigma)\n\n return s\n }\n}\n","export class BoolNode<V = unknown> {\n true: Set<V>\n false: Set<V>\n\n constructor() {\n this.true = new Set()\n this.false = new Set()\n }\n\n insert(value: V, bool: boolean): void {\n if (bool) {\n this.true.add(value)\n } else {\n this.false.add(value)\n }\n }\n\n delete(value: V, bool: boolean): void {\n if (bool) {\n this.true.delete(value)\n } else {\n this.false.delete(value)\n }\n }\n\n getSize(): number {\n return this.true.size + this.false.size\n }\n\n toJSON(): any {\n return {\n true: Array.from(this.true),\n false: Array.from(this.false)\n }\n }\n\n static fromJSON<V>(json: any): BoolNode<V> {\n const node = new BoolNode<V>()\n node.true = new Set(json.true)\n node.false = new Set(json.false)\n return node\n }\n}\n","import { createError } from '../errors.js'\nimport { TokenScore, BM25Params } from '../types.js'\nimport { InternalDocumentID } from './internal-document-id-store.js'\n\nexport function prioritizeTokenScores(\n arrays: TokenScore[][],\n boost: number,\n threshold = 0,\n keywordsCount: number\n): TokenScore[] {\n if (boost === 0) {\n throw createError('INVALID_BOOST_VALUE')\n }\n\n const tokenScoresMap = new Map<InternalDocumentID, [number, number]>()\n\n const mapsLength = arrays.length\n for (let i = 0; i < mapsLength; i++) {\n const arr = arrays[i]\n\n const entriesLength = arr.length\n for (let j = 0; j < entriesLength; j++) {\n const [token, score] = arr[j]\n const boostScore = score * boost\n const oldScore = tokenScoresMap.get(token)?.[0]\n\n if (oldScore !== undefined) {\n tokenScoresMap.set(token, [oldScore * 1.5 + boostScore, (tokenScoresMap?.get(token)?.[1] || 0) + 1])\n } else {\n tokenScoresMap.set(token, [boostScore, 1])\n }\n }\n }\n\n const tokenScores: TokenScore[] = []\n\n for (const tokenScoreEntry of tokenScoresMap.entries()) {\n tokenScores.push([tokenScoreEntry[0], tokenScoreEntry[1][0]])\n }\n\n const results = tokenScores.sort((a, b) => b[1] - a[1])\n\n // If threshold is 1, it means we will return all the results with at least one search term,\n // prioritizing the ones that contains more search terms (fuzzy match)\n if (threshold === 1) {\n return results\n }\n\n // For threshold = 0 when keywordsCount is 1 (single term search),\n // we return all matches since they automatically contain 100% of keywords\n if (threshold === 0 && keywordsCount === 1) {\n return results\n }\n\n // Prepare keywords count tracking for threshold handling\n const allResults = results.length\n const tokenScoreWithKeywordsCount: [InternalDocumentID, number, number][] = []\n\n for (const tokenScoreEntry of tokenScoresMap.entries()) {\n tokenScoreWithKeywordsCount.push([tokenScoreEntry[0], tokenScoreEntry[1][0], tokenScoreEntry[1][1]])\n }\n\n // Find the index of the last result with all keywords.\n // Order the documents by the number of keywords they contain, and then by the score.\n const keywordsPerToken = tokenScoreWithKeywordsCount.sort((a, b) => {\n // Compare by the third element, higher numbers first\n if (a[2] > b[2]) return -1\n if (a[2] < b[2]) return 1\n\n // If the third elements are equal, compare by the second element, higher numbers first\n if (a[1] > b[1]) return -1\n if (a[1] < b[1]) return 1\n\n // If both the second and third elements are equal, consider the elements equal\n return 0\n })\n\n let lastTokenWithAllKeywords: number | undefined = undefined\n for (let i = 0; i < allResults; i++) {\n if (keywordsPerToken[i][2] === keywordsCount) {\n lastTokenWithAllKeywords = i\n } else {\n break\n }\n }\n\n // If no results had all the keywords, either bail out earlier or normalize\n if (typeof lastTokenWithAllKeywords === 'undefined') {\n if (threshold === 0) {\n return []\n }\n\n lastTokenWithAllKeywords = 0\n }\n\n const keywordsPerTokenLength = keywordsPerToken.length\n const resultsWithIdAndScore: [number, number][] = new Array(keywordsPerTokenLength)\n for (let i = 0; i < keywordsPerTokenLength; i++) {\n resultsWithIdAndScore[i] = [keywordsPerToken[i][0], keywordsPerToken[i][1]]\n }\n\n // If threshold is 0, it means we will only return all the results that contains ALL the search terms (exact match)\n if (threshold === 0) {\n return resultsWithIdAndScore.slice(0, lastTokenWithAllKeywords + 1)\n }\n\n // If the threshold is between 0 and 1, we will return all the results that contains at least the threshold of search terms\n // For example, if threshold is 0.5, we will return all the results that contains at least 50% of the search terms\n // (fuzzy match with a minimum threshold)\n const thresholdLength =\n lastTokenWithAllKeywords + Math.ceil((threshold * 100 * (allResults - lastTokenWithAllKeywords)) / 100)\n\n return resultsWithIdAndScore.slice(0, Math.min(allResults, thresholdLength))\n}\n\nexport function BM25(\n tf: number,\n matchingCount: number,\n docsCount: number,\n fieldLength: number,\n averageFieldLength: number,\n { k, b, d }: Required<BM25Params>\n) {\n const idf = Math.log(1 + (docsCount - matchingCount + 0.5) / (matchingCount + 0.5))\n return (idf * (d + tf * (k + 1))) / (tf + k * (1 - b + (b * fieldLength) / averageFieldLength))\n}\n","import { InternalDocumentID } from '../components/internal-document-id-store.js'\n\nexport type Magnitude = number\nexport type VectorType = Float32Array\nexport type VectorTypeLike = number[] | VectorType\n\nexport type SimilarVector = [number, number]\n\nexport const DEFAULT_SIMILARITY = 0.8\n\nexport class VectorIndex {\n private vectors: Map<InternalDocumentID, [Magnitude, VectorType]> = new Map()\n\n constructor(public size: number) {}\n\n add(internalDocumentId: InternalDocumentID, value: VectorTypeLike) {\n if (!(value instanceof Float32Array)) {\n value = new Float32Array(value)\n }\n\n const magnitude = getMagnitude(value, this.size)\n this.vectors.set(internalDocumentId, [magnitude, value])\n }\n\n remove(internalDocumentId: InternalDocumentID) {\n this.vectors.delete(internalDocumentId)\n }\n\n find(\n vector: VectorTypeLike,\n similarity: number,\n whereFiltersIDs: Set<InternalDocumentID> | undefined\n ): SimilarVector[] {\n if (!(vector instanceof Float32Array)) {\n vector = new Float32Array(vector)\n }\n\n const results = findSimilarVectors(vector, whereFiltersIDs, this.vectors, this.size, similarity)\n\n return results\n }\n\n public toJSON(): { size: number; vectors: [InternalDocumentID, [Magnitude, number[]]][] } {\n const vectors: [InternalDocumentID, [Magnitude, number[]]][] = []\n\n for (const [id, [magnitude, vector]] of this.vectors) {\n vectors.push([id, [magnitude, Array.from(vector)]])\n }\n\n return {\n size: this.size,\n vectors\n }\n }\n\n public static fromJSON(json: any): VectorIndex {\n const raw: { size: number; vectors: [InternalDocumentID, [Magnitude, number[]]][] } = json\n\n const index = new VectorIndex(raw.size)\n for (const [id, [magnitude, vector]] of raw.vectors) {\n index.vectors.set(id, [magnitude, new Float32Array(vector)])\n }\n\n return index\n }\n}\n\nexport function getMagnitude(vector: Float32Array, vectorLength: number): number {\n let magnitude = 0\n for (let i = 0; i < vectorLength; i++) {\n magnitude += vector[i] * vector[i]\n }\n return Math.sqrt(magnitude)\n}\n\n// @todo: Write plugins for Node and Browsers to use parallel computation for this function\nexport function findSimilarVectors(\n targetVector: Float32Array,\n keys: Set<InternalDocumentID> | undefined,\n vectors: Map<InternalDocumentID, [Magnitude, VectorType]>,\n length: number,\n threshold\n): SimilarVector[] {\n const targetMagnitude = getMagnitude(targetVector, length)\n\n const similarVectors: SimilarVector[] = []\n\n const base = keys ? keys : vectors.keys()\n\n for (const vectorId of base) {\n const entry = vectors.get(vectorId)\n if (!entry) {\n continue\n }\n const magnitude = entry[0]\n const vector = entry[1]\n\n let dotProduct = 0\n for (let i = 0; i < length; i++) {\n dotProduct += targetVector[i] * vector[i]\n }\n\n const similarity = dotProduct / (targetMagnitude * magnitude)\n\n if (similarity >= threshold) {\n similarVectors.push([vectorId, similarity])\n }\n }\n\n return similarVectors\n}\n","// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\n\nconst step2List = {\n ational: 'ate',\n tional: 'tion',\n enci: 'ence',\n anci: 'ance',\n izer: 'ize',\n bli: 'ble',\n alli: 'al',\n entli: 'ent',\n eli: 'e',\n ousli: 'ous',\n ization: 'ize',\n ation: 'ate',\n ator: 'ate',\n alism: 'al',\n iveness: 'ive',\n fulness: 'ful',\n ousness: 'ous',\n aliti: 'al',\n iviti: 'ive',\n biliti: 'ble',\n logi: 'log'\n}\n\nconst step3List = {\n icate: 'ic',\n ative: '',\n alize: 'al',\n iciti: 'ic',\n ical: 'ic',\n ful: '',\n ness: ''\n}\n\n// Consonant\nconst c = '[^aeiou]'\n// Vowel\nconst v = '[aeiouy]'\n// Consonant sequence\nconst C = c + '[^aeiouy]*'\n// Vowel sequence\nconst V = v + '[aeiou]*'\n\n// [C]VC... is m>0\nconst mgr0 = '^(' + C + ')?' + V + C\n// [C]VC[V] is m=1\nconst meq1 = '^(' + C + ')?' + V + C + '(' + V + ')?$'\n// [C]VCVC... is m>1\nconst mgr1 = '^(' + C + ')?' + V + C + V + C\n// vowel in stem\nconst s_v = '^(' + C + ')?' + v\n\nexport function stemmer(w) {\n let stem\n let suffix\n let re\n let re2\n let re3\n let re4\n\n if (w.length < 3) {\n return w\n }\n\n const firstch = w.substring(0, 1)\n if (firstch == 'y') {\n w = firstch.toUpperCase() + w.substring(1)\n }\n\n re = /^(.+?)(ss|i)es$/\n re2 = /^(.+?)([^s])s$/\n\n if (re.test(w)) {\n w = w.replace(re, '$1$2')\n } else if (re2.test(w)) {\n w = w.replace(re2, '$1$2')\n }\n\n re = /^(.+?)eed$/\n re2 = /^(.+?)(ed|ing)$/\n if (re.test(w)) {\n const fp = re.exec(w)\n re = new RegExp(mgr0)\n if (re.test(fp[1])) {\n re = /.$/\n w = w.replace(re, '')\n }\n } else if (re2.test(w)) {\n const fp = re2.exec(w)\n stem = fp[1]\n re2 = new RegExp(s_v)\n if (re2.test(stem)) {\n w = stem\n re2 = /(at|bl|iz)$/\n re3 = new RegExp('([^aeiouylsz])\\\\1$')\n re4 = new RegExp('^' + C + v + '[^aeiouwxy]$')\n if (re2.test(w)) {\n w = w + 'e'\n } else if (re3.test(w)) {\n re = /.$/\n w = w.replace(re, '')\n } else if (re4.test(w)) {\n w = w + 'e'\n }\n }\n }\n\n re = /^(.+?)y$/\n if (re.test(w)) {\n const fp = re.exec(w)\n stem = fp?.[1]\n re = new RegExp(s_v)\n if (stem && re.test(stem)) {\n w = stem + 'i'\n }\n }\n\n re =\n /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/\n if (re.test(w)) {\n const fp = re.exec(w)\n stem = fp?.[1]\n suffix = fp?.[2]\n re = new RegExp(mgr0)\n if (stem && re.test(stem)) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n w = stem + step2List[suffix]\n }\n }\n\n re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/\n if (re.test(w)) {\n const fp = re.exec(w)\n stem = fp?.[1]\n suffix = fp?.[2]\n re = new RegExp(mgr0)\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (stem && re.test(stem)) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n w = stem + step3List[suffix]\n }\n }\n\n re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/\n re2 = /^(.+?)(s|t)(ion)$/\n if (re.test(w)) {\n const fp = re.exec(w)\n stem = fp?.[1]\n re = new RegExp(mgr1)\n if (stem && re.test(stem)) {\n w = stem\n }\n } else if (re2.test(w)) {\n const fp = re2.exec(w)\n stem = fp?.[1] ?? '' + fp?.[2] ?? ''\n re2 = new RegExp(mgr1)\n if (re2.test(stem)) {\n w = stem\n }\n }\n\n re = /^(.+?)e$/\n if (re.test(w)) {\n const fp = re.exec(w)\n stem = fp?.[1]\n re = new RegExp(mgr1)\n re2 = new RegExp(meq1)\n re3 = new RegExp('^' + C + v + '[^aeiouwxy]$')\n if (stem && (re.test(stem) || (re2.test(stem) && !re3.test(stem)))) {\n w = stem\n }\n }\n\n re = /ll$/\n re2 = new RegExp(mgr1)\n if (re.test(w) && re2.test(w)) {\n re = /.$/\n w = w.replace(re, '')\n }\n\n if (firstch == 'y') {\n w = firstch.toLowerCase() + w.substring(1)\n }\n\n return w\n}\n","import { AnyIndexStore, AnyOrama, SearchableType, Tokenizer } from '@orama/orama'\nimport { avl, bkd, flat, radix, bool, vector } from '@orama/orama/trees'\nimport { getVectorSize, index as Index, internalDocumentIDStore, isVectorType } from '@orama/orama/components'\n\ntype InternalDocumentID = internalDocumentIDStore.InternalDocumentID\n\nexport interface QPSIndex extends AnyIndexStore {\n indexes: Record<string, Index.Tree>\n searchableProperties: string[]\n searchablePropertiesWithTypes: Record<string, SearchableType>\n stats: Record<\n string,\n {\n tokenQuantums: Record<InternalDocumentID, Record<string, number>>\n tokensLength: Map<InternalDocumentID, number>\n }\n >\n}\n\nexport function recursiveCreate<T extends AnyOrama>(indexDatastore: QPSIndex, schema: T['schema'], prefix: string) {\n for (const entry of Object.entries<SearchableType>(schema)) {\n const prop = entry[0]\n const type = entry[1]\n const path = `${prefix}${prefix ? '.' : ''}${prop}`\n\n if (typeof type === 'object' && !Array.isArray(type)) {\n // Nested\n recursiveCreate(indexDatastore, type, path)\n continue\n }\n\n if (isVectorType(type)) {\n indexDatastore.searchableProperties.push(path)\n indexDatastore.searchablePropertiesWithTypes[path] = type\n indexDatastore.vectorIndexes[path] = {\n type: 'Vector',\n node: new vector.VectorIndex(getVectorSize(type)),\n isArray: false\n }\n } else {\n const isArray = /\\[/.test(type as string)\n switch (type) {\n case 'boolean':\n case 'boolean[]':\n indexDatastore.indexes[path] = { type: 'Bool', node: new bool.BoolNode(), isArray }\n break\n case 'number':\n case 'number[]':\n indexDatastore.indexes[path] = {\n type: 'AVL',\n node: new avl.AVLTree<number, InternalDocumentID>(0, []),\n isArray\n }\n break\n case 'string':\n case 'string[]':\n indexDatastore.indexes[path] = { type: 'Radix', node: new radix.RadixTree(), isArray }\n break\n case 'enum':\n case 'enum[]':\n indexDatastore.indexes[path] = { type: 'Flat', node: new flat.FlatTree(), isArray }\n break\n case 'geopoint':\n indexDatastore.indexes[path] = { type: 'BKD', node: new bkd.BKDTree(), isArray }\n break\n default:\n throw new Error('INVALID_SCHEMA_TYPE: ' + path)\n }\n\n indexDatastore.searchableProperties.push(path)\n indexDatastore.searchablePropertiesWithTypes[path] = type\n }\n }\n}\n\nconst BIT_MASK_20 = 0b11111111111111111111\n\nexport function calculateTokenQuantum(prevValue: number, bit: number) {\n // if (prevValue < 0) {\n // throw new Error(\"Overflow\")\n // }\n // if (bit < 0 || bit > 20) {\n // throw new Error(\"Invalid bit\")\n // }\n\n const currentCount = count(prevValue)\n const currentSentenceMask = bitmask_20(prevValue)\n const newSentenceMask = currentSentenceMask | (1 << bit)\n return ((currentCount + 1) << 20) | newSentenceMask\n}\n\nexport function insertString(\n value: string,\n radixTree: radix.RadixTree,\n stats: QPSIndex['stats'][string],\n prop: string,\n internalId: InternalDocumentID,\n language: string | undefined,\n tokenizer: Tokenizer\n) {\n const sentences = value.split(/\\.|\\?|!/)\n\n let quantumIndex = 0\n let tokenNumber = 0\n for (const sentence of sentences) {\n const tokens = tokenizer.tokenize(sentence, language, prop)\n\n for (const token of tokens) {\n tokenNumber++\n\n if (!stats[token]) {\n stats[token] = 0\n }\n\n const tokenBitIndex = Math.min(quantumIndex, 20)\n\n stats.tokenQuantums[internalId][token] = calculateTokenQuantum(\n stats.tokenQuantums[internalId][token],\n tokenBitIndex\n )\n\n radixTree.insert(token, internalId)\n }\n\n // Don't increment the quantum index if the sentence is too short\n if (tokens.length > 1) {\n quantumIndex++\n }\n }\n\n stats.tokensLength.set(internalId, tokenNumber)\n}\n\nexport function searchString(prop: {\n tokens: string[]\n radixNode: radix.RadixNode\n exact: boolean\n tolerance: number\n stats: {\n tokensLength: Map<number, number>\n tokenQuantums: Record<number, Record<string, number>>\n }\n boostPerProp: number\n resultMap: Map<number, [number, number]>\n whereFiltersIDs: Set<number> | undefined\n}) {\n const tokens = prop.tokens\n const radixNode = prop.radixNode\n const exact = prop.exact\n const tolerance = prop.tolerance\n const stats = prop.stats\n const boostPerProp = prop.boostPerProp\n const resultMap = prop.resultMap\n const whereFiltersIDs = prop.whereFiltersIDs\n const tokensLength = stats.tokensLength\n const tokenQuantums = stats.tokenQuantums\n\n const findParam = {\n term: '',\n exact,\n tolerance\n }\n\n let foundWords = {} as Record<string, number[]>\n const tokenLength = tokens.length\n for (let i = 0; i < tokenLength; i++) {\n const term = tokens[i]\n findParam.term = term\n const results = radixNode.find(findParam)\n foundWords = {\n ...foundWords,\n ...results\n }\n }\n\n const foundKeys = Object.keys(foundWords)\n const foundKeysLength = foundKeys.length\n for (let i = 0; i < foundKeysLength; i++) {\n const key = foundKeys[i]\n const matchedDocs = foundWords[key]\n const matchedDocsLength = matchedDocs.length\n const isExactMatch = tokens.includes(key)\n\n for (let j = 0; j < matchedDocsLength; j++) {\n const docId = matchedDocs[j]\n\n if (whereFiltersIDs && !whereFiltersIDs.has(docId)) {\n continue\n }\n\n const numberOfQuantums = tokensLength.get(docId)!\n const tokenQuantumDescriptor = tokenQuantums[docId][key]\n\n const occurrence = count(tokenQuantumDescriptor)\n const bitMask = bitmask_20(tokenQuantumDescriptor)\n const score = ((occurrence * occurrence) / numberOfQuantums + (isExactMatch ? 1 : 0)) * boostPerProp\n\n if (!resultMap.has(docId)) {\n resultMap.set(docId, [score, bitMask])\n continue\n }\n\n const current = resultMap.get(docId)!\n\n const totalScore = current[0] + numberOfOnes(current[1] & bitMask) * 2 + score\n\n current[0] = totalScore\n current[1] = current[1] | bitMask\n }\n }\n}\n\nexport function bitmask_20(n: number) {\n return n & BIT_MASK_20\n}\nexport function count(n: number) {\n return n >> 20\n}\n\nexport function numberOfOnes(n: number) {\n let i = 0\n do {\n if (n & 1) {\n ++i\n }\n // eslint-disable-next-line no-cond-assign\n } while ((n >>= 1))\n return i\n}\n\nexport function removeString(\n value: string,\n radixTree: radix.RadixTree,\n prop: string,\n internalId: InternalDocumentID,\n tokenizer: Tokenizer,\n language: string | undefined,\n stats: {\n tokensLength: Map<number, number>\n tokenQuantums: Record<number, Record<string, number>>\n }\n) {\n const tokensLength = stats.tokensLength\n const tokenQuantums = stats.tokenQuantums\n\n const tokens = tokenizer.tokenize(value, language, prop)\n\n for (const token of tokens) {\n radixTree.removeDocumentByWord(token, internalId, true)\n }\n\n tokensLength.delete(internalId)\n delete tokenQuantums[internalId]\n}\n","import type {\n AnyOrama,\n SearchableType,\n IIndex,\n SearchableValue,\n Tokenizer,\n OnlyStrings,\n FlattenSchemaProperty,\n TokenScore,\n WhereCondition,\n OramaPluginSync,\n AnySchema,\n ObjectComponents,\n BM25Params\n} from '@orama/orama'\nimport { index as Index, internalDocumentIDStore } from '@orama/orama/components'\nimport { insertString, QPSIndex as QPSIndexStorage, recursiveCreate, removeString, searchString } from './algorithm.js'\nimport { radix } from '@orama/orama/trees'\nimport { setIntersection } from '@orama/orama/internals'\n\ntype InternalDocumentID = internalDocumentIDStore.InternalDocumentID\ntype InternalDocumentIDStore = internalDocumentIDStore.InternalDocumentIDStore\ntype DocumentID = internalDocumentIDStore.DocumentID\n\nconst unusedRadix = new radix.RadixNode('', '', false)\nconst unusedStats = {\n tokenQuantums: {},\n tokensLength: new Map()\n}\n\nfunction search<T extends AnyOrama>(\n index: QPSIndexStorage,\n term: string,\n tokenizer: Tokenizer,\n language: string | undefined,\n propertiesToSearch: string[],\n exact: boolean,\n tolerance: number,\n boost: Partial<Record<OnlyStrings<FlattenSchemaProperty<T>[]>, number>>,\n relevance: Required<BM25Params>,\n docsCount: number,\n whereFiltersIDs: Set<InternalDocumentID> | undefined\n): TokenScore[] {\n const all: Map<InternalDocumentID, [number, number]> = new Map()\n\n const args = {\n tokens: tokenizer.tokenize(term, language),\n radixNode: unusedRadix,\n exact,\n tolerance,\n stats: unusedStats,\n boostPerProp: 0,\n all,\n resultMap: all,\n whereFiltersIDs\n }\n\n const propertiesToSearchLength = propertiesToSearch.length\n for (let i = 0; i < propertiesToSearchLength; i++) {\n const prop = propertiesToSearch[i]\n const stats = index.stats[prop]\n const boostPerProp = boost[prop] ?? 1\n args.radixNode = index.indexes[prop].node as radix.RadixNode\n args.stats = stats\n args.boostPerProp = boostPerProp\n searchString(args)\n }\n\n const g: [number, [number, number]][] = Array.from(all)\n const gLength = g.length\n const res: TokenScore[] = []\n for (let i = 0; i < gLength; i++) {\n const element = g[i]\n const id = element[0]\n const score = element[1][0]\n\n res.push([id, score])\n }\n\n return res\n}\n\nexport function pluginQPS(): OramaPluginSync<unknown> {\n return {\n name: 'qps',\n getComponents(schema: AnySchema) {\n return qpsComponents(schema)\n }\n }\n}\n\nfunction qpsComponents(schema: AnySchema): Partial<ObjectComponents<any, any, any, any>> {\n return {\n index: {\n create: function create() {\n const indexDatastore: QPSIndexStorage = {\n indexes: {},\n vectorIndexes: {},\n searchableProperties: [],\n searchablePropertiesWithTypes: {},\n stats: {}\n }\n\n recursiveCreate(indexDatastore, schema, '')\n\n return indexDatastore\n },\n insert: function insert(\n implementation: IIndex<QPSIndexStorage>,\n indexDatastorage: QPSIndexStorage,\n prop: string,\n id: DocumentID,\n internalId: InternalDocumentID,\n value: SearchableValue,\n schemaType: SearchableType,\n language: string | undefined,\n tokenizer: Tokenizer,\n docsCount: number\n ) {\n if (!(schemaType === 'string' || schemaType === 'string[]')) {\n return Index.insert(\n implementation as unknown as IIndex<Index.Index>,\n indexDatastorage as unknown as Index.Index,\n prop,\n id,\n internalId,\n value,\n schemaType,\n language,\n tokenizer,\n docsCount\n )\n }\n\n if (!indexDatastorage.stats[prop]) {\n indexDatastorage.stats[prop] = {\n tokenQuantums: {},\n tokensLength: new Map()\n }\n }\n\n const stats = indexDatastorage.stats[prop]\n const radixTree = indexDatastorage.indexes[prop].node as radix.RadixNode\n\n stats.tokenQuantums[internalId] = {}\n\n if (Array.isArray(value)) {\n for (const item of value) {\n insertString(item as string, radixTree, stats, prop, internalId, language, tokenizer)\n }\n } else {\n insertString(value as string, radixTree, stats, prop, internalId, language, tokenizer)\n }\n },\n remove: function remove(\n implementation: IIndex<QPSIndexStorage>,\n indexDatastorage: QPSIndexStorage,\n prop: string,\n id: DocumentID,\n internalId: InternalDocumentID,\n value: SearchableValue,\n schemaType: SearchableType,\n language: string | undefined,\n tokenizer: Tokenizer,\n docsCount: number\n ) {\n if (!(schemaType === 'string' || schemaType === 'string[]')) {\n return Index.remove(\n implementation as unknown as IIndex<Index.Index>,\n indexDatastorage as unknown as Index.Index,\n prop,\n id,\n internalId,\n value,\n schemaType,\n language,\n tokenizer,\n docsCount\n )\n }\n\n const stats = indexDatastorage.stats[prop]\n const radixTree = indexDatastorage.indexes[prop].node as radix.RadixNode\n\n if (Array.isArray(value)) {\n for (const item of value) {\n removeString(item as string, radixTree, prop, internalId, tokenizer, language, stats)\n }\n } else {\n removeString(value as string, radixTree, prop, internalId, tokenizer, language, stats)\n }\n },\n insertDocumentScoreParameters: () => {\n throw new Error()\n },\n insertTokenScoreParameters: () => {\n throw new Error()\n },\n removeDocumentScoreParameters: () => {\n throw new Error()\n },\n removeTokenScoreParameters: () => {\n throw new Error()\n },\n calculateResultScores: () => {\n throw new Error()\n },\n search,\n searchByWhereClause: function searchByWhereClause<T extends AnyOrama>(\n index: QPSIndexStorage,\n tokenizer: Tokenizer,\n filters: Partial<WhereCondition<T['schema']>>,\n language: string | undefined\n ) {\n const stringFiltersList = Object.entries(filters).filter(\n ([propName]) => index.indexes[propName].type === 'Radix'\n )\n\n // If there are no string filters, we can use the regular search\n if (stringFiltersList.length === 0) {\n return Index.searchByWhereClause(index as unknown as Index.Index, tokenizer, filters, language)\n }\n\n let idsFromStringFilters: Set<InternalDocumentID> | undefined\n for (const [propName, filter] of stringFiltersList) {\n let tokens: string[] = []\n\n if (Array.isArray(filter)) {\n for (const item of filter) {\n const token = tokenizer.tokenize(item as string, language)?.[0]\n tokens.push(token)\n }\n } else {\n tokens = tokenizer.tokenize(filter as string, language)\n }\n\n const radixTree = index.indexes[propName].node as radix.RadixNode\n const propIds = new Set<InternalDocumentID>()\n for (const token of tokens) {\n const ret = radixTree.find({\n term: token,\n exact: true\n })\n\n const ids = ret[token]\n\n if (ids) {\n for (const id of ids) {\n propIds.add(id)\n }\n }\n }\n\n if (idsFromStringFilters) {\n idsFromStringFilters = setIntersection(idsFromStringFilters, propIds)\n } else {\n idsFromStringFilters = propIds\n }\n }\n\n // Split the filters into string and non-string filters\n const nonStringFiltersList = Object.entries(filters).filter(\n ([propName]) => index.indexes[propName].type !== 'Radix'\n )\n if (nonStringFiltersList.length === 0) {\n return idsFromStringFilters\n }\n\n const idsFromNonStringFilters = Index.searchByWhereClause(\n index as unknown as Index.Index,\n tokenizer,\n filters,\n language\n )\n\n return setIntersection(idsFromStringFilters!, idsFromNonStringFilters)\n },\n getSearchableProperties: function getSearchableProperties(index: QPSIndexStorage): string[] {\n return index.searchableProperties\n },\n getSearchablePropertiesWithTypes: function (index: QPSIndexStorage) {\n return index.searchablePropertiesWithTypes\n },\n load: function load<R = unknown>(sharedInternalDocumentStore: InternalDocumentIDStore, raw: R): QPSIndexStorage {\n const dump1 = Index.load(sharedInternalDocumentStore, raw[0])\n\n const dump2 = raw[1] as {\n radixTrees: [string, boolean, string, unknown][]\n stats: [\n string,\n {\n tokenQuantums: [InternalDocumentID, Record<string, number>][]\n tokensLength: [InternalDocumentID, number][]\n }\n ][]\n }\n\n const indexes = {\n ...dump1.indexes,\n ...Object.fromEntries(\n dump2.radixTrees.map(([prop, isArray, type, node]) => [\n prop,\n {\n node: radix.RadixNode.fromJSON(node),\n isArray,\n type\n } as Index.Tree\n ])\n )\n }\n\n return {\n ...dump1,\n indexes,\n stats: Object.fromEntries(\n dump2.stats.map(([prop, { tokenQuantums, tokensLength }]) => [\n prop,\n {\n tokenQuantums,\n tokensLength: new Map(tokensLength)\n }\n ])\n )\n } as unknown as QPSIndexStorage\n },\n save: function save<R = unknown>(index: QPSIndexStorage): R {\n const baseIndex = index as unknown as Index.Index\n const nonStringIndexes = Object.entries(baseIndex.indexes).filter(([, { type }]) => type !== 'Radix')\n const dump1 = Index.save({\n ...baseIndex,\n indexes: Object.fromEntries(nonStringIndexes)\n })\n\n const stringIndexes = Object.entries(baseIndex.indexes).filter(([, { type }]) => type === 'Radix')\n const dump2 = {\n radixTrees: stringIndexes.map(([prop, { node, isArray, type }]) => [prop, isArray, type, node.toJSON()]),\n stats: Object.entries(index.stats).map(([prop, { tokenQuantums, tokensLength }]) => [\n prop,\n {\n tokenQuantums,\n tokensLength: Array.from(tokensLength.entries())\n }\n ])\n }\n\n return [dump1, dump2] as unknown as R\n }\n }\n }\n}\n"],"mappings":"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","names":["STEMMERS","SUPPORTED_LANGUAGES","STEMMERS","baseId","nano","milli","second","sprintf","template","args","replaceArgs","groups","rawWidth","type","position","replacement","width","value","padding","precision","w","getOwnProperty","object","property","mapDistanceToMeters","convertDistanceToMeters","distance","unit","ratio","createError","withIntersection","setIntersection","sets","set1","set2","result","base","other","value","min","i","withUnion","setUnion","setDifference","allLanguages","SUPPORTED_LANGUAGES","errors","createError","code","args","error","sprintf","IS_ARRAY_TYPE","INNER_TYPE","isVectorType","type","isArrayType","IS_ARRAY_TYPE","getInnerType","INNER_TYPE","getVectorSize","size","createError","getInternalDocumentId","store","id","internalId","currentId","components_exports","__export","calculateResultScores","create","createIndex","getSearchableProperties","getSearchablePropertiesWithTypes","insert","insertDocumentScoreParameters","insertTokenScoreParameters","insertVector","load","remove","removeDocumentScoreParameters","removeTokenScoreParameters","save","search","searchByGeoWhereClause","searchByWhereClause","avl_exports","__export","AVLNode","AVLTree","AVLNode","_AVLNode","key","value","__publicField","node","newRoot","json","AVLTree","_AVLTree","rebalanceThreshold","v","tree","path","current","parent","needRebalance","i","currentNode","rebalancedNode","balanceFactor","count","stack","id","child","successorParent","successor","min","max","result","inclusive","flat_exports","__export","FlatTree","FlatTree","_FlatTree","__publicField","key","value","idSet","id","size","operation","operationKeys","operationType","values","resultSet","excludeValues","idSets","intersection","prev","curr","union","json","tree","ids","radix_exports","__export","RadixNode","RadixTree","_boundedLevenshtein","term","word","tolerance","m","n","diff","matrix","i","j","rowMin","syncBoundedLevenshtein","term","w","tolerance","distance","_boundedLevenshtein","RadixNode","_RadixNode","key","subWord","end","__publicField","parent","docID","output","term","exact","tolerance","stack","node","w","docIDs","getOwnProperty","syncBoundedLevenshtein","docs","word","docId","i","wordLength","currentCharacter","childNode","edgeLabel","edgeLabelLength","j","commonPrefix","newEdgeLabel","newWordLabel","inbetweenNode","newNode","index","originalTolerance","currentChar","character","params","termLength","a","b","len","json","nodeJson","RadixTree","_RadixTree","tree","bkd_exports","__export","BKDTree","BKDNode","_BKDNode","point","docIDs","__publicField","json","parent","node","BKDTree","_BKDTree","pointKey","existingNode","id","newNode","depth","docID","child","center","radius","inclusive","sort","highPrecision","distanceFn","stack","result","dist","a","b","distA","distB","polygon","isInsidePolygon","centroid","tree","totalArea","centroidX","centroidY","polygonLength","i","j","xi","yi","xj","yj","areaSegment","centroidCoordinate","isInside","x","y","coord1","coord2","P","lat1","lat2","deltaLat","deltaLon","f","U1","U2","sinU1","cosU1","sinU2","cosU2","lambda","prevLambda","iterationLimit","sinSigma","cosSigma","sigma","sinAlpha","cos2Alpha","cos2SigmaM","sinLambda","cosLambda","C","uSquared","A","B","deltaSigma","bool_exports","__export","BoolNode","BoolNode","_BoolNode","__publicField","value","bool","json","node","BM25","tf","matchingCount","docsCount","fieldLength","averageFieldLength","k","b","d","vector_exports","__export","DEFAULT_SIMILARITY","VectorIndex","findSimilarVectors","getMagnitude","DEFAULT_SIMILARITY","VectorIndex","_VectorIndex","size","__publicField","internalDocumentId","value","magnitude","getMagnitude","vector","similarity","whereFiltersIDs","findSimilarVectors","vectors","id","json","raw","index","vectorLength","i","targetVector","keys","length","threshold","targetMagnitude","similarVectors","base","vectorId","entry","dotProduct","insertDocumentScoreParameters","index","prop","id","tokens","docsCount","internalId","getInternalDocumentId","insertTokenScoreParameters","token","tokenFrequency","t","tf","removeDocumentScoreParameters","removeTokenScoreParameters","create","orama","sharedInternalDocumentStore","schema","prefix","type","path","isVectorType","VectorIndex","getVectorSize","isArray","BoolNode","AVLTree","RadixTree","FlatTree","BKDTree","createError","insertScalarBuilder","implementation","language","tokenizer","options","value","node","avlRebalanceThreshold","insert","schemaType","insertVector","insertScalar","isArrayType","elements","elementsLength","i","internalDocumentId","removeScalar","remove","innerSchemaType","getInnerType","calculateResultScores","term","ids","bm25Relevance","resultsMap","boostPerProperty","whereFiltersIDs","keywordMatchesMap","documentIDs","avgFieldLength","fieldLengths","oramaOccurrences","oramaFrequencies","termOccurrences","documentIDsLength","k","propertyMatches","bm25","BM25","search","propertiesToSearch","exact","tolerance","boost","relevance","threshold","keywordsCount","tokenFoundMap","tree","tokenLength","searchResult","termsFound","termsFoundLength","j","word","results","score","a","b","matches","fullMatches","remainingResults","fid","additionalResults","searchByWhereClause","filters","andFilters","filter","setIntersection","orFilters","acc","set","setUnion","notFilter","allDocs","docsStore","notResult","setDifference","filterKeys","filtersMap","key","param","operation","idx","filteredIDs","reqOperation","coordinates","unit","inside","highPrecision","distanceInMeters","convertDistanceToMeters","addGeoResult","raw","filteredIDsResults","addFindResult","operationKeys","operationOpt","operationValue","min","max","getSearchableProperties","getSearchablePropertiesWithTypes","load","rawIndexes","rawVectorIndexes","searchableProperties","searchablePropertiesWithTypes","frequencies","tokenOccurrences","indexes","vectorIndexes","save","dumpVectorIndexes","savedIndexes","name","createIndex","idsLength","entry","createGeoTokenScores","centerPoint","distanceFn","distances","point","maxDistance","docIDs","distance","docID","isGeosearchOnlyQuery","searchByGeoWhereClause","indexTyped","geoInfo","bkdNode","centroid","keys","keysLength","c","v","C","V","mgr0","meq1","mgr1","s_v","recursiveCreate","indexDatastore","schema","prefix","entry","prop","type","path","isVectorType","vector_exports","getVectorSize","isArray","bool_exports","avl_exports","radix_exports","flat_exports","bkd_exports","BIT_MASK_20","calculateTokenQuantum","prevValue","bit","currentCount","count","newSentenceMask","bitmask_20","insertString","value","radixTree","stats","internalId","language","tokenizer","sentences","quantumIndex","tokenNumber","sentence","tokens","token","tokenBitIndex","searchString","radixNode","exact","tolerance","boostPerProp","resultMap","whereFiltersIDs","tokensLength","tokenQuantums","findParam","foundWords","tokenLength","i","term","results","foundKeys","foundKeysLength","key","matchedDocs","matchedDocsLength","isExactMatch","j","docId","numberOfQuantums","tokenQuantumDescriptor","occurrence","bitMask","score","current","totalScore","numberOfOnes","n","removeString","unusedRadix","radix_exports","unusedStats","search","index","term","tokenizer","language","propertiesToSearch","exact","tolerance","boost","relevance","docsCount","whereFiltersIDs","all","args","propertiesToSearchLength","i","prop","stats","boostPerProp","searchString","g","gLength","res","element","id","score","pluginQPS","schema","qpsComponents","indexDatastore","recursiveCreate","implementation","indexDatastorage","internalId","value","schemaType","components_exports","radixTree","item","insertString","removeString","filters","stringFiltersList","propName","idsFromStringFilters","filter","tokens","token","propIds","ids","setIntersection","idsFromNonStringFilters","sharedInternalDocumentStore","raw","dump1","dump2","indexes","isArray","type","node","tokenQuantums","tokensLength","baseIndex","nonStringIndexes"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wcs-colab/plugin-qps",
|
|
3
|
+
"version": "3.1.16-custom.10",
|
|
4
|
+
"description": "Performant search algorithm optimized for descriptive texts",
|
|
5
|
+
"keywords": ["orama", "embeddings", "secure proxy", "vector search"],
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"require": "./dist/index.cjs",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"browser": "./dist/index.global.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/oramasearch/orama/issues"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/oramasearch/orama#readme",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/oramasearch/orama.git"
|
|
24
|
+
},
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"files": ["dist"],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsup --config tsup.lib.js",
|
|
30
|
+
"lint": "exit 0",
|
|
31
|
+
"test": "node --test --import tsx test/*.test.ts"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^20.9.0",
|
|
38
|
+
"tap": "^21.0.1",
|
|
39
|
+
"tsup": "^7.2.0",
|
|
40
|
+
"tsx": "^4.19.1",
|
|
41
|
+
"typescript": "^5.0.0"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@wcs-colab/orama": "3.1.16-custom.9"
|
|
45
|
+
}
|
|
46
|
+
}
|