@variojs/core 0.0.1
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/README.md +270 -0
- package/dist/errors.d.ts +100 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +132 -0
- package/dist/errors.js.map +1 -0
- package/dist/expression/cache.d.ts +53 -0
- package/dist/expression/cache.d.ts.map +1 -0
- package/dist/expression/cache.js +158 -0
- package/dist/expression/cache.js.map +1 -0
- package/dist/expression/compiler.d.ts +34 -0
- package/dist/expression/compiler.d.ts.map +1 -0
- package/dist/expression/compiler.js +141 -0
- package/dist/expression/compiler.js.map +1 -0
- package/dist/expression/dependencies.d.ts +17 -0
- package/dist/expression/dependencies.d.ts.map +1 -0
- package/dist/expression/dependencies.js +106 -0
- package/dist/expression/dependencies.js.map +1 -0
- package/dist/expression/evaluate.d.ts +22 -0
- package/dist/expression/evaluate.d.ts.map +1 -0
- package/dist/expression/evaluate.js +75 -0
- package/dist/expression/evaluate.js.map +1 -0
- package/dist/expression/evaluator.d.ts +22 -0
- package/dist/expression/evaluator.d.ts.map +1 -0
- package/dist/expression/evaluator.js +533 -0
- package/dist/expression/evaluator.js.map +1 -0
- package/dist/expression/index.d.ts +12 -0
- package/dist/expression/index.d.ts.map +1 -0
- package/dist/expression/index.js +12 -0
- package/dist/expression/index.js.map +1 -0
- package/dist/expression/parser.d.ts +15 -0
- package/dist/expression/parser.d.ts.map +1 -0
- package/dist/expression/parser.js +42 -0
- package/dist/expression/parser.js.map +1 -0
- package/dist/expression/utils.d.ts +46 -0
- package/dist/expression/utils.d.ts.map +1 -0
- package/dist/expression/utils.js +78 -0
- package/dist/expression/utils.js.map +1 -0
- package/dist/expression/whitelist.d.ts +24 -0
- package/dist/expression/whitelist.d.ts.map +1 -0
- package/dist/expression/whitelist.js +198 -0
- package/dist/expression/whitelist.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime/context.d.ts +8 -0
- package/dist/runtime/context.d.ts.map +1 -0
- package/dist/runtime/context.js +7 -0
- package/dist/runtime/context.js.map +1 -0
- package/dist/runtime/create-context.d.ts +20 -0
- package/dist/runtime/create-context.d.ts.map +1 -0
- package/dist/runtime/create-context.js +62 -0
- package/dist/runtime/create-context.js.map +1 -0
- package/dist/runtime/index.d.ts +10 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +10 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/loop-context-pool.d.ts +58 -0
- package/dist/runtime/loop-context-pool.d.ts.map +1 -0
- package/dist/runtime/loop-context-pool.js +114 -0
- package/dist/runtime/loop-context-pool.js.map +1 -0
- package/dist/runtime/path.d.ts +114 -0
- package/dist/runtime/path.d.ts.map +1 -0
- package/dist/runtime/path.js +302 -0
- package/dist/runtime/path.js.map +1 -0
- package/dist/runtime/proxy.d.ts +18 -0
- package/dist/runtime/proxy.d.ts.map +1 -0
- package/dist/runtime/proxy.js +54 -0
- package/dist/runtime/proxy.js.map +1 -0
- package/dist/runtime/sandbox.d.ts +20 -0
- package/dist/runtime/sandbox.d.ts.map +1 -0
- package/dist/runtime/sandbox.js +32 -0
- package/dist/runtime/sandbox.js.map +1 -0
- package/dist/types.d.ts +191 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +20 -0
- package/dist/types.js.map +1 -0
- package/dist/vm/errors.d.ts +5 -0
- package/dist/vm/errors.d.ts.map +1 -0
- package/dist/vm/errors.js +5 -0
- package/dist/vm/errors.js.map +1 -0
- package/dist/vm/executor.d.ts +35 -0
- package/dist/vm/executor.d.ts.map +1 -0
- package/dist/vm/executor.js +137 -0
- package/dist/vm/executor.js.map +1 -0
- package/dist/vm/handlers/array/pop.d.ts +12 -0
- package/dist/vm/handlers/array/pop.d.ts.map +1 -0
- package/dist/vm/handlers/array/pop.js +28 -0
- package/dist/vm/handlers/array/pop.js.map +1 -0
- package/dist/vm/handlers/array/push.d.ts +13 -0
- package/dist/vm/handlers/array/push.d.ts.map +1 -0
- package/dist/vm/handlers/array/push.js +42 -0
- package/dist/vm/handlers/array/push.js.map +1 -0
- package/dist/vm/handlers/array/shift.d.ts +12 -0
- package/dist/vm/handlers/array/shift.d.ts.map +1 -0
- package/dist/vm/handlers/array/shift.js +28 -0
- package/dist/vm/handlers/array/shift.js.map +1 -0
- package/dist/vm/handlers/array/splice.d.ts +12 -0
- package/dist/vm/handlers/array/splice.d.ts.map +1 -0
- package/dist/vm/handlers/array/splice.js +59 -0
- package/dist/vm/handlers/array/splice.js.map +1 -0
- package/dist/vm/handlers/array/unshift.d.ts +13 -0
- package/dist/vm/handlers/array/unshift.d.ts.map +1 -0
- package/dist/vm/handlers/array/unshift.js +42 -0
- package/dist/vm/handlers/array/unshift.js.map +1 -0
- package/dist/vm/handlers/array/utils.d.ts +10 -0
- package/dist/vm/handlers/array/utils.d.ts.map +1 -0
- package/dist/vm/handlers/array/utils.js +33 -0
- package/dist/vm/handlers/array/utils.js.map +1 -0
- package/dist/vm/handlers/batch.d.ts +12 -0
- package/dist/vm/handlers/batch.d.ts.map +1 -0
- package/dist/vm/handlers/batch.js +40 -0
- package/dist/vm/handlers/batch.js.map +1 -0
- package/dist/vm/handlers/call.d.ts +14 -0
- package/dist/vm/handlers/call.d.ts.map +1 -0
- package/dist/vm/handlers/call.js +65 -0
- package/dist/vm/handlers/call.js.map +1 -0
- package/dist/vm/handlers/emit.d.ts +12 -0
- package/dist/vm/handlers/emit.d.ts.map +1 -0
- package/dist/vm/handlers/emit.js +26 -0
- package/dist/vm/handlers/emit.js.map +1 -0
- package/dist/vm/handlers/if.d.ts +13 -0
- package/dist/vm/handlers/if.d.ts.map +1 -0
- package/dist/vm/handlers/if.js +35 -0
- package/dist/vm/handlers/if.js.map +1 -0
- package/dist/vm/handlers/index.d.ts +14 -0
- package/dist/vm/handlers/index.d.ts.map +1 -0
- package/dist/vm/handlers/index.js +55 -0
- package/dist/vm/handlers/index.js.map +1 -0
- package/dist/vm/handlers/log.d.ts +12 -0
- package/dist/vm/handlers/log.d.ts.map +1 -0
- package/dist/vm/handlers/log.js +41 -0
- package/dist/vm/handlers/log.js.map +1 -0
- package/dist/vm/handlers/loop.d.ts +12 -0
- package/dist/vm/handlers/loop.d.ts.map +1 -0
- package/dist/vm/handlers/loop.js +71 -0
- package/dist/vm/handlers/loop.js.map +1 -0
- package/dist/vm/handlers/navigate.d.ts +12 -0
- package/dist/vm/handlers/navigate.d.ts.map +1 -0
- package/dist/vm/handlers/navigate.js +43 -0
- package/dist/vm/handlers/navigate.js.map +1 -0
- package/dist/vm/handlers/set.d.ts +15 -0
- package/dist/vm/handlers/set.d.ts.map +1 -0
- package/dist/vm/handlers/set.js +30 -0
- package/dist/vm/handlers/set.js.map +1 -0
- package/dist/vm/index.d.ts +8 -0
- package/dist/vm/index.d.ts.map +1 -0
- package/dist/vm/index.js +7 -0
- package/dist/vm/index.js.map +1 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# @variojs/core
|
|
2
|
+
|
|
3
|
+
Vario Core Runtime - 指令虚拟机、表达式系统、运行时上下文
|
|
4
|
+
|
|
5
|
+
## 简介
|
|
6
|
+
|
|
7
|
+
`@variojs/core` 是 Vario 的核心运行时模块,提供了框架无关的基础能力:
|
|
8
|
+
|
|
9
|
+
- **RuntimeContext**: 扁平化状态管理 + `$` 前缀系统 API
|
|
10
|
+
- **Expression System**: 安全表达式解析、编译和求值
|
|
11
|
+
- **Action VM**: 指令虚拟机,执行各种操作指令
|
|
12
|
+
- **安全沙箱**: 多层防护机制,防止恶意代码执行
|
|
13
|
+
- **性能优化**: 表达式缓存、对象池、路径记忆化
|
|
14
|
+
|
|
15
|
+
## 安装
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @variojs/core
|
|
19
|
+
# 或
|
|
20
|
+
pnpm add @variojs/core
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 核心概念
|
|
24
|
+
|
|
25
|
+
### RuntimeContext 运行时上下文
|
|
26
|
+
|
|
27
|
+
运行时上下文是 Vario 的核心,提供了扁平化的状态管理和系统 API:
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { createRuntimeContext } from '@variojs/core'
|
|
31
|
+
|
|
32
|
+
const ctx = createRuntimeContext({
|
|
33
|
+
state: {
|
|
34
|
+
count: 0,
|
|
35
|
+
user: { name: 'John', age: 30 }
|
|
36
|
+
},
|
|
37
|
+
methods: {
|
|
38
|
+
increment: (ctx) => {
|
|
39
|
+
ctx._set('count', ctx._get('count') + 1)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
// 访问状态(扁平化,无 models. 前缀)
|
|
45
|
+
ctx.count // 0
|
|
46
|
+
ctx.user.name // 'John'
|
|
47
|
+
|
|
48
|
+
// 使用系统 API
|
|
49
|
+
ctx._get('count') // 0
|
|
50
|
+
ctx._set('count', 10) // 设置值
|
|
51
|
+
ctx.$emit('countChanged', 10) // 发射事件
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Expression System 表达式系统
|
|
55
|
+
|
|
56
|
+
安全、强大的表达式求值引擎,支持复杂的条件判断、数据访问和计算:
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import { createExpressionSandbox, compileExpression } from '@variojs/core'
|
|
60
|
+
|
|
61
|
+
const sandbox = createExpressionSandbox(ctx)
|
|
62
|
+
|
|
63
|
+
// 编译表达式
|
|
64
|
+
const expr = compileExpression('count > 10 && user.age >= 18')
|
|
65
|
+
|
|
66
|
+
// 求值
|
|
67
|
+
const result = expr.evaluate(sandbox) // true/false
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**支持的语法**:
|
|
71
|
+
- 变量访问:`count`, `user.name`
|
|
72
|
+
- 数组访问:`items[0]`, `todos[index]`
|
|
73
|
+
- 可选链:`user?.profile?.email`
|
|
74
|
+
- 二元运算:`count + 1`, `price * quantity`
|
|
75
|
+
- 比较运算:`count > 10`, `role === "admin"`
|
|
76
|
+
- 逻辑运算:`showContent && isActive`
|
|
77
|
+
- 三元表达式:`count > 10 ? "high" : "low"`
|
|
78
|
+
- 函数调用(白名单):`Array.isArray(items)`, `Math.max(a, b)`
|
|
79
|
+
|
|
80
|
+
### Action VM 指令虚拟机
|
|
81
|
+
|
|
82
|
+
执行各种操作指令,如 `set`、`call`、`if`、`loop` 等:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { createVMExecutor } from '@variojs/core'
|
|
86
|
+
|
|
87
|
+
const executor = createVMExecutor(ctx)
|
|
88
|
+
|
|
89
|
+
// 执行 set 指令
|
|
90
|
+
await executor.execute({
|
|
91
|
+
type: 'set',
|
|
92
|
+
path: 'count',
|
|
93
|
+
value: 10
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
// 执行 call 指令
|
|
97
|
+
await executor.execute({
|
|
98
|
+
type: 'call',
|
|
99
|
+
method: 'increment'
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
// 执行 if 指令
|
|
103
|
+
await executor.execute({
|
|
104
|
+
type: 'if',
|
|
105
|
+
cond: 'count > 10',
|
|
106
|
+
then: {
|
|
107
|
+
type: 'set',
|
|
108
|
+
path: 'status',
|
|
109
|
+
value: 'high'
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## API 参考
|
|
115
|
+
|
|
116
|
+
### createRuntimeContext
|
|
117
|
+
|
|
118
|
+
创建运行时上下文。
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
function createRuntimeContext<TState extends Record<string, unknown>>(
|
|
122
|
+
options: CreateContextOptions<TState>
|
|
123
|
+
): RuntimeContext<TState>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**选项**:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
interface CreateContextOptions<TState> {
|
|
130
|
+
/** 初始状态 */
|
|
131
|
+
state?: TState
|
|
132
|
+
/** 方法注册表 */
|
|
133
|
+
methods?: Record<string, MethodHandler>
|
|
134
|
+
/** 表达式选项 */
|
|
135
|
+
exprOptions?: ExpressionOptions
|
|
136
|
+
/** 事件发射器 */
|
|
137
|
+
onEmit?: (event: string, data?: unknown) => void
|
|
138
|
+
/** 状态变化回调 */
|
|
139
|
+
onStateChange?: (path: string, value: unknown) => void
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Expression System
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
// 创建表达式沙箱
|
|
147
|
+
function createExpressionSandbox(ctx: RuntimeContext): ExpressionSandbox
|
|
148
|
+
|
|
149
|
+
// 编译表达式
|
|
150
|
+
function compileExpression(expr: string): CompiledExpression
|
|
151
|
+
|
|
152
|
+
// 解析表达式
|
|
153
|
+
function parseExpression(expr: string): ExpressionAST
|
|
154
|
+
|
|
155
|
+
// 求值表达式
|
|
156
|
+
function evaluateExpression(expr: string, ctx: RuntimeContext): unknown
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Action VM
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
// 创建 VM 执行器
|
|
163
|
+
function createVMExecutor(ctx: RuntimeContext): VMExecutor
|
|
164
|
+
|
|
165
|
+
// 执行动作
|
|
166
|
+
function executeAction(action: Action, ctx: RuntimeContext): Promise<void>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Path Utilities
|
|
170
|
+
|
|
171
|
+
路径解析和操作工具:
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
// 解析路径
|
|
175
|
+
function parsePath(path: string): PathSegment[]
|
|
176
|
+
|
|
177
|
+
// 获取路径值
|
|
178
|
+
function getPathValue(obj: Record<string, unknown>, path: string): unknown
|
|
179
|
+
|
|
180
|
+
// 设置路径值
|
|
181
|
+
function setPathValue(
|
|
182
|
+
obj: Record<string, unknown>,
|
|
183
|
+
path: string,
|
|
184
|
+
value: unknown,
|
|
185
|
+
options?: { createObject?: () => object, createArray?: () => unknown[] }
|
|
186
|
+
): void
|
|
187
|
+
|
|
188
|
+
// 路径匹配
|
|
189
|
+
function matchPath(pattern: string, path: string): boolean
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## 安全特性
|
|
193
|
+
|
|
194
|
+
### 表达式白名单
|
|
195
|
+
|
|
196
|
+
表达式系统使用白名单机制,只允许安全的操作:
|
|
197
|
+
|
|
198
|
+
- ✅ 允许:属性访问、数组访问、数学运算、比较运算
|
|
199
|
+
- ✅ 允许:白名单函数(`Array.isArray`, `Math.max` 等)
|
|
200
|
+
- ❌ 禁止:`eval`, `Function`, `global`, `window` 等危险操作
|
|
201
|
+
- ❌ 禁止:直接访问 Node.js API(`require`, `process` 等)
|
|
202
|
+
|
|
203
|
+
### 沙箱机制
|
|
204
|
+
|
|
205
|
+
表达式在隔离的沙箱中执行,无法访问外部作用域:
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
const sandbox = createExpressionSandbox(ctx)
|
|
209
|
+
|
|
210
|
+
// 只能访问 ctx 中定义的状态和方法
|
|
211
|
+
// 无法访问全局变量、Node.js API 等
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## 性能优化
|
|
215
|
+
|
|
216
|
+
### 表达式缓存
|
|
217
|
+
|
|
218
|
+
编译后的表达式会被缓存,避免重复编译:
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
// 第一次编译
|
|
222
|
+
const expr1 = compileExpression('count > 10') // 编译
|
|
223
|
+
|
|
224
|
+
// 第二次使用相同表达式
|
|
225
|
+
const expr2 = compileExpression('count > 10') // 从缓存获取
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### 路径缓存
|
|
229
|
+
|
|
230
|
+
路径解析结果会被缓存:
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
parsePathCached('user.profile.name') // 第一次解析
|
|
234
|
+
parsePathCached('user.profile.name') // 从缓存获取
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### 对象池
|
|
238
|
+
|
|
239
|
+
循环上下文使用对象池复用,减少内存分配:
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
import { createLoopContext, releaseLoopContext } from '@variojs/core'
|
|
243
|
+
|
|
244
|
+
// 创建循环上下文(从池中获取)
|
|
245
|
+
const loopCtx = createLoopContext(ctx, { item, index })
|
|
246
|
+
|
|
247
|
+
// 使用后释放(归还到池中)
|
|
248
|
+
releaseLoopContext(loopCtx)
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## 类型支持
|
|
252
|
+
|
|
253
|
+
完整的 TypeScript 类型定义:
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
import type {
|
|
257
|
+
RuntimeContext,
|
|
258
|
+
Action,
|
|
259
|
+
ExpressionOptions,
|
|
260
|
+
MethodHandler
|
|
261
|
+
} from '@variojs/core'
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## 示例
|
|
265
|
+
|
|
266
|
+
查看主项目的 `play/src/examples/` 目录下的完整示例。
|
|
267
|
+
|
|
268
|
+
## 许可证
|
|
269
|
+
|
|
270
|
+
MIT
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vario 错误处理体系
|
|
3
|
+
*
|
|
4
|
+
* 统一的错误基类和错误码系统
|
|
5
|
+
*/
|
|
6
|
+
import type { Action } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* 错误上下文信息
|
|
9
|
+
*/
|
|
10
|
+
export interface ErrorContext {
|
|
11
|
+
/** Schema 路径(如 "events.click[0]") */
|
|
12
|
+
schemaPath?: string;
|
|
13
|
+
/** 表达式字符串 */
|
|
14
|
+
expression?: string;
|
|
15
|
+
/** 动作对象 */
|
|
16
|
+
action?: Action;
|
|
17
|
+
/** 调用栈(简化版) */
|
|
18
|
+
stack?: string[];
|
|
19
|
+
/** 额外上下文信息 */
|
|
20
|
+
metadata?: Record<string, unknown>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Vario 错误基类
|
|
24
|
+
*
|
|
25
|
+
* 所有 Vario 相关错误都应继承此类
|
|
26
|
+
*/
|
|
27
|
+
export declare class VarioError extends Error {
|
|
28
|
+
/** 错误码 */
|
|
29
|
+
readonly code: string;
|
|
30
|
+
/** 错误上下文 */
|
|
31
|
+
readonly context: ErrorContext;
|
|
32
|
+
constructor(message: string, code: string, context?: ErrorContext);
|
|
33
|
+
/**
|
|
34
|
+
* 获取友好的错误消息
|
|
35
|
+
*/
|
|
36
|
+
getFriendlyMessage(): string;
|
|
37
|
+
/**
|
|
38
|
+
* 转换为 JSON(用于序列化)
|
|
39
|
+
*/
|
|
40
|
+
toJSON(): Record<string, unknown>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 动作执行错误
|
|
44
|
+
*/
|
|
45
|
+
export declare class ActionError extends VarioError {
|
|
46
|
+
constructor(action: Action, message: string, code?: string, context?: Omit<ErrorContext, 'action'>);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 表达式求值错误
|
|
50
|
+
*/
|
|
51
|
+
export declare class ExpressionError extends VarioError {
|
|
52
|
+
constructor(expression: string, message: string, code?: string, context?: Omit<ErrorContext, 'expression'>);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 服务调用错误
|
|
56
|
+
*/
|
|
57
|
+
export declare class ServiceError extends VarioError {
|
|
58
|
+
readonly service: string;
|
|
59
|
+
readonly originalError?: Error;
|
|
60
|
+
constructor(service: string, message: string, originalError?: Error, context?: ErrorContext);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* 批量执行错误
|
|
64
|
+
*/
|
|
65
|
+
export declare class BatchError extends VarioError {
|
|
66
|
+
readonly failedActions: Array<{
|
|
67
|
+
action: Action;
|
|
68
|
+
error: Error;
|
|
69
|
+
}>;
|
|
70
|
+
constructor(failedActions: Array<{
|
|
71
|
+
action: Action;
|
|
72
|
+
error: Error;
|
|
73
|
+
}>, message: string, context?: ErrorContext);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 错误码定义
|
|
77
|
+
*/
|
|
78
|
+
export declare const ErrorCodes: {
|
|
79
|
+
readonly ACTION_UNKNOWN_TYPE: "ACTION_UNKNOWN_TYPE";
|
|
80
|
+
readonly ACTION_EXECUTION_ERROR: "ACTION_EXECUTION_ERROR";
|
|
81
|
+
readonly ACTION_ABORTED: "ACTION_ABORTED";
|
|
82
|
+
readonly ACTION_TIMEOUT: "ACTION_TIMEOUT";
|
|
83
|
+
readonly ACTION_MAX_STEPS_EXCEEDED: "ACTION_MAX_STEPS_EXCEEDED";
|
|
84
|
+
readonly ACTION_MISSING_PARAM: "ACTION_MISSING_PARAM";
|
|
85
|
+
readonly ACTION_INVALID_PARAM: "ACTION_INVALID_PARAM";
|
|
86
|
+
readonly EXPRESSION_PARSE_ERROR: "EXPRESSION_PARSE_ERROR";
|
|
87
|
+
readonly EXPRESSION_VALIDATION_ERROR: "EXPRESSION_VALIDATION_ERROR";
|
|
88
|
+
readonly EXPRESSION_EVALUATION_ERROR: "EXPRESSION_EVALUATION_ERROR";
|
|
89
|
+
readonly EXPRESSION_TIMEOUT: "EXPRESSION_TIMEOUT";
|
|
90
|
+
readonly EXPRESSION_MAX_STEPS_EXCEEDED: "EXPRESSION_MAX_STEPS_EXCEEDED";
|
|
91
|
+
readonly EXPRESSION_UNSAFE_ACCESS: "EXPRESSION_UNSAFE_ACCESS";
|
|
92
|
+
readonly EXPRESSION_FUNCTION_NOT_WHITELISTED: "EXPRESSION_FUNCTION_NOT_WHITELISTED";
|
|
93
|
+
readonly SERVICE_NOT_FOUND: "SERVICE_NOT_FOUND";
|
|
94
|
+
readonly SERVICE_CALL_ERROR: "SERVICE_CALL_ERROR";
|
|
95
|
+
readonly BATCH_ERROR: "BATCH_ERROR";
|
|
96
|
+
readonly SCHEMA_VALIDATION_ERROR: "SCHEMA_VALIDATION_ERROR";
|
|
97
|
+
readonly SCHEMA_INVALID_ACTION: "SCHEMA_INVALID_ACTION";
|
|
98
|
+
};
|
|
99
|
+
export type ErrorCode = typeof ErrorCodes[keyof typeof ErrorCodes];
|
|
100
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAExC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW;IACX,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,eAAe;IACf,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,cAAc;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAED;;;;GAIG;AACH,qBAAa,UAAW,SAAQ,KAAK;IACnC,UAAU;IACV,SAAgB,IAAI,EAAE,MAAM,CAAA;IAC5B,YAAY;IACZ,SAAgB,OAAO,EAAE,YAAY,CAAA;gBAGnC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,YAAiB;IAa5B;;OAEG;IACH,kBAAkB,IAAI,MAAM;IAkB5B;;OAEG;IACH,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CASlC;AAED;;GAEG;AACH,qBAAa,WAAY,SAAQ,UAAU;gBAEvC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,MAAuB,EAC7B,OAAO,GAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAM;CAQ7C;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,UAAU;gBAE3C,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,MAA2B,EACjC,OAAO,GAAE,IAAI,CAAC,YAAY,EAAE,YAAY,CAAM;CAQjD;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,UAAU;IAC1C,SAAgB,OAAO,EAAE,MAAM,CAAA;IAC/B,SAAgB,aAAa,CAAC,EAAE,KAAK,CAAA;gBAGnC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE,KAAK,EACrB,OAAO,GAAE,YAAiB;CAO7B;AAED;;GAEG;AACH,qBAAa,UAAW,SAAQ,UAAU;IACxC,SAAgB,aAAa,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC,CAAA;gBAGpE,aAAa,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC,EACtD,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,YAAiB;CAM7B;AAED;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;CA6Bb,CAAA;AAEV,MAAM,MAAM,SAAS,GAAG,OAAO,UAAU,CAAC,MAAM,OAAO,UAAU,CAAC,CAAA"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vario 错误处理体系
|
|
3
|
+
*
|
|
4
|
+
* 统一的错误基类和错误码系统
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Vario 错误基类
|
|
8
|
+
*
|
|
9
|
+
* 所有 Vario 相关错误都应继承此类
|
|
10
|
+
*/
|
|
11
|
+
export class VarioError extends Error {
|
|
12
|
+
/** 错误码 */
|
|
13
|
+
code;
|
|
14
|
+
/** 错误上下文 */
|
|
15
|
+
context;
|
|
16
|
+
constructor(message, code, context = {}) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.name = 'VarioError';
|
|
19
|
+
this.code = code;
|
|
20
|
+
this.context = context;
|
|
21
|
+
// 确保 stack 属性存在
|
|
22
|
+
if (Error.captureStackTrace) {
|
|
23
|
+
Error.captureStackTrace(this, VarioError);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 获取友好的错误消息
|
|
28
|
+
*/
|
|
29
|
+
getFriendlyMessage() {
|
|
30
|
+
const parts = [this.message];
|
|
31
|
+
if (this.context.schemaPath) {
|
|
32
|
+
parts.push(`\n Schema 路径: ${this.context.schemaPath}`);
|
|
33
|
+
}
|
|
34
|
+
if (this.context.expression) {
|
|
35
|
+
parts.push(`\n 表达式: ${this.context.expression}`);
|
|
36
|
+
}
|
|
37
|
+
if (this.context.action) {
|
|
38
|
+
parts.push(`\n 动作类型: ${this.context.action.type}`);
|
|
39
|
+
}
|
|
40
|
+
return parts.join('');
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 转换为 JSON(用于序列化)
|
|
44
|
+
*/
|
|
45
|
+
toJSON() {
|
|
46
|
+
return {
|
|
47
|
+
name: this.name,
|
|
48
|
+
message: this.message,
|
|
49
|
+
code: this.code,
|
|
50
|
+
context: this.context,
|
|
51
|
+
stack: this.stack
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 动作执行错误
|
|
57
|
+
*/
|
|
58
|
+
export class ActionError extends VarioError {
|
|
59
|
+
constructor(action, message, code = 'ACTION_ERROR', context = {}) {
|
|
60
|
+
super(message, code, {
|
|
61
|
+
...context,
|
|
62
|
+
action
|
|
63
|
+
});
|
|
64
|
+
this.name = 'ActionError';
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* 表达式求值错误
|
|
69
|
+
*/
|
|
70
|
+
export class ExpressionError extends VarioError {
|
|
71
|
+
constructor(expression, message, code = 'EXPRESSION_ERROR', context = {}) {
|
|
72
|
+
super(message, code, {
|
|
73
|
+
...context,
|
|
74
|
+
expression
|
|
75
|
+
});
|
|
76
|
+
this.name = 'ExpressionError';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* 服务调用错误
|
|
81
|
+
*/
|
|
82
|
+
export class ServiceError extends VarioError {
|
|
83
|
+
service;
|
|
84
|
+
originalError;
|
|
85
|
+
constructor(service, message, originalError, context = {}) {
|
|
86
|
+
super(message, 'SERVICE_ERROR', context);
|
|
87
|
+
this.name = 'ServiceError';
|
|
88
|
+
this.service = service;
|
|
89
|
+
this.originalError = originalError;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* 批量执行错误
|
|
94
|
+
*/
|
|
95
|
+
export class BatchError extends VarioError {
|
|
96
|
+
failedActions;
|
|
97
|
+
constructor(failedActions, message, context = {}) {
|
|
98
|
+
super(message, 'BATCH_ERROR', context);
|
|
99
|
+
this.name = 'BatchError';
|
|
100
|
+
this.failedActions = failedActions;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* 错误码定义
|
|
105
|
+
*/
|
|
106
|
+
export const ErrorCodes = {
|
|
107
|
+
// 动作相关错误
|
|
108
|
+
ACTION_UNKNOWN_TYPE: 'ACTION_UNKNOWN_TYPE',
|
|
109
|
+
ACTION_EXECUTION_ERROR: 'ACTION_EXECUTION_ERROR',
|
|
110
|
+
ACTION_ABORTED: 'ACTION_ABORTED',
|
|
111
|
+
ACTION_TIMEOUT: 'ACTION_TIMEOUT',
|
|
112
|
+
ACTION_MAX_STEPS_EXCEEDED: 'ACTION_MAX_STEPS_EXCEEDED',
|
|
113
|
+
ACTION_MISSING_PARAM: 'ACTION_MISSING_PARAM',
|
|
114
|
+
ACTION_INVALID_PARAM: 'ACTION_INVALID_PARAM',
|
|
115
|
+
// 表达式相关错误
|
|
116
|
+
EXPRESSION_PARSE_ERROR: 'EXPRESSION_PARSE_ERROR',
|
|
117
|
+
EXPRESSION_VALIDATION_ERROR: 'EXPRESSION_VALIDATION_ERROR',
|
|
118
|
+
EXPRESSION_EVALUATION_ERROR: 'EXPRESSION_EVALUATION_ERROR',
|
|
119
|
+
EXPRESSION_TIMEOUT: 'EXPRESSION_TIMEOUT',
|
|
120
|
+
EXPRESSION_MAX_STEPS_EXCEEDED: 'EXPRESSION_MAX_STEPS_EXCEEDED',
|
|
121
|
+
EXPRESSION_UNSAFE_ACCESS: 'EXPRESSION_UNSAFE_ACCESS',
|
|
122
|
+
EXPRESSION_FUNCTION_NOT_WHITELISTED: 'EXPRESSION_FUNCTION_NOT_WHITELISTED',
|
|
123
|
+
// 服务相关错误
|
|
124
|
+
SERVICE_NOT_FOUND: 'SERVICE_NOT_FOUND',
|
|
125
|
+
SERVICE_CALL_ERROR: 'SERVICE_CALL_ERROR',
|
|
126
|
+
// 批量执行错误
|
|
127
|
+
BATCH_ERROR: 'BATCH_ERROR',
|
|
128
|
+
// Schema 相关错误
|
|
129
|
+
SCHEMA_VALIDATION_ERROR: 'SCHEMA_VALIDATION_ERROR',
|
|
130
|
+
SCHEMA_INVALID_ACTION: 'SCHEMA_INVALID_ACTION',
|
|
131
|
+
};
|
|
132
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 表达式缓存系统
|
|
3
|
+
*
|
|
4
|
+
* 功能:
|
|
5
|
+
* - 每个 RuntimeContext 独立缓存(WeakMap 关联)
|
|
6
|
+
* - LRU 淘汰策略
|
|
7
|
+
* - 通配符依赖匹配
|
|
8
|
+
* - 缓存失效机制
|
|
9
|
+
*
|
|
10
|
+
* 设计原则:
|
|
11
|
+
* - 惰性求值:只在需要时计算
|
|
12
|
+
* - 依赖追踪:精确的缓存失效
|
|
13
|
+
* - 内存友好:WeakMap + LRU 淘汰
|
|
14
|
+
*/
|
|
15
|
+
import type { RuntimeContext } from '../types.js';
|
|
16
|
+
/**
|
|
17
|
+
* 获取缓存的表达式结果
|
|
18
|
+
*
|
|
19
|
+
* @param expr 表达式字符串
|
|
20
|
+
* @param ctx 运行时上下文
|
|
21
|
+
* @returns 缓存的结果,无缓存或已失效返回 null
|
|
22
|
+
*/
|
|
23
|
+
export declare function getCachedExpression(expr: string, ctx: RuntimeContext): unknown | null;
|
|
24
|
+
/**
|
|
25
|
+
* 设置表达式缓存
|
|
26
|
+
*
|
|
27
|
+
* @param expr 表达式字符串
|
|
28
|
+
* @param result 求值结果
|
|
29
|
+
* @param dependencies 依赖的状态路径
|
|
30
|
+
* @param ctx 运行时上下文
|
|
31
|
+
*/
|
|
32
|
+
export declare function setCachedExpression(expr: string, result: unknown, dependencies: string[], ctx: RuntimeContext): void;
|
|
33
|
+
/**
|
|
34
|
+
* 使缓存失效
|
|
35
|
+
*
|
|
36
|
+
* 当状态变化时调用,精确删除依赖该状态的缓存
|
|
37
|
+
*
|
|
38
|
+
* @param changedPath 变化的状态路径
|
|
39
|
+
* @param ctx 运行时上下文
|
|
40
|
+
*/
|
|
41
|
+
export declare function invalidateCache(changedPath: string, ctx: RuntimeContext): void;
|
|
42
|
+
/**
|
|
43
|
+
* 清除指定上下文的所有缓存
|
|
44
|
+
*/
|
|
45
|
+
export declare function clearCache(ctx: RuntimeContext): void;
|
|
46
|
+
/**
|
|
47
|
+
* 获取缓存统计信息(调试用)
|
|
48
|
+
*/
|
|
49
|
+
export declare function getCacheStats(ctx: RuntimeContext): {
|
|
50
|
+
size: number;
|
|
51
|
+
expressions: string[];
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/expression/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAmB,MAAM,aAAa,CAAA;AA0ElE;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,cAAc,GAClB,OAAO,GAAG,IAAI,CAgBhB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,OAAO,EACf,YAAY,EAAE,MAAM,EAAE,EACtB,GAAG,EAAE,cAAc,GAClB,IAAI,CAcN;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,cAAc,GAClB,IAAI,CAmBN;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAGpD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG;IAClD,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,EAAE,CAAA;CACtB,CAMA"}
|