@zhin.js/schema 1.1.4 → 1.1.5
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/lib/schema.d.ts +5 -3
- package/lib/schema.js +20 -9
- package/lib/validate.js +1 -1
- package/package.json +1 -1
package/lib/schema.d.ts
CHANGED
|
@@ -57,7 +57,9 @@ export declare class Schema<S = any, T = S> {
|
|
|
57
57
|
static date(key?: string): Schema<number | Date, Date>;
|
|
58
58
|
/** 声明一个字典类型 */
|
|
59
59
|
static dict<X extends Schema>(input: X, key?: string): Schema<Record<string, Schema.Input<X>>, Record<string, Schema.Output<X>>>;
|
|
60
|
-
static object<X extends Record<string, Schema<any, any>>>(input: X, key?: string): Schema<Schema.InputRecord<X>, Schema.RecordTypes<X
|
|
60
|
+
static object<X extends Record<string, Schema<any, any>>>(input: X, key?: string): Schema<Schema.InputRecord<X>, Schema.RecordTypes<X>> & {
|
|
61
|
+
readonly output?: Schema.RecordTypes<X>;
|
|
62
|
+
};
|
|
61
63
|
/** 声明一个列表类型 */
|
|
62
64
|
static list<X extends Schema>(inner: X, key?: string): Schema<Schema.Input<X>[], Schema.Output<X>[]>;
|
|
63
65
|
/** 声明一个元组类型 */
|
|
@@ -130,11 +132,11 @@ export declare namespace Schema {
|
|
|
130
132
|
list?: readonly Schema[];
|
|
131
133
|
}
|
|
132
134
|
type Types<T> = Output<T>;
|
|
133
|
-
type RecordTypes<T
|
|
135
|
+
type RecordTypes<T extends Record<string, any>> = {
|
|
134
136
|
[K in keyof T as T[K] extends Present ? K : never]-?: Output<T[K]>;
|
|
135
137
|
} & {
|
|
136
138
|
[K in keyof T as T[K] extends Present ? never : K]?: Output<T[K]>;
|
|
137
|
-
}
|
|
139
|
+
};
|
|
138
140
|
type Union<T extends readonly any[]> = T extends readonly [infer L, ...infer R] ? Types<L> | Union<R> : never;
|
|
139
141
|
type Intersect<T extends readonly any[]> = T extends readonly [infer L, ...infer R] ? Types<L> & Intersect<R> : unknown;
|
|
140
142
|
type Tuple<T extends readonly any[]> = T extends readonly [infer L, ...infer R] ? [Types<L>, ...Tuple<R>] : [];
|
package/lib/schema.js
CHANGED
|
@@ -24,6 +24,9 @@ export class Schema {
|
|
|
24
24
|
set(target, p, value, receiver) {
|
|
25
25
|
return Reflect.set(_this, p, value, receiver);
|
|
26
26
|
},
|
|
27
|
+
has(target, p) {
|
|
28
|
+
return Reflect.has(_this, p) || Reflect.has(target, p);
|
|
29
|
+
},
|
|
27
30
|
});
|
|
28
31
|
}
|
|
29
32
|
static fromJSON(json) {
|
|
@@ -221,7 +224,7 @@ export class Schema {
|
|
|
221
224
|
throw new TypeError(`${key} is not a string`);
|
|
222
225
|
break;
|
|
223
226
|
case 'number':
|
|
224
|
-
if (!['number', 'undefined'].includes(typeof value))
|
|
227
|
+
if (!['number', 'undefined'].includes(typeof value) || (typeof value === 'number' && Number.isNaN(value)))
|
|
225
228
|
throw new TypeError(`${key} is not a number`);
|
|
226
229
|
break;
|
|
227
230
|
case 'boolean':
|
|
@@ -239,11 +242,11 @@ export class Schema {
|
|
|
239
242
|
throw new TypeError(`${key} is not a valid Date`);
|
|
240
243
|
break;
|
|
241
244
|
case 'dict':
|
|
242
|
-
if (!['object', 'undefined'
|
|
245
|
+
if (!['object', 'undefined'].includes(typeof value) || value === null || Array.isArray(value))
|
|
243
246
|
throw new TypeError(`${key} is not a object`);
|
|
244
247
|
break;
|
|
245
248
|
case 'object':
|
|
246
|
-
if (!['object', 'undefined'
|
|
249
|
+
if (!['object', 'undefined'].includes(typeof value) || value === null || Array.isArray(value))
|
|
247
250
|
throw new TypeError(`${key} is not a object`);
|
|
248
251
|
break;
|
|
249
252
|
case 'list':
|
|
@@ -310,19 +313,27 @@ Schema.extend('dict', function (key, value) {
|
|
|
310
313
|
Schema.extend('object', function (key, value) {
|
|
311
314
|
const getDefault = (schema) => {
|
|
312
315
|
const result = Object.create(null);
|
|
313
|
-
for (const
|
|
314
|
-
const propSchema = schema.options.object[
|
|
315
|
-
result[
|
|
316
|
+
for (const propKey in schema.options.object) {
|
|
317
|
+
const propSchema = schema.options.object[propKey];
|
|
318
|
+
result[propKey] = propSchema.meta.default !== undefined ? propSchema.meta.default : undefined;
|
|
316
319
|
}
|
|
317
320
|
return result;
|
|
318
321
|
};
|
|
319
322
|
value = Schema.checkDefault(this, key, value, getDefault(this));
|
|
323
|
+
if (value === undefined)
|
|
324
|
+
return value;
|
|
320
325
|
const result = Object.create(null);
|
|
321
|
-
|
|
322
|
-
|
|
326
|
+
const shape = this.options.object || {};
|
|
327
|
+
const allKeys = new Set([...Object.keys(shape), ...Object.keys(value)]);
|
|
328
|
+
for (const k of allKeys) {
|
|
329
|
+
const val = value[k];
|
|
330
|
+
const propSchema = shape[k];
|
|
323
331
|
if (propSchema) {
|
|
324
332
|
// propSchema是一个可调用的Schema实例
|
|
325
|
-
|
|
333
|
+
const evaluated = propSchema(val, `${key}.${k}`);
|
|
334
|
+
if (evaluated !== undefined || k in value) {
|
|
335
|
+
result[k] = evaluated;
|
|
336
|
+
}
|
|
326
337
|
}
|
|
327
338
|
else {
|
|
328
339
|
result[k] = val;
|
package/lib/validate.js
CHANGED
|
@@ -29,7 +29,7 @@ function validateOnly(schema, path, value) {
|
|
|
29
29
|
}
|
|
30
30
|
return value;
|
|
31
31
|
case 'number':
|
|
32
|
-
if (value !== undefined && typeof value !== 'number') {
|
|
32
|
+
if (value !== undefined && (typeof value !== 'number' || Number.isNaN(value))) {
|
|
33
33
|
throw issue(path, `${path} is not a number`);
|
|
34
34
|
}
|
|
35
35
|
return value;
|