@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 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> = T extends Record<string, Schema> ? {
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
- } : unknown;
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', 'null'].includes(typeof value))
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', 'null'].includes(typeof value))
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 key in schema.options.object) {
314
- const propSchema = schema.options.object[key];
315
- result[key] = propSchema.default !== undefined ? propSchema.default : undefined;
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
- for (const [k, val] of Object.entries(value)) {
322
- const propSchema = this.options.object[k];
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
- result[k] = propSchema(val, `${key}.${k}`);
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/schema",
3
- "version": "1.1.4",
3
+ "version": "1.1.5",
4
4
  "description": "Configuration validation and schema system for Zhin.js",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",