@andrew_l/search-query-language 0.3.22 → 0.4.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","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 isNumber,\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 * Max of query ops combination.\n * @default Infinity\n */\n maxOps?: number;\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 maxOps: number;\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 ops = new OpsResource(opts.maxOps);\n const exp = new Expression(input).parse();\n\n for (const node of exp.body) {\n Object.assign(result, reduceNode(node, opts, ops));\n }\n\n return result;\n}\n\nexport function reduceNode(\n node: NodeExpression,\n options: ParseToMongoOptionsInternal,\n opsResource: OpsResource,\n): Record<string, any> {\n switch (node.type) {\n case NODE.BINARY_EXPRESSION: {\n opsResource.assert();\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, opsResource);\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, opsResource), ...right[op]],\n };\n }\n\n return {\n [op]: [reduceNode(node.left, options, opsResource), right],\n };\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 maxOps: Infinity,\n };\n\n for (const { transform, allowedKeys, ...rest } of options) {\n Object.assign(result, rest);\n\n if (allowedKeys?.length) {\n result.allowedKeys = new Set(allowedKeys);\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\nexport class OpsResource {\n uses: number;\n\n constructor(private max: number) {\n assert.ok(\n max === Infinity || (isNumber(max) && max > 0),\n 'maxOps must be a number greater than zero.',\n );\n\n this.uses = 0;\n }\n\n assert() {\n assert.ok(\n ++this.uses <= this.max,\n `Maximum search operations reached: ${this.max}`,\n );\n }\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 OpsResource,\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 null.`);\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 extractFromSchema('schema' in reference ? reference.schema : reference),\n options,\n );\n\n const result: Record<string, any> = {};\n const ops = new OpsResource(opts.maxOps);\n const exp = new Expression(input).parse();\n\n for (const node of exp.body) {\n Object.assign(result, reduceNode(node, opts, ops));\n }\n\n return result;\n}\n\nconst extractFromSchema = withCache(\n { objectStrategy: 'ref' },\n (schema: mongoose.Schema): ParseToMongoOptions => {\n const allowedKeys: string[] = [];\n const transform: Record<string, ParseToMongoTransformFn[]> = {};\n\n eachPath(schema, (path, type) => {\n transform[path] = INSTANCE_TO_TRANSFORM[type.instance];\n allowedKeys.push(path);\n });\n\n return { allowedKeys, transform };\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":[],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"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 isNumber,\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 * Max of query ops combination.\n * @default Infinity\n */\n maxOps?: number;\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 maxOps: number;\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 ops = new OpsResource(opts.maxOps);\n const exp = new Expression(input).parse();\n\n for (const node of exp.body) {\n Object.assign(result, reduceNode(node, opts, ops));\n }\n\n return result;\n}\n\nexport function reduceNode(\n node: NodeExpression,\n options: ParseToMongoOptionsInternal,\n opsResource: OpsResource,\n): Record<string, any> {\n switch (node.type) {\n case NODE.BINARY_EXPRESSION: {\n opsResource.assert();\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, opsResource);\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, opsResource), ...right[op]],\n };\n }\n\n return {\n [op]: [reduceNode(node.left, options, opsResource), right],\n };\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 maxOps: Infinity,\n };\n\n for (const { transform, allowedKeys, ...rest } of options) {\n Object.assign(result, rest);\n\n if (allowedKeys?.length) {\n result.allowedKeys = new Set(allowedKeys);\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\nexport class OpsResource {\n uses: number;\n\n constructor(private max: number) {\n assert.ok(\n max === Infinity || (isNumber(max) && max > 0),\n 'maxOps must be a number greater than zero.',\n );\n\n this.uses = 0;\n }\n\n assert() {\n assert.ok(\n ++this.uses <= this.max,\n `Maximum search operations reached: ${this.max}`,\n );\n }\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 OpsResource,\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 null.`);\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 extractFromSchema('schema' in reference ? reference.schema : reference),\n options,\n );\n\n const result: Record<string, any> = {};\n const ops = new OpsResource(opts.maxOps);\n const exp = new Expression(input).parse();\n\n for (const node of exp.body) {\n Object.assign(result, reduceNode(node, opts, ops));\n }\n\n return result;\n}\n\nconst extractFromSchema = withCache(\n { objectStrategy: 'ref' },\n (schema: mongoose.Schema): ParseToMongoOptions => {\n const allowedKeys: string[] = [];\n const transform: Record<string, ParseToMongoTransformFn[]> = {};\n\n eachPath(schema, (path, type) => {\n transform[path] = INSTANCE_TO_TRANSFORM[type.instance];\n allowedKeys.push(path);\n });\n\n return { allowedKeys, transform };\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"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andrew_l/search-query-language",
3
- "version": "0.3.22",
3
+ "version": "0.4.1",
4
4
  "description": "Converts human-readable query strings into structured representations.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -20,29 +20,30 @@
20
20
  "exports": {
21
21
  ".": {
22
22
  "import": "./dist/index.mjs",
23
- "require": "./dist/index.cjs"
23
+ "require": "./dist/index.mjs",
24
+ "types": "./dist/index.d.mts"
24
25
  }
25
26
  },
26
- "main": "./dist/index.cjs",
27
- "types": "./dist/index.d.ts",
27
+ "main": "./dist/index.mjs",
28
+ "types": "./dist/index.d.mts",
28
29
  "files": [
29
30
  "dist"
30
31
  ],
31
32
  "devDependencies": {
32
33
  "@types/node": "22.10.5",
33
- "typescript": "~5.8.3",
34
- "unbuild": "3.5.0",
34
+ "obuild": "^0.4.37",
35
+ "typescript": "6.0.3",
35
36
  "vitest": "^3.2.4"
36
37
  },
37
38
  "peerDependencies": {
38
39
  "mongoose": "^7 || ^8"
39
40
  },
40
41
  "dependencies": {
41
- "@andrew_l/toolkit": "0.3.22"
42
+ "@andrew_l/toolkit": "0.4.1"
42
43
  },
43
44
  "scripts": {
44
45
  "check-types": "tsc --noEmit",
45
- "build": "unbuild",
46
+ "build": "obuild",
46
47
  "test": "vitest run --typecheck",
47
48
  "test:watch": "vitest watch --typecheck"
48
49
  }