@andrew_l/search-query-language 0.2.13

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/TokenType.ts","../src/constants.ts","../src/Token.ts","../src/Tokenizer.ts","../src/Expression.ts","../src/parseQuery.ts","../src/parseToMongo.ts","../src/parseToMongoose.ts"],"sourcesContent":["export interface TokenTypeOptions {\n keyword?: string;\n}\n\n/**\n * @group Utils\n */\nexport class TokenType {\n readonly label: string;\n readonly keyword: string | undefined;\n\n constructor(label: string, options?: TokenTypeOptions) {\n this.label = label;\n this.keyword = options?.keyword;\n }\n}\n","import { TokenType, type TokenTypeOptions } from './TokenType';\n\n/**\n * Node types\n * @group Constants\n */\nexport const NODE = Object.freeze({\n PROGRAM: 'program',\n IDENTIFIER: 'identifier',\n LITERAL: 'literal',\n LOGICAL_EXPRESSION: 'logical-expression',\n BINARY_EXPRESSION: 'binary-expression',\n});\n\n/**\n * Keyword tokens.\n * @group Constants\n */\nexport const KEYWORDS: Record<string, TokenType> = {};\n\n/**\n * Token types\n * @group Constants\n */\nexport const TOKEN = Object.freeze({\n /**\n * Start of File token.\n */\n SOF: new TokenType('sof'),\n\n /**\n * End of File token.\n */\n EOF: new TokenType('eof'),\n\n /**\n * Number token.\n */\n NUM: new TokenType('num'),\n\n /**\n * String token.\n */\n STRING: new TokenType('string'),\n\n /**\n * Identifier token.\n */\n NAME: new TokenType('identifier'),\n\n /**\n * Parenthesis token.\n */\n PAREN_L: new TokenType('('),\n\n /**\n * Parenthesis token.\n */\n PAREN_R: new TokenType(')'),\n\n /**\n * Logical operator token.\n */\n LOGICAL_OR: kw('OR'),\n\n /**\n * Logical operator token.\n */\n LOGICAL_AND: kw('AND'),\n\n /**\n * Equality operator token.\n */\n EQUALITY: new TokenType('=/!='),\n\n /**\n * Relational operator token.\n */\n RELATIONAL: new TokenType('</>/<=/>='),\n\n /**\n * Minus operator token.\n */\n MINUS: new TokenType('-'),\n\n /**\n * Null literal token.\n */\n NULL: kw('null'),\n\n /**\n * True literal tokens.\n */\n TRUE: kw('true'),\n\n /**\n * False literal tokens.\n */\n FALSE: kw('false'),\n} as const);\n\nfunction kw(name: string, options: TokenTypeOptions = {}) {\n options.keyword = name;\n return (KEYWORDS[name] = new TokenType(name, options));\n}\n","import type { TokenType } from './TokenType';\n\nexport interface TokenOptions {\n type: TokenType;\n value: unknown;\n start: number;\n end: number;\n}\n\n/**\n * @group Utils\n */\nexport class Token {\n public readonly type: TokenType;\n public readonly value: unknown;\n public readonly start: number;\n public readonly end: number;\n\n constructor(p: TokenOptions) {\n this.type = p.type;\n this.value = p.value;\n this.start = p.start;\n this.end = p.end;\n }\n}\n","import { KEYWORDS, TOKEN } from './constants';\nimport { Token, type TokenOptions } from './Token';\nimport type { TokenType } from './TokenType';\n\n/**\n * @group Utils\n */\nexport class Tokenizer implements Iterable<Token> {\n protected input: string;\n protected pos: number;\n protected length: number;\n protected state: TokenOptions;\n protected prev: TokenOptions;\n\n constructor(input: string) {\n this.input = input;\n this.length = input.length;\n this.pos = 0;\n this.state = {\n start: 0,\n end: 0,\n type: TOKEN.SOF,\n value: null,\n };\n this.prev = { ...this.state };\n }\n\n [Symbol.iterator]() {\n return {\n next: () => {\n let token = this.getToken();\n\n return {\n done: token.type === TOKEN.EOF,\n value: token,\n };\n },\n };\n }\n\n /**\n * Get the next token.\n */\n getToken(): Token {\n this.nextToken();\n const token = new Token(this.state);\n\n return token;\n }\n\n protected nextToken(): void {\n this.skipSpace();\n this.state.start = this.pos;\n if (this.pos >= this.length) return this.finishToken(TOKEN.EOF);\n this.readToken(this.charCodeAtPos());\n }\n\n protected skipSpace(): void {\n let ch: number;\n while (this.pos < this.length) {\n ch = this.charCodeAtPos();\n if (ch === 32 || ch === 160) {\n this.pos++;\n } else {\n break;\n }\n }\n }\n\n protected finishToken(type: TokenType, value?: unknown): void {\n Object.assign(this.prev, this.state);\n this.state.end = this.pos;\n this.state.type = type;\n this.state.value = value;\n }\n\n protected finishOp(type: TokenType, size: number): void {\n let str = this.input.slice(this.pos, this.pos + size);\n this.pos += size;\n return this.finishToken(type, str);\n }\n\n protected readToken(code: number): void {\n if (isIdentifierStart(code)) {\n return this.readWord();\n }\n\n return this.getTokenFromCode(code);\n }\n\n protected getTokenFromCode(code: number): void {\n switch (code) {\n case 40:\n ++this.pos;\n return this.finishToken(TOKEN.PAREN_L);\n case 41:\n ++this.pos;\n return this.finishToken(TOKEN.PAREN_R);\n\n case 49:\n case 50:\n case 51:\n case 52:\n case 53:\n case 54:\n case 55:\n case 56:\n case 57: // 1-9\n return this.readNumber();\n\n case 45: // -\n ++this.pos;\n return this.finishToken(TOKEN.MINUS);\n\n case 61:\n case 33: // '=!'\n return this.readEquality(code);\n\n case 60:\n case 62: // <>\n return this.readLtGt();\n\n case 34: // \"\n return this.readString();\n }\n\n this.raise(\n this.pos,\n \"Unexpected character '\" + String.fromCharCode(code) + \"'\",\n );\n }\n\n protected charCodeAtPos(): number {\n return this.input.charCodeAt(this.pos);\n }\n\n protected readEquality(code: number): void {\n let next = this.input.charCodeAt(this.pos + 1);\n\n if (code === 33) {\n if (next === 61) return this.finishOp(TOKEN.EQUALITY, 2);\n } else {\n return this.finishOp(TOKEN.EQUALITY, 1);\n }\n }\n\n protected readLtGt(): void {\n let next = this.input.charCodeAt(this.pos + 1);\n let size = 1;\n\n // =\n if (next === 61) size = 2;\n\n return this.finishOp(TOKEN.RELATIONAL, size);\n }\n\n protected readInt(): number | null {\n const radix = 10;\n let start = this.pos;\n let code = 0;\n let total = 0;\n\n for (;;) {\n code = this.input.charCodeAt(this.pos);\n\n if (code >= 48 && code <= 57) {\n total = total * radix + (code - 48);\n this.pos++;\n } else {\n break;\n }\n }\n\n if (this.pos === start) return null;\n\n return total;\n }\n\n protected raise(pos: number, message: string): never {\n throw new SyntaxError(`${message} (${pos})`);\n }\n\n protected readString(): void {\n let out = '';\n let chunkStart = ++this.pos;\n let ch: number;\n\n for (;;) {\n if (this.pos >= this.length) {\n this.raise(this.state.start, 'Unterminated string constant');\n }\n\n ch = this.input.charCodeAt(this.pos);\n if (ch === 34) break;\n if (ch === 92) {\n // '\\'\n out += this.input.slice(chunkStart, this.pos);\n out += this.readEscapedChar();\n chunkStart = this.pos;\n }\n ++this.pos;\n }\n out += this.input.slice(chunkStart, this.pos++);\n return this.finishToken(TOKEN.STRING, out);\n }\n\n protected readWord(): void {\n let chunkStart = this.pos;\n let ch: number;\n let cmp = isIdentifierStart;\n\n while (this.pos < this.input.length) {\n ch = this.charCodeAtPos();\n if (!cmp(ch)) break;\n cmp = isIdentifierChar;\n this.pos++;\n }\n\n const word = this.input.slice(chunkStart, this.pos);\n\n let type = TOKEN.NAME;\n\n if (word in KEYWORDS) {\n type = KEYWORDS[word];\n }\n\n return this.finishToken(type, word);\n }\n\n protected readEscapedChar(): string {\n let ch = this.input.charCodeAt(++this.pos);\n ++this.pos;\n return String.fromCharCode(ch);\n }\n\n protected readNumber(): void {\n let start = this.pos;\n if (this.readInt() === null) this.raise(start, 'Invalid number');\n let next = this.input.charCodeAt(this.pos);\n\n // '.'\n if (next === 46) {\n ++this.pos;\n this.readInt();\n next = this.input.charCodeAt(this.pos);\n }\n\n let val = Number(this.input.slice(start, this.pos));\n return this.finishToken(TOKEN.NUM, val);\n }\n}\n\nfunction isIdentifierStart(code: number) {\n // A-Z\n if (code < 65) return false;\n if (code < 91) return true;\n // _\n if (code < 97) return code === 95;\n // a-z\n if (code < 123) return true;\n return false;\n}\n\nfunction isIdentifierChar(code: number) {\n if (code < 48) return code === 46;\n // 0-9\n if (code < 58) return true;\n // A-Z\n if (code < 65) return false;\n if (code < 91) return true;\n // _\n if (code < 97) return code === 95;\n // a-z\n if (code < 123) return true;\n\n return false;\n}\n","import { NODE, TOKEN } from './constants';\nimport { Tokenizer } from './Tokenizer';\nimport type {\n LogicalOperator,\n Node,\n NodeBinaryExpression,\n NodeExpression,\n NodeIdentifier,\n NodeLiteral,\n NodeLogicalExpression,\n NodeMap,\n NodeProgram,\n NodeType,\n} from './types';\n\n/**\n * Parse an expression class.\n *\n * @group Utils\n */\nexport class Expression extends Tokenizer {\n constructor(input: string) {\n super(input);\n }\n\n /**\n * Parse input into a program AST.\n */\n parse(): NodeProgram {\n let node = this.startNode(NODE.PROGRAM);\n node.body = [];\n this.nextToken();\n return this.parseTopLevel(node);\n }\n\n protected finishNode<T extends Node>(node: T): T {\n node.end = this.state.start;\n return node;\n }\n\n protected parseTopLevel(node: NodeProgram): NodeProgram {\n while (this.state.type !== TOKEN.EOF) {\n let stmt = this.parseExpression();\n node.body.push(stmt);\n }\n\n this.nextToken();\n return this.finishNode(node);\n }\n\n protected parseExpression(): NodeExpression {\n let left: NodeExpression | NodeIdentifier;\n\n if (this.state.type === TOKEN.PAREN_L) {\n this.nextToken();\n left = this.parseExpression();\n\n if (this.state.type !== TOKEN.PAREN_R) {\n this.raise(this.pos, 'Expected closing paren.');\n }\n\n this.nextToken();\n\n if (this.state.type === TOKEN.EOF) {\n return left;\n }\n } else {\n left = this.parseExprAtom() as NodeIdentifier;\n }\n\n let node: NodeBinaryExpression | NodeLogicalExpression;\n\n for (;;) {\n node = this.parseExprOp(left);\n node.start = left.start;\n left = node;\n\n if (this.state.type === TOKEN.EOF || this.state.type === TOKEN.PAREN_R)\n break;\n }\n\n return node;\n }\n\n protected parseExprOp(\n left: NodeExpression | NodeIdentifier,\n ): NodeBinaryExpression | NodeLogicalExpression {\n const node = this.startNode(NODE.BINARY_EXPRESSION) as\n | NodeLogicalExpression\n | NodeBinaryExpression;\n\n node.operator = this.state.value as LogicalOperator;\n node.left = left;\n\n switch (this.state.type) {\n case TOKEN.LOGICAL_AND:\n case TOKEN.LOGICAL_OR: {\n if (!isNodeExpression(node.left)) {\n this.raise(\n node.left.start,\n 'Expected expression as left side of logical expression.',\n );\n }\n\n this.nextToken();\n node.right = this.maybeLiteral() || this.parseExpression();\n node.type = NODE.LOGICAL_EXPRESSION;\n\n if (!isNodeExpression(node.right)) {\n this.raise(\n (node.right as Node).start,\n `Unexpected ${(node.right as Node).type} as right side of logical expression.`,\n );\n }\n\n break;\n }\n\n case TOKEN.EQUALITY:\n case TOKEN.RELATIONAL: {\n this.nextToken();\n\n if ((node.left as Node).type !== NODE.IDENTIFIER) {\n this.raise(\n node.start,\n `Expected identifier as left side of binary expression.`,\n );\n }\n\n node.right = this.parseExprAtom() as NodeLiteral;\n\n if ((node.right as Node).type !== NODE.LITERAL) {\n this.raise(\n (node.right as Node).start,\n 'Expected literal as right side of binary expression.',\n );\n }\n\n break;\n }\n\n default: {\n if (this.state.type === TOKEN.EOF) {\n this.raise(\n this.pos,\n `Expected operator after ${this.prev.type.label}`,\n );\n } else {\n this.raise(this.pos, `Unexpected operator: ${this.state.type.label}`);\n }\n }\n }\n\n return this.finishNode(node);\n }\n\n protected maybeLiteral(): NodeLiteral | null {\n switch (this.state.type) {\n case TOKEN.MINUS: {\n const start = this.state.start;\n this.nextToken();\n\n if (this.state.type !== TOKEN.NUM) {\n this.raise(this.pos, `Expected number after minus operator`);\n }\n\n const node = this.maybeLiteral()!;\n node.start = start;\n node.raw = `-${node.raw}`;\n node.value = (node.value as number) * -1;\n\n return node;\n }\n\n case TOKEN.NUM:\n case TOKEN.STRING: {\n let node = this.startNode(NODE.LITERAL);\n node.raw = this.input.slice(this.state.start, this.state.end);\n node.value = this.state.value as any;\n this.nextToken();\n return this.finishNode(node);\n }\n\n case TOKEN.NULL:\n case TOKEN.TRUE:\n case TOKEN.FALSE: {\n let node = this.startNode(NODE.LITERAL);\n node.raw = this.state.type.keyword;\n node.value =\n this.state.type === TOKEN.NULL\n ? null\n : this.state.type === TOKEN.TRUE;\n this.nextToken();\n return this.finishNode(node);\n }\n\n default: {\n return null;\n }\n }\n }\n\n protected maybeIdentifier(): NodeIdentifier | null {\n switch (this.state.type) {\n case TOKEN.NAME: {\n let node = this.startNode(NODE.IDENTIFIER);\n node.name = String(this.state.value);\n this.nextToken();\n return this.finishNode(node);\n }\n\n default:\n return null;\n }\n }\n\n protected parseExprAtom(): NodeIdentifier | NodeLiteral {\n const node = this.maybeIdentifier() || this.maybeLiteral();\n\n if (!node) {\n this.raise(this.pos, `Unexpected token ${this.state.type.label}.`);\n }\n\n return node;\n }\n\n protected startNode<T extends NodeType>(type: T): NodeMap[T] {\n const node: Node = { type, start: this.state.start, end: 0 };\n return node as NodeMap[T];\n }\n}\n\nfunction isNodeExpression(node: Node): node is NodeExpression {\n return (\n node.type === NODE.BINARY_EXPRESSION ||\n node.type === NODE.LOGICAL_EXPRESSION\n );\n}\n","import { Expression } from './Expression';\nimport type { NodeProgram } from './types';\n\n/**\n * Parses a query string into a NodeProgram representation.\n *\n * @param {string} value - The query string to be parsed.\n * @returns {NodeProgram} - The parsed representation of the query.\n *\n * @example\n * const program = parseQuery('age > 30');\n * console.log(program);\n * // {\n * // type: 'program',\n * // body: [\n * // {\n * // type: 'binary-expression',\n * // operator: '>',\n * // left: { type: 'identifier', name: 'age' },\n * // right: { type: 'literal', value: 30 }\n * // }\n * // ]\n * // }\n *\n * @group Main\n */\nexport function parseQuery(value: string): NodeProgram {\n return new Expression(value).parse();\n}\n","import {\n type Arrayable,\n arrayable,\n assert,\n isFunction,\n} from '@andrew_l/toolkit';\nimport { NODE } from './constants';\nimport { Expression } from './Expression';\nimport type { BinaryOperator, Node, NodeExpression } from './types';\n\nconst OPERATOR_MAP: Record<BinaryOperator, string> = {\n '=': '$eq',\n '!=': '$ne',\n '>': '$gt',\n '>=': '$gte',\n '<': '$lt',\n '<=': '$lte',\n};\n\nexport type ParseToMongoTransformFn = (value: unknown, key: string) => unknown;\n\nexport interface ParseToMongoOptions {\n /**\n * Determines whether empty search queries are allowed.\n * If `true`, an empty query will return an unfiltered result.\n * If `false`, an empty query will be rejected.\n *\n * @default false\n */\n allowEmpty?: boolean;\n\n /**\n * A list of allowed keys that can be used in the search query.\n * If provided, any query using keys outside this list will be rejected.\n */\n allowedKeys?: string[];\n\n /**\n * A transformation function or a mapping of transformation functions\n * to modify query values before they are converted into a MongoDB query.\n *\n * - If an array is provided, all functions in the array will be applied.\n * - If a record object is provided, transformations will be applied\n * based on the corresponding field key.\n *\n * @example\n * {\n 'age': MONGO_TRANSFORM.NUMBER\n 'customer._id': [MONGO_TRANSFORM.OBJECT_ID, MONGO_TRANSFORM.NOT_NULLABLE]\n}\n */\n transform?:\n | Readonly<Arrayable<ParseToMongoTransformFn>>\n | Readonly<Record<string, Readonly<Arrayable<ParseToMongoTransformFn>>>>;\n}\n\ninterface ParseToMongoOptionsInternal {\n allowEmpty: boolean;\n allowedKeys?: Set<string>;\n transform: Record<string, ParseToMongoTransformFn[]>;\n}\n\nconst NOOP_TRANSFORM: ParseToMongoTransformFn[] = [];\n\n/**\n * Parses a query string and converts it into a MongoDB-compatible query object.\n *\n * @param {string} input - The query string to be parsed.\n * @returns {Record<string, any>} - The MongoDB query representation.\n *\n * @example\n * const query = parseToMongo('age > 30');\n * console.log(query);\n * // { age: { $gt: 30 } }\n *\n * @example\n * const query = parseToMongo('name = \"Alice\" AND age > 18');\n * console.log(query);\n * // { $and: [{ name: 'Alice' }, { age: { $gt: 18 } }] }\n *\n * @example\n * const query = parseToMongo('_id = \"67d737b73af3ff3e00a3bbf1\"', {\n * transform: {\n * _id: [MONGO_TRANSFORM.OBJECT_ID, MONGO_TRANSFORM.NOT_NULLABLE]\n * }\n * });\n * console.log(query);\n * // { $and: [{ name: 'Alice' }, { age: { $gt: 18 } }] }\n *\n * @group Main\n */\nexport function parseToMongo(\n input: string,\n options: ParseToMongoOptions = {},\n): Record<string, any> {\n const opts = mergeOptions(options);\n\n if (input.trim() === '') {\n assert.ok(opts.allowEmpty, 'Search query cannot be empty.');\n return {};\n }\n\n const result: Record<string, any> = {};\n const exp = new Expression(input).parse();\n\n for (const node of exp.body) {\n Object.assign(result, reduceNode(node, opts));\n }\n\n return result;\n}\n\nexport function reduceNode(\n node: NodeExpression,\n options: ParseToMongoOptionsInternal,\n): Record<string, any> {\n switch (node.type) {\n case NODE.BINARY_EXPRESSION: {\n assert.ok(\n !options.allowedKeys || options.allowedKeys.has(node.left.name),\n `The search key \"${node.left.name}\" is not allowed.`,\n );\n\n const transform =\n options.transform?.[node.left.name] ||\n options.transform?.['*'] ||\n NOOP_TRANSFORM;\n\n return {\n [node.left.name]:\n node.operator === '='\n ? callTransform(transform, node.right.value, node.left.name)\n : {\n [OPERATOR_MAP[node.operator]]: callTransform(\n transform,\n node.right.value,\n node.left.name,\n ),\n },\n };\n }\n\n case NODE.LOGICAL_EXPRESSION: {\n const op = node.operator === 'AND' ? '$and' : '$or';\n const right = reduceNode(node.right, options);\n\n // combine same operator\n if (\n node.right.type === NODE.LOGICAL_EXPRESSION &&\n node.right.operator === node.operator\n ) {\n return {\n [op]: [reduceNode(node.left, options), ...right[op]],\n };\n }\n\n return {\n [op]: [reduceNode(node.left, options), right],\n };\n break;\n }\n\n default: {\n assert.ok(false, `Unexpected ast node: ${(node as Node).type}`);\n }\n }\n}\n\nexport function mergeOptions(\n ...options: ParseToMongoOptions[]\n): ParseToMongoOptionsInternal {\n const optsTransform: Record<string, ParseToMongoTransformFn[]> = {};\n\n const result: ParseToMongoOptionsInternal = {\n transform: optsTransform,\n allowEmpty: false,\n };\n\n for (const { transform, allowedKeys, ...rest } of options) {\n Object.assign(result, rest);\n\n if (allowedKeys?.length) {\n result.allowedKeys = result.allowedKeys || new Set();\n\n for (const key of result.allowedKeys) {\n result.allowedKeys.add(key);\n }\n }\n\n if (Array.isArray(transform) || isFunction(transform)) {\n optsTransform['*'] = optsTransform['*'] || [];\n optsTransform['*'].push(...arrayable(transform));\n } else if (transform) {\n for (const [key, value] of Object.entries(transform)) {\n optsTransform[key] = optsTransform[key] || [];\n optsTransform[key].push(...arrayable(value));\n }\n }\n }\n\n return result;\n}\n\nfunction callTransform(\n fns: ParseToMongoTransformFn[],\n value: unknown,\n key: string,\n): unknown {\n for (const fn of fns) {\n value = fn(value, key);\n }\n\n return value;\n}\n","import { assert, isNumber, isString, withCache } from '@andrew_l/toolkit';\nimport mongoose, { isObjectIdOrHexString } from 'mongoose';\nimport { Expression } from './Expression';\nimport {\n type ParseToMongoOptions,\n type ParseToMongoTransformFn,\n mergeOptions,\n reduceNode,\n} from './parseToMongo';\n\n/**\n * Utility transform functions\n * @group Constants\n */\nexport const MONGO_TRANSFORM = Object.freeze({\n /**\n * Ensures the value is not null.\n * Throws an error if the value is null.\n *\n * @throws {Error} If the value is null.\n */\n NOT_NULLABLE: ((value, key) => {\n assert.ok(value !== null, `The search key \"${key}\" cannot be nullable.`);\n return value;\n }) as ParseToMongoTransformFn,\n\n /**\n * Validates that the value is a number.\n * If the value is `null`, it returns `null` without throwing an error.\n *\n * @throws {Error} If the value is not a valid number.\n */\n NUMBER: ((value, key) => {\n if (value === null) return null;\n assert.number(value, `The search key \"${key}\" is not valid number.`);\n return value;\n }) as ParseToMongoTransformFn,\n\n /**\n * Validates that the value is a string.\n * If the value is `null`, it returns `null` without throwing an error.\n *\n * @throws {Error} If the value is not a valid string.\n */\n STRING: ((value, key) => {\n if (value === null) return null;\n assert.string(value, `The search key \"${key}\" is not valid string.`);\n return value;\n }) as ParseToMongoTransformFn,\n\n /**\n * Validates that the value is a boolean.\n * If the value is `null`, it returns `null` without throwing an error.\n *\n * @throws {Error} If the value is not a valid boolean.\n */\n BOOLEAN: ((value, key) => {\n if (value === null) return null;\n assert.boolean(value, `The search key \"${key}\" is not valid boolean.`);\n return value;\n }) as ParseToMongoTransformFn,\n\n /**\n * Validates and converts the value to a MongoDB ObjectId.\n * If the value is `null`, it returns `null` without throwing an error.\n *\n * @throws {Error} If the value is not a valid ObjectId.\n */\n OBJECT_ID: ((value, key) => {\n if (value === null) return null;\n assert.ok(\n isObjectIdOrHexString,\n `The search key \"${key}\" is not valid object id.`,\n );\n return new mongoose.Types.ObjectId(value as string);\n }) as ParseToMongoTransformFn,\n\n /**\n * Validates and converts the value to a Date.\n * Supports string and number inputs for conversion.\n * If the value is `null`, it returns `null` without throwing an error.\n *\n * @throws {Error} If the value is not a valid date.\n */\n DATE: ((value, key) => {\n if (value === null) return null;\n\n const result = isString(value)\n ? new Date(value)\n : isNumber(value)\n ? new Date(value)\n : undefined;\n\n assert.date(result, `The search key \"${key}\" is not valid date.`);\n\n return result;\n }) as ParseToMongoTransformFn,\n} as const);\n\nconst INSTANCE_TO_TRANSFORM: Record<string, ParseToMongoTransformFn[]> = {\n Number: [MONGO_TRANSFORM.NUMBER],\n Decimal128: [MONGO_TRANSFORM.NUMBER],\n String: [MONGO_TRANSFORM.STRING],\n UUID: [MONGO_TRANSFORM.STRING],\n ObjectId: [MONGO_TRANSFORM.OBJECT_ID],\n Boolean: [MONGO_TRANSFORM.BOOLEAN],\n Date: [MONGO_TRANSFORM.DATE],\n};\n\ntype MongooseSchema = mongoose.Schema;\ntype MongooseModel = mongoose.Model<any>;\n\n/**\n * Parses a query string and converts it into a MongoDB-compatible query object,\n * using a provided Mongoose schema or model for field validation and transformation.\n *\n * @param {MongooseSchema | MongooseModel} reference - The Mongoose schema or model\n * used to infer field types and transformations.\n * @param {string} input - The query string to be parsed.\n * @param {ParseToMongoOptions} [options={}] - Optional configuration for parsing behavior.\n * @returns {Record<string, any>} - The MongoDB query representation.\n *\n * @example\n * // Type transformations are automatically inferred from the schema.\n * const schema = new mongoose.Schema({\n * age: { type: Number },\n * });\n *\n * const query = parseToMongoose(schema, '_id = \"67d737b73af3ff3e00a3bbf1\"');\n * console.log(query);\n * // Output: { _id: new ObjectId(\"67d737b73af3ff3e00a3bbf1\") }\n *\n * @example\n * // Complex queries with logical operators\n * const schema = new mongoose.Schema({\n * age: { type: Number },\n * customer: {\n * name: { type: String },\n * active: { type: Boolean },\n * }\n * });\n *\n * const query = parseToMongoose(schema, 'customer.active = true AND age >= 18');\n * console.log(query);\n * // Output: { $and: [{ 'customer.active': true }, { age: { $gte: 18 } }] }\n *\n * @throws {Error} If the input query contains invalid syntax or references disallowed fields.\n *\n * @group Main\n */\nexport function parseToMongoose(\n reference: MongooseSchema | MongooseModel,\n input: string,\n options: ParseToMongoOptions = {},\n): Record<string, any> {\n const opts = mergeOptions(\n {\n transform: transformFromSchema(\n 'schema' in reference ? reference.schema : reference,\n ),\n },\n options,\n );\n\n const result: Record<string, any> = {};\n const exp = new Expression(input).parse();\n\n for (const node of exp.body) {\n Object.assign(result, reduceNode(node, opts));\n }\n\n return result;\n}\n\nconst transformFromSchema = withCache(\n { objectStrategy: 'ref' },\n (schema: mongoose.Schema): Record<string, ParseToMongoTransformFn[]> => {\n const result: Record<string, ParseToMongoTransformFn[]> = {};\n\n eachPath(schema, (path, type) => {\n result[path] = INSTANCE_TO_TRANSFORM[type.instance];\n });\n\n return result;\n },\n);\n\nfunction eachPath(\n schema: mongoose.Schema,\n fn: (path: string, type: mongoose.SchemaType) => void,\n prefix: string = '',\n) {\n schema.eachPath((path, type) => {\n if (type.schema) {\n eachPath(type.schema, fn, `${path}.`);\n } else {\n fn(`${prefix}${path}`, type);\n }\n });\n}\n"],"names":["assert","isFunction","arrayable","isObjectIdOrHexString","mongoose","isString","isNumber","withCache"],"mappings":"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"}
@@ -0,0 +1,473 @@
1
+ import { Arrayable } from '@andrew_l/toolkit';
2
+ import mongoose from 'mongoose';
3
+
4
+ interface TokenTypeOptions {
5
+ keyword?: string;
6
+ }
7
+ /**
8
+ * @group Utils
9
+ */
10
+ declare class TokenType {
11
+ readonly label: string;
12
+ readonly keyword: string | undefined;
13
+ constructor(label: string, options?: TokenTypeOptions);
14
+ }
15
+
16
+ /**
17
+ * Node types
18
+ * @group Constants
19
+ */
20
+ declare const NODE: Readonly<{
21
+ PROGRAM: "program";
22
+ IDENTIFIER: "identifier";
23
+ LITERAL: "literal";
24
+ LOGICAL_EXPRESSION: "logical-expression";
25
+ BINARY_EXPRESSION: "binary-expression";
26
+ }>;
27
+ /**
28
+ * Keyword tokens.
29
+ * @group Constants
30
+ */
31
+ declare const KEYWORDS: Record<string, TokenType>;
32
+ /**
33
+ * Token types
34
+ * @group Constants
35
+ */
36
+ declare const TOKEN: Readonly<{
37
+ /**
38
+ * Start of File token.
39
+ */
40
+ readonly SOF: TokenType;
41
+ /**
42
+ * End of File token.
43
+ */
44
+ readonly EOF: TokenType;
45
+ /**
46
+ * Number token.
47
+ */
48
+ readonly NUM: TokenType;
49
+ /**
50
+ * String token.
51
+ */
52
+ readonly STRING: TokenType;
53
+ /**
54
+ * Identifier token.
55
+ */
56
+ readonly NAME: TokenType;
57
+ /**
58
+ * Parenthesis token.
59
+ */
60
+ readonly PAREN_L: TokenType;
61
+ /**
62
+ * Parenthesis token.
63
+ */
64
+ readonly PAREN_R: TokenType;
65
+ /**
66
+ * Logical operator token.
67
+ */
68
+ readonly LOGICAL_OR: TokenType;
69
+ /**
70
+ * Logical operator token.
71
+ */
72
+ readonly LOGICAL_AND: TokenType;
73
+ /**
74
+ * Equality operator token.
75
+ */
76
+ readonly EQUALITY: TokenType;
77
+ /**
78
+ * Relational operator token.
79
+ */
80
+ readonly RELATIONAL: TokenType;
81
+ /**
82
+ * Minus operator token.
83
+ */
84
+ readonly MINUS: TokenType;
85
+ /**
86
+ * Null literal token.
87
+ */
88
+ readonly NULL: TokenType;
89
+ /**
90
+ * True literal tokens.
91
+ */
92
+ readonly TRUE: TokenType;
93
+ /**
94
+ * False literal tokens.
95
+ */
96
+ readonly FALSE: TokenType;
97
+ }>;
98
+
99
+ interface TokenOptions {
100
+ type: TokenType;
101
+ value: unknown;
102
+ start: number;
103
+ end: number;
104
+ }
105
+ /**
106
+ * @group Utils
107
+ */
108
+ declare class Token {
109
+ readonly type: TokenType;
110
+ readonly value: unknown;
111
+ readonly start: number;
112
+ readonly end: number;
113
+ constructor(p: TokenOptions);
114
+ }
115
+
116
+ /**
117
+ * @group Utils
118
+ */
119
+ declare class Tokenizer implements Iterable<Token> {
120
+ protected input: string;
121
+ protected pos: number;
122
+ protected length: number;
123
+ protected state: TokenOptions;
124
+ protected prev: TokenOptions;
125
+ constructor(input: string);
126
+ [Symbol.iterator](): {
127
+ next: () => {
128
+ done: boolean;
129
+ value: Token;
130
+ };
131
+ };
132
+ /**
133
+ * Get the next token.
134
+ */
135
+ getToken(): Token;
136
+ protected nextToken(): void;
137
+ protected skipSpace(): void;
138
+ protected finishToken(type: TokenType, value?: unknown): void;
139
+ protected finishOp(type: TokenType, size: number): void;
140
+ protected readToken(code: number): void;
141
+ protected getTokenFromCode(code: number): void;
142
+ protected charCodeAtPos(): number;
143
+ protected readEquality(code: number): void;
144
+ protected readLtGt(): void;
145
+ protected readInt(): number | null;
146
+ protected raise(pos: number, message: string): never;
147
+ protected readString(): void;
148
+ protected readWord(): void;
149
+ protected readEscapedChar(): string;
150
+ protected readNumber(): void;
151
+ }
152
+
153
+ /**
154
+ * @group Types
155
+ */
156
+ interface Node {
157
+ /**
158
+ * Start positions of the node in the source code.
159
+ */
160
+ start: number;
161
+ /**
162
+ * End positions of the node in the source code.
163
+ */
164
+ end: number;
165
+ /**
166
+ * Type of the node.
167
+ */
168
+ type: string;
169
+ }
170
+ /**
171
+ * @group Types
172
+ */
173
+ type NodeMap = {
174
+ [NODE.PROGRAM]: NodeProgram;
175
+ [NODE.LITERAL]: NodeLiteral;
176
+ [NODE.BINARY_EXPRESSION]: NodeBinaryExpression;
177
+ [NODE.LOGICAL_EXPRESSION]: NodeLogicalExpression;
178
+ [NODE.IDENTIFIER]: NodeIdentifier;
179
+ };
180
+ /**
181
+ * The node type.
182
+ * @group Types
183
+ */
184
+ type NodeType = (typeof NODE)[keyof typeof NODE];
185
+ /**
186
+ * The node expression.
187
+ * @group Types
188
+ */
189
+ type NodeExpression = NodeBinaryExpression | NodeLogicalExpression;
190
+ /**
191
+ * Root node of the AST.
192
+ * @group Types
193
+ */
194
+ interface NodeProgram extends Node {
195
+ type: typeof NODE.PROGRAM;
196
+ body: NodeExpression[];
197
+ }
198
+ /**
199
+ * Literal node of the AST.
200
+ * @group Types
201
+ */
202
+ interface NodeLiteral extends Node {
203
+ type: typeof NODE.LITERAL;
204
+ /**
205
+ * Value of the literal.
206
+ */
207
+ value: string | boolean | null | number;
208
+ /**
209
+ * Raw value of the literal.
210
+ */
211
+ raw?: string;
212
+ }
213
+ /**
214
+ * Identifier node of the AST.
215
+ * @group Types
216
+ */
217
+ interface NodeIdentifier extends Node {
218
+ type: typeof NODE.IDENTIFIER;
219
+ /**
220
+ * Name of the identifier.
221
+ */
222
+ name: string;
223
+ }
224
+ /**
225
+ * Binary expression node of the AST.
226
+ * @group Types
227
+ */
228
+ interface NodeBinaryExpression extends Node {
229
+ type: typeof NODE.BINARY_EXPRESSION;
230
+ /**
231
+ * Operator of the binary expression.
232
+ */
233
+ operator: BinaryOperator;
234
+ /**
235
+ * Left operand of the binary expression.
236
+ */
237
+ left: NodeIdentifier;
238
+ /**
239
+ * Right operand of the binary expression.
240
+ */
241
+ right: NodeLiteral;
242
+ }
243
+ /**
244
+ * Binary operator.
245
+ * @group Types
246
+ */
247
+ type BinaryOperator = '=' | '!=' | '<' | '<=' | '>' | '>=';
248
+ /**
249
+ * Logical expression node of the AST.
250
+ * @group Types
251
+ */
252
+ /**
253
+ * @group Types
254
+ */
255
+ interface NodeLogicalExpression extends Node {
256
+ type: typeof NODE.LOGICAL_EXPRESSION;
257
+ /**
258
+ * Operator of the logical expression.
259
+ */
260
+ operator: LogicalOperator;
261
+ /**
262
+ * Left operand of the logical expression.
263
+ */
264
+ left: NodeExpression;
265
+ /**
266
+ * Right operand of the logical expression.
267
+ */
268
+ right: NodeExpression;
269
+ }
270
+ /**
271
+ * Logical operator.
272
+ * @group Types
273
+ */
274
+ type LogicalOperator = 'OR' | 'AND';
275
+
276
+ /**
277
+ * Parse an expression class.
278
+ *
279
+ * @group Utils
280
+ */
281
+ declare class Expression extends Tokenizer {
282
+ constructor(input: string);
283
+ /**
284
+ * Parse input into a program AST.
285
+ */
286
+ parse(): NodeProgram;
287
+ protected finishNode<T extends Node>(node: T): T;
288
+ protected parseTopLevel(node: NodeProgram): NodeProgram;
289
+ protected parseExpression(): NodeExpression;
290
+ protected parseExprOp(left: NodeExpression | NodeIdentifier): NodeBinaryExpression | NodeLogicalExpression;
291
+ protected maybeLiteral(): NodeLiteral | null;
292
+ protected maybeIdentifier(): NodeIdentifier | null;
293
+ protected parseExprAtom(): NodeIdentifier | NodeLiteral;
294
+ protected startNode<T extends NodeType>(type: T): NodeMap[T];
295
+ }
296
+
297
+ /**
298
+ * Parses a query string into a NodeProgram representation.
299
+ *
300
+ * @param {string} value - The query string to be parsed.
301
+ * @returns {NodeProgram} - The parsed representation of the query.
302
+ *
303
+ * @example
304
+ * const program = parseQuery('age > 30');
305
+ * console.log(program);
306
+ * // {
307
+ * // type: 'program',
308
+ * // body: [
309
+ * // {
310
+ * // type: 'binary-expression',
311
+ * // operator: '>',
312
+ * // left: { type: 'identifier', name: 'age' },
313
+ * // right: { type: 'literal', value: 30 }
314
+ * // }
315
+ * // ]
316
+ * // }
317
+ *
318
+ * @group Main
319
+ */
320
+ declare function parseQuery(value: string): NodeProgram;
321
+
322
+ type ParseToMongoTransformFn = (value: unknown, key: string) => unknown;
323
+ interface ParseToMongoOptions {
324
+ /**
325
+ * Determines whether empty search queries are allowed.
326
+ * If `true`, an empty query will return an unfiltered result.
327
+ * If `false`, an empty query will be rejected.
328
+ *
329
+ * @default false
330
+ */
331
+ allowEmpty?: boolean;
332
+ /**
333
+ * A list of allowed keys that can be used in the search query.
334
+ * If provided, any query using keys outside this list will be rejected.
335
+ */
336
+ allowedKeys?: string[];
337
+ /**
338
+ * A transformation function or a mapping of transformation functions
339
+ * to modify query values before they are converted into a MongoDB query.
340
+ *
341
+ * - If an array is provided, all functions in the array will be applied.
342
+ * - If a record object is provided, transformations will be applied
343
+ * based on the corresponding field key.
344
+ *
345
+ * @example
346
+ * {
347
+ 'age': MONGO_TRANSFORM.NUMBER
348
+ 'customer._id': [MONGO_TRANSFORM.OBJECT_ID, MONGO_TRANSFORM.NOT_NULLABLE]
349
+ }
350
+ */
351
+ transform?: Readonly<Arrayable<ParseToMongoTransformFn>> | Readonly<Record<string, Readonly<Arrayable<ParseToMongoTransformFn>>>>;
352
+ }
353
+ /**
354
+ * Parses a query string and converts it into a MongoDB-compatible query object.
355
+ *
356
+ * @param {string} input - The query string to be parsed.
357
+ * @returns {Record<string, any>} - The MongoDB query representation.
358
+ *
359
+ * @example
360
+ * const query = parseToMongo('age > 30');
361
+ * console.log(query);
362
+ * // { age: { $gt: 30 } }
363
+ *
364
+ * @example
365
+ * const query = parseToMongo('name = "Alice" AND age > 18');
366
+ * console.log(query);
367
+ * // { $and: [{ name: 'Alice' }, { age: { $gt: 18 } }] }
368
+ *
369
+ * @example
370
+ * const query = parseToMongo('_id = "67d737b73af3ff3e00a3bbf1"', {
371
+ * transform: {
372
+ * _id: [MONGO_TRANSFORM.OBJECT_ID, MONGO_TRANSFORM.NOT_NULLABLE]
373
+ * }
374
+ * });
375
+ * console.log(query);
376
+ * // { $and: [{ name: 'Alice' }, { age: { $gt: 18 } }] }
377
+ *
378
+ * @group Main
379
+ */
380
+ declare function parseToMongo(input: string, options?: ParseToMongoOptions): Record<string, any>;
381
+
382
+ /**
383
+ * Utility transform functions
384
+ * @group Constants
385
+ */
386
+ declare const MONGO_TRANSFORM: Readonly<{
387
+ /**
388
+ * Ensures the value is not null.
389
+ * Throws an error if the value is null.
390
+ *
391
+ * @throws {Error} If the value is null.
392
+ */
393
+ readonly NOT_NULLABLE: ParseToMongoTransformFn;
394
+ /**
395
+ * Validates that the value is a number.
396
+ * If the value is `null`, it returns `null` without throwing an error.
397
+ *
398
+ * @throws {Error} If the value is not a valid number.
399
+ */
400
+ readonly NUMBER: ParseToMongoTransformFn;
401
+ /**
402
+ * Validates that the value is a string.
403
+ * If the value is `null`, it returns `null` without throwing an error.
404
+ *
405
+ * @throws {Error} If the value is not a valid string.
406
+ */
407
+ readonly STRING: ParseToMongoTransformFn;
408
+ /**
409
+ * Validates that the value is a boolean.
410
+ * If the value is `null`, it returns `null` without throwing an error.
411
+ *
412
+ * @throws {Error} If the value is not a valid boolean.
413
+ */
414
+ readonly BOOLEAN: ParseToMongoTransformFn;
415
+ /**
416
+ * Validates and converts the value to a MongoDB ObjectId.
417
+ * If the value is `null`, it returns `null` without throwing an error.
418
+ *
419
+ * @throws {Error} If the value is not a valid ObjectId.
420
+ */
421
+ readonly OBJECT_ID: ParseToMongoTransformFn;
422
+ /**
423
+ * Validates and converts the value to a Date.
424
+ * Supports string and number inputs for conversion.
425
+ * If the value is `null`, it returns `null` without throwing an error.
426
+ *
427
+ * @throws {Error} If the value is not a valid date.
428
+ */
429
+ readonly DATE: ParseToMongoTransformFn;
430
+ }>;
431
+ type MongooseSchema = mongoose.Schema;
432
+ type MongooseModel = mongoose.Model<any>;
433
+ /**
434
+ * Parses a query string and converts it into a MongoDB-compatible query object,
435
+ * using a provided Mongoose schema or model for field validation and transformation.
436
+ *
437
+ * @param {MongooseSchema | MongooseModel} reference - The Mongoose schema or model
438
+ * used to infer field types and transformations.
439
+ * @param {string} input - The query string to be parsed.
440
+ * @param {ParseToMongoOptions} [options={}] - Optional configuration for parsing behavior.
441
+ * @returns {Record<string, any>} - The MongoDB query representation.
442
+ *
443
+ * @example
444
+ * // Type transformations are automatically inferred from the schema.
445
+ * const schema = new mongoose.Schema({
446
+ * age: { type: Number },
447
+ * });
448
+ *
449
+ * const query = parseToMongoose(schema, '_id = "67d737b73af3ff3e00a3bbf1"');
450
+ * console.log(query);
451
+ * // Output: { _id: new ObjectId("67d737b73af3ff3e00a3bbf1") }
452
+ *
453
+ * @example
454
+ * // Complex queries with logical operators
455
+ * const schema = new mongoose.Schema({
456
+ * age: { type: Number },
457
+ * customer: {
458
+ * name: { type: String },
459
+ * active: { type: Boolean },
460
+ * }
461
+ * });
462
+ *
463
+ * const query = parseToMongoose(schema, 'customer.active = true AND age >= 18');
464
+ * console.log(query);
465
+ * // Output: { $and: [{ 'customer.active': true }, { age: { $gte: 18 } }] }
466
+ *
467
+ * @throws {Error} If the input query contains invalid syntax or references disallowed fields.
468
+ *
469
+ * @group Main
470
+ */
471
+ declare function parseToMongoose(reference: MongooseSchema | MongooseModel, input: string, options?: ParseToMongoOptions): Record<string, any>;
472
+
473
+ export { type BinaryOperator, Expression, KEYWORDS, type LogicalOperator, MONGO_TRANSFORM, NODE, type Node, type NodeBinaryExpression, type NodeExpression, type NodeIdentifier, type NodeLiteral, type NodeLogicalExpression, type NodeMap, type NodeProgram, type NodeType, type ParseToMongoOptions, type ParseToMongoTransformFn, TOKEN, Tokenizer, parseQuery, parseToMongo, parseToMongoose };