@yuhere/js-jsonrpc2 2.1.13 → 2.1.14

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.
@@ -50,12 +50,12 @@ function convert(desc) {
50
50
  out.minItems = c.min;
51
51
  if (c.max !== undefined)
52
52
  out.maxItems = c.max;
53
- out.items = convert(desc.children.items);
53
+ out.items = convert(desc.element);
54
54
  break;
55
55
  }
56
56
  case 'tuple': {
57
57
  out.type = 'array';
58
- const items = desc.children.items;
58
+ const items = desc.elements;
59
59
  out.items = items.map(convert);
60
60
  out.minItems = items.length;
61
61
  out.maxItems = items.length;
@@ -63,19 +63,19 @@ function convert(desc) {
63
63
  }
64
64
  case 'object': {
65
65
  out.type = 'object';
66
- const strict = Boolean(desc.constraints.strict);
67
- const props = desc.children
68
- .properties;
66
+ const optional = new Set((desc.constraints
67
+ ?.optionalProps) ?? []);
68
+ const allowUnknown = (desc.constraints
69
+ ?.allowUnknownProps) ?? true;
70
+ const props = desc.properties;
69
71
  out.properties = {};
70
72
  for (const [k, v] of Object.entries(props))
71
73
  out.properties[k] = convert(v);
72
- if (strict) {
73
- out.required = Object.keys(props);
74
+ const required = Object.keys(props).filter((k) => !optional.has(k));
75
+ if (required.length > 0)
76
+ out.required = required;
77
+ if (!allowUnknown)
74
78
  out.additionalProperties = false;
75
- }
76
- else {
77
- out.additionalProperties = true;
78
- }
79
79
  break;
80
80
  }
81
81
  case 'record': {
@@ -85,12 +85,11 @@ function convert(desc) {
85
85
  out.minProperties = c.min;
86
86
  if (c.max !== undefined)
87
87
  out.maxProperties = c.max;
88
- out.additionalProperties = convert(desc.children.values);
88
+ out.additionalProperties = convert(desc.value);
89
89
  break;
90
90
  }
91
91
  case 'union': {
92
- const options = desc.children.options;
93
- out.anyOf = options.map(convert);
92
+ out.anyOf = desc.options.map(convert);
94
93
  break;
95
94
  }
96
95
  case 'unknown': {
@@ -101,8 +100,10 @@ function convert(desc) {
101
100
  out.type = 'null';
102
101
  break;
103
102
  }
104
- default:
105
- throw new Error(`Unsupported schema kind for JSON Schema: ${desc.kind}`);
103
+ default: {
104
+ const _exhaustive = desc;
105
+ throw new Error(`Unsupported schema kind for JSON Schema: ${JSON.stringify(_exhaustive)}`);
106
+ }
106
107
  }
107
108
  if (desc.nullable) {
108
109
  if (desc.kind === 'unknown' || desc.kind === 'null') {
@@ -150,7 +151,6 @@ function renderSchema(schema, indent = 0) {
150
151
  if (c)
151
152
  head += ` \`${c}\``;
152
153
  lines.push(head);
153
- const ch = schema.children ?? {};
154
154
  const pushChild = (label, child) => {
155
155
  const sub = renderSchema(child, indent + 1);
156
156
  if (sub.length) {
@@ -158,36 +158,35 @@ function renderSchema(schema, indent = 0) {
158
158
  lines.push(...sub);
159
159
  }
160
160
  };
161
- if (isSchema(ch.inner))
162
- pushChild('inner', ch.inner);
163
- if (Array.isArray(ch.items)) {
164
- ch.items.forEach((it, i) => {
165
- if (isSchema(it))
166
- pushChild(`[${i}]`, it);
167
- });
168
- }
169
- else if (isSchema(ch.items)) {
170
- pushChild('items', ch.items);
171
- }
172
- if (Array.isArray(ch.options)) {
173
- ch.options.forEach((opt, i) => {
174
- if (isSchema(opt))
175
- pushChild(`option[${i}]`, opt);
176
- });
177
- }
178
- if (ch.properties && typeof ch.properties === 'object') {
179
- for (const [k, v] of Object.entries(ch.properties)) {
180
- if (isSchema(v))
161
+ switch (schema.kind) {
162
+ case 'array': {
163
+ pushChild('element', schema.element);
164
+ break;
165
+ }
166
+ case 'record': {
167
+ pushChild('value', schema.value);
168
+ break;
169
+ }
170
+ case 'object': {
171
+ for (const [k, v] of Object.entries(schema.properties)) {
181
172
  pushChild(k, v);
173
+ }
174
+ break;
175
+ }
176
+ case 'union': {
177
+ schema.options.forEach((opt, i) => pushChild(`option[${i}]`, opt));
178
+ break;
182
179
  }
180
+ case 'tuple': {
181
+ schema.elements.forEach((it, i) => pushChild(`[${i}]`, it));
182
+ break;
183
+ }
184
+ default:
185
+ // 叶子类型:无子节点。
186
+ break;
183
187
  }
184
- if (isSchema(ch.values))
185
- pushChild('values', ch.values);
186
188
  return lines;
187
189
  }
188
- function isSchema(v) {
189
- return !!v && typeof v === 'object' && typeof v.kind === 'string';
190
- }
191
190
  /** 渲染返回值槽位(Schema / VoidMarker / StreamMarker)。 */
192
191
  function renderReturnSlot(slot) {
193
192
  if (slot instanceof VoidMarker)
@@ -6,7 +6,7 @@ export declare const s: {
6
6
  boolean: () => import("./primitives.js").BooleanSchema;
7
7
  literal: <const T extends import("./primitives.js").LiteralValue>(value: T) => import("./primitives.js").LiteralSchema<T>;
8
8
  array: <T>(item: import("./primitives.js").Schema<T>) => import("./primitives.js").ArraySchema<T>;
9
- object: <S extends import("./primitives.js").ObjectShape>(shape: S) => import("./primitives.js").ObjectSchema<S, false>;
9
+ object: <S extends import("./primitives.js").ObjectShape>(shape: S) => import("./primitives.js").ObjectSchema<S>;
10
10
  record: <T>(value: import("./primitives.js").Schema<T>) => import("./primitives.js").RecordSchema<T>;
11
11
  union: <const S extends readonly [import("./primitives.js").Schema<unknown>, ...import("./primitives.js").Schema<unknown>[]]>(schemas: S) => import("./primitives.js").UnionSchema<S>;
12
12
  tuple: <const S extends readonly [import("./primitives.js").Schema<unknown>, ...import("./primitives.js").Schema<unknown>[]]>(schemas: S) => import("./primitives.js").TupleSchema<S>;
@@ -9,20 +9,36 @@ export type JSONValue = JSONPrimitive | JSONValue[] | {
9
9
  [key: string]: JSONValue;
10
10
  };
11
11
  export type SchemaKind = string;
12
- export interface SchemaDescription {
12
+ export interface BaseSchemaDescription {
13
13
  kind: SchemaKind;
14
14
  description?: string;
15
- /**
16
- * 该值是否允许为 null。
17
- *
18
- * 唯一真相来源:由 `NullableSchema` 及其子类通过 `.nullable(bool)` 设置,
19
- * `UnknownSchema` / `NullSchema` 不使用该字段(它们本身就接受 null)。
20
- * `kind` 永远表示值的真实形状,不会被 nullability 污染。
21
- */
22
15
  nullable?: boolean;
23
16
  constraints?: Record<string, unknown>;
24
- children?: Record<string, unknown>;
25
17
  }
18
+ export interface LeafSchemaDescription extends BaseSchemaDescription {
19
+ kind: "string" | "number" | "boolean" | "literal" | "enum" | "unknown" | "null";
20
+ }
21
+ export interface ObjectSchemaDescription extends BaseSchemaDescription {
22
+ kind: "object";
23
+ properties: Record<string, SchemaDescription>;
24
+ }
25
+ export interface ArraySchemaDescription extends BaseSchemaDescription {
26
+ kind: "array";
27
+ element: SchemaDescription;
28
+ }
29
+ export interface RecordSchemaDescription extends BaseSchemaDescription {
30
+ kind: "record";
31
+ value: SchemaDescription;
32
+ }
33
+ export interface UnionSchemaDescription extends BaseSchemaDescription {
34
+ kind: "union";
35
+ options: SchemaDescription[];
36
+ }
37
+ export interface TupleSchemaDescription extends BaseSchemaDescription {
38
+ kind: "tuple";
39
+ elements: SchemaDescription[];
40
+ }
41
+ export type SchemaDescription = LeafSchemaDescription | ObjectSchemaDescription | ArraySchemaDescription | RecordSchemaDescription | UnionSchemaDescription | TupleSchemaDescription;
26
42
  export declare class SchemaValidationError extends Error {
27
43
  readonly path: string[];
28
44
  constructor(message: string, path?: string[]);
@@ -36,14 +52,13 @@ export declare class SchemaValidationError extends Error {
36
52
  */
37
53
  export declare abstract class Schema<T> {
38
54
  abstract readonly kind: SchemaKind;
39
- private description?;
40
- constructor(description?: string);
55
+ private description;
41
56
  describe(description: string): this;
42
57
  /**
43
58
  * 创建保留原型和现有字段的新实例,供不可变链式方法使用。
44
59
  */
45
60
  protected cloneWith(updates: Record<string, unknown>): this;
46
- getDescription(): string | undefined;
61
+ getDescription(): string;
47
62
  parse(input: unknown): T;
48
63
  safeParse(input: unknown): {
49
64
  success: true;
@@ -84,7 +99,7 @@ export declare class StringSchema<K extends string = "string"> extends NullableS
84
99
  min(value: number): this;
85
100
  max(value: number): this;
86
101
  protected _parseValue(input: unknown, path: string[]): string;
87
- protected _describe(): SchemaDescription;
102
+ protected _describe(): LeafSchemaDescription;
88
103
  protected validateBound(value: number): void;
89
104
  }
90
105
  export declare class NumberSchema extends NullableSchema<number> {
@@ -95,28 +110,22 @@ export declare class NumberSchema extends NullableSchema<number> {
95
110
  min(value: number): this;
96
111
  max(value: number): this;
97
112
  protected _parseValue(input: unknown, path: string[]): number;
98
- protected _describe(): SchemaDescription;
113
+ protected _describe(): LeafSchemaDescription;
99
114
  protected validateBound(value: number): void;
100
115
  }
101
116
  export declare class BooleanSchema extends NullableSchema<boolean> {
102
117
  readonly kind: "boolean";
103
118
  constructor();
104
119
  protected _parseValue(input: unknown, path: string[]): boolean;
105
- protected _describe(): SchemaDescription;
120
+ protected _describe(): LeafSchemaDescription;
106
121
  }
107
- /**
108
- * 字面量只支持 string / number / boolean。
109
- *
110
- * null 由 `s.null()` 表达;需要「该字面量或 null」时,对字面量调用
111
- * `.nullable()`。`literal(null)` 会抛 TypeError。
112
- */
113
122
  export type LiteralValue = string | number | boolean;
114
123
  export declare class LiteralSchema<const T extends LiteralValue> extends NullableSchema<T> {
115
124
  private readonly expected;
116
125
  readonly kind: "literal";
117
126
  constructor(expected: T);
118
127
  protected _parseValue(input: unknown, path: string[]): T;
119
- protected _describe(): SchemaDescription;
128
+ protected _describe(): LeafSchemaDescription;
120
129
  }
121
130
  export declare class ArraySchema<T> extends NullableSchema<T[]> {
122
131
  private readonly itemSchema;
@@ -127,28 +136,25 @@ export declare class ArraySchema<T> extends NullableSchema<T[]> {
127
136
  min(value: number): this;
128
137
  max(value: number): this;
129
138
  protected _parseValue(input: unknown, path: string[]): T[];
130
- protected _describe(): SchemaDescription;
139
+ protected _describe(): ArraySchemaDescription;
131
140
  protected validateBound(value: number): void;
132
141
  }
133
142
  export type ObjectShape = Record<string, Schema<unknown>>;
134
143
  type SchemaValue<S> = S extends Schema<infer T> ? T : never;
135
- type ShapeOutput<S extends ObjectShape> = {
136
- [K in keyof S]: SchemaValue<S[K]>;
137
- };
138
- type OptionalShapeOutput<S extends ObjectShape> = {
144
+ export type ObjectOutput<S extends ObjectShape> = {
139
145
  [K in keyof S]?: SchemaValue<S[K]>;
140
146
  };
141
- export declare class ObjectSchema<S extends ObjectShape, Strict extends boolean = false> extends NullableSchema<Strict extends true ? ShapeOutput<S> : OptionalShapeOutput<S>> {
147
+ export declare class ObjectSchema<S extends ObjectShape> extends NullableSchema<ObjectOutput<S>> {
142
148
  private readonly shape;
143
149
  readonly kind: "object";
144
- private isStrict;
145
- constructor(shape: S, strict?: Strict, description?: string);
146
- /**
147
- * strict() 要求所有声明属性存在,并拒绝未声明属性。
148
- */
149
- strict(): ObjectSchema<S, true>;
150
- protected _parseValue(input: unknown, path: string[]): Strict extends true ? ShapeOutput<S> : OptionalShapeOutput<S>;
151
- protected _describe(): SchemaDescription;
150
+ private optionalProps;
151
+ private allowUnknownProps;
152
+ constructor(shape: S);
153
+ optionalProperties(keys: string[]): this;
154
+ allowUnknownProperties(value?: boolean): this;
155
+ strict(value?: boolean): this;
156
+ protected _parseValue(input: unknown, path: string[]): ObjectOutput<S>;
157
+ protected _describe(): ObjectSchemaDescription;
152
158
  }
153
159
  export declare class RecordSchema<T> extends NullableSchema<Record<string, T>> {
154
160
  private readonly valueSchema;
@@ -159,68 +165,42 @@ export declare class RecordSchema<T> extends NullableSchema<Record<string, T>> {
159
165
  min(value: number): this;
160
166
  max(value: number): this;
161
167
  protected _parseValue(input: unknown, path: string[]): Record<string, T>;
162
- protected _describe(): SchemaDescription;
168
+ protected _describe(): RecordSchemaDescription;
163
169
  protected validateBound(value: number): void;
164
170
  }
165
- /**
166
- * 联合。
167
- *
168
- * 传入的 member schemas 会被 clone 并 `nullable(false)`——因为「某个
169
- * 分支允许 null」这件事在 union 层面没有意义:null 是否允许应通过
170
- * `union(...).nullable()` 统一表达。
171
- */
172
171
  export declare class UnionSchema<const S extends readonly [Schema<unknown>, ...Schema<unknown>[]]> extends NullableSchema<SchemaValue<S[number]>> {
173
172
  readonly kind: "union";
174
173
  private readonly options;
175
174
  constructor(schemas: S);
176
175
  protected _parseValue(input: unknown, path: string[]): SchemaValue<S[number]>;
177
- protected _describe(): SchemaDescription;
176
+ protected _describe(): UnionSchemaDescription;
178
177
  }
179
178
  export declare class TupleSchema<const S extends readonly [Schema<unknown>, ...Schema<unknown>[]]> extends NullableSchema<SchemaValue<S[number]>[]> {
180
179
  private readonly schemas;
181
180
  readonly kind: "tuple";
182
181
  constructor(schemas: S);
183
182
  protected _parseValue(input: unknown, path: string[]): SchemaValue<S[number]>[];
184
- protected _describe(): SchemaDescription;
183
+ protected _describe(): TupleSchemaDescription;
185
184
  }
186
- /**
187
- * 字符串枚举。
188
- *
189
- * 继承 `NullableSchema`,因此可以 `s.enum([...]).nullable()`;
190
- * 它不包含嵌套 schema,所以不需要像 union 那样处理成员 nullability。
191
- */
192
185
  export declare class EnumSchema<const T extends readonly [string, ...string[]]> extends NullableSchema<T[number]> {
193
186
  private readonly values;
194
187
  readonly kind: "enum";
195
188
  private readonly allowedValues;
196
189
  constructor(values: T);
197
190
  protected _parseValue(input: unknown, path: string[]): T[number];
198
- protected _describe(): SchemaDescription;
191
+ protected _describe(): LeafSchemaDescription;
199
192
  }
200
- /**
201
- * 校验任意 JSON 值。
202
- *
203
- * 不允许 undefined、非有限数字、循环引用等非 JSON 数据。
204
- * null 本身就在接受范围内,因此不继承 `NullableSchema`,也不提供
205
- * `.nullable()`——那是冗余的。
206
- */
207
193
  export declare class UnknownSchema extends Schema<JSONValue> {
208
194
  readonly kind: "unknown";
209
195
  constructor();
210
196
  protected _parse(input: unknown, path: string[]): JSONValue;
211
- protected _describe(): SchemaDescription;
197
+ protected _describe(): LeafSchemaDescription;
212
198
  }
213
- /**
214
- * 精确的 null 值。
215
- *
216
- * 与 `UnknownSchema` 一样天然表达 null,不需要 `.nullable()`。
217
- * 想表达「某类型或 null」用 `.nullable()`;想表达「就是 null」用 `s.null()`。
218
- */
219
199
  export declare class NullSchema extends Schema<null> {
220
200
  readonly kind: "null";
221
201
  constructor();
222
202
  protected _parse(input: unknown, path: string[]): null;
223
- protected _describe(): SchemaDescription;
203
+ protected _describe(): LeafSchemaDescription;
224
204
  }
225
205
  export type Infer<T extends Schema<unknown>> = T extends Schema<infer U> ? U : never;
226
206
  export declare const primitives: {
@@ -229,7 +209,7 @@ export declare const primitives: {
229
209
  boolean: () => BooleanSchema;
230
210
  literal: <const T extends LiteralValue>(value: T) => LiteralSchema<T>;
231
211
  array: <T>(item: Schema<T>) => ArraySchema<T>;
232
- object: <S extends ObjectShape>(shape: S) => ObjectSchema<S, false>;
212
+ object: <S extends ObjectShape>(shape: S) => ObjectSchema<S>;
233
213
  record: <T>(value: Schema<T>) => RecordSchema<T>;
234
214
  union: <const S extends readonly [Schema<unknown>, ...Schema<unknown>[]]>(schemas: S) => UnionSchema<S>;
235
215
  tuple: <const S extends readonly [Schema<unknown>, ...Schema<unknown>[]]>(schemas: S) => TupleSchema<S>;
@@ -14,10 +14,7 @@ export class SchemaValidationError extends Error {
14
14
  * 不需要 `.nullable()`。
15
15
  */
16
16
  export class Schema {
17
- description;
18
- constructor(description) {
19
- this.description = description;
20
- }
17
+ description = "";
21
18
  describe(description) {
22
19
  return this.cloneWith({ description });
23
20
  }
@@ -118,12 +115,13 @@ export class StringSchema extends NullableSchema {
118
115
  return input;
119
116
  }
120
117
  _describe() {
118
+ const constraints = buildConstraints({
119
+ min: this.minimum,
120
+ max: this.maximum,
121
+ });
121
122
  return {
122
123
  kind: this.kind,
123
- constraints: {
124
- ...(this.minimum !== undefined ? { min: this.minimum } : {}),
125
- ...(this.maximum !== undefined ? { max: this.maximum } : {}),
126
- },
124
+ ...(constraints ? { constraints } : {}),
127
125
  };
128
126
  }
129
127
  validateBound(value) {
@@ -160,12 +158,13 @@ export class NumberSchema extends NullableSchema {
160
158
  return input;
161
159
  }
162
160
  _describe() {
161
+ const constraints = buildConstraints({
162
+ min: this.minimum,
163
+ max: this.maximum,
164
+ });
163
165
  return {
164
166
  kind: this.kind,
165
- constraints: {
166
- ...(this.minimum !== undefined ? { min: this.minimum } : {}),
167
- ...(this.maximum !== undefined ? { max: this.maximum } : {}),
168
- },
167
+ ...(constraints ? { constraints } : {}),
169
168
  };
170
169
  }
171
170
  validateBound(value) {
@@ -259,13 +258,14 @@ export class ArraySchema extends NullableSchema {
259
258
  });
260
259
  }
261
260
  _describe() {
261
+ const constraints = buildConstraints({
262
+ min: this.minimum,
263
+ max: this.maximum,
264
+ });
262
265
  return {
263
266
  kind: this.kind,
264
- constraints: {
265
- ...(this.minimum !== undefined ? { min: this.minimum } : {}),
266
- ...(this.maximum !== undefined ? { max: this.maximum } : {}),
267
- },
268
- children: { items: this.itemSchema.toJSON() },
267
+ ...(constraints ? { constraints } : {}),
268
+ element: this.itemSchema.toJSON(),
269
269
  };
270
270
  }
271
271
  validateBound(value) {
@@ -277,17 +277,29 @@ export class ArraySchema extends NullableSchema {
277
277
  export class ObjectSchema extends NullableSchema {
278
278
  shape;
279
279
  kind = "object";
280
- isStrict;
281
- constructor(shape, strict = false, description) {
282
- super(description);
280
+ optionalProps;
281
+ allowUnknownProps = true;
282
+ constructor(shape) {
283
+ super();
283
284
  this.shape = shape;
284
- this.isStrict = strict;
285
+ this.optionalProps = Object.keys(shape);
285
286
  }
286
- /**
287
- * strict() 要求所有声明属性存在,并拒绝未声明属性。
288
- */
289
- strict() {
290
- return new ObjectSchema(this.shape, true, this.getDescription());
287
+ optionalProperties(keys) {
288
+ for (const key of keys) {
289
+ if (!Object.prototype.hasOwnProperty.call(this.shape, key)) {
290
+ throw new TypeError(`optionalProperties: unknown property "${key}"`);
291
+ }
292
+ }
293
+ return this.cloneWith({ optionalProps: [...new Set(keys)] });
294
+ }
295
+ allowUnknownProperties(value = true) {
296
+ return this.cloneWith({ allowUnknownProps: value });
297
+ }
298
+ strict(value = true) {
299
+ if (value) {
300
+ return this.optionalProperties([]).allowUnknownProperties(false);
301
+ }
302
+ return this.optionalProperties(Object.keys(this.shape)).allowUnknownProperties(true);
291
303
  }
292
304
  _parseValue(input, path) {
293
305
  if (input === null ||
@@ -297,16 +309,17 @@ export class ObjectSchema extends NullableSchema {
297
309
  }
298
310
  const source = input;
299
311
  const output = {};
300
- if (this.isStrict) {
312
+ const optional = new Set(this.optionalProps);
313
+ if (!this.allowUnknownProps) {
301
314
  for (const key of Object.keys(source)) {
302
- if (!(key in this.shape)) {
315
+ if (!Object.prototype.hasOwnProperty.call(this.shape, key)) {
303
316
  this.fail(`Unknown property "${key}"`, [...path, key]);
304
317
  }
305
318
  }
306
319
  }
307
320
  for (const [key, schema] of Object.entries(this.shape)) {
308
321
  if (!Object.prototype.hasOwnProperty.call(source, key)) {
309
- if (this.isStrict) {
322
+ if (!optional.has(key)) {
310
323
  this.fail(`Missing required property "${key}"`, [...path, key]);
311
324
  }
312
325
  continue;
@@ -324,10 +337,9 @@ export class ObjectSchema extends NullableSchema {
324
337
  throw error;
325
338
  }
326
339
  }
327
- // 非 strict 模式允许额外属性,并保留这些属性。
328
- if (!this.isStrict) {
340
+ if (this.allowUnknownProps) {
329
341
  for (const [key, value] of Object.entries(source)) {
330
- if (!(key in this.shape)) {
342
+ if (!Object.prototype.hasOwnProperty.call(this.shape, key)) {
331
343
  assertJSONValue(value, [...path, key]);
332
344
  output[key] = value;
333
345
  }
@@ -338,13 +350,14 @@ export class ObjectSchema extends NullableSchema {
338
350
  _describe() {
339
351
  return {
340
352
  kind: this.kind,
341
- constraints: { strict: this.isStrict },
342
- children: {
343
- properties: Object.fromEntries(Object.entries(this.shape).map(([key, schema]) => [
344
- key,
345
- schema.toJSON(),
346
- ])),
353
+ constraints: {
354
+ optionalProps: [...this.optionalProps],
355
+ allowUnknownProps: this.allowUnknownProps,
347
356
  },
357
+ properties: Object.fromEntries(Object.entries(this.shape).map(([key, schema]) => [
358
+ key,
359
+ schema.toJSON(),
360
+ ])),
348
361
  };
349
362
  }
350
363
  }
@@ -396,13 +409,14 @@ export class RecordSchema extends NullableSchema {
396
409
  return output;
397
410
  }
398
411
  _describe() {
412
+ const constraints = buildConstraints({
413
+ min: this.minimum,
414
+ max: this.maximum,
415
+ });
399
416
  return {
400
417
  kind: this.kind,
401
- constraints: {
402
- ...(this.minimum !== undefined ? { min: this.minimum } : {}),
403
- ...(this.maximum !== undefined ? { max: this.maximum } : {}),
404
- },
405
- children: { values: this.valueSchema.toJSON() },
418
+ ...(constraints ? { constraints } : {}),
419
+ value: this.valueSchema.toJSON(),
406
420
  };
407
421
  }
408
422
  validateBound(value) {
@@ -411,13 +425,6 @@ export class RecordSchema extends NullableSchema {
411
425
  }
412
426
  }
413
427
  }
414
- /**
415
- * 联合。
416
- *
417
- * 传入的 member schemas 会被 clone 并 `nullable(false)`——因为「某个
418
- * 分支允许 null」这件事在 union 层面没有意义:null 是否允许应通过
419
- * `union(...).nullable()` 统一表达。
420
- */
421
428
  export class UnionSchema extends NullableSchema {
422
429
  kind = "union";
423
430
  options;
@@ -452,9 +459,7 @@ export class UnionSchema extends NullableSchema {
452
459
  _describe() {
453
460
  return {
454
461
  kind: this.kind,
455
- children: {
456
- options: this.options.map((schema) => schema.toJSON()),
457
- },
462
+ options: this.options.map((schema) => schema.toJSON()),
458
463
  };
459
464
  }
460
465
  }
@@ -483,7 +488,10 @@ export class TupleSchema extends NullableSchema {
483
488
  }
484
489
  catch (error) {
485
490
  if (error instanceof SchemaValidationError) {
486
- return this.fail(error.message, [...path, "" + i]);
491
+ throw new SchemaValidationError(error.message, [
492
+ String(i),
493
+ ...error.path,
494
+ ]);
487
495
  }
488
496
  throw error;
489
497
  }
@@ -493,18 +501,10 @@ export class TupleSchema extends NullableSchema {
493
501
  _describe() {
494
502
  return {
495
503
  kind: this.kind,
496
- children: {
497
- items: this.schemas.map((schema) => schema.toJSON()),
498
- },
504
+ elements: this.schemas.map((schema) => schema.toJSON()),
499
505
  };
500
506
  }
501
507
  }
502
- /**
503
- * 字符串枚举。
504
- *
505
- * 继承 `NullableSchema`,因此可以 `s.enum([...]).nullable()`;
506
- * 它不包含嵌套 schema,所以不需要像 union 那样处理成员 nullability。
507
- */
508
508
  export class EnumSchema extends NullableSchema {
509
509
  values;
510
510
  kind = "enum";
@@ -527,13 +527,6 @@ export class EnumSchema extends NullableSchema {
527
527
  };
528
528
  }
529
529
  }
530
- /**
531
- * 校验任意 JSON 值。
532
- *
533
- * 不允许 undefined、非有限数字、循环引用等非 JSON 数据。
534
- * null 本身就在接受范围内,因此不继承 `NullableSchema`,也不提供
535
- * `.nullable()`——那是冗余的。
536
- */
537
530
  export class UnknownSchema extends Schema {
538
531
  kind = "unknown";
539
532
  constructor() {
@@ -547,12 +540,6 @@ export class UnknownSchema extends Schema {
547
540
  return { kind: this.kind };
548
541
  }
549
542
  }
550
- /**
551
- * 精确的 null 值。
552
- *
553
- * 与 `UnknownSchema` 一样天然表达 null,不需要 `.nullable()`。
554
- * 想表达「某类型或 null」用 `.nullable()`;想表达「就是 null」用 `s.null()`。
555
- */
556
543
  export class NullSchema extends Schema {
557
544
  kind = "null";
558
545
  constructor() {
@@ -568,6 +555,13 @@ export class NullSchema extends Schema {
568
555
  return { kind: this.kind };
569
556
  }
570
557
  }
558
+ function buildConstraints(values) {
559
+ const entries = Object.entries(values).filter(([, value]) => value !== undefined);
560
+ if (entries.length === 0) {
561
+ return undefined;
562
+ }
563
+ return Object.fromEntries(entries);
564
+ }
571
565
  function assertJSONValue(value, path, ancestors = new Set()) {
572
566
  if (value === null ||
573
567
  typeof value === "string" ||
@@ -5,4 +5,4 @@ export declare const RPCRequestSchema: import("../json/index.js").ObjectSchema<{
5
5
  method: import("../json/index.js").StringSchema<"string">;
6
6
  params: import("../json/index.js").ArraySchema<import("../json/index.js").JSONValue>;
7
7
  id: import("../json/index.js").UnionSchema<readonly [import("../json/index.js").StringSchema<"string">, import("../json/index.js").NumberSchema]>;
8
- }, true>;
8
+ }>;