@codehz/json-expr 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +325 -0
- package/dist/index.d.mts +365 -0
- package/dist/index.mjs +981 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +61 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* 表示一个类型化变量
|
|
6
|
+
* @template T - Zod schema 类型
|
|
7
|
+
*/
|
|
8
|
+
type Variable<T extends z.ZodType = z.ZodType> = {
|
|
9
|
+
_tag: "variable";
|
|
10
|
+
schema: T;
|
|
11
|
+
_type: z.infer<T>;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* 表示一个表达式
|
|
15
|
+
* @template TContext - 表达式上下文类型
|
|
16
|
+
* @template TResult - 表达式结果类型
|
|
17
|
+
*/
|
|
18
|
+
type Expression<TContext = Record<string, unknown>, TResult = unknown> = {
|
|
19
|
+
_tag: "expression";
|
|
20
|
+
context: TContext;
|
|
21
|
+
source: string;
|
|
22
|
+
_type: TResult;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* 编译后的可序列化结构
|
|
26
|
+
* 数组形式:[string[], ...string[]]
|
|
27
|
+
* - 第一个元素是变量名列表
|
|
28
|
+
* - 后续是表达式序列,使用 $N 引用前面的变量或表达式
|
|
29
|
+
*/
|
|
30
|
+
type CompiledData = [variableNames: string[], ...expressions: string[]];
|
|
31
|
+
/**
|
|
32
|
+
* 内部表达式节点接口(供编译器使用)
|
|
33
|
+
*/
|
|
34
|
+
interface ExprNode {
|
|
35
|
+
id: symbol;
|
|
36
|
+
tag: "variable" | "expression";
|
|
37
|
+
schema?: z.ZodType;
|
|
38
|
+
context?: Record<string, ExprNode>;
|
|
39
|
+
source?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 编译上下文接口(供编译器使用)
|
|
43
|
+
*/
|
|
44
|
+
interface CompileContext {
|
|
45
|
+
variableOrder: string[];
|
|
46
|
+
nodeToIndex: Map<symbol, number>;
|
|
47
|
+
expressions: string[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* 从 Variable 推导值类型
|
|
51
|
+
* @template V - Variable 类型
|
|
52
|
+
*/
|
|
53
|
+
type InferVariableType<V> = V extends Variable<infer T> ? z.infer<T> : never;
|
|
54
|
+
/**
|
|
55
|
+
* 从上下文对象推导各项的类型
|
|
56
|
+
* @template C - 上下文对象类型
|
|
57
|
+
*/
|
|
58
|
+
type InferContextType<C> = { [K in keyof C]: C[K] extends Variable<infer T> ? z.infer<T> : C[K] extends Expression<unknown, infer R> ? R : never };
|
|
59
|
+
/**
|
|
60
|
+
* 从 Expression 推导结果类型
|
|
61
|
+
* @template E - Expression 类型
|
|
62
|
+
*/
|
|
63
|
+
type InferExpressionType<E> = E extends Expression<unknown, infer R> ? R : never;
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/compile.d.ts
|
|
66
|
+
/**
|
|
67
|
+
* 编译选项
|
|
68
|
+
*/
|
|
69
|
+
interface CompileOptions {
|
|
70
|
+
/**
|
|
71
|
+
* 是否启用内联优化
|
|
72
|
+
* 将只被引用一次的子表达式内联到使用位置
|
|
73
|
+
* @default true
|
|
74
|
+
*/
|
|
75
|
+
inline?: boolean;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* 表达式上下文类型约束
|
|
79
|
+
*/
|
|
80
|
+
type ExpressionContext = Record<string, Variable<z.ZodType> | Expression<Record<string, unknown>, unknown>>;
|
|
81
|
+
/**
|
|
82
|
+
* 将表达式树编译为可序列化的 JSON 结构
|
|
83
|
+
*
|
|
84
|
+
* @template TResult - 表达式结果类型
|
|
85
|
+
* @param expression - 根表达式
|
|
86
|
+
* @param variables - 所有使用的变量定义
|
|
87
|
+
* @param options - 编译选项
|
|
88
|
+
* @returns 编译后的数据结构 [变量名列表, 表达式1, 表达式2, ...]
|
|
89
|
+
*
|
|
90
|
+
* @throws 如果检测到循环依赖或未定义的变量引用
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* const x = variable(z.number())
|
|
95
|
+
* const y = variable(z.number())
|
|
96
|
+
* const sum = expr({ x, y })<number>("x + y")
|
|
97
|
+
* const result = expr({ sum })<number>("sum * 2")
|
|
98
|
+
* const compiled = compile(result, { x, y })
|
|
99
|
+
* // => [["x", "y"], "($0+$1)*2"] // 内联优化后
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
declare function compile<TResult>(expression: Expression<ExpressionContext, TResult>, variables: Record<string, Variable<z.ZodType>>, options?: CompileOptions): CompiledData;
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region src/evaluate.d.ts
|
|
105
|
+
/**
|
|
106
|
+
* 执行编译后的表达式
|
|
107
|
+
*
|
|
108
|
+
* @template TResult - 表达式结果类型
|
|
109
|
+
* @param data - 编译后的数据结构 [变量名列表, 表达式1, 表达式2, ...]
|
|
110
|
+
* @param values - 变量值映射,按变量名提供值
|
|
111
|
+
* @returns 最后一个表达式的求值结果
|
|
112
|
+
*
|
|
113
|
+
* @throws 如果运行时类型验证失败或表达式执行出错
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```ts
|
|
117
|
+
* const compiled = [["x", "y"], "$0+$1", "$1*2"]
|
|
118
|
+
* const result = evaluate<number>(compiled, { x: 2, y: 3 })
|
|
119
|
+
* // => 6 (3 * 2)
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
declare function evaluate<TResult>(data: CompiledData, values: Record<string, unknown>): TResult;
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region src/type-parser.d.ts
|
|
125
|
+
/** 去除字符串两端空白 */
|
|
126
|
+
type TrimStart<S extends string> = S extends ` ${infer Rest}` | `\t${infer Rest}` | `\n${infer Rest}` ? TrimStart<Rest> : S;
|
|
127
|
+
/** 是否是字母或下划线 */
|
|
128
|
+
type IsIdentifierStart<C extends string> = C extends "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" | "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" | "_" | "$" ? true : false;
|
|
129
|
+
/** 是否是标识符字符(字母、数字、下划线) */
|
|
130
|
+
type IsIdentifierChar<C extends string> = IsIdentifierStart<C> extends true ? true : C extends "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ? true : false;
|
|
131
|
+
/** 是否是数字 */
|
|
132
|
+
type IsDigit<C extends string> = C extends "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ? true : false;
|
|
133
|
+
/** JS保留字和全局对象 */
|
|
134
|
+
type ReservedWords = "true" | "false" | "null" | "undefined" | "if" | "else" | "for" | "while" | "do" | "switch" | "case" | "break" | "continue" | "return" | "function" | "var" | "let" | "const" | "class" | "new" | "this" | "typeof" | "instanceof" | "Math" | "Number" | "String" | "Boolean" | "Array" | "Object" | "Date" | "JSON" | "parseInt" | "parseFloat" | "isNaN" | "isFinite" | "NaN" | "Infinity";
|
|
135
|
+
/** 解析一个标识符,返回 [标识符, 剩余字符串] */
|
|
136
|
+
type ParseIdentifier<S extends string, Acc extends string = ""> = S extends `${infer C}${infer Rest}` ? IsIdentifierChar<C> extends true ? ParseIdentifier<Rest, `${Acc}${C}`> : [Acc, S] : [Acc, S];
|
|
137
|
+
/** 跳过数字字面量 */
|
|
138
|
+
type SkipNumber<S extends string> = S extends `${infer C}${infer Rest}` ? C extends "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "." ? SkipNumber<Rest> : S : S;
|
|
139
|
+
/** 跳过字符串字面量(单引号) */
|
|
140
|
+
type SkipSingleQuoteString<S extends string> = S extends `'${infer Rest}` ? SkipSingleQuoteStringContent<Rest> : S;
|
|
141
|
+
type SkipSingleQuoteStringContent<S extends string> = S extends `\\'${infer Rest}` ? SkipSingleQuoteStringContent<Rest> : S extends `'${infer Rest}` ? Rest : S extends `${string}${infer Rest}` ? SkipSingleQuoteStringContent<Rest> : S;
|
|
142
|
+
/** 跳过字符串字面量(双引号) */
|
|
143
|
+
type SkipDoubleQuoteString<S extends string> = S extends `"${infer Rest}` ? SkipDoubleQuoteStringContent<Rest> : S;
|
|
144
|
+
type SkipDoubleQuoteStringContent<S extends string> = S extends `\\"${infer Rest}` ? SkipDoubleQuoteStringContent<Rest> : S extends `"${infer Rest}` ? Rest : S extends `${string}${infer Rest}` ? SkipDoubleQuoteStringContent<Rest> : S;
|
|
145
|
+
/** 跳过模板字符串 */
|
|
146
|
+
type SkipTemplateString<S extends string> = S extends `\`${infer Rest}` ? SkipTemplateStringContent<Rest> : S;
|
|
147
|
+
type SkipTemplateStringContent<S extends string> = S extends `\\\`${infer Rest}` ? SkipTemplateStringContent<Rest> : S extends `\`${infer Rest}` ? Rest : S extends `${string}${infer Rest}` ? SkipTemplateStringContent<Rest> : S;
|
|
148
|
+
/**
|
|
149
|
+
* 从表达式字符串中提取所有标识符(排除保留字)
|
|
150
|
+
* 返回标识符的联合类型
|
|
151
|
+
*/
|
|
152
|
+
type ExtractIdentifiers<S extends string, Collected extends string = never> = S extends "" ? Collected : TrimStart<S> extends `${infer Trimmed}` ? Trimmed extends "" ? Collected : Trimmed extends `'${string}` ? ExtractIdentifiers<SkipSingleQuoteString<Trimmed>, Collected> : Trimmed extends `"${string}` ? ExtractIdentifiers<SkipDoubleQuoteString<Trimmed>, Collected> : Trimmed extends `\`${string}` ? ExtractIdentifiers<SkipTemplateString<Trimmed>, Collected> : Trimmed extends `${infer First}${infer Rest}` ? IsIdentifierStart<First> extends true ? ParseIdentifier<Trimmed> extends [infer Id extends string, infer Remaining extends string] ? Id extends ReservedWords ? ExtractIdentifiers<Remaining, Collected> : ExtractIdentifiers<Remaining, Collected | Id> : Collected : IsDigit<First> extends true ? ExtractIdentifiers<SkipNumber<Trimmed>, Collected> : ExtractIdentifiers<Rest, Collected> : Collected : Collected;
|
|
153
|
+
/** 从 Variable 或 Expression 提取值类型 */
|
|
154
|
+
type ExtractType<T> = T extends Variable<infer Schema> ? z.infer<Schema> : T extends Expression<unknown, infer R> ? R : never;
|
|
155
|
+
/** 从上下文对象构建类型映射 */
|
|
156
|
+
type ContextTypeMap<TContext> = { [K in keyof TContext]: ExtractType<TContext[K]> };
|
|
157
|
+
/** 找出未定义的标识符 */
|
|
158
|
+
type FindUndefinedIdentifiers<Ids extends string, ContextKeys extends string> = Ids extends ContextKeys ? never : Ids;
|
|
159
|
+
interface ASTNumber {
|
|
160
|
+
type: "number";
|
|
161
|
+
}
|
|
162
|
+
interface ASTString {
|
|
163
|
+
type: "string";
|
|
164
|
+
}
|
|
165
|
+
interface ASTBoolean {
|
|
166
|
+
type: "boolean";
|
|
167
|
+
}
|
|
168
|
+
interface ASTIdentifier<Name extends string = string> {
|
|
169
|
+
type: "identifier";
|
|
170
|
+
name: Name;
|
|
171
|
+
}
|
|
172
|
+
interface ASTBinary<Op extends string = string, Left = unknown, Right = unknown> {
|
|
173
|
+
type: "binary";
|
|
174
|
+
op: Op;
|
|
175
|
+
left: Left;
|
|
176
|
+
right: Right;
|
|
177
|
+
}
|
|
178
|
+
interface ASTUnary<Op extends string = string, Operand = unknown> {
|
|
179
|
+
type: "unary";
|
|
180
|
+
op: Op;
|
|
181
|
+
operand: Operand;
|
|
182
|
+
}
|
|
183
|
+
interface ASTTernary<Cond = unknown, Then = unknown, Else = unknown> {
|
|
184
|
+
type: "ternary";
|
|
185
|
+
condition: Cond;
|
|
186
|
+
then: Then;
|
|
187
|
+
else: Else;
|
|
188
|
+
}
|
|
189
|
+
interface ASTParen<Inner = unknown> {
|
|
190
|
+
type: "paren";
|
|
191
|
+
inner: Inner;
|
|
192
|
+
}
|
|
193
|
+
interface ASTMemberAccess<Obj = unknown, Prop extends string = string> {
|
|
194
|
+
type: "member";
|
|
195
|
+
object: Obj;
|
|
196
|
+
property: Prop;
|
|
197
|
+
}
|
|
198
|
+
interface ASTCall<Callee = unknown, Args extends unknown[] = unknown[]> {
|
|
199
|
+
type: "call";
|
|
200
|
+
callee: Callee;
|
|
201
|
+
args: Args;
|
|
202
|
+
}
|
|
203
|
+
interface ASTUnknown {
|
|
204
|
+
type: "unknown";
|
|
205
|
+
}
|
|
206
|
+
/** 运算符优先级(从低到高) */
|
|
207
|
+
/** 解析结果:[AST, 剩余字符串] */
|
|
208
|
+
type ParseResult<T, Rest extends string> = {
|
|
209
|
+
ast: T;
|
|
210
|
+
rest: Rest;
|
|
211
|
+
};
|
|
212
|
+
type ParseError = {
|
|
213
|
+
error: true;
|
|
214
|
+
};
|
|
215
|
+
/** 解析三元表达式(最低优先级)- 右结合 */
|
|
216
|
+
type ParseTernary<S extends string> = ParseLogicalOr<TrimStart<S>> extends ParseResult<infer Left, infer Rest1> ? TrimStart<Rest1> extends `?${infer AfterQ}` ? ParseTernary<AfterQ> extends ParseResult<infer Then, infer Rest2> ? TrimStart<Rest2> extends `:${infer AfterColon}` ? ParseTernary<AfterColon> extends ParseResult<infer Else, infer Rest3> ? ParseResult<ASTTernary<Left, Then, Else>, Rest3> : ParseResult<Left, Rest1> : ParseResult<Left, Rest1> : ParseResult<Left, Rest1> : ParseResult<Left, Rest1> : ParseError;
|
|
217
|
+
/** 解析逻辑或 || */
|
|
218
|
+
type ParseLogicalOr<S extends string> = ParseLogicalAnd<TrimStart<S>> extends ParseResult<infer Left, infer Rest> ? ParseLogicalOrTail<Left, Rest> : ParseError;
|
|
219
|
+
type ParseLogicalOrTail<Left, S extends string> = TrimStart<S> extends `||${infer Rest}` ? ParseLogicalAnd<Rest> extends ParseResult<infer Right, infer Rest2> ? ParseLogicalOrTail<ASTBinary<"||", Left, Right>, Rest2> : ParseResult<Left, S> : ParseResult<Left, S>;
|
|
220
|
+
/** 解析逻辑与 && */
|
|
221
|
+
type ParseLogicalAnd<S extends string> = ParseEquality<TrimStart<S>> extends ParseResult<infer Left, infer Rest> ? ParseLogicalAndTail<Left, Rest> : ParseError;
|
|
222
|
+
type ParseLogicalAndTail<Left, S extends string> = TrimStart<S> extends `&&${infer Rest}` ? ParseEquality<Rest> extends ParseResult<infer Right, infer Rest2> ? ParseLogicalAndTail<ASTBinary<"&&", Left, Right>, Rest2> : ParseResult<Left, S> : ParseResult<Left, S>;
|
|
223
|
+
/** 解析相等性运算符 */
|
|
224
|
+
type ParseEquality<S extends string> = ParseComparison<TrimStart<S>> extends ParseResult<infer Left, infer Rest> ? ParseEqualityTail<Left, Rest> : ParseError;
|
|
225
|
+
type ParseEqualityTail<Left, S extends string> = TrimStart<S> extends `===${infer Rest}` ? ParseComparison<Rest> extends ParseResult<infer Right, infer Rest2> ? ParseEqualityTail<ASTBinary<"===", Left, Right>, Rest2> : ParseResult<Left, S> : TrimStart<S> extends `!==${infer Rest}` ? ParseComparison<Rest> extends ParseResult<infer Right, infer Rest2> ? ParseEqualityTail<ASTBinary<"!==", Left, Right>, Rest2> : ParseResult<Left, S> : TrimStart<S> extends `==${infer Rest}` ? Rest extends `=${string}` ? ParseResult<Left, S> : ParseComparison<Rest> extends ParseResult<infer Right, infer Rest2> ? ParseEqualityTail<ASTBinary<"==", Left, Right>, Rest2> : ParseResult<Left, S> : TrimStart<S> extends `!=${infer Rest}` ? Rest extends `=${string}` ? ParseResult<Left, S> : ParseComparison<Rest> extends ParseResult<infer Right, infer Rest2> ? ParseEqualityTail<ASTBinary<"!=", Left, Right>, Rest2> : ParseResult<Left, S> : ParseResult<Left, S>;
|
|
226
|
+
/** 解析比较运算符 */
|
|
227
|
+
type ParseComparison<S extends string> = ParseAdditive<TrimStart<S>> extends ParseResult<infer Left, infer Rest> ? ParseComparisonTail<Left, Rest> : ParseError;
|
|
228
|
+
type ParseComparisonTail<Left, S extends string> = TrimStart<S> extends `<=${infer Rest}` ? ParseAdditive<Rest> extends ParseResult<infer Right, infer Rest2> ? ParseComparisonTail<ASTBinary<"<=", Left, Right>, Rest2> : ParseResult<Left, S> : TrimStart<S> extends `>=${infer Rest}` ? ParseAdditive<Rest> extends ParseResult<infer Right, infer Rest2> ? ParseComparisonTail<ASTBinary<">=", Left, Right>, Rest2> : ParseResult<Left, S> : TrimStart<S> extends `<${infer Rest}` ? Rest extends `=${string}` ? ParseResult<Left, S> : ParseAdditive<Rest> extends ParseResult<infer Right, infer Rest2> ? ParseComparisonTail<ASTBinary<"<", Left, Right>, Rest2> : ParseResult<Left, S> : TrimStart<S> extends `>${infer Rest}` ? Rest extends `=${string}` ? ParseResult<Left, S> : ParseAdditive<Rest> extends ParseResult<infer Right, infer Rest2> ? ParseComparisonTail<ASTBinary<">", Left, Right>, Rest2> : ParseResult<Left, S> : ParseResult<Left, S>;
|
|
229
|
+
/** 解析加减运算符 */
|
|
230
|
+
type ParseAdditive<S extends string> = ParseMultiplicative<TrimStart<S>> extends ParseResult<infer Left, infer Rest> ? ParseAdditiveTail<Left, Rest> : ParseError;
|
|
231
|
+
type ParseAdditiveTail<Left, S extends string> = TrimStart<S> extends `+${infer Rest}` ? ParseMultiplicative<Rest> extends ParseResult<infer Right, infer Rest2> ? ParseAdditiveTail<ASTBinary<"+", Left, Right>, Rest2> : ParseResult<Left, S> : TrimStart<S> extends `-${infer Rest}` ? ParseMultiplicative<Rest> extends ParseResult<infer Right, infer Rest2> ? ParseAdditiveTail<ASTBinary<"-", Left, Right>, Rest2> : ParseResult<Left, S> : ParseResult<Left, S>;
|
|
232
|
+
/** 解析乘除运算符 */
|
|
233
|
+
type ParseMultiplicative<S extends string> = ParseUnary<TrimStart<S>> extends ParseResult<infer Left, infer Rest> ? ParseMultiplicativeTail<Left, Rest> : ParseError;
|
|
234
|
+
type ParseMultiplicativeTail<Left, S extends string> = TrimStart<S> extends `*${infer Rest}` ? ParseUnary<Rest> extends ParseResult<infer Right, infer Rest2> ? ParseMultiplicativeTail<ASTBinary<"*", Left, Right>, Rest2> : ParseResult<Left, S> : TrimStart<S> extends `/${infer Rest}` ? ParseUnary<Rest> extends ParseResult<infer Right, infer Rest2> ? ParseMultiplicativeTail<ASTBinary<"/", Left, Right>, Rest2> : ParseResult<Left, S> : TrimStart<S> extends `%${infer Rest}` ? ParseUnary<Rest> extends ParseResult<infer Right, infer Rest2> ? ParseMultiplicativeTail<ASTBinary<"%", Left, Right>, Rest2> : ParseResult<Left, S> : ParseResult<Left, S>;
|
|
235
|
+
/** 解析一元运算符 */
|
|
236
|
+
type ParseUnary<S extends string> = TrimStart<S> extends `!${infer Rest}` ? ParseUnary<Rest> extends ParseResult<infer Operand, infer Rest2> ? ParseResult<ASTUnary<"!", Operand>, Rest2> : ParseError : TrimStart<S> extends `-${infer Rest}` ? IsDigit<Rest extends `${infer C}${string}` ? C : ""> extends true ? ParsePostfix<S> : ParseUnary<Rest> extends ParseResult<infer Operand, infer Rest2> ? ParseResult<ASTUnary<"-", Operand>, Rest2> : ParseError : TrimStart<S> extends `+${infer Rest}` ? ParseUnary<Rest> extends ParseResult<infer Operand, infer Rest2> ? ParseResult<ASTUnary<"+", Operand>, Rest2> : ParseError : ParsePostfix<S>;
|
|
237
|
+
/** 解析后缀运算符(成员访问、函数调用) */
|
|
238
|
+
type ParsePostfix<S extends string> = ParsePrimary<TrimStart<S>> extends ParseResult<infer Base, infer Rest> ? ParsePostfixTail<Base, Rest> : ParseError;
|
|
239
|
+
type ParsePostfixTail<Base, S extends string> = TrimStart<S> extends `.${infer Rest}` ? ParseIdentifier<TrimStart<Rest>> extends [infer Prop extends string, infer Rest2 extends string] ? Prop extends "" ? ParseResult<Base, S> : ParsePostfixTail<ASTMemberAccess<Base, Prop>, Rest2> : ParseResult<Base, S> : TrimStart<S> extends `[${infer Rest}` ? ParseTernary<Rest> extends ParseResult<infer _Index, infer Rest2> ? TrimStart<Rest2> extends `]${infer Rest3}` ? ParsePostfixTail<ASTMemberAccess<Base, "[computed]">, Rest3> : ParseResult<Base, S> : ParseResult<Base, S> : TrimStart<S> extends `(${infer Rest}` ? ParseCallArgs<Rest> extends {
|
|
240
|
+
args: infer Args extends unknown[];
|
|
241
|
+
rest: infer Rest2 extends string;
|
|
242
|
+
} ? ParsePostfixTail<ASTCall<Base, Args>, Rest2> : ParseResult<Base, S> : ParseResult<Base, S>;
|
|
243
|
+
/** 解析函数调用参数 */
|
|
244
|
+
type ParseCallArgs<S extends string, Args extends unknown[] = []> = TrimStart<S> extends `)${infer Rest}` ? {
|
|
245
|
+
args: Args;
|
|
246
|
+
rest: Rest;
|
|
247
|
+
} : ParseTernary<S> extends ParseResult<infer Arg, infer Rest> ? TrimStart<Rest> extends `,${infer Rest2}` ? ParseCallArgs<Rest2, [...Args, Arg]> : TrimStart<Rest> extends `)${infer Rest2}` ? {
|
|
248
|
+
args: [...Args, Arg];
|
|
249
|
+
rest: Rest2;
|
|
250
|
+
} : {
|
|
251
|
+
args: Args;
|
|
252
|
+
rest: S;
|
|
253
|
+
} : {
|
|
254
|
+
args: Args;
|
|
255
|
+
rest: S;
|
|
256
|
+
};
|
|
257
|
+
/** 解析数字字面量,返回 [数字字符串, 剩余] */
|
|
258
|
+
type ParseNumberLiteral<S extends string, Acc extends string = ""> = S extends `${infer C}${infer Rest}` ? C extends "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "." ? ParseNumberLiteral<Rest, `${Acc}${C}`> : [Acc, S] : [Acc, S];
|
|
259
|
+
/** 解析主表达式 */
|
|
260
|
+
type ParsePrimary<S extends string> = TrimStart<S> extends `(${infer Rest}` ? ParseTernary<Rest> extends ParseResult<infer Inner, infer Rest2> ? TrimStart<Rest2> extends `)${infer Rest3}` ? ParseResult<ASTParen<Inner>, Rest3> : ParseError : ParseError : TrimStart<S> extends `true${infer Rest}` ? IsIdentifierChar<Rest extends `${infer C}${string}` ? C : ""> extends true ? ParseIdentifierPrimary<S> : ParseResult<ASTBoolean, Rest> : TrimStart<S> extends `false${infer Rest}` ? IsIdentifierChar<Rest extends `${infer C}${string}` ? C : ""> extends true ? ParseIdentifierPrimary<S> : ParseResult<ASTBoolean, Rest> : TrimStart<S> extends `${infer C}${infer __Rest}` ? IsDigit<C> extends true ? ParseNumberLiteral<TrimStart<S>> extends [infer __Num, infer Rest2 extends string] ? ParseResult<ASTNumber, Rest2> : ParseError : C extends "-" ? TrimStart<__Rest> extends `${infer C2}${string}` ? IsDigit<C2> extends true ? ParseNumberLiteral<TrimStart<__Rest>> extends [infer __Num, infer Rest2 extends string] ? ParseResult<ASTNumber, Rest2> : ParseError : ParseError : ParseError : C extends "'" | '"' | "`" ? ParseStringLiteral<TrimStart<S>> extends {
|
|
261
|
+
rest: infer Rest2 extends string;
|
|
262
|
+
} ? ParseResult<ASTString, Rest2> : ParseError : IsIdentifierStart<C> extends true ? ParseIdentifierPrimary<S> : ParseError : ParseError;
|
|
263
|
+
type ParseIdentifierPrimary<S extends string> = ParseIdentifier<TrimStart<S>> extends [infer Name extends string, infer Rest extends string] ? Name extends "" ? ParseError : ParseResult<ASTIdentifier<Name>, Rest> : ParseError;
|
|
264
|
+
type ParseStringLiteral<S extends string> = S extends `'${infer __}` ? {
|
|
265
|
+
rest: SkipSingleQuoteString<S>;
|
|
266
|
+
} : S extends `"${infer __}` ? {
|
|
267
|
+
rest: SkipDoubleQuoteString<S>;
|
|
268
|
+
} : S extends `\`${infer __}` ? {
|
|
269
|
+
rest: SkipTemplateString<S>;
|
|
270
|
+
} : never;
|
|
271
|
+
/** 解析表达式入口 */
|
|
272
|
+
type ParseExpression<S extends string> = ParseTernary<S> extends ParseResult<infer AST, infer Rest> ? TrimStart<Rest> extends "" ? AST : ASTUnknown : ASTUnknown;
|
|
273
|
+
/** 从 AST 推导类型 */
|
|
274
|
+
type InferTypeFromAST<AST, TypeMap> = AST extends ASTNumber ? number : AST extends ASTString ? string : AST extends ASTBoolean ? boolean : AST extends ASTIdentifier<infer Name> ? Name extends keyof TypeMap ? TypeMap[Name] : unknown : AST extends ASTUnary<infer Op, infer __Operand> ? InferUnaryType<Op, InferTypeFromAST<__Operand, TypeMap>> : AST extends ASTBinary<infer Op, infer Left, infer Right> ? InferBinaryType<Op, InferTypeFromAST<Left, TypeMap>, InferTypeFromAST<Right, TypeMap>> : AST extends ASTTernary<infer __Cond, infer Then, infer Else> ? InferTypeFromAST<Then, TypeMap> | InferTypeFromAST<Else, TypeMap> : AST extends ASTParen<infer Inner> ? InferTypeFromAST<Inner, TypeMap> : AST extends ASTMemberAccess<infer Obj, infer Prop> ? InferMemberType<InferTypeFromAST<Obj, TypeMap>, Prop> : AST extends ASTCall<infer Callee, infer __Args> ? InferCallType<InferTypeFromAST<Callee, TypeMap>> : unknown;
|
|
275
|
+
/** 一元运算符类型推导 */
|
|
276
|
+
type InferUnaryType<Op extends string, __Operand> = Op extends "!" ? boolean : Op extends "-" | "+" ? number : unknown;
|
|
277
|
+
/** 二元运算符类型推导 */
|
|
278
|
+
type InferBinaryType<Op extends string, Left, Right> = Op extends "+" ? Left extends string ? Right extends string ? string : string | number : Right extends string ? string | number : Left extends number ? Right extends number ? number : number | string : unknown : Op extends "-" | "*" | "/" | "%" ? number : Op extends "<" | ">" | "<=" | ">=" | "==" | "!=" | "===" | "!==" ? boolean : Op extends "&&" ? Left extends false ? Left : Right : Op extends "||" ? Left extends true ? Left : Right : unknown;
|
|
279
|
+
/** 成员访问类型推导 */
|
|
280
|
+
type InferMemberType<Obj, Prop extends string> = Obj extends Record<string, unknown> ? (Prop extends keyof Obj ? Obj[Prop] : unknown) : unknown;
|
|
281
|
+
/** 函数调用类型推导 */
|
|
282
|
+
type InferCallType<Callee> = Callee extends ((...args: unknown[]) => infer R) ? R : unknown;
|
|
283
|
+
/** 表达式验证结果 */
|
|
284
|
+
type ValidateExpression<Source extends string, TContext> = ExtractIdentifiers<Source> extends infer Ids extends string ? keyof TContext extends infer Keys extends string ? FindUndefinedIdentifiers<Ids, Keys> extends never ? true : {
|
|
285
|
+
error: "undefined_identifiers";
|
|
286
|
+
identifiers: FindUndefinedIdentifiers<Ids, Keys>;
|
|
287
|
+
} : {
|
|
288
|
+
error: "invalid_context";
|
|
289
|
+
} : {
|
|
290
|
+
error: "parse_error";
|
|
291
|
+
};
|
|
292
|
+
/** 从表达式推导返回类型 */
|
|
293
|
+
type InferExpressionResult<Source extends string, TContext> = InferTypeFromAST<ParseExpression<Source>, ContextTypeMap<TContext>>;
|
|
294
|
+
/** 验证并推导表达式类型 */
|
|
295
|
+
type ExpressionType<Source extends string, TContext> = ValidateExpression<Source, TContext> extends true ? InferExpressionResult<Source, TContext> : ValidateExpression<Source, TContext>;
|
|
296
|
+
//#endregion
|
|
297
|
+
//#region src/expr.d.ts
|
|
298
|
+
/**
|
|
299
|
+
* 表达式上下文类型约束
|
|
300
|
+
*/
|
|
301
|
+
type ExprContext = Record<string, Variable<z.ZodType> | Expression<Record<string, unknown>, unknown>>;
|
|
302
|
+
/**
|
|
303
|
+
* 表达式错误类型
|
|
304
|
+
*/
|
|
305
|
+
type ExprError<Msg extends string, Details = unknown> = {
|
|
306
|
+
readonly __error: Msg;
|
|
307
|
+
readonly __details: Details;
|
|
308
|
+
};
|
|
309
|
+
/**
|
|
310
|
+
* 验证结果处理:如果验证失败返回错误类型,否则返回推导的结果类型
|
|
311
|
+
*/
|
|
312
|
+
type ExprResult<Source extends string, TContext extends ExprContext> = ValidateExpression<Source, TContext> extends true ? InferExpressionResult<Source, TContext> : ValidateExpression<Source, TContext> extends {
|
|
313
|
+
error: "undefined_identifiers";
|
|
314
|
+
identifiers: infer Ids;
|
|
315
|
+
} ? ExprError<"Undefined identifiers in expression", Ids> : ExprError<"Expression validation failed", ValidateExpression<Source, TContext>>;
|
|
316
|
+
/**
|
|
317
|
+
* 创建一个表达式,支持编译时类型检查和返回类型自动推导
|
|
318
|
+
*
|
|
319
|
+
* @template TContext - 表达式上下文类型(Variable 或 Expression 的映射)
|
|
320
|
+
* @param context - 包含 Variable 或 Expression 的上下文对象
|
|
321
|
+
* @returns 返回一个函数,该函数接收表达式源码字符串并返回 Expression 对象
|
|
322
|
+
*
|
|
323
|
+
* 类型系统会:
|
|
324
|
+
* 1. 验证表达式中使用的所有标识符都在 context 中定义
|
|
325
|
+
* 2. 根据表达式和操作数类型自动推导返回类型
|
|
326
|
+
*
|
|
327
|
+
* @example
|
|
328
|
+
* ```ts
|
|
329
|
+
* const x = variable(z.number())
|
|
330
|
+
* const y = variable(z.number())
|
|
331
|
+
*
|
|
332
|
+
* // 自动推导返回类型为 number
|
|
333
|
+
* const sum = expr({ x, y })("x + y")
|
|
334
|
+
*
|
|
335
|
+
* // 自动推导返回类型为 boolean
|
|
336
|
+
* const isPositive = expr({ sum })("sum > 0")
|
|
337
|
+
*
|
|
338
|
+
* // 编译错误:z 未在 context 中定义
|
|
339
|
+
* // const invalid = expr({ x, y })("x + z")
|
|
340
|
+
* ```
|
|
341
|
+
*/
|
|
342
|
+
declare function expr<TContext extends ExprContext>(context: TContext): <Source extends string>(source: Source) => Expression<TContext, ExprResult<Source, TContext>>;
|
|
343
|
+
//#endregion
|
|
344
|
+
//#region src/variable.d.ts
|
|
345
|
+
/**
|
|
346
|
+
* 创建一个类型化变量
|
|
347
|
+
*
|
|
348
|
+
* @template T - Zod schema 类型
|
|
349
|
+
* @param schema - Zod schema 对象,定义变量的类型和验证规则
|
|
350
|
+
* @returns 返回 Variable 对象,包含 _tag 标记和 schema
|
|
351
|
+
*
|
|
352
|
+
* @example
|
|
353
|
+
* ```ts
|
|
354
|
+
* const x = variable(z.number())
|
|
355
|
+
* const name = variable(z.string())
|
|
356
|
+
* const config = variable(z.object({
|
|
357
|
+
* count: z.number(),
|
|
358
|
+
* enabled: z.boolean()
|
|
359
|
+
* }))
|
|
360
|
+
* ```
|
|
361
|
+
*/
|
|
362
|
+
declare function variable<T extends z.ZodType>(schema: T): Variable<T>;
|
|
363
|
+
//#endregion
|
|
364
|
+
export { type CompileContext, type CompileOptions, type CompiledData, type ContextTypeMap, type ExprNode, type Expression, type ExpressionType, type ExtractType, type InferContextType, type InferExpressionResult, type InferExpressionType, type InferVariableType, type ParseExpression, type ValidateExpression, type Variable, compile, evaluate, expr, variable };
|
|
365
|
+
//# sourceMappingURL=index.d.mts.map
|