@osqd/jql 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -1
- package/conformance/cases.json +2 -0
- package/dist/chunk-2ZMIVDES.cjs +1661 -0
- package/dist/chunk-2ZMIVDES.cjs.map +1 -0
- package/dist/chunk-6PWYYYWU.js +1637 -0
- package/dist/chunk-6PWYYYWU.js.map +1 -0
- package/dist/chunk-74QKHM6Y.cjs +145 -0
- package/dist/chunk-74QKHM6Y.cjs.map +1 -0
- package/dist/chunk-ATRXHPBJ.js +112 -0
- package/dist/chunk-ATRXHPBJ.js.map +1 -0
- package/dist/chunk-EJFHVGBC.cjs +63 -0
- package/dist/chunk-EJFHVGBC.cjs.map +1 -0
- package/dist/chunk-ITPY6VTV.cjs +115 -0
- package/dist/chunk-ITPY6VTV.cjs.map +1 -0
- package/dist/chunk-JK6OYDLX.js +712 -0
- package/dist/chunk-JK6OYDLX.js.map +1 -0
- package/dist/chunk-N7DS4QNW.js +60 -0
- package/dist/chunk-N7DS4QNW.js.map +1 -0
- package/dist/chunk-PNBQ2HIJ.js +133 -0
- package/dist/chunk-PNBQ2HIJ.js.map +1 -0
- package/dist/chunk-VMFEQXBB.js +578 -0
- package/dist/chunk-VMFEQXBB.js.map +1 -0
- package/dist/cjs/text/index.d.ts +1 -1
- package/dist/cjs/text/parse.d.ts +2 -1
- package/dist/cjs/text/quote.d.ts +17 -0
- package/dist/cjs/text/suggest.d.ts +27 -5
- package/dist/cli.js +13 -2395
- package/dist/cli.js.map +1 -1
- package/dist/global.cjs +26 -1849
- package/dist/global.cjs.map +1 -1
- package/dist/global.js +8 -1831
- package/dist/global.js.map +1 -1
- package/dist/index.cjs +143 -1996
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +5 -2493
- package/dist/index.js.map +1 -1
- package/dist/mongo.cjs +20 -119
- package/dist/mongo.cjs.map +1 -1
- package/dist/mongo.js +2 -101
- package/dist/mongo.js.map +1 -1
- package/dist/text/index.d.ts +1 -1
- package/dist/text/parse.d.ts +2 -1
- package/dist/text/quote.d.ts +17 -0
- package/dist/text/suggest.d.ts +27 -5
- package/dist/text.cjs +146 -101
- package/dist/text.cjs.map +1 -1
- package/dist/text.js +3 -665
- package/dist/text.js.map +1 -1
- package/docs/course/11-the-search-box.md +49 -2
- package/docs/course/16-extending.md +1 -1
- package/docs/reference/api.md +14 -1
- package/docs/reference/specification.md +9 -2
- package/docs/reference/text-syntax.md +41 -6
- package/package.json +2 -2
package/dist/text.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/duration.ts","../src/errors.ts","../src/internal/values.ts","../src/vocabulary.ts","../src/text/parse.ts","../src/text/suggest.ts","../src/text/write.ts"],"names":["quote","parts","partial","name","PATH_NAME","comparison"],"mappings":"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","file":"text.cjs","sourcesContent":["/**\n * Durations, for the relative dates a saved filter is written with.\n *\n * `\"1h\"`, `\"30m\"`, `\"1h30m\"`, `\"7d\"`. Written as one or more counts with a unit, largest\n * first by convention but in any order, because a filter is typed by a person and\n * `\"30m1h\"` means what it says.\n *\n * Months and years are deliberately absent: neither has a fixed length, so `\"1mo\"` would\n * mean something slightly different in February, and a filter whose window changes size\n * with the calendar is one nobody can reason about. Use days or weeks.\n */\n\nconst PART = /(\\d+)(ms|s|m|h|d|w)/g;\nconst SHAPE = /^(?:\\d+(?:ms|s|m|h|d|w))+$/;\n\nconst UNITS: Readonly<Record<string, number>> = {\n ms: 1,\n s: 1_000,\n m: 60_000,\n h: 3_600_000,\n d: 86_400_000,\n w: 604_800_000,\n};\n\n/** The unit names, for an error that says what is accepted. */\nexport const DURATION_UNITS = Object.keys(UNITS);\n\n/** A duration in milliseconds, or `undefined` when the text is not one. */\nexport function parseDuration(text: string): number | undefined {\n if (!SHAPE.test(text)) return undefined;\n let total = 0;\n PART.lastIndex = 0;\n for (;;) {\n const part = PART.exec(text);\n if (part === null) break;\n const count = Number(part[1]);\n // A count that does not survive the round trip through a number is not a duration\n // anybody meant; it is a digit string long enough to have lost its tail.\n if (!Number.isSafeInteger(count)) return undefined;\n total += count * (UNITS[part[2] as string] as number);\n }\n return Number.isSafeInteger(total) ? total : undefined;\n}\n","/**\n * The one way a query is refused.\n *\n * A query that looks right and matches nothing is the failure this library exists to\n * prevent: a misspelt operator, a field value that is `undefined` because a variable was,\n * a regex that does not compile. Each of those used to be a filter that silently let\n * everything through or nothing through, and nobody could tell which from the result. So\n * `compile` refuses, with a sentence saying what was wrong and where in the query it was.\n */\nexport class JqlError extends Error {\n /**\n * Where in the query the problem is, written the way you would reach it in code:\n * `$or[1].age.$gt`. Empty for the query as a whole.\n */\n readonly at: string;\n\n constructor(message: string, at = \"\") {\n super(at === \"\" ? message : `at ${show(at)}: ${message}`);\n this.name = \"JqlError\";\n this.at = at;\n }\n}\n\n/**\n * The location, short enough to read.\n *\n * A location is built from the query's own field names, and a field name is a string from\n * outside — a long one makes the sentence it prefixes unreadable, and turns a log line into\n * a paragraph. `at` itself keeps the whole path, because that is the part a program reads.\n */\nfunction show(at: string): string {\n return at.length > 80 ? `${at.slice(0, 80)}…` : at;\n}\n","import { parseDuration } from \"./duration.js\";\nimport type { DateLiteral, FieldReference, TypeName } from \"../types.js\";\n\n/** An object literal or a JSON-parsed object: what a query document is made of. */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\n/** `{ $date: … }` and nothing else. */\nexport function isDateLiteral(value: unknown): value is DateLiteral {\n if (!isPlainObject(value) || !(\"$date\" in value)) return false;\n for (const key in value) if (key !== \"$date\") return false;\n return true;\n}\n\n/** `{ $field: \"path\" }` and nothing else: a comparison with another field of the same item. */\nexport function isFieldReference(value: unknown): value is FieldReference {\n if (!isPlainObject(value) || typeof value.$field !== \"string\") return false;\n for (const key in value) if (key !== \"$field\") return false;\n return true;\n}\n\n/**\n * The instant a `$date` literal stands for, in epoch milliseconds, or `NaN`.\n *\n * `now` is passed in rather than read here, because a query holding `{ \"$ago\": \"1h\" }` has\n * to resolve against one instant for the whole run: reading the clock per comparison would\n * let the window move while a scan is in progress, so two items a second apart could be\n * judged against different hours. It is also what makes a relative filter testable without\n * waiting.\n */\nexport function resolveDate(value: unknown, now: number): number {\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\") return value === \"now\" ? now : instant(value);\n if (isPlainObject(value)) {\n const keys = Object.keys(value);\n if (keys.length !== 1) return Number.NaN;\n const amount = keys[0] === \"$ago\" || keys[0] === \"$ahead\" ? value[keys[0] as string] : undefined;\n if (typeof amount !== \"string\") return Number.NaN;\n const span = parseDuration(amount);\n if (span === undefined) return Number.NaN;\n return keys[0] === \"$ago\" ? now - span : now + span;\n }\n return Number.NaN;\n}\n\n/**\n * A document value read as a date, in epoch milliseconds, or `NaN`.\n *\n * Only called where the query supplied a `$date`, so a string is only ever parsed as a\n * date because somebody asked for that. `NaN` compares false with everything, which is\n * what a value that is not a date should do.\n */\n/**\n * The forms of a date a document may hold, per the specification: a `Date`, epoch\n * milliseconds, or an **ISO 8601** string.\n *\n * `Date.parse` accepts a great deal more than that — `\"12/31/2020\"`, `\"Mar 5 2021\"`, and\n * `\"5\"`, which it reads as a year — and what it accepts beyond ISO 8601 is left to the\n * implementation by the language it comes from. A document that matched here and nowhere\n * else would make the same query mean different things in different engines, which is the\n * one thing this language promises it does not do. The space instead of `T` is allowed\n * because RFC 3339 allows it and people write it.\n */\nconst ISO_8601 = /^\\d{4}-\\d{2}-\\d{2}(?:[T ]\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{1,9})?)?(?:Z|[+-]\\d{2}:?\\d{2})?)?$/;\n\n/** A timestamp with a time and no offset, which is the one shape whose meaning is not fixed. */\nconst NO_OFFSET = /^(\\d{4}-\\d{2}-\\d{2})[T ](\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{1,9})?)?)$/;\n\n/**\n * An instant from a string, read the same way on every machine.\n *\n * JavaScript reads a date-only string as midnight **UTC** and a timestamp with no offset as\n * **local time** — so `\"2026-01-01T12:00:00\"` was a different instant in Tokyo and in London,\n * and a query and a document that both held one answered differently depending on where the\n * process happened to be running. That is the failure the language already rules out for\n * `\"12/31/2020\"`: the same query meaning two things. A missing offset is UTC here, which is\n * the rule the date-only form already follows.\n */\nexport function instant(text: string): number {\n const bare = NO_OFFSET.exec(text);\n return bare === null ? Date.parse(text) : Date.parse(`${bare[1] as string}T${bare[2] as string}Z`);\n}\n\nexport function toTime(value: unknown): number {\n if (typeof value === \"number\") return value;\n if (value instanceof Date) return value.getTime();\n if (typeof value === \"string\") return ISO_8601.test(value) ? instant(value) : Number.NaN;\n return Number.NaN;\n}\n\n/** The type names `$type` knows, in one list, so the error for a wrong one can offer the right one. */\nexport const TYPE_NAMES: readonly TypeName[] = [\"string\", \"number\", \"integer\", \"bigint\", \"boolean\", \"null\", \"array\", \"object\", \"date\"];\n\n/** Whether a document value is of the named type. A missing value is of no type. */\nexport function isOfType(value: unknown, type: TypeName): boolean {\n switch (type) {\n case \"string\":\n return typeof value === \"string\";\n case \"number\":\n // A big integer is a number for ordering, so it is one here too: `$gt` and `$type`\n // disagreeing about the same value is a distinction nobody could explain.\n return typeof value === \"number\" || typeof value === \"bigint\";\n case \"integer\":\n return Number.isInteger(value) || typeof value === \"bigint\";\n case \"bigint\":\n return typeof value === \"bigint\";\n case \"boolean\":\n return typeof value === \"boolean\";\n case \"null\":\n return value === null;\n case \"array\":\n return Array.isArray(value);\n case \"date\":\n return value instanceof Date;\n case \"object\":\n return value !== null && typeof value === \"object\" && !Array.isArray(value) && !(value instanceof Date);\n }\n}\n\n/**\n * A readable name for a value in an error sentence.\n *\n * Specific about what it was given, because \"a query is an object, not an object\" — which\n * is what a `Map`, a `Set` and a class instance all used to produce — tells the reader\n * nothing at all about the thing they passed.\n */\nexport function describe(value: unknown): string {\n if (value === null) return \"null\";\n // Named rather than written out: `String(fn)` is the function's entire source, and a\n // closure of any size turned the sentence refusing it into a listing.\n if (typeof value === \"function\") return \"a function\";\n if (Array.isArray(value)) return \"an array\";\n if (value instanceof RegExp) return \"a RegExp object\";\n if (value instanceof Date) return \"a Date object\";\n if (value instanceof Map) return \"a Map\";\n if (value instanceof Set) return \"a Set\";\n if (typeof value === \"object\") {\n if (isPlainObject(value)) return \"an object\";\n const name = nameOf(value);\n return name === undefined ? \"an object\" : `an instance of ${name}`;\n }\n if (typeof value === \"string\") return `the string ${JSON.stringify(value.length > 40 ? `${value.slice(0, 40)}…` : value)}`;\n return `${typeof value} ${String(value)}`;\n}\n\n/** The class an object came from, when it can be read without running anything of the caller's. */\nfunction nameOf(value: object): string | undefined {\n const prototype = Object.getPrototypeOf(value) as { constructor?: { name?: unknown } } | null;\n // Read from the prototype rather than through the object, so a `constructor` field of\n // the caller's own — which a document or a query read from JSON can have — is not what\n // names it.\n const name = prototype?.constructor?.name;\n return typeof name === \"string\" && name !== \"\" && name !== \"Object\" ? name : undefined;\n}\n","import { JqlError } from \"./errors.js\";\nimport { describe } from \"./internal/values.js\";\nimport type { PathValue } from \"./types.js\";\n\n/**\n * The names a query may use for one kind of document.\n *\n * Without one, a field name is a path and nothing more. With one, a collection gets the\n * names people actually type — `ip` for `actor`, `ua` for `request.headers.user-agent` —\n * and fields that are computed rather than stored, like BotHandler's `outcome`, which is\n * derived from the action and never kept anywhere.\n *\n * The same vocabulary serves the JSON engine and the text front end. That is deliberate:\n * two places that each kept their own list of field names would be two dialects within a\n * week, and a filter typed into a search box has to mean exactly what the JSON it becomes\n * means.\n */\n\n/**\n * How the text front end reads a value typed after `field:`. The JSON engine ignores it:\n * a JSON query says what it means with its operator.\n *\n * - `text` — contains the value, ignoring case. The default, and right for prose.\n * - `word` — contains it as a whole component (`1.2.3.4` does not find `1.2.3.45`). For identifiers.\n * - `exact` — equals it, ignoring case. For closed sets like a verdict or a method.\n * - `number` — compares: `>70`, `<=5`, `10..20`, `42`.\n * - `date` — compares instants the same way: `>2026-01-01`.\n * - `boolean` — `true`/`false`, `yes`/`no`, `1`/`0`.\n */\nexport type FieldKind = \"text\" | \"word\" | \"exact\" | \"number\" | \"date\" | \"boolean\";\n\nexport interface FieldDefinition<T = unknown> {\n /** Where the value lives. Default: the field's own name. */\n readonly path?: string | undefined;\n /** Computes the value instead. Called once per document the field is tested against; it must not throw. */\n readonly get?: ((document: T) => unknown) | undefined;\n /** Other names that mean this field. */\n readonly aliases?: readonly string[] | undefined;\n /** Default `\"text\"`. */\n readonly kind?: FieldKind | undefined;\n /** The values worth offering as completions, when the set is closed. Leave out for a field that takes anything. */\n readonly values?: readonly string[] | undefined;\n}\n\nexport interface VocabularyDefinition<T = unknown> {\n readonly fields: Readonly<Record<string, FieldDefinition<T>>>;\n /** The fields a bare search word looks in. Default: the whole document. */\n readonly text?: readonly string[] | undefined;\n /**\n * Whether a name outside the vocabulary is refused. Default `false`, so any path still\n * works alongside the named fields. Turn it on where the vocabulary is the whole\n * contract — a public API whose documents may grow fields nobody promised to keep.\n */\n readonly strict?: boolean | undefined;\n}\n\n/** One field, with every name that reaches it already resolved. */\nexport interface VocabularyField<T = unknown> {\n readonly name: string;\n readonly kind: FieldKind;\n readonly path: string;\n readonly get: ((document: T) => unknown) | undefined;\n readonly aliases: readonly string[];\n readonly values: readonly string[] | undefined;\n}\n\n/**\n * A vocabulary ready to use.\n *\n * `Extra` is the type of the fields it names, so a typed query can use them: build one\n * with `defineVocabulary<Doc>()({ … })` and the computed names type-check.\n */\nexport interface Vocabulary<T = unknown, Extra extends object = {}> {\n /** Every name, aliases included, lower-cased, to the field it means. */\n readonly lookup: ReadonlyMap<string, VocabularyField<T>>;\n /** The canonical fields, in the order they were defined. */\n readonly fields: readonly VocabularyField<T>[];\n /** Every name a query may use, aliases included, sorted. For completions. */\n readonly names: readonly string[];\n readonly text: readonly string[] | undefined;\n readonly strict: boolean;\n /** Carries the computed field types. Never present at run time. */\n readonly __extra?: Extra | undefined;\n}\n\ntype ExtraOf<T, F> = {\n [K in keyof F]: F[K] extends { get: (document: T) => infer R } ? R : F[K] extends { path: infer P extends string } ? PathValue<T, P> : K extends string ? PathValue<T, K> : unknown;\n};\n\n/** Names a query may never use for a field: they begin like an operator, or contain a path separator. */\nconst BAD_NAME = /^\\$|\\./;\n\n/**\n * Builds a vocabulary, refusing one that would quietly misbehave.\n *\n * Two names that collide, a text field that is not a field, a field with both a path and a\n * getter: each is a vocabulary that looks defined and means something other than what it\n * says, so each is an error here rather than a surprise at query time.\n *\n * Curried so the document type can be given while the field names are inferred:\n * `defineVocabulary<Request>()({ fields: { … } })`.\n */\nexport function defineVocabulary<T = unknown>(): <const D extends VocabularyDefinition<T>>(definition: D) => Vocabulary<T, ExtraOf<T, D[\"fields\"]>> {\n return (definition) => build(definition) as Vocabulary<T, ExtraOf<T, (typeof definition)[\"fields\"]>>;\n}\n\n/**\n * Refuses anything that is not a vocabulary, where one was expected.\n *\n * Two mistakes land here, and both used to arrive as `Cannot read properties of undefined\n * (reading 'get')` from somewhere inside the engine. `defineVocabulary` is curried, so\n * `defineVocabulary({ fields: … })` — the empty parentheses forgotten — returns a *function*;\n * and a definition passed straight through is an object with no `lookup` on it. Neither is\n * caught by the types from JavaScript, and a `TypeError` is not a `JqlError`, so `validate`\n * re-threw it: the one call whose job is to answer 400 rather than 500 answered 500.\n */\nexport function checkVocabulary<T>(value: T, at = \"vocabulary\"): T {\n if (value === undefined || (value !== null && typeof value === \"object\" && (value as { lookup?: unknown }).lookup instanceof Map)) return value;\n throw new JqlError(\n `is not a vocabulary, but ${describe(value)}: build one with defineVocabulary()({ fields: … }) — the empty parentheses first — and pass what that returns`,\n at,\n );\n}\n\nfunction build<T>(definition: VocabularyDefinition<T>): Vocabulary<T> {\n const lookup = new Map<string, VocabularyField<T>>();\n const fields: VocabularyField<T>[] = [];\n const claim = (name: string, field: VocabularyField<T>): void => {\n const key = name.toLowerCase();\n if (name === \"\" || BAD_NAME.test(name)) throw new JqlError(`\"${name}\" cannot name a field: a field name is not empty, does not start with \"$\" and has no \".\"`, \"vocabulary\");\n const holder = lookup.get(key);\n if (holder !== undefined) {\n throw new JqlError(`\"${name}\" names both \"${holder.name}\" and \"${field.name}\", so a query using it could mean either`, \"vocabulary\");\n }\n lookup.set(key, field);\n };\n\n for (const [name, spec] of Object.entries(definition.fields)) {\n if (spec.path !== undefined && spec.get !== undefined) {\n throw new JqlError(`\"${name}\" has both a path and a getter; one of them would be ignored, so say which`, `vocabulary.${name}`);\n }\n if (spec.path === \"\") throw new JqlError(`\"${name}\" has an empty path, which reaches nothing`, `vocabulary.${name}`);\n const field: VocabularyField<T> = {\n name,\n kind: spec.kind ?? \"text\",\n path: spec.path ?? name,\n get: spec.get,\n aliases: spec.aliases ?? [],\n values: spec.values,\n };\n fields.push(field);\n claim(name, field);\n for (const alias of field.aliases) claim(alias, field);\n }\n\n if (definition.text !== undefined) {\n for (const name of definition.text) {\n if (!lookup.has(name.toLowerCase())) throw new JqlError(`the text field \"${name}\" is not a field of this vocabulary, so a bare word would never search it`, \"vocabulary.text\");\n }\n }\n\n return {\n lookup,\n fields,\n names: [...lookup.keys()].sort(),\n text: definition.text,\n strict: definition.strict ?? false,\n };\n}\n","import { parseDuration } from \"../internal/duration.js\";\nimport type { LooseQuery, UntypedQuery } from \"../types.js\";\nimport { checkVocabulary, type FieldKind, type Vocabulary, type VocabularyField } from \"../vocabulary.js\";\n\n/**\n * The search-box syntax, compiled into a JQL document.\n *\n * Ported from BotHandler's feed filter, where it was its own language with its own\n * matcher. Here it has no matcher at all: it produces the JSON query that means the same\n * thing, and the engine runs that. So a filter typed into a box and the JSON a service\n * receives cannot drift apart — there is only one set of semantics, and the text is a way\n * of writing it.\n *\n * ```text\n * actor:203.0.113.4 -path:/health that address, except its health checks\n * verdict:human $or verdict:unknown either verdict\n * $not path:/health the same as -path:/health, spelled out\n * action:$in(block, drop) one of a set\n * action:$notin(allow, tag) none of a set\n * score:>70 score:>=70 score:10..20 numeric comparisons and a range\n * at:>2026-09-01 a date comparison\n * at:>-1h the last hour, and it stays the last hour\n * has:rule -has:rule the field is set, or is not\n * (verdict:human $or score:<20) $and $not path:/health\n * \"GET /api/v2/orders\" a phrase, spaces and all\n * ```\n *\n * **Adjacent terms mean AND**, which is what narrowing means. `$or` binds more loosely than\n * `$and`, and `$not` more tightly than either — the conventional precedence. Operators\n * carry a `$` because a bare `or` is a word that appears in User-Agents and paths, and a\n * language where an ordinary search word silently becomes an operator is a language that\n * lies about what it matched.\n *\n * **Nothing here throws for anything anybody types.** It backs live search boxes, so\n * half-typed input is the normal state rather than an error: an unclosed bracket, a dangling\n * `$or`, a `$in(` with nothing after it all parse to the best reading available. A\n * *vocabulary* that is not one is the exception — that is a mistake in the calling code\n * rather than in the box, and it is refused by name instead of failing later, deeper, as a\n * `TypeError` nobody can place. That is the opposite of the JSON\n * engine's rule, and on purpose: JSON is written by a program that can be told it is wrong,\n * a search box by a person who has not finished typing.\n */\n\nexport interface TextOptions {\n /** The field names the text may use, and how each one reads a value. */\n readonly vocabulary?: Vocabulary<never, object> | undefined;\n /**\n * What a name before a colon may be.\n *\n * - `\"vocabulary\"` — only a vocabulary field; anything else is searched for as text,\n * because a path or a User-Agent can contain a colon. The default when a vocabulary is given.\n * - `\"any\"` — any name that looks like a path (`address.city:London`), read as text.\n * The default without a vocabulary, since there is nothing else to go on. A URL then\n * has to be quoted: `\"http://example.com\"`.\n */\n readonly fields?: \"vocabulary\" | \"any\" | undefined;\n}\n\n/**\n * The longest input this will read.\n *\n * Parsing is linear, so length is not a cliff the way nesting is, but this runs on every\n * keystroke and on whatever arrives in a URL. Eight kilobytes is past any query a person\n * writes. Longer input is cut, not refused, because refusing would be the one way this\n * function could fail.\n */\nexport const MAX_TEXT_CHARS = 8192;\n\n/**\n * How deep brackets may nest.\n *\n * Past anything anyone types, and deliberately no deeper than the tightest limit the engine\n * is asked to compile under (`UNTRUSTED_LIMITS` allows sixteen levels): a box that produced\n * a query the engine would refuse would be a box that lies about what it accepts.\n */\nexport const MAX_TEXT_DEPTH = 16;\n\n/** The name that asks whether a field is set, rather than naming one. */\nexport const EXISTS_TERM = \"has\";\n\n/** The operator words the text syntax understands. */\nexport const TEXT_OPERATORS: readonly string[] = [\"$and\", \"$or\", \"$not\", \"$in\", \"$notin\"];\n\ninterface Term {\n readonly name: string | undefined;\n readonly value: string;\n readonly negated: boolean;\n /** For `$in` and `$notin`. */\n readonly values?: readonly string[] | undefined;\n}\n\ntype Tree = { kind: \"all\" } | { kind: \"term\"; term: Term } | { kind: \"not\"; of: Tree } | { kind: \"and\"; parts: Tree[] } | { kind: \"or\"; parts: Tree[] };\n\ntype Token = { kind: \"word\"; text: string } | { kind: \"open\" } | { kind: \"close\" } | { kind: \"op\"; op: \"and\" | \"or\" | \"not\" };\n\n/**\n * Parses search-box text into a JQL query. Never throws; an empty input is `{}`, which\n * matches everything. The result is an `UntypedQuery`, so it can be handed to a typed\n * collection: what the text names is only known once somebody has typed it.\n */\nexport function parseText(input: string, options: TextOptions = {}): UntypedQuery {\n checkVocabulary(options.vocabulary);\n const trimmed = plainQuotes(String(input).trim());\n const tokens = tokenize(trimmed.length > MAX_TEXT_CHARS ? trimmed.slice(0, MAX_TEXT_CHARS) : trimmed);\n const mode = options.fields ?? (options.vocabulary === undefined ? \"any\" : \"vocabulary\");\n // A cast rather than a call to `untyped()`: importing the engine for an identity function\n // would put all of it in the text entry, which exists so that it does not.\n return toQuery(parseTokens(tokens), options.vocabulary, mode) as unknown as UntypedQuery;\n}\n\n/* ------------------------------------------------------------------------------------ */\n/* Quotes and tokens */\n/* ------------------------------------------------------------------------------------ */\n\n/**\n * Typographic quotes, and the plain ones they stand for.\n *\n * Nobody types a curly quote into a filter meaning a curly quote. They arrive by paste,\n * from anything with smart punctuation turned on. In BotHandler they used to be taken\n * literally, so `actor:$notin(“203.0.113.4”)` excluded nothing, with no sign anything was\n * wrong.\n */\nconst DOUBLE_QUOTES = \"\\u201c\\u201d\\u201e\\u201f\\u2033\\u2036\";\nconst TYPOGRAPHIC_QUOTES = /[\\u201c\\u201d\\u201e\\u201f\\u2033\\u2036\\u2018\\u2019\\u201a\\u201b\\u2032\\u2035]/g;\n\nfunction plainQuotes(input: string): string {\n return input.replace(TYPOGRAPHIC_QUOTES, (quote) => (DOUBLE_QUOTES.includes(quote) ? '\"' : \"'\"));\n}\n\nconst SET_OPENER = /\\$(in|notin)$/i;\nconst SPACE = /\\s/;\n\n/**\n * Splits the input into words, operators and brackets.\n *\n * Quoted runs stay whole, spaces and brackets included. A `field:$in(...)` list is one\n * word, because its brackets belong to the term rather than grouping.\n */\nfunction tokenize(input: string): Token[] {\n const tokens: Token[] = [];\n let current = \"\";\n let quote: '\"' | \"'\" | undefined;\n // The same, inside a `$in(...)` set, where quotes are kept for `splitSet` to read and a\n // bracket inside one must not end the set.\n let setQuote: '\"' | \"'\" | undefined;\n let depth = 0;\n\n const flush = (): void => {\n if (current === \"\") return;\n const lower = current.toLowerCase();\n if (lower === \"$and\" || lower === \"$or\" || lower === \"$not\") tokens.push({ kind: \"op\", op: lower.slice(1) as \"and\" | \"or\" | \"not\" });\n else tokens.push({ kind: \"word\", text: current });\n current = \"\";\n };\n\n for (let i = 0; i < input.length; i++) {\n const character = input[i] as string;\n if (depth > 0) {\n current += character;\n if (setQuote !== undefined) {\n if (character === setQuote) setQuote = undefined;\n } else if (character === '\"' || character === \"'\") setQuote = character;\n else if (character === \"(\") depth++;\n else if (character === \")\") {\n depth--;\n if (depth === 0) flush();\n }\n continue;\n }\n if (quote !== undefined) {\n if (character === quote) quote = undefined;\n else current += character;\n continue;\n }\n if (character === '\"') {\n quote = '\"';\n continue;\n }\n // A single quote is a quote only where a value begins. Anywhere else it is the\n // apostrophe in `don't` or `o'reilly`, and treating it as a quote would swallow the\n // rest of the query.\n if (character === \"'\" && (current === \"\" || current === \"-\" || current === \"!\" || current.endsWith(\":\"))) {\n quote = \"'\";\n continue;\n }\n if (character === \"(\") {\n if (SET_OPENER.test(current)) {\n current += character;\n depth = 1;\n continue;\n }\n flush();\n tokens.push({ kind: \"open\" });\n continue;\n }\n if (character === \")\") {\n flush();\n tokens.push({ kind: \"close\" });\n continue;\n }\n if (SPACE.test(character)) {\n flush();\n continue;\n }\n current += character;\n }\n flush();\n return tokens;\n}\n\n/**\n * The values of a `$in(...)` set. A comma separates values only outside quotes, and a quote\n * left open runs to the end, because that is what a box somebody is typing into looks like.\n */\nfunction splitSet(inside: string): string[] {\n const values: string[] = [];\n let at = 0;\n while (at < inside.length) {\n while (at < inside.length && SPACE.test(inside[at] as string)) at++;\n if (at >= inside.length) break;\n const open = inside[at];\n let value: string;\n if (open === '\"' || open === \"'\") {\n const close = inside.indexOf(open, at + 1);\n value = close === -1 ? inside.slice(at + 1) : inside.slice(at + 1, close);\n at = close === -1 ? inside.length : close + 1;\n const comma = inside.indexOf(\",\", at);\n at = comma === -1 ? inside.length : comma + 1;\n } else {\n const comma = inside.indexOf(\",\", at);\n const end = comma === -1 ? inside.length : comma;\n value = inside.slice(at, end);\n at = end + 1;\n }\n const cleaned = value.trim();\n if (cleaned !== \"\") values.push(cleaned);\n }\n return values;\n}\n\nfunction unquote(value: string): string {\n const trimmed = value.trim();\n if (trimmed.length < 2) return trimmed;\n const first = trimmed[0];\n return (first === '\"' || first === \"'\") && trimmed.endsWith(first) ? trimmed.slice(1, -1) : trimmed;\n}\n\nexport const SET_TERM = /^\\$(in|notin)\\(([\\s\\S]*)$/i;\n\nfunction toTerm(word: string): Term | undefined {\n const negated = word.startsWith(\"-\") || word.startsWith(\"!\");\n const body = negated ? word.slice(1) : word;\n if (body === \"\") return undefined;\n const colon = body.indexOf(\":\");\n if (colon <= 0) return { name: undefined, value: body, negated };\n const name = body.slice(0, colon);\n const rest = body.slice(colon + 1);\n // The closing bracket is stripped separately. Matched as an optional `\\)?` at the end of\n // one pattern, the greedy middle swallowed it and handed it to the last value, so\n // `$notin(/health, /checkout)` stopped excluding `/checkout`.\n const set = SET_TERM.exec(rest);\n if (set !== null) {\n const raw = set[2] as string;\n const values = splitSet(raw.endsWith(\")\") ? raw.slice(0, -1) : raw);\n const inverted = (set[1] as string).toLowerCase() === \"notin\";\n return { name, value: values[0] ?? \"\", negated: negated !== inverted, values };\n }\n const value = unquote(rest);\n if (value === \"\") return undefined;\n return { name, value, negated };\n}\n\n/**\n * Recursive descent, `$not` tightest and `$or` loosest.\n *\n * A dangling operator, an unclosed bracket or a stray close is dropped rather than raised.\n * Brackets past `MAX_TEXT_DEPTH` are ignored rather than descended into: in BotHandler five\n * thousand nested brackets in a shared link overflowed the stack and broke the dashboard\n * for whoever opened it.\n */\nfunction parseTokens(tokens: readonly Token[]): Tree {\n let at = 0;\n let depth = 0;\n\n const parseUnary = (): Tree | undefined => {\n const token = tokens[at];\n if (token === undefined) return undefined;\n if (token.kind === \"op\" && token.op === \"not\") {\n // A run of negations is its parity, which is both what they mean and what keeps the\n // query shallow: thirty-three `$not`s used to build thirty-three levels, past what the\n // engine will compile, so the box could produce a filter that would not run.\n let negations = 0;\n while (tokens[at]?.kind === \"op\" && (tokens[at] as { op: string }).op === \"not\") {\n at++;\n negations++;\n }\n const of = parseUnary();\n if (of === undefined) return undefined;\n return negations % 2 === 0 ? of : { kind: \"not\", of };\n }\n if (token.kind === \"open\") {\n at++;\n if (depth >= MAX_TEXT_DEPTH) return undefined;\n depth++;\n const inner = parseOr();\n depth--;\n if (tokens[at]?.kind === \"close\") at++;\n return inner.kind === \"all\" ? undefined : inner;\n }\n if (token.kind === \"close\") return undefined;\n if (token.kind === \"op\") {\n at++;\n return parseUnary();\n }\n at++;\n const term = toTerm(token.text);\n return term === undefined ? undefined : { kind: \"term\", term };\n };\n\n const parseAnd = (): Tree => {\n const parts: Tree[] = [];\n while (at < tokens.length) {\n const token = tokens[at];\n if (token === undefined || token.kind === \"close\") break;\n if (token.kind === \"op\" && token.op === \"or\") break;\n if (token.kind === \"op\" && token.op === \"and\") {\n at++;\n continue;\n }\n const before = at;\n const part = parseUnary();\n if (part !== undefined) parts.push(part);\n if (at === before) at++;\n }\n return parts.length === 0 ? { kind: \"all\" } : parts.length === 1 ? (parts[0] as Tree) : { kind: \"and\", parts };\n };\n\n const parseOr = (): Tree => {\n const parts: Tree[] = [parseAnd()];\n while (tokens[at]?.kind === \"op\" && (tokens[at] as { op: string }).op === \"or\") {\n at++;\n parts.push(parseAnd());\n }\n const real = parts.filter((part) => part.kind !== \"all\");\n if (real.length === 0) return { kind: \"all\" };\n return real.length === 1 ? (real[0] as Tree) : { kind: \"or\", parts: real };\n };\n\n // Stray closing brackets at the top level end `parseOr` early; keep going past them so\n // `a) b` still reads both terms.\n const parts: Tree[] = [];\n while (at < tokens.length) {\n const tree = parseOr();\n if (tree.kind !== \"all\") parts.push(tree);\n if (tokens[at]?.kind === \"close\") at++;\n }\n if (parts.length === 0) return { kind: \"all\" };\n return parts.length === 1 ? (parts[0] as Tree) : { kind: \"and\", parts };\n}\n\n/* ------------------------------------------------------------------------------------ */\n/* To JQL */\n/* ------------------------------------------------------------------------------------ */\n\n/** A query that matches nothing: an empty `$in`. What a half-typed set or an unreadable number means. */\nfunction nothing(key: string): LooseQuery {\n return { [key]: { $in: [] } };\n}\n\nfunction toQuery(tree: Tree, vocabulary: Vocabulary<never, object> | undefined, mode: \"vocabulary\" | \"any\"): LooseQuery {\n switch (tree.kind) {\n case \"all\":\n return {};\n case \"not\":\n return { $not: toQuery(tree.of, vocabulary, mode) };\n case \"and\":\n return { $and: tree.parts.map((part) => toQuery(part, vocabulary, mode)) };\n case \"or\":\n return { $or: tree.parts.map((part) => toQuery(part, vocabulary, mode)) };\n case \"term\": {\n const query = termQuery(tree.term, vocabulary, mode);\n return tree.term.negated ? { $not: query } : query;\n }\n }\n}\n\nconst PATH_NAME = /^[\\p{L}_][\\p{L}\\p{N}_-]*(?:\\.[\\p{L}\\p{N}_-]+)*$/u;\n\nfunction termQuery(term: Term, vocabulary: Vocabulary<never, object> | undefined, mode: \"vocabulary\" | \"any\"): LooseQuery {\n let field: VocabularyField<never> | undefined;\n let key: string | undefined;\n // `has:rule` asks about a field rather than a value, so its value *is* the field name.\n if (term.name !== undefined && term.name.toLowerCase() === EXISTS_TERM && term.values === undefined) {\n const named = existence(term.value, vocabulary, mode);\n if (named !== undefined) return named;\n }\n if (term.name !== undefined) {\n field = vocabulary?.lookup.get(term.name.toLowerCase());\n if (field !== undefined) key = field.name;\n else if (mode === \"any\" && PATH_NAME.test(term.name)) key = term.name;\n }\n if (key === undefined) {\n // A colon with an unknown name in front of it is not a field term: `foo:bar` searches\n // for the text `foo:bar`, and a set on an unknown name for what was typed.\n const text = term.name === undefined ? term.value : `${term.name}:${term.values === undefined ? term.value : term.values.join(\",\")}`;\n return freeText(text, vocabulary);\n }\n const kind: FieldKind = field?.kind ?? (term.values === undefined && EXPLICIT_COMPARISON.test(term.value) ? \"number\" : \"text\");\n const values = term.values ?? [term.value];\n // An empty set matches nothing rather than everything: `$in()` is half-typed, and a\n // filter that widens while somebody is still typing it is a filter that lies.\n if (values.length === 0) return nothing(key);\n switch (kind) {\n case \"text\":\n return { [key]: { $contains: single(values), $options: \"i\" } };\n case \"word\":\n return { [key]: { $word: single(values), $options: \"i\" } };\n case \"exact\":\n return values.length === 1 ? { [key]: { $eq: values[0], $options: \"i\" } } : { [key]: { $in: values, $options: \"i\" } };\n case \"boolean\": {\n const read = values.map(readBoolean).filter((value): value is boolean => value !== undefined);\n if (read.length === 0) return nothing(key);\n return read.length === 1 ? { [key]: read[0] } : { [key]: { $in: read } };\n }\n case \"number\":\n case \"date\": {\n if (term.values !== undefined) {\n const read = values.map((value) => readScalar(value, kind)).filter((value) => value !== undefined);\n return read.length === 0 ? nothing(key) : { [key]: { $in: read } };\n }\n const condition = comparison(term.value, kind);\n return condition === undefined ? nothing(key) : { [key]: condition };\n }\n }\n}\n\n/**\n * A comparison written out in full, on a field nothing is known about.\n *\n * Without a vocabulary every field reads as text, and `score:>70` would search for the\n * characters \">70\" — which nobody typing it means. An operator or a range with a number\n * on it is unambiguous, so it compares. A bare `70` stays text, because on an unknown\n * field it is as likely to be part of an identifier as a quantity.\n */\nexport const EXPLICIT_COMPARISON = /^(?:(?:>=|<=|>|<)[+-]?(?:\\d+\\.?\\d*|\\.\\d+)|[+-]?(?:\\d+\\.?\\d*|\\.\\d+)?\\.\\.[+-]?(?:\\d+\\.?\\d*|\\.\\d+)?)$/;\n\n/**\n * `has:<field>` — the field has a value.\n *\n * Returns nothing when the name is not a field here, so `has:something-else` falls through\n * and is searched for as text, the same as any other name the vocabulary does not know.\n */\nfunction existence(name: string, vocabulary: Vocabulary<never, object> | undefined, mode: \"vocabulary\" | \"any\"): LooseQuery | undefined {\n const field = vocabulary?.lookup.get(name.toLowerCase());\n if (field !== undefined) return { [field.name]: { $exists: true } };\n if (mode === \"any\" && PATH_NAME.test(name)) return { [name]: { $exists: true } };\n return undefined;\n}\n\nfunction single(values: readonly string[]): string | readonly string[] {\n return values.length === 1 ? (values[0] as string) : values;\n}\n\nfunction freeText(text: string, vocabulary: Vocabulary<never, object> | undefined): LooseQuery {\n if (vocabulary?.text !== undefined) return { $text: { $search: text, $fields: vocabulary.text } };\n return { $text: text };\n}\n\nconst TRUE_WORDS = new Set([\"true\", \"yes\", \"1\", \"on\"]);\nconst FALSE_WORDS = new Set([\"false\", \"no\", \"0\", \"off\"]);\n\nfunction readBoolean(value: string): boolean | undefined {\n const lower = value.toLowerCase();\n if (TRUE_WORDS.has(lower)) return true;\n if (FALSE_WORDS.has(lower)) return false;\n return undefined;\n}\n\nconst NUMBER = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:e[+-]?\\d+)?$/i;\n\n/**\n * A relative instant, written with the sign that says which way: `-1h` is an hour ago,\n * `+30m` is half an hour from now.\n *\n * The sign is required. A bare `1h` in a date field could as easily be part of an\n * identifier somebody is searching for, and a filter that quietly turned it into a moment\n * in time would be reading something into what was typed.\n */\nconst RELATIVE = /^([+-])(\\d+(?:ms|s|m|h|d|w))+$/;\n\nfunction readScalar(value: string, kind: \"number\" | \"date\"): number | { $date: string | { $ago: string } | { $ahead: string } } | undefined {\n const trimmed = value.trim();\n if (kind === \"number\") {\n if (!NUMBER.test(trimmed)) return undefined;\n const read = Number(trimmed);\n // `1e309` reads as Infinity, which is not a JSON number: the query would be one the\n // engine refuses and `JSON.stringify` turns into null, so a box could produce a filter\n // that could neither run nor be saved. A number nobody can write is a value nothing has.\n if (!Number.isFinite(read)) return undefined;\n // `-0` matches everything `0` matches, and writing it out as JSON turns it into `0`\n // anyway; normalising here keeps a saved query identical to the one that was typed.\n return read === 0 ? 0 : read;\n }\n if (trimmed.toLowerCase() === \"now\") return { $date: \"now\" };\n const relative = RELATIVE.exec(trimmed);\n if (relative !== null) {\n const span = trimmed.slice(1);\n // A duration the engine could not size is not one anybody typed on purpose, and\n // emitting it would hand the box a query that cannot run.\n if (parseDuration(span) === undefined) return undefined;\n return { $date: relative[1] === \"-\" ? { $ago: span } : { $ahead: span } };\n }\n return trimmed !== \"\" && !Number.isNaN(Date.parse(trimmed)) ? { $date: trimmed } : undefined;\n}\n\nconst COMPARISON = /^(>=|<=|>|<|=)?([\\s\\S]*)$/;\n\n/** `>70`, `>=70`, `<70`, `<=70`, `=70`, `70`, and the range `10..20` (both ends included). */\nfunction comparison(value: string, kind: \"number\" | \"date\"): Record<string, unknown> | undefined {\n const range = value.indexOf(\"..\");\n if (range !== -1) {\n const low = value.slice(0, range);\n const high = value.slice(range + 2);\n const from = low === \"\" ? undefined : readScalar(low, kind);\n const to = high === \"\" ? undefined : readScalar(high, kind);\n if ((low !== \"\" && from === undefined) || (high !== \"\" && to === undefined) || (from === undefined && to === undefined)) return undefined;\n return { ...(from === undefined ? {} : { $gte: from }), ...(to === undefined ? {} : { $lte: to }) };\n }\n const [, operator, rest] = COMPARISON.exec(value) as RegExpExecArray;\n const scalar = readScalar(rest as string, kind);\n if (scalar === undefined) return undefined;\n switch (operator) {\n case \">\":\n return { $gt: scalar };\n case \">=\":\n return { $gte: scalar };\n case \"<\":\n return { $lt: scalar };\n case \"<=\":\n return { $lte: scalar };\n default:\n return { $eq: scalar };\n }\n}\n","import { checkVocabulary, type Vocabulary } from \"../vocabulary.js\";\nimport { TEXT_OPERATORS } from \"./parse.js\";\n\n/**\n * What to offer for the token the caret is in.\n *\n * Returns the completions and the span they replace, so a caller can put one in without\n * disturbing the rest of the input. A token that already names a field with a closed set\n * of values completes the value; anything else completes the field name. Every name\n * offered comes from the vocabulary the parser reads, so nothing offered is something the\n * language would not accept.\n */\nexport interface Suggestions {\n readonly options: readonly string[];\n readonly from: number;\n readonly to: number;\n}\n\nexport function suggest(input: string, caret: number, vocabulary?: Vocabulary<never, object>): Suggestions {\n checkVocabulary(vocabulary);\n const before = input.slice(0, caret);\n const start = Math.max(before.lastIndexOf(\" \") + 1, 0);\n const token = before.slice(start);\n const to = caret;\n const negated = token.startsWith(\"-\") || token.startsWith(\"!\");\n const body = negated ? token.slice(1) : token;\n const sign = negated ? (token[0] as string) : \"\";\n const colon = body.indexOf(\":\");\n\n if (colon === -1) {\n const partial = body.toLowerCase();\n // A token that has begun with `$` can only be an operator; no field name starts with one.\n if (partial.startsWith(\"$\")) return { options: TEXT_OPERATORS.filter((name) => name.startsWith(partial)), from: start, to };\n const names = vocabulary?.names ?? [];\n return { options: names.filter((name) => name.startsWith(partial)).map((name) => `${sign}${name}:`), from: start, to };\n }\n\n const name = body.slice(0, colon).toLowerCase();\n const values = vocabulary?.lookup.get(name)?.values;\n // A field that takes anything gets nothing: guessing there would be inventing options\n // rather than completing them.\n if (values === undefined) return { options: [], from: start, to };\n const partial = body.slice(colon + 1).toLowerCase();\n const prefix = `${sign}${name}:`;\n // The set forms come first, because a field with a closed set is exactly the field\n // somebody wants two of.\n const forms = partial.startsWith(\"$\") ? [\"$in(\", \"$notin(\"].filter((form) => form.startsWith(partial)).map((form) => `${prefix}${form}`) : [];\n return { options: [...forms, ...values.filter((value) => value.toLowerCase().startsWith(partial)).map((value) => `${prefix}${value}`)], from: start, to };\n}\n","import { checkVocabulary, type FieldKind, type Vocabulary } from \"../vocabulary.js\";\nimport { EXISTS_TERM, EXPLICIT_COMPARISON, SET_TERM, type TextOptions } from \"./parse.js\";\n\n/**\n * A query, written back as something somebody can type.\n *\n * A dashboard that stores filters as JSON still has to put one in a search box when\n * somebody opens it to edit. That is this, and it is deliberately **not** total: the text\n * syntax has no spelling for `$elemMatch`, `$size`, `$glob` or a `{ \"$field\": … }`\n * reference, and inventing one per operator would turn a box people can type into a\n * language they have to learn.\n *\n * So the honest answer is two things: the text, and what was left out of it. **The text is\n * exact for what it says** — parsed back with the same vocabulary it means precisely the\n * clauses it carries, which the tests hold it to — but a caller that ignores `unexpressed`\n * is showing somebody a filter wider than the one that is running. `complete` is there so\n * that check is one line.\n */\n\nexport interface Unexpressed {\n /** Where the clause is in the query: `$or[1].tags`. */\n readonly at: string;\n /** The clause itself, as it was written. */\n readonly clause: unknown;\n /** Why the text cannot say it. */\n readonly why: string;\n}\n\nexport interface TextForm {\n /** The query as text. Parsing it back gives exactly the clauses it carries. */\n readonly text: string;\n /** True when the text says everything the query does. */\n readonly complete: boolean;\n /** The clauses with no spelling in the text syntax, in the order they were met. */\n readonly unexpressed: readonly Unexpressed[];\n}\n\n/** The operators a condition may hold that the text syntax can say, per field kind. */\nconst SAYABLE: Readonly<Record<FieldKind, readonly string[]>> = {\n text: [\"$contains\", \"$exists\"],\n word: [\"$word\", \"$exists\"],\n exact: [\"$eq\", \"$in\", \"$exists\"],\n number: [\"$eq\", \"$gt\", \"$gte\", \"$lt\", \"$lte\", \"$in\", \"$exists\"],\n date: [\"$eq\", \"$gt\", \"$gte\", \"$lt\", \"$lte\", \"$in\", \"$exists\"],\n boolean: [\"$eq\", \"$in\", \"$exists\"],\n};\n\nconst PATH_NAME = /^[\\p{L}_][\\p{L}\\p{N}_-]*(?:\\.[\\p{L}\\p{N}_-]+)*$/u;\n\n/** The comparisons a field with no vocabulary entry can carry: the ones the parser infers back. */\nconst INFERRED = [\"$gt\", \"$gte\", \"$lt\", \"$lte\"];\n\nfunction inferKind(condition: Record<string, unknown>): FieldKind {\n const operators = Object.keys(condition).filter((operator) => operator !== \"$options\");\n const numeric = operators.length > 0 && operators.every((operator) => INFERRED.includes(operator) && typeof condition[operator] === \"number\" && Number.isFinite(condition[operator]));\n return numeric ? \"number\" : \"text\";\n}\n\n/** Writes a query as search-box text, and says what it could not write. */\nexport function toText(query: unknown, options: TextOptions = {}): TextForm {\n const vocabulary = checkVocabulary(options.vocabulary);\n const mode = options.fields ?? (vocabulary === undefined ? \"any\" : \"vocabulary\");\n const left: Unexpressed[] = [];\n const text = writeQuery(query, { vocabulary, mode, left }, \"\", false);\n return { text, complete: left.length === 0, unexpressed: left };\n}\n\ninterface Writing {\n readonly vocabulary: Vocabulary<never, object> | undefined;\n readonly mode: \"vocabulary\" | \"any\";\n readonly left: Unexpressed[];\n}\n\nfunction drop(writing: Writing, at: string, clause: unknown, why: string): \"\" {\n writing.left.push({ at, clause, why });\n return \"\";\n}\n\n/**\n * One query, as terms joined by juxtaposition — which is what `$and` means in the text.\n *\n * `grouped` says whether the caller will put this inside something tighter than an `$and`,\n * in which case an `$or` has to be bracketed to keep its meaning.\n */\nfunction writeQuery(query: unknown, writing: Writing, at: string, grouped: boolean): string {\n if (query === null || typeof query !== \"object\" || Array.isArray(query)) {\n return drop(writing, at, query, \"only an object is a query, and the text syntax writes nothing else\");\n }\n const clauses: string[] = [];\n for (const [key, value] of Object.entries(query as Record<string, unknown>)) {\n const here = at === \"\" ? key : `${at}.${key}`;\n const written = writeClause(key, value, writing, here, grouped);\n if (written !== \"\") clauses.push(written);\n }\n if (clauses.length === 0) return \"\";\n const joined = clauses.join(\" \");\n return grouped && clauses.length > 1 ? `(${joined})` : joined;\n}\n\nfunction writeClause(key: string, value: unknown, writing: Writing, at: string, grouped: boolean): string {\n switch (key) {\n case \"$comment\":\n // A note is not part of what the query asks, so losing it loses nothing.\n return \"\";\n case \"$and\": {\n if (!Array.isArray(value)) return drop(writing, at, value, \"$and takes a list of queries\");\n const parts = value.map((part, index) => writeQuery(part, writing, `${at}[${index}]`, true)).filter((part) => part !== \"\");\n const joined = parts.join(\" \");\n // Several terms are several clauses. Handed back unbracketed to a caller expecting\n // one — a `$not` — only the first was negated: `$not ((a $or b) c)` came out as\n // `$not (a $or b) c`, which is a different question.\n return grouped && parts.length > 1 ? `(${joined})` : joined;\n }\n case \"$or\": {\n if (!Array.isArray(value)) return drop(writing, at, value, \"$or takes a list of queries\");\n // An `$or` of nothing matches nothing, and the text syntax has no term for that: it\n // was written as `()`, which reads back as an empty query — everything. A filter that\n // widened from nothing to everything, and called itself complete while doing it.\n if (value.length === 0) return drop(writing, at, value, \"an $or of nothing matches nothing, and no term says that\");\n const parts = value.map((part, index) => writeQuery(part, writing, `${at}[${index}]`, true));\n // A branch that cannot be written would widen the whole `$or`, so none of it is said.\n if (parts.some((part) => part === \"\")) return drop(writing, at, value, \"one branch of the $or has no spelling, and writing the others would widen it\");\n return parts.length === 1 ? (parts[0] as string) : `(${parts.join(\" $or \")})`;\n }\n case \"$nor\": {\n if (!Array.isArray(value) || value.length === 0) return drop(writing, at, value, \"$nor takes a list of queries\");\n const parts = value.map((part, index) => writeQuery(part, writing, `${at}[${index}]`, true));\n if (parts.some((part) => part === \"\")) return drop(writing, at, value, \"one branch of the $nor has no spelling\");\n return `$not (${parts.join(\" $or \")})`;\n }\n case \"$not\":\n return writeNot(value, writing, at);\n case \"$text\":\n return writeText(value, writing, at);\n default:\n if (key.startsWith(\"$\")) return drop(writing, at, value, `\"${key}\" is a query operator the text syntax cannot say`);\n return writeField(key, value, writing, at, false);\n }\n}\n\n/** `$not` is a leading `-` on one term, and `$not ( … )` on anything larger. */\nfunction writeNot(value: unknown, writing: Writing, at: string): string {\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n const keys = Object.keys(value as Record<string, unknown>);\n // A negated single field is `-term`, and a negated set is `$notin(…)`.\n if (keys.length === 1) {\n const key = keys[0] as string;\n if (!key.startsWith(\"$\")) return writeField(key, (value as Record<string, unknown>)[key], writing, `${at}.${key}`, true);\n }\n }\n // What was already unsayable inside it, before this writes anything: a `$not` whose\n // contents were dropped is reported by that drop, and leaving the negation out is the\n // conservative reading the contract asks for.\n const reported = writing.left.length;\n const inner = writeQuery(value, writing, at, true);\n if (inner === \"\") {\n // Nothing written and nothing reported means the negation held only things that say\n // nothing — an empty query, or a comment. `$not {}` matches *nothing*, and the empty\n // text matches everything, so staying quiet here turned the narrowest query there is\n // into the widest one and still called the form complete.\n if (writing.left.length === reported) return drop(writing, at, value, \"$not of a query that asks nothing matches nothing, and no term says that\");\n return \"\";\n }\n return inner.startsWith(\"(\") ? `$not ${inner}` : `$not (${inner})`;\n}\n\nfunction writeText(value: unknown, writing: Writing, at: string): string {\n const search = typeof value === \"string\" ? { $search: value } : (value as Record<string, unknown> | null);\n if (search === null || typeof search !== \"object\" || typeof search.$search !== \"string\") {\n return drop(writing, at, value, \"a text search is a phrase or { $search: … }\");\n }\n if (search.$caseSensitive === true) return drop(writing, at, value, \"a bare word in the text syntax always ignores case\");\n if (search.$fields !== undefined) {\n const fields = search.$fields;\n const same =\n Array.isArray(fields) &&\n writing.vocabulary?.text !== undefined &&\n fields.length === writing.vocabulary.text.length &&\n fields.every((name, index) => name === (writing.vocabulary?.text as readonly string[])[index]);\n // A bare word searches the vocabulary's own text fields; any other list is a question\n // the box cannot ask.\n if (!same) return drop(writing, at, value, \"a bare word searches the vocabulary's text fields, not a list of its own\");\n }\n if (search.$search === \"\") return drop(writing, at, value, \"an empty search is not a term anybody can type\");\n // Quoting cannot save a bare word that begins with a dash, or one that *is* an operator:\n // the parser strips the quotes before it decides what the word is, so `\"-a\"` would be\n // read back as a negated `a` and `\"$or\"` as an operator. A field term is safe — the\n // decision there is made on the whole word, which starts with the field's name.\n if (/^[-!]/.test(search.$search)) return drop(writing, at, value, \"a bare word cannot begin with a dash: quoted or not, the parser reads that as a negation\");\n if (/^\\$(and|or|not)$/i.test(search.$search)) return drop(writing, at, value, \"a bare word cannot be an operator's name: quoted or not, the parser reads it as the operator\");\n const quoted = quote(search.$search, false);\n return quoted ?? drop(writing, at, value, \"the phrase holds both kinds of quote, and the syntax has no escape for either\");\n}\n\n/** One field, as `name:value`, `-name:value`, `name:$in(…)` or `has:name`. */\nfunction writeField(name: string, value: unknown, writing: Writing, at: string, negated: boolean): string {\n const field = writing.vocabulary?.lookup.get(name.toLowerCase());\n if (field === undefined && (writing.mode === \"vocabulary\" || !PATH_NAME.test(name))) {\n return drop(writing, at, { [name]: value }, writing.mode === \"vocabulary\" ? `\"${name}\" is not a field of this vocabulary, so the text would search for it as words` : `\"${name}\" cannot be written before a colon`);\n }\n const key = field?.name ?? name;\n if (key.toLowerCase() === EXISTS_TERM) {\n return drop(writing, at, { [name]: value }, `\"${key}\" is how the syntax asks whether a field is set, so a field of that name cannot be written`);\n }\n const condition = value !== null && typeof value === \"object\" && !Array.isArray(value) ? (value as Record<string, unknown>) : { $eq: value };\n // Without a vocabulary the parser reads a value by its shape, so the writer has to reach\n // the same conclusion: an explicit comparison against a number is a number, and\n // everything else is text. Writing `x:30` for `{ x: { $eq: 30 } }` would read back as the\n // characters \"30\" — narrower than it looks, and wrong.\n const inferred = field === undefined;\n const kind: FieldKind = field?.kind ?? inferKind(condition);\n const operators = Object.keys(condition).filter((operator) => operator !== \"$options\");\n if (operators.length === 0 || !operators.every((operator) => operator.startsWith(\"$\"))) {\n return drop(writing, at, { [name]: value }, \"the value mixes operators with fields, or holds none\");\n }\n const sayable = SAYABLE[kind];\n // `10..20` is what somebody typed, and what the box reads back most naturally; written as\n // two terms it means the same thing but no longer looks like the range it is.\n const range = writeRange(key, kind, condition, operators, negated);\n if (range !== undefined) return range;\n const terms: string[] = [];\n for (const operator of operators) {\n const term = writeOperator(key, kind, operator, condition, writing, at, negated, sayable, inferred);\n if (term === \"\") return \"\";\n terms.push(term);\n }\n // Several operators on one field are several terms, which is what juxtaposition means —\n // except under a negation, where `-a -b` would mean neither rather than not both.\n if (terms.length > 1 && negated) return drop(writing, at, { [name]: value }, \"a negated field with several operators would have to be written as $not ( … ), which changes what a set means\");\n return terms.join(\" \");\n}\n\n/** `field:a..b`, when the condition is exactly the two ends of one. */\nfunction writeRange(key: string, kind: FieldKind, condition: Record<string, unknown>, operators: readonly string[], negated: boolean): string | undefined {\n if (negated || (kind !== \"number\" && kind !== \"date\")) return undefined;\n if (operators.length !== 2 || !operators.includes(\"$gte\") || !operators.includes(\"$lte\")) return undefined;\n const low = writeValue(condition.$gte, kind, \"$eq\", false, false);\n const high = writeValue(condition.$lte, kind, \"$eq\", false, false);\n if (low === undefined || high === undefined) return undefined;\n return `${key}:${low}..${high}`;\n}\n\nfunction writeOperator(\n key: string,\n kind: FieldKind,\n operator: string,\n condition: Record<string, unknown>,\n writing: Writing,\n at: string,\n negated: boolean,\n sayable: readonly string[],\n inferred: boolean,\n): string {\n const operand = condition[operator];\n const here = `${at}.${operator}`;\n const sign = negated ? \"-\" : \"\";\n if (!sayable.includes(operator)) return drop(writing, here, { [operator]: operand }, `\"${operator}\" has no spelling in the text syntax`);\n if (operator === \"$exists\") {\n if (operand !== true) return drop(writing, here, { [operator]: operand }, \"only $exists: true is written, as has:field; its negation is the leading dash\");\n return `${sign}has:${key}`;\n }\n // The box always matches text and names without regard to case, so a condition that does\n // care is one it cannot ask.\n const ignoresCase = condition.$options === \"i\";\n if ((kind === \"text\" || kind === \"word\" || kind === \"exact\") && !ignoresCase) {\n return drop(writing, here, condition, \"the text syntax always ignores case, and this condition does not\");\n }\n\n // A string operator holding a list is a set, and the box writes a set one way.\n const set = operator === \"$in\" || ((operator === \"$contains\" || operator === \"$word\") && Array.isArray(operand));\n const values = set ? operand : [operand];\n if (!Array.isArray(values)) return drop(writing, here, { [operator]: operand }, \"$in takes a list\");\n if (values.length === 0) return drop(writing, here, { [operator]: operand }, \"an empty set is not something anybody types\");\n const written: string[] = [];\n for (const value of values) {\n const one = writeValue(value, kind, operator, values.length > 1, inferred);\n if (one === undefined) return drop(writing, here, { [operator]: operand }, `${describeValue(value)} cannot be written after a colon`);\n written.push(one);\n }\n if (written.length > 1) return `${key}:${negated ? \"$notin\" : \"$in\"}(${written.join(\", \")})`;\n return `${sign}${key}:${written[0] as string}`;\n}\n\n/** A value as the box would take it, or `undefined` when it has no spelling. */\nfunction writeValue(value: unknown, kind: FieldKind, operator: string, inSet: boolean, inferred: boolean): string | undefined {\n if (kind === \"boolean\") return value === true ? \"true\" : value === false ? \"false\" : undefined;\n if (kind === \"number\") {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return undefined;\n return `${comparison(operator)}${String(value)}`;\n }\n if (kind === \"date\") {\n const instant = writeDate(value);\n return instant === undefined ? undefined : `${comparison(operator)}${instant}`;\n }\n if (typeof value !== \"string\" || value === \"\") return undefined;\n // The parser trims a value after the tokenizer has taken its quotes off, so whitespace at\n // either end is lost — and a value that is only whitespace disappears altogether, taking\n // the term with it and leaving a query that matches everything.\n if (value.trim() !== value) return undefined;\n // `$in(` and `$notin(` are read before quoting is considered, so a value beginning with\n // either is read as a set however it is written.\n if (SET_TERM.test(value)) return undefined;\n // On a field with no kind of its own, the parser reads an explicit comparison as a number,\n // so text that looks like one cannot be written as text.\n if (kind === \"text\" && inferred && EXPLICIT_COMPARISON.test(value)) return undefined;\n return quote(value, inSet);\n}\n\nfunction comparison(operator: string): string {\n switch (operator) {\n case \"$gt\":\n return \">\";\n case \"$gte\":\n return \">=\";\n case \"$lt\":\n return \"<\";\n case \"$lte\":\n return \"<=\";\n default:\n return \"\";\n }\n}\n\nfunction writeDate(value: unknown): string | undefined {\n if (value === null || typeof value !== \"object\") return undefined;\n const date = (value as { $date?: unknown }).$date;\n if (Object.keys(value as object).length !== 1) return undefined;\n if (typeof date === \"string\") return date === \"now\" ? \"now\" : /\\s/.test(date) ? undefined : date;\n if (date !== null && typeof date === \"object\") {\n const relative = date as { $ago?: unknown; $ahead?: unknown };\n if (typeof relative.$ago === \"string\") return `-${relative.$ago}`;\n if (typeof relative.$ahead === \"string\") return `+${relative.$ahead}`;\n }\n // Epoch milliseconds have no spelling: the box reads a bare number as text.\n return undefined;\n}\n\n/** A value quoted the way it has to be for the parser to read it back whole. */\nfunction quote(value: string, inSet: boolean): string | undefined {\n const plain = !/[\\s()\"'“”‘’]/.test(value) && !/^[-!$]/.test(value) && !(inSet && value.includes(\",\"));\n if (plain) return value;\n if (!value.includes('\"')) return `\"${value}\"`;\n if (!value.includes(\"'\")) return `'${value}'`;\n // The syntax has no escape inside a quoted run, so a value holding both kinds cannot be\n // written at all. Saying so is better than writing something that reads as less.\n return undefined;\n}\n\nfunction describeValue(value: unknown): string {\n if (value === null) return \"null\";\n if (Array.isArray(value)) return \"a list\";\n if (typeof value === \"object\") return \"an object\";\n return `${typeof value} ${JSON.stringify(value)}`;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/text/parse.ts","../src/text/quote.ts","../src/text/suggest.ts","../src/text/write.ts"],"names":["checkVocabulary","quote","parts","parseDuration","JqlError","name","PATH_NAME","comparison"],"mappings":"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","file":"text.cjs","sourcesContent":["import { parseDuration } from \"../internal/duration.js\";\nimport type { LooseQuery, UntypedQuery } from \"../types.js\";\nimport { checkVocabulary, type FieldKind, type Vocabulary, type VocabularyField } from \"../vocabulary.js\";\n\n/**\n * The search-box syntax, compiled into a JQL document.\n *\n * Ported from BotHandler's feed filter, where it was its own language with its own\n * matcher. Here it has no matcher at all: it produces the JSON query that means the same\n * thing, and the engine runs that. So a filter typed into a box and the JSON a service\n * receives cannot drift apart — there is only one set of semantics, and the text is a way\n * of writing it.\n *\n * ```text\n * actor:203.0.113.4 -path:/health that address, except its health checks\n * verdict:human $or verdict:unknown either verdict\n * $not path:/health the same as -path:/health, spelled out\n * action:$in(block, drop) one of a set\n * action:$notin(allow, tag) none of a set\n * score:>70 score:>=70 score:10..20 numeric comparisons and a range\n * at:>2026-09-01 a date comparison\n * at:>-1h the last hour, and it stays the last hour\n * has:rule -has:rule the field is set, or is not\n * (verdict:human $or score:<20) $and $not path:/health\n * \"connection reset\" a phrase, spaces and all — matched against one\n * value, never joined across two fields\n * ```\n *\n * **Adjacent terms mean AND**, which is what narrowing means. `$or` binds more loosely than\n * `$and`, and `$not` more tightly than either — the conventional precedence. Operators\n * carry a `$` because a bare `or` is a word that appears in User-Agents and paths, and a\n * language where an ordinary search word silently becomes an operator is a language that\n * lies about what it matched.\n *\n * **Nothing here throws for anything anybody types.** It backs live search boxes, so\n * half-typed input is the normal state rather than an error: an unclosed bracket, a dangling\n * `$or`, a `$in(` with nothing after it all parse to the best reading available. A\n * *vocabulary* that is not one is the exception — that is a mistake in the calling code\n * rather than in the box, and it is refused by name instead of failing later, deeper, as a\n * `TypeError` nobody can place. That is the opposite of the JSON\n * engine's rule, and on purpose: JSON is written by a program that can be told it is wrong,\n * a search box by a person who has not finished typing.\n */\n\nexport interface TextOptions {\n /** The field names the text may use, and how each one reads a value. */\n readonly vocabulary?: Vocabulary<never, object> | undefined;\n /**\n * What a name before a colon may be.\n *\n * - `\"vocabulary\"` — only a vocabulary field; anything else is searched for as text,\n * because a path or a User-Agent can contain a colon. The default when a vocabulary is given.\n * - `\"any\"` — any name that looks like a path (`address.city:London`), read as text.\n * The default without a vocabulary, since there is nothing else to go on. A URL then\n * has to be quoted: `\"http://example.com\"`.\n */\n readonly fields?: \"vocabulary\" | \"any\" | undefined;\n}\n\n/**\n * The longest input this will read.\n *\n * Parsing is linear, so length is not a cliff the way nesting is, but this runs on every\n * keystroke and on whatever arrives in a URL. Eight kilobytes is past any query a person\n * writes. Longer input is cut, not refused, because refusing would be the one way this\n * function could fail.\n */\nexport const MAX_TEXT_CHARS = 8192;\n\n/**\n * How deep brackets may nest.\n *\n * Past anything anyone types, and deliberately no deeper than the tightest limit the engine\n * is asked to compile under (`UNTRUSTED_LIMITS` allows sixteen levels): a box that produced\n * a query the engine would refuse would be a box that lies about what it accepts.\n */\nexport const MAX_TEXT_DEPTH = 16;\n\n/** The name that asks whether a field is set, rather than naming one. */\nexport const EXISTS_TERM = \"has\";\n\n/** The operator words the text syntax understands. */\nexport const TEXT_OPERATORS: readonly string[] = [\"$and\", \"$or\", \"$not\", \"$in\", \"$notin\"];\n\ninterface Term {\n readonly name: string | undefined;\n readonly value: string;\n readonly negated: boolean;\n /** For `$in` and `$notin`. */\n readonly values?: readonly string[] | undefined;\n}\n\ntype Tree = { kind: \"all\" } | { kind: \"term\"; term: Term } | { kind: \"not\"; of: Tree } | { kind: \"and\"; parts: Tree[] } | { kind: \"or\"; parts: Tree[] };\n\ntype Token = { kind: \"word\"; text: string } | { kind: \"open\" } | { kind: \"close\" } | { kind: \"op\"; op: \"and\" | \"or\" | \"not\" };\n\n/**\n * Parses search-box text into a JQL query. Never throws; an empty input is `{}`, which\n * matches everything. The result is an `UntypedQuery`, so it can be handed to a typed\n * collection: what the text names is only known once somebody has typed it.\n */\nexport function parseText(input: string, options: TextOptions = {}): UntypedQuery {\n checkVocabulary(options.vocabulary);\n const trimmed = plainQuotes(String(input).trim());\n const tokens = tokenize(trimmed.length > MAX_TEXT_CHARS ? trimmed.slice(0, MAX_TEXT_CHARS) : trimmed);\n const mode = options.fields ?? (options.vocabulary === undefined ? \"any\" : \"vocabulary\");\n // A cast rather than a call to `untyped()`: importing the engine for an identity function\n // would put all of it in the text entry, which exists so that it does not.\n return toQuery(parseTokens(tokens), options.vocabulary, mode) as unknown as UntypedQuery;\n}\n\n/* ------------------------------------------------------------------------------------ */\n/* Quotes and tokens */\n/* ------------------------------------------------------------------------------------ */\n\n/**\n * Typographic quotes, and the plain ones they stand for.\n *\n * Nobody types a curly quote into a filter meaning a curly quote. They arrive by paste,\n * from anything with smart punctuation turned on. In BotHandler they used to be taken\n * literally, so `actor:$notin(“203.0.113.4”)` excluded nothing, with no sign anything was\n * wrong.\n */\nconst DOUBLE_QUOTES = \"\\u201c\\u201d\\u201e\\u201f\\u2033\\u2036\";\nconst TYPOGRAPHIC_QUOTES = /[\\u201c\\u201d\\u201e\\u201f\\u2033\\u2036\\u2018\\u2019\\u201a\\u201b\\u2032\\u2035]/g;\n\nfunction plainQuotes(input: string): string {\n return input.replace(TYPOGRAPHIC_QUOTES, (quote) => (DOUBLE_QUOTES.includes(quote) ? '\"' : \"'\"));\n}\n\nconst SET_OPENER = /\\$(in|notin)$/i;\nconst SPACE = /\\s/;\n\n/**\n * Splits the input into words, operators and brackets.\n *\n * Quoted runs stay whole, spaces and brackets included. A `field:$in(...)` list is one\n * word, because its brackets belong to the term rather than grouping.\n */\nfunction tokenize(input: string): Token[] {\n const tokens: Token[] = [];\n let current = \"\";\n let quote: '\"' | \"'\" | undefined;\n // The same, inside a `$in(...)` set, where quotes are kept for `splitSet` to read and a\n // bracket inside one must not end the set.\n let setQuote: '\"' | \"'\" | undefined;\n let depth = 0;\n\n const flush = (): void => {\n if (current === \"\") return;\n const lower = current.toLowerCase();\n if (lower === \"$and\" || lower === \"$or\" || lower === \"$not\") tokens.push({ kind: \"op\", op: lower.slice(1) as \"and\" | \"or\" | \"not\" });\n else tokens.push({ kind: \"word\", text: current });\n current = \"\";\n };\n\n for (let i = 0; i < input.length; i++) {\n const character = input[i] as string;\n if (depth > 0) {\n current += character;\n if (setQuote !== undefined) {\n if (character === setQuote) setQuote = undefined;\n } else if (character === '\"' || character === \"'\") setQuote = character;\n else if (character === \"(\") depth++;\n else if (character === \")\") {\n depth--;\n if (depth === 0) flush();\n }\n continue;\n }\n if (quote !== undefined) {\n if (character === quote) quote = undefined;\n else current += character;\n continue;\n }\n if (character === '\"') {\n quote = '\"';\n continue;\n }\n // A single quote is a quote only where a value begins. Anywhere else it is the\n // apostrophe in `don't` or `o'reilly`, and treating it as a quote would swallow the\n // rest of the query.\n if (character === \"'\" && (current === \"\" || current === \"-\" || current === \"!\" || current.endsWith(\":\"))) {\n quote = \"'\";\n continue;\n }\n if (character === \"(\") {\n if (SET_OPENER.test(current)) {\n current += character;\n depth = 1;\n continue;\n }\n flush();\n tokens.push({ kind: \"open\" });\n continue;\n }\n if (character === \")\") {\n flush();\n tokens.push({ kind: \"close\" });\n continue;\n }\n if (SPACE.test(character)) {\n flush();\n continue;\n }\n current += character;\n }\n flush();\n return tokens;\n}\n\n/**\n * The values of a `$in(...)` set. A comma separates values only outside quotes, and a quote\n * left open runs to the end, because that is what a box somebody is typing into looks like.\n */\nfunction splitSet(inside: string): string[] {\n const values: string[] = [];\n let at = 0;\n while (at < inside.length) {\n while (at < inside.length && SPACE.test(inside[at] as string)) at++;\n if (at >= inside.length) break;\n const open = inside[at];\n let value: string;\n if (open === '\"' || open === \"'\") {\n const close = inside.indexOf(open, at + 1);\n value = close === -1 ? inside.slice(at + 1) : inside.slice(at + 1, close);\n at = close === -1 ? inside.length : close + 1;\n const comma = inside.indexOf(\",\", at);\n at = comma === -1 ? inside.length : comma + 1;\n } else {\n const comma = inside.indexOf(\",\", at);\n const end = comma === -1 ? inside.length : comma;\n value = inside.slice(at, end);\n at = end + 1;\n }\n const cleaned = value.trim();\n if (cleaned !== \"\") values.push(cleaned);\n }\n return values;\n}\n\nfunction unquote(value: string): string {\n const trimmed = value.trim();\n if (trimmed.length < 2) return trimmed;\n const first = trimmed[0];\n return (first === '\"' || first === \"'\") && trimmed.endsWith(first) ? trimmed.slice(1, -1) : trimmed;\n}\n\nexport const SET_TERM = /^\\$(in|notin)\\(([\\s\\S]*)$/i;\n\nfunction toTerm(word: string): Term | undefined {\n const negated = word.startsWith(\"-\") || word.startsWith(\"!\");\n const body = negated ? word.slice(1) : word;\n if (body === \"\") return undefined;\n const colon = body.indexOf(\":\");\n if (colon <= 0) return { name: undefined, value: body, negated };\n const name = body.slice(0, colon);\n const rest = body.slice(colon + 1);\n // The closing bracket is stripped separately. Matched as an optional `\\)?` at the end of\n // one pattern, the greedy middle swallowed it and handed it to the last value, so\n // `$notin(/health, /checkout)` stopped excluding `/checkout`.\n const set = SET_TERM.exec(rest);\n if (set !== null) {\n const raw = set[2] as string;\n const values = splitSet(raw.endsWith(\")\") ? raw.slice(0, -1) : raw);\n const inverted = (set[1] as string).toLowerCase() === \"notin\";\n return { name, value: values[0] ?? \"\", negated: negated !== inverted, values };\n }\n const value = unquote(rest);\n if (value === \"\") return undefined;\n return { name, value, negated };\n}\n\n/**\n * Recursive descent, `$not` tightest and `$or` loosest.\n *\n * A dangling operator, an unclosed bracket or a stray close is dropped rather than raised.\n * Brackets past `MAX_TEXT_DEPTH` are ignored rather than descended into: in BotHandler five\n * thousand nested brackets in a shared link overflowed the stack and broke the dashboard\n * for whoever opened it.\n */\nfunction parseTokens(tokens: readonly Token[]): Tree {\n let at = 0;\n let depth = 0;\n\n const parseUnary = (): Tree | undefined => {\n const token = tokens[at];\n if (token === undefined) return undefined;\n if (token.kind === \"op\" && token.op === \"not\") {\n // A run of negations is its parity, which is both what they mean and what keeps the\n // query shallow: thirty-three `$not`s used to build thirty-three levels, past what the\n // engine will compile, so the box could produce a filter that would not run.\n let negations = 0;\n while (tokens[at]?.kind === \"op\" && (tokens[at] as { op: string }).op === \"not\") {\n at++;\n negations++;\n }\n const of = parseUnary();\n if (of === undefined) return undefined;\n return negations % 2 === 0 ? of : { kind: \"not\", of };\n }\n if (token.kind === \"open\") {\n at++;\n if (depth >= MAX_TEXT_DEPTH) return undefined;\n depth++;\n const inner = parseOr();\n depth--;\n if (tokens[at]?.kind === \"close\") at++;\n return inner.kind === \"all\" ? undefined : inner;\n }\n if (token.kind === \"close\") return undefined;\n if (token.kind === \"op\") {\n at++;\n return parseUnary();\n }\n at++;\n const term = toTerm(token.text);\n return term === undefined ? undefined : { kind: \"term\", term };\n };\n\n const parseAnd = (): Tree => {\n const parts: Tree[] = [];\n while (at < tokens.length) {\n const token = tokens[at];\n if (token === undefined || token.kind === \"close\") break;\n if (token.kind === \"op\" && token.op === \"or\") break;\n if (token.kind === \"op\" && token.op === \"and\") {\n at++;\n continue;\n }\n const before = at;\n const part = parseUnary();\n if (part !== undefined) parts.push(part);\n if (at === before) at++;\n }\n return parts.length === 0 ? { kind: \"all\" } : parts.length === 1 ? (parts[0] as Tree) : { kind: \"and\", parts };\n };\n\n const parseOr = (): Tree => {\n const parts: Tree[] = [parseAnd()];\n while (tokens[at]?.kind === \"op\" && (tokens[at] as { op: string }).op === \"or\") {\n at++;\n parts.push(parseAnd());\n }\n const real = parts.filter((part) => part.kind !== \"all\");\n if (real.length === 0) return { kind: \"all\" };\n return real.length === 1 ? (real[0] as Tree) : { kind: \"or\", parts: real };\n };\n\n // Stray closing brackets at the top level end `parseOr` early; keep going past them so\n // `a) b` still reads both terms.\n const parts: Tree[] = [];\n while (at < tokens.length) {\n const tree = parseOr();\n if (tree.kind !== \"all\") parts.push(tree);\n if (tokens[at]?.kind === \"close\") at++;\n }\n if (parts.length === 0) return { kind: \"all\" };\n return parts.length === 1 ? (parts[0] as Tree) : { kind: \"and\", parts };\n}\n\n/* ------------------------------------------------------------------------------------ */\n/* To JQL */\n/* ------------------------------------------------------------------------------------ */\n\n/** A query that matches nothing: an empty `$in`. What a half-typed set or an unreadable number means. */\nfunction nothing(key: string): LooseQuery {\n return { [key]: { $in: [] } };\n}\n\nfunction toQuery(tree: Tree, vocabulary: Vocabulary<never, object> | undefined, mode: \"vocabulary\" | \"any\"): LooseQuery {\n switch (tree.kind) {\n case \"all\":\n return {};\n case \"not\":\n return { $not: toQuery(tree.of, vocabulary, mode) };\n case \"and\":\n return { $and: tree.parts.map((part) => toQuery(part, vocabulary, mode)) };\n case \"or\":\n return { $or: tree.parts.map((part) => toQuery(part, vocabulary, mode)) };\n case \"term\": {\n const query = termQuery(tree.term, vocabulary, mode);\n return tree.term.negated ? { $not: query } : query;\n }\n }\n}\n\nconst PATH_NAME = /^[\\p{L}_][\\p{L}\\p{N}_-]*(?:\\.[\\p{L}\\p{N}_-]+)*$/u;\n\nfunction termQuery(term: Term, vocabulary: Vocabulary<never, object> | undefined, mode: \"vocabulary\" | \"any\"): LooseQuery {\n let field: VocabularyField<never> | undefined;\n let key: string | undefined;\n // `has:rule` asks about a field rather than a value, so its value *is* the field name.\n if (term.name !== undefined && term.name.toLowerCase() === EXISTS_TERM && term.values === undefined) {\n const named = existence(term.value, vocabulary, mode);\n if (named !== undefined) return named;\n }\n if (term.name !== undefined) {\n field = vocabulary?.lookup.get(term.name.toLowerCase());\n if (field !== undefined) key = field.name;\n else if (mode === \"any\" && PATH_NAME.test(term.name)) key = term.name;\n }\n if (key === undefined) {\n // A colon with an unknown name in front of it is not a field term: `foo:bar` searches\n // for the text `foo:bar`, and a set on an unknown name for what was typed.\n const text = term.name === undefined ? term.value : `${term.name}:${term.values === undefined ? term.value : term.values.join(\",\")}`;\n return freeText(text, vocabulary);\n }\n const kind: FieldKind = field?.kind ?? (term.values === undefined && EXPLICIT_COMPARISON.test(term.value) ? \"number\" : \"text\");\n const values = term.values ?? [term.value];\n // An empty set matches nothing rather than everything: `$in()` is half-typed, and a\n // filter that widens while somebody is still typing it is a filter that lies.\n if (values.length === 0) return nothing(key);\n switch (kind) {\n case \"text\":\n return { [key]: { $contains: single(values), $options: \"i\" } };\n case \"word\":\n return { [key]: { $word: single(values), $options: \"i\" } };\n case \"exact\":\n return values.length === 1 ? { [key]: { $eq: values[0], $options: \"i\" } } : { [key]: { $in: values, $options: \"i\" } };\n case \"boolean\": {\n const read = values.map(readBoolean).filter((value): value is boolean => value !== undefined);\n if (read.length === 0) return nothing(key);\n return read.length === 1 ? { [key]: read[0] } : { [key]: { $in: read } };\n }\n case \"number\":\n case \"date\": {\n if (term.values !== undefined) {\n const read = values.map((value) => readScalar(value, kind)).filter((value) => value !== undefined);\n return read.length === 0 ? nothing(key) : { [key]: { $in: read } };\n }\n const condition = comparison(term.value, kind);\n return condition === undefined ? nothing(key) : { [key]: condition };\n }\n }\n}\n\n/**\n * A comparison written out in full, on a field nothing is known about.\n *\n * Without a vocabulary every field reads as text, and `score:>70` would search for the\n * characters \">70\" — which nobody typing it means. An operator or a range with a number\n * on it is unambiguous, so it compares. A bare `70` stays text, because on an unknown\n * field it is as likely to be part of an identifier as a quantity.\n */\nexport const EXPLICIT_COMPARISON = /^(?:(?:>=|<=|>|<)[+-]?(?:\\d+\\.?\\d*|\\.\\d+)|[+-]?(?:\\d+\\.?\\d*|\\.\\d+)?\\.\\.[+-]?(?:\\d+\\.?\\d*|\\.\\d+)?)$/;\n\n/**\n * `has:<field>` — the field has a value.\n *\n * Returns nothing when the name is not a field here, so `has:something-else` falls through\n * and is searched for as text, the same as any other name the vocabulary does not know.\n */\nfunction existence(name: string, vocabulary: Vocabulary<never, object> | undefined, mode: \"vocabulary\" | \"any\"): LooseQuery | undefined {\n const field = vocabulary?.lookup.get(name.toLowerCase());\n if (field !== undefined) return { [field.name]: { $exists: true } };\n if (mode === \"any\" && PATH_NAME.test(name)) return { [name]: { $exists: true } };\n return undefined;\n}\n\nfunction single(values: readonly string[]): string | readonly string[] {\n return values.length === 1 ? (values[0] as string) : values;\n}\n\nfunction freeText(text: string, vocabulary: Vocabulary<never, object> | undefined): LooseQuery {\n if (vocabulary?.text !== undefined) return { $text: { $search: text, $fields: vocabulary.text } };\n return { $text: text };\n}\n\nconst TRUE_WORDS = new Set([\"true\", \"yes\", \"1\", \"on\"]);\nconst FALSE_WORDS = new Set([\"false\", \"no\", \"0\", \"off\"]);\n\nfunction readBoolean(value: string): boolean | undefined {\n const lower = value.toLowerCase();\n if (TRUE_WORDS.has(lower)) return true;\n if (FALSE_WORDS.has(lower)) return false;\n return undefined;\n}\n\nconst NUMBER = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:e[+-]?\\d+)?$/i;\n\n/**\n * A relative instant, written with the sign that says which way: `-1h` is an hour ago,\n * `+30m` is half an hour from now.\n *\n * The sign is required. A bare `1h` in a date field could as easily be part of an\n * identifier somebody is searching for, and a filter that quietly turned it into a moment\n * in time would be reading something into what was typed.\n */\nconst RELATIVE = /^([+-])(\\d+(?:ms|s|m|h|d|w))+$/;\n\nfunction readScalar(value: string, kind: \"number\" | \"date\"): number | { $date: string | { $ago: string } | { $ahead: string } } | undefined {\n const trimmed = value.trim();\n if (kind === \"number\") {\n if (!NUMBER.test(trimmed)) return undefined;\n const read = Number(trimmed);\n // `1e309` reads as Infinity, which is not a JSON number: the query would be one the\n // engine refuses and `JSON.stringify` turns into null, so a box could produce a filter\n // that could neither run nor be saved. A number nobody can write is a value nothing has.\n if (!Number.isFinite(read)) return undefined;\n // `-0` matches everything `0` matches, and writing it out as JSON turns it into `0`\n // anyway; normalising here keeps a saved query identical to the one that was typed.\n return read === 0 ? 0 : read;\n }\n if (trimmed.toLowerCase() === \"now\") return { $date: \"now\" };\n const relative = RELATIVE.exec(trimmed);\n if (relative !== null) {\n const span = trimmed.slice(1);\n // A duration the engine could not size is not one anybody typed on purpose, and\n // emitting it would hand the box a query that cannot run.\n if (parseDuration(span) === undefined) return undefined;\n return { $date: relative[1] === \"-\" ? { $ago: span } : { $ahead: span } };\n }\n return trimmed !== \"\" && !Number.isNaN(Date.parse(trimmed)) ? { $date: trimmed } : undefined;\n}\n\nconst COMPARISON = /^(>=|<=|>|<|=)?([\\s\\S]*)$/;\n\n/** `>70`, `>=70`, `<70`, `<=70`, `=70`, `70`, and the range `10..20` (both ends included). */\nfunction comparison(value: string, kind: \"number\" | \"date\"): Record<string, unknown> | undefined {\n const range = value.indexOf(\"..\");\n if (range !== -1) {\n const low = value.slice(0, range);\n const high = value.slice(range + 2);\n const from = low === \"\" ? undefined : readScalar(low, kind);\n const to = high === \"\" ? undefined : readScalar(high, kind);\n if ((low !== \"\" && from === undefined) || (high !== \"\" && to === undefined) || (from === undefined && to === undefined)) return undefined;\n return { ...(from === undefined ? {} : { $gte: from }), ...(to === undefined ? {} : { $lte: to }) };\n }\n const [, operator, rest] = COMPARISON.exec(value) as RegExpExecArray;\n const scalar = readScalar(rest as string, kind);\n if (scalar === undefined) return undefined;\n switch (operator) {\n case \">\":\n return { $gt: scalar };\n case \">=\":\n return { $gte: scalar };\n case \"<\":\n return { $lt: scalar };\n case \"<=\":\n return { $lte: scalar };\n default:\n return { $eq: scalar };\n }\n}\n","/**\n * Writing a value so the tokenizer reads it back whole.\n *\n * Shared by the writer and by completion, because both hand a value to somebody who will\n * feed it straight back to the parser. They disagreed once: `toText` quoted a value with a\n * space in it and `suggest` did not, so completing `status:` with `in progress` produced\n * `status:in progress` — which parses as `status:in` and a loose search word. A completion\n * that changes the query is worse than no completion at all, and one copy of this rule is\n * how the two stay honest.\n */\n\n/**\n * The value, quoted if it has to be — or `undefined` when the syntax cannot write it.\n *\n * `inSet` is for a value inside `$in(…)`, where a comma separates values and so has to be\n * quoted as well.\n */\nexport function quote(value: string, inSet: boolean): string | undefined {\n const plain = !/[\\s()\"'“”‘’]/.test(value) && !/^[-!$]/.test(value) && !(inSet && value.includes(\",\"));\n if (plain) return value;\n if (!value.includes('\"')) return `\"${value}\"`;\n if (!value.includes(\"'\")) return `'${value}'`;\n // The syntax has no escape inside a quoted run, so a value holding both kinds cannot be\n // written at all. Saying so is better than writing something that reads as less.\n return undefined;\n}\n","import { JqlError } from \"../errors.js\";\nimport { checkVocabulary, type Vocabulary } from \"../vocabulary.js\";\nimport { TEXT_OPERATORS } from \"./parse.js\";\nimport { quote } from \"./quote.js\";\n\n/**\n * What to offer for the token the caret is in.\n *\n * Returns the completions and the span they replace, so a caller can put one in without\n * disturbing the rest of the input. A token that already names a field with a known set of\n * values completes the value; anything else completes the field name. Every name offered\n * comes from the vocabulary the parser reads, so nothing offered is something the language\n * would not accept.\n *\n * The rule the whole module is written to: **what is offered, inserted, means what it\n * says.** A completion is text somebody will press Tab on without reading, so one that\n * parses into a different query is worse than no completion — the box looks as though it\n * filled itself in correctly and the result is wrong.\n */\nexport interface Suggestions {\n readonly options: readonly string[];\n readonly from: number;\n readonly to: number;\n}\n\n/** Anything completion needs that the vocabulary cannot know when it is written. */\nexport interface SuggestOptions {\n /**\n * Values seen at run time, by field name — the statuses actually in the table, the paths\n * actually in the log.\n *\n * A vocabulary's `values` is a *closed set*: what the field is allowed to hold, known\n * when the vocabulary is written. Plenty of fields have no such set and still have a\n * handful of values in practice, and a console that has just listed a thousand rows knows\n * them. Passing them here completes the field; leaving them out still offers nothing,\n * because guessing is inventing options rather than completing them.\n *\n * Declared values come first and the two are merged, so a field may have both. Names are\n * resolved through the vocabulary, so an alias works.\n */\n readonly values?: Readonly<Record<string, readonly string[]>> | undefined;\n}\n\n/**\n * The start of the token the caret is in.\n *\n * A replay of the parser's own tokenizer over the text before the caret, because the two\n * have to agree about where a token begins. Splitting on the last space — which is what\n * this did — puts the caret's token in the wrong place the moment a value holds one:\n * `status:\"in pro` looked like a fresh token `pro` starting after the space, so the span\n * offered to replace cut the input in half.\n */\nfunction tokenAt(before: string): number {\n let start = 0;\n let started = false;\n let quote: '\"' | \"'\" | undefined;\n let setQuote: '\"' | \"'\" | undefined;\n let depth = 0;\n // What the tokenizer has accumulated for this token, which decides whether a `'` is a\n // quote or the apostrophe in `don't`.\n let current = \"\";\n\n const begin = (at: number): void => {\n if (!started) {\n start = at;\n started = true;\n }\n };\n const flush = (): void => {\n started = false;\n current = \"\";\n };\n\n for (let i = 0; i < before.length; i++) {\n const character = before[i] as string;\n if (depth > 0) {\n current += character;\n if (setQuote !== undefined) {\n if (character === setQuote) setQuote = undefined;\n } else if (character === '\"' || character === \"'\") setQuote = character;\n else if (character === \"(\") depth++;\n else if (character === \")\") {\n depth--;\n if (depth === 0) flush();\n }\n continue;\n }\n if (quote !== undefined) {\n if (character === quote) quote = undefined;\n else current += character;\n continue;\n }\n if (character === '\"') {\n begin(i);\n quote = '\"';\n continue;\n }\n if (character === \"'\" && (current === \"\" || current === \"-\" || current === \"!\" || current.endsWith(\":\"))) {\n begin(i);\n quote = \"'\";\n continue;\n }\n if (character === \"(\") {\n if (/\\$(in|notin)$/i.test(current)) {\n current += character;\n depth = 1;\n continue;\n }\n flush();\n continue;\n }\n if (character === \")\") {\n flush();\n continue;\n }\n if (/\\s/.test(character)) {\n flush();\n continue;\n }\n begin(i);\n current += character;\n }\n return start;\n}\n\n/** The values to offer for one field: those it declares, then those the caller has seen. */\nfunction valuesFor(name: string, vocabulary: Vocabulary<never, object> | undefined, given: SuggestOptions[\"values\"]): readonly string[] | undefined {\n const field = vocabulary?.lookup.get(name);\n const declared = field?.values;\n // Looked up by the canonical name as well as by what was typed, so `{ values: { status:\n // … } }` still reaches the field when somebody typed one of its aliases.\n const seen = given?.[name] ?? (field === undefined ? undefined : given?.[field.name]);\n if (declared === undefined && seen === undefined) return undefined;\n const out: string[] = [];\n for (const value of [...(declared ?? []), ...(seen ?? [])]) if (!out.includes(value)) out.push(value);\n return out;\n}\n\nfunction checkGivenValues(values: SuggestOptions[\"values\"]): void {\n if (values === undefined) return;\n if (values === null || typeof values !== \"object\" || Array.isArray(values)) {\n throw new JqlError(\"takes an object of field names to lists of values\", \"options.values\");\n }\n for (const [name, list] of Object.entries(values)) {\n // Refused rather than skipped: a console that passes the wrong shape here would\n // otherwise get an empty list of completions and no way to tell that from a field\n // nobody has seen a value of yet.\n if (!Array.isArray(list) || list.some((value) => typeof value !== \"string\")) {\n throw new JqlError(\"takes a list of strings\", `options.values.${name}`);\n }\n }\n}\n\nexport function suggest(input: string, caret: number, vocabulary?: Vocabulary<never, object>, options?: SuggestOptions): Suggestions {\n checkVocabulary(vocabulary);\n checkGivenValues(options?.values);\n const to = Math.max(0, Math.min(caret, input.length));\n const before = input.slice(0, to);\n const start = tokenAt(before);\n const token = before.slice(start);\n const negated = token.startsWith(\"-\") || token.startsWith(\"!\");\n const body = negated ? token.slice(1) : token;\n const sign = negated ? (token[0] as string) : \"\";\n const none = { options: [], from: start, to };\n\n // A token that opens with a quote is a phrase, whatever is inside it. Offering field\n // names there would complete `\"sta` to `\"status:`, which is a search for the text\n // \"status:\" and not the field at all.\n if (body.startsWith('\"') || body.startsWith(\"'\")) return none;\n\n const colon = body.indexOf(\":\");\n if (colon === -1) {\n const partial = body.toLowerCase();\n // A token that has begun with `$` can only be an operator; no field name starts with one.\n if (partial.startsWith(\"$\")) return { options: TEXT_OPERATORS.filter((name) => name.startsWith(partial)), from: start, to };\n const names = vocabulary?.names ?? [];\n return { options: names.filter((name) => name.startsWith(partial)).map((name) => `${sign}${name}:`), from: start, to };\n }\n\n const name = body.slice(0, colon).toLowerCase();\n const rest = body.slice(colon + 1);\n const prefix = `${sign}${name}:`;\n const values = valuesFor(name, vocabulary, options?.values);\n\n // Inside `$in(…)`: complete the value after the last comma, and leave everything before\n // it exactly as typed so the values already chosen survive.\n const set = /^\\$(in|notin)\\(/i.exec(rest);\n if (set !== null) {\n if (values === undefined) return none;\n const opener = set[0];\n const inside = rest.slice(opener.length);\n const comma = inside.lastIndexOf(\",\");\n const kept = comma === -1 ? \"\" : inside.slice(0, comma + 1);\n const typed = comma === -1 ? inside : inside.slice(comma + 1);\n const partial = typed.trimStart();\n const spacing = typed.slice(0, typed.length - partial.length);\n return { options: offer(values, partial, true, (written) => `${prefix}${opener}${kept}${spacing}${written}`), from: start, to };\n }\n\n // The set forms come first, because a field with a known set is exactly the field\n // somebody wants two of.\n const forms = rest.startsWith(\"$\") ? [\"$in(\", \"$notin(\"].filter((form) => form.startsWith(rest)).map((form) => `${prefix}${form}`) : [];\n if (values === undefined) return { options: forms, from: start, to };\n return { options: [...forms, ...offer(values, unopened(rest), false, (written) => `${prefix}${written}`)], from: start, to };\n}\n\n/**\n * What the caret is in the middle of typing, with a quote it has opened taken off.\n *\n * The parser strips those quotes before it reads the value, so `\"in pro` is a partial\n * `in pro` — and matching against the quote as though it were part of the value is why a\n * box stopped offering anything the moment somebody opened one.\n */\nfunction unopened(rest: string): string {\n const first = rest[0];\n if (first !== '\"' && first !== \"'\") return rest;\n const body = rest.slice(1);\n return body.endsWith(first) ? body.slice(0, -1) : body;\n}\n\n/** The values that continue what has been typed, each written so the parser reads it back. */\nfunction offer(values: readonly string[], partial: string, inSet: boolean, write: (written: string) => string): string[] {\n const wanted = partial.toLowerCase();\n const out: string[] = [];\n for (const value of values) {\n if (!value.toLowerCase().startsWith(wanted)) continue;\n const written = quote(value, inSet);\n // A value holding both kinds of quote has no spelling in this syntax. Offering it\n // unquoted would complete the box with something that parses as something else.\n if (written !== undefined) out.push(write(written));\n }\n return out;\n}\n","import { checkVocabulary, type FieldKind, type Vocabulary } from \"../vocabulary.js\";\nimport { quote } from \"./quote.js\";\nimport { EXISTS_TERM, EXPLICIT_COMPARISON, SET_TERM, type TextOptions } from \"./parse.js\";\n\n/**\n * A query, written back as something somebody can type.\n *\n * A dashboard that stores filters as JSON still has to put one in a search box when\n * somebody opens it to edit. That is this, and it is deliberately **not** total: the text\n * syntax has no spelling for `$elemMatch`, `$size`, `$glob` or a `{ \"$field\": … }`\n * reference, and inventing one per operator would turn a box people can type into a\n * language they have to learn.\n *\n * So the honest answer is two things: the text, and what was left out of it. **The text is\n * exact for what it says** — parsed back with the same vocabulary it means precisely the\n * clauses it carries, which the tests hold it to — but a caller that ignores `unexpressed`\n * is showing somebody a filter wider than the one that is running. `complete` is there so\n * that check is one line.\n */\n\nexport interface Unexpressed {\n /** Where the clause is in the query: `$or[1].tags`. */\n readonly at: string;\n /** The clause itself, as it was written. */\n readonly clause: unknown;\n /** Why the text cannot say it. */\n readonly why: string;\n}\n\nexport interface TextForm {\n /** The query as text. Parsing it back gives exactly the clauses it carries. */\n readonly text: string;\n /** True when the text says everything the query does. */\n readonly complete: boolean;\n /** The clauses with no spelling in the text syntax, in the order they were met. */\n readonly unexpressed: readonly Unexpressed[];\n}\n\n/** The operators a condition may hold that the text syntax can say, per field kind. */\nconst SAYABLE: Readonly<Record<FieldKind, readonly string[]>> = {\n text: [\"$contains\", \"$exists\"],\n word: [\"$word\", \"$exists\"],\n exact: [\"$eq\", \"$in\", \"$exists\"],\n number: [\"$eq\", \"$gt\", \"$gte\", \"$lt\", \"$lte\", \"$in\", \"$exists\"],\n date: [\"$eq\", \"$gt\", \"$gte\", \"$lt\", \"$lte\", \"$in\", \"$exists\"],\n boolean: [\"$eq\", \"$in\", \"$exists\"],\n};\n\nconst PATH_NAME = /^[\\p{L}_][\\p{L}\\p{N}_-]*(?:\\.[\\p{L}\\p{N}_-]+)*$/u;\n\n/** The comparisons a field with no vocabulary entry can carry: the ones the parser infers back. */\nconst INFERRED = [\"$gt\", \"$gte\", \"$lt\", \"$lte\"];\n\nfunction inferKind(condition: Record<string, unknown>): FieldKind {\n const operators = Object.keys(condition).filter((operator) => operator !== \"$options\");\n const numeric = operators.length > 0 && operators.every((operator) => INFERRED.includes(operator) && typeof condition[operator] === \"number\" && Number.isFinite(condition[operator]));\n return numeric ? \"number\" : \"text\";\n}\n\n/** Writes a query as search-box text, and says what it could not write. */\nexport function toText(query: unknown, options: TextOptions = {}): TextForm {\n const vocabulary = checkVocabulary(options.vocabulary);\n const mode = options.fields ?? (vocabulary === undefined ? \"any\" : \"vocabulary\");\n const left: Unexpressed[] = [];\n const text = writeQuery(query, { vocabulary, mode, left }, \"\", false);\n return { text, complete: left.length === 0, unexpressed: left };\n}\n\ninterface Writing {\n readonly vocabulary: Vocabulary<never, object> | undefined;\n readonly mode: \"vocabulary\" | \"any\";\n readonly left: Unexpressed[];\n}\n\nfunction drop(writing: Writing, at: string, clause: unknown, why: string): \"\" {\n writing.left.push({ at, clause, why });\n return \"\";\n}\n\n/**\n * One query, as terms joined by juxtaposition — which is what `$and` means in the text.\n *\n * `grouped` says whether the caller will put this inside something tighter than an `$and`,\n * in which case an `$or` has to be bracketed to keep its meaning.\n */\nfunction writeQuery(query: unknown, writing: Writing, at: string, grouped: boolean): string {\n if (query === null || typeof query !== \"object\" || Array.isArray(query)) {\n return drop(writing, at, query, \"only an object is a query, and the text syntax writes nothing else\");\n }\n const clauses: string[] = [];\n for (const [key, value] of Object.entries(query as Record<string, unknown>)) {\n const here = at === \"\" ? key : `${at}.${key}`;\n const written = writeClause(key, value, writing, here, grouped);\n if (written !== \"\") clauses.push(written);\n }\n if (clauses.length === 0) return \"\";\n const joined = clauses.join(\" \");\n return grouped && clauses.length > 1 ? `(${joined})` : joined;\n}\n\nfunction writeClause(key: string, value: unknown, writing: Writing, at: string, grouped: boolean): string {\n switch (key) {\n case \"$comment\":\n // A note is not part of what the query asks, so losing it loses nothing.\n return \"\";\n case \"$and\": {\n if (!Array.isArray(value)) return drop(writing, at, value, \"$and takes a list of queries\");\n const parts = value.map((part, index) => writeQuery(part, writing, `${at}[${index}]`, true)).filter((part) => part !== \"\");\n const joined = parts.join(\" \");\n // Several terms are several clauses. Handed back unbracketed to a caller expecting\n // one — a `$not` — only the first was negated: `$not ((a $or b) c)` came out as\n // `$not (a $or b) c`, which is a different question.\n return grouped && parts.length > 1 ? `(${joined})` : joined;\n }\n case \"$or\": {\n if (!Array.isArray(value)) return drop(writing, at, value, \"$or takes a list of queries\");\n // An `$or` of nothing matches nothing, and the text syntax has no term for that: it\n // was written as `()`, which reads back as an empty query — everything. A filter that\n // widened from nothing to everything, and called itself complete while doing it.\n if (value.length === 0) return drop(writing, at, value, \"an $or of nothing matches nothing, and no term says that\");\n const parts = value.map((part, index) => writeQuery(part, writing, `${at}[${index}]`, true));\n // A branch that cannot be written would widen the whole `$or`, so none of it is said.\n if (parts.some((part) => part === \"\")) return drop(writing, at, value, \"one branch of the $or has no spelling, and writing the others would widen it\");\n return parts.length === 1 ? (parts[0] as string) : `(${parts.join(\" $or \")})`;\n }\n case \"$nor\": {\n if (!Array.isArray(value) || value.length === 0) return drop(writing, at, value, \"$nor takes a list of queries\");\n const parts = value.map((part, index) => writeQuery(part, writing, `${at}[${index}]`, true));\n if (parts.some((part) => part === \"\")) return drop(writing, at, value, \"one branch of the $nor has no spelling\");\n return `$not (${parts.join(\" $or \")})`;\n }\n case \"$not\":\n return writeNot(value, writing, at);\n case \"$text\":\n return writeText(value, writing, at);\n default:\n if (key.startsWith(\"$\")) return drop(writing, at, value, `\"${key}\" is a query operator the text syntax cannot say`);\n return writeField(key, value, writing, at, false);\n }\n}\n\n/** `$not` is a leading `-` on one term, and `$not ( … )` on anything larger. */\nfunction writeNot(value: unknown, writing: Writing, at: string): string {\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n const keys = Object.keys(value as Record<string, unknown>);\n // A negated single field is `-term`, and a negated set is `$notin(…)`.\n if (keys.length === 1) {\n const key = keys[0] as string;\n if (!key.startsWith(\"$\")) return writeField(key, (value as Record<string, unknown>)[key], writing, `${at}.${key}`, true);\n }\n }\n // What was already unsayable inside it, before this writes anything: a `$not` whose\n // contents were dropped is reported by that drop, and leaving the negation out is the\n // conservative reading the contract asks for.\n const reported = writing.left.length;\n const inner = writeQuery(value, writing, at, true);\n if (inner === \"\") {\n // Nothing written and nothing reported means the negation held only things that say\n // nothing — an empty query, or a comment. `$not {}` matches *nothing*, and the empty\n // text matches everything, so staying quiet here turned the narrowest query there is\n // into the widest one and still called the form complete.\n if (writing.left.length === reported) return drop(writing, at, value, \"$not of a query that asks nothing matches nothing, and no term says that\");\n return \"\";\n }\n return inner.startsWith(\"(\") ? `$not ${inner}` : `$not (${inner})`;\n}\n\nfunction writeText(value: unknown, writing: Writing, at: string): string {\n const search = typeof value === \"string\" ? { $search: value } : (value as Record<string, unknown> | null);\n if (search === null || typeof search !== \"object\" || typeof search.$search !== \"string\") {\n return drop(writing, at, value, \"a text search is a phrase or { $search: … }\");\n }\n if (search.$caseSensitive === true) return drop(writing, at, value, \"a bare word in the text syntax always ignores case\");\n if (search.$fields !== undefined) {\n const fields = search.$fields;\n const same =\n Array.isArray(fields) &&\n writing.vocabulary?.text !== undefined &&\n fields.length === writing.vocabulary.text.length &&\n fields.every((name, index) => name === (writing.vocabulary?.text as readonly string[])[index]);\n // A bare word searches the vocabulary's own text fields; any other list is a question\n // the box cannot ask.\n if (!same) return drop(writing, at, value, \"a bare word searches the vocabulary's text fields, not a list of its own\");\n }\n if (search.$search === \"\") return drop(writing, at, value, \"an empty search is not a term anybody can type\");\n // Quoting cannot save a bare word that begins with a dash, or one that *is* an operator:\n // the parser strips the quotes before it decides what the word is, so `\"-a\"` would be\n // read back as a negated `a` and `\"$or\"` as an operator. A field term is safe — the\n // decision there is made on the whole word, which starts with the field's name.\n if (/^[-!]/.test(search.$search)) return drop(writing, at, value, \"a bare word cannot begin with a dash: quoted or not, the parser reads that as a negation\");\n if (/^\\$(and|or|not)$/i.test(search.$search)) return drop(writing, at, value, \"a bare word cannot be an operator's name: quoted or not, the parser reads it as the operator\");\n const quoted = quote(search.$search, false);\n return quoted ?? drop(writing, at, value, \"the phrase holds both kinds of quote, and the syntax has no escape for either\");\n}\n\n/** One field, as `name:value`, `-name:value`, `name:$in(…)` or `has:name`. */\nfunction writeField(name: string, value: unknown, writing: Writing, at: string, negated: boolean): string {\n const field = writing.vocabulary?.lookup.get(name.toLowerCase());\n if (field === undefined && (writing.mode === \"vocabulary\" || !PATH_NAME.test(name))) {\n return drop(writing, at, { [name]: value }, writing.mode === \"vocabulary\" ? `\"${name}\" is not a field of this vocabulary, so the text would search for it as words` : `\"${name}\" cannot be written before a colon`);\n }\n const key = field?.name ?? name;\n if (key.toLowerCase() === EXISTS_TERM) {\n return drop(writing, at, { [name]: value }, `\"${key}\" is how the syntax asks whether a field is set, so a field of that name cannot be written`);\n }\n const condition = value !== null && typeof value === \"object\" && !Array.isArray(value) ? (value as Record<string, unknown>) : { $eq: value };\n // Without a vocabulary the parser reads a value by its shape, so the writer has to reach\n // the same conclusion: an explicit comparison against a number is a number, and\n // everything else is text. Writing `x:30` for `{ x: { $eq: 30 } }` would read back as the\n // characters \"30\" — narrower than it looks, and wrong.\n const inferred = field === undefined;\n const kind: FieldKind = field?.kind ?? inferKind(condition);\n const operators = Object.keys(condition).filter((operator) => operator !== \"$options\");\n if (operators.length === 0 || !operators.every((operator) => operator.startsWith(\"$\"))) {\n return drop(writing, at, { [name]: value }, \"the value mixes operators with fields, or holds none\");\n }\n const sayable = SAYABLE[kind];\n // `10..20` is what somebody typed, and what the box reads back most naturally; written as\n // two terms it means the same thing but no longer looks like the range it is.\n const range = writeRange(key, kind, condition, operators, negated);\n if (range !== undefined) return range;\n const terms: string[] = [];\n for (const operator of operators) {\n const term = writeOperator(key, kind, operator, condition, writing, at, negated, sayable, inferred);\n if (term === \"\") return \"\";\n terms.push(term);\n }\n // Several operators on one field are several terms, which is what juxtaposition means —\n // except under a negation, where `-a -b` would mean neither rather than not both.\n if (terms.length > 1 && negated) return drop(writing, at, { [name]: value }, \"a negated field with several operators would have to be written as $not ( … ), which changes what a set means\");\n return terms.join(\" \");\n}\n\n/** `field:a..b`, when the condition is exactly the two ends of one. */\nfunction writeRange(key: string, kind: FieldKind, condition: Record<string, unknown>, operators: readonly string[], negated: boolean): string | undefined {\n if (negated || (kind !== \"number\" && kind !== \"date\")) return undefined;\n if (operators.length !== 2 || !operators.includes(\"$gte\") || !operators.includes(\"$lte\")) return undefined;\n const low = writeValue(condition.$gte, kind, \"$eq\", false, false);\n const high = writeValue(condition.$lte, kind, \"$eq\", false, false);\n if (low === undefined || high === undefined) return undefined;\n return `${key}:${low}..${high}`;\n}\n\nfunction writeOperator(\n key: string,\n kind: FieldKind,\n operator: string,\n condition: Record<string, unknown>,\n writing: Writing,\n at: string,\n negated: boolean,\n sayable: readonly string[],\n inferred: boolean,\n): string {\n const operand = condition[operator];\n const here = `${at}.${operator}`;\n const sign = negated ? \"-\" : \"\";\n if (!sayable.includes(operator)) return drop(writing, here, { [operator]: operand }, `\"${operator}\" has no spelling in the text syntax`);\n if (operator === \"$exists\") {\n if (operand !== true) return drop(writing, here, { [operator]: operand }, \"only $exists: true is written, as has:field; its negation is the leading dash\");\n return `${sign}has:${key}`;\n }\n // The box always matches text and names without regard to case, so a condition that does\n // care is one it cannot ask.\n const ignoresCase = condition.$options === \"i\";\n if ((kind === \"text\" || kind === \"word\" || kind === \"exact\") && !ignoresCase) {\n return drop(writing, here, condition, \"the text syntax always ignores case, and this condition does not\");\n }\n\n // A string operator holding a list is a set, and the box writes a set one way.\n const set = operator === \"$in\" || ((operator === \"$contains\" || operator === \"$word\") && Array.isArray(operand));\n const values = set ? operand : [operand];\n if (!Array.isArray(values)) return drop(writing, here, { [operator]: operand }, \"$in takes a list\");\n if (values.length === 0) return drop(writing, here, { [operator]: operand }, \"an empty set is not something anybody types\");\n const written: string[] = [];\n for (const value of values) {\n const one = writeValue(value, kind, operator, values.length > 1, inferred);\n if (one === undefined) return drop(writing, here, { [operator]: operand }, `${describeValue(value)} cannot be written after a colon`);\n written.push(one);\n }\n if (written.length > 1) return `${key}:${negated ? \"$notin\" : \"$in\"}(${written.join(\", \")})`;\n return `${sign}${key}:${written[0] as string}`;\n}\n\n/** A value as the box would take it, or `undefined` when it has no spelling. */\nfunction writeValue(value: unknown, kind: FieldKind, operator: string, inSet: boolean, inferred: boolean): string | undefined {\n if (kind === \"boolean\") return value === true ? \"true\" : value === false ? \"false\" : undefined;\n if (kind === \"number\") {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return undefined;\n return `${comparison(operator)}${String(value)}`;\n }\n if (kind === \"date\") {\n const instant = writeDate(value);\n return instant === undefined ? undefined : `${comparison(operator)}${instant}`;\n }\n if (typeof value !== \"string\" || value === \"\") return undefined;\n // The parser trims a value after the tokenizer has taken its quotes off, so whitespace at\n // either end is lost — and a value that is only whitespace disappears altogether, taking\n // the term with it and leaving a query that matches everything.\n if (value.trim() !== value) return undefined;\n // `$in(` and `$notin(` are read before quoting is considered, so a value beginning with\n // either is read as a set however it is written.\n if (SET_TERM.test(value)) return undefined;\n // On a field with no kind of its own, the parser reads an explicit comparison as a number,\n // so text that looks like one cannot be written as text.\n if (kind === \"text\" && inferred && EXPLICIT_COMPARISON.test(value)) return undefined;\n return quote(value, inSet);\n}\n\nfunction comparison(operator: string): string {\n switch (operator) {\n case \"$gt\":\n return \">\";\n case \"$gte\":\n return \">=\";\n case \"$lt\":\n return \"<\";\n case \"$lte\":\n return \"<=\";\n default:\n return \"\";\n }\n}\n\nfunction writeDate(value: unknown): string | undefined {\n if (value === null || typeof value !== \"object\") return undefined;\n const date = (value as { $date?: unknown }).$date;\n if (Object.keys(value as object).length !== 1) return undefined;\n if (typeof date === \"string\") return date === \"now\" ? \"now\" : /\\s/.test(date) ? undefined : date;\n if (date !== null && typeof date === \"object\") {\n const relative = date as { $ago?: unknown; $ahead?: unknown };\n if (typeof relative.$ago === \"string\") return `-${relative.$ago}`;\n if (typeof relative.$ahead === \"string\") return `+${relative.$ahead}`;\n }\n // Epoch milliseconds have no spelling: the box reads a bare number as text.\n return undefined;\n}\n\nfunction describeValue(value: unknown): string {\n if (value === null) return \"null\";\n if (Array.isArray(value)) return \"a list\";\n if (typeof value === \"object\") return \"an object\";\n return `${typeof value} ${JSON.stringify(value)}`;\n}\n"]}
|