@yanit/jsondb 0.1.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.
Files changed (118) hide show
  1. package/README.md +903 -0
  2. package/dist/bin/cli-export.d.ts +7 -0
  3. package/dist/bin/cli-export.d.ts.map +1 -0
  4. package/dist/bin/cli-export.js +318 -0
  5. package/dist/bin/cli-export.js.map +1 -0
  6. package/dist/bin/cli-import.d.ts +7 -0
  7. package/dist/bin/cli-import.d.ts.map +1 -0
  8. package/dist/bin/cli-import.js +298 -0
  9. package/dist/bin/cli-import.js.map +1 -0
  10. package/dist/bin/server.d.ts +7 -0
  11. package/dist/bin/server.d.ts.map +1 -0
  12. package/dist/bin/server.js +92 -0
  13. package/dist/bin/server.js.map +1 -0
  14. package/dist/examples/sql-example.d.ts +7 -0
  15. package/dist/examples/sql-example.d.ts.map +1 -0
  16. package/dist/examples/sql-example.js +131 -0
  17. package/dist/examples/sql-example.js.map +1 -0
  18. package/dist/src/BulkOp.d.ts +74 -0
  19. package/dist/src/BulkOp.d.ts.map +1 -0
  20. package/dist/src/BulkOp.js +143 -0
  21. package/dist/src/BulkOp.js.map +1 -0
  22. package/dist/src/Collection.d.ts +232 -0
  23. package/dist/src/Collection.d.ts.map +1 -0
  24. package/dist/src/Collection.js +705 -0
  25. package/dist/src/Collection.js.map +1 -0
  26. package/dist/src/Cursor.d.ts +94 -0
  27. package/dist/src/Cursor.d.ts.map +1 -0
  28. package/dist/src/Cursor.js +259 -0
  29. package/dist/src/Cursor.js.map +1 -0
  30. package/dist/src/Database.d.ts +98 -0
  31. package/dist/src/Database.d.ts.map +1 -0
  32. package/dist/src/Database.js +198 -0
  33. package/dist/src/Database.js.map +1 -0
  34. package/dist/src/Operators.d.ts +73 -0
  35. package/dist/src/Operators.d.ts.map +1 -0
  36. package/dist/src/Operators.js +339 -0
  37. package/dist/src/Operators.js.map +1 -0
  38. package/dist/src/QueryCache.d.ts +87 -0
  39. package/dist/src/QueryCache.d.ts.map +1 -0
  40. package/dist/src/QueryCache.js +155 -0
  41. package/dist/src/QueryCache.js.map +1 -0
  42. package/dist/src/SQLExecutor.d.ts +60 -0
  43. package/dist/src/SQLExecutor.d.ts.map +1 -0
  44. package/dist/src/SQLExecutor.js +317 -0
  45. package/dist/src/SQLExecutor.js.map +1 -0
  46. package/dist/src/SQLParser.d.ts +181 -0
  47. package/dist/src/SQLParser.d.ts.map +1 -0
  48. package/dist/src/SQLParser.js +640 -0
  49. package/dist/src/SQLParser.js.map +1 -0
  50. package/dist/src/Schema.d.ts +92 -0
  51. package/dist/src/Schema.d.ts.map +1 -0
  52. package/dist/src/Schema.js +253 -0
  53. package/dist/src/Schema.js.map +1 -0
  54. package/dist/src/Transaction.d.ts +118 -0
  55. package/dist/src/Transaction.d.ts.map +1 -0
  56. package/dist/src/Transaction.js +233 -0
  57. package/dist/src/Transaction.js.map +1 -0
  58. package/dist/src/Utils.d.ts +68 -0
  59. package/dist/src/Utils.d.ts.map +1 -0
  60. package/dist/src/Utils.js +187 -0
  61. package/dist/src/Utils.js.map +1 -0
  62. package/dist/src/errors.d.ts +58 -0
  63. package/dist/src/errors.d.ts.map +1 -0
  64. package/dist/src/errors.js +85 -0
  65. package/dist/src/errors.js.map +1 -0
  66. package/dist/src/index.d.ts +39 -0
  67. package/dist/src/index.d.ts.map +1 -0
  68. package/dist/src/index.js +44 -0
  69. package/dist/src/index.js.map +1 -0
  70. package/dist/test/basic.test.d.ts +5 -0
  71. package/dist/test/basic.test.d.ts.map +1 -0
  72. package/dist/test/basic.test.js +283 -0
  73. package/dist/test/basic.test.js.map +1 -0
  74. package/dist/test/index.test.d.ts +5 -0
  75. package/dist/test/index.test.d.ts.map +1 -0
  76. package/dist/test/index.test.js +126 -0
  77. package/dist/test/index.test.js.map +1 -0
  78. package/dist/test/jsonb.test.d.ts +5 -0
  79. package/dist/test/jsonb.test.d.ts.map +1 -0
  80. package/dist/test/jsonb.test.js +165 -0
  81. package/dist/test/jsonb.test.js.map +1 -0
  82. package/dist/test/optimization.test.d.ts +6 -0
  83. package/dist/test/optimization.test.d.ts.map +1 -0
  84. package/dist/test/optimization.test.js +196 -0
  85. package/dist/test/optimization.test.js.map +1 -0
  86. package/dist/test/schema.test.d.ts +5 -0
  87. package/dist/test/schema.test.d.ts.map +1 -0
  88. package/dist/test/schema.test.js +197 -0
  89. package/dist/test/schema.test.js.map +1 -0
  90. package/dist/test/sql.test.d.ts +7 -0
  91. package/dist/test/sql.test.d.ts.map +1 -0
  92. package/dist/test/sql.test.js +21 -0
  93. package/dist/test/sql.test.js.map +1 -0
  94. package/package.json +73 -0
  95. package/src/BulkOp.js +181 -0
  96. package/src/BulkOp.ts +191 -0
  97. package/src/Collection.js +843 -0
  98. package/src/Collection.ts +896 -0
  99. package/src/Cursor.js +315 -0
  100. package/src/Cursor.ts +319 -0
  101. package/src/Database.js +244 -0
  102. package/src/Database.ts +268 -0
  103. package/src/Operators.js +382 -0
  104. package/src/Operators.ts +375 -0
  105. package/src/QueryCache.js +190 -0
  106. package/src/QueryCache.ts +208 -0
  107. package/src/SQLExecutor.ts +391 -0
  108. package/src/SQLParser.ts +814 -0
  109. package/src/Schema.js +292 -0
  110. package/src/Schema.ts +317 -0
  111. package/src/Transaction.js +291 -0
  112. package/src/Transaction.ts +313 -0
  113. package/src/Utils.js +205 -0
  114. package/src/Utils.ts +205 -0
  115. package/src/errors.js +93 -0
  116. package/src/errors.ts +93 -0
  117. package/src/index.js +90 -0
  118. package/src/index.ts +106 -0
