ajv-standalone-bundler 1.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/README.md +75 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +3 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# ajv-standalone-bundler
|
|
2
|
+
|
|
3
|
+
一个将 Ajv 和 standalone code generator 打包在一起的包,解决在浏览器/ESM 环境下分别导入导致的模块实例问题。
|
|
4
|
+
|
|
5
|
+
## 问题背景
|
|
6
|
+
|
|
7
|
+
当你在浏览器中使用 CDN 动态导入 Ajv 和 standaloneCode 时,通常会这样写:
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
const [{ default: Ajv }, { default: standaloneCode }] = await Promise.all([
|
|
11
|
+
import('https://esm.sh/ajv@8.18.0'),
|
|
12
|
+
import('https://esm.sh/ajv@8.18.0/dist/standalone'),
|
|
13
|
+
]);
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### 问题根源
|
|
17
|
+
|
|
18
|
+
这种导入方式会创建**两个独立的模块实例**:
|
|
19
|
+
|
|
20
|
+
1. 第一个 `import()` 加载 `ajv.mjs` → 创建模块实例 A → 包含 `_Code` 类定义 A
|
|
21
|
+
2. 第二个 `import()` 加载 `standalone.mjs` → 创建模块实例 B → 包含 `_Code` 类定义 B
|
|
22
|
+
|
|
23
|
+
当调用 `ajv.compile(schema)` 返回验证函数后,这个函数内部包含 `_Code` 对象。当 `standaloneCode` 尝试处理这些对象时,它使用 `instanceof _Code` 进行类型检查:
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
// ajv 内部代码 (lib/compile/codegen/code.ts)
|
|
27
|
+
export function addCodeArg(code: CodeItem[], arg: CodeArg | string[]): void {
|
|
28
|
+
if (arg instanceof _Code) code.push(...arg._items) // ← 这里!
|
|
29
|
+
else if (arg instanceof Name) code.push(arg)
|
|
30
|
+
else code.push(interpolate(arg)) // ← 当 instanceof 失败时走这里
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
由于 `_Code` 类来自不同的模块实例,`instanceof` 检查返回 `false`,导致代码走入了错误的分支:
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
// 当 instanceof 失败时,对象被 JSON 序列化
|
|
38
|
+
function interpolate(x?: string | string[] | number | boolean | null): SafeExpr | string {
|
|
39
|
+
return typeof x == "number" || typeof x == "boolean" || x === null
|
|
40
|
+
? x
|
|
41
|
+
: safeStringify(Array.isArray(x) ? x.join(",") : x) // ← 错误的 JSON 序列化
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 实际后果
|
|
46
|
+
|
|
47
|
+
生成的代码中会出现这样的错误输出:
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
const validate11 = function(data, {...}) {
|
|
51
|
+
// ... 验证代码 ...
|
|
52
|
+
|
|
53
|
+
// ❌ 错误:_Code 对象被 JSON 序列化
|
|
54
|
+
var _self = {"_items":["self"]};
|
|
55
|
+
|
|
56
|
+
// ❌ 错误:_Code 对象数组被 JSON 序列化
|
|
57
|
+
var validate = {"_items":["validate"]};
|
|
58
|
+
};
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
而不是正确的 JavaScript 代码:
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
const validate11 = function(data, {...}) {
|
|
65
|
+
// ... 正确的验证代码 ...
|
|
66
|
+
var self = this;
|
|
67
|
+
var validate = validate11;
|
|
68
|
+
};
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## 解决方案
|
|
72
|
+
|
|
73
|
+
这个包将 Ajv 和 standaloneCode 打包在一起,确保它们共享同一个模块实例。
|
|
74
|
+
|
|
75
|
+
通过在同一个项目中一起导入并重新导出,Rollup 打包时会将所有代码合并到单个模块中,从而保证 `_Code` 类的 `instanceof` 检查能够正常工作。
|
package/dist/index.d.mts
ADDED
package/dist/index.mjs
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ajv-standalone-bundler",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A bundled package combining Ajv and standalone code generator for CDN usage",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./dist/index.mjs",
|
|
8
|
+
"./*": "./*"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsdown"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"ajv"
|
|
18
|
+
],
|
|
19
|
+
"author": "qire930",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"tsdown": "^0.21.2",
|
|
23
|
+
"typescript": "^5.9.3"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"ajv": "^8.18.0"
|
|
27
|
+
}
|
|
28
|
+
}
|