Skip to content

Commit 5747a87

Browse files
committed
docs: update README.md with comprehensive project documentation
1 parent 0f30cdb commit 5747a87

1 file changed

Lines changed: 314 additions & 4 deletions

File tree

README.md

Lines changed: 314 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,325 @@
11
# @codehz/json-expr
22

3-
To install dependencies:
3+
一个可序列化为 JSON 的表达式 DSL 库,提供类型安全的表达式构建、编译和求值。
4+
5+
[![npm version](https://img.shields.io/npm/v/@codehz/json-expr.svg)](https://www.npmjs.com/package/@codehz/json-expr)
6+
7+
## 特性
8+
9+
- 🎯 **类型安全** - 使用 TypeScript 和 Zod 进行完整的类型推导和验证
10+
- 📦 **可序列化** - 编译后的表达式为纯 JSON 格式,易于传输和存储
11+
- 🔧 **灵活的表达式** - 支持任意 JavaScript 表达式,包括函数调用和对象属性访问
12+
-**高性能** - 使用 `new Function()` 进行优化执行
13+
- 🧩 **可组合** - 表达式可以相互组合,形成复杂的计算树
14+
- 🔐 **类型验证** - 运行时通过 Zod schema 进行数据验证
15+
16+
## 快速开始
17+
18+
### 安装
19+
20+
```bash
21+
bun install @codehz/json-expr
22+
```
23+
24+
### 基本用法
25+
26+
```typescript
27+
import { z } from "zod";
28+
import { variable, expr, compile, evaluate } from "@codehz/json-expr";
29+
30+
// 定义类型化变量
31+
const x = variable(z.number());
32+
const y = variable(z.number());
33+
34+
// 构建表达式
35+
const sum = expr({ x, y })("x + y");
36+
const product = expr({ x, y })("x * y");
37+
const result = expr({ sum, product })("sum + product");
38+
39+
// 编译表达式(可序列化为 JSON)
40+
const compiled = compile(result, { x, y });
41+
// => [["x", "y"], "$0+$1", "$0*$1", "$2+$3"]
42+
43+
// 执行编译后的表达式
44+
const value = evaluate(compiled, { x: 2, y: 3 });
45+
// => 11 (2+3 + 2*3 = 5 + 6 = 11)
46+
```
47+
48+
## 核心概念
49+
50+
### Variable(变量)
51+
52+
变量是表达式中的占位符,通过 Zod schema 定义其类型和验证规则。
53+
54+
```typescript
55+
const age = variable(z.number().int().min(0).max(150));
56+
const name = variable(z.string().min(1));
57+
const config = variable(
58+
z.object({
59+
debug: z.boolean(),
60+
timeout: z.number(),
61+
})
62+
);
63+
```
64+
65+
### Expression(表达式)
66+
67+
表达式对变量或其他表达式进行运算,使用字符串形式描述。
68+
69+
```typescript
70+
const x = variable(z.number());
71+
const y = variable(z.number());
72+
73+
// 简单表达式
74+
const sum = expr({ x, y })("x + y");
75+
76+
// 复杂表达式(可以使用 JS 语言特性)
77+
const abs = expr({ x })("Math.abs(x)");
78+
const conditional = expr({ x, y })("x > y ? x : y");
79+
const array = expr({ x, y })("[x, y].filter(v => v > 0)");
80+
```
81+
82+
### CompiledData(编译数据)
83+
84+
编译后的表达式为 JSON 数组格式:
85+
86+
```typescript
87+
// 格式: [variableNames, expression1, expression2, ...]
88+
// 其中 $N 用于引用之前的变量或表达式
89+
90+
const compiled = compile(result, { x, y });
91+
// [["x", "y"], "$0+$1", "$0*$1", "$2+$3"]
92+
```
93+
94+
## API 参考
95+
96+
### `variable<T>(schema: T): Variable<T>`
97+
98+
创建一个类型化变量。
99+
100+
**参数:**
101+
102+
- `schema` - Zod schema,定义变量的类型和验证规则
103+
104+
**返回值:** Variable 对象
105+
106+
**示例:**
107+
108+
```typescript
109+
const num = variable(z.number());
110+
const str = variable(z.string());
111+
const date = variable(z.date());
112+
```
113+
114+
### `expr<TContext>(context: TContext): (source: string) => Expression<TContext, TResult>`
115+
116+
创建表达式,采用柯里化设计以支持完整的类型推导。
117+
118+
**参数:**
119+
120+
- `context` - 上下文对象,包含变量和/或其他表达式的映射
121+
122+
**返回值:** 函数,接收表达式源码字符串并返回 Expression 对象
123+
124+
**示例:**
125+
126+
```typescript
127+
const x = variable(z.number());
128+
const y = variable(z.number());
129+
130+
const sum = expr({ x, y })("x + y");
131+
const result = expr({ sum, x })("sum * x");
132+
```
133+
134+
### `compile<TResult>(expression: Expression<any, TResult>, variables: Record<string, Variable<any>>, options?: CompileOptions): CompiledData`
135+
136+
将表达式树编译为可序列化的 JSON 结构。
137+
138+
**参数:**
139+
140+
- `expression` - 要编译的表达式
141+
- `variables` - 表达式中使用的所有变量映射
142+
- `options` - 编译选项(可选)
143+
- `optimize?: boolean` - 是否进行优化(默认:false)
144+
145+
**返回值:** CompiledData 数组
146+
147+
**示例:**
148+
149+
```typescript
150+
const x = variable(z.number());
151+
const y = variable(z.number());
152+
const sum = expr({ x, y })("x + y");
153+
const product = expr({ x, y })("x * y");
154+
const result = expr({ sum, product })("sum + product");
155+
156+
const compiled = compile(result, { x, y });
157+
// [["x", "y"], "$0+$1", "$0*$1", "$2+$3"]
158+
159+
// 使用优化选项
160+
const optimized = compile(result, { x, y }, { optimize: true });
161+
// [["x", "y"], "($0+$1)+($0*$1)"]
162+
```
163+
164+
### `evaluate<TResult>(data: CompiledData, values: Record<string, unknown>): TResult`
165+
166+
执行编译后的表达式。
167+
168+
**参数:**
169+
170+
- `data` - 编译后的表达式数据
171+
- `values` - 变量值映射,对应编译数据中的变量名顺序
172+
173+
**返回值:** 表达式计算结果
174+
175+
**示例:**
176+
177+
```typescript
178+
const compiled = compile(result, { x, y });
179+
const value = evaluate(compiled, { x: 5, y: 3 });
180+
// => 23 ((5+3) + (5*3) = 8 + 15 = 23)
181+
```
182+
183+
## 高级用法
184+
185+
### 传入对象和内置对象
186+
187+
支持在上下文中传入对象(如 Math)以在表达式中访问其属性和方法:
188+
189+
```typescript
190+
const x = variable(z.number());
191+
192+
const sqrtExpr = expr({ x, Math: variable(z.any()) })("Math.sqrt(x)");
193+
const compiled = compile(sqrtExpr, { x, Math: variable(z.any()) });
194+
const result = evaluate(compiled, { x: 16, Math });
195+
// => 4
196+
```
197+
198+
### 条件表达式
199+
200+
```typescript
201+
const score = variable(z.number());
202+
const gradeExpr = expr({ score })("score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 70 ? 'C' : 'F'");
203+
204+
const compiled = compile(gradeExpr, { score });
205+
const grade = evaluate(compiled, { score: 85 });
206+
// => "B"
207+
```
208+
209+
### 数组和对象操作
210+
211+
```typescript
212+
const numbers = variable(z.array(z.number()));
213+
214+
const sumExpr = expr({ numbers })("numbers.reduce((a, b) => a + b, 0)");
215+
216+
const compiled = compile(sumExpr, { numbers });
217+
const sum = evaluate(compiled, { numbers: [1, 2, 3, 4, 5] });
218+
// => 15
219+
```
220+
221+
### 链式表达式组合
222+
223+
```typescript
224+
const a = variable(z.number());
225+
const b = variable(z.number());
226+
227+
const sum = expr({ a, b })("a + b");
228+
const product = expr({ a, b })("a * b");
229+
const difference = expr({ a, b })("a - b");
230+
231+
const complex = expr({ sum, product, difference })("sum * product - difference");
232+
233+
const compiled = compile(complex, { a, b });
234+
const result = evaluate(compiled, { a: 2, b: 3 });
235+
// => (2+3) * (2*3) - (2-3) = 5 * 6 - (-1) = 30 + 1 = 31
236+
```
237+
238+
## 序列化和传输
239+
240+
编译后的数据可以轻松进行 JSON 序列化,适合网络传输或持久化存储:
241+
242+
```typescript
243+
// 编译表达式
244+
const compiled = compile(result, { x, y });
245+
246+
// 序列化
247+
const json = JSON.stringify(compiled);
248+
// "[["x","y"],"$0+$1","$0*$1","$2+$3"]"
249+
250+
// 存储或传输...
251+
252+
// 反序列化
253+
const deserialized = JSON.parse(json);
254+
255+
// 执行
256+
const value = evaluate(deserialized, { x: 5, y: 3 });
257+
```
258+
259+
## 类型安全
260+
261+
项目充分利用 TypeScript 的类型系统进行编译时检查和类型推导:
262+
263+
```typescript
264+
const x = variable(z.number());
265+
const y = variable(z.string());
266+
267+
// 提供完整的类型推导和自动补全
268+
const sum = expr({ x, y })("x + y");
269+
```
270+
271+
## 性能考虑
272+
273+
- **编译时间**:编译过程涉及依赖分析和拓扑排序,通常快速完成
274+
- **执行时间**:表达式通过 `new Function()` 编译为原生 JavaScript,执行性能接近原生代码
275+
- **内存占用**:编译数据为纯 JSON,占用空间小,适合在网络上传输
276+
277+
## 项目结构
278+
279+
```
280+
src/
281+
├── index.ts # 导出入口
282+
├── variable.ts # variable 函数实现
283+
├── expr.ts # expr 函数实现
284+
├── compile.ts # compile 函数实现
285+
├── evaluate.ts # evaluate 函数实现
286+
├── parser.ts # 表达式解析器
287+
├── type-parser.ts # 类型解析器
288+
├── types.ts # 类型定义
289+
└── *.test.ts # 测试文件
290+
```
291+
292+
## 开发
293+
294+
### 安装依赖
4295

5296
```bash
6297
bun install
7298
```
8299

9-
To run:
300+
### 运行测试
301+
302+
```bash
303+
bun test
304+
```
305+
306+
### 代码检查
10307

11308
```bash
12-
bun run src/index.ts
309+
bun run lint
310+
bun run type-check
13311
```
14312

15-
This project was created using `bun init` in bun v1.3.6. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
313+
### 代码格式化
314+
315+
```bash
316+
bun run format
317+
```
318+
319+
## 许可证
320+
321+
MIT
322+
323+
## 贡献
324+
325+
欢迎提交 Issue 和 Pull Request!

0 commit comments

Comments
 (0)