package/src/Schema.js ADDED
@@ -0,0 +1,292 @@
1
+ /**
2
+ * Schema 验证模块
3
+ * 提供数据验证功能
4
+ */
5
+
6
+ /**
7
+ * 验证器类型
8
+ */
9
+ export const validators = {
10
+ /**
11
+ * 字符串验证
12
+ */
13
+ string: (value, options = {}) => {
14
+ if (typeof value !== 'string') {
15
+ return { valid: false, message: '必须是字符串' };
16
+ }
17
+ if (options.minLength && value.length < options.minLength) {
18
+ return { valid: false, message: `最小长度为 ${options.minLength}` };
19
+ }
20
+ if (options.maxLength && value.length > options.maxLength) {
21
+ return { valid: false, message: `最大长度为 ${options.maxLength}` };
22
+ }
23
+ if (options.pattern && !options.pattern.test(value)) {
24
+ return { valid: false, message: '格式不匹配' };
25
+ }
26
+ if (options.enum && !options.enum.includes(value)) {
27
+ return { valid: false, message: '值不在枚举列表中' };
28
+ }
29
+ return { valid: true };
30
+ },
31
+
32
+ /**
33
+ * 数字验证
34
+ */
35
+ number: (value, options = {}) => {
36
+ if (typeof value !== 'number') {
37
+ return { valid: false, message: '必须是数字' };
38
+ }
39
+ if (options.min !== undefined && value < options.min) {
40
+ return { valid: false, message: `最小值为 ${options.min}` };
41
+ }
42
+ if (options.max !== undefined && value > options.max) {
43
+ return { valid: false, message: `最大值为 ${options.max}` };
44
+ }
45
+ if (options.integer && !Number.isInteger(value)) {
46
+ return { valid: false, message: '必须是整数' };
47
+ }
48
+ return { valid: true };
49
+ },
50
+
51
+ /**
52
+ * 布尔值验证
53
+ */
54
+ boolean: (value) => {
55
+ if (typeof value !== 'boolean') {
56
+ return { valid: false, message: '必须是布尔值' };
57
+ }
58
+ return { valid: true };
59
+ },
60
+
61
+ /**
62
+ * 日期验证
63
+ */
64
+ date: (value) => {
65
+ if (!(value instanceof Date) || isNaN(value.getTime())) {
66
+ return { valid: false, message: '必须是有效的日期' };
67
+ }
68
+ return { valid: true };
69
+ },
70
+
71
+ /**
72
+ * 数组验证
73
+ */
74
+ array: (value, options = {}) => {
75
+ if (!Array.isArray(value)) {
76
+ return { valid: false, message: '必须是数组' };
77
+ }
78
+ if (options.minLength && value.length < options.minLength) {
79
+ return { valid: false, message: `最小长度为 ${options.minLength}` };
80
+ }
81
+ if (options.maxLength && value.length > options.maxLength) {
82
+ return { valid: false, message: `最大长度为 ${options.maxLength}` };
83
+ }
84
+ if (options.items) {
85
+ for (let i = 0; i < value.length; i++) {
86
+ const result = validateValue(value[i], options.items);
87
+ if (!result.valid) {
88
+ return { valid: false, message: `索引 ${i}: ${result.message}` };
89
+ }
90
+ }
91
+ }
92
+ return { valid: true };
93
+ },
94
+
95
+ /**
96
+ * 对象验证
97
+ */
98
+ object: (value, options = {}) => {
99
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
100
+ return { valid: false, message: '必须是对象' };
101
+ }
102
+ if (options.properties) {
103
+ return validateObject(value, options.properties);
104
+ }
105
+ return { valid: true };
106
+ },
107
+
108
+ /**
109
+ * 枚举验证
110
+ */
111
+ enum: (value, options = {}) => {
112
+ if (!options.values || !options.values.includes(value)) {
113
+ return { valid: false, message: '值不在允许的列表中' };
114
+ }
115
+ return { valid: true };
116
+ },
117
+
118
+ /**
119
+ * 自定义验证
120
+ */
121
+ custom: (value, options = {}) => {
122
+ if (typeof options.validate !== 'function') {
123
+ return { valid: false, message: '验证函数无效' };
124
+ }
125
+ try {
126
+ const result = options.validate(value);
127
+ return result === true ? { valid: true } : { valid: false, message: result || '验证失败' };
128
+ } catch (e) {
129
+ return { valid: false, message: e.message };
130
+ }
131
+ }
132
+ };
133
+
134
+ /**
135
+ * 验证单个值
136
+ * @param {any} value - 值
137
+ * @param {Object} schema - Schema 定义
138
+ * @returns {Object} 验证结果
139
+ */
140
+ function validateValue(value, schema) {
141
+ if (!schema || !schema.type) {
142
+ return { valid: true };
143
+ }
144
+
145
+ const validator = validators[schema.type];
146
+ if (!validator) {
147
+ return { valid: false, message: `未知的类型:${schema.type}` };
148
+ }
149
+
150
+ // 检查是否允许 null
151
+ if (value === null || value === undefined) {
152
+ if (schema.required) {
153
+ return { valid: false, message: '此字段不能为空' };
154
+ }
155
+ return { valid: true };
156
+ }
157
+
158
+ return validator(value, schema);
159
+ }
160
+
161
+ /**
162
+ * 验证对象
163
+ * @param {Object} obj - 对象
164
+ * @param {Object} properties - 属性定义
165
+ * @returns {Object} 验证结果
166
+ */
167
+ function validateObject(obj, properties) {
168
+ const errors = [];
169
+
170
+ // 检查必填字段
171
+ for (const [key, schema] of Object.entries(properties)) {
172
+ if (schema.required && (obj[key] === undefined || obj[key] === null)) {
173
+ errors.push({ field: key, message: '此字段不能为空' });
174
+ continue;
175
+ }
176
+
177
+ if (obj[key] !== undefined && obj[key] !== null) {
178
+ const result = validateValue(obj[key], schema);
179
+ if (!result.valid) {
180
+ errors.push({ field: key, message: result.message });
181
+ }
182
+ }
183
+ }
184
+
185
+ // 检查额外字段
186
+ if (properties._additional === false) {
187
+ const allowedKeys = Object.keys(properties);
188
+ for (const key of Object.keys(obj)) {
189
+ if (!allowedKeys.includes(key)) {
190
+ errors.push({ field: key, message: '不允许的字段' });
191
+ }
192
+ }
193
+ }
194
+
195
+ return errors.length === 0
196
+ ? { valid: true }
197
+ : { valid: false, errors };
198
+ }
199
+
200
+ /**
201
+ * Schema 类
202
+ */
203
+ export class Schema {
204
+ constructor(properties, options = {}) {
205
+ this.properties = properties;
206
+ this.options = {
207
+ strict: options.strict || false, // 严格模式:不允许额外字段
208
+ ...options
209
+ };
210
+ }
211
+
212
+ /**
213
+ * 验证对象
214
+ * @param {Object} obj - 对象
215
+ * @returns {Object} 验证结果
216
+ */
217
+ validate(obj) {
218
+ if (this.options.strict) {
219
+ this.properties._additional = false;
220
+ }
221
+ return validateObject(obj, this.properties);
222
+ }
223
+
224
+ /**
225
+ * 验证并抛出异常
226
+ * @param {Object} obj - 对象
227
+ * @throws {Error} 验证失败时抛出异常
228
+ */
229
+ validateOrThrow(obj) {
230
+ const result = this.validate(obj);
231
+ if (!result.valid) {
232
+ const error = new Error(`验证失败:${result.errors.map(e => `${e.field}: ${e.message}`).join(', ')}`);
233
+ error.errors = result.errors;
234
+ throw error;
235
+ }
236
+ }
237
+
238
+ /**
239
+ * 清理对象(移除额外字段)
240
+ * @param {Object} obj - 对象
241
+ * @returns {Object} 清理后的对象
242
+ */
243
+ sanitize(obj) {
244
+ const result = {};
245
+ for (const key of Object.keys(this.properties)) {
246
+ if (obj[key] !== undefined) {
247
+ result[key] = obj[key];
248
+ }
249
+ }
250
+ return result;
251
+ }
252
+
253
+ /**
254
+ * 应用默认值
255
+ * @param {Object} obj - 对象
256
+ * @returns {Object} 应用默认值后的对象
257
+ */
258
+ applyDefaults(obj) {
259
+ const result = { ...obj };
260
+ for (const [key, schema] of Object.entries(this.properties)) {
261
+ if (result[key] === undefined && schema.default !== undefined) {
262
+ result[key] = schema.default;
263
+ }
264
+ }
265
+ return result;
266
+ }
267
+ }
268
+
269
+ /**
270
+ * 创建 Schema
271
+ * @param {Object} properties - 属性定义
272
+ * @param {Object} options - 选项
273
+ * @returns {Schema}
274
+ */
275
+ export function createSchema(properties, options) {
276
+ return new Schema(properties, options);
277
+ }
278
+
279
+ /**
280
+ * 验证中间件工厂
281
+ * @param {Schema} schema - Schema 实例
282
+ * @returns {Function} 中间件函数
283
+ */
284
+ export function createValidator(schema) {
285
+ return async (doc) => {
286
+ const result = schema.validate(doc);
287
+ if (!result.valid) {
288
+ throw new Error(`验证失败:${result.errors.map(e => `${e.field}: ${e.message}`).join(', ')}`);
289
+ }
290
+ return doc;
291
+ };
292
+ }
package/src/Schema.ts ADDED
@@ -0,0 +1,317 @@
1
+ /**
2
+ * Schema 验证模块
3
+ * 提供数据验证功能
4
+ */
5
+
6
+ /**
7
+ * 验证结果接口
8
+ */
9
+ interface ValidationResult {
10
+ valid: boolean;
11
+ message?: string;
12
+ errors?: Array<{ field: string; message: string }>;
13
+ }
14
+
15
+ /**
16
+ * Schema 选项接口
17
+ */
18
+ interface SchemaOptions {
19
+ required?: boolean;
20
+ minLength?: number;
21
+ maxLength?: number;
22
+ pattern?: RegExp;
23
+ enum?: string[];
24
+ values?: string[];
25
+ min?: number;
26
+ max?: number;
27
+ integer?: boolean;
28
+ items?: SchemaDefinition;
29
+ properties?: Record<string, SchemaDefinition>;
30
+ validate?: (value: unknown) => boolean | string;
31
+ default?: unknown;
32
+ strict?: boolean;
33
+ _additional?: boolean;
34
+ type?: string;
35
+ }
36
+
37
+ /**
38
+ * Schema 定义接口
39
+ */
40
+ interface SchemaDefinition {
41
+ type: string;
42
+ required?: boolean;
43
+ default?: unknown;
44
+ [key: string]: unknown;
45
+ }
46
+
47
+ /**
48
+ * 验证器类型
49
+ */
50
+ export const validators: Record<string, (value: unknown, options?: SchemaOptions) => ValidationResult> = {
51
+ /**
52
+ * 字符串验证
53
+ */
54
+ string: (value, options = {}) => {
55
+ if (typeof value !== 'string') {
56
+ return { valid: false, message: '必须是字符串' };
57
+ }
58
+ if (options.minLength && value.length < options.minLength) {
59
+ return { valid: false, message: `最小长度为 ${options.minLength}` };
60
+ }
61
+ if (options.maxLength && value.length > options.maxLength) {
62
+ return { valid: false, message: `最大长度为 ${options.maxLength}` };
63
+ }
64
+ if (options.pattern && !options.pattern.test(value)) {
65
+ return { valid: false, message: '格式不匹配' };
66
+ }
67
+ if (options.enum && !options.enum.includes(value)) {
68
+ return { valid: false, message: '值不在枚举列表中' };
69
+ }
70
+ return { valid: true };
71
+ },
72
+
73
+ /**
74
+ * 数字验证
75
+ */
76
+ number: (value, options = {}) => {
77
+ if (typeof value !== 'number') {
78
+ return { valid: false, message: '必须是数字' };
79
+ }
80
+ if (options.min !== undefined && value < options.min) {
81
+ return { valid: false, message: `最小值为 ${options.min}` };
82
+ }
83
+ if (options.max !== undefined && value > options.max) {
84
+ return { valid: false, message: `最大值为 ${options.max}` };
85
+ }
86
+ if (options.integer && !Number.isInteger(value)) {
87
+ return { valid: false, message: '必须是整数' };
88
+ }
89
+ return { valid: true };
90
+ },
91
+
92
+ /**
93
+ * 布尔值验证
94
+ */
95
+ boolean: (value) => {
96
+ if (typeof value !== 'boolean') {
97
+ return { valid: false, message: '必须是布尔值' };
98
+ }
99
+ return { valid: true };
100
+ },
101
+
102
+ /**
103
+ * 日期验证
104
+ */
105
+ date: (value) => {
106
+ if (!(value instanceof Date) || isNaN(value.getTime())) {
107
+ return { valid: false, message: '必须是有效的日期' };
108
+ }
109
+ return { valid: true };
110
+ },
111
+
112
+ /**
113
+ * 数组验证
114
+ */
115
+ array: (value, options = {}) => {
116
+ if (!Array.isArray(value)) {
117
+ return { valid: false, message: '必须是数组' };
118
+ }
119
+ if (options.minLength && value.length < options.minLength) {
120
+ return { valid: false, message: `最小长度为 ${options.minLength}` };
121
+ }
122
+ if (options.maxLength && value.length > options.maxLength) {
123
+ return { valid: false, message: `最大长度为 ${options.maxLength}` };
124
+ }
125
+ if (options.items) {
126
+ for (let i = 0; i < value.length; i++) {
127
+ const result = validateValue(value[i], options.items);
128
+ if (!result.valid) {
129
+ return { valid: false, message: `索引 ${i}: ${result.message}` };
130
+ }
131
+ }
132
+ }
133
+ return { valid: true };
134
+ },
135
+
136
+ /**
137
+ * 对象验证
138
+ */
139
+ object: (value, options = {}) => {
140
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
141
+ return { valid: false, message: '必须是对象' };
142
+ }
143
+ if (options.properties) {
144
+ return validateObject(value as Record<string, unknown>, options.properties);
145
+ }
146
+ return { valid: true };
147
+ },
148
+
149
+ /**
150
+ * 枚举验证
151
+ */
152
+ enum: (value, options = {}) => {
153
+ if (!options.values || !options.values.includes(value as string)) {
154
+ return { valid: false, message: '值不在允许的列表中' };
155
+ }
156
+ return { valid: true };
157
+ },
158
+
159
+ /**
160
+ * 自定义验证
161
+ */
162
+ custom: (value, options = {}) => {
163
+ if (typeof options.validate !== 'function') {
164
+ return { valid: false, message: '验证函数无效' };
165
+ }
166
+ try {
167
+ const result = options.validate(value);
168
+ return result === true ? { valid: true } : { valid: false, message: result || '验证失败' };
169
+ } catch (e) {
170
+ return { valid: false, message: (e as Error).message };
171
+ }
172
+ }
173
+ };
174
+
175
+ /**
176
+ * 验证单个值
177
+ */
178
+ function validateValue(value: unknown, schema: SchemaDefinition): ValidationResult {
179
+ if (!schema || !schema.type) {
180
+ return { valid: true };
181
+ }
182
+
183
+ const validator = validators[schema.type];
184
+ if (!validator) {
185
+ return { valid: false, message: `未知的类型:${schema.type}` };
186
+ }
187
+
188
+ // 检查是否允许 null
189
+ if (value === null || value === undefined) {
190
+ if (schema.required) {
191
+ return { valid: false, message: '此字段不能为空' };
192
+ }
193
+ return { valid: true };
194
+ }
195
+
196
+ return validator(value, schema as SchemaOptions);
197
+ }
198
+
199
+ /**
200
+ * 验证对象
201
+ */
202
+ function validateObject(obj: Record<string, unknown>, properties: Record<string, SchemaDefinition>): ValidationResult {
203
+ const errors: Array<{ field: string; message: string }> = [];
204
+
205
+ // 检查必填字段
206
+ for (const [key, schema] of Object.entries(properties)) {
207
+ if (schema.required && (obj[key] === undefined || obj[key] === null)) {
208
+ errors.push({ field: key, message: '此字段不能为空' });
209
+ continue;
210
+ }
211
+
212
+ if (obj[key] !== undefined && obj[key] !== null) {
213
+ const result = validateValue(obj[key], schema);
214
+ if (!result.valid) {
215
+ errors.push({ field: key, message: result.message! });
216
+ }
217
+ }
218
+ }
219
+
220
+ // 检查额外字段
221
+ if ((properties as Record<string, unknown> & { _additional?: boolean })._additional === false) {
222
+ const allowedKeys = Object.keys(properties);
223
+ for (const key of Object.keys(obj)) {
224
+ if (!allowedKeys.includes(key)) {
225
+ errors.push({ field: key, message: '不允许的字段' });
226
+ }
227
+ }
228
+ }
229
+
230
+ return errors.length === 0
231
+ ? { valid: true }
232
+ : { valid: false, errors };
233
+ }
234
+
235
+ /**
236
+ * Schema 类
237
+ */
238
+ export class Schema {
239
+ properties: Record<string, SchemaDefinition>;
240
+ options: { strict: boolean; [key: string]: unknown };
241
+
242
+ constructor(properties: Record<string, SchemaDefinition>, options: { strict?: boolean; [key: string]: unknown } = {}) {
243
+ this.properties = properties;
244
+ this.options = {
245
+ strict: options.strict || false,
246
+ ...options
247
+ };
248
+ }
249
+
250
+ /**
251
+ * 验证对象
252
+ */
253
+ validate(obj: Record<string, unknown>): ValidationResult {
254
+ if (this.options.strict) {
255
+ (this.properties as SchemaOptions)._additional = false;
256
+ }
257
+ return validateObject(obj, this.properties);
258
+ }
259
+
260
+ /**
261
+ * 验证并抛出异常
262
+ */
263
+ validateOrThrow(obj: Record<string, unknown>): void {
264
+ const result = this.validate(obj);
265
+ if (!result.valid) {
266
+ const error = new Error(`验证失败:${result.errors!.map(e => `${e.field}: ${e.message}`).join(', ')}`);
267
+ (error as Error & { errors: Array<{ field: string; message: string }> }).errors = result.errors!;
268
+ throw error;
269
+ }
270
+ }
271
+
272
+ /**
273
+ * 清理对象(移除额外字段)
274
+ */
275
+ sanitize(obj: Record<string, unknown>): Record<string, unknown> {
276
+ const result: Record<string, unknown> = {};
277
+ for (const key of Object.keys(this.properties)) {
278
+ if (obj[key] !== undefined) {
279
+ result[key] = obj[key];
280
+ }
281
+ }
282
+ return result;
283
+ }
284
+
285
+ /**
286
+ * 应用默认值
287
+ */
288
+ applyDefaults(obj: Record<string, unknown>): Record<string, unknown> {
289
+ const result = { ...obj };
290
+ for (const [key, schema] of Object.entries(this.properties)) {
291
+ if (result[key] === undefined && schema.default !== undefined) {
292
+ result[key] = schema.default;
293
+ }
294
+ }
295
+ return result;
296
+ }
297
+ }
298
+
299
+ /**
300
+ * 创建 Schema
301
+ */
302
+ export function createSchema(properties: Record<string, SchemaDefinition>, options?: { strict?: boolean; [key: string]: unknown }): Schema {
303
+ return new Schema(properties, options);
304
+ }
305
+
306
+ /**
307
+ * 验证中间件工厂
308
+ */
309
+ export function createValidator(schema: Schema) {
310
+ return async (doc: Record<string, unknown>): Promise<Record<string, unknown>> => {
311
+ const result = schema.validate(doc);
312
+ if (!result.valid) {
313
+ throw new Error(`验证失败:${result.errors!.map(e => `${e.field}: ${e.message}`).join(', ')}`);
314
+ }
315
+ return doc;
316
+ };
317
+ }