@omgbase/oqx 0.10.2 โ 0.12.0
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 +162 -0
- package/README.md +130 -30
- package/dist/context.d.ts +18 -3
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +21 -9
- package/dist/context.js.map +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +80 -61
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/lexer.d.ts.map +1 -1
- package/dist/lexer.js +47 -21
- package/dist/lexer.js.map +1 -1
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +356 -163
- package/dist/parser.js.map +1 -1
- package/dist/regex.d.ts +19 -0
- package/dist/regex.d.ts.map +1 -0
- package/dist/regex.js +0 -0
- package/dist/regex.js.map +1 -0
- package/dist/semantics.d.ts +37 -9
- package/dist/semantics.d.ts.map +1 -1
- package/dist/semantics.js +138 -36
- package/dist/semantics.js.map +1 -1
- package/package.json +8 -7
- package/src/context.ts +34 -9
- package/src/engine.ts +81 -60
- package/src/index.ts +7 -1
- package/src/lexer.ts +44 -14
- package/src/parser.ts +340 -119
- package/src/regex.ts +0 -0
- package/src/semantics.ts +128 -31
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,168 @@ All notable changes to `@omgbase/oqx` are recorded here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow
|
|
5
5
|
[Semantic Versioning](https://semver.org/) (pre-1.0: a minor bump may break).
|
|
6
6
|
|
|
7
|
+
## [0.12.0] - 2026-09-25
|
|
8
|
+
|
|
9
|
+
**OQX is now a language with a specification and two implementations.** The
|
|
10
|
+
spec lives at `spec/oqx` in the monorepo: `GRAMMAR.md`, `SEMANTICS.md`, and
|
|
11
|
+
835 executable fixtures in 28 files that this package and the Rust
|
|
12
|
+
crate `oqx` both run. **Versioning changed accordingly:** the language version
|
|
13
|
+
is `spec/oqx/VERSION` (`0.12`) and every implementation's version is
|
|
14
|
+
`<language>.<patch>`, so `@omgbase/oqx 0.12.x` and the `oqx` crate `0.12.x`
|
|
15
|
+
both mean "the 0.12 language"; the patch digit is per implementation. The
|
|
16
|
+
package exports `LANGUAGE_VERSION`.
|
|
17
|
+
|
|
18
|
+
Everything below follows one principle, applied without exception: **least
|
|
19
|
+
surprise.** Where the reference behaved by JavaScript accident, it now does
|
|
20
|
+
what a careful user would predict.
|
|
21
|
+
|
|
22
|
+
### Changed (breaking) โ semantics
|
|
23
|
+
- **Identity is structural.** `distinct` over unprojected rows and `follow`
|
|
24
|
+
cycle detection/dedup use the `id` property when present, else the row's
|
|
25
|
+
structural value (deep equality, key order ignored). Previously identities
|
|
26
|
+
were stringified, so every id-less object collided as `[object Object]`
|
|
27
|
+
(`count distinct { }` over two different objects gave 1; `follow` over
|
|
28
|
+
id-less nodes marked every successor a cycle) and `1` equalled `"1"`.
|
|
29
|
+
- **No cross-type ordering.** `< <= > >=` and range coverage order only
|
|
30
|
+
number/number and string/string; every other pair, including booleans and
|
|
31
|
+
anything absent, is false. `1 < "2"` and `"3" in 1..5` were true.
|
|
32
|
+
- **Strings order and measure by Unicode code point**, not UTF-16 code unit:
|
|
33
|
+
`"๐".size()` is 1 and astral characters sort after the BMP.
|
|
34
|
+
- **Own enumerable properties only.** Property reads (`name`, `.name`,
|
|
35
|
+
`^name`), `has()`, `in` over an object, and `entries()` never see inherited
|
|
36
|
+
members (`has(toString)` is false). Arrays expose only their integer
|
|
37
|
+
indices โ `.length` is absent; use `size()`. Primitives have no properties.
|
|
38
|
+
- **Absent propagates.** Any arithmetic with an absent operand is absent,
|
|
39
|
+
including `"a" + missing` (was `"aundefined"`) and `null + 1` (was `1`).
|
|
40
|
+
`.lower()` / `.upper()` on absent are absent (were `"undefined"` /
|
|
41
|
+
`"NULL"`).
|
|
42
|
+
- **Regex is an OQX concern.** An invalid `matches()` pattern raises
|
|
43
|
+
`OqxError` (`eval`, `invalid regular expression`) instead of a raw
|
|
44
|
+
`SyntaxError`. Lookaround and backreferences are rejected (`not supported in
|
|
45
|
+
OQX`) so the dialect is the portable intersection.
|
|
46
|
+
- **Ranges never appear in results.** Projecting a range value is an error
|
|
47
|
+
(`a range โฆ cannot appear in a result`); no range covers an absent value,
|
|
48
|
+
however open.
|
|
49
|
+
- **`&&` and `||` evaluate strictly left to right** with short-circuit; the
|
|
50
|
+
engine no longer reorders conjuncts by cost, so `false && bogus()` never
|
|
51
|
+
errors and `true && bogus()` always does.
|
|
52
|
+
- **`single` reports the true row count** in its error.
|
|
53
|
+
- **`$ordinal` path components compare as values** (numbers numerically,
|
|
54
|
+
before strings), not as text: `[1, 9, 10]`, not `[1, 10, 9]`.
|
|
55
|
+
- **Bindings out of range** (`run(query, { values })` with fewer values than
|
|
56
|
+
the query references) raise `OqxError` instead of reading `undefined`.
|
|
57
|
+
|
|
58
|
+
### Changed (breaking) โ grammar
|
|
59
|
+
- **`!` has one precedence everywhere:** a prefix operator binding tighter
|
|
60
|
+
than comparison, applied to the operand right after it. `where !a == b` is
|
|
61
|
+
`(!a) == b` (it negated the whole comparison before); `!jobs exists { โฆ }`
|
|
62
|
+
and `!(a == b)` work as written.
|
|
63
|
+
- **Parenthesized scalars work in `where`:** `where (a + 1) > 2` was a parse
|
|
64
|
+
error; a group followed by an operator is a scalar.
|
|
65
|
+
- **`follow distinct` requires a relation** (`follow distinct { depth 2 }` no
|
|
66
|
+
longer treats `distinct` as the relation name); `follow ^rel` is a clear
|
|
67
|
+
error.
|
|
68
|
+
- **Open-ended ranges stop at clause words** (`in ..5 order by a`); a range
|
|
69
|
+
with no bound at all is an error.
|
|
70
|
+
- **Duplicate projection names are an error** (`a: 1, a: 2` last-wins is
|
|
71
|
+
gone), including a dotted default key colliding with an alias.
|
|
72
|
+
- **Malformed numerals are lex errors:** `1e`, `1e+`, `1.`, `.5`, `xs.0`.
|
|
73
|
+
`1..5`, `1...5`, `..5`, `1..`, `1.5..2.5` are unchanged.
|
|
74
|
+
- **Top-level `limit ^n` / `offset ^n`** are parse errors (`no enclosing
|
|
75
|
+
scope`); they were always absent and failed at run time.
|
|
76
|
+
- **`true` / `false` / `null` are literals in every position;** as a receiver
|
|
77
|
+
or follow relation they error instead of resolving a root by that name.
|
|
78
|
+
- **Lifts (`^name:`) outside a where-position `collect`** are parse errors
|
|
79
|
+
instead of silently doing nothing.
|
|
80
|
+
- **Chained comparisons** (`a == b == c`) error clearly; **stray tokens** after
|
|
81
|
+
a query or in a block get a located message; clause words without their
|
|
82
|
+
clause (`order age`, bare `follow`, `limit x`) say what they need.
|
|
83
|
+
|
|
84
|
+
### Changed (breaking) โ regular expressions
|
|
85
|
+
- **`matches()` compiles the OQX regex baseline, not a JavaScript `RegExp`.**
|
|
86
|
+
The baseline (SEMANTICS ยง11) is a fixed grammar โ literals and escaped
|
|
87
|
+
metacharacters, `\n \t \r \f \v`, `\uXXXX` / `\u{โฆ}`, the classes
|
|
88
|
+
`\d \D \w \W \s \S` with spec-fixed sets (`\d` = `[0-9]`, `\w` =
|
|
89
|
+
`[A-Za-z0-9_]`, `\s` = one listed set), `\b \B` over that `\w`, bracket
|
|
90
|
+
classes, `.`, `^ $`, the quantifiers and their lazy forms, `|`, `(โฆ)`,
|
|
91
|
+
`(?:โฆ)`, `(?<name>โฆ)` โ and the pattern is validated and rewritten before
|
|
92
|
+
`RegExp` sees it (`src/regex.ts`). **The line terminator is `\n` alone**
|
|
93
|
+
for `.` and for `m`-mode anchors (`\r`, U+2028, U+2029 are ordinary
|
|
94
|
+
characters), and `.` consumes a code point. Every construct outside the
|
|
95
|
+
grammar is an eval error naming it (`an inline flag (?i) is not supported in
|
|
96
|
+
OQX regular expressions`): lookaround and backreferences (already rejected),
|
|
97
|
+
now also inline flags `(?i)` / `(?i:โฆ)`, `\p{โฆ}`, `\x..`, `\c.`, octal
|
|
98
|
+
escapes, identity escapes of non-metacharacters, possessive quantifiers,
|
|
99
|
+
atomic and comment groups, `(?P<โฆ>)`, `\A \z \Z \G \K \Q \E`, POSIX and
|
|
100
|
+
nested classes, class set operations, `[\b]`. Malformed patterns that
|
|
101
|
+
`RegExp` tolerated (`a{`, a lone `]`, `a**`, `[]`, `[^]`, `(?<n>โฆ)` twice)
|
|
102
|
+
are `invalid regular expression`.
|
|
103
|
+
- **Flags are an explicit second argument**: `matches(pattern, flags)` with
|
|
104
|
+
`flags` a string of distinct letters from `i` (simple case folding, so `รฉ`
|
|
105
|
+
matches `ร`), `m`, `s`. Anything else is an eval error: `unknown regex
|
|
106
|
+
flag` (`"g"`, `"I"`, a non-string) or `duplicate regex flag`. There is no
|
|
107
|
+
inline flag syntax.
|
|
108
|
+
- **Engine-native dialects are a host opt-in, not query syntax.**
|
|
109
|
+
`DataContext` gains an optional `regexDialect: "oqx" | "native"` (default
|
|
110
|
+
`"oqx"`); `new DefaultContext(roots, { regexDialect: "native" })` hands
|
|
111
|
+
patterns to `RegExp` unvalidated with the `u` flag plus the given flags โ
|
|
112
|
+
implementation-defined, not portable, untested by the spec. `DefaultContext`
|
|
113
|
+
answers `matches` itself so it can read the dialect; `BUILTIN_METHODS.matches`
|
|
114
|
+
stays the baseline, and `semantics.regexMatches(recv, args, dialect)` is the
|
|
115
|
+
helper for custom contexts. `compileRegex(pattern, flags?, dialect?)` and the
|
|
116
|
+
`RegexDialect` / `RegexFlags` types are exported.
|
|
117
|
+
- Fixtures: the `matches` cases moved from `strings.json` to a new
|
|
118
|
+
`regex.json` (21 moved, 98 added), pinning each baseline construct, the
|
|
119
|
+
`\n`-only line terminator, ASCII `\d \w \b`, the `\s` set, code-point `.`,
|
|
120
|
+
flags, and one rejection per construct.
|
|
121
|
+
|
|
122
|
+
### Documentation
|
|
123
|
+
- Integer-like object keys enumerate first in JavaScript before OQX sees the
|
|
124
|
+
object; this is a host fact the reference cannot undo, and fixtures must not
|
|
125
|
+
depend on the relative order of integer-like and other keys.
|
|
126
|
+
|
|
127
|
+
## [0.11.0] - 2026-09-24
|
|
128
|
+
|
|
129
|
+
### Changed (breaking)
|
|
130
|
+
- **Clause order is fixed** (omgbase ADR-020). Within one clause body โ the
|
|
131
|
+
top level or any consumer block โ clauses appear at most once each, in
|
|
132
|
+
exactly this order: `select โฆ from โฆ where โฆ follow โฆ order by โฆ limit N
|
|
133
|
+
offset N`. Every clause is optional except a top-level `from` (the
|
|
134
|
+
`<receiver> <consumer> { โฆ }` form supplies its own source). A clause out
|
|
135
|
+
of order is a parse error that names the order (`` `select` must come
|
|
136
|
+
before `from` โ OQX clause order is select, from, where, follow, order by,
|
|
137
|
+
limit, offset ``); a second `from` in one body is a duplicate. The
|
|
138
|
+
order-flexible grammar (`from ${people} select name where โฆ`, `limit 1 name
|
|
139
|
+
from โฆ`, `offset 1 limit 1`) no longer parses.
|
|
140
|
+
- **Only `select` may drop its keyword, and only when it is the first clause
|
|
141
|
+
written** (`name, age from people`). Every other clause always carries its
|
|
142
|
+
keyword, so a predicate is never implicit: the `looksLikePredicate` shape
|
|
143
|
+
heuristic is gone. **A block now needs `where`** โ `jobs exists { where
|
|
144
|
+
!end }` โ and a bare comparison in leading position (`exists { age > 50 }`,
|
|
145
|
+
`age > 50 from people`) is a parse error that points at `where`. A bare name
|
|
146
|
+
in leading position projects, as before (`count { active }` selects
|
|
147
|
+
`active`).
|
|
148
|
+
- **The `from docs count` footgun is closed.** A bare run after `from` is an
|
|
149
|
+
error; `from people count` fails at `count` with a hint โ write
|
|
150
|
+
`people count { โฆ }` for the whole-query consumer, or `select count from โฆ`
|
|
151
|
+
to project a field named `count`. (Previously it silently projected the
|
|
152
|
+
field.)
|
|
153
|
+
|
|
154
|
+
### Added
|
|
155
|
+
- **`where` may reference the same body's `select` aliases.** Implemented as a
|
|
156
|
+
compile-time inline rewrite (not a second execution pass): after a body is
|
|
157
|
+
parsed, each bare identifier in its `where` that names an alias is replaced
|
|
158
|
+
by the alias's expression, so the engine and any pushdown planner see an
|
|
159
|
+
ordinary predicate. An alias shadows a same-named row field inside `where`;
|
|
160
|
+
an alias's own name inside its own expression is still the field
|
|
161
|
+
(`name: name.upper()` is not recursive); a chain of aliases that returns to
|
|
162
|
+
one being resolved (`a: b, b: a โฆ where a`) is a parse error; an alias whose
|
|
163
|
+
value is a `collect`/`first`/`single { โฆ }` block may stand alone as a
|
|
164
|
+
where leaf (non-empty test) but not inside an expression. Each body rewrites
|
|
165
|
+
only against its own `select` (nested blocks and `follow` blocks are their
|
|
166
|
+
own scopes); `^name` is never an alias. `order by` is unchanged โ it reads
|
|
167
|
+
row fields, not aliases.
|
|
168
|
+
|
|
7
169
|
## [0.10.2] - 2026-09-23
|
|
8
170
|
|
|
9
171
|
Moved into the omgbase monorepo (`packages/oqx`, via `git subtree` โ full
|
package/README.md
CHANGED
|
@@ -13,6 +13,10 @@ JavaScript tagged template.
|
|
|
13
13
|
> is published independently under its own version line and has **zero runtime
|
|
14
14
|
> dependencies** โ it is usable without omgbase, and omgbase code is never
|
|
15
15
|
> imported here (omgbase binds it from the outside via the `DataContext` seam).
|
|
16
|
+
> OQX is a language with more than one implementation; the specification is
|
|
17
|
+
> [`spec/oqx`](https://github.com/omgbase/omgbase/tree/main/spec/oqx). The
|
|
18
|
+
> language version is the package version's `major.minor` (`LANGUAGE_VERSION`,
|
|
19
|
+
> `"0.12"`); the patch digit is this implementation's own.
|
|
16
20
|
> Requirements: Node โฅ 22.13 for `@omgbase/oqx/sqlite`; Node โฅ 22.18 to run the
|
|
17
21
|
> test suite (see [Requirements](#requirements)).
|
|
18
22
|
|
|
@@ -30,7 +34,7 @@ const company = "Globocorp";
|
|
|
30
34
|
const employees = oqx`
|
|
31
35
|
name, id, title
|
|
32
36
|
from ${people}
|
|
33
|
-
where jobs exists { employer == ${company} && !end_date }
|
|
37
|
+
where jobs exists { where employer == ${company} && !end_date }
|
|
34
38
|
`;
|
|
35
39
|
// โ [{ name: "Bob", id: 124, title: "Engineer" }, โฆ] (current Globocorp employees)
|
|
36
40
|
```
|
|
@@ -46,18 +50,30 @@ template's identity and re-runs with fresh bindings each call.
|
|
|
46
50
|
|
|
47
51
|
## Language tutorial
|
|
48
52
|
|
|
49
|
-
A query
|
|
50
|
-
|
|
51
|
-
`from`, whichever reads better:
|
|
53
|
+
A query is a list of clauses in a **fixed order**. Each clause appears at most
|
|
54
|
+
once, and every one is optional except `from` at the top level:
|
|
52
55
|
|
|
53
56
|
```
|
|
54
|
-
[ [select] projection ] name, id, title: label
|
|
57
|
+
[ [select] projection ] name, id, title: label (or: select distinct โฆ, โฆ values)
|
|
55
58
|
from <collection> from ${people}
|
|
56
|
-
[ where <predicate> ] where age >= 18 && jobs exists { !end }
|
|
57
|
-
[ order by <expr> โฆ ] order by age desc, name
|
|
59
|
+
[ where <predicate> ] where age >= 18 && jobs exists { where !end }
|
|
58
60
|
[ follow <relation> โฆ ] follow children { depth 4 }
|
|
61
|
+
[ order by <expr> โฆ ] order by age desc, name
|
|
62
|
+
[ limit N ] limit 10
|
|
63
|
+
[ offset N ] offset 20
|
|
59
64
|
```
|
|
60
65
|
|
|
66
|
+
**`select` is the only keyword you may drop, and only when the projection comes
|
|
67
|
+
first** (`name, id from ${people}`). Every other clause always carries its
|
|
68
|
+
keyword โ in particular a predicate is never implicit, so a block filters with
|
|
69
|
+
`where` (`jobs exists { where !end }`), and `from ${people} count` is an error
|
|
70
|
+
rather than a projection of a field called `count`. Writing a clause out of
|
|
71
|
+
order is a parse error that names the order (`` `select` must come before
|
|
72
|
+
`from` โ OQX clause order is select, from, where, follow, order by, limit,
|
|
73
|
+
offset ``). The same body grammar applies inside every consumer block
|
|
74
|
+
(`collect { โฆ }`, `exists { โฆ }`, โฆ), where `from` is optional because the
|
|
75
|
+
receiver supplies the rows.
|
|
76
|
+
|
|
61
77
|
The examples below all use this dataset:
|
|
62
78
|
|
|
63
79
|
```js
|
|
@@ -113,8 +129,12 @@ An item that is not a plain navigation โ a call, arithmetic, a comparison โ
|
|
|
113
129
|
no natural key, so it must be aliased (`n: size(jobs)`), unless the projection is
|
|
114
130
|
in `values` mode (next).
|
|
115
131
|
|
|
116
|
-
The `select` keyword
|
|
117
|
-
is identical to `name from
|
|
132
|
+
The `select` keyword may be dropped when the projection is the first clause โ
|
|
133
|
+
`select name from โฆ` is identical to `name from โฆ`. The keyword form hosts
|
|
134
|
+
`select distinct` (ยง6), and is the only way to write a projection whose first
|
|
135
|
+
item would otherwise be misread (there is no other keyword-less clause). The
|
|
136
|
+
projection always comes *before* `from`: `from ${people} select name` is an
|
|
137
|
+
ordering error.
|
|
118
138
|
|
|
119
139
|
**`values` โ scalar projection.** Ordinarily every row projects to a record. Add
|
|
120
140
|
`values` after a projection of exactly **one** item to get the value itself:
|
|
@@ -182,8 +202,9 @@ ask for one. As a plain value (not a source) `entries(x)` is an array of
|
|
|
182
202
|
|
|
183
203
|
`where` filters rows. The predicate language has comparisons (`== != < <= > >=`),
|
|
184
204
|
boolean operators (`&& || !`) with grouping `( )`, membership (`in`), arithmetic
|
|
185
|
-
(`+ - * / %`), and bare truthiness. The `where` keyword is
|
|
186
|
-
leading expression is
|
|
205
|
+
(`+ - * / %`), and bare truthiness. The `where` keyword is always written โ a
|
|
206
|
+
leading expression without it is a projection, and a bare comparison in that
|
|
207
|
+
position is an error that points you at `where`.
|
|
187
208
|
|
|
188
209
|
```js
|
|
189
210
|
const min = 40;
|
|
@@ -231,6 +252,25 @@ non-range string yields an absent range, so `x in range(bad)` is just false.
|
|
|
231
252
|
**Interpolations are always values, never syntax.** `where name == ${x}` compares
|
|
232
253
|
against the value of `x`; a string in `x` can't inject operators or identifiers.
|
|
233
254
|
|
|
255
|
+
**`where` sees the `select` aliases.** A name defined in the same body's
|
|
256
|
+
projection may be used in its `where`; an alias shadows a same-named field
|
|
257
|
+
there. It is a compile-time rewrite โ the alias's expression is substituted
|
|
258
|
+
inline โ so it costs nothing at run time and a storage planner still sees an
|
|
259
|
+
ordinary predicate:
|
|
260
|
+
|
|
261
|
+
```js
|
|
262
|
+
oqx`select name, adult: age >= 18 from ${people} where adult`; // โก where age >= 18
|
|
263
|
+
oqx`select name, active: age > 50 from ${people} where active`; // the ALIAS, not the field โ Alice
|
|
264
|
+
oqx`select name, current: jobs collect { employer where !end } from ${people} where current`;
|
|
265
|
+
// a collect alias in predicate position means "non-empty" โ Bob, Carol
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Inside an alias's own expression its name is still the field
|
|
269
|
+
(`name: name.upper()` is not recursive); a chain of aliases that comes back to
|
|
270
|
+
itself (`a: b, b: a โฆ where a`) is a parse error. Each block rewrites only
|
|
271
|
+
against its *own* `select`; `^name` always reads an enclosing row's field, never
|
|
272
|
+
an alias. `order by` is not rewritten โ it reads row fields (ยง8).
|
|
273
|
+
|
|
234
274
|
**Scoping: bare names are local, `^` reaches out.** A bare identifier resolves
|
|
235
275
|
against the **current row only**. If the row lacks that property the value is
|
|
236
276
|
absent โ it never falls through to an enclosing row. To correlate with an
|
|
@@ -242,10 +282,10 @@ const accounts = [
|
|
|
242
282
|
{ owner: "x", budget: 100, orders: [{ amount: 50 }, { amount: 150 }] },
|
|
243
283
|
{ owner: "y", budget: 200, orders: [{ amount: 250 }] },
|
|
244
284
|
];
|
|
245
|
-
oqx`owner from ${accounts} where orders exists { amount > ^budget }`;
|
|
285
|
+
oqx`owner from ${accounts} where orders exists { where amount > ^budget }`;
|
|
246
286
|
// [{ owner: "x" }, { owner: "y" }] โ `^budget` is the enclosing account's budget
|
|
247
287
|
|
|
248
|
-
oqx`owner from ${accounts} where orders exists { amount > budget }`;
|
|
288
|
+
oqx`owner from ${accounts} where orders exists { where amount > budget }`;
|
|
249
289
|
// [] โ a bare `budget` is the ORDER's own budget: absent, so `>` is false
|
|
250
290
|
```
|
|
251
291
|
|
|
@@ -311,13 +351,56 @@ oqx`name from ${people} where tags.contains("admin")`; // array membership
|
|
|
311
351
|
- `.contains(v)` works on strings (substring) **and arrays** (an element equal
|
|
312
352
|
to `v` under OQX's strict equality); on anything else it is false.
|
|
313
353
|
- `.size()` / `size(x)` is the length of a string or array, the key count of
|
|
314
|
-
an object, and 0 for absent
|
|
315
|
-
|
|
354
|
+
an object, and 0 for absent.
|
|
355
|
+
- `.matches(re, flags?)` searches the receiver's text for a regular expression
|
|
356
|
+
written in the **OQX regex baseline** (below), unanchored unless the pattern
|
|
357
|
+
anchors. `flags` is an optional string of `i` (case-insensitive), `m` (`^`/`$`
|
|
358
|
+
also at newlines), `s` (`.` also matches `\n`); an absent receiver is `false`.
|
|
316
359
|
|
|
317
360
|
Anything not in these tables is an **eval error** (`unknown function 'f(โฆ)'` /
|
|
318
361
|
`unknown method '.m(โฆ)'`) โ see [custom functions](#custom-functions-and-methods)
|
|
319
362
|
for adding your own.
|
|
320
363
|
|
|
364
|
+
#### The regex baseline
|
|
365
|
+
|
|
366
|
+
OQX is a language with more than one implementation, so `matches()` does not
|
|
367
|
+
expose the host's `RegExp`. It compiles a fixed, portable dialect whose every
|
|
368
|
+
construct has one spec-defined meaning (`spec/oqx/SEMANTICS.md` ยง11):
|
|
369
|
+
|
|
370
|
+
- literals; escaped metacharacters `\. \* \+ \? \( \) \[ \] \{ \} \| \^ \$ \\ \/ \-`;
|
|
371
|
+
`\n \t \r \f \v`; `\uXXXX` (four hex digits) and `\u{Xโฆ}` (any code point);
|
|
372
|
+
- `\d` = `[0-9]`, `\w` = `[A-Za-z0-9_]`, `\s` = JavaScript's white space (one
|
|
373
|
+
listed set), `\D \W \S` their complements, `\b \B` word boundaries over that
|
|
374
|
+
`\w`; bracket classes `[โฆ]` / `[^โฆ]` with ranges;
|
|
375
|
+
- `.` = any code point except `\n` (the line terminator is `\n` alone โ `\r`
|
|
376
|
+
is an ordinary character); anchors `^ $`; quantifiers `* + ? {n} {n,} {n,m}`
|
|
377
|
+
and their lazy `?` forms; alternation `|`; groups `(โฆ)`, `(?:โฆ)`, `(?<name>โฆ)`.
|
|
378
|
+
|
|
379
|
+
Everything else โ lookaround, backreferences, inline flags `(?i)`, `\p{โฆ}`,
|
|
380
|
+
`\x..`, octal, possessive quantifiers, POSIX classes, `\A \z` โฆ โ is an
|
|
381
|
+
`OqxError` (stage `eval`) naming the construct: `an inline flag (?i) is not
|
|
382
|
+
supported in OQX regular expressions`. A pattern that is malformed within the
|
|
383
|
+
baseline is `invalid regular expression โฆ`; a bad flag is `unknown regex flag`
|
|
384
|
+
/ `duplicate regex flag`. The pattern is validated and rewritten before
|
|
385
|
+
`RegExp` sees it (`src/regex.ts`), so JavaScript-only behavior never leaks.
|
|
386
|
+
|
|
387
|
+
```js
|
|
388
|
+
oqx`name from ${people} where title.matches("^(eng|dir)", "i")`; // Bob, Alice
|
|
389
|
+
oqx`x: "a\nb".matches("a.b") from ${one}`; // false: . stops at \n
|
|
390
|
+
oqx`x: "a\nb".matches("a.b", "s") from ${one}`; // true
|
|
391
|
+
oqx`x: "ูฃ".matches(${"\\d"}) from ${one}`; // false: \d is ASCII
|
|
392
|
+
oqx`x: "รฉ".matches(${"^\\u{e9}$"}) from ${one}`; // true
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
A pattern with backslashes is easiest to pass as a binding (`${"\\d"}`): the
|
|
396
|
+
template's own escaping and the OQX string literal's `\<c>` escape would each
|
|
397
|
+
consume one level otherwise (`"\\\\d"` in the template is `\d` to the regex).
|
|
398
|
+
|
|
399
|
+
A host that wants JavaScript's own dialect can opt in per context:
|
|
400
|
+
`new DefaultContext(roots, { regexDialect: "native" })` hands patterns to
|
|
401
|
+
`RegExp` unvalidated (with the `u` flag plus the given flags). That is
|
|
402
|
+
implementation-defined and not portable to the Rust implementation.
|
|
403
|
+
|
|
321
404
|
### 5. Consumers
|
|
322
405
|
|
|
323
406
|
A consumer shapes a result set. There are six:
|
|
@@ -333,8 +416,9 @@ A consumer shapes a result set. There are six:
|
|
|
333
416
|
|
|
334
417
|
The bare `from โฆ ` form is always `collect`. To reduce the **whole** query with a
|
|
335
418
|
different consumer, use the directive form `<source> <consumer> { <body> }` โ note
|
|
336
|
-
this is *not* SQL: `count from people`
|
|
337
|
-
|
|
419
|
+
this is *not* SQL: `count from people` projects a field called `count`, and
|
|
420
|
+
`from people count` is a parse error that points at the directive form. A real
|
|
421
|
+
reduction is a directive:
|
|
338
422
|
|
|
339
423
|
```js
|
|
340
424
|
oqx`${people} exists { where active }`; // true
|
|
@@ -342,8 +426,11 @@ oqx`${people} count { where active }`; // 2
|
|
|
342
426
|
oqx`${people} first { name where age > 50 }`; // { name: "Alice" }
|
|
343
427
|
```
|
|
344
428
|
|
|
345
|
-
(
|
|
346
|
-
|
|
429
|
+
(A consumer block follows the same clause grammar as the top level, with `from`
|
|
430
|
+
optional. A leading bare identifier **projects** โ `count { active }` selects a
|
|
431
|
+
field named `active`; write `count { where active }` to filter, and always write
|
|
432
|
+
`where` before a predicate: `exists { !end }` is an error, `exists { where !end }`
|
|
433
|
+
is the test.)
|
|
347
434
|
|
|
348
435
|
### 6. Nested collections and relations
|
|
349
436
|
|
|
@@ -354,7 +441,7 @@ In `where`, an `exists { โฆ }` tests non-emptiness and `count { โฆ } <op> N` c
|
|
|
354
441
|
cardinality:
|
|
355
442
|
|
|
356
443
|
```js
|
|
357
|
-
oqx`name from ${people} where jobs exists { !end }`; // has a current job โ Bob, Carol
|
|
444
|
+
oqx`name from ${people} where jobs exists { where !end }`; // has a current job โ Bob, Carol
|
|
358
445
|
oqx`name from ${people} where jobs count {} >= 2`; // โฅ2 jobs โ Bob, Alice
|
|
359
446
|
oqx`name from ${people} where jobs none { where end }`; // no past job โ Carol
|
|
360
447
|
```
|
|
@@ -384,7 +471,7 @@ counts and collections are over distinct projections rather than raw rows. Spell
|
|
|
384
471
|
it after the consumer (`count distinct { โฆ }`) or inside via `select distinct`:
|
|
385
472
|
|
|
386
473
|
```js
|
|
387
|
-
oqx`from ${jobs}
|
|
474
|
+
oqx`select distinct employer from ${jobs}`; // distinct employers
|
|
388
475
|
oqx`n: jobs collect distinct { select employer } from ${people}`; // per person, unique employers
|
|
389
476
|
oqx`name from ${people} where jobs count distinct { select employer } == 1`; // worked at exactly one employer
|
|
390
477
|
```
|
|
@@ -437,7 +524,9 @@ fully), not a short-circuiting `exists`.
|
|
|
437
524
|
### 8. Ordering
|
|
438
525
|
|
|
439
526
|
`order by <expr> [asc|desc]`, comma-separated for tie-breaks. Absent values sort
|
|
440
|
-
last.
|
|
527
|
+
last. The sort expression reads the row (fields, `$value`, recursion
|
|
528
|
+
intrinsics) โ it is not rewritten against the `select` aliases, so
|
|
529
|
+
`order by decade` sorts by a field called `decade`, not by `decade: age / 10`.
|
|
441
530
|
|
|
442
531
|
```js
|
|
443
532
|
oqx`name from ${people} where city == "NYC" order by age desc`;
|
|
@@ -456,7 +545,7 @@ inside `{ โฆ }`; it must be a non-negative integer.
|
|
|
456
545
|
|
|
457
546
|
```js
|
|
458
547
|
oqx`name values from ${people} order by age desc limit 2`; // ["Alice", "Bob"]
|
|
459
|
-
oqx`name values from ${people} order by age desc
|
|
548
|
+
oqx`name values from ${people} order by age desc limit 1 offset 1`; // ["Bob"]
|
|
460
549
|
oqx`name, latest: jobs collect { employer values order by start desc limit 1 } from ${people}`;
|
|
461
550
|
oqx`name from ${people} where jobs exists { offset 1 }`; // has a second job
|
|
462
551
|
```
|
|
@@ -513,9 +602,11 @@ your relation returns fresh objects rather than shared references.
|
|
|
513
602
|
### Cheat-sheet
|
|
514
603
|
|
|
515
604
|
```
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
605
|
+
select โฆ from โฆ where โฆ follow โฆ order by โฆ limit N offset N the fixed clause order (each at most once)
|
|
606
|
+
name, alias: expr, nested: rel collect { โฆ } projection (`select` may be dropped only here, in first position)
|
|
607
|
+
from ${source} source collection (required at the top level)
|
|
608
|
+
where a == b && rel exists { where โฆ } || !c predicate tree + nested ops (`where` is never implicit)
|
|
609
|
+
where alias `where` may use this body's select aliases (inlined; an alias shadows a field)
|
|
519
610
|
where rel none { โฆ } zero rows (โก !rel exists { โฆ }; "all" = none over the complement)
|
|
520
611
|
where x in lo..hi / lo...hi / ..hi / lo.. range membership (incl. / excl. / open-ended)
|
|
521
612
|
where x in range(field) coerce a string field to a range, then test coverage
|
|
@@ -699,14 +790,23 @@ adapter lives on the `@omgbase/oqx/sqlite` subpath.
|
|
|
699
790
|
- `InMemoryEngine` โ `new InMemoryEngine(context?)`; the reference engine over a
|
|
700
791
|
`DataContext` (tier 1/2).
|
|
701
792
|
- `DataContext` โ the tier-2 interface: `root`, `get`, `toRows`, `identity`,
|
|
702
|
-
plus optional `callFunction` / `callMethod` (above)
|
|
793
|
+
plus optional `callFunction` / `callMethod` (above) and an optional
|
|
794
|
+
`regexDialect` (`"oqx"` default | `"native"`). The engine dispatches
|
|
795
|
+
`matches` through `callMethod`, so a custom context that wants the native
|
|
796
|
+
dialect answers `matches` itself with `semantics.regexMatches(recv, args,
|
|
797
|
+
"native")`; `BUILTIN_METHODS.matches` is always the baseline.
|
|
703
798
|
- `CallResult` โ `{ handled: boolean; value?: unknown }`, returned by those hooks.
|
|
704
|
-
- `DefaultContext` โ `new DefaultContext(roots?)`; plain-object
|
|
705
|
-
identity, and the builtin function/method tables.
|
|
799
|
+
- `DefaultContext` โ `new DefaultContext(roots?, options?)`; plain-object
|
|
800
|
+
access, `.id` identity, and the builtin function/method tables. `options`:
|
|
801
|
+
`{ regexDialect?: RegexDialect }` (see the regex baseline, ยง4).
|
|
802
|
+
- `compileRegex(pattern, flags?, dialect?)` โ the `matches()` compiler: a
|
|
803
|
+
`RegExp`, or an `OqxError` for a bad pattern/flag. `RegexDialect` /
|
|
804
|
+
`RegexFlags` are the types.
|
|
706
805
|
- `semantics` โ the scalar-contract module (`equals`, `relate`, `arith`,
|
|
707
806
|
`membership`, `truthy`, `compareForSort`, `sizeOf`, `toList`,
|
|
708
807
|
`coerceCollection`, ranges: `makeRange` / `isRange` / `rangeCovers` /
|
|
709
|
-
`parseRangeString`, entries: `makeEntry` / `isEntry` / `entriesOf`,
|
|
808
|
+
`parseRangeString`, entries: `makeEntry` / `isEntry` / `entriesOf`, regex:
|
|
809
|
+
`compileRegex` / `regexMatches` / `parseRegexFlags`, and the
|
|
710
810
|
`BUILTIN_FUNCTIONS` / `BUILTIN_METHODS` tables). A backend reproducing a rule
|
|
711
811
|
natively must match these.
|
|
712
812
|
|
package/dist/context.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RegexDialect } from "./regex.js";
|
|
1
2
|
/** Result of a context-provided function/method call: `handled: false` tells the
|
|
2
3
|
* engine to fall back to the builtin table (or error if none). */
|
|
3
4
|
export interface CallResult {
|
|
@@ -20,13 +21,27 @@ export interface DataContext {
|
|
|
20
21
|
callFunction?(name: string, args: unknown[]): CallResult;
|
|
21
22
|
/** Optional custom method; return `{ handled: false }` to defer. */
|
|
22
23
|
callMethod?(name: string, recv: unknown, args: unknown[]): CallResult;
|
|
24
|
+
/** The regex dialect `matches()` compiles against. `"oqx"` (the default when
|
|
25
|
+
* absent) is the portable baseline the spec tests; `"native"` hands the
|
|
26
|
+
* pattern to the host `RegExp` unvalidated โ implementation-defined, not
|
|
27
|
+
* portable. Note the engine dispatches `matches` through `callMethod`, so
|
|
28
|
+
* this is read by the context's own `matches` (`DefaultContext` does;
|
|
29
|
+
* `regexMatches(recv, args, dialect)` is the helper). `BUILTIN_METHODS.matches`
|
|
30
|
+
* is always the baseline. */
|
|
31
|
+
readonly regexDialect?: RegexDialect;
|
|
32
|
+
}
|
|
33
|
+
export interface DefaultContextOptions {
|
|
34
|
+
/** See `DataContext.regexDialect`. Default `"oqx"`. */
|
|
35
|
+
regexDialect?: RegexDialect;
|
|
23
36
|
}
|
|
24
37
|
/** The default context: ordinary JavaScript objects. Named roots come from a
|
|
25
|
-
* plain `{ name: collection }` map; properties are
|
|
26
|
-
*
|
|
38
|
+
* plain `{ name: collection }` map; properties are OWN keys only (an array
|
|
39
|
+
* exposes only its integer indices, a primitive has none); identity is `.id`
|
|
40
|
+
* when present, else the row itself (the engine keys it structurally). */
|
|
27
41
|
export declare class DefaultContext implements DataContext {
|
|
28
42
|
private roots;
|
|
29
|
-
|
|
43
|
+
readonly regexDialect: RegexDialect;
|
|
44
|
+
constructor(roots?: Record<string, unknown>, options?: DefaultContextOptions);
|
|
30
45
|
root(name: string): unknown;
|
|
31
46
|
get(row: unknown, key: string): unknown;
|
|
32
47
|
toRows(value: unknown): Iterable<unknown>;
|
package/dist/context.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAQ/C;kEACkE;AAClE,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,gFAAgF;IAChF,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B;;;+DAG2D;IAC3D,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACxC,8DAA8D;IAC9D,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC1C,8DAA8D;IAC9D,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC;IAChC,2EAA2E;IAC3E,YAAY,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;IACzD,oEAAoE;IACpE,UAAU,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;IACtE;;;;;;iCAM6B;IAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;CACtC;AAED,MAAM,WAAW,qBAAqB;IACpC,uDAAuD;IACvD,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;;0EAG0E;AAC1E,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,KAAK,CAA0B;IACvC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;gBAExB,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAAE,OAAO,GAAE,qBAA0B;IAKpF,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI3B,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IAMvC,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;IAIzC,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IAK/B,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,UAAU;IAKvD,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,UAAU;CAKrE"}
|
package/dist/context.js
CHANGED
|
@@ -7,22 +7,32 @@
|
|
|
7
7
|
//
|
|
8
8
|
// (Performant execution over a real store is the tier-3 seam โ see planner.ts โ
|
|
9
9
|
// which pushes work into the store instead of driving it row-by-row here.)
|
|
10
|
-
import { coerceCollection, BUILTIN_FUNCTIONS, BUILTIN_METHODS } from "./semantics.js";
|
|
10
|
+
import { coerceCollection, regexMatches, BUILTIN_FUNCTIONS, BUILTIN_METHODS } from "./semantics.js";
|
|
11
|
+
// An array's only properties are its integer indices, spelled canonically
|
|
12
|
+
// (`"0"`, `"12"`; never `"01"`, `"length"`, or a method name).
|
|
13
|
+
function isIndexKey(key) {
|
|
14
|
+
return /^(0|[1-9]\d*)$/.test(key);
|
|
15
|
+
}
|
|
11
16
|
/** The default context: ordinary JavaScript objects. Named roots come from a
|
|
12
|
-
* plain `{ name: collection }` map; properties are
|
|
13
|
-
*
|
|
17
|
+
* plain `{ name: collection }` map; properties are OWN keys only (an array
|
|
18
|
+
* exposes only its integer indices, a primitive has none); identity is `.id`
|
|
19
|
+
* when present, else the row itself (the engine keys it structurally). */
|
|
14
20
|
export class DefaultContext {
|
|
15
21
|
roots;
|
|
16
|
-
|
|
22
|
+
regexDialect;
|
|
23
|
+
constructor(roots = {}, options = {}) {
|
|
17
24
|
this.roots = roots;
|
|
25
|
+
this.regexDialect = options.regexDialect ?? "oqx";
|
|
18
26
|
}
|
|
19
27
|
root(name) {
|
|
20
|
-
return this.roots[name];
|
|
28
|
+
return Object.hasOwn(this.roots, name) ? this.roots[name] : undefined;
|
|
21
29
|
}
|
|
22
30
|
get(row, key) {
|
|
23
|
-
if (row == null)
|
|
31
|
+
if (row == null || typeof row !== "object")
|
|
24
32
|
return undefined;
|
|
25
|
-
|
|
33
|
+
if (Array.isArray(row))
|
|
34
|
+
return isIndexKey(key) ? row[Number(key)] : undefined;
|
|
35
|
+
return Object.hasOwn(row, key) ? row[key] : undefined;
|
|
26
36
|
}
|
|
27
37
|
toRows(value) {
|
|
28
38
|
return coerceCollection(value);
|
|
@@ -33,11 +43,13 @@ export class DefaultContext {
|
|
|
33
43
|
return row;
|
|
34
44
|
}
|
|
35
45
|
callFunction(name, args) {
|
|
36
|
-
const fn = BUILTIN_FUNCTIONS[name];
|
|
46
|
+
const fn = Object.hasOwn(BUILTIN_FUNCTIONS, name) ? BUILTIN_FUNCTIONS[name] : undefined;
|
|
37
47
|
return fn ? { handled: true, value: fn(args) } : { handled: false };
|
|
38
48
|
}
|
|
39
49
|
callMethod(name, recv, args) {
|
|
40
|
-
|
|
50
|
+
if (name === "matches")
|
|
51
|
+
return { handled: true, value: regexMatches(recv, args, this.regexDialect) };
|
|
52
|
+
const fn = Object.hasOwn(BUILTIN_METHODS, name) ? BUILTIN_METHODS[name] : undefined;
|
|
41
53
|
return fn ? { handled: true, value: fn(recv, args) } : { handled: false };
|
|
42
54
|
}
|
|
43
55
|
}
|
package/dist/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,iFAAiF;AACjF,gFAAgF;AAChF,4EAA4E;AAC5E,gFAAgF;AAChF,gFAAgF;AAChF,EAAE;AACF,gFAAgF;AAChF,2EAA2E;AAE3E,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,KAAK,EACN,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAOhD,yEAAyE;AACzE,MAAM,MAAM,SAAS,GACjB;IAAE,QAAQ,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,OAAO,EAAE,CAAA;CAAE,GACxC;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GACvC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GACnC;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,GAC1C;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,CAAC;AAEhD,6EAA6E;AAC7E,MAAM,WAAW,MAAM;IACrB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,SAAS,CAAC;CAC5D;AA4BD,qBAAa,cAAe,YAAW,MAAM;IAC3C,OAAO,CAAC,GAAG,CAAc;gBAEb,OAAO,GAAE,WAAkC;IAIvD,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,GAAE,SAAS,OAAO,EAAO,GAAG,SAAS;IAmD/D,OAAO,CAAC,OAAO;IAef,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,KAAK;IASb,OAAO,CAAC,KAAK;IAab,OAAO,CAAC,SAAS;IAiBjB,OAAO,CAAC,iBAAiB;IA6BzB,OAAO,CAAC,UAAU;IA8DlB,OAAO,CAAC,KAAK;IAgBb,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,SAAS;IAYjB,OAAO,CAAC,WAAW;IAiCnB,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAE,aAAa;IAStB,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,gBAAgB;IA2BxB,OAAO,CAAC,UAAU;IAwBlB,OAAO,CAAC,QAAQ;IA+DhB,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,QAAQ;CAYjB;AAkGD,8EAA8E;AAC9E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,GAAG,SAAS,CAG9F"}
|