From e4c6b755ce2c5562e6e75939bfc4c03c8a0fe387 Mon Sep 17 00:00:00 2001 From: Matt Fysh Date: Wed, 3 Sep 2025 16:39:52 +1000 Subject: [PATCH 1/3] allow context modifiers to work in macros --- packages/get/package.json | 1 - packages/get/src/calls.ts | 98 ++++++++++ packages/get/src/execute.ts | 122 ++++++------ packages/get/src/hooks.spec.ts | 4 +- packages/get/src/index.ts | 21 +- packages/get/src/modifiers.ts | 41 ---- packages/get/src/modules.ts | 185 ------------------ packages/get/src/registry.ts | 158 +++++++++++++++ packages/get/src/value.ts | 8 +- packages/lib/package.json | 11 +- .../{utils/src => lib/src/core}/errors.ts | 17 +- packages/lib/src/core/hooks.ts | 70 +++++++ packages/lib/src/index.ts | 12 +- packages/lib/src/net/http.ts | 4 +- packages/lib/src/slice.ts | 5 + packages/lib/src/values/cookies.ts | 3 +- packages/lib/src/values/headers.ts | 2 +- packages/lib/src/values/html.ts | 20 +- packages/lib/src/values/js.ts | 11 +- packages/lib/src/values/json.ts | 2 +- packages/parser/package.json | 2 +- packages/parser/src/grammar/lex/slice.ts | 4 +- packages/parser/src/grammar/parse.ts | 4 +- packages/parser/src/parse.ts | 4 +- packages/parser/src/passes/analyze.ts | 19 +- packages/parser/src/passes/desugar/context.ts | 4 +- packages/parser/src/passes/desugar/links.ts | 4 +- .../parser/src/passes/desugar/reqparse.ts | 4 +- .../parser/src/passes/desugar/slicedeps.ts | 4 +- .../parser/src/passes/inference/typeinfo.ts | 12 +- packages/parser/src/passes/lineage.ts | 10 +- packages/utils/CHANGELOG.md | 43 ---- packages/utils/package.json | 25 --- packages/utils/src/hooks.ts | 48 ----- packages/utils/src/index.ts | 20 -- packages/utils/tsconfig.json | 4 - packages/walker/package.json | 3 +- packages/walker/src/index.ts | 8 +- packages/walker/src/path.ts | 9 +- packages/walker/src/scope.ts | 9 +- packages/{utils => walker}/src/wait.ts | 2 +- test/calls.spec.ts | 2 +- test/helpers.ts | 6 +- test/modifiers.spec.ts | 46 ++++- test/modules.spec.ts | 2 +- test/package.json | 2 +- test/request.spec.ts | 2 +- test/slice.spec.ts | 2 +- test/values.spec.ts | 2 +- 49 files changed, 566 insertions(+), 535 deletions(-) create mode 100644 packages/get/src/calls.ts delete mode 100644 packages/get/src/modifiers.ts delete mode 100644 packages/get/src/modules.ts create mode 100644 packages/get/src/registry.ts rename packages/{utils/src => lib/src/core}/errors.ts (87%) create mode 100644 packages/lib/src/core/hooks.ts create mode 100644 packages/lib/src/slice.ts delete mode 100644 packages/utils/CHANGELOG.md delete mode 100644 packages/utils/package.json delete mode 100644 packages/utils/src/hooks.ts delete mode 100644 packages/utils/src/index.ts delete mode 100644 packages/utils/tsconfig.json rename packages/{utils => walker}/src/wait.ts (93%) diff --git a/packages/get/package.json b/packages/get/package.json index 86a5251..89d2c9a 100644 --- a/packages/get/package.json +++ b/packages/get/package.json @@ -20,7 +20,6 @@ "@getlang/ast": "workspace:^0.0.1", "@getlang/lib": "workspace:^0.1.5", "@getlang/parser": "workspace:^0.3.4", - "@getlang/utils": "workspace:^0.1.6", "@getlang/walker": "workspace:^0.0.1", "lodash-es": "^4.17.21" }, diff --git a/packages/get/src/calls.ts b/packages/get/src/calls.ts new file mode 100644 index 0000000..b440885 --- /dev/null +++ b/packages/get/src/calls.ts @@ -0,0 +1,98 @@ +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 { partition } from 'lodash-es' +import type { Entry, Registry } from './registry.js' +import type { RuntimeValue } from './value.js' +import { materialize } from './value.js' + +export async function callModifier( + registry: Registry, + mod: string, + args: Record, + context?: RuntimeValue, +) { + const entry = await registry.importMod(mod) + if (entry) { + return entry.mod(context?.data, args) + } + + invariant(context, 'Modifier requires context') + + if (mod === 'link') { + invariant(typeof args.base === 'string', '@link requires base url') + const data = html.findLink(context.data) + const link = materialize({ data, typeInfo: context.typeInfo }) + return new URL(link, args.base).toString() + } + + const doc = materialize(context) + + switch (mod) { + case 'html': + return html.parse(doc) + case 'js': + return js.parse(doc) + case 'json': + return json.parse(doc) + case 'cookies': + return cookies.parse(doc) + default: + throw new ValueReferenceError(`Unsupported modifier: ${mod}`) + } +} + +export type Execute = (entry: Entry, inputs: Inputs) => Promise + +export async function callModule( + registry: Registry, + execute: Execute, + hooks: Required, + module: string, + args: RuntimeValue, + contextType?: TypeInfo, +) { + let entry: Entry + try { + entry = await registry.import(module, [], contextType) + } catch (e) { + const err = `Failed to import module: ${module}` + throw new ImportError(err, { cause: e }) + } + const [inputArgs, attrArgs] = partition(Object.entries(args.data), e => + entry.inputs.has(e[0]), + ) + const inputs = Object.fromEntries(inputArgs) + let extracted = await hooks.call(module, inputs) + if (typeof extracted === 'undefined') { + extracted = await execute(entry, inputs) + } + await hooks.extract(module, inputs, extracted.data) + + function dropWarning(reason: string) { + if (attrArgs.length) { + const dropped = attrArgs.map(e => e[0]).join(', ') + const err = [ + `Module '${module}' ${reason}`, + `dropping view attributes: ${dropped}`, + ].join(', ') + console.warn(err) + } + } + + if (entry.returnType.type !== Type.Value) { + dropWarning('returned unmaterialized value') + return extracted + } + + if (typeof extracted !== 'object') { + dropWarning('returned a primitive') + return extracted + } + + const data = Object.fromEntries(attrArgs) + const raster = materialize({ data, typeInfo: args.typeInfo }) + return { ...raster, ...extracted } +} diff --git a/packages/get/src/execute.ts b/packages/get/src/execute.ts index 53901bc..3f2a420 100644 --- a/packages/get/src/execute.ts +++ b/packages/get/src/execute.ts @@ -1,14 +1,13 @@ import type { Expr, TypeInfo } from '@getlang/ast' import { isToken, Type } from '@getlang/ast' -import { cookies, headers, html, http, js, json } from '@getlang/lib' -import type { Hooks, Inputs } from '@getlang/utils' -import { invariant, NullSelection } from '@getlang/utils' -import * as errors from '@getlang/utils/errors' -import type { Path, ReduceVisitor } from '@getlang/walker' +import type { Hooks, Inputs } from '@getlang/lib' +import * as lib from '@getlang/lib' +import * as errors from '@getlang/lib/errors' +import type { ReduceVisitor } from '@getlang/walker' import { reduce, ScopeTracker } from '@getlang/walker' -import { callModifier } from './modifiers.js' -import type { Execute } from './modules.js' -import { Modules } from './modules.js' +import type { Execute } from './calls.js' +import { callModifier, callModule } from './calls.js' +import { Registry } from './registry.js' import type { RuntimeValue } from './value.js' import { assert, materialize } from './value.js' @@ -18,51 +17,46 @@ const { SliceError, UnknownInputsError, ValueTypeError, + ValueReferenceError, } = errors -class ExecutionTracker extends ScopeTracker { - override exit(value: RuntimeValue, path: Path) { - if ('typeInfo' in path.node) { - assert(value) - } - super.exit(value, path) - } -} - export async function execute( rootModule: string, rootInputs: Inputs, hooks: Required, ) { - const scope = new ExecutionTracker() + const scope = new ScopeTracker() const executeModule: Execute = async (entry, inputs) => { const provided = new Set(Object.keys(inputs)) const unknown = provided.difference(entry.inputs) - invariant(unknown.size === 0, new UnknownInputsError([...unknown])) + lib.invariant(unknown.size === 0, new UnknownInputsError([...unknown])) - async function withItemContext(expr: Expr): Promise { + async function withItemContext(expr: Expr): Promise { const ctx = scope.context if (ctx?.typeInfo.type !== Type.List) { - return reduce(expr, options) + const { data } = await reduce(expr, options) + return data } const list = [] for (const data of ctx.data) { scope.push({ data, typeInfo: ctx.typeInfo.of }) - const value = await withItemContext(expr) - list.push(value.data) + const item = await withItemContext(expr) + list.push(item) scope.pop() } - return { data: list, typeInfo: expr.typeInfo } + return list + } + + function lookup(id: string, typeInfo: TypeInfo) { + const value = scope.lookup(id) + lib.invariant(value, new ValueReferenceError(id)) + return { data: value.data, typeInfo } } let ex: RuntimeValue | undefined const visitor: ReduceVisitor = { - /** - * Statement nodes - */ - InputExpr(node) { const name = node.id.value let data = inputs[name] @@ -72,12 +66,16 @@ export async function execute( } else if (node.defaultValue) { data = node.defaultValue.data } else { - data = new NullSelection(`input:${name}`) + data = new lib.NullSelection(`input:${name}`) } } return { data, typeInfo: node.typeInfo } }, + AssignmentStmt(node) { + assert(node.value) + }, + LiteralExpr(node) { return { data: node.value, typeInfo: node.typeInfo } }, @@ -91,12 +89,9 @@ export async function execute( }, }, - /** - * Expression nodes - */ TemplateExpr(node, path) { const firstNull = node.elements.find( - el => 'data' in el && el.data instanceof NullSelection, + el => 'data' in el && el.data instanceof lib.NullSelection, ) if (firstNull) { const isRoot = path.parent?.node.kind !== 'TemplateExpr' @@ -114,7 +109,8 @@ export async function execute( const ctx = scope.context const deps = ctx && materialize(ctx) const ret = await hooks.slice(slice.value, deps) - const data = ret === undefined ? new NullSelection('') : ret + const data = + ret === undefined ? new lib.NullSelection('') : ret return { data, typeInfo } } catch (e) { throw new SliceError({ cause: e }) @@ -122,19 +118,18 @@ export async function execute( }, IdentifierExpr(node) { - return scope.lookup(node.id.value) + return lookup(node.id.value, node.typeInfo) }, DrillIdentifierExpr(node) { - const { data } = scope.lookup(node.id.value) - return { data, typeInfo: node.typeInfo } + return lookup(node.id.value, node.typeInfo) }, SelectorExpr(node) { - invariant(scope.context, 'Unresolved context') + lib.invariant(scope.context, 'Unresolved context') const selector = node.selector.data - invariant( + lib.invariant( typeof selector === 'string', new ValueTypeError('Expected selector string'), ) @@ -146,15 +141,15 @@ export async function execute( case Type.Maybe: return select(typeInfo.option) case Type.Html: - return html.select(...args) + return lib.html.select(...args) case Type.Js: - return js.select(...args) + return lib.js.select(...args) case Type.Headers: - return headers.select(...args) + return lib.headers.select(...args) case Type.Cookies: - return cookies.select(...args) + return lib.cookies.select(...args) default: - return json.select(...args) + return lib.json.select(...args) } } @@ -163,18 +158,21 @@ export async function execute( }, async ModifierExpr(node) { - const mod = node.modifier.value - const args = node.args.data - const entry = await modules.importMod(mod) - const data = entry - ? entry.mod(scope.context?.data, args) - : callModifier(mod, args, scope.context) + const data = await callModifier( + registry, + node.modifier.value, + node.args.data, + scope.context, + ) return { data, typeInfo: node.typeInfo } }, ModuleExpr(node) { if (node.call) { - return modules.call( + return callModule( + registry, + executeModule, + hooks, node.module.value, node.args, scope.context?.typeInfo, @@ -187,6 +185,7 @@ export async function execute( }, ObjectEntryExpr(node) { + assert(node.value) const data = [node.key.data, node.value.data] return { data, typeInfo: { type: Type.Value } } }, @@ -195,24 +194,23 @@ export async function execute( const data = Object.fromEntries( node.entries .map(e => e.data) - .filter(e => !(e[1] instanceof NullSelection)), + .filter(e => !(e[1] instanceof lib.NullSelection)), ) return { data, typeInfo: node.typeInfo } }, SubqueryExpr() { const ex = scope.extracted - invariant(ex, new QuerySyntaxError('Subquery must extract a value')) + lib.invariant(ex, new QuerySyntaxError('Subquery must extract a value')) return ex }, DrillExpr: { async enter(node, path) { for (const expr of node.body) { - scope.context = await withItemContext(expr) - const optional = expr.typeInfo.type === Type.Maybe - if (optional && scope.context.data instanceof NullSelection) { - break + if (!(scope.context?.data instanceof lib.NullSelection)) { + const data = await withItemContext(expr) + scope.context = { data, typeInfo: expr.typeInfo } } } path.replace(scope.context) @@ -227,7 +225,7 @@ export async function execute( const headers = node.headers.data[1] const blocks = Object.fromEntries(node.blocks.map(v => v.data)) - const data = await http.request( + const data = await lib.http.request( method, url, headers, @@ -242,7 +240,7 @@ export async function execute( const value = Object.fromEntries( node.entries .map(e => e.data) - .filter(e => !(e[1] instanceof NullSelection)), + .filter(e => !(e[1] instanceof lib.NullSelection)), ) const data = [node.name.value, value] return { data, typeInfo: node.typeInfo } @@ -259,8 +257,8 @@ export async function execute( return ex } - const modules = new Modules(hooks, executeModule) - const rootEntry = await modules.import(rootModule) + const registry = new Registry(hooks) + const rootEntry = await registry.import(rootModule) const ex = await executeModule(rootEntry, rootInputs) - return ex && materialize(ex) + return ex && assert(ex) && materialize(ex) } diff --git a/packages/get/src/hooks.spec.ts b/packages/get/src/hooks.spec.ts index 153e379..36c41f4 100644 --- a/packages/get/src/hooks.spec.ts +++ b/packages/get/src/hooks.spec.ts @@ -6,8 +6,8 @@ import type { ImportHook, RequestHook, SliceHook, -} from '@getlang/utils' -import { invariant } from '@getlang/utils' +} from '@getlang/lib' +import { invariant } from '@getlang/lib' import { execute } from './index.js' describe('hook', () => { diff --git a/packages/get/src/index.ts b/packages/get/src/index.ts index f11d056..24fc2ad 100644 --- a/packages/get/src/index.ts +++ b/packages/get/src/index.ts @@ -1,24 +1,7 @@ -import { http, slice } from '@getlang/lib' -import type { Hooks, Inputs } from '@getlang/utils' -import { invariant } from '@getlang/utils' -import { ImportError } from '@getlang/utils/errors' +import type { Hooks, Inputs } from '@getlang/lib' +import { buildHooks } from '@getlang/lib' import { execute as exec } from './execute.js' -function buildHooks(hooks: Hooks): Required { - return { - import: (module: string) => { - const err = 'Imports are not supported by the current runtime' - invariant(hooks.import, new ImportError(err)) - return hooks.import(module) - }, - modifier: modifier => hooks.modifier?.(modifier), - call: hooks.call ?? (() => {}), - request: hooks.request ?? http.requestHook, - slice: hooks.slice ?? slice.runSlice, - extract: hooks.extract ?? (() => {}), - } -} - export function execute( source: string, inputs: Inputs = {}, diff --git a/packages/get/src/modifiers.ts b/packages/get/src/modifiers.ts deleted file mode 100644 index edf3a09..0000000 --- a/packages/get/src/modifiers.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { cookies, html, js, json } from '@getlang/lib' -import { invariant } from '@getlang/utils' -import { ValueReferenceError } from '@getlang/utils/errors' -import type { RuntimeValue } from './value.js' -import { materialize } from './value.js' - -export function callModifier( - mod: string, - args: Record, - context?: RuntimeValue, -) { - let ctx = context - if (context && mod === 'link') { - let { data, typeInfo } = context - const tag = data.type === 'tag' ? data.name : undefined - if (tag === 'a') { - data = html.select(data, 'xpath:@href', false) - } else if (tag === 'img') { - data = html.select(data, 'xpath:@src', false) - } - ctx = { data, typeInfo } - } - - const doc = ctx && materialize(ctx) - - switch (mod) { - case 'link': - invariant(typeof args.base === 'string', '@link requires base url') - return new URL(doc, args.base).toString() - case 'html': - return html.parse(doc) - case 'js': - return js.parse(doc) - case 'json': - return json.parse(doc) - case 'cookies': - return cookies.parse(doc) - default: - throw new ValueReferenceError(`Unsupported modifier: ${mod}`) - } -} diff --git a/packages/get/src/modules.ts b/packages/get/src/modules.ts deleted file mode 100644 index 04c7372..0000000 --- a/packages/get/src/modules.ts +++ /dev/null @@ -1,185 +0,0 @@ -import type { Program, TypeInfo } from '@getlang/ast' -import { Type } from '@getlang/ast' -import { analyze, desugar, inference, parse } from '@getlang/parser' -import type { Hooks, Inputs, Modifier } from '@getlang/utils' -import { - ImportError, - RecursiveCallError, - ValueTypeError, -} from '@getlang/utils/errors' -import { partition } from 'lodash-es' -import type { RuntimeValue } from './value.js' -import { materialize } from './value.js' - -type Info = { - ast: Program - imports: Set - isMacro: boolean -} - -type Entry = { - program: Program - inputs: Set - returnType: TypeInfo -} - -type ModEntry = { - mod: Modifier - returnType: TypeInfo -} - -export type Execute = (entry: Entry, inputs: Inputs) => Promise - -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) { - key += `<${repr(typeInfo)}>` - } - return key -} - -export class Modules { - private info: Record> = {} - private entries: Record> = {} - private modifiers: Record> = {} - - constructor( - private hooks: Required, - private execute: Execute, - ) {} - - async load(module: string): Promise { - const source = await this.hooks.import(module) - const ast = parse(source) - const info = analyze(ast) - return { ast, ...info } - } - - async getInfo(module: string) { - this.info[module] ??= this.load(module) - return this.info[module] - } - - async compile( - module: string, - stack: string[], - contextType?: TypeInfo, - ): Promise { - const { ast, imports } = await this.getInfo(module) - const macros: string[] = [] - for (const i of imports) { - const depInfo = await this.getInfo(i) - if (depInfo.isMacro) { - macros.push(i) - } - } - const simplified = desugar(ast, macros) - const { inputs, calls, modifiers } = analyze(simplified) - - const returnTypes: Record = {} - for (const call of calls) { - const { returnType } = await this.import(call, stack) - returnTypes[call] = returnType - } - for (const mod of modifiers) { - const entry = await this.importMod(mod) - if (entry) { - returnTypes[mod] = entry.returnType - } - } - - const { program, returnType } = inference(simplified, { - returnTypes, - contextType, - }) - - return { program, inputs, returnType } - } - - import(module: string, prev: string[] = [], contextType?: TypeInfo) { - const stack = [...prev, module] - if (prev.includes(module)) { - throw new RecursiveCallError(stack) - } - const key = buildImportKey(module, contextType) - this.entries[key] ??= this.compile(module, stack, contextType) - return this.entries[key] - } - - async compileMod(mod: string): Promise { - const compiled = await this.hooks.modifier(mod) - if (!compiled) { - return null - } - return { mod: compiled.modifier, returnType: { type: Type.Value } } - } - - importMod(mod: string) { - this.modifiers[mod] ??= this.compileMod(mod) - return this.modifiers[mod] - } - - async call(module: string, args: RuntimeValue, contextType?: TypeInfo) { - let entry: Entry - try { - entry = await this.import(module, [], contextType) - } catch (e) { - const err = `Failed to import module: ${module}` - throw new ImportError(err, { cause: e }) - } - const [inputArgs, attrArgs] = partition(Object.entries(args.data), e => - entry.inputs.has(e[0]), - ) - const inputs = Object.fromEntries(inputArgs) - let extracted = await this.hooks.call(module, inputs) - if (typeof extracted === 'undefined') { - extracted = await this.execute(entry, inputs) - } - await this.hooks.extract(module, inputs, extracted.data) - - function dropWarning(reason: string) { - if (attrArgs.length) { - const dropped = attrArgs.map(e => e[0]).join(', ') - const err = [ - `Module '${module}' ${reason}`, - `dropping view attributes: ${dropped}`, - ].join(', ') - console.warn(err) - } - } - - if (entry.returnType.type !== Type.Value) { - dropWarning(`returned ${repr(entry.returnType)}`) - return extracted - } - - if (typeof extracted !== 'object') { - dropWarning('returned a primitive') - return extracted - } - - const data = Object.fromEntries(attrArgs) - const raster = materialize({ data, typeInfo: args.typeInfo }) - return { ...raster, ...extracted } - } -} diff --git a/packages/get/src/registry.ts b/packages/get/src/registry.ts new file mode 100644 index 0000000..dae0cdc --- /dev/null +++ b/packages/get/src/registry.ts @@ -0,0 +1,158 @@ +import type { Program, TypeInfo } from '@getlang/ast' +import { Type } from '@getlang/ast' +import type { Hooks, Modifier } from '@getlang/lib' +import { RecursiveCallError, ValueTypeError } from '@getlang/lib/errors' +import { analyze, desugar, inference, parse } from '@getlang/parser' +import type { Pattern } from 'acorn' +import { parse as acorn } from 'acorn' +import { traverse } from 'estree-toolkit' + +type ModEntry = { + mod: Modifier + useContext: boolean + returnType: TypeInfo +} + +type Info = { + ast: Program + imports: Set + isMacro: boolean +} + +export type Entry = { + program: Program + inputs: Set + 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) { + key += `<${repr(typeInfo)}>` + } + return key +} + +function inferContext(mod: Modifier) { + const src = mod.toString() + const ast = acorn(src, { ecmaVersion: 'latest' }) + let useContext = false + traverse(ast, { + $: { scope: true }, + Program(path) { + const fn = ast.body[0] + let ctxParam: Pattern | undefined + if (fn?.type === 'FunctionDeclaration') { + ctxParam = fn.params[0] + } else if (fn?.type === 'ExpressionStatement') { + if (fn.expression.type === 'ArrowFunctionExpression') { + ctxParam = fn.expression.params[0] + } + } + const fnScope = path.scope?.children[0] + const bindings = Object.values(fnScope?.bindings || {}) + const ctxBinding = bindings.find(b => b?.identifierPath.node === ctxParam) + useContext = Boolean(ctxBinding?.references.length) + }, + }) + return useContext +} + +export class Registry { + private info: Record> = {} + private entries: Record> = {} + private modifiers: Record> = {} + + constructor(private hooks: Required) {} + + importMod(mod: string) { + this.modifiers[mod] ??= Promise.resolve().then(async () => { + const compiled = await this.hooks.modifier(mod) + if (!compiled) { + return null + } + const fn = compiled.modifier + const useContext = inferContext(fn) + const returnType = compiled.typeInfo || { type: Type.Value } + return { mod: fn, useContext, returnType } + }) + return this.modifiers[mod] + } + + private getInfo(module: string) { + this.info[module] ??= Promise.resolve().then(async () => { + const source = await this.hooks.import(module) + const ast = parse(source) + const { imports, ...info } = analyze(ast) + let isMacro = info.hasUnboundSelector + for (const [mod, unbound] of info.modifiers) { + if (unbound && !isMacro) { + const entry = await this.importMod(mod) + isMacro = entry?.useContext || false + } + } + return { ast, imports, isMacro } + }) + return this.info[module] + } + + import(module: string, prev: string[] = [], contextType?: TypeInfo) { + const stack = [...prev, module] + if (prev.includes(module)) { + throw new RecursiveCallError(stack) + } + const key = buildImportKey(module, contextType) + this.entries[key] ??= Promise.resolve().then(async () => { + const { ast, imports } = await this.getInfo(module) + const macros: string[] = [] + for (const i of imports) { + const depInfo = await this.getInfo(i) + if (depInfo.isMacro) { + macros.push(i) + } + } + const simplified = desugar(ast, macros) + const { inputs, calls, modifiers } = analyze(simplified) + + const returnTypes: Record = {} + for (const call of calls) { + const { returnType } = await this.import(call, stack) + returnTypes[call] = returnType + } + for (const mod of modifiers.keys()) { + const entry = await this.importMod(mod) + if (entry) { + returnTypes[mod] = entry.returnType + } + } + + const { program, returnType } = inference(simplified, { + returnTypes, + contextType, + }) + + return { program, inputs, returnType } + }) + return this.entries[key] + } +} diff --git a/packages/get/src/value.ts b/packages/get/src/value.ts index 4556b05..656bf49 100644 --- a/packages/get/src/value.ts +++ b/packages/get/src/value.ts @@ -1,9 +1,11 @@ import type { TypeInfo } from '@getlang/ast' import { Type } from '@getlang/ast' -import { cookies, headers, html, js } from '@getlang/lib' -import { NullSelection } from '@getlang/utils' -import { NullSelectionError, ValueTypeError } from '@getlang/utils/errors' +import { cookies, headers, html, js, NullSelection } from '@getlang/lib' import { mapValues } from 'lodash-es' +import { + NullSelectionError, + ValueTypeError, +} from '../../lib/src/core/errors.js' export type RuntimeValue = { data: any diff --git a/packages/lib/package.json b/packages/lib/package.json index 17b6981..28ef8bf 100644 --- a/packages/lib/package.json +++ b/packages/lib/package.json @@ -4,8 +4,14 @@ "license": "Apache-2.0", "type": "module", "exports": { - "bun": "./src/index.ts", - "default": "./dist/index.js" + ".": { + "bun": "./src/index.ts", + "default": "./dist/index.js" + }, + "./errors": { + "bun": "./src/core/errors.ts", + "default": "./dist/core/errors.js" + } }, "bugs": { "url": "https://github.com/getlang-dev/get/issues" @@ -17,7 +23,6 @@ }, "homepage": "https://getlang.dev", "dependencies": { - "@getlang/utils": "workspace:^0.1.5", "@getlang/xpath": "0.0.35-0", "@types/esquery": "^1.5.4", "@types/lodash-es": "^4.17.12", diff --git a/packages/utils/src/errors.ts b/packages/lib/src/core/errors.ts similarity index 87% rename from packages/utils/src/errors.ts rename to packages/lib/src/core/errors.ts index 6ca609e..88a86e8 100644 --- a/packages/utils/src/errors.ts +++ b/packages/lib/src/core/errors.ts @@ -73,9 +73,9 @@ export class NullInputError extends RuntimeError { } export class UnknownInputsError extends RuntimeError { - public override name = 'UnknownInputError' + public override name = 'UnknownInputsError' - constructor(inputNames: string[], options?: ErrorOptions) { + constructor(inputNames: string[] = [], options?: ErrorOptions) { const noun = inputNames.length > 1 ? 'inputs' : 'input' super(`Unknown ${noun} provided: ${inputNames.join(', ')}`, options) } @@ -99,3 +99,16 @@ export class RecursiveCallError extends RuntimeError { super(`Recursive call error: ${chain.join(' -> ')}`, options) } } + +export function invariant( + condition: unknown, + err: string | RuntimeError, +): asserts condition { + if (!condition) { + throw typeof err === 'string' ? new FatalError({ cause: err }) : err + } +} + +export class NullSelection { + constructor(public selector: string) {} +} diff --git a/packages/lib/src/core/hooks.ts b/packages/lib/src/core/hooks.ts new file mode 100644 index 0000000..ae37d96 --- /dev/null +++ b/packages/lib/src/core/hooks.ts @@ -0,0 +1,70 @@ +import type { TypeInfo } from '@getlang/ast' +import type { Inputs, MaybePromise } from '../index.js' +import { requestHook } from '../net/http.js' +import { runSlice } from '../slice.js' +import { ImportError, invariant } from './errors.js' + +export type ImportHook = (module: string) => MaybePromise + +export type CallHook = (module: string, inputs: Inputs) => MaybePromise + +export type RequestHook = ( + url: string, + opts: RequestInit, +) => MaybePromise + +export type SliceHook = ( + slice: string, + context?: unknown, +) => MaybePromise + +export type ExtractHook = ( + module: string, + inputs: Inputs, + value: any, +) => MaybePromise + +export type Modifier = (context: any, options: Record) => any +export type ModifierHook = (modifier: string) => MaybePromise< + | { + modifier: Modifier + typeInfo?: TypeInfo + } + | undefined +> + +export type Hooks = Partial<{ + import: ImportHook + request: RequestHook + slice: SliceHook + call: CallHook + extract: ExtractHook + modifier: ModifierHook +}> + +type RequestInit = { + method?: string + headers?: Headers + body?: string +} + +export type Response = { + status: number + headers: Headers + body?: string +} + +export function buildHooks(hooks: Hooks): Required { + return { + import: (module: string) => { + const err = 'Imports are not supported by the current runtime' + invariant(hooks.import, new ImportError(err)) + return hooks.import(module) + }, + modifier: modifier => hooks.modifier?.(modifier), + call: hooks.call ?? (() => {}), + request: hooks.request ?? requestHook, + slice: hooks.slice ?? runSlice, + extract: hooks.extract ?? (() => {}), + } +} diff --git a/packages/lib/src/index.ts b/packages/lib/src/index.ts index 4ef2db5..5d81bd4 100644 --- a/packages/lib/src/index.ts +++ b/packages/lib/src/index.ts @@ -1,14 +1,12 @@ +export { invariant, NullSelection } from './core/errors.js' +export * from './core/hooks.js' export * as http from './net/http.js' +export * as slice from './slice.js' export * as cookies from './values/cookies.js' export * as headers from './values/headers.js' export * as html from './values/html.js' export * as js from './values/js.js' export * as json from './values/json.js' -const AsyncFunction: any = (async () => {}).constructor - -function runSlice(slice: string, context: unknown = {}) { - return new AsyncFunction('$', slice)(context) -} - -export const slice = { runSlice } +export type Inputs = Record +export type MaybePromise = T | Promise diff --git a/packages/lib/src/net/http.ts b/packages/lib/src/net/http.ts index 21c0020..67a1443 100644 --- a/packages/lib/src/net/http.ts +++ b/packages/lib/src/net/http.ts @@ -1,5 +1,5 @@ -import type { RequestHook } from '@getlang/utils' -import { RequestError } from '@getlang/utils/errors' +import { RequestError } from '../core/errors.js' +import type { RequestHook } from '../core/hooks.js' type StringMap = Record diff --git a/packages/lib/src/slice.ts b/packages/lib/src/slice.ts new file mode 100644 index 0000000..911217c --- /dev/null +++ b/packages/lib/src/slice.ts @@ -0,0 +1,5 @@ +const AsyncFunction: any = (async () => {}).constructor + +export function runSlice(slice: string, context: unknown = {}) { + return new AsyncFunction('$', slice)(context) +} diff --git a/packages/lib/src/values/cookies.ts b/packages/lib/src/values/cookies.ts index 92cd4bf..d89795d 100644 --- a/packages/lib/src/values/cookies.ts +++ b/packages/lib/src/values/cookies.ts @@ -1,7 +1,6 @@ -import { invariant, NullSelection } from '@getlang/utils' -import { QuerySyntaxError } from '@getlang/utils/errors' import { mapValues } from 'lodash-es' import * as scp from 'set-cookie-parser' +import { invariant, NullSelection, QuerySyntaxError } from '../core/errors.js' export const parse = (source: string) => { const cookie = scp.splitCookiesString(source) diff --git a/packages/lib/src/values/headers.ts b/packages/lib/src/values/headers.ts index 24a4d63..7d1bb30 100644 --- a/packages/lib/src/values/headers.ts +++ b/packages/lib/src/values/headers.ts @@ -1,4 +1,4 @@ -import { NullSelection } from '@getlang/utils' +import { NullSelection } from '../core/errors.js' export const select = (headers: Headers, selector: string, expand: boolean) => { if (expand && selector === 'set-cookie') { diff --git a/packages/lib/src/values/html.ts b/packages/lib/src/values/html.ts index 487aa21..02e3c2a 100644 --- a/packages/lib/src/values/html.ts +++ b/packages/lib/src/values/html.ts @@ -1,7 +1,5 @@ /// -import { invariant, NullSelection } from '@getlang/utils' -import { NullSelectionError, SelectorSyntaxError } from '@getlang/utils/errors' import xpath from '@getlang/xpath' import { selectAll, selectOne } from 'css-select' import { parse as parseCss } from 'css-what' @@ -9,6 +7,12 @@ import type { AnyHtmlNode } from 'domhandler' import { textContent } from 'domutils' import { parse as parse5 } from 'parse5' import { adapter } from 'parse5-htmlparser2-tree-adapter' +import { + invariant, + NullSelection, + NullSelectionError, + SelectorSyntaxError, +} from '../core/errors.js' import './html/patch-dom.js' export { Element } from 'domhandler' @@ -68,3 +72,15 @@ export const toValue = (el: AnyHtmlNode) => { } return str.trim() } + +export const findLink = (el: AnyHtmlNode) => { + const tag = el.type === 'tag' && el.name + switch (tag) { + case 'a': + return select(el, 'xpath:@href', false) + case 'img': + return select(el, 'xpath:@src', false) + default: + return el + } +} diff --git a/packages/lib/src/values/js.ts b/packages/lib/src/values/js.ts index bb76c9b..7a69fc1 100644 --- a/packages/lib/src/values/js.ts +++ b/packages/lib/src/values/js.ts @@ -1,12 +1,13 @@ -import { invariant, NullSelection } from '@getlang/utils' +import type { AnyNode } from 'acorn' +import { parse as acorn } from 'acorn' +import esquery from 'esquery' import { ConversionError, + invariant, + NullSelection, SelectorSyntaxError, SliceSyntaxError, -} from '@getlang/utils/errors' -import type { AnyNode } from 'acorn' -import { parse as acorn } from 'acorn' -import esquery from 'esquery' +} from '../core/errors.js' export const parse = (js: string): AnyNode => { try { diff --git a/packages/lib/src/values/json.ts b/packages/lib/src/values/json.ts index 39ac010..ad01ae1 100644 --- a/packages/lib/src/values/json.ts +++ b/packages/lib/src/values/json.ts @@ -1,5 +1,5 @@ -import { NullSelection } from '@getlang/utils' import { get } from 'lodash-es' +import { NullSelection } from '../core/errors.js' export const parse = (json: string) => JSON.parse(json) diff --git a/packages/parser/package.json b/packages/parser/package.json index 49b91db..14bca1b 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "@getlang/ast": "workspace:^0.0.1", - "@getlang/utils": "workspace:^0.1.6", + "@getlang/lib": "workspace:^0.1.5", "@getlang/walker": "workspace:^0.0.1", "@types/moo": "^0.5.10", "@types/nearley": "^2.11.5", diff --git a/packages/parser/src/grammar/lex/slice.ts b/packages/parser/src/grammar/lex/slice.ts index 47d8780..88e2d01 100644 --- a/packages/parser/src/grammar/lex/slice.ts +++ b/packages/parser/src/grammar/lex/slice.ts @@ -1,5 +1,5 @@ -import { invariant } from '@getlang/utils' -import { QuerySyntaxError } from '@getlang/utils/errors' +import { invariant } from '@getlang/lib' +import { QuerySyntaxError } from '@getlang/lib/errors' import { until } from './templates.js' const getSliceValue = (text: string) => { diff --git a/packages/parser/src/grammar/parse.ts b/packages/parser/src/grammar/parse.ts index 81e1241..286f343 100644 --- a/packages/parser/src/grammar/parse.ts +++ b/packages/parser/src/grammar/parse.ts @@ -1,7 +1,7 @@ import type { Expr } from '@getlang/ast' import { isToken, t } from '@getlang/ast' -import { invariant } from '@getlang/utils' -import { QuerySyntaxError } from '@getlang/utils/errors' +import { invariant } from '@getlang/lib' +import { QuerySyntaxError } from '@getlang/lib/errors' import { tx } from '../utils.js' type PP = nearley.Postprocessor diff --git a/packages/parser/src/parse.ts b/packages/parser/src/parse.ts index 9998649..e8b7abf 100644 --- a/packages/parser/src/parse.ts +++ b/packages/parser/src/parse.ts @@ -1,6 +1,6 @@ import type { Program } from '@getlang/ast' -import { invariant } from '@getlang/utils' -import { QuerySyntaxError } from '@getlang/utils/errors' +import { invariant } from '@getlang/lib' +import { QuerySyntaxError } from '@getlang/lib/errors' import nearley from 'nearley' import lexer from './grammar/lexer.js' import grammar from './grammar.js' diff --git a/packages/parser/src/passes/analyze.ts b/packages/parser/src/passes/analyze.ts index 3ed9d6e..0e2bd1a 100644 --- a/packages/parser/src/passes/analyze.ts +++ b/packages/parser/src/passes/analyze.ts @@ -5,9 +5,9 @@ export function analyze(ast: Program) { const scope = new ScopeTracker() const inputs = new Set() const calls = new Set() - const modifiers = new Set() + const modifiers = new Map() const imports = new Set() - let isMacro = false + let hasUnboundSelector = false transform(ast, { scope, @@ -19,13 +19,20 @@ export function analyze(ast: Program) { node.call && calls.add(node.module.value) }, SelectorExpr() { - isMacro ||= !scope.context + hasUnboundSelector ||= !scope.context }, ModifierExpr(node) { - isMacro ||= !scope.context - modifiers.add(node.modifier.value) + const mod = node.modifier.value + const unbound = modifiers.get(mod) || !scope.context + modifiers.set(mod, unbound) }, }) - return { inputs, imports, calls, modifiers, isMacro } + return { + inputs, + imports, + calls, + modifiers, + hasUnboundSelector, + } } diff --git a/packages/parser/src/passes/desugar/context.ts b/packages/parser/src/passes/desugar/context.ts index 529282a..b45bbab 100644 --- a/packages/parser/src/passes/desugar/context.ts +++ b/packages/parser/src/passes/desugar/context.ts @@ -1,5 +1,5 @@ -import { invariant } from '@getlang/utils' -import { QuerySyntaxError } from '@getlang/utils/errors' +import { invariant } from '@getlang/lib' +import { QuerySyntaxError } from '@getlang/lib/errors' import { ScopeTracker, transform } from '@getlang/walker' import type { DesugarPass } from '../desugar.js' diff --git a/packages/parser/src/passes/desugar/links.ts b/packages/parser/src/passes/desugar/links.ts index 1bd5da9..b273864 100644 --- a/packages/parser/src/passes/desugar/links.ts +++ b/packages/parser/src/passes/desugar/links.ts @@ -1,6 +1,6 @@ import { t } from '@getlang/ast' -import { invariant } from '@getlang/utils' -import { QuerySyntaxError } from '@getlang/utils/errors' +import { invariant } from '@getlang/lib' +import { QuerySyntaxError } from '@getlang/lib/errors' import { transform } from '@getlang/walker' import { render, tx } from '../../utils.js' import type { DesugarPass } from '../desugar.js' diff --git a/packages/parser/src/passes/desugar/reqparse.ts b/packages/parser/src/passes/desugar/reqparse.ts index 88ffff3..3a6c793 100644 --- a/packages/parser/src/passes/desugar/reqparse.ts +++ b/packages/parser/src/passes/desugar/reqparse.ts @@ -1,7 +1,7 @@ import type { RequestExpr, Stmt } from '@getlang/ast' import { t } from '@getlang/ast' -import { invariant } from '@getlang/utils' -import { QuerySyntaxError } from '@getlang/utils/errors' +import { invariant } from '@getlang/lib' +import { QuerySyntaxError } from '@getlang/lib/errors' import { getContentField, tx } from '../../utils.js' type Parsers = Record diff --git a/packages/parser/src/passes/desugar/slicedeps.ts b/packages/parser/src/passes/desugar/slicedeps.ts index f3beb10..a9307f7 100644 --- a/packages/parser/src/passes/desugar/slicedeps.ts +++ b/packages/parser/src/passes/desugar/slicedeps.ts @@ -1,7 +1,7 @@ import type { Expr } from '@getlang/ast' import { t } from '@getlang/ast' -import { invariant } from '@getlang/utils' -import { SliceSyntaxError } from '@getlang/utils/errors' +import { invariant } from '@getlang/lib' +import { SliceSyntaxError } from '@getlang/lib/errors' import { ScopeTracker, transform } from '@getlang/walker' import { parse as acorn } from 'acorn' import { traverse } from 'estree-toolkit' diff --git a/packages/parser/src/passes/inference/typeinfo.ts b/packages/parser/src/passes/inference/typeinfo.ts index 4676980..9d5baf0 100644 --- a/packages/parser/src/passes/inference/typeinfo.ts +++ b/packages/parser/src/passes/inference/typeinfo.ts @@ -1,7 +1,7 @@ import type { Expr, Node, Program, TypeInfo } from '@getlang/ast' import { Type, t } from '@getlang/ast' -import { invariant } from '@getlang/utils' -import { QuerySyntaxError } from '@getlang/utils/errors' +import { invariant } from '@getlang/lib' +import { QuerySyntaxError, ValueReferenceError } from '@getlang/lib/errors' import type { Path, TransformVisitor } from '@getlang/walker' import { ScopeTracker, transform } from '@getlang/walker' import { toPath } from 'lodash-es' @@ -128,13 +128,17 @@ export function resolveTypes(ast: Program, options: ResolveTypeOptions) { }, IdentifierExpr(node) { - const value = scope.lookup(node.id.value) + const id = node.id.value + const value = scope.lookup(id) + invariant(value, new ValueReferenceError(id)) const typeInfo = structuredClone(value.typeInfo) return { ...node, typeInfo } }, DrillIdentifierExpr(node) { - const value = scope.lookup(node.id.value) + const id = node.id.value + const value = scope.lookup(id) + invariant(value, new ValueReferenceError(id)) let typeInfo = structuredClone(value.typeInfo) if (node.expand) { typeInfo = { type: Type.List, of: typeInfo } diff --git a/packages/parser/src/passes/lineage.ts b/packages/parser/src/passes/lineage.ts index 72497c2..9f5cc0e 100644 --- a/packages/parser/src/passes/lineage.ts +++ b/packages/parser/src/passes/lineage.ts @@ -1,4 +1,6 @@ import type { Expr, Node } from '@getlang/ast' +import { invariant } from '@getlang/lib' +import { ValueReferenceError } from '@getlang/lib/errors' import type { Path } from '@getlang/walker' import { ScopeTracker } from '@getlang/walker' @@ -22,9 +24,13 @@ export class LineageTracker extends ScopeTracker { switch (node.kind) { case 'IdentifierExpr': - case 'DrillIdentifierExpr': - derive(this.lookup(node.id.value)) + case 'DrillIdentifierExpr': { + const id = node.id.value + const value = this.lookup(id) + invariant(value, new ValueReferenceError(id)) + derive(value) break + } case 'DrillExpr': derive(node.body.at(-1)!) diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md deleted file mode 100644 index 9bc4921..0000000 --- a/packages/utils/CHANGELOG.md +++ /dev/null @@ -1,43 +0,0 @@ -# @getlang/utils - -## 0.1.6 - -### Patch Changes - -- [#31](https://github.com/getlang-dev/get/pull/31) [`1a395f9`](https://github.com/getlang-dev/get/commit/1a395f9df71d3507bc5b3841eddc9336db3a69ee) Thanks [@mattfysh](https://github.com/mattfysh)! - request parsers - -## 0.1.5 - -### Patch Changes - -- [`aca9d92`](https://github.com/getlang-dev/get/commit/aca9d929e4877fc614b66740c9415f5bcd083c24) Thanks [@mattfysh](https://github.com/mattfysh)! - fix publish - -## 0.1.4 - -### Patch Changes - -- [`3660548`](https://github.com/getlang-dev/get/commit/3660548d79dd24e13a74bf0d6f24c1fec512062d) Thanks [@mattfysh](https://github.com/mattfysh)! - prevent tsconfig publish - -## 0.1.3 - -### Patch Changes - -- [#28](https://github.com/getlang-dev/get/pull/28) [`f1bdc2c`](https://github.com/getlang-dev/get/commit/f1bdc2c8433a942f84503606790e8bcf4fb37477) Thanks [@mattfysh](https://github.com/mattfysh)! - page links - -## 0.1.2 - -### Patch Changes - -- [#23](https://github.com/getlang-dev/get/pull/23) [`28d0ca8`](https://github.com/getlang-dev/get/commit/28d0ca8dcf840cfc70f002d06a48cace834edcf9) Thanks [@mattfysh](https://github.com/mattfysh)! - workspace layout updates - -## 0.1.1 - -### Patch Changes - -- [#14](https://github.com/getlang-dev/get/pull/14) [`58e9988`](https://github.com/getlang-dev/get/commit/58e99887e39956ee1e3eaf669cb92fbfa188a022) Thanks [@mattfysh](https://github.com/mattfysh)! - add contextual identifier to slices reference converted or raw context - -## 0.1.0 - -### Minor Changes - -- [`57ff46d`](https://github.com/getlang-dev/get/commit/57ff46d904484e3277ee7a8481cdf4cee4c3deb2) Thanks [@mattfysh](https://github.com/mattfysh)! - Release v0.1.0 diff --git a/packages/utils/package.json b/packages/utils/package.json deleted file mode 100644 index 5731fea..0000000 --- a/packages/utils/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@getlang/utils", - "version": "0.1.6", - "license": "Apache-2.0", - "type": "module", - "exports": { - ".": { - "bun": "./src/index.ts", - "default": "./dist/index.js" - }, - "./errors": { - "bun": "./src/errors.ts", - "default": "./dist/errors.js" - } - }, - "bugs": { - "url": "https://github.com/getlang-dev/get/issues" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/getlang-dev/get.git", - "directory": "packages/utils" - }, - "homepage": "https://getlang.dev" -} diff --git a/packages/utils/src/hooks.ts b/packages/utils/src/hooks.ts deleted file mode 100644 index 1a089f9..0000000 --- a/packages/utils/src/hooks.ts +++ /dev/null @@ -1,48 +0,0 @@ -import type { Inputs } from './index.js' -import type { MaybePromise } from './wait.js' - -export type ImportHook = (module: string) => MaybePromise - -export type CallHook = (module: string, inputs: Inputs) => MaybePromise - -export type RequestHook = ( - url: string, - opts: RequestInit, -) => MaybePromise - -export type SliceHook = ( - slice: string, - context?: unknown, -) => MaybePromise - -export type ExtractHook = ( - module: string, - inputs: Inputs, - value: any, -) => MaybePromise - -export type Modifier = (context: any, options: Record) => any -export type ModifierHook = ( - modifier: string, -) => MaybePromise<{ modifier: Modifier } | undefined> - -export type Hooks = Partial<{ - import: ImportHook - request: RequestHook - slice: SliceHook - call: CallHook - extract: ExtractHook - modifier: ModifierHook -}> - -type RequestInit = { - method?: string - headers?: Headers - body?: string -} - -export type Response = { - status: number - headers: Headers - body?: string -} diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts deleted file mode 100644 index 2e308ac..0000000 --- a/packages/utils/src/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { RuntimeError } from './errors.js' -import { FatalError } from './errors.js' - -export * from './hooks.js' -export * from './wait.js' - -export type Inputs = Record - -export class NullSelection { - constructor(public selector: string) {} -} - -export function invariant( - condition: unknown, - err: string | RuntimeError, -): asserts condition { - if (!condition) { - throw typeof err === 'string' ? new FatalError({ cause: err }) : err - } -} diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json deleted file mode 100644 index dafae0f..0000000 --- a/packages/utils/tsconfig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "include": ["src/index.ts", "src/errors.ts"] -} diff --git a/packages/walker/package.json b/packages/walker/package.json index d606acc..41f01bf 100644 --- a/packages/walker/package.json +++ b/packages/walker/package.json @@ -19,7 +19,6 @@ }, "homepage": "https://getlang.dev", "dependencies": { - "@getlang/ast": "workspace:^0.0.1", - "@getlang/utils": "workspace:^0.1.6" + "@getlang/ast": "workspace:^0.0.1" } } diff --git a/packages/walker/src/index.ts b/packages/walker/src/index.ts index 818de2c..049e019 100644 --- a/packages/walker/src/index.ts +++ b/packages/walker/src/index.ts @@ -1,5 +1,4 @@ import type { Node } from '@getlang/ast' -import { wait, waitMap } from '@getlang/utils' import { Path } from './path.js' import type { ScopeTracker } from './scope.js' import type { @@ -8,6 +7,7 @@ import type { ReduceVisitor, TransformVisitor, } from './visitor.js' +import { wait, waitMap } from './wait.js' export { ScopeTracker } from './scope.js' export type { TransformVisitor, ReduceVisitor, Path } @@ -50,8 +50,10 @@ function walk( const path = parent?.add(node) || new Path(node) return wait(enter(node, path), () => { - let xnode: any = path.replacement - if (!xnode) { + let xnode: any + if (path.replacement) { + xnode = path.replacement.value + } else { const entries = waitMap(Object.entries(node), e => { const [key, value] = e let val = value diff --git a/packages/walker/src/path.ts b/packages/walker/src/path.ts index 20384e9..43b7560 100644 --- a/packages/walker/src/path.ts +++ b/packages/walker/src/path.ts @@ -1,5 +1,4 @@ import type { Node } from '@getlang/ast' -import { invariant } from '@getlang/utils' type Staging = { before: Node[] @@ -10,7 +9,7 @@ type Mutation = Map export class Path { private staging: Staging = { before: [] } protected mutations: Mutation = new Map() - public replacement: unknown + public replacement?: { value: unknown } constructor( public node: N, @@ -26,7 +25,7 @@ export class Path { } replace(value: any) { - this.replacement = value + this.replacement = { value } } private mutate(node: Node) { @@ -53,7 +52,9 @@ export class Path { apply(node: Node) { const applied = this.mutate(node) if (this.staging.before.length) { - invariant(this.parent, 'Unable to apply path mutations') + if (!this.parent) { + throw new Error('Unable to apply path mutations') + } this.parent.mutations.set(applied, this.staging) } return applied diff --git a/packages/walker/src/scope.ts b/packages/walker/src/scope.ts index 960a1b1..0a6aee3 100644 --- a/packages/walker/src/scope.ts +++ b/packages/walker/src/scope.ts @@ -1,6 +1,4 @@ import type { Node } from '@getlang/ast' -import { invariant } from '@getlang/utils' -import { ValueReferenceError } from '@getlang/utils/errors' import type { Path } from './index.js' class Scope { @@ -13,8 +11,7 @@ class Scope { lookup(id: string) { const value = id ? this.vars[id] : this.context - invariant(value !== undefined, new ValueReferenceError(id)) - return value + return value ?? null } } @@ -35,7 +32,9 @@ export class ScopeTracker { } private get ensure() { - invariant(this.head, new ValueReferenceError('Invalid scope stack')) + if (!this.head) { + throw new Error('Invalid scope stack') + } return this.head } diff --git a/packages/utils/src/wait.ts b/packages/walker/src/wait.ts similarity index 93% rename from packages/utils/src/wait.ts rename to packages/walker/src/wait.ts index 70ccfdb..a6dd0c6 100644 --- a/packages/utils/src/wait.ts +++ b/packages/walker/src/wait.ts @@ -1,4 +1,4 @@ -export type MaybePromise = T | Promise +type MaybePromise = T | Promise export function wait( value: MaybePromise, diff --git a/test/calls.spec.ts b/test/calls.spec.ts index 2e20226..2a6e920 100644 --- a/test/calls.spec.ts +++ b/test/calls.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from 'bun:test' -import { RecursiveCallError } from '@getlang/utils/errors' +import { RecursiveCallError } from '@getlang/lib/errors' import { execute } from './helpers.js' describe('calls', () => { diff --git a/test/helpers.ts b/test/helpers.ts index f46e983..f3f0166 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -1,9 +1,9 @@ import { expect } from 'bun:test' import { executeModule } from '@getlang/get' +import type { Hooks, Inputs, MaybePromise, ModifierHook } from '@getlang/lib' +import { invariant } from '@getlang/lib' +import { ImportError } from '@getlang/lib/errors' import { desugar, parse, print } from '@getlang/parser' -import type { Hooks, Inputs, MaybePromise, ModifierHook } from '@getlang/utils' -import { invariant } from '@getlang/utils' -import { ImportError } from '@getlang/utils/errors' import dedent from 'dedent' import './expect.js' diff --git a/test/modifiers.spec.ts b/test/modifiers.spec.ts index dd96f31..59193de 100644 --- a/test/modifiers.spec.ts +++ b/test/modifiers.spec.ts @@ -1,10 +1,14 @@ import { describe, expect, test } from 'bun:test' -import type { Modifier } from '@getlang/utils' -import { invariant } from '@getlang/utils' -import { ValueTypeError } from '@getlang/utils/errors' +import type { Modifier } from '@getlang/lib' +import { invariant } from '@getlang/lib' +import { ValueTypeError } from '@getlang/lib/errors' import { execute as exec } from './helpers.js' -function execute(source: string, name: string, modifier: Modifier) { +function execute( + source: string | Record, + name: string, + modifier: Modifier, +) { return exec( source, {}, @@ -25,7 +29,7 @@ describe('modifiers', () => { test('with context', async () => { const result = await execute( - 'extract `1` -> @add_one', + 'extract 1 -> @add_one', 'add_one', (ctx: number) => { expect(ctx).toEqual(1) @@ -37,7 +41,7 @@ describe('modifiers', () => { test('with args', async () => { const result = await execute( - 'extract @product({ a: `7`, b: `6` })', + 'extract @product({ a: 7, b: 6 })', 'product', (_ctx, { a, b }) => { invariant( @@ -51,4 +55,34 @@ describe('modifiers', () => { ) expect(result).toEqual(42) }) + + test('in macros', async () => { + const result = await execute( + { + MyMacro: `extract @add_ten`, + Home: `extract 4 -> @MyMacro`, + }, + 'add_ten', + function mymod(ctx: number) { + expect(ctx).toEqual(4) + return ctx + 10 + }, + ) + expect(result).toEqual(14) + }) + + test('in macros, arrow function', async () => { + const result = await execute( + { + MyMacro: `extract @add_ten`, + Home: `extract 4 -> @MyMacro`, + }, + 'add_ten', + (ctx: number) => { + expect(ctx).toEqual(4) + return ctx + 10 + }, + ) + expect(result).toEqual(14) + }) }) diff --git a/test/modules.spec.ts b/test/modules.spec.ts index aa1fe0d..3276db8 100644 --- a/test/modules.spec.ts +++ b/test/modules.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from 'bun:test' -import { NullInputError, UnknownInputsError } from '@getlang/utils/errors' +import { NullInputError, UnknownInputsError } from '@getlang/lib/errors' import { execute } from './helpers.js' describe('modules', () => { diff --git a/test/package.json b/test/package.json index 72258fa..6ba67bc 100644 --- a/test/package.json +++ b/test/package.json @@ -4,8 +4,8 @@ "type": "module", "dependencies": { "@getlang/get": "workspace:*", + "@getlang/lib": "workspace:^0.1.5", "@getlang/parser": "workspace:*", - "@getlang/utils": "workspace:*", "dedent": "^1.6.0" }, "devDependencies": { diff --git a/test/request.spec.ts b/test/request.spec.ts index 67b5db7..6be4d4d 100644 --- a/test/request.spec.ts +++ b/test/request.spec.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, mock, test } from 'bun:test' -import type { Inputs } from '@getlang/utils' +import type { Inputs } from '@getlang/lib' import type { Fetch } from './helpers.js' import { execute as _exec } from './helpers.js' diff --git a/test/slice.spec.ts b/test/slice.spec.ts index 072a3e6..96aafe9 100644 --- a/test/slice.spec.ts +++ b/test/slice.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it, test } from 'bun:test' -import { SliceError } from '@getlang/utils/errors' +import { SliceError } from '@getlang/lib/errors' import { execute } from './helpers.js' describe('slice', () => { diff --git a/test/values.spec.ts b/test/values.spec.ts index fab08a6..7a5bb5c 100644 --- a/test/values.spec.ts +++ b/test/values.spec.ts @@ -3,7 +3,7 @@ import { ConversionError, NullSelectionError, SelectorSyntaxError, -} from '@getlang/utils/errors' +} from '@getlang/lib/errors' import { execute, SELSYN } from './helpers.js' describe('values', () => { From 8529c5aa607582f0b9302609bda1f13485784c2a Mon Sep 17 00:00:00 2001 From: Matt Fysh Date: Tue, 9 Sep 2025 15:08:02 +1000 Subject: [PATCH 2/3] misc --- bun.lock | 563 +++++++++++++++++++++++++++ bun.lockb | Bin 90680 -> 0 bytes packages/lib/src/values/html.ts | 4 +- packages/lib/src/values/json.ts | 6 +- packages/parser/src/grammar/parse.ts | 2 +- packages/walker/src/path.ts | 2 +- packages/walker/src/scope.ts | 2 +- test/calls.spec.ts | 5 +- test/request.spec.ts | 21 + test/values.spec.ts | 4 +- 10 files changed, 599 insertions(+), 10 deletions(-) create mode 100644 bun.lock delete mode 100755 bun.lockb diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..b2b14f2 --- /dev/null +++ b/bun.lock @@ -0,0 +1,563 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "get", + "devDependencies": { + "@biomejs/biome": "^2.2.0", + "@changesets/changelog-github": "^0.5.1", + "@changesets/cli": "^2.29.6", + "@types/bun": "^1.2.20", + "knip": "^5.62.0", + "sherif": "^1.6.1", + "typescript": "^5.9.2", + }, + }, + "packages/ast": { + "name": "@getlang/ast", + "version": "0.0.1", + "dependencies": { + "moo": "^0.5.2", + }, + }, + "packages/get": { + "name": "@getlang/get", + "version": "0.2.5", + "dependencies": { + "@getlang/ast": "workspace:^0.0.1", + "@getlang/lib": "workspace:^0.1.5", + "@getlang/parser": "workspace:^0.3.4", + "@getlang/walker": "workspace:^0.0.1", + "lodash-es": "^4.17.21", + }, + "devDependencies": { + "@types/lodash-es": "^4.17.12", + }, + }, + "packages/lib": { + "name": "@getlang/lib", + "version": "0.1.5", + "dependencies": { + "@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", + "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", + }, + }, + "packages/parser": { + "name": "@getlang/parser", + "version": "0.3.4", + "dependencies": { + "@getlang/ast": "workspace:^0.0.1", + "@getlang/lib": "workspace:^0.1.5", + "@getlang/walker": "workspace:^0.0.1", + "@types/moo": "^0.5.10", + "@types/nearley": "^2.11.5", + "acorn": "^8.15.0", + "estree-toolkit": "^1.7.13", + "globals": "^16.3.0", + "lodash-es": "^4.17.21", + "moo": "^0.5.2", + "nearley": "^2.20.1", + "prettier": "^3.6.2", + }, + "devDependencies": { + "@types/lodash-es": "^4.17.12", + }, + }, + "packages/walker": { + "name": "@getlang/walker", + "version": "0.0.1", + "dependencies": { + "@getlang/ast": "workspace:^0.0.1", + }, + }, + "test": { + "name": "test", + "dependencies": { + "@getlang/get": "workspace:*", + "@getlang/lib": "workspace:^0.1.5", + "@getlang/parser": "workspace:*", + "dedent": "^1.6.0", + }, + "devDependencies": { + "jest-diff": "^30.0.5", + }, + }, + }, + "packages": { + "@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="], + + "@biomejs/biome": ["@biomejs/biome@2.2.3", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.2.3", "@biomejs/cli-darwin-x64": "2.2.3", "@biomejs/cli-linux-arm64": "2.2.3", "@biomejs/cli-linux-arm64-musl": "2.2.3", "@biomejs/cli-linux-x64": "2.2.3", "@biomejs/cli-linux-x64-musl": "2.2.3", "@biomejs/cli-win32-arm64": "2.2.3", "@biomejs/cli-win32-x64": "2.2.3" }, "bin": { "biome": "bin/biome" } }, "sha512-9w0uMTvPrIdvUrxazZ42Ib7t8Y2yoGLKLdNne93RLICmaHw7mcLv4PPb5LvZLJF3141gQHiCColOh/v6VWlWmg=="], + + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.2.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-OrqQVBpadB5eqzinXN4+Q6honBz+tTlKVCsbEuEpljK8ASSItzIRZUA02mTikl3H/1nO2BMPFiJ0nkEZNy3B1w=="], + + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.2.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-OCdBpb1TmyfsTgBAM1kPMXyYKTohQ48WpiN9tkt9xvU6gKVKHY4oVwteBebiOqyfyzCNaSiuKIPjmHjUZ2ZNMg=="], + + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-g/Uta2DqYpECxG+vUmTAmUKlVhnGEcY7DXWgKP8ruLRa8Si1QHsWknPY3B/wCo0KgYiFIOAZ9hjsHfNb9L85+g=="], + + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-q3w9jJ6JFPZPeqyvwwPeaiS/6NEszZ+pXKF+IczNo8Xj6fsii45a4gEEicKyKIytalV+s829ACZujQlXAiVLBQ=="], + + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-LEtyYL1fJsvw35CxrbQ0gZoxOG3oZsAjzfRdvRBRHxOpQ91Q5doRVjvWW/wepgSdgk5hlaNzfeqpyGmfSD0Eyw=="], + + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-y76Dn4vkP1sMRGPFlNc+OTETBhGPJ90jY3il6jAfur8XWrYBQV3swZ1Jo0R2g+JpOeeoA0cOwM7mJG6svDz79w=="], + + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.2.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-Ms9zFYzjcJK7LV+AOMYnjN3pV3xL8Prxf9aWdDVL74onLn5kcvZ1ZMQswE5XHtnd/r/0bnUd928Rpbs14BzVmA=="], + + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.2.3", "", { "os": "win32", "cpu": "x64" }, "sha512-gvCpewE7mBwBIpqk1YrUqNR4mCiyJm6UI3YWQQXkedSSEwzRdodRpaKhbdbHw1/hmTWOVXQ+Eih5Qctf4TCVOQ=="], + + "@changesets/apply-release-plan": ["@changesets/apply-release-plan@7.0.12", "", { "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-EaET7As5CeuhTzvXTQCRZeBUcisoYPDDcXvgTE/2jmmypKp0RC7LxKj/yzqeh/1qFTZI7oDGFcL1PHRuQuketQ=="], + + "@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/changelog-git": ["@changesets/changelog-git@0.2.1", "", { "dependencies": { "@changesets/types": "^6.1.0" } }, "sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q=="], + + "@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/cli": ["@changesets/cli@2.29.6", "", { "dependencies": { "@changesets/apply-release-plan": "^7.0.12", "@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-6qCcVsIG1KQLhpQ5zE8N0PckIx4+9QlHK3z6/lwKnw7Tir71Bjw8BeOZaxA/4Jt00pcgCnCSWZnyuZf5Il05QQ=="], + + "@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/errors": ["@changesets/errors@0.2.0", "", { "dependencies": { "extendable-error": "^0.1.5" } }, "sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow=="], + + "@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/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-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-version-range-type": ["@changesets/get-version-range-type@0.4.0", "", {}, "sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ=="], + + "@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/logger": ["@changesets/logger@0.1.1", "", { "dependencies": { "picocolors": "^1.1.0" } }, "sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg=="], + + "@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/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/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/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/types": ["@changesets/types@6.1.0", "", {}, "sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA=="], + + "@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=="], + + "@emnapi/core": ["@emnapi/core@1.5.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="], + + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], + + "@getlang/ast": ["@getlang/ast@workspace:packages/ast"], + + "@getlang/get": ["@getlang/get@workspace:packages/get"], + + "@getlang/lib": ["@getlang/lib@workspace:packages/lib"], + + "@getlang/parser": ["@getlang/parser@workspace:packages/parser"], + + "@getlang/walker": ["@getlang/walker@workspace:packages/walker"], + + "@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.0.1", "", {}, "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw=="], + + "@jest/get-type": ["@jest/get-type@30.1.0", "", {}, "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA=="], + + "@jest/schemas": ["@jest/schemas@30.0.5", "", { "dependencies": { "@sinclair/typebox": "^0.34.0" } }, "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA=="], + + "@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=="], + + "@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=="], + + "@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=="], + + "@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=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@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-resolver/binding-android-arm-eabi": ["@oxc-resolver/binding-android-arm-eabi@11.7.1", "", { "os": "android", "cpu": "arm" }, "sha512-K0gF1mD6CYMAuX0dMWe6XW1Js00xCOBh/+ZAAJReQMa4+jmAk3bIeitsc8VnDthDbzOOKp3riizP3o/tBvNpgw=="], + + "@oxc-resolver/binding-android-arm64": ["@oxc-resolver/binding-android-arm64@11.7.1", "", { "os": "android", "cpu": "arm64" }, "sha512-O1XEX/KxKX7baPgYHahP+3vT+9f4gasPA0px4DYrjy1mN9wWQqJPLLo/PO3cBw3qI3qRaaiAGT3eJSs8rKu8mA=="], + + "@oxc-resolver/binding-darwin-arm64": ["@oxc-resolver/binding-darwin-arm64@11.7.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-OSCJlXUTvGoal5dTMkdacmXL2R3YQ+97R7NMSdjkUVnh3TxvGBhoF9OebqY3PR7w2gQaY5LX+Ju+dYeHGBCGgw=="], + + "@oxc-resolver/binding-darwin-x64": ["@oxc-resolver/binding-darwin-x64@11.7.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-d0jKwK4r4Yw19xSijyt7wHZT77xh3v4GnJSbvEiPavLms27zqc//BqYJUSp9XgOTOkyFQ+oHno47JNiLTnsSnQ=="], + + "@oxc-resolver/binding-freebsd-x64": ["@oxc-resolver/binding-freebsd-x64@11.7.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-oNch5OpAnxFjukDZ5GJkuEDEPPYDirm10q2cJcbK0SETVM0rY+ou1cLqJAJC9R/dULbqGKC9fv2kuyuw9M6Fig=="], + + "@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-resolver/binding-linux-arm-musleabihf": ["@oxc-resolver/binding-linux-arm-musleabihf@11.7.1", "", { "os": "linux", "cpu": "arm" }, "sha512-M+ORXlPV0dXCHleqOYLjKHwxn9kDmcJqnJ7zGZ07vggaxOCnpM6zqyGS92YTTyeYre2AqO3Xrx1D4rnUeozI8g=="], + + "@oxc-resolver/binding-linux-arm64-gnu": ["@oxc-resolver/binding-linux-arm64-gnu@11.7.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-ukHZp9Vm07AlxqdOLFf8Bj4inzpt+ISbbODvwwHxX32GfcMLWYYJGAYWc13IGhWoElvWnI7D1M9ifDGyTNRGzg=="], + + "@oxc-resolver/binding-linux-arm64-musl": ["@oxc-resolver/binding-linux-arm64-musl@11.7.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-atkZ1OIt6t90kjQz1iqq6cN3OpfPG5zUJlO64Vd1ieYeqHRkOFeRgnWEobTePUHi34NlYr7mNZqIaAg7gjPUFg=="], + + "@oxc-resolver/binding-linux-ppc64-gnu": ["@oxc-resolver/binding-linux-ppc64-gnu@11.7.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-HGgV4z3JwVF4Qvg2a1GhDnqn8mKLihy5Gp4rMfqNIAlERPSyIxo8oPQIL1XQKLYyyrkEEO99uwM+4cQGwhtbpQ=="], + + "@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-resolver/binding-linux-riscv64-musl": ["@oxc-resolver/binding-linux-riscv64-musl@11.7.1", "", { "os": "linux", "cpu": "none" }, "sha512-3folNmS5gYNFy/9HYzLcdeThqAGvDJU0gQKrhHn7RPWQa58yZ0ZPpBMk6KRSSO61+wkchkL+0sdcLsoe5wZW8g=="], + + "@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-resolver/binding-linux-x64-gnu": ["@oxc-resolver/binding-linux-x64-gnu@11.7.1", "", { "os": "linux", "cpu": "x64" }, "sha512-QyFW5e43imQLxiBpCImhOiP4hY9coWGjroEm8elDqGNNaA7vXooaMQS2N3avMQawSaKhsb/3RemxaZ852XG38Q=="], + + "@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-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-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-resolver/binding-win32-ia32-msvc": ["@oxc-resolver/binding-win32-ia32-msvc@11.7.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-iNRgJxOkfmxeq9DiF9S4jtw3vq5kkAm6dsP4RPxoAO/WsShPPHOSlTpOqyB8bSj5Bt9DBLRoI43XcNfDKgM+jA=="], + + "@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=="], + + "@sinclair/typebox": ["@sinclair/typebox@0.34.41", "", {}, "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g=="], + + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="], + + "@types/bun": ["@types/bun@1.2.21", "", { "dependencies": { "bun-types": "1.2.21" } }, "sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A=="], + + "@types/esquery": ["@types/esquery@1.5.4", "", { "dependencies": { "@types/estree": "*" } }, "sha512-yYO4Q8H+KJHKW1rEeSzHxcZi90durqYgWVfnh5K6ZADVBjBv2e1NEveYX5yT2bffgN7RqzH3k9930m+i2yBoMA=="], + + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="], + + "@types/lodash": ["@types/lodash@4.17.20", "", {}, "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA=="], + + "@types/lodash-es": ["@types/lodash-es@4.17.12", "", { "dependencies": { "@types/lodash": "*" } }, "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ=="], + + "@types/moo": ["@types/moo@0.5.10", "", {}, "sha512-W6KzyZjXUYpwQfLK1O1UDzqcqYlul+lO7Bt71luyIIyNlOZwJaNeWWdqFs1C/f2hohZvUFHMk6oFNe9Rg48DbA=="], + + "@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=="], + + "@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="], + + "@types/set-cookie-parser": ["@types/set-cookie-parser@2.4.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-GGmQVGpQWUe5qglJozEjZV/5dyxbOOZ0LHe/lqyWssB88Y4svNfst0uqBVscdDeIKl5Jy5+aPSvy7mI9tYRguw=="], + + "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + + "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="], + + "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=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="], + + "better-path-resolve": ["better-path-resolve@1.0.0", "", { "dependencies": { "is-windows": "^1.0.0" } }, "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g=="], + + "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "bun-types": ["bun-types@1.2.21", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-sa2Tj77Ijc/NTLS0/Odjq/qngmEPZfbfnOERi0KRUYhT9R8M4VBioWVmMWE5GrYbKMc+5lVybXygLdibHaqVqw=="], + + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "chardet": ["chardet@2.1.0", "", {}, "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA=="], + + "ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "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=="], + + "css-what": ["css-what@7.0.0", "", {}, "sha512-wD5oz5xibMOPHzy13CyGmogB3phdvcDaB5t0W/Nr5Z2O/agcB8YwOz6e2Lsp10pNDzBoDO9nVa3RGs/2BttpHQ=="], + + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + + "dataloader": ["dataloader@1.4.0", "", {}, "sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw=="], + + "dedent": ["dedent@1.7.0", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ=="], + + "detect-indent": ["detect-indent@6.1.0", "", {}, "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA=="], + + "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="], + + "discontinuous-range": ["discontinuous-range@1.0.0", "", {}, "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ=="], + + "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=="], + + "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], + + "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], + + "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=="], + + "dotenv": ["dotenv@8.6.0", "", {}, "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g=="], + + "enquirer": ["enquirer@2.4.1", "", { "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" } }, "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ=="], + + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + + "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], + + "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "estree-toolkit": ["estree-toolkit@1.7.13", "", { "dependencies": { "@types/estree": ">=1.0.7", "@types/estree-jsx": ">=1.0.5" } }, "sha512-/fLCEcVBUgAtMkGXZHplPVyUv7wiSfsCGubBdM16n1iYCidPfyk1Kk1U0wAxLZADuA3z8k87DfVYXlBmHJeekg=="], + + "extendable-error": ["extendable-error@0.1.7", "", {}, "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg=="], + + "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=="], + + "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], + + "fd-package-json": ["fd-package-json@2.0.0", "", { "dependencies": { "walk-up-path": "^4.0.0" } }, "sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], + + "formatly": ["formatly@0.3.0", "", { "dependencies": { "fd-package-json": "^2.0.0" }, "bin": { "formatly": "bin/index.mjs" } }, "sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w=="], + + "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=="], + + "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "globals": ["globals@16.3.0", "", {}, "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ=="], + + "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=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "human-id": ["human-id@4.1.1", "", { "bin": { "human-id": "dist/cli.js" } }, "sha512-3gKm/gCSUipeLsRYZbbdA1BD83lBoWUkZ7G9VFrhWPAU76KwYo5KR8V28bpoPm/ygy0x5/GCbpRQdY7VLYCoIg=="], + + "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "is-subdir": ["is-subdir@1.2.0", "", { "dependencies": { "better-path-resolve": "1.0.0" } }, "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw=="], + + "is-windows": ["is-windows@1.0.2", "", {}, "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "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=="], + + "jiti": ["jiti@2.5.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="], + + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + + "jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], + + "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=="], + + "locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], + + "lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="], + + "lodash.startcase": ["lodash.startcase@4.4.0", "", {}, "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + + "moo": ["moo@0.5.2", "", {}, "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q=="], + + "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], + + "napi-postinstall": ["napi-postinstall@0.3.3", "", { "bin": { "napi-postinstall": "lib/cli.js" } }, "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow=="], + + "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=="], + + "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=="], + + "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], + + "outdent": ["outdent@0.5.0", "", {}, "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q=="], + + "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=="], + + "p-filter": ["p-filter@2.1.0", "", { "dependencies": { "p-map": "^2.0.0" } }, "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw=="], + + "p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], + + "p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], + + "p-map": ["p-map@2.1.0", "", {}, "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw=="], + + "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], + + "package-manager-detector": ["package-manager-detector@0.2.11", "", { "dependencies": { "quansync": "^0.2.7" } }, "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ=="], + + "parse5": ["parse5@8.0.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA=="], + + "parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@8.0.0", "", { "dependencies": { "domhandler": "^5.0.3", "parse5": "^8.0.0" } }, "sha512-h4bXApvAdtcuv3MPcLQUCSQ2bJg9pG3cS5LwlXDJqweH06+0DjXVu1zwpjlbyu9tNsHiNnm4TM0nvTsGxQi5pw=="], + + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + + "pify": ["pify@4.0.1", "", {}, "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="], + + "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=="], + + "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=="], + + "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=="], + + "sherif-darwin-arm64": ["sherif-darwin-arm64@1.6.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-J15oBJcrnCAZ0rQE8WbMShYw3204A18akCH6C/uZrILTwX/vZyJIqi7lAt5L00LzsadA3HcyQqVjLNNCvuihoQ=="], + + "sherif-darwin-x64": ["sherif-darwin-x64@1.6.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-oLA/GtvUasi+qCl35LczOhQ4g/xY2mxE5/eiTYQGT3Ow7FKLscnkE6v5l28bgkFeR/uke0AgZ/CgHhozAf0ulg=="], + + "sherif-linux-arm64": ["sherif-linux-arm64@1.6.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-OoltlucT7v9BZdkYZRbs1QU0DYMCQ5qgpMqQdMW1Rq3w3amr7+oEiV9NHntD83udOo8xRxKq0uPXfNYu+VptJw=="], + + "sherif-linux-x64": ["sherif-linux-x64@1.6.1", "", { "os": "linux", "cpu": "x64" }, "sha512-qyDyYqpi3ABGkRuCnjnxN3OMT8DxMiiLzhS9p9xC05Y9nr5hjkxvqP4DdJ4e5opm4E7vzRAS7VQoZ6m7h6tsgQ=="], + + "sherif-windows-arm64": ["sherif-windows-arm64@1.6.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-wAbCiqP//lo7bZUlHmZUV3/sGjnJxo6QB5/fqhz5/GUeWh4CTyvlSacJKZxLnXnzpiUSeFnWutquWnHkRov5Ug=="], + + "sherif-windows-x64": ["sherif-windows-x64@1.6.1", "", { "os": "win32", "cpu": "x64" }, "sha512-2r0qMxZGCMO2aq8Hlq7npxtAsUFVDsEFtUM/6dFo1npa/jHe2mbU7ii/Ymy0bloSa/qw/azrSfRV6GLU7Gjtxg=="], + + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], + + "smol-toml": ["smol-toml@1.4.2", "", {}, "sha512-rInDH6lCNiEyn3+hH8KVGFdbjc099j47+OSgbMrfDYX1CmXLfdKd7qi6IfcWj2wFxvSVkuI46M+wPGYfEOEj6g=="], + + "spawndamnit": ["spawndamnit@3.0.1", "", { "dependencies": { "cross-spawn": "^7.0.5", "signal-exit": "^4.0.1" } }, "sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg=="], + + "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], + + "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], + + "strip-json-comments": ["strip-json-comments@5.0.2", "", {}, "sha512-4X2FR3UwhNUE9G49aIsJW5hRRR3GXGTBTZRMfv568O60ojM8HcWjV/VxAxCDW3SUND33O6ZY66ZuRcdkj73q2g=="], + + "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=="], + + "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], + + "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=="], + + "undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="], + + "universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], + + "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=="], + + "@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=="], + + "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/bun.lockb b/bun.lockb deleted file mode 100755 index 756f218f14429850dabd13173de93ec128b345ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 90680 zcmeFa2{@Kr+dq28Z7f1cndd2FDv^1}5RxH7=6RkaLy=G-MMNc0GLwo7Wy)A8L#7Ow zi%>$M40|o^>wT{Ox4*B4+Q&ZjK927^p4EA;;rBbwb*|~U)_r?lHkJcEUY-Xm9b6CC zxSnRV^l>ExiQn1H%E{Kj*@oZN&C|ugoBy;RDINxcnek_47!Ha`c{nBUb#Y#seKr;h93_`#GbQ#dxKwk%%3usqdxgyZKAWsK0576I5kw6L=A!eB;lZ7;;b_ z05s@&u#1hSosBT?0o23saPZ={b9S@D*wSq9j00Zim#u}Dw+FEAY2)MNVC#pO1od!y za`)ow0}cJ520XC+d(am8@nYYG9YWfTc2-_q-hS>jm{*`4wzsF>s5b!`+Mmbi37igK z*l5=RG#RLOxA3;-ce3&GwRf2TvQ%5HN_aAB{LI zfb+}Bf#1Q^)(x`{?$|%HjA6;p!FmH`@Q?+vr~h z$iw+{NMOSccYZKB-Zq}@{4N&mAg(DmycN*E)!SzQ7@~}S*AkPT2 zh|tEmX9F7gw+CoAuiSjRt!-SrG5LTS^1TFW0ziXhMKSFb;c_Hv9+cz}X4(=?=(4KkY5N_-&mn?2z_0M>pCR z0uB4~1@OXlJwSu4I(SGUM^7&L?a8|w!F>C}Y%EDiyKclkZDp-GrdQxTVU>gb<}|jN z=*O0-F@1V%S)gqn7SZ_V^skNWiEEc>X zR8|Wgum_gQrZvQTo43-a+D*ww`jBsT+bG}9X1^i@3Kz-2@e52x@AhZkqj|RIaQ_~8 z2^E#nhqah~JC0`FD{G^CV=@-P0%7N`j6a}hnD5HE_BePtW9Itv0ek#jOy2X5W6xTI zi{`WZzSVR_hyS26v?9N=XJp66DW>wmnbU6G_sk3yyKZFo6}62tmy+K8@-x0-<*ZuZALJrVvJx^D=x>v#{SEH9p-o}EvpO2Uh^y_OvQOd)fHJl!|c_M^aYpM#`# zhI&GYMno$4ZucC~+pBhZSnZvl<`t8j>`J;a@qET_c4)L46@BHoNW_z@asP3~5hfK= z|5&wSk=AjKp7*>QctyxleoXNEe8805n@d!athBp1D9^L$ycS>Z-m%^9dd%%JnGI{a zCxjoyv8(7ZXIs~F%i?LtB#MwM+Dm`^RUGX7cIx=umy`+O0Zvk}Q^eWNOi}-)tALXtyVQ;@zieOy5nk zqE@_K@t)V;Pm^9`Vw*2?NW7e-uh`^l_CdpQJ6M;y)bNya-(EUali6{2@brhnYOlTs z-=;moly~}ux#+Sh1M3i56$xvp(YB=Cqd)Gt7iV#fUuk{uS`L5vvg1@f`B9tCqOU`y zL@peSHYAb%cC_3*G5Y%e(hp}9 z$88?2@BPR>I*`*Ao$yi)+?8r+I+StpM3bfkMPWl1n!?O_}+?`0KPgd!xv6s!v=K zd|E|F`#w`a?Z^8|uZYlc<}c(1Pjs$+xn-ou7^mI!s5ZIfBrEgV+JoP?%8HS78b#H>1n5m4AQQ?eUXKC_3$_EZ~J46hIDcd*2&bw zKV7pQK1K25RS36;7=a=d8j(e|2P#x0CX?{3Fqs+Ui#^H9KN{9Vu z=+81D%R@xRX}TgWrZKtiaB9I17}|bq;Xz6n1AYkQzPg0HEr&bPct1q?sPd>u*ba5y zEDBYKJ4WK65MSpT@W?neD4^rZy(H&Mj~dQ=y{obz`D(*#Ww&hhD#tn2$na+oJN7Vs z9a|D{8fC-BE6-Jtq1QircjsKf4JPU4l-5H}VHc9BXV400gat^_j^q$b~TzV?Ivx}2HXfmNf(5tmpXH{=W(4zhQIg`@V0gY|; z-|U4_`@@pQTb!qMBmHV~%d64t`EZ)eWyvgDPR*1eIqdqY^KE2Tcbiz0mfd30Jn-V) zzE?HWcg_UZ8k`N(WV(YlC`wiMsd?nQp!y!;ZlxM4t2bP8p4a>A%g79RUm@)+J=mpW zx9>dMYLMNcI)8Vp_p^1GsL_dr@+<0!1$5pe+rSz8H-d))F98jnQGyA82G0Q)q#RfM zKPsf%LEwlez(aosLE5Ze2)+XVwEhCm0f^N90`CFvnty?>1bDT-z?0zro&S0Ouksi6 zivb?I0<4cecqH7kAmeumi@|_L>R|9}2cL7{v)-lz!KVVe9L_#1K*D*r8A0&F01xL6 z=mrL+tRXG^ui9v!f+>9XjT7U=Z?my#?%%gwfK=61V@Zc5hkMWuSkL(}N zCNhsUYySqon*sZOI{x1Q@YG-6wZNuh^B4FcfOq-}JTrJXcK8c?1i=4||6c$e+-&@D z{7t}y?eZ7+R{(GK7kD9XiSjr2M1cRB_^klE#b5Yu3NC&AX8(Ey@K%3epAlSc{f+-Y z0RK1f8wL2k8NXxTGVyQvUjp!O|APA!-21n>|HDgGWdB6=aLDytjfyEmSH5c}{9-;5ykeE=TXhk0mwtK;_& z;6-u%L%Un`e;VgM5zh8j?TdlSctv2J02&9fReUJG!~R42TM;CF6#x(W5ADJ+*sA?m zfQQdd(0_|yhtJQD58B_V|G5A!1MrCNTb+Na055{W zgROYW_J#It^dIpXiNkM$2P%>H*#W!~s{hD5+AO{V;AK($|2G^`kJu*yUn0T%2Z`TS z$4>*`Vf+!kt@`*}JwH zzbKr2$OpdfTYm@KOaKu39`yh0pRf#>hyTWb;Bx>Tu7AYut>V{k_^s?c&^N@s6zDXx zkL-Wob$C;P;4cIG-<+TQ056Z~|E7$CMu>eT#*OnI8UL-u&ja9*_g`om;r%y1kaqX~ z3;y45NIild26%XW!1%-1BjrfD|4Ae5_JA*AWdVM(>mK1l@FxM@0N`OcQiinookrT` z13X-RFptdP-{Fut1V0M!Nc@p9q|NU%(smCs1|tCMBm39yFz7l2uL$sm0UnwETb)1G z0bUjtzpeOy*nfw!zu9vOgA)Y5on>SHhj>^9?=dzb2wn}~VgF%%D|-lnj{5#E|0Td51bDda5RR?jNjNt4zs=f3xDoqD03MznaQ#4z z&H8}g-2fiG|3EBENICfUTS3}o0X&Q!GJeQD`dculMDSw(5BDFW|6BE+lXJs=#Qwk8 zMd}gz<^V4Z?8E$KZ9@(OpA7KOfB4?>C-_c)R{(g3{S*8?u7B3gpWtl(9`^rF<98p2 zhx2bMg2ZnK;9>lr{Xg-4ANR)i!|(3ky9?NhHYJFC9e{`ZCjzLwAVIwuLGWn+e;nW; z=1=y&Ih_4J?Y|JuKi@w?A2u69#Q#WuhwB$&2|+^EA(AJU;(F{YT0m&%X)MRtMl!Q1RR9{&O4Pq5oSMd*~Zte;nX7arl4p8C{Ry zWx>lAGJa@Ybld;#GlCBUcx3%-cI?o03IQH@fBX~tM}UX%L;OMXf9Es03~9%F0E5v3 zcx2v?p&R|?GlKU4cv*ml`!4icBoS@3-22Uhwh+-+v(|6oh9Z_doxO_-_R8$o}^y^XCS@ga6jw zAO0l%?*JIyze9fzpZ;gB|EWRRwt<&dxc>eWzaLCqxc~hrJ{aKP^YfqLn*sjVU*KuM z3&V-Oz&ioF#$Vt|0RC_KPXrFnKj}Z%^VS9VJEcF3zb&v2=Pz7$TbaLzeOrJd2Y7BK zV>Mpj#Aeqof`@u1z{@gk4G;SZg&tfU!RHUS?xFukIjsAgAno1)JQ%|D`AZD|oAn>T zGl7Q>WdDcz$7W-Q;Ozk(JOTtmU!iRfi%kiFPXKs$es9)qgdD+-0leB@;17V!3p|1a zLtc0WAiOaDJ3-o+06en)!T4`=|4sy8xPQagQ-ZYncSccli2ZhehvQEH>NaZ|(jfTl zz_=2?!}!DVbF0sft^luq!$aQ9o}-BUM*t7whm1clB-w-@`0oG@j^Oq4YqN6?(j$0o zsg3tHnBNZ4R{ggHcx3%REGbBv5oG@e0gd7Qv3K9r_74OPpI1Q&KFqK+JktLp;6EHc zWd3dS`F9H7!4UihzuEX9{?qYWFCT# zzZC?}DFgnd9^i?8+xq`riQuCE9-d!+imw8Aczz)J_E!C01b8@p$hd8G4?+AFmEHLM z2H!fN0^5(-0c2~;3ohcY+>v6Vf-P-W(2`=g3S|serm@zwwj9zlbtfPH+BHam`p|91c$ z_8;wk^EN2 zzXIUl{sVC^K|eMlh`pZx500?^jQ>{ciz{!uzasNzvv}wucyC-!$Y(wmw(oaCtC>>+=6) z4gCh&-MXMPELQ{xYOoyE1!@A2z_ZLt~pfzl#1rpTY zj%Hn;hI3B`Bv`Hs5)`Om`ALvqxjslx&>EH-fCSqafduoXK!O4_JxIPV0|aW=&JSjQ zKn>StAV?5*79=QW4a?81m;PSEc0ssyXbt&8aOF_Lb{BAYsG&b$Ai?r*kf8i`8m@yV zkl!ts_hW3j=g3o9bAVHo=kf1;f z>#IS6{i_EF);E9z1!|aY#OaqnLxCEWzk(ScP(wf7f&}B&4idE23lc0J011|lfdp|M zL4xo4b09(aore8i015iJh|@oDdKqXaztiyD1`Cb;rH1h#0X&e36vqcO><0}l4>jyB z9njEU23+}{XozP5cu2vFIX2hl3i9$9|wGftJLTLk)4#K*J&#TshS6 zqbx2DHT)=t%R>#vMG>c!aphsmVjvF#0p$M;4TnNu-P-@DVYwnmP%Gi; zp@#EF4J0_u@ce`VHEgGW)Bk&pfV0k!5Q2sj& z_v2gC?>V}a^A)b=|2;?7r_K6#3fJrZ|Ig9YovUy|`F~OX z-!{w!FPa)lV(w)^+P8W?Eu71}eX3exd!kbDZ0*69LfSsYebn^UnkSuZ`Ll5LO>#WA zb3*^aooUv~S7LKiZWsR?_?AG{I*;Oodl({E+dyGWzl2nUtE7hH_~%|4M1|Gza=)&= zcx#_bMp3T@CGn?Z8e^VnytCCpLDY}4SdNKGooVOG36qZYWpD$Sx>%^$LP_>CGB-y3~?|ZgnKa}*q(A;kv&I=Yo0njB)XCRDT7Y-k(?fRH9?Vr z%tWhwr@zsv(1#w|_AlI(md=H)MpRBe3s!O`Rp<4_E!(H;r|WV4LQc3Q5y5hq+G7*; zCo%79E5v@YeXX`faKPm-z8UQ`mY>^y-OLSnR~_`#j#VXFU<~iWv3K%wk1}NYe1+v7 zSn<7+uNY5F#rX?);TeJmHl;v@wzu7}u_BYlceGeUg8J}7!v;bLVyO|V5T9Iul0yl8}QUF5uEQ<(MBEsdyr(Ivxy8{q)e6FHqsT?DX?VZ z!iDn}@}j>7!R9c}T4r1JVUEVog(QoA6Z48XUiD3wJMt}cc}Ac7yBku;6&BIzZken2 z-pPy~FWU}ketknhHLc5Sm-Xyoj`R6--i`T-{#_Y1Y`$GzJV)@|u1*yjo0+|d6x;m9 z-3^uYM+JWWsCtG!1(rNENr6vOwJ2bT%A(Xwd&nwDyBek?>gU$D5pWgNvziUa{@ z?4y@8pV}SFWqj(-?3crPk3Cv$8<87`lP+cbls8HGDF`_ zd*_H{K4ST(6|eb*{XltWqM;vw@qtT$k7HSW3{@W6ZTs0j4aK_yAq5&+V*J8Rx=w!o zp-&l(HNh-W#P|~{6R*2yR}%f-?^5K?87s5i_QAbT>tx+%920f%4(Dm-ch*NtcMd+N zIUlFmZH?lE?_h{vjp@&BJEI@l-Jb26b^dVZ*pe}K_@2n09|PoQuYNIT)1NLecl;?C z^K9wPki(by%$=Pd`_o!-&5!P^f8Iea!|)l!3-8zv!491bQ}z)I?ZD2vO4&z}oJu^Q z#87W+U9AzPes0x&=1bu{5lM!+`}*HK@F^~w@{SXg`f()PU^3lRslobc`R5)KFT8U@ z1e+UC!;~d|h(-8rP%6`l_`Uk4uDp?2kUp|Fn&SLwfGq4gsZG<_wmV-k%UFKwx#~<% zKOY}Ee0aRMK+=|pVu%gxFPy`OU_}aK_0w#;1YCc*W=d1++=Hj{nmE&J^?Zw@=W}uU z1vBa6eoZ`OeQ(Kb@T))ZjXw5`_O90Ja2c^Q=ccaiV(S+uf8jeLBG|fyi#;!giYn9> z46?~zhSnrM2sroi<{@j!pb^T-*4kE2e|*=3;wz7}5@cExuFm#7Q(ER$kMbB4Ok3`)2+;fJ$+Z_RbH07wn{j%Hh=%ey znDyz;kF9LJBlC6YEG^`<|VlZznHnwF)Ab%((lYCgZJj-1IIhUI^#7eL>U!hi|QWCS7l_$3p(sdwe_l=rW zM_nElQYjpHpOu<0@8|Z#qv5EGJk4&2+xZ*&`o=!F7tL$>Vy2^&JY6wi#VP6Z0~RT( zU!juP<%x+)zo@sHvMip`>c03XGU}5vU10h|tJxS^cT8o;q2(mG4&I*~H+~q7q5R#4 z=9P>)=R6U0_}emG*RH)g5)bW<82DyCK2y)(@>1TVK1+HyF)ixJkYQ$}i#on~7*C0E z2%mz^w=(6duiNV#N?9Bef}U+}a=|=w_~z(%*qPBkq3`mErHy%pA%^EB9h$etNT@5{ zqFu$SuIjm8hwwY`uI-C<+lqGDzcS!4^b)vs8ZVslyrxXLBNH{L)l#l)x8B6Ttoxp~ zY<#P^8Lvpd|8E2EA0FHr;2kd_*igRKOC^p0CpFW&r_?R8zL31;*cB6BkQbJ_t@Kk) z&-7CzEq1309{shFv=x`kH%D&rXx%N6)f~IEbEi3}SrWXH0sq1O-R$-M?STLA9v0T* zJR=e0EtEzu#6RJCog;Vl$rQ(DDdTYE*W?pxKPo=Tzb4b{)i6Blce9;w$~n6#Q1DnY zDHqALl+d!zOL!<=MuZe-ETd#ryRHc*9X2h>**0I#{YaQs{q60t=1o|}*4BTxOud-_>;CSKSv7&i}9*$mc z)8aU*`ewqdb>~PAi|dIDAEPsa(h@r1i=U+>G#g7^oX89#=9voLcjGF1X?tc7YlQDP zvG18X-ny(2GOzPu*W0v=q( z`3vK~f#$6jUZcL3^zkmqHNAUGWvYgJQvt+x`{&I%pC8I*_c;2qs3g2B;iAoE6 zHwMRe$;C`1N>z)#-;->&^Peq5o`2!9Bqy4eCR#mI@rc}`fyWCjy1l_`J#^2`JeVeS zFo_5eTDF_MefG`_dCg_5*?roh65|X;zIiT7&sqZ-j>IVyAG%n$ zoT-UE`-k~+C#y$pJfCgwa-(@UvZf?um(DHY`q zd=&cY^6UVK@SRV-stXeIQ0CqVS* z*^W?$ZF$zDf%W!9to&uAOPX{H1e|g@G+BB=EcPsvZp@X;PsoF8S|>%;c{k2CJ~VHs zgwI#YCKEna)$?Ch)dZGSFQ4*`N{^Si{L8{Yw<{uRrC`$6xOtA@{De|sHHUqqzw*;$Ukb>$+&D1Qaeyf2arpS-iLyAeUjdXyz@ zcE{1gbQ1y|W@&0BBTl~L#7y-U>RK1_hK8inI0*{FD`Uk-CC#I)xv}3 zx@u0aZM&P@yHHC=R#Wl$RX>VX5Y3yv(~Er|eE4ie;7vavmueC2eP+o|xaagJ!+CR_ z-buG&8N9h5+bS47&p{(_UrOIN^}}@CZ8ZjmSzBf?C-vqj6t57PH||0JZNdSwrJzXH z{mYf7lI{?HBbo2ayl)i8v*XA+zVh;<>{$C)*I|ajUqz~)T|)4v4=t;%?R&0p$^A*r z%8o`9FZk`oe*_zqmHs`_`Jh+8T)Xy~YV7O5qJwJXx0FmKZ}+NlIP-MZmxooCXmT4) zUpuTu;I}X0!o=~?B!^qYb)GsFsk^xRP`o1lVFl;r2fB(vnZ0jV>q}1ZOYK>l{b9k~ zSja=*_c$ous8V|R9X4kre5LnTUdwQ@{781b4$I?hS3=Iv z?s#|dqe(dSkox{^0Tk~+G_O=36X70#HVS!}o%na z2EHIO#%40y`u2;sk}$ULjI2Qnqh7y#2WGj2Lt-gG(ZoB_Wxv1yJgaNWC$p%j(eEu{ zXx^8EUBO@9s>UmHN3seSjsJQyFhLebaqE@JF@}`aug=USc=iuIm*M8Gx#k^JUv_J0 zk4z}pSLP#29$s2rfv-HCqx?OL=C!QO3h=qe_i&%30KdWELtOkHT<90_`~`RJ8}khx zm1Pk1X#Q@uQ`X46FtTrYM`GUPUs~n&qn?k;?V;uS~pPG0{NDV^|%Wq-$O z`jB}cm&bzBs$#)YrQR1^>@L@o4}T6XR+SkZUJmpxW-Sywy4r32_|9MyCrfrN=7q|8 z$&GuijeQ6H&I1wbh}OMxDiQ&;v+=wpMG~g`I=tn~iu$6{g#opS(u-Z6?d+<^Dm6q0 zYmbe1lS+!KeXo9aDEW$wtuEoodXp%RWR$;05K^GAv-urV_#~%70*e|tWDYRDduOab zXyUd_F`K5+@Fq9g;ZJMc^*gs~l0@p$QHULBI{r36gqV4-a%4d!sjxLxQv$^+iRQ%& zGpk~f(^(CwR;rGAJo*)Hr#XF*;G&na)#BLjOy|!ZuNl5t7eDsvci!G@=TejOV?IZO zO&lw55yPP$_A1-Y{6(xAt;YV6;1q2eHi=GA%MFjrrE zw)w*~7N3OU?K0ZjkN01?%0Bdk!p%g7$dbS~&}n+^Ls!W7g4S@&nP@pWhi9u(!uCZv z6ARPZv9rx6UU@WcMP3PE-t6s|T6vc%+`KgSNJ1#5E8*XT3&w+^rs zxL)7OKUMduv=8$vaIjsBM@nOVvyWZ}*RAY@!;7f+9!2x|oNc8Om0Zl^6d`}{$W`cg z>@EW49M$3muXC{nrM^>)F)tTLaX1$0iYXe4Y6oa@={cJ8vbKwy(4|?z9$}v|NAW77 zc{8X#$z90d{h?XI{n!_b^nfSzrwlQT!&di8;<)g%L*o6VC3g!LmrF{WA2p(^I;&ar z-aa})cbJ~~i}okdxZB4$#a@mb)O$NNn6~srns1Hm5&b#MFKq%PPePIk z@ZoPP5P#wK;)q~BrzD+xLD-(QJv>hQ^>MP6AM9+5(%(sx_Xqx5H731F{_b+ccS1=? zf{~j}6f%Riz1tF)N!?=&Z_bt`EU}u1%b|FWA*4WKtMVu#FTSNcvSz&eT!r#I>ApbX zw_k+b>Iqh~WwVREc3tI)cUsy-L4Llcn@wjtwf&CJCF8S;S|aQ+g48dwS$hJ zhyGFm0eW5n&!hH6K2w_HFCAH{IUk2z?I7;1ZH#@#c*1Rja)OL#3>p^+wq`}PC$o(Q`7yN!t zuF9`2*M5G>9bh}5IJ`$|G}iJ)$XWGqu10*5wi3r^r?$+E`;rY__`3o`u%#x~#H|+Y zI8Qa%MrG8;M3h*5fA2*TGk7uXqCJylgivUs=rDWIqqeEi4ubxdw$m6dSEsO-Z{(Al zyq@qV`=ZZzE2M{M4JG#7Q0u6NNb@-Jwl_59u`DkA&^@E=)C4Pbj`F^NN1iUzx5Q#d`wH zdrv%BOzqAuezqq<{Hf8B4;4P-B)AKz634OSPmr697@EbtrYXrW$luGY8T+a6BGGME z>hRoiV-o4z5p7i^iW4YaZ8R_Tv6!Zb&MB|23FRCEyv0`etV_8()&9AA_w0#Pi+Xyx zE943OFYaIYy9;B7@Ee4UEIjU0y4s)5Ruioz6>S`LM)B&Pc@+cI1@77;rPed-8~nb_ zLXnNmoM?CYx$?)>;huQ|1G!e`^-gN;UCh4Mt6u6jy`OD{=`IVIVhIZ&n}gaDc1AW7 zFZ`V)B3SAcVgmC=3mKH*=ljmT@DBNYM5W)xLgS|C=-mWOIu!xU^qB@4R{1OMlEQmUnxfpY2edlrqDfuThdK_g#r^Y)ig+_KS0h zg}U!FzFWN0Jru7#LJBl?ZA~&!FP4jmqn2;R8?#M4c0q*We3x4?OZ4j<<*}Ki!7;;e z3%MuConl`e{@AC-nMS#zM8EGE9xvsCqgs-uCQ-ZwXkO)r=54xFIVrF0JZuwcr!RHMU*A4GBGmgeC0D`+#cPP> zEtZ^$Det9w@zvZyY1RB)dfrG{^tB&EVtlIS9f@5R#pEA1`0UOio1zg7)3M#flHE~O ze3WREq`dDY-h}8}P6~<_{*D$AtogMb;v0%d`;y$qe9!%m6=@L^9dfw}~H?|{lL{dY-9jGe-3hQsgl!?&Y&;qP$~!RAt#vRzBSGkn|` ze{RyWlc>$VUo*iYw}IZ|?)%P{k&HBN;|W@+i)~8gsV&KgxA%;$^)H)iTBP797)!V2 zw#TA)jS*6yvA0uwlmnNe#m#znt}*am3y^k>dT{N{v;6SkAnJ4irQ6NByuL8hM(HID z6qFp*onZ2H;dZXjHjp)~iA%kab7kZEA9b`$50^UDuPSUM>fS z7@F+-db)2>fAP+NNluwW2Z2j;+|dV=>1PP4l{k(%?+Uu<8q zZ2ZYGcA9pT!3;ObaBH*5w#&p*+0CVjPl}XvM^U`yXx{8$EmPe#Ez1SIAngO7~}yb+Ie|g zd^E*%{$}qDUxxRZ@t6D(gMH^aMBX2(c*DL|PB7!-)z%gvl)qMJ-g8&4g^!749$(PF zr?^?9o|Ps+Y5O`{07GE4dL(#9d(TzEsX~bY9{t$2AvVX#bWumoL@Ss|PA|cXH}4>whgzkIrRw+m7ZMs3 z7au=*k;piB^18d(Jr60NKBjxz8^2B6h=UE9w>+mxX!qOT-5NAmvlOb4eS&IT-7#rm z+-w9DPq5M?kM2DywR)Cwj#E{(y?Vw!EYG2ve=sy&yRNBGqIjswxC#{qTQqM8ljt?d zQ>$J5ll2|(L*>U~!V9cMI3HJO$N5Rc?hoD9=s?|aRN@ZDeqvsQtK);jyGwrU{oGgD zC7#y({wGm9`u)NV&3jLQXlksB>*;>6cWDFj3Hbpf5ka03$De-mPZ;Kj?eTXlKZJkl zY76Bp-s+os?Sn@@9CX8uzGYUyhTVJn%3XT_<*z-O_l#2*4SD;6&Wa0{&&dXSI;H5T z5!9wPEVrY1kn|l!ahhIWbb+Co^p42a@Pq#LcGwxCH zA7|f`qd^xMxvY~$jPI{}c-Zl%c5mDpA7a zghYxKMoI6R&hY``8^0ai7&k{W@6N8BA;+5HO{V*znp&jx3VaKmC$=8^aX_DdPE1*w zw%kZY!KpYHd*>isiPPs2*}_Ef651S}pu;)wbm9?3-)2$%I-z-^sc7t{W;^Sb*?8$4 zpWRS9s}t=|eX<$zibi}LxLYP0s_R4P%ijB)<##K+637%tReYwd z@s!hbrpwJrK6Gzo2VVz!i?E`v_wGoJwg?zqHbeRAisnr{n^Uq)t9tEi zz6|HrbKPSZ9%T51e3*b00rk5Schp<@hm+4gVcq?BO;x^Xmy2ljOloV|b7F=f8?DZ~ zx`Co2C|)--FW=l+U-tgjeB0`N#FgH>rJP>hqio8+`JrVc&&uPNlI8)+lJ4e2l_5fR zebo^ih7teaHWeabcEXNGZ)PyUhvUKoj+ytMo+4% zq?Kb%qzb+NdZKyhogbx)cIz-leQweXNF@pJJwtV|024hY)b;tu1YxwFVIsxcO0D06 zwf!r#XN>X-3o0jCBIvKkVP&wzdyN{KQ2u(Md0*|*3MNla8rJ2Wq|`da%+ZclA)o3c z!yg}0N>9zC^l@KPbaYkm-lfD_ZB8bPHJLvS49N^W671il(=L=Ud2|@X>y75UrBYf# zH^e0JJSLpA;d@MzO~N<+>Q6*^s?7@H8Pp$j$wG7%UVR8$(QhijD_I~pVa#p+=qhc7 zBS~i_r;|q<`aabM%`1JqU|YM4rCv+V;KoNG#P!o1x6d6ekl6Fkx#Y5nffV^;PpSlzzo*f>j>ol{;*MMiUpPg?*c9VXL3TNX zNXGioF_kB=gx0pN@TcfVcAxBLvdQDke<$+OHIGA(=xm(i9>4R0)g}DS&(=`9zG&X! z68D8zX`^2SqVY4=lR6laQdx5cd(y^YwKaoO<7=&N2Y5KVH%PW=a6NdbhfhNI^Icck zIP5-)=hKerygH8Pedi3CSGm&AZbcBED*T!MUSZ?qs|QA1>B#Z~+IW(iYvrnglh4sO z_0s5zU~xEp&-HeHOhZeU_bU7aT;#+(8=hLB-um=`|?dazc ze>ATS@ixWAmoigsbICQNXAWd}im~QL46g{9I@5oy&$=)*8}^)2?%XqeIf8uo(xT@P z11j|;F7L}77j;P7;C2k;%}eb?3;hF zN|AK5;<-Q5Gt<(^&nHvzrD|TSt$ZLa8QS(w(nUvPRm=bsQ1!QU%vEHkpHuD9bU-+LdnR{<+qp01AXH!$v#naH&op2Hl{); z8;X8jNB#~D(qqMQN*c>ce9irsD>$9PcwC56Vhp?_4>sM)EegRa3Go1&c9L)Kg)9}8~V3|x2664o^1{e0GR$2;5Bv?!Y6-%-4wXx8qGnZC+D> zS_7M>{rFl6bAEEEHtcqf%5{x~3}&dm-Yc+-R#UD!{jJPi+HLj%ztE>|A+B*+KG7Zg z!I`Wm-Y_(8CSIjc*$uvytGzb(-qf!p&zX(rKhPC-7URt8dV?A8Jy}17-`Hb5F*m$y zeBBP~6k#yfQpubwY}ak3k9XcX2gMtX=G9t$LrX^$<^DtO<9zMc*Dn@w_kCp)VRKUc zwQB(zsNg;%PH35rml_tZHoM!IO_4`h)cald*-OUu9Gds;280WvcrT)P#kZdrNViEI z{l=TUXK4S=h8x786Cv?5eh-}3Y#U6hXiq-56QC?N`ikqW?5uDhhs96=-X|t~dpA;z zF24wB>T@XGOK4t=ou?Cb-DopuI@9o&-!#4Xz^G9rN6f%bhTruI&-d90~ z)@7T|;QM1g3>&lsVjlb?)bM%p(ysT`L3|W%1e!OJgirXbT+lK#YggZek%U||CI zT;;O_tK5wjnue8h6620YwzT=)$G23|=3sER`^;IMrLZWAvIgOlb|iz9bkk80J^tIMOM5hfcaVvU>SVp9J;_ z^9NV4OBF&qO2>^_E3(U)=0!&yykGW<43T4ZKz~mbh33^7kL}_4xk5&;U(q|~!QO=h z9t9WMhx1(R_cMyVd@aD_izX~}g*_zZAX25c>Pg&u+_oyTjpXzR373;u?Uw2OD1Wb@ zdAqScua46MthoB8cTUW{=VTS^Gh;QjbSYN9kay#JD4`;qQBQ=Vn&I(F()aP+U}(f; zFME?y?`WiTPhA-Ec#7WFqtUz%O2@_m>j`@5be4AwOQdt?eClS5qo2{dC_)i)wM|N) zdSbh->HG8aRDvW$FYlT8CVoCD>@6&_cAm)0@m-YF7nHwO(Y$`1MOqP`-#__ymE&iC zk20Ic_SE9TTpw5m2{IP_9s9<_dDU9Ce~8{z>nlYSl;%`+yS6onvibXa8o5)umf7Ob z&#BkYyw>y{cDJ{8pJDM&v`90jI33Aee^cj0MI%W@svTZq{OnJMrug&MKh800lu{62 zEqDuMhHffnfBzhL!8!N4|5_8u-xxG+)9Gd2guui2XGSi01n#LjC#7UHZ&f4~SbRt@ zOznzAp!eCp(-G%5?N=!tW~VZzw-{eJR4rWPlh0&vw8jzJPJ`l&Me{P;TMJeXJGsO( zpK3mN^>8(lb6aMW>B+z>tC|?e%QO$4WDA-uUrB#OEGATD_-ouGQgJ-9gWy}^$n=b7 zYqz8}iuXF2m&~Fleey`RKAE52jxHyUUv!EMENfnE2b-sFnd;nTI#X^=zG@h=+mU6C z(M0Sits5S}b*0pwgRjh(Xhi}|YbsE@acEwbfnvNn*LebMqQKjq>Sd|r7qS`gD+doZ zPN#MYJjCNxx!>gVXprmum(lqB_g;q6RBSID5Fu;-lqeX=?m)UH3B?>_hL@vcQ6mKG$mojzN z)OK-_$<*UVx->8`HiNpJ`?<|$YCHl4)sHVkJ3LOy_Er>Vs?A($l1RR|;<)>e%9r5! z-7mgNdb`R`FczVBZ=!iG5*9oSUm<^V0?Q$HzQp`**QBjn?HtcT*gh2~wd%r3|)AM~Q~vafaS=3z|m z=9t|Uo;*ouN}J`Ay{95L-v7W7k8v=AQl*Axk6dz}on%toGhH&OT&LI=nno%V?`<@1 z-bZ!~d0CrEbM23(kA9awv|IT!`BO!|m(!Lu-+rk_UbM8ke=@!?`VD^IY&?sKd~NlT zYWN3k*(38bvg!$hiG?WMBsA};&^PL+aUowv8POin7%vP#YP#Zm>u+aHzWf;JTzdbwjlDOWnbS6u zzsYFc%K5e=J$<&OIkSP8zJrG(%;Mq?89(zYjPV}PkS2{Ia#vdxD5~#RDk$E&XkM@LC(f!?`V{Z6E0XSTEX2n=rmieb?!Uc@OuTwo zyLqtlffMUflGyVRkKea5oMH{>dU%H7$!Fo_?l+28?h8+&?%>`%;VO=^*lI%YUHB8 zt#0@?@yPeQsc7ErYg_{|80GAd{k7?{ms_{11i8EnBER>mXjlKfWa4)2ewra#!P3N9 z%30Il$hoVgr8RZoGxoJjO!0HKXVs0+zZ1KM<`wgadi*(lGD~MbHpjTL_9`RcE)x5i zfS>sloFq*@(@O_lP#1QVGB@g5NwygHc1})}>Fb+?-eNcy==ZtX&K&){>3uZsWRv)n zi#Fvs#D&9lq{D|4dJpFeFt=TMe86MU{hsU0eb@7rYGLK> zr;8amd;*xxuxH_Kg&bJBvOWhXm!$Ahu%t|`qT>4i&D%HeLy2?yqo9oWtZ_A>aZ7!6 zb6V;NUG-i&!A{H>D~0?Mx{1DXl|A**?60Z@J1bYmye#pDCDfG$M@FNxUbL65p6P$(bY=35mwRxqh!TI}X!3}<#~nhx8?=3L*GU*2 zvC31kAGABO+xN)3Bv!3Zn{|ITey5v(=4Fcw{KQdk!qJ?IxrpR--a(f9$J1H!XKIp0 zs;FJ}eloSFrkIb8JNrl`=(s*9V{gcFMVSJ+Z@+Sfn%|$Tl0Ulfd;1N4Gts;gpDDdf z9-oS_JJmMfzkg_|{&9F7DOu+Qp$id7K}N?lE|;>>jF~9kw3L^_pJ5>!B4>PVTg;Qt zm~m9M*6}RW#y#SOzgcMBG1Y4gb2qomnnk*L;kgqsCe>zP_{lxfdaS?q}Ewd^^tA*?&bEYSrLF;kY`1^}&H1F&5nG-7K7KUsM=btkh z+v-Xuyht^s=zjlP{q7OUsgBQ9-e+f;*eK}U5bQm|={PcT%yB8kS5f5H+ERNXeyjdQ z95(*`A_vX8IB|Wbm*)NGK&Z5Fp2F1{@8e-<=Tsgzr+UUoiwbF2D1d4ZRSVzWn;6k53`~{WYcQk6CX#Tf*M=3&d0heJPB& zMH<#B<)rk%Rd=Pp7kv+tkK+C7kEr$b5JiTiIeBhOHZ0wm`t^;Xj!e47@9M6JyH-=g zR#+c%8O#!rJo8berhIr{J_$eObDNxR&oz328^S`N!;Z8n?bZKRdtU(-RoAsWg5BML zV(XBCScr{cVWLi$-JWyy+H38#*Y0FtGjYAXK_vH&Uq$+E{9|Dv0V27ZM9!IQH)J0%BgJaBcd~bA zmAL(b8;&n}aLkI6J(qMpnD4-j_w7Q}d!4WLTU|M#iet4mn;$;*n0cmS-8COd?0wrY z+Im3a1d-g$V!59V*Y{pjR@vir*So81XMfGJ+Acvd#`<*6xjA-J8eF?guiA+%PBuw? zlsW1|_^w6YVzNXObA2+e!mJ|eCrqf--YS>4-?v39_ieL@vu`!A_6iK#*&*KEB*NV2()cR$|Uc`>N%+Gm%q^ zHg8vQV_=H*(CiHrmo94Rebi_4_iwA>7A(FaJ(uuc>BhoC4-_wTzR{+i%|vpyrIOn) zBCm5V>BI{CH%xRJGHG|^=1p%kuUx9k+{=oEU97xLeIMdp^lMqq!n0&kiuTy&lY5r; zpcW@%t$&;vbANE`);=jBx!c8Z$Jykl*+1v}Auh94)@V8 zw-O3Rg>=lGptawnfcV!ALT(1A1`5On7pU`i} zp1K_>y*zUB;!FDh-!99mRa|17uZnW%;ZmjEUUC$VH+P8Ts+NzOH^0rc$eXLn#62kA zyM%p>?<-ZaMlT!D@B038^0nQLpzu8~lV51HasZ*nw0R!a?dc^M8S)t`utCA1*=}rz@=rb#4m3Bj`xm0h{ z>72w-I@x-Ap0{t>)ywnVr&s&H(lZxK70KNtmiwsBJnxRpj(&J=-6z-L0}kJ6hiA#u zW_Fc;?b3Zy7A%P?);cQp*Gm4Qn%`|UW5ni|c8T4qo`1Az*P`VIGey)}s!Q1~lDk_h zH(d6%%-R_%n;rS~yy?4?r;C#cRh`{`cJ%{Ge8MY?TfJwwd*yp!!Qsz(m-DrI(Wlgg zPCgy-oIRS|BetP^_alSK7JDj^yGJb7W!|{H8+zL(T-^KD?!r!A0vEn1?b)k-Qqa8l zPB&NF9Z>zD>xa_Yj<4TZX}|@q2Q6RBS(feonGY^S;x~S}UT)6Z=i>F)y<)k#Q|H#) zDAl#V=$@`w505Ti;^Aua@9M?IB#w{vIUPLXa`H`euxxEaoPCM&PKrnMJ3D+`wkw-* zUH`xlb$cb$8tEa@cb{0U?~=_&XI=9CE3DC*W9OfD%2#*Zs&T5BkJ~;gHRz)6CYuQp zV;_c9TH32yP~V~_8-M@4cu7%pd+!s|;-#b$Qk)B}6ko)pPFD3nIw{Bvug!~tKZ;mfHEo-A*6ozZ`q`<&Yc&;vLRDIJzL~M3LO1V!2~RU$UCJxBn%(J=%O> zTMFl>=&GF6U|HyOuc@!5haFv=ZOpm#Tk^VG*wN$F-*tSCy$p5Tch@y?d+U=`cGb&z zFnhuZk=$cqxgS)O?*}aE<@Cv_-rqIq#uv@@_{PE-n?9X!Nx0uN+l$NNrmSq+Bst;o zm261^qXrkL+#uJ2kFvI14_02K>)$a*zA{!M_qbSY@U1~E;iFQr3~RHpcc;5Gvc2sv zy7k@rLk@n}rToz6W0>2g>M^~qu9S5doqJsT!DkAuT@Qce3tri6&CZzx8$9p2LcIUs zgjlX7ccnew{fcBCHNV}!o&yThE$7(g(b`QKzq|*oKX%;7SL9He?`@8Ej~~5y`bwupk3{;O6w7tnSSYLehUBLuqf3|RrM*$RMHR=_QA?%` ze1FXS`J8KmU$5>z?Lw_0w&y~sjb9XAd#BaNEfw5{Sa}Y8TlxK~M=L9r6UjX#mfLT= zBI#1ftgboTUwie+->Ut3UEu2_s`4?r3bs+z@%P_RFLC|nJ})xWt6hA{oRJ5wM}62h zFgRP476l&mYjpke>inBTa!-rpIvn({-;j%XSh^+kS89@Xxv^`(!)TD!d~lhXM3EAjb&WU<^Q&08I9zBIO8 zT&!k#?;iC=)TlJ+T)y&yj})!>b4|#$hqvSR9@#zlNc+9P^1HrKiDA1s@9}i)-ymq{ z73-m+MrIx#BGUJaSnl3&lJ!;Nwtc>EziG}@IfHLhO!0gWRmJ0xa?XYt@$0|Wz5Y>o zB-7{tMLXJkns(5){jK7@gD=GHFDW^o*mkSu-8Yp*a?gt8cJ=fxH>SCJIgh1tbWS6E zQi}B5CRsYheZB3}bFZu-?+@KR;?}2K8(*J~84x8cmT=T-q~qQ-@2tiiNjl^@{`K3} zV?=V#iRJEf4?aE5Pnk5ST>bd#HAl}Go9X7Pp1by5%{Eu(`!?jk{Fv`6OJ_UeP|tnA z7wQ7^kAvpKTpw4U0lsx?*>or9gk=*lQxoc;1_DtyY=DT}=N%^fjF0NUr7=ClA z^|ZBRk7QbKVj^)_FkLswPIT5wlC_{e94WExqVC* z#Byh>d>RuNvna>K!AFPH-!s#7@QT1PyEo_d>m43j$jj|Wqa#n$(fc=T^`5q5)=2q{ zp`RKZ@4U)hGH%wv)wZM89K7~Zr0+$s+)C4?T5qoUA*p$`)3Fn)I_q`>Pw7+fc#mtR z&eiT#aDV86cRwQvNv=$u^~n3BbkV2zWv|HJBuO=1F+1ZYja~O-WRghkC9&M%ipib& zw(r&=AudPDrH;1p-k&3C`no;T)r{CPW6g|Bdk4Rcsk!sgvu$2+S$s?DYLBhntL5>9 za~jlm^TMw|{K!5#L~<{S7GpijxPP-LxR=wn!O|XMV?iI1zAI%FK=yTlH@l>|N z-TTkSHuesQKisL`vEIiY{P(fZfG&9Wv9I>^CpGw^gVKa?yG!5?!-KrecrCprDcQ3bRXwehLJ&rvt?)BEY zn{$KJJKSuyG#+?o`OA9ltJ_MV2m6cU-Vn?Ew&_II%4^R0+_Sn`eC(H5WA_y4Hu${v z`8(_6b-qMx$usvy$nE9L$E@#IzfP4R?&VV=zn`vm>}sJby_=u+`D^gmp5pP_O|jfu zrK@cVSlF)C^PY!K&2$_Y`7-b4(-UTUW?gf6Sii^@zNJQ0j7SWb^7h4=^7~%29ky(i zZQ~rf8$an5<>9HGSMhP?u_AqMiRI=E@)>?=ayZ~tU--zl+J!zB9v|2-Ew zeRQyS+1YyCPWP7uCcpTRtoq`)rR|`a4RXfTdg`-%mPqbhvD~=H(Ys1SZMqgy_Tyih zh8&*1-+T8D-Nhv(!`39nzWiaIyT`}p)vsB-*%N(h_pMsroF84C6O(m+&%D)bdIUs$ zditt`NbWtc+(OlIw0q}Lz1Bs|RYi2PO_c4HEz4DM&pXk_-oI!yEz!SHO178R8yB4Z zpx&zK&Wpniw$5}ew_TpP!}bIfsa^1M>jomZ_r-EgZire_!J}RGYcZ9YsDt}f^*-5W zXP>R@@_3i-c71eMzJ3E;ulx3lwOXKCaz4TFQ*_Fxa}SEn-+C>JN6oRl0%8k_*IOQl z&@TJvx-@ z_LRIck9}`D_|99KTZdZYSX`-^NZ*HIxw>b&ujiU^W9Z~5t@A<_Bbu(w}C8;SM4?PmgwXR%d zpnU(|=cg2{e&l|Wt0%5&8cK4Vb$NcPcG;q?OJAMwtNK$>S6V7+V3nb9%Z8rZeDy}M z&&TmO~h#9;BCme<#F@P%s7$AfdDRR^m)~W0Qa&~2ll*Drq5b6=iR1$OW#nCBR{HO_k?qsgIn>T( z2k4pc%dmjh0+e6EG;*CzA=g}}&i$QAatjU*m8qnPfYLSC-^`2_^JKhdSm58b0Od(P zg*sG@=doH`8~JbR@c%nJaaqk>hiiYSPR|Wc{r-R9M>df8t2K0H@>%`=oB81XLON%} z@qd;DOiVNV&r&i&n+ywNSRlg!85YQ}K!yb}ERbP=3=3pfAj1L~7Razbh6OS#kYRxg z3uIUz!vYx=$gn_$1u`s0vQ&_ut0_dGA!_~S>V6Fo8q@a_-%%N%~%-$ zWmw>UfdziM0R1+@f8Pkdt}{*-*q`U;g+ zCsQizlxqKwK!s9n*GVInyW2Q9*k~040=?z}gnMl0-UD)@^B+3^ z`jPd>4QDPTV*&b+B`J)&z+V9Uo&e-8A21%E-&26xaIRBAch`~JX8^es0Hy;Z<2gWX zIQlG^2#|~y0J-6)vV`ubCjT!1ayvo_;5U|p;g_?1xU-WxQq4^I5g+MH=|T12GaR1gZly0VzQDF3=q{^mp@|0Q&nZwE!2u6{rnRzNib(9kTTI zg!2KEFX--yB0y1q?tjV-{6siE0J=Zh8lVW$owncc`VDvwyaV0>l#hAIphMt&fe=6mgaUNdMGb@j{Qw-Rm1qGS5DxSQx&noPB0y1~7*HH2 z0pLinq%=?lz;RqjIlu-e4^TQ$dQ%!w+EV&ay4oU6bmt)5H{t~}2Rs1Eqx820N&qE+ zc0hZ;8=$=U0lXi9Hvr`)$}5y7F93&teE{WEx`T5QuohScj0VO6lt0G{&;e)$v;aJTCO~7r9;gY_23&y}fCJzNNC7**32+8*luY6RR0FC5Za@{F zDo`1y1lR(l5Vz7mSHK782+$q%pFnE`90ra88-O*y-@r5=7MKCd0%Cwkz$joKFbIeQ zx&xhojzBx0DS+c$lJ1b-4d?=V!S`37HE;x&0;~j90gHgaKormgXb;o{>H+lux@))% zo>PH1pdsJ^v<2Kjqr0~rs@&?&(BS1FX4^Y0Kut+x9xH*smumYeCs|T{-nH9(aWCpAO ziXWvbrMCk>=}qZg5GVlT2Za2d2k*IooB+wp1&~`!fbvaspc+8=p$bqLs0365C|^_n z$^$k)Ie^L+l`|@DrGSz^A%Mzeae&HY5uhlK5~6p?w?e*bhIfhwr5~ju3jJ<4l0^=6Hb8k@D(az!-q?$!K5{FdP^L zL;?PQ4DbVb0o{RaKv#hB9oe=s&Xy^Vk9sEAe#}$UgSO*7z>bn#{onmJChs5gT5yMl*VK? zN)zIp0K@>3fGGgUBEJHi(vi|oNH1}iBuns1VUfJ)0HqCuEBGZ@r{_F? z!W{v02Ic}3k2wJOq40@^_-6yl0CHadECm(0j@!SXO1@-_tfgM01upQV8YyuMa?`?Q)0k#71z;0j{{}f~r z-$6hK=P=#{9Vk4KP5N8~E(7H65EkAOSCb>J3o6Sx7~2JQoQfqTFM;344i2LIu=fjT$% z<*e`P_R1DYhfetWRjbepXBVlKo@lsj!!cWxAOs*6q5 zio8pG{#h=$(dj;mvwXM7>cG2D3CahagF)f<8rLth*e0td@1nyqFDOg=ude=?<5N4E ztbx4C6yC?}ibeA8&a$PmP1fN8k6cS^l4f~wpAX$Su&hm19q+OTu1wlI<;s3ZmDgp@ z)XT}v$qs6)1En;=$=0serSW5yl>^1W&c)7=OBK>>?tqnte^&Q);&|%VxiVYB=F!Kp zR@>#}Fzg*Dj*#Z$APG?^!XQwxPv_kK@4{`{f#PE4N&yLXZRJR~G-LYKGZh$*D}_U; zLDCjhimq8>l-!T;)Uk6yU4|sd56YdgN|#2%UvJHv$sjA{^4P-dXet$Bq&X>sB1==nQ`-ZfCx^U|zO_RqX8+sTgx%05sEgJ-W- z=M7Gzm^DcJH+$Hy3P~c8B5biIDxiUWA=cQ|`K&fTtNGTVpP$@zc zTHWj$v0J@IKXd?vQo#*vcV;dp?($f6c*^T{{zP$POnE>dTWiO8{@Aj-;$X%D653)= zNbAmhp8fnXS@wa2<3JP}p5pvrQhdiFQ+15TnY6A33R$$>+A|T)FO_hy%H(2)2q8TO zsskt+NTja!p0;Q@bRT$}?VKp8^}$0Ho!m>-+f}`_y%?I zXL4`gh}fjhAw;2&YDuPphssN0m4IJHIxJ6mHlw0gO z`2P4eZ5^Qj!Y7Mv0Hq?N4OrsetlO}~J(1dchC2^RWl-+R+6?Y=SLtA&d;z5rD2?m} zhqo$sew~3*E*t9=MUS4=rbUZMH!N*eF{PWH)de1xzS?i}v5BiSk5K)K6Hdo^w6tzheG7;OrvkPR8shNN9u zHF;C?^A!e46;LXGVmE5o#FXX54jU*fK_QE_*;}MQ*_`WZ8YqWBDFRB7v-fL$IUO0# z@-@rxl~6<|SKa(MD-C{r?8-yNl%Dk=R$x@&| zXVSVbj7BjX9}v57=hdUPcpemc({*A+@KD)aFnULmmEZIJ4IZ>HR8@q^H9>Mb-~C;1 zp4HUA$)GrLrO_TdFlzME&;xUQ9(f<KU4p?=8ybL8tti(vX7+LFbTVt)K~Si20c8*<$RyF#?LEJJ@-6&^ z@h}@Gw9+7@+D{TOGVq~YyKvNe%sSu+EXHY_bN-#HBeUIe2E~aB=P4*uTb|6_=6v_~ zm({E?5y1s%8Yt81`r+CCZmV++Z722w57j%cwMHJURRl&#@>Oissp0gRJs5>$g!HL^ zR+dRygDwiC+?Z_D7PMKqX$9kPw5x-b2^320dgVNO4V>D_i&4;SV}x0Pi|L?eK_|x+ zd|H9>8*9+h)yh_xszX!yWi82tQ?f{<0>f-Oo&ovM zEUMgX0w|OW$UFX^P*3R0zLwUbw>y;wg>t;3vt%eJWVg@GeFInaY2n7gVW|+qhhuZ< zfXnMDiQ8B>OoK%{&y%g=3n{&$&a!Zr4c3D~<)_1?jRzJacY&=DA6H7cJ)o2W<>HSQ zbGo-J8_P?B-EM+X0F-HGN(F|r8Cez-bc85}yyPi63qGpyxMq8*#h@8cC^AUa=p$LC zHhY&l=KxTs5&@+IC@2om&E-#Oof!U%@+fpB8`yzD<#gMs$|)1i>^}ht^)|>l3aLUB zsFpOc&h@SDvvqkvakfL+VbrPW7p~CAHRaa!pV6n*Hx(#UzfoDxO63D|8d=Y%IG1ii za#KuMYNOO^6qHdU>l|I{>?(hq>_!<5(!!)l^lEgH_dVNB_^v%hbuZsjtpnYVfuk>L zO3zxjwG~&xG9DAX8c6d750!;ypZsq0E|k3%q*2)hMYxl%NXrLZ@=UFGkLl(@G409Q zAnCG))wXi)sgzLeMSOxmq55EbY(>vbHgN$=Hk^lj(w`A@azx+C4umbf}*L6x3m) z^`J6bPV^{pYgXMo*`s(KP?AB(1Kn~y?pmhdq6uFZ4_{Zw2gni5%9>rTb}abhl7S~o zs?$V*GOTNjVt>c?3^Y&%+i>~7t<|v?PIF6A-l2SeoY+^ZR?)(PSJKK0Znyj2WE2+8 z81Rs-zg=o&)vVL0v7jI}q;*;6sr3DV7QpeeTJ4%{X9=RU;)!pUV{kEv*eeA&WvcBRza) zZkQ8BRX={tUJpNP9Z@YC<6$;vV9Vvi?NbKdYP=|dauwxKXl8X5&$JW0XyQR?{{V&RgH!i+h0Th2&$ac;Ispm| zYXY?g4qiJx{Ux=hd?_(H{&Aw3oR+0D$cj%o96EYg{&!#SptnvM80`hHIz+3KX{nSv zpP!>}HTlF-hM1;r0a^Kh*8fUB1f8*e(hn(v4ms5!>#py3R$g0^Mu&VV7|kKfI{&21 znJx=y$63(8(Fs+#qa+X)VN1iqBzYey@|KMErrsdsQL|;C9lH0FL%Mh$Z!62clw$0aA%%{-6t z8%hEMO8kRmngF>@aUK-Wp(9Is59pfVj z(`~)!9;E41Xd>lu%BDm2OP72W@58La>i7$wQ0{%LdtGBn_d6ZA@f@#p zhDp=6{$yISS~*M_Dhs39zjoEQxUCM$K%xEtm`ta(Y3uxx_?YgKo9=o4lYXyhtxen7 zv<*zBw&`$8TgP{hCZa7y*hS7gGb9r|B$R_BIqTZu+`vgF}^<~v>jt_5Hjb`2Xes5m%q%mC+z2<6Bmwg}F zp2>{a71nu@R0M^_jb~gpH{NsVO)mqbJ}8)!iO%ckVO;c$cwj#?TeXULAQ8N%7D^& zlE?6Mt?t?yC>`9m*335abMMiOTJ^%Jh%*@h4ERwGMObID%IXWh)CcPd3e8gpt4Rim z4ivWj!>=Y8C;@U-up}=oggtJY_t9&XrYyDRKx!dKo40BF1jpQ23Lt&>QRrGwD97)8 z74f2W)8`YR8~Om~K{^%ZbrV*{tg`On{ifI8Bu|;bYb~s28F+5M2j#b>tA;i%aPAAu zzp=F`2gxH)C_WpCBrj{I*hnKI%;Hc}E8K^B<>RD)#6|ZhKFINu72oqbL#u6`yQjbi zn%i)sZm+Y1#&a^IR${k%yIo_asx(*Qh;AZytTAe#-g;b)()p^}l|2m#i>Z@is9FuZ zvF1Og*|$aQceVkAbVJ!u$z>X)JW{f4#(Fz>bTl{f<3z(YBQ+9@^uUv)E*H+lymeFs zi+Ht!G{mP4G%yhkN>*O*6o76~j@v7^eH%@%;Wr}Ih7p-?A{ zid1LtP@0b0=q8mX)Ea2$hv3?C7N7dkw*_>aTNh$w4!tJ_N&EU-o#@`nYUlZv*)ayh zx(ouUE$ImgX;5h1(53;~9MHq(C@w~Lsx#@_z7NX1zmr2u*Z_9B)qvBjQv1Uxm3O?s ze25UvKgpwr4l7y0I;~aKs_tA)PhYa!c*;M?*QRq-dTD|No(PX}{8{zdq)u0F_NO#O zmFOaM=)zNOj9QSAtbA64qwU{#UI zk6ha?T#mV{i_Y&;@@%du2Zf(OH*IUSB!cR+(*D)UZOVr$!Gq;N(s~Uvpn2FCKF90E zsoK!22TwT;3g!5-bmT=Eh~<1L!rItYg< zB*{7tE)_x=#E$KE?)qWy&`Qd0+FFoiT5Ho9nBbvQNFN`pVUuotYPHf&rj2;LF2Ilz)7N}L?Q*pVw?4OP zV(X?GO6j&+Wnzu9BliA+Lgn<@lYqop-Mx`M0tNFF$`I5rr|%7OXkE0&W$12e8j(i2A?40BE zmA4x3(7G8Y!7{BhP$>(Vc0D*TkIyxfV8n-&A9-_5YrlRK8+hc(MxxzYIK%qM1 zj89y0%XbSOu$e~mAz>EUSd5=t zT{^T*>d)lt{aSdrCU$aR{0$*{a?5vfY5f;v`X%bLTDb;)m8a)9n_(RSy*@pMZ)%rD zy1AUlG$8Mfv^!bmTXXjQuy6M5(B8cl6J6>TuKKx6-XzZT&wT18AN48u`a^$Z~-;&yU|NRl)WQlva;fnkLEw5$5Oe?j_%R_v}2exQb zn(syUU!JjDdFyon|4!(Mko>Foqp6k846WynZ_@W=BU@GS#}UWW_$K}jkz16lTiT8s z&in6p|BPnJ-QH!V;G6o#o7Q$8wW8zXxE1)$kMBp1S2z{j-nH*Gd{bX|SN%g9&nO#Q z2;ol>R>vd1$_<{u&pl56d;uBms&yWU;w2aDr+KX}*s zVdm55N!+KN%Gv=vk$vfD5h!PJ11JB<{$NI5tv!2spfIYSp56J&2-u$PKH zq%L;Y-eji>8fb=>+b;z^?nTNrq7V=NtyHMO2S^9F)=Kp)(}e0>0%V#9g-YawcM$u5 zhX8eiR^&-=VZJQtCr#zuplvE=gYLgB4-rc*4UWGfOB`Q=FtO`Dkd{g@gNc7f5|?z$ zzy`HMj=wJ}l~VegVUR=ll`1U!6*b|N>MnemNfBazeypP7Ht|vR^H8Y+WQNNlO}1kV4UC z&|h3uC8Rq-?k9RIYkvj)tR#s)rQhgZGV4repvCf=u07kIMbpGMKwqjZag%Dm(Xyn(zu^MoB{OH z29VyyJzzdSqgDh+nbO9+i0dB<%J5M)sg5W#sa)o#un?dW!I8J%KuaFU0+xM-h4~}> zEW|;h(E9iPb#JC^&)H4uT*qO6=`aoLgz+ef+a%*YB4pZ7WF~tZtAf zDkdJRoM^Q66rfatPLCqgYz1u0KSB|+qZDJ9L50vm9!mc0@i(jF!aE-ZYI46wK3M9` znTur_uR?IdCPnR!F^GjKgKd=r8+%HzXWC*VlSW(c@_Mt1(Ng;$a8ta&N)H2{K%}&l z>Vh$R3ozF#8}rUtK+nw#&Kf{-Ry0}xigO~Q3YkUhEXpnaR6N&TNh6$UT|<5S+oIDH zM3M4oD1RP^P1)k&!RRS}9tc_vsi6{27gB2SeWFPUf}Y zJwXWnhJh7ztjvckYzGCK@QVHpI!VMwR-lt-QZfZ5t<1E!~Ir_LHXzhA+%4#f&utbPhjHTz(zY5%$v=KTAcR0jx7Fcq=umz6+_&kBsVwC6ni6G zL|n`mtaiY90XSeP;rl@;ckv~p<}R<}}7v49xrr<9xYkZN5? z%;`@jXoAEpY{pwFcEJjnG(a9EN9&3Sa%qr878abAZb~yOV~M?DWh)5FVWNm*ACmZ! zW*o%d+F*6KGC-;g!8|?RG>geB&BYE88ih{oq2P~!*`vB)3${{ufI^3f{7{)HGAx8G z3<~13G8N`J_!R z`$6*R-zkwT);ywsz$^MVbMV{@vc_DSlbc42i0D}n-nwbj2MlKB$}}WEITjF8gW^`h7h+|I{CCg1N&d7m7p~cf+1PYPghG4dL%=w|% z%R{mJg`~l*J`2$n=WlR|KUvqtQbj0qn$wmW$TCG@oohN+zU(L= zM^e=GObDW;GLW zgD1!^d`M~E8I!_lW=n)XMUOMT>06_ai*~WPWm`Fu||qWvAmbYPF8qOKGGm6!{GYVa-G}wMT@P+JS}0 zROb@HPaSGTnBEWM=-*khWGVJ^j1)}tV42iXE=xbtfG!rF$+%jW-`s==3%QnGxR(nQ z{kPc~lRu0KwfMJR(oC4b0Gsd%BeEqQDgZd&s?r5w8o`_y^`6L%`VS_?Qs$#^mmisu zd!hLxeg;OS(a0jDs7BN(b79k2RtlD$zm#;`iCM64FDPJ^$M5=y2(anj5gKikwNNGN zCndm|X1<}e1zzDiFgS%*7DJZVSi4UBMl;6I`+)@gJIfW8^0&zN;1zwLZnQi@CNw8t z6<($6jEsc{r>_@C0-d0xI>J!4%|w|$Z!7R&zDhr(#~qMG<)jN{#y}rat239cMZO?U z^z}<76a@!v(bunaMfmf)6fpm4h>4l_8`-^stveWvx>y{>rmCV5uCN+g+s>&L4s{@( zQyZp|Yh)No{K7i65#J;=y$tFe@O7cNn2APPY`g?v+*nzk!sfV5jin$Z&FG4&{wTiK zXr=0p9-GcwAv1V_D8mOLMdw{0#l3+I6&fd-`ZlcZu9XF%KkFABh=&=C#oi!U{K*QT zrJ4ukqBGoJ<==j(=%yQlf}agW5g(c|Ghf?@xl^YRJ8n(f=>JQFLp$bY=LKKTKzKzI z+_*XZ0F+(J%MHRQa)=OKSt+vAT#MsjWatiYMqGcXmn)V`T^ERAJs5Uf4cSNRfo;$= zlSRaSxhV;V<6f9DmZC|M*!pgx;p3MoT5;G+PXx`LETdQoSO74YJJ*0`}LNzBP= z!~M)pf{I0OlRc2ay+8$iutY^0vm7+1#7Jh0nbs>wOT*2KYN^%M>ka|>cbJsd$WKo5 zEvyw1_I8?4%7|}>HR8%DEmk}cCe{dP3$hux22Y%pJO`6vsbUeXKLDrj`b$*{JABWW za0vgGIK)YeDu8&g%ZChUNk=g!jY!1vdJvP=i8biB3*pymH*UfaqPQ1iUFx|0I=`{W zNM5nDbCk?fzoVPX*fc7H8+B*H)H=VRIoAyHd;7@%Y}-Ho%}U7}wt&r<7{ zR#`|(>x7JGxs^?20SHO;jr6qKLFdo@gO`7U{MXW3sCeh>yKs%*Uq*P5QD!LS_Q?NOhVBLfALbfp0kVbXr~FcEMm5 ziV;_~0Vb8ZXs@sk2niAIz)a;|zZuDhYkKK=-)tYADHcZjmFSaZM)su{b2b>~_XM-u zJKQ!agIK}wp9*D$L9!VnGM9fU4(g;5M(XMF!mmbGoWi^`vC}^mXi(0OwSHfiXe$@5 zoXF*$iZiIDFCzv~eQ|fWG(Zs;7@^jLV7<*>Ubng#TXGj!KsW9Mb%0QwX*L(jx8Xq; z&4tQn35}n4;2JckTx$pc2Vyb6PxTE!y#G+OT9~rn?s$NPIC_C&O=@L`f^Xj;j%pBL z6lmvfb~;k<2EBz>)Rg?{5y=tGfnxZ{ze?#+cM*wwi^$wk(&e>)!h$|*%7(R_bf60>kQlx2;*owbta5~!Ye4whDj<-5L)DMlDp>P~QyOX< zK~ROO!?hMS4B-k35`wmt)-rJChxr}?M&)URgWZU$VYp%@`=yI9iw|dHy%l~*Qm9%D zUi^<}(DjJsW1%-Wc=Yd7h%C3B`s@!@{X0!LU=qzzx0q(Yab*fP`8O$dV~PcBQx_O; zr*?pS=t33}!WT4-p6Ubh`vc4*L^{8QP{7Diz*5dgCBnc?T~+;_O?JQMzc{G!sKsdA6S?KFH;^~n#7_3vC(z>KURIXIe`Xs42A5XLeUi$R*I z)g{$8{;GifO!okq!`7z+yWWHU!l`ZaP1PX^Y|5c)%{6p~gcjR${B^h?1aBGz)_(`e zHTZ%n9Wf=#;tQj{040v65|@iKSQo0~1UTU$T-4*T09hF3JJQKF6W?@x5$AMnD2|pl zy;)ESaxM5kCbPVok&|H%_A5NFAG@XmT*9kiz1WOx3w`RW{e zq72M&iyRPd%V{hm5^2pR9g4E$`bW5m1$@FQo64{hS3~jRIk~dP@(ANq;W}&oV7b4! z-I01fkfDD^bS=+R2{*fdQF#5OcGgsF0y)M?Fsd+1hDcpoL5?Bc;XWn{DX(Xys)+Hj zI*A$`i&a177uek!tj+{4dvYUaTo7d;V0}LujQV#eci9}P`pFUfqQF38MAXA7{Ott~ z=0?*RRI{?4YowIh+i#{qNaYWqrTR`6q83>uRK{%;#NQK8%FT8n`Acsg6-yNC{u?QG z>y3rjvkfSmc<_q8P|W$kyqOqrcHlJyKmR6lYHqzTiSC z;-VgBOS}Ftt)&bB7kg6s%~d$s@USqo2Kz|a0*aaVr1nS=O2vulz_Lw*dx5|$yh0Pp z)t1QiU=@9Vo3HGd`ux0?1Qagx5v5R={Uqm~Nm$tpEi9>Jh?w&sU6MuWswU)b$ zoBk3X(Tz#MeSE^LlENK$!d;TW-ysujXBBqQ6RsYe!|~~ z3*+Ul)Q7{TV@I}?wIg@y7WWWm9nqh}V{yb?RO~(~Tw}$axFC!@J@KS_s{-+)d&GwG O-@;#}!{`5~-~R(gP&ros diff --git a/packages/lib/src/values/html.ts b/packages/lib/src/values/html.ts index 02e3c2a..b223c4d 100644 --- a/packages/lib/src/values/html.ts +++ b/packages/lib/src/values/html.ts @@ -77,9 +77,9 @@ export const findLink = (el: AnyHtmlNode) => { const tag = el.type === 'tag' && el.name switch (tag) { case 'a': - return select(el, 'xpath:@href', false) + return selectXpath(el, '@href', false) case 'img': - return select(el, 'xpath:@src', false) + return selectXpath(el, '@src', false) default: return el } diff --git a/packages/lib/src/values/json.ts b/packages/lib/src/values/json.ts index ad01ae1..72481f6 100644 --- a/packages/lib/src/values/json.ts +++ b/packages/lib/src/values/json.ts @@ -1,4 +1,4 @@ -import { get } from 'lodash-es' +import { get, toPath } from 'lodash-es' import { NullSelection } from '../core/errors.js' export const parse = (json: string) => JSON.parse(json) @@ -7,5 +7,7 @@ export const parse = (json: string) => JSON.parse(json) // if result itself is null, the key is present. This is a // valid scenario that should not raise a NullSelectionError export const select = (value: any, selector: string, expand: boolean) => { - return get(value, selector, expand ? [] : new NullSelection(selector)) + const path = toPath(selector) + const fallback = expand ? [] : new NullSelection(selector) + return get(value, path, fallback) } diff --git a/packages/parser/src/grammar/parse.ts b/packages/parser/src/grammar/parse.ts index 286f343..475da48 100644 --- a/packages/parser/src/grammar/parse.ts +++ b/packages/parser/src/grammar/parse.ts @@ -113,7 +113,7 @@ export const objectEntry: PP = ([callkey, identifier, optional, , , value]) => { export const objectEntryShorthandSelect: PP = ([identifier, optional]) => { const value = t.templateExpr([identifier]) - const selector = t.selectorExpr(value, false) + const selector = t.drillExpr([t.selectorExpr(value, false)]) return objectEntry([null, identifier, optional, null, null, selector]) } diff --git a/packages/walker/src/path.ts b/packages/walker/src/path.ts index 43b7560..5531e38 100644 --- a/packages/walker/src/path.ts +++ b/packages/walker/src/path.ts @@ -24,7 +24,7 @@ export class Path { this.staging.before.push(node) } - replace(value: any) { + replace(value?: any) { this.replacement = { value } } diff --git a/packages/walker/src/scope.ts b/packages/walker/src/scope.ts index 0a6aee3..3632d74 100644 --- a/packages/walker/src/scope.ts +++ b/packages/walker/src/scope.ts @@ -16,7 +16,7 @@ class Scope { } export class ScopeTracker { - scopeStack: Scope[] = [] + private scopeStack: Scope[] = [] push(context: T | undefined = this.head?.context) { const vars = Object.create(this.head?.vars ?? null) diff --git a/test/calls.spec.ts b/test/calls.spec.ts index 2a6e920..6a618bf 100644 --- a/test/calls.spec.ts +++ b/test/calls.spec.ts @@ -212,7 +212,10 @@ describe('calls', () => { Home: ` GET http://stub/x/y/z - extract #a -> >#b -> @Link) >#c -> >#d + extract #a + -> :scope > #b + -> @Link) :scope > #c + -> :scope > #d `, Link: ` extract { diff --git a/test/request.spec.ts b/test/request.spec.ts index 6be4d4d..e20fa96 100644 --- a/test/request.spec.ts +++ b/test/request.spec.ts @@ -171,6 +171,18 @@ describe('request', () => { ) }) + test('querystring merge', async () => { + await execute(` + GET http://example.com/?a=1 + [query] + a: 2 + b: 4 + `) + await expect(mockFetch).toHaveServed('http://example.com/?a=1&a=2&b=4', { + method: 'GET', + }) + }) + test('cookies, encoded', async () => { await execute(` GET https://example.com @@ -502,4 +514,13 @@ describe('request', () => { expect(result).toEqual('jZDE5MDBhNzczNDMzMTk4') }) }) + + test('selector object shorthand', async () => { + const result = await execute(` + GET http://get.com + + extract { h1 } + `) + expect(result).toEqual({ h1: 'test' }) + }) }) diff --git a/test/values.spec.ts b/test/values.spec.ts index 7a5bb5c..6425f74 100644 --- a/test/values.spec.ts +++ b/test/values.spec.ts @@ -487,7 +487,7 @@ describe('values', () => { const result = await execute(` set ctx = |return { '12': 'pass', - '12.34': 'pass', + '123': { '4': 'pass' }, 'true': 'pass', 'false': 'pass', }| @@ -496,7 +496,7 @@ describe('values', () => { str_s: -> 'one' str_d: -> "two" int: -> 12 - float: -> 12.34 + float: -> 123.4 bool_on: -> true bool_off: -> false } From 72a958ab3598747dbc76549c78a90e548b840de6 Mon Sep 17 00:00:00 2001 From: Matt Fysh Date: Tue, 9 Sep 2025 15:10:55 +1000 Subject: [PATCH 3/3] gh actions i --- bun.lock | 13 ++++++++----- package.json | 8 ++++---- packages/get/package.json | 2 ++ packages/lib/package.json | 1 + test/package.json | 4 ++-- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/bun.lock b/bun.lock index b2b14f2..0ec4fa0 100644 --- a/bun.lock +++ b/bun.lock @@ -4,11 +4,11 @@ "": { "name": "get", "devDependencies": { - "@biomejs/biome": "^2.2.0", + "@biomejs/biome": "^2.2.3", "@changesets/changelog-github": "^0.5.1", "@changesets/cli": "^2.29.6", - "@types/bun": "^1.2.20", - "knip": "^5.62.0", + "@types/bun": "^1.2.21", + "knip": "^5.63.1", "sherif": "^1.6.1", "typescript": "^5.9.2", }, @@ -28,6 +28,8 @@ "@getlang/lib": "workspace:^0.1.5", "@getlang/parser": "workspace:^0.3.4", "@getlang/walker": "workspace:^0.0.1", + "acorn": "^8.15.0", + "estree-toolkit": "^1.7.13", "lodash-es": "^4.17.21", }, "devDependencies": { @@ -38,6 +40,7 @@ "name": "@getlang/lib", "version": "0.1.5", "dependencies": { + "@getlang/ast": "workspace:^0.0.1", "@getlang/xpath": "0.0.35-0", "@types/esquery": "^1.5.4", "@types/lodash-es": "^4.17.12", @@ -90,10 +93,10 @@ "@getlang/get": "workspace:*", "@getlang/lib": "workspace:^0.1.5", "@getlang/parser": "workspace:*", - "dedent": "^1.6.0", + "dedent": "^1.7.0", }, "devDependencies": { - "jest-diff": "^30.0.5", + "jest-diff": "^30.1.2", }, }, }, diff --git a/package.json b/package.json index c32c2c1..f7cb58f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "get", "license": "Apache-2.0", "private": true, - "packageManager": "bun@1.2.20", + "packageManager": "bun@1.2.21", "scripts": { "fmt": "biome check --write", "lint": "bun lint:check && bun lint:types && bun lint:unused && bun lint:repo", @@ -18,11 +18,11 @@ "test" ], "devDependencies": { - "@biomejs/biome": "^2.2.0", + "@biomejs/biome": "^2.2.3", "@changesets/changelog-github": "^0.5.1", "@changesets/cli": "^2.29.6", - "@types/bun": "^1.2.20", - "knip": "^5.62.0", + "@types/bun": "^1.2.21", + "knip": "^5.63.1", "sherif": "^1.6.1", "typescript": "^5.9.2" } diff --git a/packages/get/package.json b/packages/get/package.json index 89d2c9a..4f2b229 100644 --- a/packages/get/package.json +++ b/packages/get/package.json @@ -21,6 +21,8 @@ "@getlang/lib": "workspace:^0.1.5", "@getlang/parser": "workspace:^0.3.4", "@getlang/walker": "workspace:^0.0.1", + "acorn": "^8.15.0", + "estree-toolkit": "^1.7.13", "lodash-es": "^4.17.21" }, "devDependencies": { diff --git a/packages/lib/package.json b/packages/lib/package.json index 28ef8bf..ae53dc4 100644 --- a/packages/lib/package.json +++ b/packages/lib/package.json @@ -23,6 +23,7 @@ }, "homepage": "https://getlang.dev", "dependencies": { + "@getlang/ast": "workspace:^0.0.1", "@getlang/xpath": "0.0.35-0", "@types/esquery": "^1.5.4", "@types/lodash-es": "^4.17.12", diff --git a/test/package.json b/test/package.json index 6ba67bc..2c6bbb2 100644 --- a/test/package.json +++ b/test/package.json @@ -6,9 +6,9 @@ "@getlang/get": "workspace:*", "@getlang/lib": "workspace:^0.1.5", "@getlang/parser": "workspace:*", - "dedent": "^1.6.0" + "dedent": "^1.7.0" }, "devDependencies": { - "jest-diff": "^30.0.5" + "jest-diff": "^30.1.2" } }