diff --git a/packages/config-typescript/base.json b/packages/config-typescript/base.json index 766703c0..4be314e3 100644 --- a/packages/config-typescript/base.json +++ b/packages/config-typescript/base.json @@ -4,7 +4,6 @@ "compilerOptions": { "composite": false, "declaration": true, - "declarationMap": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "inlineSources": false, diff --git a/packages/matchers/.prettierignore b/packages/matchers/.prettierignore new file mode 100644 index 00000000..68eb0740 --- /dev/null +++ b/packages/matchers/.prettierignore @@ -0,0 +1 @@ +src/generated.ts diff --git a/packages/matchers/benchmark/test.js b/packages/matchers/benchmark/test.js new file mode 100644 index 00000000..9dec8d8d --- /dev/null +++ b/packages/matchers/benchmark/test.js @@ -0,0 +1,66 @@ +import * as t from '@babel/types'; +import * as cm from '@codemod/matchers'; +import * as b from 'benny'; +import * as m from '../src/index'; + +const webcrackMatcher = m.compile( + m.binaryExpression( + m.any, + m.numericLiteral(m.capture('left')), + m.binaryExpression( + m.any, + m.numericLiteral(m.capture('middle')), + m.numericLiteral(m.capture('right')), + ), + ), +); +console.log(webcrackMatcher.toString()); + +const left = cm.capture(cm.anyNumber()); +const middle = cm.capture(cm.anyNumber()); +const right = cm.capture(cm.anyNumber()); +const codemodMatcher = cm.binaryExpression( + cm.anything(), + cm.numericLiteral(left), + cm.binaryExpression( + cm.anything(), + cm.numericLiteral(middle), + cm.numericLiteral(right), + ), +); + +const binExp = t.binaryExpression( + '+', + t.numericLiteral(1), + t.binaryExpression('+', t.numericLiteral(2), t.numericLiteral(3)), +); +const binExp2 = t.binaryExpression( + '+', + t.numericLiteral(1), + t.binaryExpression('+', t.stringLiteral('x'), t.numericLiteral(3)), +); + +b.suite( + 'Matcher Performance', + + b.add('@webcrack/matchers', () => { + const captures = webcrackMatcher(binExp); + if (captures) { + captures.left === captures.right; + } + const captures2 = webcrackMatcher(binExp2); + if (captures2) { + captures2.left === captures2.right; + } + }), + b.add('@codemod/matchers', () => { + if (codemodMatcher.match(binExp)) { + left.current === right.current; + } + if (codemodMatcher.match(binExp2)) { + left.current === right.current; + } + }), + b.cycle(), + b.complete(), +); diff --git a/packages/matchers/eslint.config.js b/packages/matchers/eslint.config.js new file mode 100644 index 00000000..54337e43 --- /dev/null +++ b/packages/matchers/eslint.config.js @@ -0,0 +1,11 @@ +import config from '@webcrack/eslint-config'; + +/** + * @type {import('eslint').Linter.Config[]} + */ +export default [ + ...config, + { + ignores: ['src/generated.ts'], + }, +]; diff --git a/packages/matchers/package.json b/packages/matchers/package.json new file mode 100644 index 00000000..7def5d1a --- /dev/null +++ b/packages/matchers/package.json @@ -0,0 +1,32 @@ +{ + "name": "@webcrack/matchers", + "version": "0.1.0", + "private": true, + "type": "module", + "main": "src/index.ts", + "scripts": { + "build": "tsx scripts/build.ts", + "bench": "tsx benchmark/test.js", + "lint": "eslint src scripts", + "lint:fix": "eslint src scripts --fix", + "format:check": "prettier --check \"{src,scripts}/**/*.ts\"", + "format": "prettier --write \"{src,scripts}**/*.ts\"", + "typecheck": "tsc --noEmit", + "test": "vitest --no-isolate" + }, + "dependencies": { + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "devDependencies": { + "@babel/traverse": "^7.27.0", + "@codemod/matchers": "^1.7.1", + "@types/babel__traverse": "^7.20.7", + "@types/node": "^22.13.16", + "@webcrack/eslint-config": "workspace:*", + "@webcrack/typescript-config": "workspace:*", + "benny": "^3.7.1", + "tsx": "^4.19.3", + "typescript": "^5.8.2" + } +} diff --git a/packages/matchers/scripts/build.ts b/packages/matchers/scripts/build.ts new file mode 100644 index 00000000..a787f859 --- /dev/null +++ b/packages/matchers/scripts/build.ts @@ -0,0 +1,136 @@ +import * as t from '@babel/types'; +import { createWriteStream } from 'node:fs'; + +type Validator = Required['validate']; + +const out = createWriteStream(new URL('../src/generated.ts', import.meta.url)); + +out.write(`// This file is generated by scripts/build.ts. Do not edit manually. +import type * as t from '@babel/types'; +import type { NodeSchema, Schema } from './types.js'; + +`); + +for (const type of Object.keys(t.BUILDER_KEYS).sort()) { + const exportedName = toFunctionName(type); + const functionName = t.toBindingIdentifierName(exportedName); + + if (exportedName === functionName) { + out.write(`export `); + } else { + out.write(`export { ${functionName} as ${exportedName} };\n`); + } + + out.write(`function ${functionName}(${generateBuilderArgs(type).join(', ')}): NodeSchema { + return { type: '${type}', ${generateBuilderProperties(type).join(', ')} }; +} +`); +} + +out.close(); + +function toFunctionName(typeName: string): string { + return typeName.replace(/^(TS|JSX|[A-Z])/, (match) => match.toLowerCase()); +} + +function generateBuilderArgs(type: string): string[] { + const fields = t.NODE_FIELDS[type]; + const fieldNames = sortFieldNames(Object.keys(t.NODE_FIELDS[type]), type); + const builderNames = t.BUILDER_KEYS[type]; + + const args: string[] = []; + + fieldNames.forEach((fieldName) => { + const field = fields[fieldName]; + let typeAnnotation = stringifyValidator(field.validate, 't.'); + + if (isNullable(field) && !hasDefault(field)) { + typeAnnotation += ' | null'; + } + + if (builderNames.includes(fieldName)) { + const bindingIdentifierName = t.toBindingIdentifierName(fieldName); + const arg = `${bindingIdentifierName}?: Schema<${typeAnnotation}>`; + args.push(arg); + } + }); + + return args; +} + +function generateBuilderProperties(type: string): string[] { + const builderKeys = sortFieldNames(t.BUILDER_KEYS[type], type); + return builderKeys.map((key) => { + const argName = t.toBindingIdentifierName(key); + return argName === key ? key : `${key}: ${argName}`; + }); +} + +function hasDefault(field: t.FieldOptions): boolean { + return field.default != null; +} + +function isNullable(field: t.FieldOptions): boolean { + return field.optional || hasDefault(field); +} + +function sortFieldNames(fields: string[], type: string): string[] { + return fields.sort((fieldA, fieldB) => { + const indexA = t.BUILDER_KEYS[type].indexOf(fieldA); + const indexB = t.BUILDER_KEYS[type].indexOf(fieldB); + if (indexA === indexB) return fieldA < fieldB ? -1 : 1; + if (indexA === -1) return 1; + if (indexB === -1) return -1; + return indexA - indexB; + }); +} + +export default function stringifyValidator( + validator: Validator | undefined, + nodePrefix: string, +): string { + if (validator === undefined) { + return 'any'; + } + + if ('each' in validator) { + return `Array<${stringifyValidator(validator.each, nodePrefix)}>`; + } + + if ('chainOf' in validator) { + const ret = stringifyValidator(validator.chainOf[1], nodePrefix); + return Array.isArray(ret) && ret.length === 1 && ret[0] === 'any' + ? stringifyValidator(validator.chainOf[0], nodePrefix) + : ret; + } + + if ('oneOf' in validator) { + return validator.oneOf.map((v) => JSON.stringify(v)).join(' | '); + } + + if ('oneOfNodeTypes' in validator) { + return validator.oneOfNodeTypes.map((_) => nodePrefix + _).join(' | '); + } + + if ('oneOfNodeOrValueTypes' in validator) { + return validator.oneOfNodeOrValueTypes + .map((_) => { + return isValueType(_) ? _ : nodePrefix + _; + }) + .join(' | '); + } + + if ('type' in validator) { + return validator.type; + } + + return 'any'; +} + +/** + * Heuristic to decide whether or not the given type is a value type (eg. "null") + * or a Node type (eg. "Expression"). + */ +export function isValueType(type: string) { + return type.charAt(0).toLowerCase() === type.charAt(0); +} diff --git a/packages/matchers/src/compiler.ts b/packages/matchers/src/compiler.ts new file mode 100644 index 00000000..83c8b77a --- /dev/null +++ b/packages/matchers/src/compiler.ts @@ -0,0 +1,219 @@ +import type { NodePath, Visitor } from '@babel/traverse'; +import * as t from '@babel/types'; +import { + type ArraySchema, + type CaptureMatcher, + type FromCaptureMatcher, + type Matcher, + type NodeSchema, + type NullableSchema, + type OrMatcher, + type Schema, +} from './types.js'; + +interface Context { + captures: Map>; +} + +/** + * **Warning**: only compile a schema from trustworthy sources. + * Otherwise, it could lead to code injection attacks. + */ +export function compile( + schema: NodeSchema, + checkType?: true, +): (input: t.Node) => object | undefined; +export function compile( + schema: NodeSchema, + checkType: false, +): (input: T) => object | undefined; +export function compile( + schema: NodeSchema, + checkType = true, +): (input: t.Node) => object | undefined { + const context: Context = { captures: new Map() }; + const checks = compileNode(schema, 'node', context, checkType); + const code = ` +const captures = { ${Array.from(context.captures.keys(), (name) => `${name}: undefined`).join(', ')} }; +if (${checks ?? true}) { return captures; }`; + + // eslint-disable-next-line @typescript-eslint/no-implied-eval + return Function('node', code) as never; +} + +/** + * **Warning**: only compile a schema from trustworthy sources. + * Otherwise, it could lead to code injection attacks. + */ +export function compileVisitor( + schema: NodeSchema, + phase: 'enter' | 'exit' = 'enter', +): (cb: VisitNodeFunction) => Visitor { + const context: Context = { captures: new Map() }; + const checks = compileNode(schema, 'node', context, false); + const code = ` +const node = path.node; +const captures = { ${Array.from(context.captures.keys(), (name) => `${name}: undefined`).join(', ')} }; +if (${checks ?? true}) { cb.call(state, path, state, captures); }`; + + // eslint-disable-next-line @typescript-eslint/no-implied-eval + const match = Function('path', 'state', 'cb', code) as ( + path: NodePath, + state: unknown, + cb: VisitNodeFunction, + ) => void; + + return (cb: VisitNodeFunction) => ({ + [schema.type]: { + [phase](path: NodePath, state: S) { + match(path, state, cb as never); + }, + }, + }); +} + +export type VisitNodeFunction = ( + this: S, + path: NodePath, + state: S, + captures: object, +) => void; + +type CompileFunction = ( + schema: never, + input: string, + ctx: Context, +) => string | null; + +const compilers: Record = { + nullable: compileNullable, + tuple: compileTuple, + arrayOf: compileArrayOf, + or: compileOr, + capture: compileCapture, + fromCapture: compileFromCapture, +}; +Object.keys(t.BUILDER_KEYS).forEach((type) => { + compilers[type as t.Node['type']] = compileNode; +}); + +function compileSchema( + schema: Schema, + input: string, + ctx: Context, +): string | null { + if (schema === undefined) { + return null; + } else if ( + typeof schema === 'string' || + typeof schema === 'number' || + typeof schema === 'boolean' || + schema === null + ) { + return `${input} === ${JSON.stringify(schema)}`; + } else if (Array.isArray(schema)) { + return compileTuple(schema, input, ctx); + } else { + return compileMatcher(schema as Matcher, input, ctx); + } +} + +function compileMatcher( + matcher: Matcher, + input: string, + ctx: Context, +): string | null { + return compilers[matcher.type](matcher as never, input, ctx); +} + +function compileTuple( + schema: Schema[], + input: string, + ctx: Context, +): string | null { + const checks = [ + `${input}.length === ${schema.length}`, + ...schema + .map((m, i) => compileSchema(m, `${input}[${i}]`, ctx)) + .filter((c) => c !== null), + ]; + return checks.join(' && '); +} + +function compileArrayOf( + schema: ArraySchema, + input: string, + ctx: Context, +): string | null { + const checks = compileSchema(schema.schema, 'element', ctx); + if (checks === null) return null; + return `${input}.every(element => ${checks})`; +} + +function compileNullable( + schema: NullableSchema, + input: string, + ctx: Context, +): string | null { + const checks = compileSchema(schema.schema, input, ctx); + if (checks === null) return null; + return `(${input} === null || ${checks})`; +} + +function compileOr(schema: OrMatcher, input: string, ctx: Context) { + const checks = schema.schema + .map((m) => compileSchema(m, input, ctx)) + .filter((c) => c !== null); + if (checks.length === 0) return null; + return `(${checks.join(' || ')})`; +} + +function compileCapture( + schema: CaptureMatcher, + input: string, + ctx: Context, +): string | null { + ctx.captures.set(schema.name, schema.schema); + const checks = compileSchema(schema.schema, input, ctx); + if (checks === null) { + return `(captures['${schema.name}'] = ${input}, true)`; + } else { + return `${checks} && (captures['${schema.name}'] = ${input}, true)`; + } +} + +function compileFromCapture( + schema: FromCaptureMatcher, + input: string, +): string | null { + return `(captures['${schema.name}'] != null && typeof captures['${schema.name}'] === 'object' ? captures['${schema.name}'].name === ${input}.name : captures['${schema.name}'] === ${input})`; +} + +function compileNode( + schema: NodeSchema, + input: string, + ctx: Context, + checkType = true, +) { + const checks: string[] = []; + if (checkType) { + checks.push(`${input}.type === '${schema.type}'`); + } + + const fields = t.NODE_FIELDS[schema.type]; + + for (const key in fields) { + const value = schema[key as never] as Schema; + const valueChecks = compileSchema(value, `${input}.${key}`, ctx); + if (valueChecks === null) continue; + + const validator = fields[key]; + if (value !== null && validator.optional) { + // TODO: only when all checks includes property accesses + checks.push(`${input}.${key} != null`); + } + checks.push(valueChecks); + } + + return checks.length ? checks.join(' && ') : null; +} diff --git a/packages/matchers/src/generated.ts b/packages/matchers/src/generated.ts new file mode 100644 index 00000000..98473877 --- /dev/null +++ b/packages/matchers/src/generated.ts @@ -0,0 +1,762 @@ +// This file is generated by scripts/build.ts. Do not edit manually. +import type * as t from '@babel/types'; +import type { NodeSchema, Schema } from './types.js'; + +export function anyTypeAnnotation(): NodeSchema { + return { type: 'AnyTypeAnnotation', }; +} +export function argumentPlaceholder(): NodeSchema { + return { type: 'ArgumentPlaceholder', }; +} +export function arrayExpression(elements?: Schema>): NodeSchema { + return { type: 'ArrayExpression', elements }; +} +export function arrayPattern(elements?: Schema>): NodeSchema { + return { type: 'ArrayPattern', elements }; +} +export function arrayTypeAnnotation(elementType?: Schema): NodeSchema { + return { type: 'ArrayTypeAnnotation', elementType }; +} +export function arrowFunctionExpression(params?: Schema>, body?: Schema, async?: Schema): NodeSchema { + return { type: 'ArrowFunctionExpression', params, body, async }; +} +export function assignmentExpression(operator?: Schema, left?: Schema, right?: Schema): NodeSchema { + return { type: 'AssignmentExpression', operator, left, right }; +} +export function assignmentPattern(left?: Schema, right?: Schema): NodeSchema { + return { type: 'AssignmentPattern', left, right }; +} +export function awaitExpression(argument?: Schema): NodeSchema { + return { type: 'AwaitExpression', argument }; +} +export function bigIntLiteral(value?: Schema): NodeSchema { + return { type: 'BigIntLiteral', value }; +} +export function binaryExpression(operator?: Schema<"+" | "-" | "/" | "%" | "*" | "**" | "&" | "|" | ">>" | ">>>" | "<<" | "^" | "==" | "===" | "!=" | "!==" | "in" | "instanceof" | ">" | "<" | ">=" | "<=" | "|>">, left?: Schema, right?: Schema): NodeSchema { + return { type: 'BinaryExpression', operator, left, right }; +} +export function bindExpression(object?: Schema, callee?: Schema): NodeSchema { + return { type: 'BindExpression', object, callee }; +} +export function blockStatement(body?: Schema>, directives?: Schema>): NodeSchema { + return { type: 'BlockStatement', body, directives }; +} +export function booleanLiteral(value?: Schema): NodeSchema { + return { type: 'BooleanLiteral', value }; +} +export function booleanLiteralTypeAnnotation(value?: Schema): NodeSchema { + return { type: 'BooleanLiteralTypeAnnotation', value }; +} +export function booleanTypeAnnotation(): NodeSchema { + return { type: 'BooleanTypeAnnotation', }; +} +export function breakStatement(label?: Schema): NodeSchema { + return { type: 'BreakStatement', label }; +} +export function callExpression(callee?: Schema, _arguments?: Schema>): NodeSchema { + return { type: 'CallExpression', callee, arguments: _arguments }; +} +export function catchClause(param?: Schema, body?: Schema): NodeSchema { + return { type: 'CatchClause', param, body }; +} +export function classAccessorProperty(key?: Schema, value?: Schema, typeAnnotation?: Schema, decorators?: Schema | null>, computed?: Schema, _static?: Schema): NodeSchema { + return { type: 'ClassAccessorProperty', key, value, typeAnnotation, decorators, computed, static: _static }; +} +export function classBody(body?: Schema>): NodeSchema { + return { type: 'ClassBody', body }; +} +export function classDeclaration(id?: Schema, superClass?: Schema, body?: Schema, decorators?: Schema | null>): NodeSchema { + return { type: 'ClassDeclaration', id, superClass, body, decorators }; +} +export function classExpression(id?: Schema, superClass?: Schema, body?: Schema, decorators?: Schema | null>): NodeSchema { + return { type: 'ClassExpression', id, superClass, body, decorators }; +} +export function classImplements(id?: Schema, typeParameters?: Schema): NodeSchema { + return { type: 'ClassImplements', id, typeParameters }; +} +export function classMethod(kind?: Schema<"get" | "set" | "method" | "constructor">, key?: Schema, params?: Schema>, body?: Schema, computed?: Schema, _static?: Schema, generator?: Schema, async?: Schema): NodeSchema { + return { type: 'ClassMethod', kind, key, params, body, computed, static: _static, generator, async }; +} +export function classPrivateMethod(kind?: Schema<"get" | "set" | "method">, key?: Schema, params?: Schema>, body?: Schema, _static?: Schema): NodeSchema { + return { type: 'ClassPrivateMethod', kind, key, params, body, static: _static }; +} +export function classPrivateProperty(key?: Schema, value?: Schema, decorators?: Schema | null>, _static?: Schema): NodeSchema { + return { type: 'ClassPrivateProperty', key, value, decorators, static: _static }; +} +export function classProperty(key?: Schema, value?: Schema, typeAnnotation?: Schema, decorators?: Schema | null>, computed?: Schema, _static?: Schema): NodeSchema { + return { type: 'ClassProperty', key, value, typeAnnotation, decorators, computed, static: _static }; +} +export function conditionalExpression(test?: Schema, consequent?: Schema, alternate?: Schema): NodeSchema { + return { type: 'ConditionalExpression', test, consequent, alternate }; +} +export function continueStatement(label?: Schema): NodeSchema { + return { type: 'ContinueStatement', label }; +} +export function debuggerStatement(): NodeSchema { + return { type: 'DebuggerStatement', }; +} +export function decimalLiteral(value?: Schema): NodeSchema { + return { type: 'DecimalLiteral', value }; +} +export function declareClass(id?: Schema, typeParameters?: Schema, _extends?: Schema | null>, body?: Schema): NodeSchema { + return { type: 'DeclareClass', id, typeParameters, extends: _extends, body }; +} +export function declareExportAllDeclaration(source?: Schema, attributes?: Schema | null>): NodeSchema { + return { type: 'DeclareExportAllDeclaration', source, attributes }; +} +export function declareExportDeclaration(declaration?: Schema, specifiers?: Schema | null>, source?: Schema, attributes?: Schema | null>): NodeSchema { + return { type: 'DeclareExportDeclaration', declaration, specifiers, source, attributes }; +} +export function declareFunction(id?: Schema): NodeSchema { + return { type: 'DeclareFunction', id }; +} +export function declareInterface(id?: Schema, typeParameters?: Schema, _extends?: Schema | null>, body?: Schema): NodeSchema { + return { type: 'DeclareInterface', id, typeParameters, extends: _extends, body }; +} +export function declareModule(id?: Schema, body?: Schema, kind?: Schema<"CommonJS" | "ES" | null>): NodeSchema { + return { type: 'DeclareModule', id, body, kind }; +} +export function declareModuleExports(typeAnnotation?: Schema): NodeSchema { + return { type: 'DeclareModuleExports', typeAnnotation }; +} +export function declareOpaqueType(id?: Schema, typeParameters?: Schema, supertype?: Schema): NodeSchema { + return { type: 'DeclareOpaqueType', id, typeParameters, supertype }; +} +export function declareTypeAlias(id?: Schema, typeParameters?: Schema, right?: Schema): NodeSchema { + return { type: 'DeclareTypeAlias', id, typeParameters, right }; +} +export function declareVariable(id?: Schema): NodeSchema { + return { type: 'DeclareVariable', id }; +} +export function declaredPredicate(value?: Schema): NodeSchema { + return { type: 'DeclaredPredicate', value }; +} +export function decorator(expression?: Schema): NodeSchema { + return { type: 'Decorator', expression }; +} +export function directive(value?: Schema): NodeSchema { + return { type: 'Directive', value }; +} +export function directiveLiteral(value?: Schema): NodeSchema { + return { type: 'DirectiveLiteral', value }; +} +export function doExpression(body?: Schema, async?: Schema): NodeSchema { + return { type: 'DoExpression', body, async }; +} +export function doWhileStatement(test?: Schema, body?: Schema): NodeSchema { + return { type: 'DoWhileStatement', test, body }; +} +export function emptyStatement(): NodeSchema { + return { type: 'EmptyStatement', }; +} +export function emptyTypeAnnotation(): NodeSchema { + return { type: 'EmptyTypeAnnotation', }; +} +export function enumBooleanBody(members?: Schema>): NodeSchema { + return { type: 'EnumBooleanBody', members }; +} +export function enumBooleanMember(id?: Schema): NodeSchema { + return { type: 'EnumBooleanMember', id }; +} +export function enumDeclaration(id?: Schema, body?: Schema): NodeSchema { + return { type: 'EnumDeclaration', id, body }; +} +export function enumDefaultedMember(id?: Schema): NodeSchema { + return { type: 'EnumDefaultedMember', id }; +} +export function enumNumberBody(members?: Schema>): NodeSchema { + return { type: 'EnumNumberBody', members }; +} +export function enumNumberMember(id?: Schema, init?: Schema): NodeSchema { + return { type: 'EnumNumberMember', id, init }; +} +export function enumStringBody(members?: Schema>): NodeSchema { + return { type: 'EnumStringBody', members }; +} +export function enumStringMember(id?: Schema, init?: Schema): NodeSchema { + return { type: 'EnumStringMember', id, init }; +} +export function enumSymbolBody(members?: Schema>): NodeSchema { + return { type: 'EnumSymbolBody', members }; +} +export function existsTypeAnnotation(): NodeSchema { + return { type: 'ExistsTypeAnnotation', }; +} +export function exportAllDeclaration(source?: Schema): NodeSchema { + return { type: 'ExportAllDeclaration', source }; +} +export function exportDefaultDeclaration(declaration?: Schema): NodeSchema { + return { type: 'ExportDefaultDeclaration', declaration }; +} +export function exportDefaultSpecifier(exported?: Schema): NodeSchema { + return { type: 'ExportDefaultSpecifier', exported }; +} +export function exportNamedDeclaration(declaration?: Schema, specifiers?: Schema>, source?: Schema): NodeSchema { + return { type: 'ExportNamedDeclaration', declaration, specifiers, source }; +} +export function exportNamespaceSpecifier(exported?: Schema): NodeSchema { + return { type: 'ExportNamespaceSpecifier', exported }; +} +export function exportSpecifier(local?: Schema, exported?: Schema): NodeSchema { + return { type: 'ExportSpecifier', local, exported }; +} +export function expressionStatement(expression?: Schema): NodeSchema { + return { type: 'ExpressionStatement', expression }; +} +export function file(program?: Schema, comments?: Schema | null>, tokens?: Schema | null>): NodeSchema { + return { type: 'File', program, comments, tokens }; +} +export function forInStatement(left?: Schema, right?: Schema, body?: Schema): NodeSchema { + return { type: 'ForInStatement', left, right, body }; +} +export function forOfStatement(left?: Schema, right?: Schema, body?: Schema, _await?: Schema): NodeSchema { + return { type: 'ForOfStatement', left, right, body, await: _await }; +} +export function forStatement(init?: Schema, test?: Schema, update?: Schema, body?: Schema): NodeSchema { + return { type: 'ForStatement', init, test, update, body }; +} +export function functionDeclaration(id?: Schema, params?: Schema>, body?: Schema, generator?: Schema, async?: Schema): NodeSchema { + return { type: 'FunctionDeclaration', id, params, body, generator, async }; +} +export function functionExpression(id?: Schema, params?: Schema>, body?: Schema, generator?: Schema, async?: Schema): NodeSchema { + return { type: 'FunctionExpression', id, params, body, generator, async }; +} +export function functionTypeAnnotation(typeParameters?: Schema, params?: Schema>, rest?: Schema, returnType?: Schema): NodeSchema { + return { type: 'FunctionTypeAnnotation', typeParameters, params, rest, returnType }; +} +export function functionTypeParam(name?: Schema, typeAnnotation?: Schema): NodeSchema { + return { type: 'FunctionTypeParam', name, typeAnnotation }; +} +export function genericTypeAnnotation(id?: Schema, typeParameters?: Schema): NodeSchema { + return { type: 'GenericTypeAnnotation', id, typeParameters }; +} +export function identifier(name?: Schema): NodeSchema { + return { type: 'Identifier', name }; +} +export function ifStatement(test?: Schema, consequent?: Schema, alternate?: Schema): NodeSchema { + return { type: 'IfStatement', test, consequent, alternate }; +} +export { _import as import }; +function _import(): NodeSchema { + return { type: 'Import', }; +} +export function importAttribute(key?: Schema, value?: Schema): NodeSchema { + return { type: 'ImportAttribute', key, value }; +} +export function importDeclaration(specifiers?: Schema>, source?: Schema): NodeSchema { + return { type: 'ImportDeclaration', specifiers, source }; +} +export function importDefaultSpecifier(local?: Schema): NodeSchema { + return { type: 'ImportDefaultSpecifier', local }; +} +export function importExpression(source?: Schema, options?: Schema): NodeSchema { + return { type: 'ImportExpression', source, options }; +} +export function importNamespaceSpecifier(local?: Schema): NodeSchema { + return { type: 'ImportNamespaceSpecifier', local }; +} +export function importSpecifier(local?: Schema, imported?: Schema): NodeSchema { + return { type: 'ImportSpecifier', local, imported }; +} +export function indexedAccessType(objectType?: Schema, indexType?: Schema): NodeSchema { + return { type: 'IndexedAccessType', objectType, indexType }; +} +export function inferredPredicate(): NodeSchema { + return { type: 'InferredPredicate', }; +} +export function interfaceDeclaration(id?: Schema, typeParameters?: Schema, _extends?: Schema | null>, body?: Schema): NodeSchema { + return { type: 'InterfaceDeclaration', id, typeParameters, extends: _extends, body }; +} +export function interfaceExtends(id?: Schema, typeParameters?: Schema): NodeSchema { + return { type: 'InterfaceExtends', id, typeParameters }; +} +export function interfaceTypeAnnotation(_extends?: Schema | null>, body?: Schema): NodeSchema { + return { type: 'InterfaceTypeAnnotation', extends: _extends, body }; +} +export function interpreterDirective(value?: Schema): NodeSchema { + return { type: 'InterpreterDirective', value }; +} +export function intersectionTypeAnnotation(types?: Schema>): NodeSchema { + return { type: 'IntersectionTypeAnnotation', types }; +} +export function jsxAttribute(name?: Schema, value?: Schema): NodeSchema { + return { type: 'JSXAttribute', name, value }; +} +export function jsxClosingElement(name?: Schema): NodeSchema { + return { type: 'JSXClosingElement', name }; +} +export function jsxClosingFragment(): NodeSchema { + return { type: 'JSXClosingFragment', }; +} +export function jsxElement(openingElement?: Schema, closingElement?: Schema, children?: Schema>, selfClosing?: Schema): NodeSchema { + return { type: 'JSXElement', openingElement, closingElement, children, selfClosing }; +} +export function jsxEmptyExpression(): NodeSchema { + return { type: 'JSXEmptyExpression', }; +} +export function jsxExpressionContainer(expression?: Schema): NodeSchema { + return { type: 'JSXExpressionContainer', expression }; +} +export function jsxFragment(openingFragment?: Schema, closingFragment?: Schema, children?: Schema>): NodeSchema { + return { type: 'JSXFragment', openingFragment, closingFragment, children }; +} +export function jsxIdentifier(name?: Schema): NodeSchema { + return { type: 'JSXIdentifier', name }; +} +export function jsxMemberExpression(object?: Schema, property?: Schema): NodeSchema { + return { type: 'JSXMemberExpression', object, property }; +} +export function jsxNamespacedName(namespace?: Schema, name?: Schema): NodeSchema { + return { type: 'JSXNamespacedName', namespace, name }; +} +export function jsxOpeningElement(name?: Schema, attributes?: Schema>, selfClosing?: Schema): NodeSchema { + return { type: 'JSXOpeningElement', name, attributes, selfClosing }; +} +export function jsxOpeningFragment(): NodeSchema { + return { type: 'JSXOpeningFragment', }; +} +export function jsxSpreadAttribute(argument?: Schema): NodeSchema { + return { type: 'JSXSpreadAttribute', argument }; +} +export function jsxSpreadChild(expression?: Schema): NodeSchema { + return { type: 'JSXSpreadChild', expression }; +} +export function jsxText(value?: Schema): NodeSchema { + return { type: 'JSXText', value }; +} +export function labeledStatement(label?: Schema, body?: Schema): NodeSchema { + return { type: 'LabeledStatement', label, body }; +} +export function logicalExpression(operator?: Schema<"||" | "&&" | "??">, left?: Schema, right?: Schema): NodeSchema { + return { type: 'LogicalExpression', operator, left, right }; +} +export function memberExpression(object?: Schema, property?: Schema, computed?: Schema, optional?: Schema): NodeSchema { + return { type: 'MemberExpression', object, property, computed, optional }; +} +export function metaProperty(meta?: Schema, property?: Schema): NodeSchema { + return { type: 'MetaProperty', meta, property }; +} +export function mixedTypeAnnotation(): NodeSchema { + return { type: 'MixedTypeAnnotation', }; +} +export function moduleExpression(body?: Schema): NodeSchema { + return { type: 'ModuleExpression', body }; +} +export function newExpression(callee?: Schema, _arguments?: Schema>): NodeSchema { + return { type: 'NewExpression', callee, arguments: _arguments }; +} +export function noop(): NodeSchema { + return { type: 'Noop', }; +} +export function nullLiteral(): NodeSchema { + return { type: 'NullLiteral', }; +} +export function nullLiteralTypeAnnotation(): NodeSchema { + return { type: 'NullLiteralTypeAnnotation', }; +} +export function nullableTypeAnnotation(typeAnnotation?: Schema): NodeSchema { + return { type: 'NullableTypeAnnotation', typeAnnotation }; +} +export function numberLiteralTypeAnnotation(value?: Schema): NodeSchema { + return { type: 'NumberLiteralTypeAnnotation', value }; +} +export function numberTypeAnnotation(): NodeSchema { + return { type: 'NumberTypeAnnotation', }; +} +export function numericLiteral(value?: Schema): NodeSchema { + return { type: 'NumericLiteral', value }; +} +export function objectExpression(properties?: Schema>): NodeSchema { + return { type: 'ObjectExpression', properties }; +} +export function objectMethod(kind?: Schema<"method" | "get" | "set">, key?: Schema, params?: Schema>, body?: Schema, computed?: Schema, generator?: Schema, async?: Schema): NodeSchema { + return { type: 'ObjectMethod', kind, key, params, body, computed, generator, async }; +} +export function objectPattern(properties?: Schema>): NodeSchema { + return { type: 'ObjectPattern', properties }; +} +export function objectProperty(key?: Schema, value?: Schema, computed?: Schema, shorthand?: Schema, decorators?: Schema | null>): NodeSchema { + return { type: 'ObjectProperty', key, value, computed, shorthand, decorators }; +} +export function objectTypeAnnotation(properties?: Schema>, indexers?: Schema>, callProperties?: Schema>, internalSlots?: Schema>, exact?: Schema): NodeSchema { + return { type: 'ObjectTypeAnnotation', properties, indexers, callProperties, internalSlots, exact }; +} +export function objectTypeCallProperty(value?: Schema): NodeSchema { + return { type: 'ObjectTypeCallProperty', value }; +} +export function objectTypeIndexer(id?: Schema, key?: Schema, value?: Schema, variance?: Schema): NodeSchema { + return { type: 'ObjectTypeIndexer', id, key, value, variance }; +} +export function objectTypeInternalSlot(id?: Schema, value?: Schema, optional?: Schema, _static?: Schema, method?: Schema): NodeSchema { + return { type: 'ObjectTypeInternalSlot', id, value, optional, static: _static, method }; +} +export function objectTypeProperty(key?: Schema, value?: Schema, variance?: Schema): NodeSchema { + return { type: 'ObjectTypeProperty', key, value, variance }; +} +export function objectTypeSpreadProperty(argument?: Schema): NodeSchema { + return { type: 'ObjectTypeSpreadProperty', argument }; +} +export function opaqueType(id?: Schema, typeParameters?: Schema, supertype?: Schema, impltype?: Schema): NodeSchema { + return { type: 'OpaqueType', id, typeParameters, supertype, impltype }; +} +export function optionalCallExpression(callee?: Schema, _arguments?: Schema>, optional?: Schema): NodeSchema { + return { type: 'OptionalCallExpression', callee, arguments: _arguments, optional }; +} +export function optionalIndexedAccessType(objectType?: Schema, indexType?: Schema): NodeSchema { + return { type: 'OptionalIndexedAccessType', objectType, indexType }; +} +export function optionalMemberExpression(object?: Schema, property?: Schema, computed?: Schema, optional?: Schema): NodeSchema { + return { type: 'OptionalMemberExpression', object, property, computed, optional }; +} +export function parenthesizedExpression(expression?: Schema): NodeSchema { + return { type: 'ParenthesizedExpression', expression }; +} +export function pipelineBareFunction(callee?: Schema): NodeSchema { + return { type: 'PipelineBareFunction', callee }; +} +export function pipelinePrimaryTopicReference(): NodeSchema { + return { type: 'PipelinePrimaryTopicReference', }; +} +export function pipelineTopicExpression(expression?: Schema): NodeSchema { + return { type: 'PipelineTopicExpression', expression }; +} +export function placeholder(expectedNode?: Schema<"Identifier" | "StringLiteral" | "Expression" | "Statement" | "Declaration" | "BlockStatement" | "ClassBody" | "Pattern">, name?: Schema): NodeSchema { + return { type: 'Placeholder', expectedNode, name }; +} +export function privateName(id?: Schema): NodeSchema { + return { type: 'PrivateName', id }; +} +export function program(body?: Schema>, directives?: Schema>, sourceType?: Schema<"script" | "module">, interpreter?: Schema): NodeSchema { + return { type: 'Program', body, directives, sourceType, interpreter }; +} +export function qualifiedTypeIdentifier(id?: Schema, qualification?: Schema): NodeSchema { + return { type: 'QualifiedTypeIdentifier', id, qualification }; +} +export function recordExpression(properties?: Schema>): NodeSchema { + return { type: 'RecordExpression', properties }; +} +export function regExpLiteral(pattern?: Schema, flags?: Schema): NodeSchema { + return { type: 'RegExpLiteral', pattern, flags }; +} +export function restElement(argument?: Schema): NodeSchema { + return { type: 'RestElement', argument }; +} +export function returnStatement(argument?: Schema): NodeSchema { + return { type: 'ReturnStatement', argument }; +} +export function sequenceExpression(expressions?: Schema>): NodeSchema { + return { type: 'SequenceExpression', expressions }; +} +export function spreadElement(argument?: Schema): NodeSchema { + return { type: 'SpreadElement', argument }; +} +export function staticBlock(body?: Schema>): NodeSchema { + return { type: 'StaticBlock', body }; +} +export function stringLiteral(value?: Schema): NodeSchema { + return { type: 'StringLiteral', value }; +} +export function stringLiteralTypeAnnotation(value?: Schema): NodeSchema { + return { type: 'StringLiteralTypeAnnotation', value }; +} +export function stringTypeAnnotation(): NodeSchema { + return { type: 'StringTypeAnnotation', }; +} +export { _super as super }; +function _super(): NodeSchema { + return { type: 'Super', }; +} +export function switchCase(test?: Schema, consequent?: Schema>): NodeSchema { + return { type: 'SwitchCase', test, consequent }; +} +export function switchStatement(discriminant?: Schema, cases?: Schema>): NodeSchema { + return { type: 'SwitchStatement', discriminant, cases }; +} +export function symbolTypeAnnotation(): NodeSchema { + return { type: 'SymbolTypeAnnotation', }; +} +export function tsAnyKeyword(): NodeSchema { + return { type: 'TSAnyKeyword', }; +} +export function tsArrayType(elementType?: Schema): NodeSchema { + return { type: 'TSArrayType', elementType }; +} +export function tsAsExpression(expression?: Schema, typeAnnotation?: Schema): NodeSchema { + return { type: 'TSAsExpression', expression, typeAnnotation }; +} +export function tsBigIntKeyword(): NodeSchema { + return { type: 'TSBigIntKeyword', }; +} +export function tsBooleanKeyword(): NodeSchema { + return { type: 'TSBooleanKeyword', }; +} +export function tsCallSignatureDeclaration(typeParameters?: Schema, parameters?: Schema>, typeAnnotation?: Schema): NodeSchema { + return { type: 'TSCallSignatureDeclaration', typeParameters, parameters, typeAnnotation }; +} +export function tsConditionalType(checkType?: Schema, extendsType?: Schema, trueType?: Schema, falseType?: Schema): NodeSchema { + return { type: 'TSConditionalType', checkType, extendsType, trueType, falseType }; +} +export function tsConstructSignatureDeclaration(typeParameters?: Schema, parameters?: Schema>, typeAnnotation?: Schema): NodeSchema { + return { type: 'TSConstructSignatureDeclaration', typeParameters, parameters, typeAnnotation }; +} +export function tsConstructorType(typeParameters?: Schema, parameters?: Schema>, typeAnnotation?: Schema): NodeSchema { + return { type: 'TSConstructorType', typeParameters, parameters, typeAnnotation }; +} +export function tsDeclareFunction(id?: Schema, typeParameters?: Schema, params?: Schema>, returnType?: Schema): NodeSchema { + return { type: 'TSDeclareFunction', id, typeParameters, params, returnType }; +} +export function tsDeclareMethod(decorators?: Schema | null>, key?: Schema, typeParameters?: Schema, params?: Schema>, returnType?: Schema): NodeSchema { + return { type: 'TSDeclareMethod', decorators, key, typeParameters, params, returnType }; +} +export function tsEnumBody(members?: Schema>): NodeSchema { + return { type: 'TSEnumBody', members }; +} +export function tsEnumDeclaration(id?: Schema, members?: Schema>): NodeSchema { + return { type: 'TSEnumDeclaration', id, members }; +} +export function tsEnumMember(id?: Schema, initializer?: Schema): NodeSchema { + return { type: 'TSEnumMember', id, initializer }; +} +export function tsExportAssignment(expression?: Schema): NodeSchema { + return { type: 'TSExportAssignment', expression }; +} +export function tsExpressionWithTypeArguments(expression?: Schema, typeParameters?: Schema): NodeSchema { + return { type: 'TSExpressionWithTypeArguments', expression, typeParameters }; +} +export function tsExternalModuleReference(expression?: Schema): NodeSchema { + return { type: 'TSExternalModuleReference', expression }; +} +export function tsFunctionType(typeParameters?: Schema, parameters?: Schema>, typeAnnotation?: Schema): NodeSchema { + return { type: 'TSFunctionType', typeParameters, parameters, typeAnnotation }; +} +export function tsImportEqualsDeclaration(id?: Schema, moduleReference?: Schema): NodeSchema { + return { type: 'TSImportEqualsDeclaration', id, moduleReference }; +} +export function tsImportType(argument?: Schema, qualifier?: Schema, typeParameters?: Schema): NodeSchema { + return { type: 'TSImportType', argument, qualifier, typeParameters }; +} +export function tsIndexSignature(parameters?: Schema>, typeAnnotation?: Schema): NodeSchema { + return { type: 'TSIndexSignature', parameters, typeAnnotation }; +} +export function tsIndexedAccessType(objectType?: Schema, indexType?: Schema): NodeSchema { + return { type: 'TSIndexedAccessType', objectType, indexType }; +} +export function tsInferType(typeParameter?: Schema): NodeSchema { + return { type: 'TSInferType', typeParameter }; +} +export function tsInstantiationExpression(expression?: Schema, typeParameters?: Schema): NodeSchema { + return { type: 'TSInstantiationExpression', expression, typeParameters }; +} +export function tsInterfaceBody(body?: Schema>): NodeSchema { + return { type: 'TSInterfaceBody', body }; +} +export function tsInterfaceDeclaration(id?: Schema, typeParameters?: Schema, _extends?: Schema | null>, body?: Schema): NodeSchema { + return { type: 'TSInterfaceDeclaration', id, typeParameters, extends: _extends, body }; +} +export function tsIntersectionType(types?: Schema>): NodeSchema { + return { type: 'TSIntersectionType', types }; +} +export function tsIntrinsicKeyword(): NodeSchema { + return { type: 'TSIntrinsicKeyword', }; +} +export function tsLiteralType(literal?: Schema): NodeSchema { + return { type: 'TSLiteralType', literal }; +} +export function tsMappedType(typeParameter?: Schema, typeAnnotation?: Schema, nameType?: Schema): NodeSchema { + return { type: 'TSMappedType', typeParameter, typeAnnotation, nameType }; +} +export function tsMethodSignature(key?: Schema, typeParameters?: Schema, parameters?: Schema>, typeAnnotation?: Schema): NodeSchema { + return { type: 'TSMethodSignature', key, typeParameters, parameters, typeAnnotation }; +} +export function tsModuleBlock(body?: Schema>): NodeSchema { + return { type: 'TSModuleBlock', body }; +} +export function tsModuleDeclaration(id?: Schema, body?: Schema): NodeSchema { + return { type: 'TSModuleDeclaration', id, body }; +} +export function tsNamedTupleMember(label?: Schema, elementType?: Schema, optional?: Schema): NodeSchema { + return { type: 'TSNamedTupleMember', label, elementType, optional }; +} +export function tsNamespaceExportDeclaration(id?: Schema): NodeSchema { + return { type: 'TSNamespaceExportDeclaration', id }; +} +export function tsNeverKeyword(): NodeSchema { + return { type: 'TSNeverKeyword', }; +} +export function tsNonNullExpression(expression?: Schema): NodeSchema { + return { type: 'TSNonNullExpression', expression }; +} +export function tsNullKeyword(): NodeSchema { + return { type: 'TSNullKeyword', }; +} +export function tsNumberKeyword(): NodeSchema { + return { type: 'TSNumberKeyword', }; +} +export function tsObjectKeyword(): NodeSchema { + return { type: 'TSObjectKeyword', }; +} +export function tsOptionalType(typeAnnotation?: Schema): NodeSchema { + return { type: 'TSOptionalType', typeAnnotation }; +} +export function tsParameterProperty(parameter?: Schema): NodeSchema { + return { type: 'TSParameterProperty', parameter }; +} +export function tsParenthesizedType(typeAnnotation?: Schema): NodeSchema { + return { type: 'TSParenthesizedType', typeAnnotation }; +} +export function tsPropertySignature(key?: Schema, typeAnnotation?: Schema): NodeSchema { + return { type: 'TSPropertySignature', key, typeAnnotation }; +} +export function tsQualifiedName(left?: Schema, right?: Schema): NodeSchema { + return { type: 'TSQualifiedName', left, right }; +} +export function tsRestType(typeAnnotation?: Schema): NodeSchema { + return { type: 'TSRestType', typeAnnotation }; +} +export function tsSatisfiesExpression(expression?: Schema, typeAnnotation?: Schema): NodeSchema { + return { type: 'TSSatisfiesExpression', expression, typeAnnotation }; +} +export function tsStringKeyword(): NodeSchema { + return { type: 'TSStringKeyword', }; +} +export function tsSymbolKeyword(): NodeSchema { + return { type: 'TSSymbolKeyword', }; +} +export function tsTemplateLiteralType(quasis?: Schema>, types?: Schema>): NodeSchema { + return { type: 'TSTemplateLiteralType', quasis, types }; +} +export function tsThisType(): NodeSchema { + return { type: 'TSThisType', }; +} +export function tsTupleType(elementTypes?: Schema>): NodeSchema { + return { type: 'TSTupleType', elementTypes }; +} +export function tsTypeAliasDeclaration(id?: Schema, typeParameters?: Schema, typeAnnotation?: Schema): NodeSchema { + return { type: 'TSTypeAliasDeclaration', id, typeParameters, typeAnnotation }; +} +export function tsTypeAnnotation(typeAnnotation?: Schema): NodeSchema { + return { type: 'TSTypeAnnotation', typeAnnotation }; +} +export function tsTypeAssertion(typeAnnotation?: Schema, expression?: Schema): NodeSchema { + return { type: 'TSTypeAssertion', typeAnnotation, expression }; +} +export function tsTypeLiteral(members?: Schema>): NodeSchema { + return { type: 'TSTypeLiteral', members }; +} +export function tsTypeOperator(typeAnnotation?: Schema): NodeSchema { + return { type: 'TSTypeOperator', typeAnnotation }; +} +export function tsTypeParameter(constraint?: Schema, _default?: Schema, name?: Schema): NodeSchema { + return { type: 'TSTypeParameter', constraint, default: _default, name }; +} +export function tsTypeParameterDeclaration(params?: Schema>): NodeSchema { + return { type: 'TSTypeParameterDeclaration', params }; +} +export function tsTypeParameterInstantiation(params?: Schema>): NodeSchema { + return { type: 'TSTypeParameterInstantiation', params }; +} +export function tsTypePredicate(parameterName?: Schema, typeAnnotation?: Schema, asserts?: Schema): NodeSchema { + return { type: 'TSTypePredicate', parameterName, typeAnnotation, asserts }; +} +export function tsTypeQuery(exprName?: Schema, typeParameters?: Schema): NodeSchema { + return { type: 'TSTypeQuery', exprName, typeParameters }; +} +export function tsTypeReference(typeName?: Schema, typeParameters?: Schema): NodeSchema { + return { type: 'TSTypeReference', typeName, typeParameters }; +} +export function tsUndefinedKeyword(): NodeSchema { + return { type: 'TSUndefinedKeyword', }; +} +export function tsUnionType(types?: Schema>): NodeSchema { + return { type: 'TSUnionType', types }; +} +export function tsUnknownKeyword(): NodeSchema { + return { type: 'TSUnknownKeyword', }; +} +export function tsVoidKeyword(): NodeSchema { + return { type: 'TSVoidKeyword', }; +} +export function taggedTemplateExpression(tag?: Schema, quasi?: Schema): NodeSchema { + return { type: 'TaggedTemplateExpression', tag, quasi }; +} +export function templateElement(value?: Schema, tail?: Schema): NodeSchema { + return { type: 'TemplateElement', value, tail }; +} +export function templateLiteral(quasis?: Schema>, expressions?: Schema>): NodeSchema { + return { type: 'TemplateLiteral', quasis, expressions }; +} +export function thisExpression(): NodeSchema { + return { type: 'ThisExpression', }; +} +export function thisTypeAnnotation(): NodeSchema { + return { type: 'ThisTypeAnnotation', }; +} +export function throwStatement(argument?: Schema): NodeSchema { + return { type: 'ThrowStatement', argument }; +} +export function topicReference(): NodeSchema { + return { type: 'TopicReference', }; +} +export function tryStatement(block?: Schema, handler?: Schema, finalizer?: Schema): NodeSchema { + return { type: 'TryStatement', block, handler, finalizer }; +} +export function tupleExpression(elements?: Schema>): NodeSchema { + return { type: 'TupleExpression', elements }; +} +export function tupleTypeAnnotation(types?: Schema>): NodeSchema { + return { type: 'TupleTypeAnnotation', types }; +} +export function typeAlias(id?: Schema, typeParameters?: Schema, right?: Schema): NodeSchema { + return { type: 'TypeAlias', id, typeParameters, right }; +} +export function typeAnnotation(typeAnnotation?: Schema): NodeSchema { + return { type: 'TypeAnnotation', typeAnnotation }; +} +export function typeCastExpression(expression?: Schema, typeAnnotation?: Schema): NodeSchema { + return { type: 'TypeCastExpression', expression, typeAnnotation }; +} +export function typeParameter(bound?: Schema, _default?: Schema, variance?: Schema): NodeSchema { + return { type: 'TypeParameter', bound, default: _default, variance }; +} +export function typeParameterDeclaration(params?: Schema>): NodeSchema { + return { type: 'TypeParameterDeclaration', params }; +} +export function typeParameterInstantiation(params?: Schema>): NodeSchema { + return { type: 'TypeParameterInstantiation', params }; +} +export function typeofTypeAnnotation(argument?: Schema): NodeSchema { + return { type: 'TypeofTypeAnnotation', argument }; +} +export function unaryExpression(operator?: Schema<"void" | "throw" | "delete" | "!" | "+" | "-" | "~" | "typeof">, argument?: Schema, prefix?: Schema): NodeSchema { + return { type: 'UnaryExpression', operator, argument, prefix }; +} +export function unionTypeAnnotation(types?: Schema>): NodeSchema { + return { type: 'UnionTypeAnnotation', types }; +} +export function updateExpression(operator?: Schema<"++" | "--">, argument?: Schema, prefix?: Schema): NodeSchema { + return { type: 'UpdateExpression', operator, argument, prefix }; +} +export function v8IntrinsicIdentifier(name?: Schema): NodeSchema { + return { type: 'V8IntrinsicIdentifier', name }; +} +export function variableDeclaration(kind?: Schema<"var" | "let" | "const" | "using" | "await using">, declarations?: Schema>): NodeSchema { + return { type: 'VariableDeclaration', kind, declarations }; +} +export function variableDeclarator(id?: Schema, init?: Schema): NodeSchema { + return { type: 'VariableDeclarator', id, init }; +} +export function variance(kind?: Schema<"minus" | "plus">): NodeSchema { + return { type: 'Variance', kind }; +} +export function voidTypeAnnotation(): NodeSchema { + return { type: 'VoidTypeAnnotation', }; +} +export function whileStatement(test?: Schema, body?: Schema): NodeSchema { + return { type: 'WhileStatement', test, body }; +} +export function withStatement(object?: Schema, body?: Schema): NodeSchema { + return { type: 'WithStatement', object, body }; +} +export function yieldExpression(argument?: Schema, delegate?: Schema): NodeSchema { + return { type: 'YieldExpression', argument, delegate }; +} diff --git a/packages/matchers/src/index.ts b/packages/matchers/src/index.ts new file mode 100644 index 00000000..a624c09c --- /dev/null +++ b/packages/matchers/src/index.ts @@ -0,0 +1,4 @@ +export * from './compiler.js'; +export * from './generated.js'; +export * from './template'; +export * from './types.js'; diff --git a/packages/matchers/src/template.ts b/packages/matchers/src/template.ts new file mode 100644 index 00000000..5d96b531 --- /dev/null +++ b/packages/matchers/src/template.ts @@ -0,0 +1,112 @@ +import { parse, parseExpression, type ParserOptions } from '@babel/parser'; +import * as t from '@babel/types'; +import type { Schema } from './types'; +import { any, capture, fromCapture, type NodeSchema } from './types.js'; + +export function expression( + strings: TemplateStringsArray, + ...schemas: Schema[] +): NodeSchema { + return parseTemplate( + strings, + schemas, + parseExpression, + ) as NodeSchema; +} + +export function statement( + strings: TemplateStringsArray, + ...schemas: Schema[] +): NodeSchema { + return parseTemplate( + strings, + schemas, + parseStatement, + ) as NodeSchema; +} + +function parseStatement(input: string) { + return parse(input, { allowReturnOutsideFunction: true }).program.body[0]; +} + +function parseTemplate( + strings: TemplateStringsArray, + schemas: Schema[], + parse: (input: string, options?: ParserOptions) => t.Node, +): NodeSchema { + let schemaIndex = 0; + const captures = new Set(); + + const pattern = strings.reduce((acc, curr, i) => { + acc += curr; + + if (i < schemas.length) { + acc += `$${schemaIndex++}`; + } + + return acc; + }, ''); + + function isPlaceholder(node: t.Node): node is t.Identifier { + return t.isIdentifier(node) && /^\$\d+$/.test(node.name); + } + + function isMetaVariable(node: t.Node): node is t.Identifier { + return t.isIdentifier(node) && /^\$[A-Z_][A-Z0-9_]*$/i.test(node.name); + } + + const ast = parse(pattern); + let rootSchema: NodeSchema | undefined; + t.traverse(ast, { + enter(node, ancestors) { + function replace( + ancestor: { node: t.Node; key: string; index?: number }, + value?: unknown, + ) { + if (ancestor) { + const container = ancestor.node[ancestor.key as keyof t.Node]; + if (Array.isArray(container)) { + container[ancestor.index!] = value as never; + } else { + ancestor.node[ancestor.key as keyof t.Node] = value as never; + } + } else { + rootSchema = value as NodeSchema; + } + } + + if (isMetaVariable(node)) { + const name = node.name.slice(1); + if (name.startsWith('_')) { + schemas.push(any); + } else if (captures.has(name)) { + schemas.push(fromCapture(name)); + } else { + schemas.push(capture(name)); + captures.add(name); + } + node.name = `$${schemaIndex++}`; + } + + if (!isPlaceholder(node)) return; + const schema = schemas[Number(node.name.slice(1))]; + + if (ancestors.length === 0) { + rootSchema = schema as never; + return; + } + + if ( + ancestors.length >= 2 && + t.isExpressionStatement(ancestors.at(-1)!.node) && + schema === any + ) { + replace(ancestors.at(-2)!, any); + } else { + replace(ancestors.at(-1)!, schema); + } + }, + }); + + return rootSchema ?? ast; +} diff --git a/packages/matchers/src/types.ts b/packages/matchers/src/types.ts new file mode 100644 index 00000000..f216e420 --- /dev/null +++ b/packages/matchers/src/types.ts @@ -0,0 +1,101 @@ +import type * as t from '@babel/types'; + +type ExcludedNodeKeys = + | 'type' + | 'extra' + | 'start' + | 'end' + | 'loc' + | 'range' + | 'trailingComments' + | 'leadingComments' + | 'innerComments'; + +export type NodeSchema = { + type: T['type']; +} & { + [K in Exclude]?: Schema | undefined; +}; + +export type OrMatcher = { + type: 'or'; + schema: T; +}; +export type ArraySchema = { + type: 'arrayOf'; + schema: T; +}; +export type NullableSchema = { + type: 'nullable'; + schema: T; +}; +export type CaptureMatcher = { + type: 'capture'; + schema: T | undefined; + name: string; +}; +export type FromCaptureMatcher = { + type: 'fromCapture'; + name: string; +}; +export type PredicateMatcher = (input: T) => boolean; + +export type Matcher = + | OrMatcher + | ArraySchema + | NullableSchema + | CaptureMatcher + | FromCaptureMatcher; +// | PredicateMatcher; + +export type Schema = + | (T extends (infer U)[] + ? Schema[] + : { + [K in keyof T]?: Schema; + }) + | T + | undefined + | Matcher; + +export type Infer = + T extends NullableSchema + ? U | null + : T extends ArraySchema + ? U[] + : T extends OrMatcher + ? U + : T extends CaptureMatcher + ? U + : T extends FromCaptureMatcher + ? t.Identifier + : T; + +export const any = undefined; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function or[]>( + ...schema: T +): OrMatcher> { + return { type: 'or', schema } as never; +} + +export function arrayOf(schema: Schema): ArraySchema { + return { type: 'arrayOf', schema } as never; +} + +export function nullable(schema: Schema): NullableSchema { + return { type: 'nullable', schema } as never; +} + +export function capture( + name: string, + schema?: Schema, +): CaptureMatcher { + return { type: 'capture', schema, name } as never; +} + +// TODO: typed +export function fromCapture(name: string): FromCaptureMatcher { + return { type: 'fromCapture', name }; +} diff --git a/packages/matchers/test/captures.test.ts b/packages/matchers/test/captures.test.ts new file mode 100644 index 00000000..e884d950 --- /dev/null +++ b/packages/matchers/test/captures.test.ts @@ -0,0 +1,42 @@ +import { parseExpression } from '@babel/parser'; +import * as t from '@babel/types'; +import { expect, test } from 'vitest'; +import * as m from '../src'; + +test('capture number', () => { + const matcher = m.compile(m.numericLiteral(m.capture('value'))); + const captures = matcher(t.numericLiteral(1)); + expect(captures).toEqual({ value: 1 }); +}); + +test('capture node', () => { + const matcher = m.compile(m.variableDeclarator(m.capture('id'))); + const id = t.identifier('foo'); + const captures = matcher(t.variableDeclarator(id)); + expect(captures).toEqual({ id }); +}); + +test('capture node with schema', () => { + const matcher = m.compile( + // @ts-expect-error idk + m.binaryExpression('+', m.capture('left', m.numericLiteral())), + ); + const left = t.numericLiteral(1); + const captures = matcher(t.binaryExpression('+', left, t.numericLiteral(2))); + expect(captures).toEqual({ left }); + + const captures2 = matcher( + t.binaryExpression('+', t.stringLiteral('x'), t.numericLiteral(2)), + ); + expect(captures2).toBeUndefined(); +}); + +test('backreference', () => { + const matcher = m.compile( + m.binaryExpression('+', m.capture('id'), m.fromCapture('id')), + ); + expect(matcher(parseExpression('foo + foo'))).toMatchObject({ + id: { name: 'foo' }, + }); + expect(matcher(parseExpression('foo + bar'))).toBeUndefined(); +}); diff --git a/packages/matchers/test/nodes.test.ts b/packages/matchers/test/nodes.test.ts new file mode 100644 index 00000000..237d65e9 --- /dev/null +++ b/packages/matchers/test/nodes.test.ts @@ -0,0 +1,20 @@ +import * as t from '@babel/types'; +import { expect, test } from 'vitest'; +import * as m from '../src'; + +test('match any numeric literal', () => { + const matcher = m.compile(m.numericLiteral()); + expect(matcher(t.numericLiteral(1))).toBeTruthy(); + expect(matcher(t.stringLiteral('x'))).toBeUndefined(); +}); + +test('match specific numeric literal', () => { + const matcher = m.compile(m.numericLiteral(1)); + expect(matcher(t.numericLiteral(1))).toBeTruthy(); + expect(matcher(t.numericLiteral(2))).toBeUndefined(); +}); + +test('matching an unexpected node throws', () => { + const matcher = m.compile(m.variableDeclarator(m.identifier()), false); + expect(() => matcher(t.stringLiteral('x') as never)).toThrowError(); +}); diff --git a/packages/matchers/test/template.test.ts b/packages/matchers/test/template.test.ts new file mode 100644 index 00000000..e5f26a14 --- /dev/null +++ b/packages/matchers/test/template.test.ts @@ -0,0 +1,59 @@ +import { parse, parseExpression } from '@babel/parser'; +import { expect, test } from 'vitest'; +import * as m from '../src'; + +function parseStatement(input: string) { + return parse(input, { allowReturnOutsideFunction: true }).program.body[0]; +} + +test('parse expression template', () => { + const schema = m.expression`console.log(${m.or(m.numericLiteral(), m.stringLiteral())})`; + const matcher = m.compile(schema); + + expect(matcher(parseExpression('console.log(1)'))).toBeTruthy(); + expect(matcher(parseExpression('console.log(true)'))).toBeUndefined(); +}); + +test('parse statement template', () => { + const schema = m.statement`if (${m.capture('test')});`; + const matcher = m.compile(schema); + + expect(matcher(parseStatement('if (1);'))).toMatchObject({ + test: { value: 1 }, + }); +}); + +test('expression statement template with any', () => { + const schema = m.statement`if (1) ${m.any}`; + const matcher = m.compile(schema); + + expect(matcher(parseStatement('if (1) foo();'))).toBeTruthy(); + expect(matcher(parseStatement('if (1) var a;'))).toBeTruthy(); + expect(matcher(parseStatement('if (1) var a; else;'))).toBeUndefined(); +}); + +test('template with meta variable syntax', () => { + const schema = m.expression`console.log($greeting)`; + const matcher = m.compile(schema); + + expect(matcher(parseExpression('console.log("hello")'))).toMatchObject({ + greeting: { value: 'hello' }, + }); +}); + +test('template with non-capturing meta variable syntax', () => { + const schema = m.expression`$_method($_arg)`; + const matcher = m.compile(schema); + + expect(matcher(parseExpression('print(1)'))).not.toHaveProperty('_method'); +}); + +test('backreference', () => { + const schema = m.expression`$foo + $foo`; + const matcher = m.compile(schema); + + expect(matcher(parseExpression('a + a'))).toMatchObject({ + foo: { name: 'a' }, + }); + expect(matcher(parseExpression('a + b'))).toBeUndefined(); +}); diff --git a/packages/matchers/test/visitor.test.ts b/packages/matchers/test/visitor.test.ts new file mode 100644 index 00000000..e758d5be --- /dev/null +++ b/packages/matchers/test/visitor.test.ts @@ -0,0 +1,24 @@ +import traverse, { type NodePath } from '@babel/traverse'; +import * as t from '@babel/types'; +import { expect, test, vi } from 'vitest'; +import * as m from '../src'; + +test('visitor', () => { + const ast = t.program([t.emptyStatement(), t.returnStatement()]); + const testState = { foo: 'bar' }; + const cb = vi.fn(function ( + this: undefined, + path: NodePath, + state: unknown, + captures: object, + ) { + expect(path.type).toBe('ReturnStatement'); + expect(this).toBe(testState); + expect(state).toBe(testState); + expect(captures).toEqual({}); + }); + const visitor = m.compileVisitor(m.returnStatement()); + traverse(ast, visitor(cb), undefined, testState); + + expect(cb).toHaveBeenCalledOnce(); +}); diff --git a/packages/matchers/tsconfig.json b/packages/matchers/tsconfig.json new file mode 100644 index 00000000..39334e15 --- /dev/null +++ b/packages/matchers/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@webcrack/typescript-config/base.json", + "compilerOptions": { + "noEmit": true, + "verbatimModuleSyntax": true, + }, + "include": [ + "*.ts", + "src", + "test", + "scripts", + ] +} diff --git a/packages/matchers/vitest.config.ts b/packages/matchers/vitest.config.ts new file mode 100644 index 00000000..ebb0784a --- /dev/null +++ b/packages/matchers/vitest.config.ts @@ -0,0 +1,3 @@ +import { defineProject } from 'vitest/config'; + +export default defineProject({}); diff --git a/packages/webcrack/package.json b/packages/webcrack/package.json index 7427a9e2..243727f2 100644 --- a/packages/webcrack/package.json +++ b/packages/webcrack/package.json @@ -74,6 +74,7 @@ "@types/debug": "^4.1.12", "@types/node": "^22.13.16", "@webcrack/eslint-config": "workspace:*", + "@webcrack/matchers": "workspace:*", "@webcrack/typescript-config": "workspace:*", "esbuild": "^0.25.2", "typescript": "^5.8.2" diff --git a/packages/webcrack/src/unminify/test/void-to-undefined.test.ts b/packages/webcrack/src/unminify/test/void-to-undefined.test.ts index 63aec1f5..6efbd82b 100644 --- a/packages/webcrack/src/unminify/test/void-to-undefined.test.ts +++ b/packages/webcrack/src/unminify/test/void-to-undefined.test.ts @@ -6,6 +6,8 @@ const expectJS = testTransform(voidToUndefined); test('void 0', () => expectJS('void 0').toMatchInlineSnapshot('undefined;')); +test('void 1', () => expectJS('void 1').toMatchInlineSnapshot('undefined;')); + test('ignore when undefined is declared in scope', () => expectJS('let undefined = 1; { void 0; }').toMatchInlineSnapshot(` let undefined = 1; diff --git a/packages/webcrack/src/unminify/transforms/void-to-undefined.ts b/packages/webcrack/src/unminify/transforms/void-to-undefined.ts index dfa708f7..3aee15c7 100644 --- a/packages/webcrack/src/unminify/transforms/void-to-undefined.ts +++ b/packages/webcrack/src/unminify/transforms/void-to-undefined.ts @@ -1,25 +1,20 @@ import * as t from '@babel/types'; -import * as m from '@codemod/matchers'; +import * as m from '@webcrack/matchers'; import type { Transform } from '../../ast-utils'; +const onVoidNumber = m.compileVisitor( + m.unaryExpression('void', m.numericLiteral()), +); + export default { name: 'void-to-undefined', tags: ['safe'], scope: true, - visitor: () => { - const matcher = m.unaryExpression('void', m.numericLiteral(0)); - return { - UnaryExpression: { - exit(path) { - if ( - matcher.match(path.node) && - !path.scope.hasBinding('undefined', { noGlobals: true }) - ) { - path.replaceWith(t.identifier('undefined')); - this.changes++; - } - }, - }, - }; - }, + visitor: () => + onVoidNumber((path, state) => { + if (!path.scope.hasBinding('undefined', { noGlobals: true })) { + path.replaceWith(t.identifier('undefined')); + state.changes++; + } + }), } satisfies Transform; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e029c305..553e24f7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,10 +19,10 @@ importers: devDependencies: '@vitest/coverage-istanbul': specifier: ^3.1.1 - version: 3.1.1(vitest@3.1.1(@types/debug@4.1.12)(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3)) + version: 3.1.1(vitest@3.1.1(@types/debug@4.1.12)(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3)) '@vitest/coverage-v8': specifier: ^3.1.1 - version: 3.1.1(vitest@3.1.1(@types/debug@4.1.12)(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3)) + version: 3.1.1(vitest@3.1.1(@types/debug@4.1.12)(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3)) '@webcrack/eslint-config': specifier: workspace:* version: link:packages/config-eslint @@ -37,7 +37,7 @@ importers: version: 2.4.4 vitest: specifier: ^3.1.1 - version: 3.1.1(@types/debug@4.1.12)(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3) + version: 3.1.1(@types/debug@4.1.12)(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3) apps/docs: devDependencies: @@ -86,7 +86,7 @@ importers: version: 4.0.17 '@tailwindcss/vite': specifier: ^4.0.17 - version: 4.0.17(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3)) + version: 4.0.17(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3)) '@types/babel__generator': specifier: ^7.6.8 version: 7.6.8 @@ -110,16 +110,16 @@ importers: version: 5.8.2 vite: specifier: ^6.2.4 - version: 6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3) + version: 6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3) vite-plugin-monaco-editor: specifier: ^1.1.0 version: 1.1.0(patch_hash=ml6vuvpbq2picjecjfyjy32u4e)(monaco-editor@0.52.2) vite-plugin-node-polyfills: specifier: ^0.23.0 - version: 0.23.0(rollup@4.34.2)(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3)) + version: 0.23.0(rollup@4.34.2)(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3)) vite-plugin-solid: specifier: ^2.11.6 - version: 2.11.6(solid-js@1.9.5)(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3)) + version: 2.11.6(solid-js@1.9.5)(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3)) apps/web: dependencies: @@ -141,6 +141,43 @@ importers: packages/config-typescript: {} + packages/matchers: + dependencies: + '@babel/parser': + specifier: ^7.27.0 + version: 7.27.0 + '@babel/types': + specifier: ^7.27.0 + version: 7.27.0 + devDependencies: + '@babel/traverse': + specifier: ^7.27.0 + version: 7.27.0 + '@codemod/matchers': + specifier: ^1.7.1 + version: 1.7.1 + '@types/babel__traverse': + specifier: ^7.20.7 + version: 7.20.7 + '@types/node': + specifier: ^22.13.16 + version: 22.13.16 + '@webcrack/eslint-config': + specifier: workspace:* + version: link:../config-eslint + '@webcrack/typescript-config': + specifier: workspace:* + version: link:../config-typescript + benny: + specifier: ^3.7.1 + version: 3.7.1 + tsx: + specifier: ^4.19.3 + version: 4.19.3 + typescript: + specifier: ^5.8.2 + version: 5.8.2 + packages/webcrack: dependencies: '@babel/generator': @@ -195,6 +232,9 @@ importers: '@webcrack/eslint-config': specifier: workspace:* version: link:../config-eslint + '@webcrack/matchers': + specifier: workspace:* + version: link:../matchers '@webcrack/typescript-config': specifier: workspace:* version: link:../config-typescript @@ -287,6 +327,21 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} + '@arrows/array@1.4.1': + resolution: {integrity: sha512-MGYS8xi3c4tTy1ivhrVntFvufoNzje0PchjEz6G/SsWRgUKxL4tKwS6iPdO8vsaJYldagAeWMd5KRD0aX3Q39g==} + + '@arrows/composition@1.2.2': + resolution: {integrity: sha512-9fh1yHwrx32lundiB3SlZ/VwuStPB4QakPsSLrGJFH6rCXvdrd060ivAZ7/2vlqPnEjBkPRRXOcG1YOu19p2GQ==} + + '@arrows/dispatch@1.0.3': + resolution: {integrity: sha512-v/HwvrFonitYZM2PmBlAlCqVqxrkIIoiEuy5bQgn0BdfvlL0ooSBzcPzTMrtzY8eYktPyYcHg8fLbSgyybXEqw==} + + '@arrows/error@1.0.2': + resolution: {integrity: sha512-yvkiv1ay4Z3+Z6oQsUkedsQm5aFdyPpkBUQs8vejazU/RmANABx6bMMcBPPHI4aW43VPQmXFfBzr/4FExwWTEA==} + + '@arrows/multimethod@1.4.1': + resolution: {integrity: sha512-AZnAay0dgPnCJxn3We5uKiB88VL+1ZIF2SjZohLj6vqY2UyvB/sKdDnFP+LZNVsTC5lcnGPmLlRRkAh4sXkXsQ==} + '@babel/code-frame@7.26.2': resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} @@ -1296,6 +1351,10 @@ packages: resolution: {integrity: sha512-7TCj+hLx6fZKppLL74lYGDEltSBNSu4vqRwgqeIKZ3VQ0q3aOrdEN0f1sDWcvU1b+psn2wnl7aHt9hWtYatUUA==} engines: {node: '>= 14.0.0'} + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -1325,6 +1384,10 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -1378,6 +1441,13 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + benchmark@2.1.4: + resolution: {integrity: sha512-l9MlfN4M1K/H2fbhfMy3B7vJd6AGKJVQn2h6Sg/Yx+KckoUA7ewS5Vv6TjSq18ooE1kS9hhAlQRH3AkXIh/aOQ==} + + benny@3.7.1: + resolution: {integrity: sha512-USzYxODdVfOS7JuQq/L0naxB788dWCiUgUTxvN+WLPt/JfcDURNNj8kN/N+uK6PDvuR67/9/55cVKGPleFQINA==} + engines: {node: '>=12'} + birpc@0.2.19: resolution: {integrity: sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==} @@ -1475,6 +1545,10 @@ packages: cipher-base@1.0.4: resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} + cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -1489,6 +1563,14 @@ packages: resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} engines: {node: '>=18'} + commander@6.2.1: + resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} + engines: {node: '>= 6'} + + common-tags@1.8.2: + resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} + engines: {node: '>=4.0.0'} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -1761,6 +1843,10 @@ packages: resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} engines: {node: '>=14'} + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -1777,6 +1863,9 @@ packages: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} + get-tsconfig@4.10.0: + resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} + github-from-package@0.0.0: resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} @@ -1998,14 +2087,31 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + json2csv@5.0.7: + resolution: {integrity: sha512-YRZbUnyaJZLZUJSRi2G/MqahCyRv9n/ds+4oIetjDF3jWQA7AG7iSeKTiZiCNqtMZM7HDyt0e/W6lEnoGEmMGA==} + engines: {node: '>= 10', npm: '>= 6.13.0'} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + hasBin: true + json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -2078,9 +2184,20 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash.get@4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + deprecated: This package is deprecated. Use the optional chaining (?.) operator instead. + lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + log-update@4.0.0: + resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} + engines: {node: '>=10'} + loupe@3.1.3: resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} @@ -2141,6 +2258,10 @@ packages: resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} hasBin: true + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + mimic-response@3.1.0: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} @@ -2220,6 +2341,10 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + oniguruma-to-es@3.1.1: resolution: {integrity: sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==} @@ -2292,6 +2417,9 @@ packages: resolution: {integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==} engines: {node: '>=10'} + platform@1.3.6: + resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==} + possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} @@ -2381,10 +2509,17 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve@1.22.8: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} hasBin: true + restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -2463,6 +2598,9 @@ packages: siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} @@ -2473,6 +2611,10 @@ packages: simple-get@4.0.1: resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + solid-js@1.9.5: resolution: {integrity: sha512-ogI3DaFcyn6UhYhrgcyRAMbu/buBJitYQASZz5WzfQVPP10RD2AbCoRZ517psnezrasyCbWzIxZ6kVqet768xw==} @@ -2610,6 +2752,11 @@ packages: peerDependencies: typescript: '>=4.8.4' + tsx@4.19.3: + resolution: {integrity: sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==} + engines: {node: '>=18.0.0'} + hasBin: true + tty-browserify@0.0.1: resolution: {integrity: sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==} @@ -2654,6 +2801,10 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + typescript-eslint@8.29.0: resolution: {integrity: sha512-ep9rVd9B4kQsZ7ZnWCVxUE/xDLUUUsRzE0poAeNu+4CkFErLfuvPt/qtm2EpnSyfvsR0S6QzDFSrPCFBwf64fg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2684,6 +2835,10 @@ packages: unist-util-visit@5.0.0: resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + update-browserslist-db@1.1.0: resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==} hasBin: true @@ -2884,6 +3039,10 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -3028,6 +3187,25 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 + '@arrows/array@1.4.1': + dependencies: + '@arrows/composition': 1.2.2 + + '@arrows/composition@1.2.2': {} + + '@arrows/dispatch@1.0.3': + dependencies: + '@arrows/composition': 1.2.2 + + '@arrows/error@1.0.2': {} + + '@arrows/multimethod@1.4.1': + dependencies: + '@arrows/array': 1.4.1 + '@arrows/composition': 1.2.2 + '@arrows/error': 1.0.2 + fast-deep-equal: 3.1.3 + '@babel/code-frame@7.26.2': dependencies: '@babel/helper-validator-identifier': 7.25.9 @@ -3630,13 +3808,13 @@ snapshots: postcss: 8.5.3 tailwindcss: 4.0.17 - '@tailwindcss/vite@4.0.17(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3))': + '@tailwindcss/vite@4.0.17(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3))': dependencies: '@tailwindcss/node': 4.0.17 '@tailwindcss/oxide': 4.0.17 lightningcss: 1.29.2 tailwindcss: 4.0.17 - vite: 6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3) + vite: 6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3) '@types/babel__core@7.20.5': dependencies: @@ -3780,7 +3958,7 @@ snapshots: vite: 5.4.16(@types/node@22.13.16)(lightningcss@1.29.2) vue: 3.5.13(typescript@5.8.2) - '@vitest/coverage-istanbul@3.1.1(vitest@3.1.1(@types/debug@4.1.12)(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3))': + '@vitest/coverage-istanbul@3.1.1(vitest@3.1.1(@types/debug@4.1.12)(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3))': dependencies: '@istanbuljs/schema': 0.1.3 debug: 4.4.0 @@ -3792,11 +3970,11 @@ snapshots: magicast: 0.3.5 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.1.1(@types/debug@4.1.12)(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3) + vitest: 3.1.1(@types/debug@4.1.12)(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3) transitivePeerDependencies: - supports-color - '@vitest/coverage-v8@3.1.1(vitest@3.1.1(@types/debug@4.1.12)(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3))': + '@vitest/coverage-v8@3.1.1(vitest@3.1.1(@types/debug@4.1.12)(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 @@ -3810,7 +3988,7 @@ snapshots: std-env: 3.8.1 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.1.1(@types/debug@4.1.12)(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3) + vitest: 3.1.1(@types/debug@4.1.12)(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3) transitivePeerDependencies: - supports-color @@ -3821,13 +3999,13 @@ snapshots: chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.1.1(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3))': + '@vitest/mocker@3.1.1(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3))': dependencies: '@vitest/spy': 3.1.1 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3) + vite: 6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3) '@vitest/pretty-format@3.1.1': dependencies: @@ -3984,6 +4162,10 @@ snapshots: '@algolia/requester-fetch': 5.23.0 '@algolia/requester-node-http': 5.23.0 + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + ansi-regex@5.0.1: {} ansi-regex@6.0.1: {} @@ -4012,6 +4194,8 @@ snapshots: assertion-error@2.0.1: {} + astral-regex@2.0.0: {} + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 @@ -4061,6 +4245,23 @@ snapshots: base64-js@1.5.1: {} + benchmark@2.1.4: + dependencies: + lodash: 4.17.21 + platform: 1.3.6 + + benny@3.7.1: + dependencies: + '@arrows/composition': 1.2.2 + '@arrows/dispatch': 1.0.3 + '@arrows/multimethod': 1.4.1 + benchmark: 2.1.4 + common-tags: 1.8.2 + fs-extra: 10.1.0 + json2csv: 5.0.7 + kleur: 4.1.5 + log-update: 4.0.0 + birpc@0.2.19: {} bn.js@4.12.0: {} @@ -4186,6 +4387,10 @@ snapshots: inherits: 2.0.4 safe-buffer: 5.2.1 + cli-cursor@3.1.0: + dependencies: + restore-cursor: 3.1.0 + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -4196,6 +4401,10 @@ snapshots: commander@13.1.0: {} + commander@6.2.1: {} + + common-tags@1.8.2: {} + concat-map@0.0.1: {} console-browserify@1.2.0: {} @@ -4547,6 +4756,12 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + fsevents@2.3.3: optional: true @@ -4562,6 +4777,10 @@ snapshots: has-symbols: 1.0.3 hasown: 2.0.2 + get-tsconfig@4.10.0: + dependencies: + resolve-pkg-maps: 1.0.0 + github-from-package@0.0.0: {} glob-parent@5.1.2: @@ -4778,12 +4997,28 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} + json2csv@5.0.7: + dependencies: + commander: 6.2.1 + jsonparse: 1.3.1 + lodash.get: 4.4.2 + json5@2.2.3: {} + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonparse@1.3.1: {} + keyv@4.5.4: dependencies: json-buffer: 3.0.1 + kleur@4.1.5: {} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -4838,8 +5073,19 @@ snapshots: dependencies: p-locate: 5.0.0 + lodash.get@4.4.2: {} + lodash.merge@4.6.2: {} + lodash@4.17.21: {} + + log-update@4.0.0: + dependencies: + ansi-escapes: 4.3.2 + cli-cursor: 3.1.0 + slice-ansi: 4.0.0 + wrap-ansi: 6.2.0 + loupe@3.1.3: {} lru-cache@10.2.2: {} @@ -4915,6 +5161,8 @@ snapshots: bn.js: 4.12.0 brorand: 1.1.0 + mimic-fn@2.1.0: {} + mimic-response@3.1.0: {} minimalistic-assert@1.0.1: {} @@ -5005,6 +5253,10 @@ snapshots: dependencies: wrappy: 1.0.2 + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + oniguruma-to-es@3.1.1: dependencies: emoji-regex-xs: 1.0.0 @@ -5080,6 +5332,8 @@ snapshots: dependencies: find-up: 5.0.0 + platform@1.3.6: {} + possible-typed-array-names@1.0.0: {} postcss@8.5.3: @@ -5187,12 +5441,19 @@ snapshots: resolve-from@4.0.0: {} + resolve-pkg-maps@1.0.0: {} + resolve@1.22.8: dependencies: is-core-module: 2.13.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + restore-cursor@3.1.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + reusify@1.0.4: {} rfdc@1.4.1: {} @@ -5291,6 +5552,8 @@ snapshots: siginfo@2.0.0: {} + signal-exit@3.0.7: {} + signal-exit@4.1.0: {} simple-concat@1.0.1: {} @@ -5301,6 +5564,12 @@ snapshots: once: 1.4.0 simple-concat: 1.0.1 + slice-ansi@4.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + solid-js@1.9.5: dependencies: csstype: 3.1.3 @@ -5448,6 +5717,13 @@ snapshots: dependencies: typescript: 5.8.2 + tsx@4.19.3: + dependencies: + esbuild: 0.25.2 + get-tsconfig: 4.10.0 + optionalDependencies: + fsevents: 2.3.3 + tty-browserify@0.0.1: {} tunnel-agent@0.6.0: @@ -5485,6 +5761,8 @@ snapshots: dependencies: prelude-ls: 1.2.1 + type-fest@0.21.3: {} + typescript-eslint@8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2): dependencies: '@typescript-eslint/eslint-plugin': 8.29.0(@typescript-eslint/parser@8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2) @@ -5522,6 +5800,8 @@ snapshots: unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 + universalify@2.0.1: {} + update-browserslist-db@1.1.0(browserslist@4.23.3): dependencies: browserslist: 4.23.3 @@ -5560,13 +5840,13 @@ snapshots: unist-util-stringify-position: 4.0.0 vfile-message: 4.0.2 - vite-node@3.1.1(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3): + vite-node@3.1.1(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3): dependencies: cac: 6.7.14 debug: 4.4.0 es-module-lexer: 1.6.0 pathe: 2.0.3 - vite: 6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3) + vite: 6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3) transitivePeerDependencies: - '@types/node' - jiti @@ -5585,15 +5865,15 @@ snapshots: dependencies: monaco-editor: 0.52.2 - vite-plugin-node-polyfills@0.23.0(rollup@4.34.2)(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3)): + vite-plugin-node-polyfills@0.23.0(rollup@4.34.2)(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3)): dependencies: '@rollup/plugin-inject': 5.0.5(rollup@4.34.2) node-stdlib-browser: 1.2.0 - vite: 6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3) + vite: 6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3) transitivePeerDependencies: - rollup - vite-plugin-solid@2.11.6(solid-js@1.9.5)(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3)): + vite-plugin-solid@2.11.6(solid-js@1.9.5)(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3)): dependencies: '@babel/core': 7.24.7 '@types/babel__core': 7.20.5 @@ -5601,8 +5881,8 @@ snapshots: merge-anything: 5.1.7 solid-js: 1.9.5 solid-refresh: 0.6.3(solid-js@1.9.5) - vite: 6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3) - vitefu: 1.0.6(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3)) + vite: 6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3) + vitefu: 1.0.6(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3)) transitivePeerDependencies: - supports-color @@ -5616,7 +5896,7 @@ snapshots: fsevents: 2.3.3 lightningcss: 1.29.2 - vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3): + vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3): dependencies: esbuild: 0.25.0 postcss: 8.5.3 @@ -5626,11 +5906,12 @@ snapshots: fsevents: 2.3.3 jiti: 2.4.2 lightningcss: 1.29.2 + tsx: 4.19.3 yaml: 2.4.3 - vitefu@1.0.6(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3)): + vitefu@1.0.6(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3)): optionalDependencies: - vite: 6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3) + vite: 6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3) vitepress@1.6.3(@algolia/client-search@5.23.0)(@types/node@22.13.16)(lightningcss@1.29.2)(postcss@8.5.3)(search-insights@2.14.0)(typescript@5.8.2): dependencies: @@ -5681,10 +5962,10 @@ snapshots: - typescript - universal-cookie - vitest@3.1.1(@types/debug@4.1.12)(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3): + vitest@3.1.1(@types/debug@4.1.12)(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3): dependencies: '@vitest/expect': 3.1.1 - '@vitest/mocker': 3.1.1(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3)) + '@vitest/mocker': 3.1.1(vite@6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3)) '@vitest/pretty-format': 3.1.1 '@vitest/runner': 3.1.1 '@vitest/snapshot': 3.1.1 @@ -5700,8 +5981,8 @@ snapshots: tinyexec: 0.3.2 tinypool: 1.0.2 tinyrainbow: 2.0.0 - vite: 6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3) - vite-node: 3.1.1(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.4.3) + vite: 6.2.4(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3) + vite-node: 3.1.1(@types/node@22.13.16)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)(yaml@2.4.3) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 @@ -5751,6 +6032,12 @@ snapshots: word-wrap@1.2.5: {} + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0