diff --git a/.changeset/sixty-pants-invent.md b/.changeset/sixty-pants-invent.md
new file mode 100644
index 0000000..6e13cc0
--- /dev/null
+++ b/.changeset/sixty-pants-invent.md
@@ -0,0 +1,9 @@
+---
+"@getlang/ast": patch
+"@getlang/get": patch
+"@getlang/lib": patch
+"@getlang/parser": patch
+"@getlang/walker": patch
+---
+
+misc
diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml
index 949d38c..da724b8 100644
--- a/.github/workflows/checks.yaml
+++ b/.github/workflows/checks.yaml
@@ -4,7 +4,7 @@ jobs:
checks:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v7
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: bun --filter @getlang/parser compile
diff --git a/.github/workflows/discord.yaml b/.github/workflows/discord.yaml
index a3010f7..99e1575 100644
--- a/.github/workflows/discord.yaml
+++ b/.github/workflows/discord.yaml
@@ -1,13 +1,13 @@
on:
release:
- types: [published]
+ types: [ published ]
jobs:
discord-notify-release:
if: startsWith(github.event.release.tag_name, '@getlang/get@')
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v7
- uses: SethCohen/github-releases-to-discord@v1
with:
webhook_url: ${{ secrets.RELEASE_DISCORD_WEBHOOK_URL }}
diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml
index 36f8cb4..72fdd37 100644
--- a/.github/workflows/publish.yaml
+++ b/.github/workflows/publish.yaml
@@ -16,11 +16,11 @@ jobs:
pull-requests: write
issues: read
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v7
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: bun --filter @getlang/parser compile
- - uses: changesets/action@v1
+ - uses: changesets/action@v2.1.2
with:
title: 'chore: version packages'
commit: 'chore: version packages'
diff --git a/assets/tokenizers/examples/01-nested-template-interpolation.get b/assets/tokenizers/examples/01-nested-template-interpolation.get
new file mode 100644
index 0000000..4abc109
--- /dev/null
+++ b/assets/tokenizers/examples/01-nested-template-interpolation.get
@@ -0,0 +1,14 @@
+-- Nested template interpolation and mixed interpolation forms.
+-- Recursive interpolation is valid in the lexer, but both tokenizers only approximate it.
+
+set slug = |'big-sur'|
+set suffix = |'guide'|
+set path = |'travel'|
+
+GET https://example.com/$path/$[$slug-$[$suffix]]/${slug}_overview
+
+extract {
+ direct: $slug,
+ nested: $[$slug-$[$suffix]],
+ embedded: |'/${slug}/$[$suffix]'|
+}
diff --git a/assets/tokenizers/examples/02-request-body-sentinels-and-comments.get b/assets/tokenizers/examples/02-request-body-sentinels-and-comments.get
new file mode 100644
index 0000000..090d606
--- /dev/null
+++ b/assets/tokenizers/examples/02-request-body-sentinels-and-comments.get
@@ -0,0 +1,14 @@
+-- In a real request body, lines are plain body text until [/body].
+-- A tokenizer may still try to color leading -- as comments.
+-- The sentinel-looking text below should remain body content until the actual closing line.
+
+POST https://example.com/submit
+[body]
+-- this line is body content, not a comment token in the real lexer
+payload starts here
+ [body] should not open a nested body block
+ [/body] inside an indented text line still looks delimiter-ish
+body ends only on the exact closing marker line
+[/body]
+
+extract |'done'|
diff --git a/assets/tokenizers/examples/03-request-values-with-comment-like-text.get b/assets/tokenizers/examples/03-request-values-with-comment-like-text.get
new file mode 100644
index 0000000..fd23bbd
--- /dev/null
+++ b/assets/tokenizers/examples/03-request-values-with-comment-like-text.get
@@ -0,0 +1,13 @@
+-- In request headers and block entries, -- is just text.
+-- TextMate and Monarch may over-highlight these as comments because they are line-oriented.
+
+GET https://example.com/search/:term
+Authorization: Bearer token--not-a-comment
+X-Trace: value -- still part of the header value
+[query]
+q: literal--value
+explain: left -- right
+[cookies]
+session: abc--123
+
+extract |'ok'|
diff --git a/assets/tokenizers/examples/04-slice-delimiter-collisions.get b/assets/tokenizers/examples/04-slice-delimiter-collisions.get
new file mode 100644
index 0000000..9284295
--- /dev/null
+++ b/assets/tokenizers/examples/04-slice-delimiter-collisions.get
@@ -0,0 +1,21 @@
+-- Backtick slices support escaped backticks.
+-- Pipe slices allow raw backticks and multiline content.
+-- A tokenizer can struggle when the slice body itself looks like source code or delimiters.
+
+set js_inline = `({
+ label: \`inner\`,
+ value: 42,
+})`
+
+set js_block = |
+return {
+ template: `raw backtick survives here`,
+ regexy: /a|b|c/,
+ note: '$[not interpolation in JS unless parsed by the host]',
+}
+|
+
+extract {
+ $js_inline,
+ $js_block
+}
diff --git a/assets/tokenizers/examples/05-colon-ambiguity.get b/assets/tokenizers/examples/05-colon-ambiguity.get
new file mode 100644
index 0000000..4eaa777
--- /dev/null
+++ b/assets/tokenizers/examples/05-colon-ambiguity.get
@@ -0,0 +1,19 @@
+-- Colons appear in request params, object entries, ternaries, and plain templates.
+-- Tokenizers cannot fully recover expression context from punctuation alone.
+
+inputs { city = |'monterey'|, fallback? }
+
+set meta = {
+ route: |'/places/:city'|,
+ label: $city ? |'known'| : |'unknown'|,
+ fallback: $fallback ?: |'none'|
+}
+
+GET https://example.com/:city?label=${city}:${fallback}
+Accept: application/json; profile=:city
+
+extract {
+ route: $meta -> route,
+ label: $meta -> label,
+ fallback: $meta -> fallback
+}
diff --git a/assets/tokenizers/examples/06-wide-arrow-subquery-and-calls.get b/assets/tokenizers/examples/06-wide-arrow-subquery-and-calls.get
new file mode 100644
index 0000000..a91cbc7
--- /dev/null
+++ b/assets/tokenizers/examples/06-wide-arrow-subquery-and-calls.get
@@ -0,0 +1,17 @@
+-- Wide-arrow chains, subqueries, and @calls/@modifiers all reuse similar symbols.
+-- The real parser knows which @name is a call bit and where subqueries reopen statement parsing.
+
+set html = |'
'| -> @html
+set out = $html => li -> (
+ set value = span
+ extract {
+ text: $value,
+ maybe: $value ?: |'missing'|
+ }
+)
+
+extract {
+ $out,
+ transformed: @SomeModule({ items: $out }) -> result,
+ modified: $out -> @flatten
+}
diff --git a/assets/tokenizers/examples/07-object-shorthand-optional-and-context.get b/assets/tokenizers/examples/07-object-shorthand-optional-and-context.get
new file mode 100644
index 0000000..34513c4
--- /dev/null
+++ b/assets/tokenizers/examples/07-object-shorthand-optional-and-context.get
@@ -0,0 +1,18 @@
+-- Optional markers can attach to input declarations, assignments, object keys, and shorthand refs.
+-- The tokenizers do not distinguish all of these structural positions.
+
+inputs { title?, slug = |'coast'| }
+
+set value? = {
+ title?,
+ slug,
+ $slug,
+ $title?
+}
+
+extract {
+ title?,
+ slug,
+ $value?,
+ current: $
+}
diff --git a/assets/tokenizers/examples/08-selector-heavy-links.get b/assets/tokenizers/examples/08-selector-heavy-links.get
new file mode 100644
index 0000000..375d22c
--- /dev/null
+++ b/assets/tokenizers/examples/08-selector-heavy-links.get
@@ -0,0 +1,6 @@
+-- Selectors after -> are lexed as template text, not parsed CSS/XPath in the tokenizer.
+-- This stresses parentheses, @, ?, :, and // in selector-like regions.
+
+set doc = |"RoadSea"|
+
+extract $doc -> @html => main a[href^='/'] -> span:nth-child(1) ?: //a[@href='/fallback']/span
diff --git a/assets/tokenizers/examples/broken.get b/assets/tokenizers/examples/broken.get
new file mode 100644
index 0000000..640db7f
--- /dev/null
+++ b/assets/tokenizers/examples/broken.get
@@ -0,0 +1,6 @@
+-- monarch
+GET http://x
+
+extract {
+ title: title
+}
diff --git a/assets/tokenizers/getlang.monarch.ts b/assets/tokenizers/getlang.monarch.ts
new file mode 100644
index 0000000..bd75490
--- /dev/null
+++ b/assets/tokenizers/getlang.monarch.ts
@@ -0,0 +1,132 @@
+// Generated from packages/parser/src/grammar/lexer.ts and getlang.ne.
+// Monarch is line-oriented, so this mirrors the lexer states where that
+// maps cleanly and uses pragmatic fallbacks for expression highlighting.
+
+const identifier = /[a-zA-Z_]\w*/
+
+export const getlangLanguageId = 'getlang'
+
+export const getlangMonarchLanguage = {
+ defaultToken: '',
+ tokenPostfix: '.getlang',
+
+ brackets: [
+ { open: '{', close: '}', token: 'delimiter.curly' },
+ { open: '(', close: ')', token: 'delimiter.parenthesis' },
+ ],
+
+ keywords: ['inputs', 'set', 'extract'],
+ requestVerbs: ['GET', 'PUT', 'POST', 'PATCH', 'DELETE'],
+ requestBlocks: ['query', 'cookies', 'json', 'form'],
+
+ tokenizer: {
+ root: [
+ { include: '@whitespace' },
+ [
+ /\b(?:GET|PUT|POST|PATCH|DELETE)\b/,
+ { token: 'keyword.control.http', next: '@requrl' },
+ ],
+ [/\b(?:inputs|set|extract)\b/, 'keyword'],
+ [/\b(?:true|false)\b/, 'constant.language.boolean'],
+ [/\d+(?:\.\d+)?\b/, 'number'],
+ [/@[a-zA-Z_]\w*\)/, 'type.identifier'],
+ [/@[a-zA-Z_]\w*/, 'predefined'],
+ [/\$(?:[a-zA-Z_]\w*)?/, 'variable'],
+ [/\?:|->|=>/, 'operator'],
+ [/[=:@?,]/, 'operator'],
+ [/[{}()]/, '@brackets'],
+ [/'/, { token: 'string.quote', next: '@strSingle' }],
+ [/"/, { token: 'string.quote', next: '@strDouble' }],
+ [/`/, { token: 'string.quote', next: '@sliceBacktick' }],
+ [/\|/, { token: 'string.quote', next: '@slicePipe' }],
+ [identifier, 'identifier'],
+ ],
+
+ whitespace: [
+ [/[ \t\r\f\v]+/, 'white'],
+ [/--.*$/, 'comment'],
+ ],
+
+ requrl: [
+ { include: '@templateWithParams' },
+ [/$/, { token: '', next: '@req' }],
+ ],
+
+ req: [
+ [/^\s*$/, { token: 'white', next: '@root' }],
+ [/^\s*\[body\]\s*$/, { token: 'keyword.control.block', next: '@reqbody' }],
+ [/^\s*\[(?:query|cookies|json|form)\]\s*$/, 'keyword.control.block'],
+ { include: '@whitespace' },
+ [/:/, 'operator'],
+ { include: '@template' },
+ [/[{}()]/, '@brackets'],
+ [/$/, { token: '', next: '@req' }],
+ ],
+
+ reqbody: [
+ [/^\s*\[\/body\]\s*$/, { token: 'keyword.control.block', next: '@req' }],
+ { include: '@template' },
+ [/$/, { token: 'string', next: '@reqbody' }],
+ ],
+
+ strSingle: [
+ [/\\./, 'string.escape'],
+ [/\$\{[^}]*\}/, 'variable'],
+ [/\$\[[^\]]*\]/, 'variable'],
+ [/\$[a-zA-Z_]\w*/, 'variable'],
+ [/'/, { token: 'string.quote', next: '@root' }],
+ [/[^\\$']+/, 'string'],
+ [/\$/, 'string'],
+ ],
+
+ strDouble: [
+ [/\\./, 'string.escape'],
+ [/\$\{[^}]*\}/, 'variable'],
+ [/\$\[[^\]]*\]/, 'variable'],
+ [/\$[a-zA-Z_]\w*/, 'variable'],
+ [/"/, { token: 'string.quote', next: '@root' }],
+ [/[^\\$"]+/, 'string'],
+ [/\$/, 'string'],
+ ],
+
+ sliceBacktick: [
+ [/\\`/, 'string.escape'],
+ [/\$\{[^}]*\}/, 'variable'],
+ [/\$\[[^\]]*\]/, 'variable'],
+ [/\$[a-zA-Z_]\w*/, 'variable'],
+ [/`/, { token: 'string.quote', next: '@root' }],
+ [/[^$`\\]+/, 'string'],
+ [/[$\\]/, 'string'],
+ ],
+
+ slicePipe: [
+ [/\$\{[^}]*\}/, 'variable'],
+ [/\$\[[^\]]*\]/, 'variable'],
+ [/\$[a-zA-Z_]\w*/, 'variable'],
+ [/\|/, { token: 'string.quote', next: '@root' }],
+ [/[^$|]+/, 'string'],
+ [/[$]/, 'string'],
+ ],
+
+ template: [
+ [/\$\{[^}]*\}/, 'variable'],
+ [/\$\[[^\]]*\]/, 'variable'],
+ [/\$[a-zA-Z_]\w*/, 'variable'],
+ [ /:[a-zA-Z_]\w*/, 'variable.parameter' ],
+ [/->|=>|\?:/, 'operator'],
+ [/[^$:>|=?-]+/, 'string'],
+ [/[$:>|=?-]/, 'string'],
+ ],
+
+ templateWithParams: [
+ [/\$\{[^}]*\}/, 'variable'],
+ [/\$\[[^\]]*\]/, 'variable'],
+ [/\$[a-zA-Z_]\w*/, 'variable'],
+ [/:[a-zA-Z_]\w*/, 'variable.parameter'],
+ [/[^$:]+/, 'string'],
+ [/[$:]/, 'string'],
+ ],
+ },
+}
+
+export default getlangMonarchLanguage
diff --git a/assets/tokenizers/getlang.tmLanguage.json b/assets/tokenizers/getlang.tmLanguage.json
new file mode 100644
index 0000000..6680f7a
--- /dev/null
+++ b/assets/tokenizers/getlang.tmLanguage.json
@@ -0,0 +1,328 @@
+{
+ "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
+ "name": "GetLang",
+ "scopeName": "source.getlang",
+ "fileTypes": ["getlang"],
+ "patterns": [
+ { "include": "#comment" },
+ { "include": "#request" },
+ { "include": "#keywords" },
+ { "include": "#booleans" },
+ { "include": "#numbers" },
+ { "include": "#strings" },
+ { "include": "#slices" },
+ { "include": "#link" },
+ { "include": "#call" },
+ { "include": "#identifierExpr" },
+ { "include": "#operators" },
+ { "include": "#braces" },
+ { "include": "#identifier" }
+ ],
+ "repository": {
+ "comment": {
+ "patterns": [
+ {
+ "name": "comment.line.double-dash.getlang",
+ "match": "--.*$"
+ }
+ ]
+ },
+ "keywords": {
+ "patterns": [
+ {
+ "name": "keyword.control.getlang",
+ "match": "\\b(?:inputs|set|extract)\\b"
+ }
+ ]
+ },
+ "booleans": {
+ "patterns": [
+ {
+ "name": "constant.language.boolean.getlang",
+ "match": "\\b(?:true|false)\\b"
+ }
+ ]
+ },
+ "numbers": {
+ "patterns": [
+ {
+ "name": "constant.numeric.getlang",
+ "match": "\\b\\d+(?:\\.\\d+)?\\b"
+ }
+ ]
+ },
+ "operators": {
+ "patterns": [
+ {
+ "name": "keyword.operator.getlang",
+ "match": "(?:\\?:|->|=>|=|:|@|\\?|,)"
+ }
+ ]
+ },
+ "braces": {
+ "patterns": [
+ {
+ "name": "punctuation.section.braces.begin.getlang",
+ "match": "[\\{\\(]"
+ },
+ {
+ "name": "punctuation.section.braces.end.getlang",
+ "match": "[\\}\\)]"
+ }
+ ]
+ },
+ "identifier": {
+ "patterns": [
+ {
+ "name": "variable.other.getlang",
+ "match": "\\b[a-zA-Z_]\\w*\\b"
+ }
+ ]
+ },
+ "identifierExpr": {
+ "patterns": [
+ {
+ "name": "variable.language.getlang",
+ "match": "\\$(?:[a-zA-Z_]\\w*)?"
+ }
+ ]
+ },
+ "link": {
+ "patterns": [
+ {
+ "name": "entity.name.type.link.getlang",
+ "match": "@[a-zA-Z_]\\w*\\)"
+ }
+ ]
+ },
+ "call": {
+ "patterns": [
+ {
+ "name": "support.function.getlang",
+ "match": "@[a-zA-Z_]\\w*"
+ }
+ ]
+ },
+ "request": {
+ "patterns": [
+ {
+ "name": "meta.request.getlang",
+ "begin": "^(\\s*)(GET|PUT|POST|PATCH|DELETE)\\b",
+ "beginCaptures": {
+ "2": { "name": "keyword.control.http.getlang" }
+ },
+ "end": "^(?=\\s*$|\\s*(?:GET|PUT|POST|PATCH|DELETE)\\b|(?:inputs|set|extract)\\b)",
+ "patterns": [
+ { "include": "#comment" },
+ { "include": "#requestBody" },
+ { "include": "#requestBlockName" },
+ { "include": "#requestEntry" },
+ { "include": "#requestUrlTail" }
+ ]
+ }
+ ]
+ },
+ "requestUrlTail": {
+ "patterns": [
+ {
+ "name": "string.unquoted.request-url.getlang",
+ "begin": "(?<=\\b(?:GET|PUT|POST|PATCH|DELETE))(?:[ \t]+)",
+ "beginCaptures": {
+ "0": { "name": "white.space.getlang" }
+ },
+ "end": "$",
+ "patterns": [
+ { "include": "#templateWithParams" }
+ ]
+ }
+ ]
+ },
+ "requestBlockName": {
+ "patterns": [
+ {
+ "name": "keyword.control.block.getlang",
+ "match": "^\\s*\\[(?:query|cookies|json|form)\\]\\s*$"
+ }
+ ]
+ },
+ "requestEntry": {
+ "patterns": [
+ {
+ "name": "meta.request.entry.getlang",
+ "match": "^(\\s*)([^:\\n]+)(:)(?:([ \t]+)(.*))?$",
+ "captures": {
+ "2": { "name": "string.unquoted.request-key.getlang" },
+ "3": { "name": "keyword.operator.getlang" },
+ "5": { "name": "string.unquoted.request-value.getlang" }
+ }
+ }
+ ]
+ },
+ "requestBody": {
+ "patterns": [
+ {
+ "name": "meta.request.body.getlang",
+ "begin": "^\\s*(\\[body\\])\\s*$",
+ "beginCaptures": {
+ "1": { "name": "keyword.control.block.getlang" }
+ },
+ "end": "^\\s*(\\[/body\\])\\s*$",
+ "endCaptures": {
+ "1": { "name": "keyword.control.block.getlang" }
+ },
+ "patterns": [
+ { "include": "#comment" },
+ { "include": "#template" }
+ ]
+ }
+ ]
+ },
+ "strings": {
+ "patterns": [
+ {
+ "name": "string.quoted.single.getlang",
+ "begin": "'",
+ "beginCaptures": {
+ "0": { "name": "punctuation.definition.string.begin.getlang" }
+ },
+ "end": "'",
+ "endCaptures": {
+ "0": { "name": "punctuation.definition.string.end.getlang" }
+ },
+ "patterns": [
+ { "include": "#escapeGeneric" },
+ { "include": "#interpolations" }
+ ]
+ },
+ {
+ "name": "string.quoted.double.getlang",
+ "begin": "\"",
+ "beginCaptures": {
+ "0": { "name": "punctuation.definition.string.begin.getlang" }
+ },
+ "end": "\"",
+ "endCaptures": {
+ "0": { "name": "punctuation.definition.string.end.getlang" }
+ },
+ "patterns": [
+ { "include": "#escapeGeneric" },
+ { "include": "#interpolations" }
+ ]
+ }
+ ]
+ },
+ "slices": {
+ "patterns": [
+ {
+ "name": "string.quoted.other.slice.backtick.getlang",
+ "begin": "`",
+ "beginCaptures": {
+ "0": { "name": "punctuation.definition.string.begin.getlang" }
+ },
+ "end": "`",
+ "endCaptures": {
+ "0": { "name": "punctuation.definition.string.end.getlang" }
+ },
+ "patterns": [
+ { "include": "#escapeBacktick" },
+ { "include": "#interpolations" }
+ ]
+ },
+ {
+ "name": "string.quoted.other.slice.pipe.getlang",
+ "begin": "\\|",
+ "beginCaptures": {
+ "0": { "name": "punctuation.definition.string.begin.getlang" }
+ },
+ "end": "\\|",
+ "endCaptures": {
+ "0": { "name": "punctuation.definition.string.end.getlang" }
+ },
+ "patterns": [
+ { "include": "#interpolations" }
+ ]
+ }
+ ]
+ },
+ "template": {
+ "patterns": [
+ { "include": "#interpolations" },
+ {
+ "name": "variable.parameter.getlang",
+ "match": ":[a-zA-Z_]\\w*"
+ },
+ {
+ "name": "keyword.operator.getlang",
+ "match": "(?:->|=>|\\?:)"
+ }
+ ]
+ },
+ "templateWithParams": {
+ "patterns": [
+ { "include": "#interpolations" },
+ {
+ "name": "variable.parameter.getlang",
+ "match": ":[a-zA-Z_]\\w*"
+ }
+ ]
+ },
+ "interpolations": {
+ "patterns": [
+ {
+ "name": "meta.interpolation.expression.getlang",
+ "begin": "\\$\\{",
+ "beginCaptures": {
+ "0": { "name": "punctuation.section.interpolation.begin.getlang" }
+ },
+ "end": "\\}",
+ "endCaptures": {
+ "0": { "name": "punctuation.section.interpolation.end.getlang" }
+ },
+ "patterns": [
+ { "include": "#comment" },
+ { "include": "#keywords" },
+ { "include": "#booleans" },
+ { "include": "#numbers" },
+ { "include": "#link" },
+ { "include": "#call" },
+ { "include": "#identifier" }
+ ]
+ },
+ {
+ "name": "meta.interpolation.template.getlang",
+ "begin": "\\$\\[",
+ "beginCaptures": {
+ "0": { "name": "punctuation.section.interpolation.begin.getlang" }
+ },
+ "end": "\\]",
+ "endCaptures": {
+ "0": { "name": "punctuation.section.interpolation.end.getlang" }
+ },
+ "patterns": [
+ { "include": "#template" }
+ ]
+ },
+ {
+ "name": "variable.language.getlang",
+ "match": "\\$[a-zA-Z_]\\w*"
+ }
+ ]
+ },
+ "escapeGeneric": {
+ "patterns": [
+ {
+ "name": "constant.character.escape.getlang",
+ "match": "\\\\."
+ }
+ ]
+ },
+ "escapeBacktick": {
+ "patterns": [
+ {
+ "name": "constant.character.escape.getlang",
+ "match": "\\\\`"
+ }
+ ]
+ }
+ }
+}
diff --git a/assets/tokenizers/plan.md b/assets/tokenizers/plan.md
new file mode 100644
index 0000000..35718b8
--- /dev/null
+++ b/assets/tokenizers/plan.md
@@ -0,0 +1,132 @@
+# Tokenizer Plan
+
+This document tracks the tokenizer work for GetLang going forward.
+
+## Goals
+
+- Keep editor tokenization aligned with the real language as defined by:
+ - `packages/parser/src/grammar/lexer.ts`
+ - `packages/parser/src/grammar/getlang.ne`
+ - behavior demonstrated in the root `test` directory
+- Make approximation boundaries explicit where Monarch or TextMate cannot exactly model the lexer/parser.
+- Maintain an installable VS Code extension bundle for fast manual review.
+- Build a repeatable verification loop so future LLMs can measure tokenizer behavior against the real lexer/parser instead of relying on visual guesswork.
+
+## Current Outputs
+
+- `assets/tokenizers/getlang.monarch.ts`
+- `assets/tokenizers/getlang.tmLanguage.json`
+- `assets/tokenizers/vscode-getlang/*`
+- `assets/tokenizers/examples/*.get`
+
+## Known Gaps To Revisit
+
+- Slice literals are currently over-highlighted as if interpolation were active inside them.
+- Recursive interpolation is only approximated in the editor grammars.
+- Request-mode tokenization is line-oriented in the editor grammars and may not perfectly match the moo request states.
+- Selector-heavy template regions after `->` are highlighted lexically, not parsed as CSS/XPath/other selector syntaxes.
+- Optional markers (`?`) and fallback/ternary operators can be hard to distinguish structurally in editor grammars.
+
+## Workstreams
+
+### 1. Tighten lexical fidelity
+
+- Review each tokenizer rule against the corresponding moo state.
+- Remove known false positives first, especially anything that highlights syntax the real lexer does not support.
+- Prefer matching token boundaries from the lexer over adding more visually appealing but inaccurate scopes.
+
+### 2. Expand example coverage
+
+- Keep `assets/tokenizers/examples` as the corpus of high-value tokenizer stress cases.
+- Add one file per edge case, with a short comment header that explains what to inspect.
+- Add examples whenever a bug is found, before or alongside the fix.
+
+### 3. Build machine-verifiable checks
+
+- Add scripts that tokenize example inputs using:
+ - the real moo lexer
+ - the Monarch grammar
+ - the TextMate grammar
+- Normalize the output into a comparable form so differences are visible and reviewable.
+
+### 4. Improve VS Code packaging
+
+- Keep `assets/tokenizers/vscode-getlang` installable with minimal setup.
+- When tokenizer behavior changes, refresh the bundled grammar copy and re-test against the example corpus.
+
+## Verification Loop
+
+Future LLMs should follow this loop whenever they change tokenizer behavior.
+
+### Step 1. Choose fixtures
+
+- Use all files in `assets/tokenizers/examples`.
+- Add any new fixture that reproduces the bug being fixed.
+- Reuse real syntax from the root `test` directory when creating new fixtures.
+
+### Step 2. Capture ground truth from the real lexer/parser
+
+- Run the real moo lexer over each fixture and record:
+ - token type
+ - token text
+ - line/column offsets when useful
+ - lexer state transitions if practical
+- For parser-valid fixtures, also record whether the parser accepts the file.
+- Treat the lexer as the source of truth for lexical boundaries.
+
+### Step 3. Capture tokenizer output
+
+- Tokenize the same fixture with the Monarch provider.
+- Tokenize the same fixture with the TextMate grammar.
+- Convert both outputs into a normalized stream, for example:
+ - line number
+ - start/end columns
+ - scope or token class
+ - matched text
+
+### Step 4. Compare normalized output to ground truth
+
+- Flag places where a tokenizer:
+ - highlights syntax the lexer does not recognize
+ - misses syntax the lexer does recognize
+ - merges or splits important token boundaries incorrectly
+ - enters a wrong lexical region, such as treating slice content like interpolated template content
+- Separate expected approximation differences from regressions.
+
+### Step 5. Review visually in an editor
+
+- Open the fixture set in the VS Code extension host.
+- Inspect at least the changed fixture and any neighboring edge cases.
+- Confirm the visual result matches the normalized diff and does not introduce obvious regressions.
+
+### Step 6. Update docs and examples
+
+- If the tokenizer is intentionally approximate, document that limitation in:
+ - this file
+ - comments near the tokenizer rule if needed
+- If a bug was found, add or refine an example fixture so the issue stays reproducible.
+
+## Suggested Verification Artifacts
+
+These do not all exist yet, but future work should converge on them.
+
+- `assets/tokenizers/examples/*.getlang`
+- `assets/tokenizers/plan.md`
+- `assets/tokenizers/verify/`
+- `assets/tokenizers/verify/fixtures.ts`
+- `assets/tokenizers/verify/lexer-truth.ts`
+- `assets/tokenizers/verify/monarch-runner.ts`
+- `assets/tokenizers/verify/textmate-runner.ts`
+- `assets/tokenizers/verify/diff.ts`
+
+## Suggested Implementation Order
+
+1. Add a small verification harness for the existing example corpus.
+2. Fix known false positives, starting with slice interpolation.
+3. Add regression fixtures for every tokenizer bug found.
+4. Improve request-state and interpolation handling where the grammars can support it safely.
+5. Repackage and manually verify the VS Code extension after each meaningful tokenizer change.
+
+## Operating Rule For Future LLMs
+
+Do not trust a tokenizer change just because it “looks better” in one file. Run the verification loop, compare against the real lexer/parser, and update the example corpus so the change remains testable.
diff --git a/assets/tokenizers/prompt.md b/assets/tokenizers/prompt.md
new file mode 100644
index 0000000..2f153e1
--- /dev/null
+++ b/assets/tokenizers/prompt.md
@@ -0,0 +1,27 @@
+# GetLang Tokenizer Prompt
+
+Review `packages/parser/src/grammar/lexer.ts` and `packages/parser/src/grammar/getlang.ne`, and use the root `test` directory if you need a more top-down view of the language behavior.
+
+Then:
+
+1. Produce a Monaco Monarch tokens provider for the language and write it into `assets/tokenizers`.
+2. Produce a TextMate grammar for the language and write it into `assets/tokenizers`.
+3. Scaffold a minimal installable VS Code extension that bundles the TextMate grammar under `assets/tokenizers/vscode-getlang`.
+4. Under `assets/tokenizers/examples`, write one `.getlang` file per edge case that might expose limitations in either tokenizer.
+
+Constraints:
+
+- Prefer mirroring the real lexer/parser structure instead of guessing from surface syntax.
+- Call out any known approximation where Monarch or TextMate cannot exactly model the moo lexer states.
+- Do not silently “improve” the language; follow the existing lexer/parser behavior.
+- Keep the tokenizer outputs self-contained and ready to inspect locally.
+- Do not make unrelated repo changes.
+
+Deliverables:
+
+- `assets/tokenizers/getlang.monarch.ts`
+- `assets/tokenizers/getlang.tmLanguage.json`
+- `assets/tokenizers/vscode-getlang/*`
+- `assets/tokenizers/examples/*.getlang`
+
+Before finishing, verify the generated grammar files are syntactically valid and summarize any known tokenizer mismatches you noticed while comparing them to the real lexer.
diff --git a/assets/tokenizers/vscode-getlang/README.md b/assets/tokenizers/vscode-getlang/README.md
new file mode 100644
index 0000000..ba68bd9
--- /dev/null
+++ b/assets/tokenizers/vscode-getlang/README.md
@@ -0,0 +1,45 @@
+# GetLang VS Code Extension
+
+This is a minimal VS Code extension that contributes the bundled GetLang TextMate grammar from this repo.
+
+## Files
+
+- `package.json`: extension manifest
+- `language-configuration.json`: comments and bracket behavior
+- `syntaxes/getlang.tmLanguage.json`: bundled TextMate grammar
+
+## Install Locally
+
+1. Change into this directory:
+
+ ```bash
+ cd /code/assets/tokenizers/vscode-getlang
+ ```
+
+2. Package the extension:
+
+ ```bash
+ npx @vscode/vsce package
+ ```
+
+3. In VS Code, run `Extensions: Install from VSIX...` and select the generated `.vsix`.
+
+## Test In An Extension Host
+
+From this directory run:
+
+```bash
+code --extensionDevelopmentPath="$(pwd)"
+```
+
+Then open any `.getlang` file, for example one of the examples in `/code/assets/tokenizers/examples`.
+
+## Updating The Grammar
+
+The extension bundles a copy of:
+
+- `/code/assets/tokenizers/getlang.tmLanguage.json`
+
+If you update the source grammar, copy those changes into:
+
+- `/code/assets/tokenizers/vscode-getlang/syntaxes/getlang.tmLanguage.json`
diff --git a/assets/tokenizers/vscode-getlang/getlang-vscode-0.0.1.vsix b/assets/tokenizers/vscode-getlang/getlang-vscode-0.0.1.vsix
new file mode 100644
index 0000000..12dcbe3
Binary files /dev/null and b/assets/tokenizers/vscode-getlang/getlang-vscode-0.0.1.vsix differ
diff --git a/assets/tokenizers/vscode-getlang/language-configuration.json b/assets/tokenizers/vscode-getlang/language-configuration.json
new file mode 100644
index 0000000..11a1efb
--- /dev/null
+++ b/assets/tokenizers/vscode-getlang/language-configuration.json
@@ -0,0 +1,71 @@
+{
+ "comments": {
+ "lineComment": "--"
+ },
+ "brackets": [
+ [
+ "{",
+ "}"
+ ],
+ [
+ "(",
+ ")"
+ ],
+ [
+ "[",
+ "]"
+ ]
+ ],
+ "autoClosingPairs": [
+ {
+ "open": "{",
+ "close": "}"
+ },
+ {
+ "open": "(",
+ "close": ")"
+ },
+ {
+ "open": "[",
+ "close": "]"
+ },
+ {
+ "open": "\"",
+ "close": "\""
+ },
+ {
+ "open": "'",
+ "close": "'"
+ },
+ {
+ "open": "`",
+ "close": "`"
+ }
+ ],
+ "surroundingPairs": [
+ [
+ "{",
+ "}"
+ ],
+ [
+ "(",
+ ")"
+ ],
+ [
+ "[",
+ "]"
+ ],
+ [
+ "\"",
+ "\""
+ ],
+ [
+ "'",
+ "'"
+ ],
+ [
+ "`",
+ "`"
+ ]
+ ]
+}
diff --git a/assets/tokenizers/vscode-getlang/package.json b/assets/tokenizers/vscode-getlang/package.json
new file mode 100644
index 0000000..a635817
--- /dev/null
+++ b/assets/tokenizers/vscode-getlang/package.json
@@ -0,0 +1,45 @@
+{
+ "name": "getlang-vscode",
+ "displayName": "GetLang",
+ "description": "VS Code syntax highlighting for GetLang using the bundled TextMate grammar.",
+ "version": "0.0.1",
+ "publisher": "local",
+ "license": "Apache-2.0",
+ "engines": {
+ "vscode": "^1.85.0"
+ },
+ "categories": [
+ "Programming Languages"
+ ],
+ "keywords": [
+ "getlang",
+ "syntax",
+ "textmate"
+ ],
+ "contributes": {
+ "languages": [
+ {
+ "id": "getlang",
+ "aliases": [
+ "GetLang",
+ "getlang"
+ ],
+ "extensions": [
+ ".get"
+ ],
+ "configuration": "./language-configuration.json"
+ }
+ ],
+ "grammars": [
+ {
+ "language": "getlang",
+ "scopeName": "source.getlang",
+ "path": "./syntaxes/getlang.tmLanguage.json"
+ }
+ ]
+ },
+ "scripts": {
+ "package": "vsce package",
+ "package:pre-release": "vsce package --pre-release"
+ }
+}
diff --git a/assets/tokenizers/vscode-getlang/syntaxes/getlang.tmLanguage.json b/assets/tokenizers/vscode-getlang/syntaxes/getlang.tmLanguage.json
new file mode 100644
index 0000000..6680f7a
--- /dev/null
+++ b/assets/tokenizers/vscode-getlang/syntaxes/getlang.tmLanguage.json
@@ -0,0 +1,328 @@
+{
+ "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
+ "name": "GetLang",
+ "scopeName": "source.getlang",
+ "fileTypes": ["getlang"],
+ "patterns": [
+ { "include": "#comment" },
+ { "include": "#request" },
+ { "include": "#keywords" },
+ { "include": "#booleans" },
+ { "include": "#numbers" },
+ { "include": "#strings" },
+ { "include": "#slices" },
+ { "include": "#link" },
+ { "include": "#call" },
+ { "include": "#identifierExpr" },
+ { "include": "#operators" },
+ { "include": "#braces" },
+ { "include": "#identifier" }
+ ],
+ "repository": {
+ "comment": {
+ "patterns": [
+ {
+ "name": "comment.line.double-dash.getlang",
+ "match": "--.*$"
+ }
+ ]
+ },
+ "keywords": {
+ "patterns": [
+ {
+ "name": "keyword.control.getlang",
+ "match": "\\b(?:inputs|set|extract)\\b"
+ }
+ ]
+ },
+ "booleans": {
+ "patterns": [
+ {
+ "name": "constant.language.boolean.getlang",
+ "match": "\\b(?:true|false)\\b"
+ }
+ ]
+ },
+ "numbers": {
+ "patterns": [
+ {
+ "name": "constant.numeric.getlang",
+ "match": "\\b\\d+(?:\\.\\d+)?\\b"
+ }
+ ]
+ },
+ "operators": {
+ "patterns": [
+ {
+ "name": "keyword.operator.getlang",
+ "match": "(?:\\?:|->|=>|=|:|@|\\?|,)"
+ }
+ ]
+ },
+ "braces": {
+ "patterns": [
+ {
+ "name": "punctuation.section.braces.begin.getlang",
+ "match": "[\\{\\(]"
+ },
+ {
+ "name": "punctuation.section.braces.end.getlang",
+ "match": "[\\}\\)]"
+ }
+ ]
+ },
+ "identifier": {
+ "patterns": [
+ {
+ "name": "variable.other.getlang",
+ "match": "\\b[a-zA-Z_]\\w*\\b"
+ }
+ ]
+ },
+ "identifierExpr": {
+ "patterns": [
+ {
+ "name": "variable.language.getlang",
+ "match": "\\$(?:[a-zA-Z_]\\w*)?"
+ }
+ ]
+ },
+ "link": {
+ "patterns": [
+ {
+ "name": "entity.name.type.link.getlang",
+ "match": "@[a-zA-Z_]\\w*\\)"
+ }
+ ]
+ },
+ "call": {
+ "patterns": [
+ {
+ "name": "support.function.getlang",
+ "match": "@[a-zA-Z_]\\w*"
+ }
+ ]
+ },
+ "request": {
+ "patterns": [
+ {
+ "name": "meta.request.getlang",
+ "begin": "^(\\s*)(GET|PUT|POST|PATCH|DELETE)\\b",
+ "beginCaptures": {
+ "2": { "name": "keyword.control.http.getlang" }
+ },
+ "end": "^(?=\\s*$|\\s*(?:GET|PUT|POST|PATCH|DELETE)\\b|(?:inputs|set|extract)\\b)",
+ "patterns": [
+ { "include": "#comment" },
+ { "include": "#requestBody" },
+ { "include": "#requestBlockName" },
+ { "include": "#requestEntry" },
+ { "include": "#requestUrlTail" }
+ ]
+ }
+ ]
+ },
+ "requestUrlTail": {
+ "patterns": [
+ {
+ "name": "string.unquoted.request-url.getlang",
+ "begin": "(?<=\\b(?:GET|PUT|POST|PATCH|DELETE))(?:[ \t]+)",
+ "beginCaptures": {
+ "0": { "name": "white.space.getlang" }
+ },
+ "end": "$",
+ "patterns": [
+ { "include": "#templateWithParams" }
+ ]
+ }
+ ]
+ },
+ "requestBlockName": {
+ "patterns": [
+ {
+ "name": "keyword.control.block.getlang",
+ "match": "^\\s*\\[(?:query|cookies|json|form)\\]\\s*$"
+ }
+ ]
+ },
+ "requestEntry": {
+ "patterns": [
+ {
+ "name": "meta.request.entry.getlang",
+ "match": "^(\\s*)([^:\\n]+)(:)(?:([ \t]+)(.*))?$",
+ "captures": {
+ "2": { "name": "string.unquoted.request-key.getlang" },
+ "3": { "name": "keyword.operator.getlang" },
+ "5": { "name": "string.unquoted.request-value.getlang" }
+ }
+ }
+ ]
+ },
+ "requestBody": {
+ "patterns": [
+ {
+ "name": "meta.request.body.getlang",
+ "begin": "^\\s*(\\[body\\])\\s*$",
+ "beginCaptures": {
+ "1": { "name": "keyword.control.block.getlang" }
+ },
+ "end": "^\\s*(\\[/body\\])\\s*$",
+ "endCaptures": {
+ "1": { "name": "keyword.control.block.getlang" }
+ },
+ "patterns": [
+ { "include": "#comment" },
+ { "include": "#template" }
+ ]
+ }
+ ]
+ },
+ "strings": {
+ "patterns": [
+ {
+ "name": "string.quoted.single.getlang",
+ "begin": "'",
+ "beginCaptures": {
+ "0": { "name": "punctuation.definition.string.begin.getlang" }
+ },
+ "end": "'",
+ "endCaptures": {
+ "0": { "name": "punctuation.definition.string.end.getlang" }
+ },
+ "patterns": [
+ { "include": "#escapeGeneric" },
+ { "include": "#interpolations" }
+ ]
+ },
+ {
+ "name": "string.quoted.double.getlang",
+ "begin": "\"",
+ "beginCaptures": {
+ "0": { "name": "punctuation.definition.string.begin.getlang" }
+ },
+ "end": "\"",
+ "endCaptures": {
+ "0": { "name": "punctuation.definition.string.end.getlang" }
+ },
+ "patterns": [
+ { "include": "#escapeGeneric" },
+ { "include": "#interpolations" }
+ ]
+ }
+ ]
+ },
+ "slices": {
+ "patterns": [
+ {
+ "name": "string.quoted.other.slice.backtick.getlang",
+ "begin": "`",
+ "beginCaptures": {
+ "0": { "name": "punctuation.definition.string.begin.getlang" }
+ },
+ "end": "`",
+ "endCaptures": {
+ "0": { "name": "punctuation.definition.string.end.getlang" }
+ },
+ "patterns": [
+ { "include": "#escapeBacktick" },
+ { "include": "#interpolations" }
+ ]
+ },
+ {
+ "name": "string.quoted.other.slice.pipe.getlang",
+ "begin": "\\|",
+ "beginCaptures": {
+ "0": { "name": "punctuation.definition.string.begin.getlang" }
+ },
+ "end": "\\|",
+ "endCaptures": {
+ "0": { "name": "punctuation.definition.string.end.getlang" }
+ },
+ "patterns": [
+ { "include": "#interpolations" }
+ ]
+ }
+ ]
+ },
+ "template": {
+ "patterns": [
+ { "include": "#interpolations" },
+ {
+ "name": "variable.parameter.getlang",
+ "match": ":[a-zA-Z_]\\w*"
+ },
+ {
+ "name": "keyword.operator.getlang",
+ "match": "(?:->|=>|\\?:)"
+ }
+ ]
+ },
+ "templateWithParams": {
+ "patterns": [
+ { "include": "#interpolations" },
+ {
+ "name": "variable.parameter.getlang",
+ "match": ":[a-zA-Z_]\\w*"
+ }
+ ]
+ },
+ "interpolations": {
+ "patterns": [
+ {
+ "name": "meta.interpolation.expression.getlang",
+ "begin": "\\$\\{",
+ "beginCaptures": {
+ "0": { "name": "punctuation.section.interpolation.begin.getlang" }
+ },
+ "end": "\\}",
+ "endCaptures": {
+ "0": { "name": "punctuation.section.interpolation.end.getlang" }
+ },
+ "patterns": [
+ { "include": "#comment" },
+ { "include": "#keywords" },
+ { "include": "#booleans" },
+ { "include": "#numbers" },
+ { "include": "#link" },
+ { "include": "#call" },
+ { "include": "#identifier" }
+ ]
+ },
+ {
+ "name": "meta.interpolation.template.getlang",
+ "begin": "\\$\\[",
+ "beginCaptures": {
+ "0": { "name": "punctuation.section.interpolation.begin.getlang" }
+ },
+ "end": "\\]",
+ "endCaptures": {
+ "0": { "name": "punctuation.section.interpolation.end.getlang" }
+ },
+ "patterns": [
+ { "include": "#template" }
+ ]
+ },
+ {
+ "name": "variable.language.getlang",
+ "match": "\\$[a-zA-Z_]\\w*"
+ }
+ ]
+ },
+ "escapeGeneric": {
+ "patterns": [
+ {
+ "name": "constant.character.escape.getlang",
+ "match": "\\\\."
+ }
+ ]
+ },
+ "escapeBacktick": {
+ "patterns": [
+ {
+ "name": "constant.character.escape.getlang",
+ "match": "\\\\`"
+ }
+ ]
+ }
+ }
+}
diff --git a/biome.json b/biome.json
index 613f78d..da385ad 100644
--- a/biome.json
+++ b/biome.json
@@ -1,6 +1,7 @@
{
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"files": {
+ "ignoreUnknown": true,
"includes": [
"packages/**/*",
"test/**/*",
@@ -22,7 +23,7 @@
"linter": {
"enabled": true,
"rules": {
- "recommended": true,
+ "preset": "recommended",
"correctness": {
"noUnusedVariables": "error",
"noUnusedImports": "error"
diff --git a/bun.lock b/bun.lock
index 15a9d51..004a851 100644
--- a/bun.lock
+++ b/bun.lock
@@ -1,34 +1,38 @@
{
- "lockfileVersion": 1,
+ "lockfileVersion": 2,
+ "configVersion": 1,
"workspaces": {
"": {
"name": "get",
"devDependencies": {
- "@biomejs/biome": "^2.2.4",
- "@changesets/changelog-github": "^0.5.1",
- "@changesets/cli": "^2.29.7",
- "@types/bun": "^1.2.22",
- "knip": "^5.63.1",
- "sherif": "^1.6.1",
- "typescript": "^5.9.2",
+ "@biomejs/biome": "^2.5.14",
+ "@changesets/changelog-github": "^1.0.1",
+ "@changesets/cli": "^3.0.3",
+ "@types/bun": "^1.4.2",
+ "knip": "^6.37.0",
+ "sherif": "^1.13.0",
+ "typescript": "^7.0.2",
},
},
"packages/ast": {
"name": "@getlang/ast",
"version": "0.1.0",
"dependencies": {
- "moo": "^0.5.2",
+ "moo": "^0.5.3",
+ },
+ "devDependencies": {
+ "@types/moo": "^0.5.10",
},
},
"packages/get": {
"name": "@getlang/get",
- "version": "0.3.0",
+ "version": "0.3.3",
"dependencies": {
"@getlang/ast": "workspace:^0.1.0",
- "@getlang/lib": "workspace:^0.2.0",
- "@getlang/parser": "workspace:^0.4.0",
+ "@getlang/lib": "workspace:^0.2.1",
+ "@getlang/parser": "workspace:^0.4.3",
"@getlang/walker": "workspace:^0.1.0",
- "lodash-es": "^4.17.21",
+ "lodash-es": "^4.18.1",
},
"devDependencies": {
"@types/lodash-es": "^4.17.12",
@@ -36,43 +40,42 @@
},
"packages/lib": {
"name": "@getlang/lib",
- "version": "0.2.0",
+ "version": "0.2.1",
"dependencies": {
"@getlang/ast": "workspace:^0.1.0",
"@getlang/xpath": "0.0.35-0",
"@types/esquery": "^1.5.4",
"@types/lodash-es": "^4.17.12",
- "@types/set-cookie-parser": "^2.4.10",
- "acorn": "^8.15.0",
- "css-select": "^6.0.0",
- "css-what": "^7.0.0",
- "dom-serializer": "^2.0.0",
+ "acorn": "^8.18.0",
+ "css-select": "^7.0.0",
+ "css-what": "^8.0.0",
+ "dom-serializer": "^3.1.1",
"domelementtype": "*",
- "domhandler": "^5.0.3",
- "domutils": "^3.2.2",
- "esquery": "^1.6.0",
- "lodash-es": "^4.17.21",
- "parse5": "^8.0.0",
- "parse5-htmlparser2-tree-adapter": "^8.0.0",
- "set-cookie-parser": "^2.7.1",
+ "domhandler": "^6.0.1",
+ "domutils": "^4.0.2",
+ "esquery": "^1.7.0",
+ "lodash-es": "^4.18.1",
+ "parse5": "^8.0.1",
+ "parse5-htmlparser2-tree-adapter": "^8.0.1",
+ "set-cookie-parser": "^3.1.2",
},
},
"packages/parser": {
"name": "@getlang/parser",
- "version": "0.4.0",
+ "version": "0.4.3",
"dependencies": {
"@getlang/ast": "workspace:^0.1.0",
- "@getlang/lib": "workspace:^0.2.0",
+ "@getlang/lib": "workspace:^0.2.1",
"@getlang/walker": "workspace:^0.1.0",
"@types/moo": "^0.5.10",
"@types/nearley": "^2.11.5",
- "acorn": "^8.15.0",
- "estree-toolkit": "^1.7.13",
- "globals": "^16.4.0",
- "lodash-es": "^4.17.21",
- "moo": "^0.5.2",
+ "acorn": "^8.18.0",
+ "estree-toolkit": "^1.7.14",
+ "globals": "^17.12.0",
+ "lodash-es": "^4.18.1",
+ "moo": "^0.5.3",
"nearley": "^2.20.1",
- "prettier": "^3.6.2",
+ "prettier": "^3.9.8",
},
"devDependencies": {
"@types/lodash-es": "^4.17.12",
@@ -89,79 +92,81 @@
"name": "test",
"dependencies": {
"@getlang/get": "workspace:*",
- "@getlang/lib": "workspace:^0.1.5",
+ "@getlang/lib": "workspace:^0.2.1",
"@getlang/parser": "workspace:*",
- "dedent": "^1.7.0",
+ "dedent": "^1.7.2",
},
"devDependencies": {
- "jest-diff": "^30.1.2",
+ "@types/bun": "^1.4.2",
+ "jest-diff": "^30.5.1",
},
},
},
+ "overrides": {
+ "domhandler": "^6.0.1",
+ },
"packages": {
- "@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="],
-
- "@biomejs/biome": ["@biomejs/biome@2.2.4", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.2.4", "@biomejs/cli-darwin-x64": "2.2.4", "@biomejs/cli-linux-arm64": "2.2.4", "@biomejs/cli-linux-arm64-musl": "2.2.4", "@biomejs/cli-linux-x64": "2.2.4", "@biomejs/cli-linux-x64-musl": "2.2.4", "@biomejs/cli-win32-arm64": "2.2.4", "@biomejs/cli-win32-x64": "2.2.4" }, "bin": { "biome": "bin/biome" } }, "sha512-TBHU5bUy/Ok6m8c0y3pZiuO/BZoY/OcGxoLlrfQof5s8ISVwbVBdFINPQZyFfKwil8XibYWb7JMwnT8wT4WVPg=="],
+ "@biomejs/biome": ["@biomejs/biome@2.5.14", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.5.14", "@biomejs/cli-darwin-x64": "2.5.14", "@biomejs/cli-linux-arm64": "2.5.14", "@biomejs/cli-linux-arm64-musl": "2.5.14", "@biomejs/cli-linux-x64": "2.5.14", "@biomejs/cli-linux-x64-musl": "2.5.14", "@biomejs/cli-win32-arm64": "2.5.14", "@biomejs/cli-win32-x64": "2.5.14" }, "bin": { "biome": "bin/biome" } }, "sha512-0FabLIjd4M/dm8VFI86RMaLLdgepzbdfiAL2R8cr7V81OYYrP1w7Z73KfAwPK5h9SrEBXTzNG2y+mBwPo9xRnw=="],
- "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RJe2uiyaloN4hne4d2+qVj3d3gFJFbmrr5PYtkkjei1O9c+BjGXgpUPVbi8Pl8syumhzJjFsSIYkcLt2VlVLMA=="],
+ "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.5.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-UnzaXO65L4tsZimFITFP2M121GyhDcWFrT3pL5ZJ5U4XcS/0L5VHYytVohdCf/gnDUFHgl2I9xnt5bV/J1kxHQ=="],
- "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-cFsdB4ePanVWfTnPVaUX+yr8qV8ifxjBKMkZwN7gKb20qXPxd/PmwqUH8mY5wnM9+U0QwM76CxFyBRJhC9tQwg=="],
+ "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.5.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-kiy8qA16K93J7uvFfWi4LgjqDpnRKyePAna6A0Y4jxyUga35SYpIZ2cNWlhy0lsfgqRenCpfymnJWEZ6mgpRgA=="],
- "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-M/Iz48p4NAzMXOuH+tsn5BvG/Jb07KOMTdSVwJpicmhN309BeEyRyQX+n1XDF0JVSlu28+hiTQ2L4rZPvu7nMw=="],
+ "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.5.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-vO/9BaU1n30CiFNLx49gMTMtbCAAqlo/EqFoG0BU3deQInTbJrmXSmTQ9e3FoDZIKQnvSLDVNL4lx1ci7y1T1Q=="],
- "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-7TNPkMQEWfjvJDaZRSkDCPT/2r5ESFPKx+TEev+I2BXDGIjfCZk2+b88FOhnJNHtksbOZv8ZWnxrA5gyTYhSsQ=="],
+ "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.5.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-SJ9PrZkBnnH9dHJDnxk34vKs0GB2dbsioaft6/hPhWJ7AHpwYH83Isnhj0FSRpFkGgpVfJ1lds23ApB2czUDLQ=="],
- "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-orr3nnf2Dpb2ssl6aihQtvcKtLySLta4E2UcXdp7+RTa7mfJjBgIsbS0B9GC8gVu0hjOu021aU8b3/I1tn+pVQ=="],
+ "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.5.14", "", { "os": "linux", "cpu": "x64" }, "sha512-VHZRa7CCQBUWKxNwUvHJeuW03WFRgN5NWO//SDGOitc9QIeNyfA42V9zlKm+x82xFSG9Bzi5fi+hbhm9anO8yA=="],
- "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-m41nFDS0ksXK2gwXL6W6yZTYPMH0LughqbsxInSKetoH6morVj43szqKx79Iudkp8WRT5SxSh7qVb8KCUiewGg=="],
+ "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.5.14", "", { "os": "linux", "cpu": "x64" }, "sha512-2kI5PrMgW5dcEZYrstLPmUmCwkUwZY39rP4BN93Vxbwcs2O57LDQOktUZZYPvvspN5i0mhGr3TJtF5sU26NUWg=="],
- "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.2.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-NXnfTeKHDFUWfxAefa57DiGmu9VyKi0cDqFpdI+1hJWQjGJhJutHPX0b5m+eXvTKOaf+brU+P0JrQAZMb5yYaQ=="],
+ "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.5.14", "", { "os": "win32", "cpu": "arm64" }, "sha512-pHgAFffmZtaYoxavEsWEYNvcA7NwOIjLyqw2HXyLbt16xYryX0L4fMV2u0G9ag6LNYPIoqWaWqzUcnc6rLGGXg=="],
- "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.2.4", "", { "os": "win32", "cpu": "x64" }, "sha512-3Y4V4zVRarVh/B/eSHczR4LYoSVyv3Dfuvm3cWs5w/HScccS0+Wt/lHOcDTRYeHjQmMYVC3rIRWqyN2EI52+zg=="],
+ "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.5.14", "", { "os": "win32", "cpu": "x64" }, "sha512-oJWmBhoHsnhUKIke+0gXDX0mltJrWHA1UyHsrTlXwX0TL64ilVZAo+TYZm97baecV0esBdpzy3k96q+09JaZUQ=="],
- "@changesets/apply-release-plan": ["@changesets/apply-release-plan@7.0.13", "", { "dependencies": { "@changesets/config": "^3.1.1", "@changesets/get-version-range-type": "^0.4.0", "@changesets/git": "^3.0.4", "@changesets/should-skip-package": "^0.1.2", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "detect-indent": "^6.0.0", "fs-extra": "^7.0.1", "lodash.startcase": "^4.4.0", "outdent": "^0.5.0", "prettier": "^2.7.1", "resolve-from": "^5.0.0", "semver": "^7.5.3" } }, "sha512-BIW7bofD2yAWoE8H4V40FikC+1nNFEKBisMECccS16W1rt6qqhNTBDmIw5HaqmMgtLNz9e7oiALiEUuKrQ4oHg=="],
+ "@changesets/apply-release-plan": ["@changesets/apply-release-plan@8.1.1", "", { "dependencies": { "@changesets/config": "^4.0.1", "@changesets/format": "^0.1.2", "@changesets/git": "^4.0.1", "@changesets/should-skip-package": "^1.0.0", "@changesets/types": "^7.0.0", "import-meta-resolve": "^4.2.0", "jsonc-parser": "^3.3.1", "semver": "^7.8.1" } }, "sha512-nk2Hbq3M9NeHMdaIRBDvawKrQJzXB9sGyBUE5yWnIKtvdcNCPj75zBekJYr0gTT2ecJH3eFeTrc8eisPImcv0Q=="],
- "@changesets/assemble-release-plan": ["@changesets/assemble-release-plan@6.0.9", "", { "dependencies": { "@changesets/errors": "^0.2.0", "@changesets/get-dependents-graph": "^2.1.3", "@changesets/should-skip-package": "^0.1.2", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "semver": "^7.5.3" } }, "sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ=="],
+ "@changesets/assemble-release-plan": ["@changesets/assemble-release-plan@7.0.0", "", { "dependencies": { "@changesets/errors": "^1.0.0", "@changesets/get-dependents-graph": "^3.0.0", "@changesets/should-skip-package": "^1.0.0", "@changesets/types": "^7.0.0", "semver": "^7.8.1" } }, "sha512-oEW8BxdA604kGGtDSCiHr5w9Tv4UWe9I2k61IBNZzCOE1kbYaJj4v+lFQNgcEZFkUc2pV/+hASErGDvpJOZCTg=="],
- "@changesets/changelog-git": ["@changesets/changelog-git@0.2.1", "", { "dependencies": { "@changesets/types": "^6.1.0" } }, "sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q=="],
+ "@changesets/changelog-git": ["@changesets/changelog-git@1.0.0", "", { "dependencies": { "@changesets/types": "^7.0.0" } }, "sha512-3Dst2Ime2Op5nd4XmWJLPIgp11ZFqJqSkVug9izK6TDcIV4YlhPS4ECbEVR+eGI0bk0r1ItogD4j2Oli87bJrA=="],
- "@changesets/changelog-github": ["@changesets/changelog-github@0.5.1", "", { "dependencies": { "@changesets/get-github-info": "^0.6.0", "@changesets/types": "^6.1.0", "dotenv": "^8.1.0" } }, "sha512-BVuHtF+hrhUScSoHnJwTELB4/INQxVFc+P/Qdt20BLiBFIHFJDDUaGsZw+8fQeJTRP5hJZrzpt3oZWh0G19rAQ=="],
+ "@changesets/changelog-github": ["@changesets/changelog-github@1.0.1", "", { "dependencies": { "@changesets/get-github-info": "^1.0.1", "@changesets/types": "^7.0.0" } }, "sha512-QUcrV7878yHlWPXXPA6gqSxNKwtVHCd1K22L7ZAoJw2yGy8K4QvjwOStD75+1Q9KD9ZSUgGS94HuYdd7HOVtpA=="],
- "@changesets/cli": ["@changesets/cli@2.29.7", "", { "dependencies": { "@changesets/apply-release-plan": "^7.0.13", "@changesets/assemble-release-plan": "^6.0.9", "@changesets/changelog-git": "^0.2.1", "@changesets/config": "^3.1.1", "@changesets/errors": "^0.2.0", "@changesets/get-dependents-graph": "^2.1.3", "@changesets/get-release-plan": "^4.0.13", "@changesets/git": "^3.0.4", "@changesets/logger": "^0.1.1", "@changesets/pre": "^2.0.2", "@changesets/read": "^0.6.5", "@changesets/should-skip-package": "^0.1.2", "@changesets/types": "^6.1.0", "@changesets/write": "^0.4.0", "@inquirer/external-editor": "^1.0.0", "@manypkg/get-packages": "^1.1.3", "ansi-colors": "^4.1.3", "ci-info": "^3.7.0", "enquirer": "^2.4.1", "fs-extra": "^7.0.1", "mri": "^1.2.0", "p-limit": "^2.2.0", "package-manager-detector": "^0.2.0", "picocolors": "^1.1.0", "resolve-from": "^5.0.0", "semver": "^7.5.3", "spawndamnit": "^3.0.1", "term-size": "^2.1.0" }, "bin": { "changeset": "bin.js" } }, "sha512-R7RqWoaksyyKXbKXBTbT4REdy22yH81mcFK6sWtqSanxUCbUi9Uf+6aqxZtDQouIqPdem2W56CdxXgsxdq7FLQ=="],
+ "@changesets/cli": ["@changesets/cli@3.0.3", "", { "dependencies": { "@changesets/apply-release-plan": "^8.1.1", "@changesets/assemble-release-plan": "^7.0.0", "@changesets/changelog-git": "^1.0.0", "@changesets/config": "^4.0.1", "@changesets/errors": "^1.0.0", "@changesets/get-dependents-graph": "^3.0.0", "@changesets/git": "^4.0.1", "@changesets/pre": "^3.0.0", "@changesets/read": "^1.0.1", "@changesets/should-skip-package": "^1.0.0", "@changesets/types": "^7.0.0", "@changesets/write": "^1.0.1", "@clack/prompts": "^1.7.0", "@manypkg/get-packages": "^3.1.0", "@pnpm/deps.graph-sequencer": "^1100.0.1", "cac": "^7.0.0", "import-meta-resolve": "^4.2.0", "launch-editor": "^2.14.1", "package-manager-detector": "^1.6.0", "semver": "^7.8.1", "tinyexec": "^1.3.1" }, "bin": { "changeset": "bin.js" } }, "sha512-L1i67bMfkK6iC/kDejuNO4pFgTRcWIObsD6Qof2woP1I4M8tj17DGlcpRaTzTv1DYSP5EMwWdEtR8X0Pj5Jg3Q=="],
- "@changesets/config": ["@changesets/config@3.1.1", "", { "dependencies": { "@changesets/errors": "^0.2.0", "@changesets/get-dependents-graph": "^2.1.3", "@changesets/logger": "^0.1.1", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "fs-extra": "^7.0.1", "micromatch": "^4.0.8" } }, "sha512-bd+3Ap2TKXxljCggI0mKPfzCQKeV/TU4yO2h2C6vAihIo8tzseAn2e7klSuiyYYXvgu53zMN1OeYMIQkaQoWnA=="],
+ "@changesets/config": ["@changesets/config@4.0.1", "", { "dependencies": { "@changesets/get-dependents-graph": "^3.0.0", "@changesets/should-skip-package": "^1.0.0", "@changesets/types": "^7.0.0", "@manypkg/get-packages": "^3.1.0", "picomatch": "^4.0.7" } }, "sha512-PxpxSQLQSLDjceAgRq+4FWlU+HflDIw03mmPVipxoQx9xrXFUjmqTy3SE+n/2t+DqPdpPiLWVr5NRiLZvjyLwg=="],
- "@changesets/errors": ["@changesets/errors@0.2.0", "", { "dependencies": { "extendable-error": "^0.1.5" } }, "sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow=="],
+ "@changesets/errors": ["@changesets/errors@1.0.0", "", {}, "sha512-ElN/mEzn6zmETgjwf5MclCMa9ef59sAR0lfO8VSYIsiRvbC2FbLB/92EoYw10Sl0kGixxHFiJZUSv7dA+YpR8g=="],
- "@changesets/get-dependents-graph": ["@changesets/get-dependents-graph@2.1.3", "", { "dependencies": { "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "picocolors": "^1.1.0", "semver": "^7.5.3" } }, "sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ=="],
+ "@changesets/format": ["@changesets/format@0.1.2", "", { "dependencies": { "package-manager-detector": "^1.8.0", "tinyexec": "^1.3.0" } }, "sha512-Caez5XtNXCFS/G5bwyav3wuXL0tMxVd2ZGbaumWbzN08tyzO21asCw7JZhNtVsAZDCvDRUzZN+Iit9SyRITSYA=="],
- "@changesets/get-github-info": ["@changesets/get-github-info@0.6.0", "", { "dependencies": { "dataloader": "^1.4.0", "node-fetch": "^2.5.0" } }, "sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA=="],
+ "@changesets/get-dependents-graph": ["@changesets/get-dependents-graph@3.0.0", "", { "dependencies": { "@changesets/types": "^7.0.0", "semver": "^7.8.1" } }, "sha512-ji/t5wFA1zREKXRUePE6Qi+Qu2UgxCeSSGQrphezwvQZrp49B7sJ+8+wvM0tA7zPeSxYKCojDy3WWgrl+s+awg=="],
- "@changesets/get-release-plan": ["@changesets/get-release-plan@4.0.13", "", { "dependencies": { "@changesets/assemble-release-plan": "^6.0.9", "@changesets/config": "^3.1.1", "@changesets/pre": "^2.0.2", "@changesets/read": "^0.6.5", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3" } }, "sha512-DWG1pus72FcNeXkM12tx+xtExyH/c9I1z+2aXlObH3i9YA7+WZEVaiHzHl03thpvAgWTRaH64MpfHxozfF7Dvg=="],
+ "@changesets/get-github-info": ["@changesets/get-github-info@1.0.1", "", { "dependencies": { "dataloader": "^2.2.3" } }, "sha512-ifLQCky/ZtDgZ4xCiUMjnLZSJ8xk52iIzMJbBBPlZWjr2CiTNTaTDddIVWKicrUAdWuLWL7PUw2fNa1yPwLpIg=="],
- "@changesets/get-version-range-type": ["@changesets/get-version-range-type@0.4.0", "", {}, "sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ=="],
+ "@changesets/git": ["@changesets/git@4.0.1", "", { "dependencies": { "@changesets/errors": "^1.0.0", "@changesets/types": "^7.0.0", "@manypkg/get-packages": "^3.1.0", "picomatch": "^4.0.4", "tinyexec": "^1.3.0" } }, "sha512-6vWpIAC4LkpmlqaIu37ViT5enyd9+uBwAiGqCGhASvkSHBgx4PrtTGXWTMFYpDmZbjgyonyVgMciPrW4MqtJsA=="],
- "@changesets/git": ["@changesets/git@3.0.4", "", { "dependencies": { "@changesets/errors": "^0.2.0", "@manypkg/get-packages": "^1.1.3", "is-subdir": "^1.1.1", "micromatch": "^4.0.8", "spawndamnit": "^3.0.1" } }, "sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw=="],
+ "@changesets/parse": ["@changesets/parse@1.0.0", "", { "dependencies": { "@changesets/types": "^7.0.0", "yaml": "^2.9.0" } }, "sha512-P0iaMb9p9CRYZiTgAllEIF9AUMQHIy1G72tKlcIqJp61icZSsKQNiOPdxAMZG8m/DvZwt/oz5xEbTpike//dWg=="],
- "@changesets/logger": ["@changesets/logger@0.1.1", "", { "dependencies": { "picocolors": "^1.1.0" } }, "sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg=="],
+ "@changesets/pre": ["@changesets/pre@3.0.0", "", { "dependencies": { "@changesets/errors": "^1.0.0", "@changesets/types": "^7.0.0", "@manypkg/get-packages": "^3.1.0" } }, "sha512-Zm/6YliV/a2oeWTqHJf6KxLrQwgcK1i/BRDl2m0EKZvbnxV5fG9QRhwJJGshjsZTUTS6dkfURQ2K6aAvgNw/3Q=="],
- "@changesets/parse": ["@changesets/parse@0.4.1", "", { "dependencies": { "@changesets/types": "^6.1.0", "js-yaml": "^3.13.1" } }, "sha512-iwksMs5Bf/wUItfcg+OXrEpravm5rEd9Bf4oyIPL4kVTmJQ7PNDSd6MDYkpSJR1pn7tz/k8Zf2DhTCqX08Ou+Q=="],
+ "@changesets/read": ["@changesets/read@1.0.1", "", { "dependencies": { "@changesets/git": "^4.0.1", "@changesets/parse": "^1.0.0", "@changesets/types": "^7.0.0" } }, "sha512-nzvSC6RcTiWf/dsuwZFXpLzGGsRHYCL68U3uHV7srsulU93aVWY7u2GEJiDZ+4GIIElfaW5EqtKC0UHroY+LTQ=="],
- "@changesets/pre": ["@changesets/pre@2.0.2", "", { "dependencies": { "@changesets/errors": "^0.2.0", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "fs-extra": "^7.0.1" } }, "sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug=="],
+ "@changesets/should-skip-package": ["@changesets/should-skip-package@1.0.0", "", { "dependencies": { "@changesets/types": "^7.0.0" } }, "sha512-pwqoJmbONn1XgXmZXPEExgAaT+HdZLjALFTDgIm+PnS5KeO2nLtzA2/Q+4aMFY14kFMuXKG30MObhvDzWgzDgg=="],
- "@changesets/read": ["@changesets/read@0.6.5", "", { "dependencies": { "@changesets/git": "^3.0.4", "@changesets/logger": "^0.1.1", "@changesets/parse": "^0.4.1", "@changesets/types": "^6.1.0", "fs-extra": "^7.0.1", "p-filter": "^2.1.0", "picocolors": "^1.1.0" } }, "sha512-UPzNGhsSjHD3Veb0xO/MwvasGe8eMyNrR/sT9gR8Q3DhOQZirgKhhXv/8hVsI0QpPjR004Z9iFxoJU6in3uGMg=="],
+ "@changesets/types": ["@changesets/types@7.0.0", "", {}, "sha512-c5GoiQyt3pxiXjrWSNoP8/GRf4kG+VnKzovx1OQM8dYYALlSwgedmkPmJ+ZqGxqwg9D3Bkj85Uo4KLd5BN3A0w=="],
- "@changesets/should-skip-package": ["@changesets/should-skip-package@0.1.2", "", { "dependencies": { "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3" } }, "sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw=="],
+ "@changesets/write": ["@changesets/write@1.0.1", "", { "dependencies": { "@changesets/format": "^0.1.1", "@changesets/types": "^7.0.0", "human-id": "^4.2.0" } }, "sha512-q/ThtP9gcnEP6xlv7LrY26C2mHqdGBti/MmOVngt/M/oIGYkssmQGxPK9WzBNt2juVcH/vml2WQ+ra8LXYOTaA=="],
- "@changesets/types": ["@changesets/types@6.1.0", "", {}, "sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA=="],
+ "@clack/core": ["@clack/core@1.5.1", "", { "dependencies": { "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" } }, "sha512-iHTrHA8MtVuLl2TfZySmcKv1qO2PoyC9Z7pfSDozEuV5vtY3/wcOPKJXlqJ5Oq2Cx5DDGQGAMVx6HZfRRoVEbQ=="],
- "@changesets/write": ["@changesets/write@0.4.0", "", { "dependencies": { "@changesets/types": "^6.1.0", "fs-extra": "^7.0.1", "human-id": "^4.1.1", "prettier": "^2.7.1" } }, "sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q=="],
+ "@clack/prompts": ["@clack/prompts@1.8.1", "", { "dependencies": { "@clack/core": "1.5.1", "fast-string-width": "^3.0.2", "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" } }, "sha512-dlT1m5e/0yUL0kRNcQn7yGLVThkgbB0Ga/1AmfDDC/8ik6AIiSf2QLQO2zPYvefsHP0aFgxO93cVLCCfDp7kzQ=="],
- "@emnapi/core": ["@emnapi/core@1.5.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg=="],
+ "@emnapi/core": ["@emnapi/core@1.11.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA=="],
- "@emnapi/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="],
+ "@emnapi/runtime": ["@emnapi/runtime@1.11.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA=="],
- "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
+ "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="],
"@getlang/ast": ["@getlang/ast@workspace:packages/ast"],
@@ -175,390 +180,330 @@
"@getlang/xpath": ["@getlang/xpath@0.0.35-0", "", {}, "sha512-kXe2kSVp0cdra0q1N8px43oKz+jOJ9CiJ1vrDYJ/cEQp0T+DSTMSLf7XdeIiIPqoj/N1bJMdV5eqPyB7wo/G3w=="],
- "@inquirer/external-editor": ["@inquirer/external-editor@1.0.1", "", { "dependencies": { "chardet": "^2.1.0", "iconv-lite": "^0.6.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-Oau4yL24d2B5IL4ma4UpbQigkVhzPDXLoqy1ggK4gnHg/stmkffJE4oOXHXF3uz0UEpywG68KcyXsyYpA1Re/Q=="],
+ "@jest/diff-sequences": ["@jest/diff-sequences@30.5.0", "", {}, "sha512-OsqBjHXCn8cadasoAZBP6nWYvMsRhpMzGXTpxJ5aO04NlbdhIz+FVe3q49l0AwVhsz/cEmIpBes6gAFl1/dWQg=="],
- "@jest/diff-sequences": ["@jest/diff-sequences@30.0.1", "", {}, "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw=="],
+ "@jest/get-type": ["@jest/get-type@30.5.0", "", {}, "sha512-9/2VUPitAjmBzbvDvqrxmvB7BzWsBW0WmkkojX1ODuxX1NLGxx9gfaZpHB0z8DtJ9uhGNmZG/VXBhf8uO0OV8Q=="],
- "@jest/get-type": ["@jest/get-type@30.1.0", "", {}, "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA=="],
+ "@jest/react-is-18": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
- "@jest/schemas": ["@jest/schemas@30.0.5", "", { "dependencies": { "@sinclair/typebox": "^0.34.0" } }, "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA=="],
+ "@jest/react-is-19": ["react-is@19.3.0", "", {}, "sha512-UpMYezM4v5/18F28aC66AEsjXIgE02kyEMH6yLdgLXu/UTfa1Ntwck/nNLrbqJsEXW7gPb0coNO9FQse9WTovA=="],
- "@manypkg/find-root": ["@manypkg/find-root@1.1.0", "", { "dependencies": { "@babel/runtime": "^7.5.5", "@types/node": "^12.7.1", "find-up": "^4.1.0", "fs-extra": "^8.1.0" } }, "sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA=="],
+ "@jest/schemas": ["@jest/schemas@30.5.0", "", { "dependencies": { "@sinclair/typebox": "^0.34.0" } }, "sha512-/hunigyNpc4RCjC0VaW3f5RCUZVM2+WQ65qP7z083Gmvac7or2LI50XVNOtE4YPgBpV0yxYiAgorAPGniCoJmg=="],
- "@manypkg/get-packages": ["@manypkg/get-packages@1.1.3", "", { "dependencies": { "@babel/runtime": "^7.5.5", "@changesets/types": "^4.0.1", "@manypkg/find-root": "^1.1.0", "fs-extra": "^8.1.0", "globby": "^11.0.0", "read-yaml-file": "^1.1.0" } }, "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A=="],
+ "@manypkg/find-root": ["@manypkg/find-root@3.1.0", "", { "dependencies": { "@manypkg/tools": "^2.1.0" } }, "sha512-BcSqCyKhBVZ5YkSzOiheMCV41kqAFptW6xGqYSTjkVTl9XQpr+pqHhwgGCOHQtjDCv7Is6EFyA14Sm5GVbVABA=="],
- "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.3", "", { "dependencies": { "@emnapi/core": "^1.4.5", "@emnapi/runtime": "^1.4.5", "@tybys/wasm-util": "^0.10.0" } }, "sha512-rZxtMsLwjdXkMUGC3WwsPwLNVqVqnTJT6MNIB6e+5fhMcSCPP0AOsNWuMQ5mdCq6HNjs/ZeWAEchpqeprqBD2Q=="],
+ "@manypkg/get-packages": ["@manypkg/get-packages@3.1.0", "", { "dependencies": { "@manypkg/find-root": "^3.1.0", "@manypkg/tools": "^2.1.0" } }, "sha512-0TbBVyvPrP7xGYBI/cP8UP+yl/z+HtbTttAD7FMAJgn/kXOTwh5/60TsqP9ZYY710forNfyV0N8P/IE/ujGZJg=="],
- "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
+ "@manypkg/tools": ["@manypkg/tools@2.1.2", "", { "dependencies": { "jju": "^1.4.0", "tinyglobby": "^0.2.13", "yaml": "^2.9.0" } }, "sha512-6QEf6yqFbETdwGITKq57aYoPfX/3K8XFNwsAlx0C1M7o8cb79sv1M3w+tWuWvIcSbNqrLF7OD7YpZMVVz335hQ=="],
- "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
+ "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.2.4", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" } }, "sha512-AJxoUD2/15ESHbvpcyjU274nsAPLuOtPHCk0vKJM5pj//Fg/B1FXNWjPnXTT9PymCYYiHo4zPj0ZomXBKhoy7g=="],
- "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
+ "@oxc-parser/binding-android-arm-eabi": ["@oxc-parser/binding-android-arm-eabi@0.150.0", "", { "os": "android", "cpu": "arm" }, "sha512-oQef2Zu4Prz1KLKznz3HqZzU9uVoA5PMoDZuuLmqms7hKmKSAPzlaMnLllJq3t+rgKmfJJ2siPrpZfFrW06btw=="],
- "@oxc-resolver/binding-android-arm-eabi": ["@oxc-resolver/binding-android-arm-eabi@11.7.1", "", { "os": "android", "cpu": "arm" }, "sha512-K0gF1mD6CYMAuX0dMWe6XW1Js00xCOBh/+ZAAJReQMa4+jmAk3bIeitsc8VnDthDbzOOKp3riizP3o/tBvNpgw=="],
+ "@oxc-parser/binding-android-arm64": ["@oxc-parser/binding-android-arm64@0.150.0", "", { "os": "android", "cpu": "arm64" }, "sha512-B6ofpoFiAUwIZ0MJ2IgHPvZK8FAtL4qzSZRwOkAKIfxEobE1mQC8nDdiFZj7pUaJiVUVCsfkMsBJKedzO8rZvA=="],
- "@oxc-resolver/binding-android-arm64": ["@oxc-resolver/binding-android-arm64@11.7.1", "", { "os": "android", "cpu": "arm64" }, "sha512-O1XEX/KxKX7baPgYHahP+3vT+9f4gasPA0px4DYrjy1mN9wWQqJPLLo/PO3cBw3qI3qRaaiAGT3eJSs8rKu8mA=="],
+ "@oxc-parser/binding-darwin-arm64": ["@oxc-parser/binding-darwin-arm64@0.150.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-J+9IHKzx/bSz1JetOfD4zKXSK9sOm4/a7+0qomJODcTL6JsRXGeV/ZdkAPSIDydfFmWzYCraMlQEosSZEyBYkQ=="],
- "@oxc-resolver/binding-darwin-arm64": ["@oxc-resolver/binding-darwin-arm64@11.7.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-OSCJlXUTvGoal5dTMkdacmXL2R3YQ+97R7NMSdjkUVnh3TxvGBhoF9OebqY3PR7w2gQaY5LX+Ju+dYeHGBCGgw=="],
+ "@oxc-parser/binding-darwin-x64": ["@oxc-parser/binding-darwin-x64@0.150.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-v6IPfcAcSYrBWXV5Tce1DmxDMXLhEYpIIWiRFPJopgCVscZdLaV4MRQOUxvL3usQlw+yrwYOjBFB9IwBx+jUiQ=="],
- "@oxc-resolver/binding-darwin-x64": ["@oxc-resolver/binding-darwin-x64@11.7.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-d0jKwK4r4Yw19xSijyt7wHZT77xh3v4GnJSbvEiPavLms27zqc//BqYJUSp9XgOTOkyFQ+oHno47JNiLTnsSnQ=="],
+ "@oxc-parser/binding-freebsd-x64": ["@oxc-parser/binding-freebsd-x64@0.150.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-AoR/4jD02HET0KO0yNT4nbTE+XJUxiO9jB1X/ycEjUE3WrIJ3IjV/Vf+gskhWLcqqeXfvNnkDtBR7epllAm88A=="],
- "@oxc-resolver/binding-freebsd-x64": ["@oxc-resolver/binding-freebsd-x64@11.7.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-oNch5OpAnxFjukDZ5GJkuEDEPPYDirm10q2cJcbK0SETVM0rY+ou1cLqJAJC9R/dULbqGKC9fv2kuyuw9M6Fig=="],
+ "@oxc-parser/binding-linux-arm-gnueabihf": ["@oxc-parser/binding-linux-arm-gnueabihf@0.150.0", "", { "os": "linux", "cpu": "arm" }, "sha512-A/hycCFjLUrCmLoL5O/vBp40ohlaXO1Ta3v5hqYZxicYFs129wZmgZJggcW4mYGYbZebQLhup+N8JjeQl8qwyw=="],
- "@oxc-resolver/binding-linux-arm-gnueabihf": ["@oxc-resolver/binding-linux-arm-gnueabihf@11.7.1", "", { "os": "linux", "cpu": "arm" }, "sha512-ldUPUfV/0L56fTSfzUo86Bmgov8SAfau8Q4Y3WiAiQi6WHLA239abTZZViLZuXvrC+4RQF/kD0ySqKfBjW/X9g=="],
+ "@oxc-parser/binding-linux-arm-musleabihf": ["@oxc-parser/binding-linux-arm-musleabihf@0.150.0", "", { "os": "linux", "cpu": "arm" }, "sha512-pbqahg1Pkz7J4RKmXm30s/iQu99hv64ayXCu8P4p75HcEH5azOdR4eGqiB6lFGkFR3mMpzaYsSKLkS8oJbjmeQ=="],
- "@oxc-resolver/binding-linux-arm-musleabihf": ["@oxc-resolver/binding-linux-arm-musleabihf@11.7.1", "", { "os": "linux", "cpu": "arm" }, "sha512-M+ORXlPV0dXCHleqOYLjKHwxn9kDmcJqnJ7zGZ07vggaxOCnpM6zqyGS92YTTyeYre2AqO3Xrx1D4rnUeozI8g=="],
+ "@oxc-parser/binding-linux-arm64-gnu": ["@oxc-parser/binding-linux-arm64-gnu@0.150.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-HV11aRbBQGwqv8bEo+K/6qr88uB4fEe1mhXncMhlVCrj+WpBSraxrUzHaPVmeQRU6x6x8v/3DuCbbo93rpp+fw=="],
- "@oxc-resolver/binding-linux-arm64-gnu": ["@oxc-resolver/binding-linux-arm64-gnu@11.7.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-ukHZp9Vm07AlxqdOLFf8Bj4inzpt+ISbbODvwwHxX32GfcMLWYYJGAYWc13IGhWoElvWnI7D1M9ifDGyTNRGzg=="],
+ "@oxc-parser/binding-linux-arm64-musl": ["@oxc-parser/binding-linux-arm64-musl@0.150.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-k6pVkJqALwtEuP4zukVhGRhdIy4+ofChUIUUsAHHyqDZlNsknmel3JjbggrJiWGaes6h/dIcWmEXsKW4SmK9oQ=="],
- "@oxc-resolver/binding-linux-arm64-musl": ["@oxc-resolver/binding-linux-arm64-musl@11.7.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-atkZ1OIt6t90kjQz1iqq6cN3OpfPG5zUJlO64Vd1ieYeqHRkOFeRgnWEobTePUHi34NlYr7mNZqIaAg7gjPUFg=="],
+ "@oxc-parser/binding-linux-ppc64-gnu": ["@oxc-parser/binding-linux-ppc64-gnu@0.150.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-tEFg39mw/rHO5n8GK2DR4ZMFfsPQZtnQIPbsIpjoQRomJc/2tRfsCSmCT6gNit+NZGoeJG5aH9ATDH5bf0WnoQ=="],
- "@oxc-resolver/binding-linux-ppc64-gnu": ["@oxc-resolver/binding-linux-ppc64-gnu@11.7.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-HGgV4z3JwVF4Qvg2a1GhDnqn8mKLihy5Gp4rMfqNIAlERPSyIxo8oPQIL1XQKLYyyrkEEO99uwM+4cQGwhtbpQ=="],
+ "@oxc-parser/binding-linux-riscv64-gnu": ["@oxc-parser/binding-linux-riscv64-gnu@0.150.0", "", { "os": "linux", "cpu": "none" }, "sha512-0JO7IFkoek6HqV589Menx3hJySNXi6quRhO4tq2P7kpEHKEXoDATnoPVUpn5B7gDH2KLkdo751N0uIrGJFCTCw=="],
- "@oxc-resolver/binding-linux-riscv64-gnu": ["@oxc-resolver/binding-linux-riscv64-gnu@11.7.1", "", { "os": "linux", "cpu": "none" }, "sha512-+vCO7iOR1s6VGefV02R2a702IASNWhSNm/MrR8RcWjKChmU0G+d1iC0oToUrGC4ovAEfstx2/O8EkROnfcLgrA=="],
+ "@oxc-parser/binding-linux-riscv64-musl": ["@oxc-parser/binding-linux-riscv64-musl@0.150.0", "", { "os": "linux", "cpu": "none" }, "sha512-7XPzREnyAS5wHU9aB+49Uaqgoo1gVCklHc3DRlc3fJy2tXD/eAJFN1QFz/crj+Ulup5P1+axNREF+/RGaB/IRA=="],
- "@oxc-resolver/binding-linux-riscv64-musl": ["@oxc-resolver/binding-linux-riscv64-musl@11.7.1", "", { "os": "linux", "cpu": "none" }, "sha512-3folNmS5gYNFy/9HYzLcdeThqAGvDJU0gQKrhHn7RPWQa58yZ0ZPpBMk6KRSSO61+wkchkL+0sdcLsoe5wZW8g=="],
+ "@oxc-parser/binding-linux-s390x-gnu": ["@oxc-parser/binding-linux-s390x-gnu@0.150.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-7n7ZxcbRWDFaTdyj8M8p0O9OfzoMKm8O6syBAIgcSutbOALq0Bb9G52Me+XH0anMLZV+NgXc726gqgG2q39vcQ=="],
- "@oxc-resolver/binding-linux-s390x-gnu": ["@oxc-resolver/binding-linux-s390x-gnu@11.7.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-Ceo4z6g8vqPUKADROFL0b7MoyXlUdOBYCxTDu/fhd/5I3Ydk2S6bxkjJdzpBdlu+h2Z+eS9lTHFvkwkaORMPzw=="],
+ "@oxc-parser/binding-linux-x64-gnu": ["@oxc-parser/binding-linux-x64-gnu@0.150.0", "", { "os": "linux", "cpu": "x64" }, "sha512-Vx0GSA9ZCRTUiczoEQnIIyXkMvtEY8uc6IiwLQtMe5ci2sXPqjrry0Ek5fsPP1k2kCzkML3ow9UOOEgnEDi7Bw=="],
- "@oxc-resolver/binding-linux-x64-gnu": ["@oxc-resolver/binding-linux-x64-gnu@11.7.1", "", { "os": "linux", "cpu": "x64" }, "sha512-QyFW5e43imQLxiBpCImhOiP4hY9coWGjroEm8elDqGNNaA7vXooaMQS2N3avMQawSaKhsb/3RemxaZ852XG38Q=="],
+ "@oxc-parser/binding-linux-x64-musl": ["@oxc-parser/binding-linux-x64-musl@0.150.0", "", { "os": "linux", "cpu": "x64" }, "sha512-ii4/9m3viDLssMnfXU7/Pni/3nYplApuGayceX4qsVGaqqQJCx3tHIH9M/HWIeSty5i8LjS21zPYT6lVIkwLxw=="],
- "@oxc-resolver/binding-linux-x64-musl": ["@oxc-resolver/binding-linux-x64-musl@11.7.1", "", { "os": "linux", "cpu": "x64" }, "sha512-JhuCqCqktqQyQVc37V+eDiP3buCIuyCLpb92tUEyAP8nY3dy2b/ojMrH1ZNnJUlfY/67AqoZPL6nQGAB2WA3Sg=="],
+ "@oxc-parser/binding-openharmony-arm64": ["@oxc-parser/binding-openharmony-arm64@0.150.0", "", { "os": "none", "cpu": "arm64" }, "sha512-ZtoxX5rez36ZWkwtiEhjkCPnlTPoQ2I7lIL0IYZ1yjxMYohbvoOjBmUIZzrf9W/HouONq0omIfTeCWEY+R380w=="],
- "@oxc-resolver/binding-wasm32-wasi": ["@oxc-resolver/binding-wasm32-wasi@11.7.1", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.0.3" }, "cpu": "none" }, "sha512-sMXm5Z2rfBwkCUespZBJCPhCVbgh/fpYQ23BQs0PmnvWoXrGQHWvnvg1p/GYmleN+nwe8strBjfutirZFiC5lA=="],
+ "@oxc-parser/binding-win32-arm64-msvc": ["@oxc-parser/binding-win32-arm64-msvc@0.150.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-VqeRb5JX/bKYBrff7TUDvJyKY0914UzuCkuXIGxJS4FUmvMNfqkCbc7Sq90iMz9DlmAtlggwaBYQ9eg3h3ltiw=="],
- "@oxc-resolver/binding-win32-arm64-msvc": ["@oxc-resolver/binding-win32-arm64-msvc@11.7.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-C/Sam1RJi/h/F618IB/H3pCOhTf+2ArdTqrqQolN8ARV35iWTSezgy6qPjQGj7aWn/9M5vgtCInfS2SwnkBJ4w=="],
+ "@oxc-parser/binding-win32-ia32-msvc": ["@oxc-parser/binding-win32-ia32-msvc@0.150.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-EPqJfeZ4Pgg2BJSsCV8GozxV0FDltRzpVtGVa1r2noJu1iu+opOw3gtBWXwIo9odCT/MdFfyHxdy0/CRqs3OqA=="],
- "@oxc-resolver/binding-win32-ia32-msvc": ["@oxc-resolver/binding-win32-ia32-msvc@11.7.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-iNRgJxOkfmxeq9DiF9S4jtw3vq5kkAm6dsP4RPxoAO/WsShPPHOSlTpOqyB8bSj5Bt9DBLRoI43XcNfDKgM+jA=="],
+ "@oxc-parser/binding-win32-x64-msvc": ["@oxc-parser/binding-win32-x64-msvc@0.150.0", "", { "os": "win32", "cpu": "x64" }, "sha512-n5YMzbqwPQqozbkrexi0lNZrUz5cnPHalYpFWe6Dau7AmKIWNo+y24IwzDuZEQtEdUHuKhXmMMih/MPjOI+CMw=="],
- "@oxc-resolver/binding-win32-x64-msvc": ["@oxc-resolver/binding-win32-x64-msvc@11.7.1", "", { "os": "win32", "cpu": "x64" }, "sha512-MXS81efp8pu2MkjEPu+nDhgoyHwdWUygXYSzIh3gV2A8/qF0PVEzH+EpmKR7Pl8dEZIaG1YXA+CO6bmNZT8oSw=="],
+ "@oxc-project/types": ["@oxc-project/types@0.150.0", "", {}, "sha512-rDS5/31E9HfPl/CIzGrn0DOlvBbXFseQ5URJ9sYMfstbKLD/c6Gm9vmRzRGDdAXyOIL4zmO37lc9RIwYqVruZw=="],
- "@sinclair/typebox": ["@sinclair/typebox@0.34.41", "", {}, "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g=="],
+ "@oxc-resolver/binding-android-arm-eabi": ["@oxc-resolver/binding-android-arm-eabi@11.24.2", "", { "os": "android", "cpu": "arm" }, "sha512-y09e0L0SRI2OA2tUIrjBgoV3eH5hvUKXNkJqXmNo5V2WxIjyC7I7aJfRLMEVpA8yi95f90gFDvO0VMgrDw+vwA=="],
- "@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="],
+ "@oxc-resolver/binding-android-arm64": ["@oxc-resolver/binding-android-arm64@11.24.2", "", { "os": "android", "cpu": "arm64" }, "sha512-cl4icWaZFnLdg8m6qtnh5rBMuGbxc/ptStFHLeCNwr+2cZjkjNwQu/jYRS0CHlnPecOJMpuS5M6/BH+0J/YkEg=="],
- "@types/bun": ["@types/bun@1.2.22", "", { "dependencies": { "bun-types": "1.2.22" } }, "sha512-5A/KrKos2ZcN0c6ljRSOa1fYIyCKhZfIVYeuyb4snnvomnpFqC0tTsEkdqNxbAgExV384OETQ//WAjl3XbYqQA=="],
+ "@oxc-resolver/binding-darwin-arm64": ["@oxc-resolver/binding-darwin-arm64@11.24.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-At29QEMF6HajbQvgY8K6OXnHD1x9rad74xBEfmCB6ZqCGsdq75aK7tOYcTbOanMy8qdIBrfL3SMr3p/lfSlb9w=="],
- "@types/esquery": ["@types/esquery@1.5.4", "", { "dependencies": { "@types/estree": "*" } }, "sha512-yYO4Q8H+KJHKW1rEeSzHxcZi90durqYgWVfnh5K6ZADVBjBv2e1NEveYX5yT2bffgN7RqzH3k9930m+i2yBoMA=="],
+ "@oxc-resolver/binding-darwin-x64": ["@oxc-resolver/binding-darwin-x64@11.24.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-A5Kqr1EUj4oIL5CF4WRssq/o5P0Y11cwoFouMRmQ7YnC/A8V93nv1nb7aSU8HwcgmXropjLNkVTl4MN87cu28Q=="],
- "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
+ "@oxc-resolver/binding-freebsd-x64": ["@oxc-resolver/binding-freebsd-x64@11.24.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-R5xkRBRRz7ceH/P5Jrc6G7FmdUdgpLYyESFAUDVTNQ9K0sGPxcp4ljiwEwEqsvNcQ4sYbMRrWcHHBCu7ksAJVw=="],
- "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="],
+ "@oxc-resolver/binding-linux-arm-gnueabihf": ["@oxc-resolver/binding-linux-arm-gnueabihf@11.24.2", "", { "os": "linux", "cpu": "arm" }, "sha512-k/RuYL4L/R58IBn3wT5ma3Wh4k62bp1eYCFRWCmMsasUOqL+H6sW0VGFadEzKWXFFlz+2uIMoeMk9ySSZJHgbg=="],
- "@types/lodash": ["@types/lodash@4.17.20", "", {}, "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA=="],
+ "@oxc-resolver/binding-linux-arm-musleabihf": ["@oxc-resolver/binding-linux-arm-musleabihf@11.24.2", "", { "os": "linux", "cpu": "arm" }, "sha512-bnHAak3ujYfH5pKk4NieFNbvYvernfoQDgwLddbZ3OtMYrem87/qjlA+u+aKG0oZcqSLGCful/6/CEA+aeAgaA=="],
- "@types/lodash-es": ["@types/lodash-es@4.17.12", "", { "dependencies": { "@types/lodash": "*" } }, "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ=="],
+ "@oxc-resolver/binding-linux-arm64-gnu": ["@oxc-resolver/binding-linux-arm64-gnu@11.24.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-vDT3KHgzYp47gmtNOqL2VNhCyl5Zv643eyxm//A68J8DeUGXrvD1pZFiaT4jSfe+RInfnn1R2yVHye4enx6RnA=="],
- "@types/moo": ["@types/moo@0.5.10", "", {}, "sha512-W6KzyZjXUYpwQfLK1O1UDzqcqYlul+lO7Bt71luyIIyNlOZwJaNeWWdqFs1C/f2hohZvUFHMk6oFNe9Rg48DbA=="],
+ "@oxc-resolver/binding-linux-arm64-musl": ["@oxc-resolver/binding-linux-arm64-musl@11.24.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-+kMlQvbzfyEYtu5FcjE4p+ttBLpKW4d/AsAsuE69BxV6V4twZJeIQZFfD8gh/wqglY0MkPSezWXQH0jBV13MUw=="],
- "@types/nearley": ["@types/nearley@2.11.5", "", {}, "sha512-dM7TrN0bVxGGXTYGx4YhGear8ysLO5SOuouAWM9oltjQ3m9oYa13qi8Z1DJp5zxVMPukvQdsrnZmgzpeuTSEQA=="],
-
- "@types/node": ["@types/node@24.3.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g=="],
+ "@oxc-resolver/binding-linux-ppc64-gnu": ["@oxc-resolver/binding-linux-ppc64-gnu@11.24.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-shjfMhmZ3gq9fv/w7bi3PnZlgOPG+2QAOFf0BJF0EgBSIGZ6PMLN2zbGEblTUYB/NKVDRyYhE2ff3dJ1QqNPkA=="],
- "@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="],
+ "@oxc-resolver/binding-linux-riscv64-gnu": ["@oxc-resolver/binding-linux-riscv64-gnu@11.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-zGelwFR5oRo+b69k8Lrzun86DyUHzfKN6cnjbR9l7Z7NIRznOE/2ZvPa1IUKqAL2PzAXOdwkfVqNvO1H2RlpAw=="],
- "@types/set-cookie-parser": ["@types/set-cookie-parser@2.4.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-GGmQVGpQWUe5qglJozEjZV/5dyxbOOZ0LHe/lqyWssB88Y4svNfst0uqBVscdDeIKl5Jy5+aPSvy7mI9tYRguw=="],
+ "@oxc-resolver/binding-linux-riscv64-musl": ["@oxc-resolver/binding-linux-riscv64-musl@11.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-qxZ1SWCXJY0eyhAlP6Lmo9F2Nrtx7EkYj9oCgL8apDPCwXwCEDA2U697bbT81JIc2IrVjxO4KX6WU2N+oN9Z4w=="],
- "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
+ "@oxc-resolver/binding-linux-s390x-gnu": ["@oxc-resolver/binding-linux-s390x-gnu@11.24.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-sGCecF3cx2DFlH4t/z7ApnOnXqN48p5p5mlHDEnHTAukQa2P+qMVE4CwyWE9W+q/m3QJ7kKfGrIjax31f44oFQ=="],
- "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="],
+ "@oxc-resolver/binding-linux-x64-gnu": ["@oxc-resolver/binding-linux-x64-gnu@11.24.2", "", { "os": "linux", "cpu": "x64" }, "sha512-k/VlMMcSzMlahb3/fENM4rTlsJ0s3fFROA0KXPBmKggqmTSaE383sl8F3KCOXPLmVsYfW6hCitMhXCEtNeZxxg=="],
- "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
-
- "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
+ "@oxc-resolver/binding-linux-x64-musl": ["@oxc-resolver/binding-linux-x64-musl@11.24.2", "", { "os": "linux", "cpu": "x64" }, "sha512-8hbnZyNi97b/8wapYaIF9+t9GmZKBW2vunaOc3h9HGJptH7b7XpvZqOTBSm/MpTjr7H497BlgOaSfLUdhmy2bw=="],
- "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
+ "@oxc-resolver/binding-openharmony-arm64": ["@oxc-resolver/binding-openharmony-arm64@11.24.2", "", { "os": "none", "cpu": "arm64" }, "sha512-MvyGik3a6pVgZ0t/kWlbmFxFLmXQJwgLsY2eYFHLpy0wGwRbfzeIGgDwQ3kXqE30z+kSXennRkCrT7TUvkptNg=="],
- "array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="],
+ "@oxc-resolver/binding-wasm32-wasi": ["@oxc-resolver/binding-wasm32-wasi@11.24.2", "", { "dependencies": { "@emnapi/core": "1.11.2", "@emnapi/runtime": "1.11.2", "@napi-rs/wasm-runtime": "^1.1.6" }, "cpu": "none" }, "sha512-vHcssMPwO08RTvj/c0iOBz90attxyG3wQJ0dTcyEQK43LRpcdLWZlV5feBhv6Isn6ahbQIzHbCgfa81+RiML0Q=="],
- "better-path-resolve": ["better-path-resolve@1.0.0", "", { "dependencies": { "is-windows": "^1.0.0" } }, "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g=="],
+ "@oxc-resolver/binding-win32-arm64-msvc": ["@oxc-resolver/binding-win32-arm64-msvc@11.24.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-uokJqro2iBqkFvJdKQLP7d8/BUmFwESQFVmIJUQKj1Xn1a/LysJoe1vmeECLF5b3jsV8CAL5sEMJXX6SdK9Nhg=="],
- "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
+ "@oxc-resolver/binding-win32-x64-msvc": ["@oxc-resolver/binding-win32-x64-msvc@11.24.2", "", { "os": "win32", "cpu": "x64" }, "sha512-UqGPmo56KDfLlfXFAFIrNflHT8tFxWGEivWg3Zeyp4Uy2NlKN1FGPr6/BxcLGG3+kZ6Wp14g5Uj+n71boqZfiw=="],
- "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
+ "@pnpm/deps.graph-sequencer": ["@pnpm/deps.graph-sequencer@1100.0.1", "", {}, "sha512-pOr5+q1fLYKwFN3LAJuGZEnfXDcQ73zqgDHMtGy+K+uIoUqyY+6MeDCWFwfu+4EFuq76I5EPFofoNAI+Bmmq4A=="],
- "bun-types": ["bun-types@1.2.22", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-hwaAu8tct/Zn6Zft4U9BsZcXkYomzpHJX28ofvx7k0Zz2HNz54n1n+tDgxoWFGB4PcFvJXJQloPhaV2eP3Q6EA=="],
+ "@sinclair/typebox": ["@sinclair/typebox@0.34.52", "", {}, "sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw=="],
- "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
+ "@tybys/wasm-util": ["@tybys/wasm-util@0.10.4", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-W3c4gRigFS0T/Ma4qIYF3GDAc5AQdHb1yL5znJT1Zv1YaD9Kitx656wBjvr19qbiosmZT8lWDM5BEMynUqX65A=="],
- "chardet": ["chardet@2.1.0", "", {}, "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA=="],
+ "@types/bun": ["@types/bun@1.4.2", "", { "dependencies": { "bun-types": "1.4.2" } }, "sha512-GimotNn7+ZV0uVArItBbriZsR1oNf0+WTzPkdcFrzShI7k2norL0uzEaJT8T33dWr7O/c9ZDuAFQrctKCi72oQ=="],
- "ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="],
+ "@types/esquery": ["@types/esquery@1.5.4", "", { "dependencies": { "@types/estree": "*" } }, "sha512-yYO4Q8H+KJHKW1rEeSzHxcZi90durqYgWVfnh5K6ZADVBjBv2e1NEveYX5yT2bffgN7RqzH3k9930m+i2yBoMA=="],
- "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
+ "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="],
- "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
+ "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="],
- "commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
+ "@types/lodash": ["@types/lodash@4.17.25", "", {}, "sha512-+K1NIO8I+F9/wNulfVvu23QYd0Pe9/OCqRrim4NoYIf1VoEDL90Ve4ClzpyqBLc7NpGGWRvYNCKZ1BE/Jpf8dQ=="],
- "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
+ "@types/lodash-es": ["@types/lodash-es@4.17.12", "", { "dependencies": { "@types/lodash": "*" } }, "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ=="],
- "css-select": ["css-select@6.0.0", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^7.0.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "nth-check": "^2.1.1" } }, "sha512-rZZVSLle8v0+EY8QAkDWrKhpgt6SA5OtHsgBnsj6ZaLb5dmDVOWUDtQitd9ydxxvEjhewNudS6eTVU7uOyzvXw=="],
+ "@types/moo": ["@types/moo@0.5.10", "", {}, "sha512-W6KzyZjXUYpwQfLK1O1UDzqcqYlul+lO7Bt71luyIIyNlOZwJaNeWWdqFs1C/f2hohZvUFHMk6oFNe9Rg48DbA=="],
- "css-what": ["css-what@7.0.0", "", {}, "sha512-wD5oz5xibMOPHzy13CyGmogB3phdvcDaB5t0W/Nr5Z2O/agcB8YwOz6e2Lsp10pNDzBoDO9nVa3RGs/2BttpHQ=="],
+ "@types/nearley": ["@types/nearley@2.11.5", "", {}, "sha512-dM7TrN0bVxGGXTYGx4YhGear8ysLO5SOuouAWM9oltjQ3m9oYa13qi8Z1DJp5zxVMPukvQdsrnZmgzpeuTSEQA=="],
- "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
+ "@types/node": ["@types/node@26.6.1", "", { "dependencies": { "undici-types": "~8.9.0" } }, "sha512-VqGJBMCtdhqkBUCcBLvywI0NJ+KLuVzgNnlBUNFOQjqVxzo2lxLUNg1DSey8+u2u6ktswSAxg+s68QLzWHNOuA=="],
- "dataloader": ["dataloader@1.4.0", "", {}, "sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw=="],
+ "@typescript/typescript-aix-ppc64": ["@typescript/typescript-aix-ppc64@7.0.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ=="],
- "dedent": ["dedent@1.7.0", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ=="],
+ "@typescript/typescript-darwin-arm64": ["@typescript/typescript-darwin-arm64@7.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA=="],
- "detect-indent": ["detect-indent@6.1.0", "", {}, "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA=="],
+ "@typescript/typescript-darwin-x64": ["@typescript/typescript-darwin-x64@7.0.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA=="],
- "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="],
+ "@typescript/typescript-freebsd-arm64": ["@typescript/typescript-freebsd-arm64@7.0.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ=="],
- "discontinuous-range": ["discontinuous-range@1.0.0", "", {}, "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ=="],
+ "@typescript/typescript-freebsd-x64": ["@typescript/typescript-freebsd-x64@7.0.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw=="],
- "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="],
+ "@typescript/typescript-linux-arm": ["@typescript/typescript-linux-arm@7.0.2", "", { "os": "linux", "cpu": "arm" }, "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ=="],
- "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="],
+ "@typescript/typescript-linux-arm64": ["@typescript/typescript-linux-arm64@7.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ=="],
- "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="],
+ "@typescript/typescript-linux-loong64": ["@typescript/typescript-linux-loong64@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ=="],
- "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
+ "@typescript/typescript-linux-mips64el": ["@typescript/typescript-linux-mips64el@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA=="],
- "dotenv": ["dotenv@8.6.0", "", {}, "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g=="],
+ "@typescript/typescript-linux-ppc64": ["@typescript/typescript-linux-ppc64@7.0.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA=="],
- "enquirer": ["enquirer@2.4.1", "", { "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" } }, "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ=="],
+ "@typescript/typescript-linux-riscv64": ["@typescript/typescript-linux-riscv64@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ=="],
- "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
+ "@typescript/typescript-linux-s390x": ["@typescript/typescript-linux-s390x@7.0.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw=="],
- "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="],
+ "@typescript/typescript-linux-x64": ["@typescript/typescript-linux-x64@7.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A=="],
- "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="],
+ "@typescript/typescript-netbsd-arm64": ["@typescript/typescript-netbsd-arm64@7.0.2", "", { "os": "none", "cpu": "arm64" }, "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA=="],
- "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
+ "@typescript/typescript-netbsd-x64": ["@typescript/typescript-netbsd-x64@7.0.2", "", { "os": "none", "cpu": "x64" }, "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA=="],
- "estree-toolkit": ["estree-toolkit@1.7.13", "", { "dependencies": { "@types/estree": ">=1.0.7", "@types/estree-jsx": ">=1.0.5" } }, "sha512-/fLCEcVBUgAtMkGXZHplPVyUv7wiSfsCGubBdM16n1iYCidPfyk1Kk1U0wAxLZADuA3z8k87DfVYXlBmHJeekg=="],
+ "@typescript/typescript-openbsd-arm64": ["@typescript/typescript-openbsd-arm64@7.0.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ=="],
- "extendable-error": ["extendable-error@0.1.7", "", {}, "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg=="],
+ "@typescript/typescript-openbsd-x64": ["@typescript/typescript-openbsd-x64@7.0.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg=="],
- "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
+ "@typescript/typescript-sunos-x64": ["@typescript/typescript-sunos-x64@7.0.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g=="],
- "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
+ "@typescript/typescript-win32-arm64": ["@typescript/typescript-win32-arm64@7.0.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ=="],
- "fd-package-json": ["fd-package-json@2.0.0", "", { "dependencies": { "walk-up-path": "^4.0.0" } }, "sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ=="],
+ "@typescript/typescript-win32-x64": ["@typescript/typescript-win32-x64@7.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g=="],
- "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
+ "acorn": ["acorn@8.18.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ=="],
- "find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="],
+ "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
- "formatly": ["formatly@0.3.0", "", { "dependencies": { "fd-package-json": "^2.0.0" }, "bin": { "formatly": "bin/index.mjs" } }, "sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w=="],
+ "boolbase": ["boolbase@2.0.0", "", {}, "sha512-DkVaaQHymRhpYEYo9x1oo7Q7B0Y6KJUsjm3c9eTyFDby4MHLBTwZ6ZDWBel5zrYxj1WsZgC5oLpiz+93MluXeA=="],
- "fs-extra": ["fs-extra@7.0.1", "", { "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw=="],
+ "bun-types": ["bun-types@1.4.2", "", { "dependencies": { "@types/node": "*" } }, "sha512-bxV1FgK7yBIzjRe5zBozIM4Bem11ZJcCXSrjWRG3YWLt8yFDePu4cLjpebO8OvPeIE9trbyPF4fuj3Cia4Fj3w=="],
- "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
+ "cac": ["cac@7.0.0", "", {}, "sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ=="],
- "globals": ["globals@16.4.0", "", {}, "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw=="],
+ "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
- "globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="],
+ "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
- "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
+ "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
- "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
+ "commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
- "human-id": ["human-id@4.1.1", "", { "bin": { "human-id": "dist/cli.js" } }, "sha512-3gKm/gCSUipeLsRYZbbdA1BD83lBoWUkZ7G9VFrhWPAU76KwYo5KR8V28bpoPm/ygy0x5/GCbpRQdY7VLYCoIg=="],
+ "css-select": ["css-select@7.0.0", "", { "dependencies": { "boolbase": "^2.0.0", "css-what": "^8.0.0", "domhandler": "^6.0.1", "domutils": "^4.0.2", "nth-check": "^3.0.1" } }, "sha512-snmjEVXy+1LnwXdxhYvTMj1d9tOh4HxkA1YmoayVBeeyR2C14Pum7fcxJIm4SswYspVy866eYNwlH6xC3/VH5g=="],
- "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
+ "css-what": ["css-what@8.0.0", "", {}, "sha512-DH0Bqq3DNp5tdOReuNyAA+Ev4Y2GS5FMbZpeTLP6C4CDi0h5nL0BmUPChXw3o/qbHLDWHl49sbNqQVY7bMSDdw=="],
- "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
+ "dataloader": ["dataloader@2.2.3", "", {}, "sha512-y2krtASINtPFS1rSDjacrFgn1dcUuoREVabwlOGOe4SdxenREqwjwjElAdwvbGM7kgZz9a3KVicWR7vcz8rnzA=="],
- "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
+ "dedent": ["dedent@1.7.2", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA=="],
- "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
+ "discontinuous-range": ["discontinuous-range@1.0.0", "", {}, "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ=="],
- "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
+ "dom-serializer": ["dom-serializer@3.1.1", "", { "dependencies": { "domelementtype": "^3.0.0", "domhandler": "^6.0.0", "entities": "^8.0.0" } }, "sha512-4MEa38/QexBob6gFNwu+EGdWvhJ1OKuNwdYY3Y3NyeWDQfnGeDYQUDfIRzWu5B5gsv03so2Uxd28YC6zrsx3Lw=="],
- "is-subdir": ["is-subdir@1.2.0", "", { "dependencies": { "better-path-resolve": "1.0.0" } }, "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw=="],
+ "domelementtype": ["domelementtype@3.0.0", "", {}, "sha512-umCQid3jKbDmVjx8jGaW7uUykm4DEUeyV21hPxNMo2nV955DhUThwqyOIDtreepP31hl84X7G5U9ZfsWvIB3Pg=="],
- "is-windows": ["is-windows@1.0.2", "", {}, "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="],
+ "domhandler": ["domhandler@6.0.1", "", { "dependencies": { "domelementtype": "^3.0.0" } }, "sha512-gYzvtM72ZtxQO0T048kd6HWSbbGCNOUwcnfQ01cqIJ4X2IYKFFHZ5mKvrQETcFXxsRObZulDaKmy//R7TPtsBg=="],
- "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
+ "domutils": ["domutils@4.0.2", "", { "dependencies": { "dom-serializer": "^3.0.0", "domelementtype": "^3.0.0", "domhandler": "^6.0.0" } }, "sha512-qI4JLRKnSzqFqr7hAlS5xQDusBCjKSEG4t4+7aNrIQMHBcsC2TGEhuyABJdYkgSewL57PNLYEiibY2iPKhKpaA=="],
- "jest-diff": ["jest-diff@30.1.2", "", { "dependencies": { "@jest/diff-sequences": "30.0.1", "@jest/get-type": "30.1.0", "chalk": "^4.1.2", "pretty-format": "30.0.5" } }, "sha512-4+prq+9J61mOVXCa4Qp8ZjavdxzrWQXrI80GNxP8f4tkI2syPuPrJgdRPZRrfUTRvIoUwcmNLbqEJy9W800+NQ=="],
+ "entities": ["entities@8.1.0", "", {}, "sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA=="],
- "jiti": ["jiti@2.5.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="],
+ "esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="],
- "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
+ "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
- "jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="],
+ "estree-toolkit": ["estree-toolkit@1.7.14", "", { "dependencies": { "@types/estree": ">=1.0.8", "@types/estree-jsx": ">=1.0.5" } }, "sha512-UD46XPj9xCQ+5r+JRv1qdaJuWLbQaconfnFHWOc20ugbHzZSOO6/A+vye46arVxbOSr/KnzRzKfnp9SJ0IqaUw=="],
- "knip": ["knip@5.63.1", "", { "dependencies": { "@nodelib/fs.walk": "^1.2.3", "fast-glob": "^3.3.3", "formatly": "^0.3.0", "jiti": "^2.5.1", "js-yaml": "^4.1.0", "minimist": "^1.2.8", "oxc-resolver": "^11.6.2", "picocolors": "^1.1.1", "picomatch": "^4.0.1", "smol-toml": "^1.4.1", "strip-json-comments": "5.0.2", "zod": "^3.25.0", "zod-validation-error": "^3.0.3" }, "peerDependencies": { "@types/node": ">=18", "typescript": ">=5.0.4" }, "bin": { "knip": "bin/knip.js", "knip-bun": "bin/knip-bun.js" } }, "sha512-wSznedUAzcU4o9e0O2WPqDnP7Jttu8cesq/R23eregRY8QYQ9NLJ3aGt9fadJfRzPBoU4tRyutwVQu6chhGDlA=="],
+ "fast-string-truncated-width": ["fast-string-truncated-width@3.0.3", "", {}, "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g=="],
- "locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="],
+ "fast-string-width": ["fast-string-width@3.0.2", "", { "dependencies": { "fast-string-truncated-width": "^3.0.2" } }, "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg=="],
- "lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="],
+ "fast-wrap-ansi": ["fast-wrap-ansi@0.2.2", "", { "dependencies": { "fast-string-width": "^3.0.2" } }, "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q=="],
- "lodash.startcase": ["lodash.startcase@4.4.0", "", {}, "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg=="],
+ "fd-package-json": ["fd-package-json@2.0.0", "", { "dependencies": { "walk-up-path": "^4.0.0" } }, "sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ=="],
- "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
+ "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
- "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
+ "formatly": ["formatly@0.7.0", "", { "dependencies": { "fd-package-json": "^2.0.0", "package-manager-detector": "^1.8.0" }, "bin": { "formatly": "bin/index.mjs" } }, "sha512-7CXJtIIA0zy/u12StsYk25qVKxvdLA2ep2sTNxK3ov0mGNIIDqIvAXDSgTnAfDJFsPfWjuz0WjfYSdpvnLA5Tg=="],
- "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
+ "get-tsconfig": ["get-tsconfig@4.14.3", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA=="],
- "moo": ["moo@0.5.2", "", {}, "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q=="],
+ "globals": ["globals@17.12.0", "", {}, "sha512-cezEd/DTyyht9cvSSURyygXPfy04GtWO/5e6ZPvH7fCtjKz9PYOmuawphw1Ctd1f6C+5JypXfGD7ahNMXvevBA=="],
- "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
+ "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
- "napi-postinstall": ["napi-postinstall@0.3.3", "", { "bin": { "napi-postinstall": "lib/cli.js" } }, "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow=="],
+ "human-id": ["human-id@4.2.1", "", { "bin": { "human-id": "dist/cli.js" } }, "sha512-zPGsiS+dWoTZtZ4AtpA9Y+BdSFSNWvnouNlWNoUFyAM6xHOHmdCvqO3k8AIbdamCOv4gUFUVNPf6rJFfc4UiJw=="],
- "nearley": ["nearley@2.20.1", "", { "dependencies": { "commander": "^2.19.0", "moo": "^0.5.0", "railroad-diagrams": "^1.0.0", "randexp": "0.4.6" }, "bin": { "nearleyc": "bin/nearleyc.js", "nearley-test": "bin/nearley-test.js", "nearley-unparse": "bin/nearley-unparse.js", "nearley-railroad": "bin/nearley-railroad.js" } }, "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ=="],
+ "import-meta-resolve": ["import-meta-resolve@4.2.0", "", {}, "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg=="],
- "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
+ "jest-diff": ["jest-diff@30.5.1", "", { "dependencies": { "@jest/diff-sequences": "30.5.0", "@jest/get-type": "30.5.0", "chalk": "^4.1.2", "pretty-format": "30.5.1" } }, "sha512-e3cNNMpv8Kh20MjjphTXs+3Vz7DQyLM1nft7KJhnh46atFhjVJRa+0Hq0beywuwsACtMQUBihQkFl8zxb7gt1Q=="],
- "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="],
+ "jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="],
- "outdent": ["outdent@0.5.0", "", {}, "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q=="],
+ "jju": ["jju@1.4.0", "", {}, "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA=="],
- "oxc-resolver": ["oxc-resolver@11.7.1", "", { "dependencies": { "napi-postinstall": "^0.3.0" }, "optionalDependencies": { "@oxc-resolver/binding-android-arm-eabi": "11.7.1", "@oxc-resolver/binding-android-arm64": "11.7.1", "@oxc-resolver/binding-darwin-arm64": "11.7.1", "@oxc-resolver/binding-darwin-x64": "11.7.1", "@oxc-resolver/binding-freebsd-x64": "11.7.1", "@oxc-resolver/binding-linux-arm-gnueabihf": "11.7.1", "@oxc-resolver/binding-linux-arm-musleabihf": "11.7.1", "@oxc-resolver/binding-linux-arm64-gnu": "11.7.1", "@oxc-resolver/binding-linux-arm64-musl": "11.7.1", "@oxc-resolver/binding-linux-ppc64-gnu": "11.7.1", "@oxc-resolver/binding-linux-riscv64-gnu": "11.7.1", "@oxc-resolver/binding-linux-riscv64-musl": "11.7.1", "@oxc-resolver/binding-linux-s390x-gnu": "11.7.1", "@oxc-resolver/binding-linux-x64-gnu": "11.7.1", "@oxc-resolver/binding-linux-x64-musl": "11.7.1", "@oxc-resolver/binding-wasm32-wasi": "11.7.1", "@oxc-resolver/binding-win32-arm64-msvc": "11.7.1", "@oxc-resolver/binding-win32-ia32-msvc": "11.7.1", "@oxc-resolver/binding-win32-x64-msvc": "11.7.1" } }, "sha512-PzbEnD6NKTCFVKkUZtmQcX69ajdfM33RqI5kyb8mH9EdIqEUS00cWSXN0lsgYrtdTMzwo0EKKoH7hnGg6EDraQ=="],
+ "jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="],
- "p-filter": ["p-filter@2.1.0", "", { "dependencies": { "p-map": "^2.0.0" } }, "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw=="],
+ "knip": ["knip@6.37.0", "", { "dependencies": { "fdir": "^6.5.0", "formatly": "^0.7.0", "get-tsconfig": "4.14.3", "jiti": "^2.7.0", "oxc-parser": "^0.150.0", "oxc-resolver": "11.24.2", "picomatch": "^4.0.7", "smol-toml": "^1.8.0", "strip-json-comments": "5.0.3", "tinyglobby": "^0.2.17", "unbash": "^4.0.11", "yaml": "^2.9.1", "zod": "^4.4.3" }, "bin": { "knip": "bin/knip.js", "knip-bun": "bin/knip-bun.js" } }, "sha512-NKCYuoGKJ+o2AuoCuV1mDvfMYnSSWfDXqxwmzxeHyd8fftjNRl8TBUg3fbSrtJjhm7Vj6sc1PX3WZnZhECs9EQ=="],
- "p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
+ "launch-editor": ["launch-editor@2.14.1", "", { "dependencies": { "picocolors": "^1.1.1", "shell-quote": "^1.8.4" } }, "sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA=="],
- "p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
+ "lodash-es": ["lodash-es@4.18.1", "", {}, "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A=="],
- "p-map": ["p-map@2.1.0", "", {}, "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw=="],
+ "moo": ["moo@0.5.3", "", {}, "sha512-m2fmM2dDm7GZQsY7KK2cme8agi+AAljILjQnof7p1ZMDe6dQ4bdnSMx0cPppudoeNv5hEFQirN6u+O4fDE0IWA=="],
- "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="],
+ "nearley": ["nearley@2.20.1", "", { "dependencies": { "commander": "^2.19.0", "moo": "^0.5.0", "railroad-diagrams": "^1.0.0", "randexp": "0.4.6" }, "bin": { "nearleyc": "bin/nearleyc.js", "nearley-test": "bin/nearley-test.js", "nearley-unparse": "bin/nearley-unparse.js", "nearley-railroad": "bin/nearley-railroad.js" } }, "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ=="],
- "package-manager-detector": ["package-manager-detector@0.2.11", "", { "dependencies": { "quansync": "^0.2.7" } }, "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ=="],
+ "nth-check": ["nth-check@3.0.1", "", { "dependencies": { "boolbase": "^2.0.0" } }, "sha512-GX0gsdbGVCgnRgbeGaubfjpBXyYRWOOCVeYh08bSQvDZqxz5ndXs1OTfAt/h36G1xvI94YIspsI0sVFqAV9+RQ=="],
- "parse5": ["parse5@8.0.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA=="],
+ "oxc-parser": ["oxc-parser@0.150.0", "", { "dependencies": { "@oxc-project/types": "^0.150.0" }, "optionalDependencies": { "@oxc-parser/binding-android-arm-eabi": "0.150.0", "@oxc-parser/binding-android-arm64": "0.150.0", "@oxc-parser/binding-darwin-arm64": "0.150.0", "@oxc-parser/binding-darwin-x64": "0.150.0", "@oxc-parser/binding-freebsd-x64": "0.150.0", "@oxc-parser/binding-linux-arm-gnueabihf": "0.150.0", "@oxc-parser/binding-linux-arm-musleabihf": "0.150.0", "@oxc-parser/binding-linux-arm64-gnu": "0.150.0", "@oxc-parser/binding-linux-arm64-musl": "0.150.0", "@oxc-parser/binding-linux-ppc64-gnu": "0.150.0", "@oxc-parser/binding-linux-riscv64-gnu": "0.150.0", "@oxc-parser/binding-linux-riscv64-musl": "0.150.0", "@oxc-parser/binding-linux-s390x-gnu": "0.150.0", "@oxc-parser/binding-linux-x64-gnu": "0.150.0", "@oxc-parser/binding-linux-x64-musl": "0.150.0", "@oxc-parser/binding-openharmony-arm64": "0.150.0", "@oxc-parser/binding-win32-arm64-msvc": "0.150.0", "@oxc-parser/binding-win32-ia32-msvc": "0.150.0", "@oxc-parser/binding-win32-x64-msvc": "0.150.0" } }, "sha512-zwajKw1GUa57IOdafIS7/yOObGF2NihwIfZfs5yJTRprMSkiwhWOc/k+n8bwnUPbHr2/XsjfBO8KyTPaW3VpWg=="],
- "parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@8.0.0", "", { "dependencies": { "domhandler": "^5.0.3", "parse5": "^8.0.0" } }, "sha512-h4bXApvAdtcuv3MPcLQUCSQ2bJg9pG3cS5LwlXDJqweH06+0DjXVu1zwpjlbyu9tNsHiNnm4TM0nvTsGxQi5pw=="],
+ "oxc-resolver": ["oxc-resolver@11.24.2", "", { "optionalDependencies": { "@oxc-resolver/binding-android-arm-eabi": "11.24.2", "@oxc-resolver/binding-android-arm64": "11.24.2", "@oxc-resolver/binding-darwin-arm64": "11.24.2", "@oxc-resolver/binding-darwin-x64": "11.24.2", "@oxc-resolver/binding-freebsd-x64": "11.24.2", "@oxc-resolver/binding-linux-arm-gnueabihf": "11.24.2", "@oxc-resolver/binding-linux-arm-musleabihf": "11.24.2", "@oxc-resolver/binding-linux-arm64-gnu": "11.24.2", "@oxc-resolver/binding-linux-arm64-musl": "11.24.2", "@oxc-resolver/binding-linux-ppc64-gnu": "11.24.2", "@oxc-resolver/binding-linux-riscv64-gnu": "11.24.2", "@oxc-resolver/binding-linux-riscv64-musl": "11.24.2", "@oxc-resolver/binding-linux-s390x-gnu": "11.24.2", "@oxc-resolver/binding-linux-x64-gnu": "11.24.2", "@oxc-resolver/binding-linux-x64-musl": "11.24.2", "@oxc-resolver/binding-openharmony-arm64": "11.24.2", "@oxc-resolver/binding-wasm32-wasi": "11.24.2", "@oxc-resolver/binding-win32-arm64-msvc": "11.24.2", "@oxc-resolver/binding-win32-x64-msvc": "11.24.2" } }, "sha512-FY91FiDBj7ls5MsFS9jN3tjz2o0/zsdSsymlakySaBwVJZorHhkWyICLZMKxlu1R9vYo+sd3z1jwb4J8x7bNDw=="],
- "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
+ "package-manager-detector": ["package-manager-detector@1.8.0", "", {}, "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A=="],
- "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
+ "parse5": ["parse5@8.0.1", "", { "dependencies": { "entities": "^8.0.0" } }, "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw=="],
- "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="],
+ "parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@8.0.1", "", { "dependencies": { "domhandler": "^6.0.1", "parse5": "^8.0.0" } }, "sha512-aqkH+xQxX+QGZtP5GIMmqqp16Y0v9muEf2VVeypv35kFsD5bqP1UeBanSshdfjMY+RTh2vN4mmK6nEOVRMEvHg=="],
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
- "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
+ "picomatch": ["picomatch@4.0.7", "", {}, "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA=="],
- "pify": ["pify@4.0.1", "", {}, "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="],
+ "prettier": ["prettier@3.9.8", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-WRFq3Wn3WId7LLROfMLdH7xaFr2jR62wU8nLO6rQUOLOxNZUviyJQs1M0iIhLexSFy+L+w0ch66wtoO2jRjG0A=="],
- "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="],
-
- "pretty-format": ["pretty-format@30.0.5", "", { "dependencies": { "@jest/schemas": "30.0.5", "ansi-styles": "^5.2.0", "react-is": "^18.3.1" } }, "sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw=="],
-
- "quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="],
-
- "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
+ "pretty-format": ["pretty-format@30.5.1", "", { "dependencies": { "@jest/react-is-18": "npm:react-is@^18.3.1", "@jest/react-is-19": "npm:react-is@^19.2.5", "@jest/schemas": "30.5.0", "ansi-styles": "^5.2.0" } }, "sha512-byhRAPguVKMQIj4kjJwJ5lAskVhfuiSdiYl/aLTWpgkGEmic2jYhJh1yE9ih8Ox44Xg9ccCT11/S6QrzSJuNrg=="],
"railroad-diagrams": ["railroad-diagrams@1.0.0", "", {}, "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A=="],
"randexp": ["randexp@0.4.6", "", { "dependencies": { "discontinuous-range": "1.0.0", "ret": "~0.1.10" } }, "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ=="],
- "react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
-
- "read-yaml-file": ["read-yaml-file@1.1.0", "", { "dependencies": { "graceful-fs": "^4.1.5", "js-yaml": "^3.6.1", "pify": "^4.0.1", "strip-bom": "^3.0.0" } }, "sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA=="],
-
- "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],
+ "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
"ret": ["ret@0.1.15", "", {}, "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="],
- "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
-
- "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
-
- "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
-
- "semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
-
- "set-cookie-parser": ["set-cookie-parser@2.7.1", "", {}, "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="],
-
- "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
-
- "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
-
- "sherif": ["sherif@1.6.1", "", { "optionalDependencies": { "sherif-darwin-arm64": "1.6.1", "sherif-darwin-x64": "1.6.1", "sherif-linux-arm64": "1.6.1", "sherif-linux-x64": "1.6.1", "sherif-windows-arm64": "1.6.1", "sherif-windows-x64": "1.6.1" }, "bin": { "sherif": "index.js" } }, "sha512-ZnwyTnmXoUOPClkOA37JWIyFxCoozMGHmhk/p7XbTREI554XXCnBAn3BMX8UsqkhSzQ9eNQsq4U+jnImEIppsQ=="],
+ "semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
- "sherif-darwin-arm64": ["sherif-darwin-arm64@1.6.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-J15oBJcrnCAZ0rQE8WbMShYw3204A18akCH6C/uZrILTwX/vZyJIqi7lAt5L00LzsadA3HcyQqVjLNNCvuihoQ=="],
+ "set-cookie-parser": ["set-cookie-parser@3.1.2", "", {}, "sha512-5/r/lTwbJ3zQ+qwdUFZYeRNqda7P5HD8zQKqlSjdGt1/S0cjLAphHusj4Y58ahDtWn/g32xrIS58/ikOvwl0Lw=="],
- "sherif-darwin-x64": ["sherif-darwin-x64@1.6.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-oLA/GtvUasi+qCl35LczOhQ4g/xY2mxE5/eiTYQGT3Ow7FKLscnkE6v5l28bgkFeR/uke0AgZ/CgHhozAf0ulg=="],
+ "shell-quote": ["shell-quote@1.10.0", "", {}, "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA=="],
- "sherif-linux-arm64": ["sherif-linux-arm64@1.6.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-OoltlucT7v9BZdkYZRbs1QU0DYMCQ5qgpMqQdMW1Rq3w3amr7+oEiV9NHntD83udOo8xRxKq0uPXfNYu+VptJw=="],
+ "sherif": ["sherif@1.13.0", "", { "optionalDependencies": { "sherif-darwin-arm64": "1.13.0", "sherif-darwin-x64": "1.13.0", "sherif-linux-arm64": "1.13.0", "sherif-linux-arm64-musl": "1.13.0", "sherif-linux-x64": "1.13.0", "sherif-linux-x64-musl": "1.13.0", "sherif-windows-arm64": "1.13.0", "sherif-windows-x64": "1.13.0" }, "bin": { "sherif": "index.js" } }, "sha512-Ld2nUOlwW1nmYDA2Q/5o7SC8WcCzVS7XjImmzW4a4z1o8DXJnt+2xYLvI42N5UYlNb/EevPahdC/XxIP6C38TQ=="],
- "sherif-linux-x64": ["sherif-linux-x64@1.6.1", "", { "os": "linux", "cpu": "x64" }, "sha512-qyDyYqpi3ABGkRuCnjnxN3OMT8DxMiiLzhS9p9xC05Y9nr5hjkxvqP4DdJ4e5opm4E7vzRAS7VQoZ6m7h6tsgQ=="],
+ "sherif-darwin-arm64": ["sherif-darwin-arm64@1.13.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-k38jpGpZIEWS5dpSRLSvVi53LZuGO3hDqB88jgdLMDN11LZM6yTDcP0GytnQ8OpE6Br/Js6bDCLsdWDarZdV9g=="],
- "sherif-windows-arm64": ["sherif-windows-arm64@1.6.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-wAbCiqP//lo7bZUlHmZUV3/sGjnJxo6QB5/fqhz5/GUeWh4CTyvlSacJKZxLnXnzpiUSeFnWutquWnHkRov5Ug=="],
+ "sherif-darwin-x64": ["sherif-darwin-x64@1.13.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-W2bOj0Ya9A0fPSWzbeaaNg2RRRr48l2lArN8sGbfc9SZuJSJWXcdWkTVC3sEUiiXwpxNeLY/CsGNyQz5Izbfig=="],
- "sherif-windows-x64": ["sherif-windows-x64@1.6.1", "", { "os": "win32", "cpu": "x64" }, "sha512-2r0qMxZGCMO2aq8Hlq7npxtAsUFVDsEFtUM/6dFo1npa/jHe2mbU7ii/Ymy0bloSa/qw/azrSfRV6GLU7Gjtxg=="],
+ "sherif-linux-arm64": ["sherif-linux-arm64@1.13.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-Z94SgKNClWarVJj4LsayOmL7zccCUAvy3ugZnIO860FoJofh812KAyF8CdWrSho8qfmmoAzNcqSSc1OZh7+ckQ=="],
- "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
+ "sherif-linux-arm64-musl": ["sherif-linux-arm64-musl@1.13.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-9IDAlwYT5Ay2nex9Da3R98cvnPKVveT57i7pJXnnY/DC90qdqqz6Twlp7STRv+7qo4k4ES+2J9zQ0k6SDe888A=="],
- "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
+ "sherif-linux-x64": ["sherif-linux-x64@1.13.0", "", { "os": "linux", "cpu": "x64" }, "sha512-xGB9iiet8l/i8/YLZje8icpZyt4pVgoxB2+SoC6JCB8iDWsCVSuixebwX2t9yeGqXBXO1kphaW0TLf8Tmwy9JQ=="],
- "smol-toml": ["smol-toml@1.4.2", "", {}, "sha512-rInDH6lCNiEyn3+hH8KVGFdbjc099j47+OSgbMrfDYX1CmXLfdKd7qi6IfcWj2wFxvSVkuI46M+wPGYfEOEj6g=="],
+ "sherif-linux-x64-musl": ["sherif-linux-x64-musl@1.13.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2L+A8jF5ylojFwl7eAePR1h3Bzx24IcMgEoWObXgD70k6xF+GOJaM/n+q4MQ9YDntAKbJfMDr6ETjt6Bt/hosA=="],
- "spawndamnit": ["spawndamnit@3.0.1", "", { "dependencies": { "cross-spawn": "^7.0.5", "signal-exit": "^4.0.1" } }, "sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg=="],
+ "sherif-windows-arm64": ["sherif-windows-arm64@1.13.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-jHzJ/EcG4HuNLf/3AEDzbRkAofLPBHRJKJJMjAosampAe9861atu4q+Z2IZ1/sHg5oVnNgaNg/Xc5DDhGcQ/3w=="],
- "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="],
+ "sherif-windows-x64": ["sherif-windows-x64@1.13.0", "", { "os": "win32", "cpu": "x64" }, "sha512-KyMqQY62Eb3O+wePlw433mH2XBPVPLXdDjWPneg9pB6jeK0B1sgEzM2yks+aAP5asZ1Y8Q7C7iR7ZtbJKdsAtA=="],
- "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
+ "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
- "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="],
+ "smol-toml": ["smol-toml@1.8.0", "", {}, "sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ=="],
- "strip-json-comments": ["strip-json-comments@5.0.2", "", {}, "sha512-4X2FR3UwhNUE9G49aIsJW5hRRR3GXGTBTZRMfv568O60ojM8HcWjV/VxAxCDW3SUND33O6ZY66ZuRcdkj73q2g=="],
+ "strip-json-comments": ["strip-json-comments@5.0.3", "", {}, "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw=="],
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
- "term-size": ["term-size@2.2.1", "", {}, "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg=="],
-
"test": ["test@workspace:test"],
- "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
+ "tinyexec": ["tinyexec@1.3.1", "", {}, "sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA=="],
- "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="],
+ "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="],
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
- "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
+ "typescript": ["typescript@7.0.2", "", { "optionalDependencies": { "@typescript/typescript-aix-ppc64": "7.0.2", "@typescript/typescript-darwin-arm64": "7.0.2", "@typescript/typescript-darwin-x64": "7.0.2", "@typescript/typescript-freebsd-arm64": "7.0.2", "@typescript/typescript-freebsd-x64": "7.0.2", "@typescript/typescript-linux-arm": "7.0.2", "@typescript/typescript-linux-arm64": "7.0.2", "@typescript/typescript-linux-loong64": "7.0.2", "@typescript/typescript-linux-mips64el": "7.0.2", "@typescript/typescript-linux-ppc64": "7.0.2", "@typescript/typescript-linux-riscv64": "7.0.2", "@typescript/typescript-linux-s390x": "7.0.2", "@typescript/typescript-linux-x64": "7.0.2", "@typescript/typescript-netbsd-arm64": "7.0.2", "@typescript/typescript-netbsd-x64": "7.0.2", "@typescript/typescript-openbsd-arm64": "7.0.2", "@typescript/typescript-openbsd-x64": "7.0.2", "@typescript/typescript-sunos-x64": "7.0.2", "@typescript/typescript-win32-arm64": "7.0.2", "@typescript/typescript-win32-x64": "7.0.2" }, "bin": { "tsc": "bin/tsc" } }, "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA=="],
- "undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
+ "unbash": ["unbash@4.0.11", "", {}, "sha512-FoSOKV7NEofQSkAefMVHam4ZPKYMxjAydxiV72UFEDNV/YofxjGfiZ2A9pZjdL/lRJzTjcu4PABo1JYJX8N5iQ=="],
- "universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="],
+ "undici-types": ["undici-types@8.9.0", "", {}, "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg=="],
"walk-up-path": ["walk-up-path@4.0.0", "", {}, "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A=="],
- "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
-
- "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],
-
- "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
-
- "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
-
- "zod-validation-error": ["zod-validation-error@3.5.3", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-OT5Y8lbUadqVZCsnyFaTQ4/O2mys4tj7PqhdbBCp7McPwvIEKfPtdA6QfPeFQK2/Rz5LgwmAXRJTugBNBi0btw=="],
-
- "@changesets/apply-release-plan/prettier": ["prettier@2.8.8", "", { "bin": { "prettier": "bin-prettier.js" } }, "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q=="],
-
- "@changesets/parse/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
-
- "@changesets/write/prettier": ["prettier@2.8.8", "", { "bin": { "prettier": "bin-prettier.js" } }, "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q=="],
+ "yaml": ["yaml@2.9.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw=="],
- "@manypkg/find-root/@types/node": ["@types/node@12.20.55", "", {}, "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="],
-
- "@manypkg/find-root/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="],
-
- "@manypkg/get-packages/@changesets/types": ["@changesets/types@4.1.0", "", {}, "sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw=="],
-
- "@manypkg/get-packages/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="],
-
- "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
-
- "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
+ "zod": ["zod@4.6.5", "", {}, "sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q=="],
"pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
-
- "read-yaml-file/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
-
- "@changesets/parse/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
-
- "read-yaml-file/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
}
}
diff --git a/knip.json b/knip.json
index 1fe5f25..60567c8 100644
--- a/knip.json
+++ b/knip.json
@@ -1,12 +1,12 @@
{
- "$schema": "https://unpkg.com/knip@5/schema.json",
+ "$schema": "./node_modules/knip/schema.json",
"vitest": {},
+ "ignore": [
+ "assets/**/*.ts"
+ ],
"ignoreDependencies": [
"@changesets/cli"
],
- "ignoreBinaries": [
- "open"
- ],
"exclude": [
"enumMembers"
]
diff --git a/package.json b/package.json
index 5358243..6e63749 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "get",
"license": "Apache-2.0",
"private": true,
- "packageManager": "bun@1.2.22",
+ "packageManager": "bun@1.4.2",
"scripts": {
"fmt": "biome check --write",
"lint": "bun lint:check && bun lint:types && bun lint:unused && bun lint:repo",
@@ -18,12 +18,15 @@
"test"
],
"devDependencies": {
- "@biomejs/biome": "^2.2.4",
- "@changesets/changelog-github": "^0.5.1",
- "@changesets/cli": "^2.29.7",
- "@types/bun": "^1.2.22",
- "knip": "^5.63.1",
- "sherif": "^1.6.1",
- "typescript": "^5.9.2"
+ "@biomejs/biome": "^2.5.14",
+ "@changesets/changelog-github": "^1.0.1",
+ "@changesets/cli": "^3.0.3",
+ "@types/bun": "^1.4.2",
+ "knip": "^6.37.0",
+ "sherif": "^1.13.0",
+ "typescript": "^7.0.2"
+ },
+ "overrides": {
+ "domhandler": "^6.0.1"
}
}
diff --git a/packages/ast/package.json b/packages/ast/package.json
index b585eef..dcb79e1 100644
--- a/packages/ast/package.json
+++ b/packages/ast/package.json
@@ -19,6 +19,9 @@
},
"homepage": "https://getlang.dev",
"dependencies": {
- "moo": "^0.5.2"
+ "moo": "^0.5.3"
+ },
+ "devDependencies": {
+ "@types/moo": "^0.5.10"
}
}
diff --git a/packages/ast/src/ast.ts b/packages/ast/src/ast.ts
index 8964aed..2d93de6 100644
--- a/packages/ast/src/ast.ts
+++ b/packages/ast/src/ast.ts
@@ -2,8 +2,8 @@ import type { Token as MooToken } from 'moo'
import type { TypeInfo } from './typeinfo.js'
import { Type } from './typeinfo.js'
-export { Type }
export type { TypeInfo }
+export { Type }
export type Token = Omit
export function isToken(value: unknown): value is Token {
@@ -117,6 +117,14 @@ type SubqueryExpr = {
typeInfo: TypeInfo
}
+type TestExpr = {
+ kind: 'TestExpr'
+ test: Expr
+ t?: Expr
+ f: Expr
+ typeInfo: TypeInfo
+}
+
type DrillExpr = {
kind: 'DrillExpr'
body: Expr[]
@@ -150,6 +158,12 @@ type LiteralExpr = {
typeInfo: TypeInfo
}
+type TemplateLiteralExpr = {
+ kind: 'TemplateLiteralExpr'
+ value: Expr
+ typeInfo: TypeInfo
+}
+
export type Stmt =
| Program
| ExtractStmt
@@ -172,8 +186,10 @@ export type Expr =
| ObjectEntryExpr
| ObjectLiteralExpr
| SliceExpr
+ | TestExpr
| DrillExpr
| LiteralExpr
+ | TemplateLiteralExpr
export type Node = Stmt | Expr
@@ -259,6 +275,14 @@ const subqueryExpr = (body: Stmt[]): SubqueryExpr => ({
body,
})
+const testExpr = (test: Expr, t: Expr | undefined, f: Expr): TestExpr => ({
+ kind: 'TestExpr',
+ typeInfo: { type: Type.Value },
+ test,
+ t,
+ f,
+})
+
const drillExpr = (body: Expr[]): DrillExpr => ({
kind: 'DrillExpr',
typeInfo: { type: Type.Value },
@@ -341,6 +365,12 @@ const literalExpr = (raw: Token): LiteralExpr => ({
value: JSON.parse(raw.value),
})
+const templateLiteralExpr = (value: Expr): TemplateLiteralExpr => ({
+ kind: 'TemplateLiteralExpr',
+ typeInfo: { type: Type.Value },
+ value,
+})
+
const templateExpr = (elements: (Expr | Token)[]): TemplateExpr => ({
kind: 'TemplateExpr',
typeInfo: { type: Type.Value },
@@ -367,6 +397,8 @@ export const t = {
objectEntryExpr,
objectLiteralExpr,
subqueryExpr,
+ testExpr,
drillExpr,
literalExpr,
+ templateLiteralExpr,
}
diff --git a/packages/ast/src/index.ts b/packages/ast/src/index.ts
index 0b59d73..d897c98 100644
--- a/packages/ast/src/index.ts
+++ b/packages/ast/src/index.ts
@@ -1,3 +1,26 @@
+import type { TypeInfo } from './typeinfo.js'
+import { Type } from './typeinfo.js'
+
export * from './ast.js'
-export type { TypeInfo } from './typeinfo.js'
-export { Type } from './typeinfo.js'
+export type { TypeInfo }
+export { Type }
+
+export function repr(ti: TypeInfo): string {
+ switch (ti.type) {
+ case Type.Maybe:
+ return `maybe<${repr(ti.option)}>`
+ case Type.List:
+ return `${repr(ti.of)}[]`
+ case Type.Struct: {
+ const fields = Object.entries(ti.schema)
+ .map(e => `${e[0]}: ${repr(e[1])};`)
+ .join(' ')
+ return `{ ${fields} }`
+ }
+ case Type.Context:
+ case Type.Never:
+ throw new Error('Unsupported key type')
+ default:
+ return ti.type
+ }
+}
diff --git a/packages/get/package.json b/packages/get/package.json
index 4c8b5ff..7f73bd5 100644
--- a/packages/get/package.json
+++ b/packages/get/package.json
@@ -21,7 +21,7 @@
"@getlang/lib": "workspace:^0.2.1",
"@getlang/parser": "workspace:^0.4.3",
"@getlang/walker": "workspace:^0.1.0",
- "lodash-es": "^4.17.21"
+ "lodash-es": "^4.18.1"
},
"devDependencies": {
"@types/lodash-es": "^4.17.12"
diff --git a/packages/get/src/calls.ts b/packages/get/src/calls.ts
index a1dc0ed..75aa194 100644
--- a/packages/get/src/calls.ts
+++ b/packages/get/src/calls.ts
@@ -2,7 +2,11 @@ import type { TypeInfo } from '@getlang/ast'
import { Type } from '@getlang/ast'
import type { Hooks, Inputs } from '@getlang/lib'
import { cookies, html, invariant, js, json } from '@getlang/lib'
-import { ImportError, ValueReferenceError } from '@getlang/lib/errors'
+import {
+ ImportError,
+ SliceError,
+ ValueReferenceError,
+} from '@getlang/lib/errors'
import { partition } from 'lodash-es'
import type { Entry, Registry } from './registry.js'
import type { RuntimeValue } from './value.js'
@@ -20,7 +24,11 @@ export async function callModifier(
if (entry.useContext && context) {
ctx = entry.materialize ? materialize(context) : context.data
}
- return entry.mod(ctx, args)
+ try {
+ return await entry.mod(ctx, args)
+ } catch (e) {
+ throw new SliceError({ cause: e })
+ }
}
invariant(context, 'Modifier requires context')
diff --git a/packages/get/src/execute.ts b/packages/get/src/execute.ts
index 85f2ffb..d90fd8a 100644
--- a/packages/get/src/execute.ts
+++ b/packages/get/src/execute.ts
@@ -80,6 +80,10 @@ export async function execute(
return { data: node.value, typeInfo: node.typeInfo }
},
+ TemplateLiteralExpr(node) {
+ return node.value
+ },
+
Program: {
enter() {
scope.extracted = { data: null, typeInfo: { type: Type.Value } }
@@ -204,7 +208,8 @@ export async function execute(
DrillExpr: {
async enter(node, path) {
for (const expr of node.body) {
- if (!(scope.context?.data instanceof lib.NullSelection)) {
+ const isNull = scope.context?.data instanceof lib.NullSelection
+ if (!isNull) {
const data = await withItemContext(expr)
scope.context = { data, typeInfo: expr.typeInfo }
}
@@ -213,6 +218,19 @@ export async function execute(
},
},
+ TestExpr: {
+ async enter(node, path) {
+ const test = await reduce(node.test, options)
+ const value =
+ test.data instanceof lib.NullSelection
+ ? await reduce(node.f, options)
+ : node.t
+ ? await reduce(node.t, options)
+ : test
+ path.replace(value)
+ },
+ },
+
async RequestExpr(node) {
const method = node.method.value
const url = node.url.data
diff --git a/packages/get/src/registry.ts b/packages/get/src/registry.ts
index 878e6d9..d7cd384 100644
--- a/packages/get/src/registry.ts
+++ b/packages/get/src/registry.ts
@@ -1,7 +1,7 @@
import type { Program, TypeInfo } from '@getlang/ast'
-import { Type } from '@getlang/ast'
+import { repr, Type } from '@getlang/ast'
import type { Hooks, Modifier } from '@getlang/lib'
-import { RecursiveCallError, ValueTypeError } from '@getlang/lib/errors'
+import { RecursiveCallError } from '@getlang/lib/errors'
import { analyze, desugar, inference, parse } from '@getlang/parser'
type ModEntry = {
@@ -24,26 +24,6 @@ export type Entry = {
returnType: TypeInfo
}
-function repr(ti: TypeInfo): string {
- switch (ti.type) {
- case Type.Maybe:
- return `maybe<${repr(ti.option)}>`
- case Type.List:
- return `${repr(ti.of)}[]`
- case Type.Struct: {
- const fields = Object.entries(ti.schema)
- .map(e => `${e[0]}: ${repr(e[1])};`)
- .join(' ')
- return `{ ${fields} }`
- }
- case Type.Context:
- case Type.Never:
- throw new ValueTypeError('Unsupported key type')
- default:
- return ti.type
- }
-}
-
function buildImportKey(module: string, typeInfo?: TypeInfo) {
let key = module
if (typeInfo) {
diff --git a/packages/lib/package.json b/packages/lib/package.json
index 20bf67d..8ab0ec0 100644
--- a/packages/lib/package.json
+++ b/packages/lib/package.json
@@ -27,18 +27,17 @@
"@getlang/xpath": "0.0.35-0",
"@types/esquery": "^1.5.4",
"@types/lodash-es": "^4.17.12",
- "@types/set-cookie-parser": "^2.4.10",
- "acorn": "^8.15.0",
- "css-select": "^6.0.0",
- "css-what": "^7.0.0",
- "dom-serializer": "^2.0.0",
+ "acorn": "^8.18.0",
+ "css-select": "^7.0.0",
+ "css-what": "^8.0.0",
+ "dom-serializer": "^3.1.1",
"domelementtype": "*",
- "domhandler": "^5.0.3",
- "domutils": "^3.2.2",
- "esquery": "^1.6.0",
- "lodash-es": "^4.17.21",
- "parse5": "^8.0.0",
- "parse5-htmlparser2-tree-adapter": "^8.0.0",
- "set-cookie-parser": "^2.7.1"
+ "domhandler": "^6.0.1",
+ "domutils": "^4.0.2",
+ "esquery": "^1.7.0",
+ "lodash-es": "^4.18.1",
+ "parse5": "^8.0.1",
+ "parse5-htmlparser2-tree-adapter": "^8.0.1",
+ "set-cookie-parser": "^3.1.2"
}
}
diff --git a/packages/lib/src/core/errors.ts b/packages/lib/src/core/errors.ts
index 88a86e8..b212671 100644
--- a/packages/lib/src/core/errors.ts
+++ b/packages/lib/src/core/errors.ts
@@ -56,6 +56,14 @@ export class SelectorSyntaxError extends RuntimeError {
}
}
+export class ParseValueError extends RuntimeError {
+ public override name = 'SelectorSyntaxError'
+
+ constructor(type: string, options?: ErrorOptions) {
+ super(`Failed to parse value as ${type}`, options)
+ }
+}
+
export class NullSelectionError extends RuntimeError {
public override name = 'NullSelectionError'
@@ -105,7 +113,11 @@ export function invariant(
err: string | RuntimeError,
): asserts condition {
if (!condition) {
- throw typeof err === 'string' ? new FatalError({ cause: err }) : err
+ if (typeof err === 'string') {
+ const cause = new Error(err)
+ throw new FatalError({ cause })
+ }
+ throw err
}
}
diff --git a/packages/lib/src/net/http.ts b/packages/lib/src/net/http.ts
index 67a1443..95b1b4f 100644
--- a/packages/lib/src/net/http.ts
+++ b/packages/lib/src/net/http.ts
@@ -1,4 +1,4 @@
-import { RequestError } from '../core/errors.js'
+import { invariant, QuerySyntaxError, RequestError } from '../core/errors.js'
import type { RequestHook } from '../core/hooks.js'
type StringMap = Record
@@ -10,15 +10,6 @@ type Blocks = {
form?: StringMap
}
-// RFC 3986 compliance
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#description
-const fixedEncodeURIComponent = (str: string) => {
- return encodeURIComponent(str).replace(
- /[!'()*]/g,
- c => `%${c.charCodeAt(0).toString(16).toUpperCase()}`,
- )
-}
-
export const requestHook: RequestHook = async (url, opts) => {
const res = await fetch(url, opts)
return {
@@ -60,19 +51,32 @@ export const request = async (
// construct headers
const headers = new Headers(_headers)
if (blocks.cookies) {
- const pairs = Object.entries(blocks.cookies).map(entry =>
- entry.map(fixedEncodeURIComponent).join('='),
- )
+ const pairs = Object.entries(blocks.cookies).map(entry => entry.join('='))
const cookieHeader = pairs.join('; ')
headers.set('cookie', cookieHeader)
}
// construct body
let body: string | undefined
+ const { json, form } = blocks
+ invariant(
+ [bodyRaw, json, form].filter(Boolean).length <= 1,
+ new QuerySyntaxError('Request accepts only one of: [body], [json], [form]'),
+ )
if (bodyRaw) {
body = bodyRaw
- } else if (blocks.json) {
+ } else if (json) {
body = JSON.stringify(blocks.json)
+ } else if (form) {
+ const fd = new FormData()
+ for (const [k, v] of Object.entries(form)) {
+ fd.append(k, v)
+ }
+ const req = new Request('http://dummy', { method: 'POST', body: fd })
+ const ct = req.headers.get('content-type')
+ invariant(ct, 'Form serialization error')
+ headers.append('content-type', ct)
+ body = await req.text()
}
// make request
diff --git a/packages/lib/src/values/html/patch-dom.ts b/packages/lib/src/values/html/patch-dom.ts
index 2d762dd..8671e18 100644
--- a/packages/lib/src/values/html/patch-dom.ts
+++ b/packages/lib/src/values/html/patch-dom.ts
@@ -1,5 +1,5 @@
-import ds from 'dom-serializer'
// @sideEffects
+import ds from 'dom-serializer'
import type { ElementType } from 'domelementtype'
import type { AnyNode } from 'domhandler'
import { Element, Node } from 'domhandler'
@@ -19,38 +19,52 @@ function main() {
return ds(this)
}
- Object.defineProperty(Node.prototype, 'nodeName', {
- get: function () {
- return this.name
- },
- })
-
- Object.defineProperty(Node.prototype, 'localName', {
- get: function () {
- return this.name
- },
- })
-
- const origAttributes = Object.getOwnPropertyDescriptor(
- Element.prototype,
- 'attributes',
- )?.get
-
- if (origAttributes) {
- Object.defineProperty(Element.prototype, 'attributes', {
- get: function (...args) {
- const attrs = origAttributes.call(this, ...args)
- attrs.item = (idx: number) => {
- const el = attrs[idx]
- return { ...el, nodeType: 2, localName: el.name }
- }
- return attrs
+ if (!Object.hasOwn(Node.prototype, 'nodeName')) {
+ Object.defineProperty(Node.prototype, 'nodeName', {
+ get: function () {
+ return this.name
},
})
- } else {
- console.warn(
- '[WARN] Unable to patch DOM: Element.attributes property descriptor not found',
- )
+ }
+
+ if (!Object.hasOwn(Node.prototype, 'localName')) {
+ Object.defineProperty(Node.prototype, 'localName', {
+ get: function () {
+ return this.name
+ },
+ })
+ }
+
+ const attributesPatched = Symbol.for('your-package.Element.attributesPatched')
+
+ if (!(attributesPatched in Element.prototype)) {
+ const origAttributes = Object.getOwnPropertyDescriptor(
+ Element.prototype,
+ 'attributes',
+ )?.get
+
+ if (origAttributes) {
+ Object.defineProperty(Element.prototype, 'attributes', {
+ get(...args) {
+ const attrs = origAttributes.call(this, ...args)
+
+ attrs.item = (idx: number) => {
+ const el = attrs[idx]
+ return { ...el, nodeType: 2, localName: el.name }
+ }
+
+ return attrs
+ },
+ })
+
+ Object.defineProperty(Element.prototype, attributesPatched, {
+ value: true,
+ })
+ } else {
+ console.warn(
+ '[WARN] Unable to patch DOM: Element.attributes property descriptor not found',
+ )
+ }
}
}
diff --git a/packages/lib/src/values/js.ts b/packages/lib/src/values/js.ts
index 7a69fc1..a5e7e32 100644
--- a/packages/lib/src/values/js.ts
+++ b/packages/lib/src/values/js.ts
@@ -5,8 +5,8 @@ import {
ConversionError,
invariant,
NullSelection,
+ ParseValueError,
SelectorSyntaxError,
- SliceSyntaxError,
} from '../core/errors.js'
export const parse = (js: string): AnyNode => {
@@ -16,7 +16,7 @@ export const parse = (js: string): AnyNode => {
allowAwaitOutsideFunction: true,
})
} catch (e) {
- throw new SliceSyntaxError('Could not parse slice', { cause: e })
+ throw new ParseValueError('JavaScript', { cause: e })
}
}
diff --git a/packages/lib/src/values/json.ts b/packages/lib/src/values/json.ts
index 72481f6..f9f2812 100644
--- a/packages/lib/src/values/json.ts
+++ b/packages/lib/src/values/json.ts
@@ -1,7 +1,13 @@
import { get, toPath } from 'lodash-es'
-import { NullSelection } from '../core/errors.js'
+import { NullSelection, ParseValueError } from '../core/errors.js'
-export const parse = (json: string) => JSON.parse(json)
+export const parse = (json: string) => {
+ try {
+ return JSON.parse(json)
+ } catch (_) {
+ throw new ParseValueError('JSON')
+ }
+}
// only an `undefined` result is considered a null selection
// if result itself is null, the key is present. This is a
diff --git a/packages/parser/package.json b/packages/parser/package.json
index 4184590..7891568 100644
--- a/packages/parser/package.json
+++ b/packages/parser/package.json
@@ -28,13 +28,13 @@
"@getlang/walker": "workspace:^0.1.0",
"@types/moo": "^0.5.10",
"@types/nearley": "^2.11.5",
- "acorn": "^8.15.0",
- "estree-toolkit": "^1.7.13",
- "globals": "^16.4.0",
- "lodash-es": "^4.17.21",
- "moo": "^0.5.2",
+ "acorn": "^8.18.0",
+ "estree-toolkit": "^1.7.14",
+ "globals": "^17.12.0",
+ "lodash-es": "^4.18.1",
+ "moo": "^0.5.3",
"nearley": "^2.20.1",
- "prettier": "^3.6.2"
+ "prettier": "^3.9.8"
},
"devDependencies": {
"@types/lodash-es": "^4.17.12"
diff --git a/packages/parser/src/grammar.ts b/packages/parser/src/grammar.ts
index 99529a0..129bd2a 100644
--- a/packages/parser/src/grammar.ts
+++ b/packages/parser/src/grammar.ts
@@ -3,7 +3,10 @@
// Bypasses TS6133. Allow declared but unused functions.
// @ts-ignore
function id(d: any[]): any { return d[0]; }
+declare var kw_inputs: any;
+declare var kw_set: any;
declare var identifier: any;
+declare var kw_extract: any;
declare var request_verb: any;
declare var request_block_name: any;
declare var request_block_body: any;
@@ -21,7 +24,7 @@ declare var ws: any;
declare var comment: any;
declare var nl: any;
-import lexer from './grammar/lexer.js'
+import { lexer } from './grammar/lexer.js'
import * as p from './grammar/parse.js'
interface NearleyToken {
@@ -69,11 +72,11 @@ const grammar: Grammar = {
{"name": "inputs$ebnf$1", "symbols": []},
{"name": "inputs$ebnf$1$subexpression$1", "symbols": ["_", {"literal":","}, "_", "input_decl"]},
{"name": "inputs$ebnf$1", "symbols": ["inputs$ebnf$1", "inputs$ebnf$1$subexpression$1"], "postprocess": (d) => d[0].concat([d[1]])},
- {"name": "inputs", "symbols": [{"literal":"inputs"}, "__", {"literal":"{"}, "_", "input_decl", "inputs$ebnf$1", "_", {"literal":"}"}], "postprocess": p.declInputs},
+ {"name": "inputs", "symbols": [(lexer.has("kw_inputs") ? {type: "kw_inputs"} : kw_inputs), "__", {"literal":"{"}, "_", "input_decl", "inputs$ebnf$1", "_", {"literal":"}"}], "postprocess": p.declInputs},
{"name": "assignment$ebnf$1", "symbols": [{"literal":"?"}], "postprocess": id},
{"name": "assignment$ebnf$1", "symbols": [], "postprocess": () => null},
- {"name": "assignment", "symbols": [{"literal":"set"}, "__", (lexer.has("identifier") ? {type: "identifier"} : identifier), "assignment$ebnf$1", "_", {"literal":"="}, "_", "expression"], "postprocess": p.assignment},
- {"name": "extract", "symbols": [{"literal":"extract"}, "__", "expression"], "postprocess": p.extract},
+ {"name": "assignment", "symbols": [(lexer.has("kw_set") ? {type: "kw_set"} : kw_set), "__", (lexer.has("identifier") ? {type: "identifier"} : identifier), "assignment$ebnf$1", "_", {"literal":"="}, "_", "expression"], "postprocess": p.assignment},
+ {"name": "extract", "symbols": [(lexer.has("kw_extract") ? {type: "kw_extract"} : kw_extract), "__", "expression"], "postprocess": p.extract},
{"name": "input_decl$ebnf$1", "symbols": [{"literal":"?"}], "postprocess": id},
{"name": "input_decl$ebnf$1", "symbols": [], "postprocess": () => null},
{"name": "input_decl$ebnf$2$subexpression$1", "symbols": ["_", {"literal":"="}, "_", "input_default"]},
@@ -102,18 +105,22 @@ const grammar: Grammar = {
{"name": "request_entry$ebnf$1", "symbols": [], "postprocess": () => null},
{"name": "request_entry", "symbols": ["template", {"literal":":"}, "request_entry$ebnf$1"], "postprocess": p.requestEntry},
{"name": "request_block_body", "symbols": [(lexer.has("request_block_body") ? {type: "request_block_body"} : request_block_body), "template", (lexer.has("request_block_body_end") ? {type: "request_block_body_end"} : request_block_body_end)], "postprocess": p.requestBlockBody},
- {"name": "expression", "symbols": ["drill"], "postprocess": id},
- {"name": "expression$ebnf$1$subexpression$1", "symbols": ["drill", "_", (lexer.has("drill_arrow") ? {type: "drill_arrow"} : drill_arrow), "_"]},
+ {"name": "expression", "symbols": ["test"], "postprocess": id},
+ {"name": "expression$ebnf$1$subexpression$1", "symbols": ["test", "_", (lexer.has("drill_arrow") ? {type: "drill_arrow"} : drill_arrow), "_"]},
{"name": "expression$ebnf$1", "symbols": ["expression$ebnf$1$subexpression$1"], "postprocess": id},
{"name": "expression$ebnf$1", "symbols": [], "postprocess": () => null},
- {"name": "expression", "symbols": ["expression$ebnf$1", (lexer.has("link") ? {type: "link"} : link), "_", "drill"], "postprocess": p.link},
- {"name": "drill$ebnf$1$subexpression$1", "symbols": [(lexer.has("drill_arrow") ? {type: "drill_arrow"} : drill_arrow), "_"]},
- {"name": "drill$ebnf$1", "symbols": ["drill$ebnf$1$subexpression$1"], "postprocess": id},
- {"name": "drill$ebnf$1", "symbols": [], "postprocess": () => null},
- {"name": "drill$ebnf$2", "symbols": []},
- {"name": "drill$ebnf$2$subexpression$1", "symbols": ["_", (lexer.has("drill_arrow") ? {type: "drill_arrow"} : drill_arrow), "_", "bit"]},
- {"name": "drill$ebnf$2", "symbols": ["drill$ebnf$2", "drill$ebnf$2$subexpression$1"], "postprocess": (d) => d[0].concat([d[1]])},
- {"name": "drill", "symbols": ["drill$ebnf$1", "bit", "drill$ebnf$2"], "postprocess": p.drill},
+ {"name": "expression", "symbols": ["expression$ebnf$1", (lexer.has("link") ? {type: "link"} : link), "_", "test"], "postprocess": p.link},
+ {"name": "test", "symbols": ["fallback", "_", {"literal":"?"}, "_", "fallback", "_", {"literal":":"}, "_", "test"], "postprocess": p.test},
+ {"name": "test", "symbols": ["fallback"], "postprocess": id},
+ {"name": "fallback", "symbols": ["chain", "_", {"literal":"?:"}, "_", "fallback"], "postprocess": p.fallback},
+ {"name": "fallback", "symbols": ["chain"], "postprocess": id},
+ {"name": "chain$ebnf$1$subexpression$1", "symbols": [(lexer.has("drill_arrow") ? {type: "drill_arrow"} : drill_arrow), "_"]},
+ {"name": "chain$ebnf$1", "symbols": ["chain$ebnf$1$subexpression$1"], "postprocess": id},
+ {"name": "chain$ebnf$1", "symbols": [], "postprocess": () => null},
+ {"name": "chain$ebnf$2", "symbols": []},
+ {"name": "chain$ebnf$2$subexpression$1", "symbols": ["_", (lexer.has("drill_arrow") ? {type: "drill_arrow"} : drill_arrow), "_", "bit"]},
+ {"name": "chain$ebnf$2", "symbols": ["chain$ebnf$2", "chain$ebnf$2$subexpression$1"], "postprocess": (d) => d[0].concat([d[1]])},
+ {"name": "chain", "symbols": ["chain$ebnf$1", "bit", "chain$ebnf$2"], "postprocess": p.drill},
{"name": "bit$subexpression$1", "symbols": ["literal"]},
{"name": "bit$subexpression$1", "symbols": ["slice"]},
{"name": "bit$subexpression$1", "symbols": ["call"]},
@@ -134,17 +141,19 @@ const grammar: Grammar = {
{"name": "object$ebnf$1$subexpression$1", "symbols": ["object_entry", "object$ebnf$1$subexpression$1$ebnf$1", "_"]},
{"name": "object$ebnf$1", "symbols": ["object$ebnf$1", "object$ebnf$1$subexpression$1"], "postprocess": (d) => d[0].concat([d[1]])},
{"name": "object", "symbols": [{"literal":"{"}, "_", "object$ebnf$1", {"literal":"}"}], "postprocess": p.object},
- {"name": "object_entry$ebnf$1", "symbols": [{"literal":"@"}], "postprocess": id},
+ {"name": "object_entry$subexpression$1$ebnf$1", "symbols": [{"literal":"@"}], "postprocess": id},
+ {"name": "object_entry$subexpression$1$ebnf$1", "symbols": [], "postprocess": () => null},
+ {"name": "object_entry$subexpression$1$ebnf$2", "symbols": [{"literal":"?"}], "postprocess": id},
+ {"name": "object_entry$subexpression$1$ebnf$2", "symbols": [], "postprocess": () => null},
+ {"name": "object_entry$subexpression$1", "symbols": ["object_entry$subexpression$1$ebnf$1", (lexer.has("identifier") ? {type: "identifier"} : identifier), "object_entry$subexpression$1$ebnf$2"]},
+ {"name": "object_entry$subexpression$1", "symbols": ["literal"]},
+ {"name": "object_entry", "symbols": ["object_entry$subexpression$1", {"literal":":"}, "_", "expression"], "postprocess": p.objectEntry},
+ {"name": "object_entry$ebnf$1", "symbols": [{"literal":"?"}], "postprocess": id},
{"name": "object_entry$ebnf$1", "symbols": [], "postprocess": () => null},
+ {"name": "object_entry", "symbols": [(lexer.has("identifier") ? {type: "identifier"} : identifier), "object_entry$ebnf$1"], "postprocess": p.objectEntryShorthandSelect},
{"name": "object_entry$ebnf$2", "symbols": [{"literal":"?"}], "postprocess": id},
{"name": "object_entry$ebnf$2", "symbols": [], "postprocess": () => null},
- {"name": "object_entry", "symbols": ["object_entry$ebnf$1", (lexer.has("identifier") ? {type: "identifier"} : identifier), "object_entry$ebnf$2", {"literal":":"}, "_", "expression"], "postprocess": p.objectEntry},
- {"name": "object_entry$ebnf$3", "symbols": [{"literal":"?"}], "postprocess": id},
- {"name": "object_entry$ebnf$3", "symbols": [], "postprocess": () => null},
- {"name": "object_entry", "symbols": [(lexer.has("identifier") ? {type: "identifier"} : identifier), "object_entry$ebnf$3"], "postprocess": p.objectEntryShorthandSelect},
- {"name": "object_entry$ebnf$4", "symbols": [{"literal":"?"}], "postprocess": id},
- {"name": "object_entry$ebnf$4", "symbols": [], "postprocess": () => null},
- {"name": "object_entry", "symbols": [(lexer.has("identifier_expr") ? {type: "identifier_expr"} : identifier_expr), "object_entry$ebnf$4"], "postprocess": p.objectEntryShorthandIdent},
+ {"name": "object_entry", "symbols": [(lexer.has("identifier_expr") ? {type: "identifier_expr"} : identifier_expr), "object_entry$ebnf$2"], "postprocess": p.objectEntryShorthandIdent},
{"name": "template$ebnf$1$subexpression$1", "symbols": [(lexer.has("str") ? {type: "str"} : str)]},
{"name": "template$ebnf$1$subexpression$1", "symbols": [(lexer.has("interpvar") ? {type: "interpvar"} : interpvar)]},
{"name": "template$ebnf$1$subexpression$1", "symbols": ["interp_expr"]},
diff --git a/packages/parser/src/grammar/getlang.ne b/packages/parser/src/grammar/getlang.ne
index 140d0e1..9709997 100644
--- a/packages/parser/src/grammar/getlang.ne
+++ b/packages/parser/src/grammar/getlang.ne
@@ -1,5 +1,5 @@
@{%
-import lexer from './grammar/lexer.js'
+import { lexer } from './grammar/lexer.js'
import * as p from './grammar/parse.js'
%}
@@ -12,9 +12,9 @@ statements -> statement (line_sep statement):* {% p.statements %}
statement -> (request | assignment | extract) {% p.idd %}
# keywords
-inputs -> "inputs" __ "{" _ input_decl (_ "," _ input_decl):* _ "}" {% p.declInputs %}
-assignment -> "set" __ %identifier "?":? _ "=" _ expression {% p.assignment %}
-extract -> "extract" __ expression {% p.extract %}
+inputs -> %kw_inputs __ "{" _ input_decl (_ "," _ input_decl):* _ "}" {% p.declInputs %}
+assignment -> %kw_set __ %identifier "?":? _ "=" _ expression {% p.assignment %}
+extract -> %kw_extract __ expression {% p.extract %}
# inputs
input_decl -> %identifier "?":? (_ "=" _ input_default):? {% p.inputDecl %}
@@ -29,11 +29,13 @@ request_entry -> template ":" (__ template):? {% p.requestEntry %}
request_block_body -> %request_block_body template %request_block_body_end {% p.requestBlockBody %}
# expression
-expression -> drill {% id %}
-expression -> (drill _ %drill_arrow _):? %link _ drill {% p.link %}
-
-# drill
-drill -> (%drill_arrow _):? bit (_ %drill_arrow _ bit):* {% p.drill %}
+expression -> test {% id %}
+expression -> (test _ %drill_arrow _):? %link _ test {% p.link %}
+test -> fallback _ "?" _ fallback _ ":" _ test {% p.test %}
+test -> fallback {% id %}
+fallback -> chain _ "?:" _ fallback {% p.fallback %}
+fallback -> chain {% id %}
+chain -> (%drill_arrow _):? bit (_ %drill_arrow _ bit):* {% p.drill %}
# drill bit
bit -> (literal | slice | call | object | subquery) {% p.idd %}
@@ -48,7 +50,7 @@ call -> %call ("(" object ")"):? {% p.call %}
# object literals
object -> "{" _ (object_entry (_ ","):? _):* "}" {% p.object %}
-object_entry -> "@":? %identifier "?":? ":" _ expression {% p.objectEntry %}
+object_entry -> ("@":? %identifier "?":? | literal) ":" _ expression {% p.objectEntry %}
object_entry -> %identifier "?":? {% p.objectEntryShorthandSelect %}
object_entry -> %identifier_expr "?":? {% p.objectEntryShorthandIdent %}
diff --git a/packages/parser/src/grammar/lex/literals.ts b/packages/parser/src/grammar/lex/literals.ts
new file mode 100644
index 0000000..361592a
--- /dev/null
+++ b/packages/parser/src/grammar/lex/literals.ts
@@ -0,0 +1,40 @@
+import { invariant } from '@getlang/lib'
+import { QuerySyntaxError } from '@getlang/lib/errors'
+import { until } from './shared.js'
+
+function literal(delim: RegExp) {
+ return {
+ match: until(delim, {
+ prefix: delim,
+ inclusive: true,
+ }),
+ value(text: string) {
+ const inner = text.slice(1, -1)
+ return inner
+ },
+ }
+}
+
+export function slice(delim: RegExp) {
+ const tok = literal(delim)
+ return {
+ defaultType: 'slice',
+ ...tok,
+ lineBreaks: true,
+ value(text: string) {
+ const src = text.slice(1, -1).replace(/\\`/g, '`')
+ let lines = src.split('\n')
+ const firstIdx = lines.findIndex(x => x.trim().length)
+ invariant(
+ firstIdx !== -1,
+ new QuerySyntaxError('Slice must contain source'),
+ )
+ lines = lines.slice(firstIdx)
+ const indent = lines[0]?.match(/^\s*/)?.[0].length || 0
+ if (indent) {
+ lines = lines.map(x => x.replace(new RegExp(`^\\s{0,${indent}}`), ''))
+ }
+ return lines.join('\n').trim()
+ },
+ }
+}
diff --git a/packages/parser/src/grammar/lex/request.ts b/packages/parser/src/grammar/lex/request.ts
index 609d54f..20052f4 100644
--- a/packages/parser/src/grammar/lex/request.ts
+++ b/packages/parser/src/grammar/lex/request.ts
@@ -2,7 +2,7 @@ import { templateUntil } from './templates.js'
const requestBlockNames = ['query', 'cookies', 'json', 'form']
-const request = {
+const req = {
request_term: {
defaultType: 'nl',
match: /\n\s*$/,
@@ -24,24 +24,24 @@ const request = {
request_block_body: {
match: /^\s*\[body\]\n/,
lineBreaks: true,
- push: 'requestBody',
+ push: 'reqbody',
},
start_of_line_incl_ws: {
defaultType: 'ws',
match: /^\s*(?=.)/,
- push: 'requestKey',
+ push: 'reqkey',
},
colon: ':',
ws: {
match: ' ',
- push: 'requestValue',
+ push: 'reqval',
},
}
export const requestStates = {
- request,
- requestUrl: templateUntil(/\n/, { interpParams: true, next: 'request' }),
- requestKey: templateUntil(/:/),
- requestValue: templateUntil(/\n/),
- requestBody: templateUntil(/\n[^\S\r\n]*\[\/body\]/),
+ req,
+ requrl: templateUntil(/\n/, { interpParams: true, next: 'req' }),
+ reqkey: templateUntil(/:/),
+ reqval: templateUntil(/\n/),
+ reqbody: templateUntil(/\n[^\S\r\n]*\[\/body\]/),
}
diff --git a/packages/parser/src/grammar/lex/shared.ts b/packages/parser/src/grammar/lex/shared.ts
index 30a5a87..ba53264 100644
--- a/packages/parser/src/grammar/lex/shared.ts
+++ b/packages/parser/src/grammar/lex/shared.ts
@@ -7,3 +7,27 @@ export const patterns = {
link: new RegExp(`\\@${id.source}\\)`),
call: new RegExp(`\\@${id.source}`),
}
+
+export const ws = {
+ ws: patterns.ws,
+ nl: {
+ match: /\n/,
+ lineBreaks: true,
+ },
+ comment: /--.*/,
+}
+
+type UntilOptions = {
+ prefix?: RegExp
+ inclusive?: boolean
+}
+
+// creates a new regex that consumes characters until the
+// `term` regex has been reached. the regex is multiline
+export const until = (term: RegExp, opts: UntilOptions = {}) => {
+ const prefix = opts.prefix ? opts.prefix.source : ''
+ const finalGroup = opts.inclusive ? '?:' : '?='
+ return new RegExp(
+ `${prefix}[^]*?[^\\\\](${finalGroup}${term.source}|(?![^]))`,
+ )
+}
diff --git a/packages/parser/src/grammar/lex/slice.ts b/packages/parser/src/grammar/lex/slice.ts
deleted file mode 100644
index 88e2d01..0000000
--- a/packages/parser/src/grammar/lex/slice.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { invariant } from '@getlang/lib'
-import { QuerySyntaxError } from '@getlang/lib/errors'
-import { until } from './templates.js'
-
-const getSliceValue = (text: string) => {
- const src = text.slice(1, -1).replace(/\\`/g, '`')
- let lines = src.split('\n')
- const firstIdx = lines.findIndex(x => x.trim().length)
- invariant(firstIdx !== -1, new QuerySyntaxError('Slice must contain source'))
- lines = lines.slice(firstIdx)
- const indent = lines[0]?.match(/^\s*/)?.[0].length || 0
- if (indent) {
- lines = lines.map(x => x.replace(new RegExp(`^\\s{0,${indent}}`), ''))
- }
- return lines.join('\n').trim()
-}
-
-export const slice_block = {
- defaultType: 'slice',
- match: until(/\|/, {
- prefix: /\|/,
- inclusive: true,
- }),
- lineBreaks: true,
- value: getSliceValue,
- pop: 1,
-}
-
-export const slice = {
- match: until(/`/, {
- prefix: /`/,
- inclusive: true,
- }),
- lineBreaks: true,
- value: getSliceValue,
- pop: 1,
-}
diff --git a/packages/parser/src/grammar/lex/templates.ts b/packages/parser/src/grammar/lex/templates.ts
index 96a2946..0af00fa 100644
--- a/packages/parser/src/grammar/lex/templates.ts
+++ b/packages/parser/src/grammar/lex/templates.ts
@@ -1,19 +1,4 @@
-import { patterns } from './shared.js'
-
-type UntilOptions = {
- prefix?: RegExp
- inclusive?: boolean
-}
-
-// creates a new regex that consumes characters until the
-// `term` regex has been reached. the regex is multiline
-export const until = (term: RegExp, opts: UntilOptions = {}) => {
- const prefix = opts.prefix ? opts.prefix.source : ''
- const finalGroup = opts.inclusive ? '?:' : '?='
- return new RegExp(
- `${prefix}[^]*?[^\\\\](${finalGroup}${term.source}|(?![^]))`,
- )
-}
+import { patterns, until } from './shared.js'
type TemplateUntilOptions = {
interpTemplate?: boolean
@@ -91,7 +76,7 @@ const interpTmplParams = {
...templateUntil(/]/, { interpParams: true }),
}
-const stringS = {
+const str_s = {
squot: {
match: `'`,
pop: 1,
@@ -99,7 +84,7 @@ const stringS = {
...templateUntil(/'/),
}
-const stringD = {
+const str_d = {
dquot: {
match: '"',
pop: 1,
@@ -108,10 +93,9 @@ const stringD = {
}
export const templateStates = {
- template: templateUntil(/\n|->|=>/, { interpTemplate: false }),
interpExpr,
interpTmpl,
interpTmplParams,
- stringS,
- stringD,
+ str_s,
+ str_d,
}
diff --git a/packages/parser/src/grammar/lexer.ts b/packages/parser/src/grammar/lexer.ts
index f8166d6..548d7d8 100644
--- a/packages/parser/src/grammar/lexer.ts
+++ b/packages/parser/src/grammar/lexer.ts
@@ -1,132 +1,142 @@
+import type { Rules } from 'moo'
import moo from 'moo'
+import { slice } from './lex/literals.js'
import { requestStates } from './lex/request.js'
-import { patterns } from './lex/shared.js'
-import { slice, slice_block } from './lex/slice.js'
-import { templateStates } from './lex/templates.js'
+import { patterns, ws } from './lex/shared.js'
+import { templateStates, templateUntil } from './lex/templates.js'
-const verbs = ['GET', 'PUT', 'POST', 'PATCH', 'DELETE']
-const keywords = ['inputs', 'set']
-
-const keywordsObj = Object.fromEntries(keywords.map(k => [`kw_${k}`, k]))
-
-const main = {
- ws: patterns.ws,
- nl: {
- match: /\n/,
- lineBreaks: true,
- },
- comment: /--.*/,
- kw_extract: {
- match: /extract(?=\s)/,
- push: 'expr',
+const strings = {
+ squot: {
+ match: `'`,
+ push: 'str_s',
},
- drill_arrow: {
- match: ['->', '=>'],
- push: 'drillExpr',
+ dquot: {
+ match: '"',
+ push: 'str_d',
},
- colon: {
- match: ':',
- push: 'expr',
+}
+
+const main: Rules = {
+ ...ws,
+ ...strings,
+ symbol: /[,?@]/,
+ lsymbol: {
+ match: /[{(]/,
+ push: 'main',
},
- assignment: {
- match: '=',
- push: 'expr',
+ rsymbol: {
+ match: /[})]/,
+ pop: 1,
},
request_verb: {
- match: new RegExp(`(?:${verbs.join('|')}) `),
- push: 'requestUrl',
+ match: /(?:GET|PUT|POST|PATCH|DELETE)\b/,
+ push: 'requrl',
value: (text: string) => text.trim(),
},
+ expr: {
+ match: /(?:extract\b|=|:)/,
+ next: 'expr',
+ type: moo.keywords({
+ kw_extract: 'extract',
+ assignment: '=',
+ colon: ':',
+ }),
+ },
identifier: {
match: patterns.identifier,
- type: moo.keywords(keywordsObj),
+ type: moo.keywords({
+ kw_inputs: 'inputs',
+ kw_set: 'set',
+ }),
},
identifier_expr: {
match: patterns.identifierExpr,
value: (text: string) => text.slice(1),
},
- symbols: /[{}(),?@]/,
}
-const exprBase = {
- ws: patterns.ws,
- nl: {
- match: /\n/,
- lineBreaks: true,
+const expr: Rules = {
+ ...ws,
+ lsymbol: {
+ type: () => 'ws',
+ match: /(?=[{('"])/,
+ next: 'chain',
+ },
+ drill_arrow: ['->', '=>', '?:'],
+ slice_block: {
+ ...slice(/\|/),
+ next: 'chain',
+ },
+ slice: {
+ ...slice(/`/),
+ next: 'chain',
},
- link: {
- match: patterns.link,
- value: (text: string) => text.slice(1, -1),
- },
- symbols: {
- match: /[{(]/,
- pop: 1,
+ num: {
+ match: /\d+(?:\.\d+)?/,
+ next: 'chain',
},
- template_interp: {
- defaultType: 'ws',
- match: /(?=\${)/,
- next: 'template',
+ bool: {
+ match: ['true', 'false'],
+ next: 'chain',
},
identifier_expr: {
match: patterns.identifierExpr,
value: (text: string) => text.slice(1),
- pop: 1,
+ next: 'chain',
+ },
+ link: {
+ match: patterns.link,
+ value: (text: string) => text.slice(1, -1),
},
- slice_block,
- slice,
call: {
match: patterns.call,
value: (text: string) => text.slice(1),
- pop: 1,
+ next: 'chain',
},
- squot: {
- match: `'`,
- next: 'stringS',
- },
- dquot: {
- match: `"`,
- next: 'stringD',
+ template: {
+ type: () => 'ws',
+ match: /(?=.)/,
+ next: 'template',
},
}
-const expr = {
- ...exprBase,
+const chain: Rules = {
+ ...ws,
drill_arrow: {
match: ['->', '=>'],
- next: 'drillExpr',
+ next: 'expr',
},
- num: {
- match: /\d+(?:\.\d+)?/,
- pop: 1,
+ fallback: {
+ match: '?:',
+ next: 'expr',
},
- bool: {
- match: ['true', 'false'],
- pop: 1,
+ test: {
+ match: '?',
+ next: 'expr',
},
- template: {
- defaultType: 'ws',
- match: /(?=.)/,
- next: 'template',
+ lsymbol: {
+ match: /[{(]/,
+ push: 'main',
},
-}
-
-const drillExpr = {
- ...exprBase,
- drill_arrow: ['->', '=>'],
- template: {
- defaultType: 'ws',
+ ...strings,
+ complete: {
+ type: () => 'ws',
match: /(?=.)/,
- next: 'template',
+ next: 'main',
},
}
-const lexer: any = moo.states({
+const template = templateUntil(/\n|->|=>|\?:/, {
+ interpTemplate: false,
+ next: 'chain',
+})
+
+export const lexer = moo.states({
$all: { err: moo.error },
main,
expr,
- drillExpr,
+ template,
+ chain,
...templateStates,
...requestStates,
})
-
-export default lexer
diff --git a/packages/parser/src/grammar/parse.ts b/packages/parser/src/grammar/parse.ts
index 475da48..871511f 100644
--- a/packages/parser/src/grammar/parse.ts
+++ b/packages/parser/src/grammar/parse.ts
@@ -93,9 +93,13 @@ export const link: PP = ([context, callee, _, link]) => {
callee,
t.objectLiteralExpr([t.objectEntryExpr(tx.template('@link'), link, true)]),
)
- const [drill, , arrow] = context || []
- const body = drill?.body || []
- return t.drillExpr([...body, drillBase(bit, arrow)])
+ const [pre, , arrow] = context || []
+ const call = drillBase(bit, arrow)
+ if (!pre) {
+ return call
+ }
+ const body = pre.kind === 'DrillExpr' ? pre.body : [pre]
+ return t.drillExpr([...body, call])
}
export const object: PP = d => {
@@ -103,7 +107,12 @@ export const object: PP = d => {
return t.objectLiteralExpr(entries)
}
-export const objectEntry: PP = ([callkey, identifier, optional, , , value]) => {
+export const objectEntry: PP = ([keypart, , , value]) => {
+ if (keypart.length === 1) {
+ const [key] = keypart
+ return t.objectEntryExpr(key, value)
+ }
+ const [callkey, identifier, optional] = keypart
const key = {
...identifier,
value: `${callkey ? '@' : ''}${identifier.value || '$'}`,
@@ -114,12 +123,14 @@ export const objectEntry: PP = ([callkey, identifier, optional, , , value]) => {
export const objectEntryShorthandSelect: PP = ([identifier, optional]) => {
const value = t.templateExpr([identifier])
const selector = t.drillExpr([t.selectorExpr(value, false)])
- return objectEntry([null, identifier, optional, null, null, selector])
+ const keypart = [null, identifier, optional]
+ return objectEntry([keypart, null, null, selector])
}
export const objectEntryShorthandIdent: PP = ([identifier, optional]) => {
const value = t.identifierExpr(identifier)
- return objectEntry([null, identifier, optional, null, null, value])
+ const keypart = [null, identifier, optional]
+ return objectEntry([keypart, null, null, value])
}
function drillBase(bit: Expr, arrow?: string): Expr {
@@ -140,6 +151,23 @@ export const drill: PP = ([arrow, bit, bits]) => {
return t.drillExpr([expr, ...exprs])
}
+function ternary(cond: any, tBranch: any, fBranch: any) {
+ invariant(cond.kind === 'DrillExpr', 'Expected drill test')
+ const pre = cond.body.slice(0, -1)
+ const test = t.testExpr(cond.body.at(-1), tBranch, fBranch)
+ return t.drillExpr([...pre, test])
+}
+
+export const test: PP = d => {
+ const [cond, , , , tBranch, , , , fBranch] = d
+ return ternary(cond, tBranch, fBranch)
+}
+
+export const fallback: PP = d => {
+ const [drill, , , , fBranch] = d
+ return ternary(drill, undefined, fBranch)
+}
+
export const selector: PP = ([template]) => t.selectorExpr(template, false)
export const idbit: PP = ([id]) => t.drillIdentifierExpr(id, false)
@@ -186,7 +214,7 @@ export const template: PP = d => {
}
export const literal: PP = ([[token]]) => t.literalExpr(token)
-export const string: PP = ([, template]) => template
+export const string: PP = ([, template]) => t.templateLiteralExpr(template)
export const interpExpr: PP = ([, , token]) => token
export const interpTmpl: PP = ([, , template]) => template
diff --git a/packages/parser/src/index.ts b/packages/parser/src/index.ts
index bec5167..962258c 100644
--- a/packages/parser/src/index.ts
+++ b/packages/parser/src/index.ts
@@ -1,4 +1,4 @@
-export { default as lexer } from './grammar/lexer.js'
+export { lexer } from './grammar/lexer.js'
export { parse } from './parse.js'
export { analyze } from './passes/analyze.js'
export { desugar } from './passes/desugar.js'
diff --git a/packages/parser/src/parse.ts b/packages/parser/src/parse.ts
index e8b7abf..fc4e219 100644
--- a/packages/parser/src/parse.ts
+++ b/packages/parser/src/parse.ts
@@ -2,15 +2,16 @@ import type { Program } from '@getlang/ast'
import { invariant } from '@getlang/lib'
import { QuerySyntaxError } from '@getlang/lib/errors'
import nearley from 'nearley'
-import lexer from './grammar/lexer.js'
+import { lexer } from './grammar/lexer.js'
import grammar from './grammar.js'
export function parse(source: string): Program {
- const parser = new nearley.Parser(nearley.Grammar.fromCompiled(grammar))
+ const gr = nearley.Grammar.fromCompiled(grammar)
+ const parser = new nearley.Parser(gr)
try {
parser.feed(source)
- } catch (e: unknown) {
- if (typeof e === 'object' && e && 'token' in e) {
+ } catch (e: any) {
+ if (e?.token) {
throw new QuerySyntaxError(
lexer.formatError(e.token, 'SyntaxError: Invalid token'),
)
diff --git a/packages/parser/src/passes/analyze.ts b/packages/parser/src/passes/analyze.ts
index 3059056..7e2acf0 100644
--- a/packages/parser/src/passes/analyze.ts
+++ b/packages/parser/src/passes/analyze.ts
@@ -16,7 +16,9 @@ export function analyze(ast: Program) {
},
ModuleExpr(node) {
imports.add(node.module.value)
- node.call && calls.add(node.module.value)
+ if (node.call) {
+ calls.add(node.module.value)
+ }
},
SelectorExpr() {
hasUnboundSelector ||= !scope.context
diff --git a/packages/parser/src/passes/desugar/links.ts b/packages/parser/src/passes/desugar/links.ts
index b273864..42196c8 100644
--- a/packages/parser/src/passes/desugar/links.ts
+++ b/packages/parser/src/passes/desugar/links.ts
@@ -18,17 +18,21 @@ export const settleLinks: DesugarPass = (ast, { parsers }) => {
new QuerySyntaxError('Modifier options must be an object'),
)
- const ctx = scope.context
- if (node.modifier.value === 'link' && ctx) {
- const lineage = scope.traceLineageRoot(ctx)
+ if (node.modifier.value === 'link') {
const hasBase = node.args.entries.some(e => render(e.key) === 'base')
- if (lineage?.kind === 'RequestExpr' && !hasBase) {
- node.args.entries.push(
- t.objectEntryExpr(
- tx.template('base'),
- parsers.lookup(lineage, 'link'),
- ),
+ if (!hasBase) {
+ const ctx = scope.findContext(ctx =>
+ scope.traceLineageRoots(ctx) ? true : ctx?.kind === 'RequestExpr',
)
+ const lineage = ctx && (scope.traceLineageRoots(ctx) || ctx)
+ if (!Array.isArray(lineage) && lineage?.kind === 'RequestExpr') {
+ node.args.entries.push(
+ t.objectEntryExpr(
+ tx.template('base'),
+ parsers.lookup(lineage, 'link'),
+ ),
+ )
+ }
}
}
},
@@ -42,11 +46,14 @@ export const settleLinks: DesugarPass = (ast, { parsers }) => {
invariant(value.kind === 'DrillExpr', 'Module links [1]')
const base = scope.getLineage(value)
invariant(base, 'Module links [2]')
- if (base.kind === 'ModifierExpr') {
+ if (Array.isArray(base) || base.kind === 'ModifierExpr') {
return
}
- const root = scope.traceLineageRoot(value)
- invariant(root?.kind === 'RequestExpr', 'Module links [3]')
+ const root = scope.traceLineageRoots(value)
+ invariant(
+ !Array.isArray(root) && root?.kind === 'RequestExpr',
+ 'Module links [3]',
+ )
const mod = t.modifierExpr(
tx.token('link'),
t.objectLiteralExpr([
diff --git a/packages/parser/src/passes/inference/calls.ts b/packages/parser/src/passes/inference/calls.ts
index 986564d..1d1ef15 100644
--- a/packages/parser/src/passes/inference/calls.ts
+++ b/packages/parser/src/passes/inference/calls.ts
@@ -10,9 +10,12 @@ export function registerCalls(
const scope = new LineageTracker()
function registerCall(node: Expr) {
- const lineage = scope.traceLineageRoot(node) || node
- if (lineage?.kind === 'ModuleExpr') {
- lineage.call = true
+ const lineage = scope.traceLineageRoots(node) || node
+ const roots = Array.isArray(lineage) ? lineage : [lineage]
+ for (const root of roots) {
+ if (root?.kind === 'ModuleExpr') {
+ root.call = true
+ }
}
}
@@ -42,7 +45,18 @@ export function registerCalls(
ModuleExpr(node) {
if (contextual.includes(node.module.value)) {
- return { ...node, call: true }
+ node.call = true
+ } else {
+ const usesResponse = node.args.entries.some(e => {
+ const lineage = scope.traceLineageRoots(e.value)
+ const roots = Array.isArray(lineage) ? lineage : [lineage]
+ return roots
+ .map(r => r?.kind)
+ .some(k => k === 'RequestExpr' || k === 'ModuleExpr')
+ })
+ if (!usesResponse) {
+ node.call = true
+ }
}
},
})
diff --git a/packages/parser/src/passes/inference/typeinfo.ts b/packages/parser/src/passes/inference/typeinfo.ts
index 4437139..e67ab98 100644
--- a/packages/parser/src/passes/inference/typeinfo.ts
+++ b/packages/parser/src/passes/inference/typeinfo.ts
@@ -1,10 +1,14 @@
import type { Expr, Node, Program, TypeInfo } from '@getlang/ast'
-import { Type, t } from '@getlang/ast'
+import { repr, Type, t } from '@getlang/ast'
import { invariant } from '@getlang/lib'
-import { QuerySyntaxError, ValueReferenceError } from '@getlang/lib/errors'
+import {
+ QuerySyntaxError,
+ ValueReferenceError,
+ ValueTypeError,
+} from '@getlang/lib/errors'
import type { Path, TransformVisitor } from '@getlang/walker'
import { ScopeTracker, transform } from '@getlang/walker'
-import { toPath } from 'lodash-es'
+import { isEqual, toPath } from 'lodash-es'
import { render, tx } from '../../utils.js'
function unwrap(typeInfo: TypeInfo) {
@@ -239,6 +243,16 @@ export function resolveTypes(ast: Program, options: ResolveTypeOptions) {
return { ...node, typeInfo }
},
+ TestExpr(node) {
+ const { t = node.test, f } = node
+ if (!isEqual(t.typeInfo, f.typeInfo)) {
+ const a = repr(t.typeInfo)
+ const b = repr(f.typeInfo)
+ throw new ValueTypeError(`Test expression type mismatch: ${a} !== ${b}`)
+ }
+ return { ...node, typeInfo: structuredClone(t.typeInfo) }
+ },
+
ObjectEntryExpr: {
enter(node) {
scope.optional.push(node.optional)
diff --git a/packages/parser/src/passes/lineage.ts b/packages/parser/src/passes/lineage.ts
index 9f5cc0e..21c8d61 100644
--- a/packages/parser/src/passes/lineage.ts
+++ b/packages/parser/src/passes/lineage.ts
@@ -4,23 +4,37 @@ import { ValueReferenceError } from '@getlang/lib/errors'
import type { Path } from '@getlang/walker'
import { ScopeTracker } from '@getlang/walker'
+type Parent = Expr | Expr[]
+
export class LineageTracker extends ScopeTracker {
- private lineage = new Map()
+ private lineage = new Map()
getLineage(expr: Expr) {
return this.lineage.get(expr)
}
- traceLineageRoot(expr: Expr) {
- let parent = this.lineage.get(expr)
- while (parent && this.lineage.has(parent)) {
- parent = this.lineage.get(parent)
+ traceLineageRoots(from: Expr): Parent | undefined {
+ const plan = new Set([from])
+ const roots = new Set()
+
+ for (const expr of plan) {
+ const lineage = this.getLineage(expr)
+ if (lineage) {
+ const list = Array.isArray(lineage) ? lineage : [lineage]
+ for (const expr of list) {
+ plan.add(expr)
+ }
+ } else if (expr !== from) {
+ roots.add(expr)
+ }
}
- return parent
+
+ const [first, ...rest] = roots
+ return rest.length ? Array.from(roots) : first
}
override exit(node: Node, path: Path) {
- const derive = (base: Expr) => this.lineage.set(node as Expr, base)
+ const derive = (base: Parent) => this.lineage.set(node as Expr, base)
switch (node.kind) {
case 'IdentifierExpr':
@@ -46,6 +60,10 @@ export class LineageTracker extends ScopeTracker {
derive(this.extracted)
}
break
+
+ case 'ObjectLiteralExpr':
+ derive(node.entries.map(x => x.value))
+ break
}
super.exit(node, path)
diff --git a/packages/parser/src/print.ts b/packages/parser/src/print.ts
index 6cad4e6..9a54c7c 100644
--- a/packages/parser/src/print.ts
+++ b/packages/parser/src/print.ts
@@ -102,6 +102,12 @@ const printVisitor: ReduceVisitor = {
})
},
+ TestExpr(node) {
+ return node.t
+ ? group([node.test, ' ? ', node.t, ' : ', node.f])
+ : group([node.test, ' ?: ', node.f])
+ },
+
ObjectEntryExpr(node, { node: orig }) {
if (orig.value.kind === 'IdentifierExpr') {
const key = render(orig.key)
@@ -152,9 +158,9 @@ const printVisitor: ReduceVisitor = {
})
},
- TemplateExpr(node, { node: orig }) {
+ TemplateExpr(node, path) {
return node.elements.map((el, i) => {
- const og = orig.elements[i]!
+ const og = path.node.elements[i]!
if (isToken(og)) {
return og.value
}
@@ -177,6 +183,10 @@ const printVisitor: ReduceVisitor = {
})
},
+ TemplateLiteralExpr(node) {
+ return ['"', node.value, '"']
+ },
+
IdentifierExpr(node) {
return ['$', node.id.value]
},
diff --git a/packages/parser/src/utils.ts b/packages/parser/src/utils.ts
index 9fd4a66..32b8ac6 100644
--- a/packages/parser/src/utils.ts
+++ b/packages/parser/src/utils.ts
@@ -1,12 +1,17 @@
import type { Expr, RequestExpr } from '@getlang/ast'
import { isToken, t } from '@getlang/ast'
-export const render = (template: Expr) => {
- if (template.kind !== 'TemplateExpr') {
- return null
+export const render = (template: Expr): string | null => {
+ switch (template.kind) {
+ case 'TemplateLiteralExpr':
+ return render(template.value)
+ case 'TemplateExpr': {
+ const els = template.elements
+ return els?.every(isToken) ? els.map(el => el.value).join('') : null
+ }
+ default:
+ return null
}
- const els = template.elements
- return els?.every(isToken) ? els.map(el => el.value).join('') : null
}
export function getContentField(req: RequestExpr) {
diff --git a/packages/walker/src/index.ts b/packages/walker/src/index.ts
index 049e019..edca8ea 100644
--- a/packages/walker/src/index.ts
+++ b/packages/walker/src/index.ts
@@ -10,7 +10,7 @@ import type {
import { wait, waitMap } from './wait.js'
export { ScopeTracker } from './scope.js'
-export type { TransformVisitor, ReduceVisitor, Path }
+export type { Path, ReduceVisitor, TransformVisitor }
export type WalkOptions = Visitor & {
scope?: ScopeTracker
diff --git a/packages/walker/src/scope.ts b/packages/walker/src/scope.ts
index 3632d74..b230bf4 100644
--- a/packages/walker/src/scope.ts
+++ b/packages/walker/src/scope.ts
@@ -27,6 +27,12 @@ export class ScopeTracker {
this.scopeStack.pop()
}
+ findContext(predicate: (ctx: T) => boolean): T | undefined {
+ return this.scopeStack.findLast(
+ s => s.context !== undefined && predicate(s.context),
+ )?.context
+ }
+
private get head() {
return this.scopeStack.at(-1)
}
diff --git a/test/expect.ts b/test/expect.ts
index 70e1da4..75a2702 100644
--- a/test/expect.ts
+++ b/test/expect.ts
@@ -2,7 +2,7 @@ import { expect } from 'bun:test'
import { diff } from 'jest-diff'
expect.extend({
- async toHaveServed(received: unknown, url: string, opts: RequestInit) {
+ toHaveServed(received: unknown, url: string, opts: RequestInit) {
const calls: [unknown, any][] = (received as any)?.mock?.calls
const { method, headers = {}, body } = opts
const expObj = { url, method, headers, body }
diff --git a/test/helpers.ts b/test/helpers.ts
index 7da58c0..f11f4ca 100644
--- a/test/helpers.ts
+++ b/test/helpers.ts
@@ -20,7 +20,7 @@ export const SELSYN = true
function testIdempotency(source: string) {
const print1 = print(desugar(parse(source)))
const print2 = print(desugar(parse(print1)))
- expect(print1).toEqual(print2)
+ expect(print2).toEqual(print1)
}
export async function execute(
diff --git a/test/modules.spec.ts b/test/modules.spec.ts
index 93baa7e..3bff579 100644
--- a/test/modules.spec.ts
+++ b/test/modules.spec.ts
@@ -204,13 +204,13 @@ describe('modules', () => {
expect(result).toEqual({ from_subquery: true })
})
- test.skip('object key', async () => {
+ test('object key', async () => {
const modules = {
Call,
Home: `
set called = |false|
extract {
- object: as_entry = { key: @Call({ $called }) } -> key -> called
+ object: { key: @Call({ $called }) } -> key -> called
}
`,
}
@@ -223,17 +223,19 @@ describe('modules', () => {
const modules = {
Reverse: `
inputs { list }
- set result = | list.map(x => Number(x) * 10).reverse() |
- extract { $result }
+ set is_html? = $list -> b
+ set mapped = | list.map(x => Number(x) * 10).reverse() |
+ extract { result: { $is_html, $mapped } }
`,
Home: `
- set list = "" -> @html => li
+ set list = "" -> @html => li
extract @Reverse({ $list }) -> result
`,
}
const result = await execute(modules)
- expect(result).toEqual([30, 20, 10])
+ expect(result).toEqual({ mapped: [30, 20, 10] })
+ expect(result).not.toHaveProperty('is_html')
})
test('drill return value', async () => {
@@ -355,12 +357,12 @@ describe('modules', () => {
extract #a
-> :scope > #b
- -> @Link) :scope > #c
+ -> @Next) :scope > #c
-> :scope > #d
`,
- Link: `
+ Next: `
extract {
- _module: |'Link'|
+ _module: |'Next'|
}
`,
}
@@ -431,7 +433,7 @@ describe('modules', () => {
Home: `
GET http://stub
- extract @Data({text: |'first'|})
+ extract @Data({text: |'first'| })
-> ./@data-json
-> @json
`,
@@ -474,40 +476,40 @@ describe('modules', () => {
)
})
- test('recursive link not called', async () => {
+ test('when no request data args', async () => {
const modules = {
- Home: `
- extract {
- page: @Page -> value
- }
+ NotMacro: `
+ inputs { num }
+ extract "100
" -> @html -> p
`,
- Page: `
- extract {
- value: @Home({
- called: |false|
- })
- }
+ Home: `
+ extract @NotMacro({ num: 0 })
`,
}
const result = await execute(modules)
- expect(result).toEqual({
- page: { called: false },
- })
+ expect(result).toEqual('100')
})
- test('non-macro not called', async () => {
+ test('when args contain module data', async () => {
const modules = {
- NotMacro: `
- extract "
100
" -> @html -> p
+ Echo: `
+ inputs { value }
+ extract { echoed: $value }
`,
Home: `
- extract @NotMacro({ num: 0 })
+ set first = @Echo({ value: "x" })
+ set value = $first -> echoed
+ set second = @Echo({ $value })
+ extract { $first, $second }
`,
}
-
const result = await execute(modules)
- expect(result).toEqual({ num: 0 })
+ expect(result).toEqual({
+ first: { echoed: 'x' },
+ // second should not contain echoed wrapped produced by call
+ second: { value: 'x' },
+ })
})
})
})
diff --git a/test/objects.spec.ts b/test/objects.spec.ts
index fa49593..ed960ce 100644
--- a/test/objects.spec.ts
+++ b/test/objects.spec.ts
@@ -83,4 +83,11 @@ describe('objects', () => {
},
})
})
+
+ test('template literals as key', async () => {
+ const result = await execute(`
+ extract {"foo":"bar"}
+ `)
+ expect(result).toEqual({ foo: 'bar' })
+ })
})
diff --git a/test/optionality.spec.ts b/test/optionality.spec.ts
new file mode 100644
index 0000000..b9148da
--- /dev/null
+++ b/test/optionality.spec.ts
@@ -0,0 +1,66 @@
+import { describe, expect, test } from 'bun:test'
+import { ValueTypeError } from '@getlang/lib/errors'
+import { execute } from './helpers.js'
+
+describe('optionality', () => {
+ describe('ternary', () => {
+ test('true branch', async () => {
+ const result = await execute(`
+ extract 12 ? 34 : 56
+ `)
+ expect(result).toEqual(34)
+ })
+ test('false branch', async () => {
+ const result = await execute(`
+ extract |undefined| ? 34 : 56
+ `)
+ expect(result).toEqual(56)
+ })
+ test('context sharing on true', async () => {
+ const result = await execute(`
+ set ctx = { a: 1, b: 2, c: 3}
+ extract $ctx
+ -> a
+ ? b
+ : c
+ `)
+ expect(result).toEqual(2)
+ })
+ test('context sharing on false', async () => {
+ const result = await execute(`
+ set ctx = { a: 1, b: 2, c: 3}
+ extract $ctx
+ -> x
+ ? b
+ : c
+ `)
+ expect(result).toEqual(3)
+ })
+ })
+
+ describe('ternary drill', () => {
+ test('true branch', async () => {
+ const result = await execute(`
+ extract "
para
" -> @html -> p ?: i
+ `)
+ expect(result).toEqual('para')
+ })
+ test('false branch', async () => {
+ const result = await execute(`
+ extract "ital" -> @html -> p ?: i
+ `)
+ expect(result).toEqual('ital')
+ })
+ })
+
+ test('type matching', async () => {
+ const result = execute(`
+ extract 12 ? { a: true } : { b: false }
+ `)
+ return expect(result).rejects.toThrow(
+ new ValueTypeError(
+ 'Test expression type mismatch: { a: value; } !== { b: value; }',
+ ),
+ )
+ })
+})
diff --git a/test/package.json b/test/package.json
index 76db412..d85254d 100644
--- a/test/package.json
+++ b/test/package.json
@@ -6,9 +6,10 @@
"@getlang/get": "workspace:*",
"@getlang/lib": "workspace:^0.2.1",
"@getlang/parser": "workspace:*",
- "dedent": "^1.7.0"
+ "dedent": "^1.7.2"
},
"devDependencies": {
- "jest-diff": "^30.1.2"
+ "@types/bun": "^1.4.2",
+ "jest-diff": "^30.5.1"
}
}
diff --git a/test/request.spec.ts b/test/request.spec.ts
index c8f1b90..b5c07c8 100644
--- a/test/request.spec.ts
+++ b/test/request.spec.ts
@@ -1,5 +1,6 @@
import { beforeEach, describe, expect, mock, test } from 'bun:test'
import type { Inputs } from '@getlang/lib'
+import dedent from 'dedent'
import type { Fetch } from './helpers.js'
import { execute as _exec } from './helpers.js'
@@ -28,32 +29,32 @@ describe('request', () => {
extract -> h1
`)
expect(mockFetch).toHaveBeenCalledTimes(1)
- await expect(mockFetch).toHaveServed('http://get.com/', { method: 'GET' })
+ expect(mockFetch).toHaveServed('http://get.com/', { method: 'GET' })
expect(result).toEqual('test')
})
test('post', async () => {
await execute('POST http://post.com')
- await expect(mockFetch).toHaveServed('http://post.com/', {
+ expect(mockFetch).toHaveServed('http://post.com/', {
method: 'POST',
})
})
test('put', async () => {
await execute('PUT http://put.com')
- await expect(mockFetch).toHaveServed('http://put.com/', { method: 'PUT' })
+ expect(mockFetch).toHaveServed('http://put.com/', { method: 'PUT' })
})
test('patch', async () => {
await execute('PATCH http://patch.com')
- await expect(mockFetch).toHaveServed('http://patch.com/', {
+ expect(mockFetch).toHaveServed('http://patch.com/', {
method: 'PATCH',
})
})
test('delete', async () => {
await execute('DELETE http://delete.com')
- await expect(mockFetch).toHaveServed('http://delete.com/', {
+ expect(mockFetch).toHaveServed('http://delete.com/', {
method: 'DELETE',
})
})
@@ -62,7 +63,7 @@ describe('request', () => {
describe('urls', () => {
test('literal', async () => {
await execute('GET http://get.com')
- await expect(mockFetch).toHaveServed('http://get.com/', {
+ expect(mockFetch).toHaveServed('http://get.com/', {
method: 'GET',
})
})
@@ -72,7 +73,7 @@ describe('request', () => {
set ident = |'http://ident.com'|
GET $ident
`)
- await expect(mockFetch).toHaveServed('http://ident.com/', {
+ expect(mockFetch).toHaveServed('http://ident.com/', {
method: 'GET',
})
})
@@ -82,12 +83,9 @@ describe('request', () => {
set query = |'monterey'|
GET https://boogle.com/search/$query
`)
- await expect(mockFetch).toHaveServed(
- 'https://boogle.com/search/monterey',
- {
- method: 'GET',
- },
- )
+ expect(mockFetch).toHaveServed('https://boogle.com/search/monterey', {
+ method: 'GET',
+ })
})
test('interpolated expression', async () => {
@@ -95,12 +93,9 @@ describe('request', () => {
set query = |'big sur'|
GET https://ging.com/\${query}_results
`)
- await expect(mockFetch).toHaveServed(
- 'https://ging.com/big%20sur_results',
- {
- method: 'GET',
- },
- )
+ expect(mockFetch).toHaveServed('https://ging.com/big%20sur_results', {
+ method: 'GET',
+ })
})
test('interpolated value', async () => {
@@ -108,7 +103,7 @@ describe('request', () => {
set loc = |'sea ranch
'| -> @html
GET https://goto.ca/:loc
`)
- await expect(mockFetch).toHaveServed('https://goto.ca/sea%20ranch', {
+ expect(mockFetch).toHaveServed('https://goto.ca/sea%20ranch', {
method: 'GET',
})
})
@@ -117,7 +112,7 @@ describe('request', () => {
await execute('GET http://implied.com/projects/:projectId', {
projectId: 12,
})
- await expect(mockFetch).toHaveServed('http://implied.com/projects/12', {
+ expect(mockFetch).toHaveServed('http://implied.com/projects/12', {
method: 'GET',
})
})
@@ -137,7 +132,7 @@ describe('request', () => {
Accept: application/json
`)
- await expect(mockFetch).toHaveServed('http://api.unweb.com/', {
+ expect(mockFetch).toHaveServed('http://api.unweb.com/', {
method: 'GET',
headers: new Headers({
Authorization: 'Bearer 123',
@@ -160,7 +155,7 @@ describe('request', () => {
c: interp$interp
`)
- await expect(mockFetch).toHaveServed(
+ expect(mockFetch).toHaveServed(
'https://example.com/?a=literal&b=b&c=interpolated',
{
method: 'GET',
@@ -178,12 +173,12 @@ describe('request', () => {
a: 2
b: 4
`)
- await expect(mockFetch).toHaveServed('http://example.com/?a=1&a=2&b=4', {
+ expect(mockFetch).toHaveServed('http://example.com/?a=1&a=2&b=4', {
method: 'GET',
})
})
- test('cookies, encoded', async () => {
+ test('cookies', async () => {
await execute(`
GET https://example.com
[cookies]
@@ -192,10 +187,10 @@ describe('request', () => {
c: /here&we!are?
`)
- await expect(mockFetch).toHaveServed('https://example.com/', {
+ expect(mockFetch).toHaveServed('https://example.com/', {
method: 'GET',
headers: new Headers({
- Cookie: 'a=A; b=123; c=%2Fhere%26we%21are%3F',
+ Cookie: 'a=A; b=123; c=/here&we!are?',
}),
})
})
@@ -208,12 +203,50 @@ describe('request', () => {
password: test
`)
- await expect(mockFetch).toHaveServed('https://example.com/login', {
+ expect(mockFetch).toHaveServed('https://example.com/login', {
method: 'POST',
body: '{"username":"admin","password":"test"}',
})
})
+ test('form body', async () => {
+ await execute(`
+ POST https://example.com/login
+ [form]
+ username: admin
+ password: test
+ `)
+
+ const [call] = (mockFetch as any).mock.calls
+ const hdrs: Headers = call[1].headers
+ const ct = hdrs.get('content-type')
+ expect(ct).toMatch(
+ /multipart\/form-data; boundary=----WebKitFormBoundary[0-9a-f]{32}/,
+ )
+
+ const boundary = ct?.split('boundary=-')[1]
+
+ const body = dedent`
+ ---${boundary}
+ Content-Disposition: form-data; name="username"
+
+ admin
+ ---${boundary}
+ Content-Disposition: form-data; name="password"
+
+ test
+ ---${boundary}--\n
+ `
+
+ expect(mockFetch).toHaveServed('https://example.com/login', {
+ method: 'POST',
+ headers: new Headers({
+ 'content-type': ct!,
+ }),
+ body: body.replaceAll('\n', '\r\n'),
+ })
+ })
+
test('raw body', async () => {
await execute(`
set hello = |"hi there"|
@@ -227,7 +260,7 @@ describe('request', () => {
[/body]
`)
- await expect(mockFetch).toHaveServed('https://example.com/', {
+ expect(mockFetch).toHaveServed('https://example.com/', {
method: 'POST',
headers: new Headers(),
body: "hello\n g'day\n welcome\n",
@@ -252,7 +285,7 @@ describe('request', () => {
bar: bar
`)
- await expect(mockFetch).toHaveServed('https://example.com/?bar=bar', {
+ expect(mockFetch).toHaveServed('https://example.com/?bar=bar', {
method: 'POST',
headers: new Headers({
'X-Bar': 'bar',
@@ -272,7 +305,7 @@ describe('request', () => {
X-Baz: baz$[$foo]zza
`)
- await expect(mockFetch).toHaveServed('https://example.com/pre/post', {
+ expect(mockFetch).toHaveServed('https://example.com/pre/post', {
method: 'GET',
headers: new Headers({
'X-Bar': 'bar',
@@ -294,22 +327,22 @@ describe('request', () => {
await execute(src, { y: '0y0' })
await execute(src, { x: '0x0', y: '0y0' })
- await expect(mockFetch).toHaveServed('https://getlang.dev/', {
+ expect(mockFetch).toHaveServed('https://getlang.dev/', {
method: 'GET',
headers: new Headers({ Header: 'aagg' }),
})
- await expect(mockFetch).toHaveServed('https://getlang.dev/', {
+ expect(mockFetch).toHaveServed('https://getlang.dev/', {
method: 'GET',
headers: new Headers({ Header: 'aabb0x0ccffgg' }),
})
- await expect(mockFetch).toHaveServed('https://getlang.dev/', {
+ expect(mockFetch).toHaveServed('https://getlang.dev/', {
method: 'GET',
headers: new Headers({ Header: 'aagg' }),
})
- await expect(mockFetch).toHaveServed('https://getlang.dev/', {
+ expect(mockFetch).toHaveServed('https://getlang.dev/', {
method: 'GET',
headers: new Headers({ Header: 'aabb0x0ccdd0y0eeffgg' }),
})
@@ -458,6 +491,16 @@ describe('request', () => {
expect(result).toEqual(['https://bar.com/foo'])
})
+ test('infer base from ambient context', async () => {
+ const result = await execute(`
+ GET http://x.y/seg1/seg2/seg3
+
+ extract "verify" -> @link
+ `)
+
+ expect(result).toEqual('http://x.y/seg1/seg2/verify')
+ })
+
test('resolved standalone links to context url', async () => {
const src = `
inputs { query, page? }
diff --git a/test/tsconfig.json b/test/tsconfig.json
index 4eb37fe..f8728a0 100644
--- a/test/tsconfig.json
+++ b/test/tsconfig.json
@@ -1,3 +1,6 @@
{
- "extends": "../tsconfig.base.json"
+ "extends": "../tsconfig.base.json",
+ "compilerOptions": {
+ "types": ["bun"]
+ }
}
diff --git a/test/values.spec.ts b/test/values.spec.ts
index 9fdbaba..ff74e14 100644
--- a/test/values.spec.ts
+++ b/test/values.spec.ts
@@ -2,6 +2,7 @@ import { describe, expect, test } from 'bun:test'
import {
ConversionError,
NullSelectionError,
+ ParseValueError,
SelectorSyntaxError,
} from '@getlang/lib/errors'
import { execute, SELSYN } from './helpers.js'
@@ -84,7 +85,7 @@ describe('values', () => {
test('thin arrow does not expand list', async () => {
let result = await execute(`
set list = |[{a: 1}, {a: 2}]|
- extract $list -> 0
+ extract $list -> [0]
`)
expect(result).toEqual({ a: 1 })
@@ -156,6 +157,11 @@ describe('values', () => {
`)
expect(result).toEqual(['item one', 'item two'])
})
+
+ test('parsing error', async () => {
+ const result = execute(`extract "" -> @json`)
+ return expect(result).rejects.toThrow(new ParseValueError('JSON'))
+ })
})
describe('html', () => {
@@ -282,6 +288,11 @@ describe('values', () => {
`)
expect(result).toEqual([501, 'many'])
})
+
+ test('parsing error', async () => {
+ const result = execute(`extract "{x!}" -> @js`)
+ return expect(result).rejects.toThrow(new ParseValueError('JavaScript'))
+ })
})
test('headers', async () => {
@@ -495,10 +506,10 @@ describe('values', () => {
extract $ctx -> {
str_s: -> 'one'
str_d: -> "two"
- int: -> 12
- float: -> 123.4
- bool_on: -> true
- bool_off: -> false
+ int: [12]
+ float: [123].4
+ bool_on: [true]
+ bool_off: [false]
}
`)
diff --git a/tsconfig.base.json b/tsconfig.base.json
index 2ce7e8e..fe5b1b2 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -1,21 +1,31 @@
{
"compilerOptions": {
"customConditions": ["bun"],
- "esModuleInterop": true,
- "skipLibCheck": true,
- "target": "es2022",
- "allowJs": true,
- "resolveJsonModule": true,
+
+ // Environment setup & latest features
+ "lib": ["esnext", "dom", "dom.iterable"],
+ "target": "ESNext",
+ "module": "Preserve",
"moduleDetection": "force",
- "isolatedModules": true,
+ "jsx": "react-jsx",
+ "allowJs": true,
+
+ // Bundler mode
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
+ "noEmit": true,
+
+ // Best practices
"strict": true,
+ "skipLibCheck": true,
+ "noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
- "module": "NodeNext",
- "outDir": "${configDir}/dist",
- "sourceMap": true,
- "declaration": true,
- "lib": ["esnext", "dom", "dom.iterable"]
+
+ // Some stricter flags (disabled by default)
+ "noUnusedLocals": false,
+ "noUnusedParameters": false,
+ "noPropertyAccessFromIndexSignature": false
}
}