@yuhere/js-jsonrpc2 2.1.12 → 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.
Files changed (181) hide show
  1. package/dist/cli/cli.d.ts +0 -1
  2. package/dist/cli/cli.js +0 -1
  3. package/dist/cli/demo-methods.d.ts +0 -1
  4. package/dist/cli/demo-methods.js +0 -1
  5. package/dist/cli/express.d.ts +0 -1
  6. package/dist/cli/express.js +0 -1
  7. package/dist/cli/stdio.d.ts +0 -1
  8. package/dist/cli/stdio.js +0 -1
  9. package/dist/core/Repository.d.ts +0 -1
  10. package/dist/core/Repository.js +0 -1
  11. package/dist/core/convert.d.ts +0 -1
  12. package/dist/core/convert.js +0 -1
  13. package/dist/core/descriptor.d.ts +0 -1
  14. package/dist/core/descriptor.js +0 -1
  15. package/dist/core/index.d.ts +0 -1
  16. package/dist/core/index.js +0 -1
  17. package/dist/core/llm-tools.d.ts +0 -1
  18. package/dist/core/llm-tools.js +41 -43
  19. package/dist/core/permission.d.ts +0 -1
  20. package/dist/core/permission.js +0 -1
  21. package/dist/core/spec-check.d.ts +0 -1
  22. package/dist/core/spec-check.js +0 -1
  23. package/dist/core/system-methods.d.ts +0 -1
  24. package/dist/core/system-methods.js +0 -1
  25. package/dist/errors/RPCError.d.ts +0 -1
  26. package/dist/errors/RPCError.js +0 -1
  27. package/dist/errors/codes.d.ts +0 -1
  28. package/dist/errors/codes.js +0 -1
  29. package/dist/errors/index.d.ts +0 -1
  30. package/dist/errors/index.js +0 -1
  31. package/dist/index.d.ts +0 -1
  32. package/dist/index.js +0 -1
  33. package/dist/metrics/memory.d.ts +0 -1
  34. package/dist/metrics/memory.js +0 -1
  35. package/dist/metrics/prom.d.ts +0 -1
  36. package/dist/metrics/prom.js +0 -1
  37. package/dist/schema/json/index.d.ts +1 -2
  38. package/dist/schema/json/index.js +0 -1
  39. package/dist/schema/json/marker.d.ts +0 -1
  40. package/dist/schema/json/marker.js +0 -1
  41. package/dist/schema/json/primitives.d.ts +49 -70
  42. package/dist/schema/json/primitives.js +70 -77
  43. package/dist/schema/z/protocol.d.ts +1 -2
  44. package/dist/schema/z/protocol.js +0 -1
  45. package/dist/schema/z/register.d.ts +0 -1
  46. package/dist/schema/z/register.js +0 -1
  47. package/dist/stream/stringify-stream.d.ts +0 -1
  48. package/dist/stream/stringify-stream.js +94 -70
  49. package/dist/transport/express/body.d.ts +0 -1
  50. package/dist/transport/express/body.js +0 -1
  51. package/dist/transport/express/index.d.ts +0 -1
  52. package/dist/transport/express/index.js +0 -1
  53. package/dist/transport/express/middleware.d.ts +0 -1
  54. package/dist/transport/express/middleware.js +0 -1
  55. package/dist/transport/express/respond.d.ts +0 -1
  56. package/dist/transport/express/respond.js +0 -1
  57. package/dist/transport/stdio/index.d.ts +0 -1
  58. package/dist/transport/stdio/index.js +0 -1
  59. package/dist/transport/stdio/middleware.d.ts +0 -1
  60. package/dist/transport/stdio/middleware.js +0 -1
  61. package/dist/transport/ws/index.d.ts +0 -1
  62. package/dist/transport/ws/index.js +0 -1
  63. package/dist/transport/ws/middleware.d.ts +0 -1
  64. package/dist/transport/ws/middleware.js +0 -1
  65. package/dist/transport/ws/standalone.d.ts +0 -1
  66. package/dist/transport/ws/standalone.js +0 -1
  67. package/dist/types.d.ts +0 -1
  68. package/dist/types.js +0 -1
  69. package/dist/webclient/webui/src/client/httpTransport.d.ts +8 -0
  70. package/dist/webclient/webui/src/client/httpTransport.js +114 -0
  71. package/dist/webclient/webui/src/client/index.d.ts +4 -0
  72. package/dist/webclient/webui/src/client/index.js +2 -0
  73. package/dist/webclient/webui/src/client/rpc.d.ts +24 -0
  74. package/dist/webclient/webui/src/client/rpc.js +32 -0
  75. package/dist/webclient/webui/src/client/types.d.ts +14 -0
  76. package/dist/webclient/webui/src/client/types.js +1 -0
  77. package/dist/webclient/webui/src/client/wsTransport.d.ts +8 -0
  78. package/{webui/src/api/wsTransport.ts → dist/webclient/webui/src/client/wsTransport.js} +263 -305
  79. package/htdoc/assets/favicon-CXdFuLlv.png +0 -0
  80. package/{webui/src/styles/geek.css → htdoc/assets/index-Rq1yIwo2.css} +58 -0
  81. package/htdoc/assets/{index-Cr0Jnrgb.js → index-mYqtDOwe.js} +1344 -398
  82. package/htdoc/assets/index-mYqtDOwe.js.map +1 -0
  83. package/htdoc/index.html +4 -2
  84. package/package.json +10 -7
  85. package/dist/cli/cli.d.ts.map +0 -1
  86. package/dist/cli/cli.js.map +0 -1
  87. package/dist/cli/demo-methods.d.ts.map +0 -1
  88. package/dist/cli/demo-methods.js.map +0 -1
  89. package/dist/cli/express.d.ts.map +0 -1
  90. package/dist/cli/express.js.map +0 -1
  91. package/dist/cli/stdio.d.ts.map +0 -1
  92. package/dist/cli/stdio.js.map +0 -1
  93. package/dist/core/Repository.d.ts.map +0 -1
  94. package/dist/core/Repository.js.map +0 -1
  95. package/dist/core/convert.d.ts.map +0 -1
  96. package/dist/core/convert.js.map +0 -1
  97. package/dist/core/descriptor.d.ts.map +0 -1
  98. package/dist/core/descriptor.js.map +0 -1
  99. package/dist/core/index.d.ts.map +0 -1
  100. package/dist/core/index.js.map +0 -1
  101. package/dist/core/llm-tools.d.ts.map +0 -1
  102. package/dist/core/llm-tools.js.map +0 -1
  103. package/dist/core/permission.d.ts.map +0 -1
  104. package/dist/core/permission.js.map +0 -1
  105. package/dist/core/spec-check.d.ts.map +0 -1
  106. package/dist/core/spec-check.js.map +0 -1
  107. package/dist/core/system-methods.d.ts.map +0 -1
  108. package/dist/core/system-methods.js.map +0 -1
  109. package/dist/errors/RPCError.d.ts.map +0 -1
  110. package/dist/errors/RPCError.js.map +0 -1
  111. package/dist/errors/codes.d.ts.map +0 -1
  112. package/dist/errors/codes.js.map +0 -1
  113. package/dist/errors/index.d.ts.map +0 -1
  114. package/dist/errors/index.js.map +0 -1
  115. package/dist/index.d.ts.map +0 -1
  116. package/dist/index.js.map +0 -1
  117. package/dist/metrics/memory.d.ts.map +0 -1
  118. package/dist/metrics/memory.js.map +0 -1
  119. package/dist/metrics/prom.d.ts.map +0 -1
  120. package/dist/metrics/prom.js.map +0 -1
  121. package/dist/schema/json/index.d.ts.map +0 -1
  122. package/dist/schema/json/index.js.map +0 -1
  123. package/dist/schema/json/marker.d.ts.map +0 -1
  124. package/dist/schema/json/marker.js.map +0 -1
  125. package/dist/schema/json/primitives.d.ts.map +0 -1
  126. package/dist/schema/json/primitives.js.map +0 -1
  127. package/dist/schema/z/protocol.d.ts.map +0 -1
  128. package/dist/schema/z/protocol.js.map +0 -1
  129. package/dist/schema/z/register.d.ts.map +0 -1
  130. package/dist/schema/z/register.js.map +0 -1
  131. package/dist/stream/stringify-stream.d.ts.map +0 -1
  132. package/dist/stream/stringify-stream.js.map +0 -1
  133. package/dist/transport/express/body.d.ts.map +0 -1
  134. package/dist/transport/express/body.js.map +0 -1
  135. package/dist/transport/express/index.d.ts.map +0 -1
  136. package/dist/transport/express/index.js.map +0 -1
  137. package/dist/transport/express/middleware.d.ts.map +0 -1
  138. package/dist/transport/express/middleware.js.map +0 -1
  139. package/dist/transport/express/respond.d.ts.map +0 -1
  140. package/dist/transport/express/respond.js.map +0 -1
  141. package/dist/transport/stdio/index.d.ts.map +0 -1
  142. package/dist/transport/stdio/index.js.map +0 -1
  143. package/dist/transport/stdio/middleware.d.ts.map +0 -1
  144. package/dist/transport/stdio/middleware.js.map +0 -1
  145. package/dist/transport/ws/index.d.ts.map +0 -1
  146. package/dist/transport/ws/index.js.map +0 -1
  147. package/dist/transport/ws/middleware.d.ts.map +0 -1
  148. package/dist/transport/ws/middleware.js.map +0 -1
  149. package/dist/transport/ws/standalone.d.ts.map +0 -1
  150. package/dist/transport/ws/standalone.js.map +0 -1
  151. package/dist/types.d.ts.map +0 -1
  152. package/dist/types.js.map +0 -1
  153. package/htdoc/assets/index-Ck-39Igh.css +0 -963
  154. package/htdoc/assets/index-Cr0Jnrgb.js.map +0 -1
  155. package/webui/index.html +0 -12
  156. package/webui/src/App.tsx +0 -164
  157. package/webui/src/api/docGen.ts +0 -188
  158. package/webui/src/api/glob.ts +0 -90
  159. package/webui/src/api/httpTransport.ts +0 -148
  160. package/webui/src/api/metrics.ts +0 -135
  161. package/webui/src/api/paramForm.ts +0 -80
  162. package/webui/src/api/rpc.ts +0 -57
  163. package/webui/src/api/schema.ts +0 -12
  164. package/webui/src/api/types.ts +0 -16
  165. package/webui/src/components/MethodDetail.tsx +0 -43
  166. package/webui/src/components/MethodTree.tsx +0 -118
  167. package/webui/src/components/MetricsPanel.md +0 -126
  168. package/webui/src/components/MetricsPanel.tsx +0 -290
  169. package/webui/src/components/SchemaForm.tsx +0 -697
  170. package/webui/src/components/SchemaView.tsx +0 -151
  171. package/webui/src/components/TestPanel.tsx +0 -322
  172. package/webui/src/components/Toolbar.tsx +0 -82
  173. package/webui/src/hooks/useMethodDetail.ts +0 -61
  174. package/webui/src/hooks/useMethods.ts +0 -27
  175. package/webui/src/hooks/useMetrics.ts +0 -91
  176. package/webui/src/main.tsx +0 -13
  177. package/webui/src/theme/ThemeProvider.tsx +0 -79
  178. package/webui/src/vite-env.d.ts +0 -1
  179. package/webui/tsconfig.json +0 -34
  180. package/webui/tsconfig.node.json +0 -13
  181. package/webui/vite.config.ts +0 -15
@@ -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" ||
@@ -623,4 +617,3 @@ export const primitives = {
623
617
  unknown: () => new UnknownSchema(),
624
618
  null: () => new NullSchema(),
625
619
  };
626
- //# sourceMappingURL=primitives.js.map
@@ -5,5 +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>;
9
- //# sourceMappingURL=protocol.d.ts.map
8
+ }>;
@@ -6,4 +6,3 @@ export const RPCRequestSchema = s.object({
6
6
  params: s.array(s.unknown()).nullable(),
7
7
  id: s.union([s.string().min(1), s.number()]),
8
8
  }).strict();
9
- //# sourceMappingURL=protocol.js.map
@@ -6,4 +6,3 @@ export declare const registerSchema: z.ZodTuple<[z.ZodObject<{
6
6
  grantTo: z.ZodOptional<z.ZodArray<z.ZodString>>;
7
7
  signature: z.ZodTuple<[z.ZodUnion<readonly [z.ZodInstanceOf<Schema<unknown>>, z.ZodInstanceOf<VoidMarker>, z.ZodInstanceOf<StreamMarker<unknown>>]>], z.ZodUnion<readonly [z.ZodInstanceOf<Schema<unknown>>, z.ZodInstanceOf<InjectableMarker<string>>]>>;
8
8
  }, z.core.$strict>, z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>], null>;
9
- //# sourceMappingURL=register.d.ts.map
@@ -18,4 +18,3 @@ export const registerSchema = z.tuple([
18
18
  descriptorSchema,
19
19
  z.function(),
20
20
  ]);
21
- //# sourceMappingURL=register.js.map
@@ -12,4 +12,3 @@ export interface StringifyStreamOptions {
12
12
  }
13
13
  export declare function stringifyStream(input: unknown, options?: StringifyStreamOptions): AsyncGenerator<string, void, unknown>;
14
14
  export declare function stringify(input: unknown, options?: StringifyStreamOptions): Promise<string>;
15
- //# sourceMappingURL=stringify-stream.d.ts.map
@@ -6,7 +6,9 @@ const MAX_GAP_LENGTH = 10;
6
6
  const DEFAULT_BUFFER_SIZE = 16 * 1024;
7
7
  export async function* stringifyStream(input, options = {}) {
8
8
  const { bufferSize: rawBufferSize = DEFAULT_BUFFER_SIZE, space, replacer, } = options;
9
- const bufferSize = Math.max(1, rawBufferSize | 0);
9
+ const bufferSize = Number.isFinite(rawBufferSize)
10
+ ? Math.max(1, Math.floor(rawBufferSize))
11
+ : DEFAULT_BUFFER_SIZE;
10
12
  const seen = new WeakSet();
11
13
  let gap = '';
12
14
  if (typeof space === 'number') {
@@ -31,8 +33,19 @@ export async function* stringifyStream(input, options = {}) {
31
33
  let buffer = '';
32
34
  function* flush(force = false) {
33
35
  while (buffer.length >= bufferSize || (force && buffer.length > 0)) {
34
- const chunk = buffer.slice(0, bufferSize);
35
- buffer = buffer.slice(bufferSize);
36
+ let end = Math.min(bufferSize, buffer.length);
37
+ // 不要在 UTF-16 surrogate pair 中间切分
38
+ if (end < buffer.length) {
39
+ const prev = buffer.charCodeAt(end - 1);
40
+ const next = buffer.charCodeAt(end);
41
+ const isHighSurrogate = prev >= 0xD800 && prev <= 0xDBFF;
42
+ const isLowSurrogate = next >= 0xDC00 && next <= 0xDFFF;
43
+ if (isHighSurrogate && isLowSurrogate) {
44
+ end++;
45
+ }
46
+ }
47
+ const chunk = buffer.slice(0, end);
48
+ buffer = buffer.slice(end);
36
49
  yield chunk;
37
50
  }
38
51
  }
@@ -69,7 +82,7 @@ export async function* stringifyStream(input, options = {}) {
69
82
  function isTypedArray(value) {
70
83
  return ArrayBuffer.isView(value) && !(value instanceof DataView);
71
84
  }
72
- function prepareValue(value, key) {
85
+ function prepareValue(value, key, holder) {
73
86
  // 1. toJSON(跳过 Buffer)
74
87
  if (value !== null &&
75
88
  typeof value === 'object' &&
@@ -79,37 +92,30 @@ export async function* stringifyStream(input, options = {}) {
79
92
  }
80
93
  // 2. replacer
81
94
  if (replacerFn) {
82
- value = replacerFn.call(key === '' ? undefined : null, key, value);
95
+ value = replacerFn.call(holder, key, value);
83
96
  }
84
97
  return value;
85
98
  }
86
- async function* serialize(value, key, depth) {
87
- // ========== 只在这里做一次 prepare ==========
88
- value = prepareValue(value, key);
89
- // undefined / function / symbol → 由调用方决定(对象省略,数组写 null)
90
- if (value === undefined ||
91
- typeof value === 'function' ||
92
- typeof value === 'symbol') {
93
- return;
94
- }
99
+ async function* serialize(value, key, depth, holder) {
100
+ // 只在这里做一次 prepare
101
+ value = prepareValue(value, key, holder);
95
102
  assertNoBigInt(value);
96
- // Promise(replacer 或 toJSON 返回的 Promise 在这里统一处理)
97
103
  if (value instanceof Promise) {
98
104
  value = await Promise.resolve(value);
99
- // 注意:await 之后要重新走完整流程(包括可能的再次 toJSON/replacer?)
100
- // 为了与「只 prepare 一次」一致,这里选择不再 prepare,直接递归时跳过 prepare
101
- // 最简单且安全的做法:再调一次 serialize(此时 value 已是 resolved 后的值)
102
- // 但为了避免对 resolved 后的 number 再次触发 replacer,我们改成内部递归时传一个 flag
103
105
  yield* serializePrepared(value, key, depth);
104
106
  return;
105
107
  }
106
108
  yield* serializePrepared(value, key, depth);
107
109
  }
108
- /** 已经完成 prepare 的值,直接序列化(不再调用 toJSON/replacer) */
110
+ /**
111
+ * 已经完成 prepare 的值,直接序列化
112
+ * 不再调用 toJSON / replacer。
113
+ */
109
114
  async function* serializePrepared(value, key, depth) {
110
115
  if (value === undefined ||
111
116
  typeof value === 'function' ||
112
117
  typeof value === 'symbol') {
118
+ write('null');
113
119
  return;
114
120
  }
115
121
  assertNoBigInt(value);
@@ -152,9 +158,16 @@ export async function* stringifyStream(input, options = {}) {
152
158
  if (!first)
153
159
  write(',');
154
160
  first = false;
155
- if (gap)
161
+ if (gap) {
156
162
  write('\n' + gap.repeat(depth + 1));
157
- let elem = prepareValue(value[i], String(i));
163
+ }
164
+ let rawValue = value[i];
165
+ // 1. 先等待原始值
166
+ if (rawValue instanceof Promise) {
167
+ rawValue = await Promise.resolve(rawValue);
168
+ }
169
+ // 2. 执行 toJSON 和 replacer
170
+ let elem = prepareValue(rawValue, String(i), value);
158
171
  if (elem instanceof Promise) {
159
172
  elem = await Promise.resolve(elem);
160
173
  }
@@ -185,8 +198,9 @@ export async function* stringifyStream(input, options = {}) {
185
198
  if (!first)
186
199
  write(',');
187
200
  first = false;
188
- if (gap)
201
+ if (gap) {
189
202
  write('\n' + gap.repeat(depth + 1));
203
+ }
190
204
  writeJSONString(String(i));
191
205
  write(gap ? ': ' : ':');
192
206
  write(JSON.stringify(arr[i]));
@@ -199,7 +213,7 @@ export async function* stringifyStream(input, options = {}) {
199
213
  uncheckCycle(value);
200
214
  return;
201
215
  }
202
- // 可迭代
216
+ // 可迭代对象
203
217
  const hasAsyncIterator = value != null &&
204
218
  typeof value[Symbol.asyncIterator] === 'function';
205
219
  const hasIterator = value != null &&
@@ -212,10 +226,9 @@ export async function* stringifyStream(input, options = {}) {
212
226
  !(value instanceof WeakMap) &&
213
227
  !(value instanceof WeakSet);
214
228
  if (shouldTreatAsIterable) {
215
- write('[');
216
- let first = true;
217
- let idx = 0;
229
+ checkCycle(value);
218
230
  let iterator;
231
+ let completed = false;
219
232
  if (hasAsyncIterator) {
220
233
  iterator = value[Symbol.asyncIterator]();
221
234
  }
@@ -225,40 +238,52 @@ export async function* stringifyStream(input, options = {}) {
225
238
  else {
226
239
  iterator = value;
227
240
  }
228
- while (true) {
229
- const step = await Promise.resolve(iterator.next());
230
- if (step.done)
231
- break;
232
- if (!first)
233
- write(',');
234
- first = false;
235
- if (gap)
236
- write('\n' + gap.repeat(depth + 1));
237
- // const before = buffer.length;
238
- // yield* serialize(step.value, String(idx), depth + 1);
239
- // if (buffer.length === before) {
240
- // write('null');
241
- // }
242
- // prepare + await 后再决定写 null 还是序列化(与对象路径一致)
243
- let elem = prepareValue(step.value, String(idx));
244
- if (elem instanceof Promise) {
245
- elem = await Promise.resolve(elem);
241
+ try {
242
+ write('[');
243
+ let first = true;
244
+ let idx = 0;
245
+ while (true) {
246
+ const step = await Promise.resolve(iterator.next());
247
+ if (step.done) {
248
+ completed = true;
249
+ break;
250
+ }
251
+ if (!first)
252
+ write(',');
253
+ first = false;
254
+ if (gap) {
255
+ write('\n' + gap.repeat(depth + 1));
256
+ }
257
+ let elem = prepareValue(step.value, String(idx), value);
258
+ if (elem instanceof Promise) {
259
+ elem = await Promise.resolve(elem);
260
+ }
261
+ if (elem === undefined ||
262
+ typeof elem === 'function' ||
263
+ typeof elem === 'symbol') {
264
+ write('null');
265
+ }
266
+ else {
267
+ yield* serializePrepared(elem, String(idx), depth + 1);
268
+ }
269
+ idx++;
270
+ yield* flush();
246
271
  }
247
- if (elem === undefined ||
248
- typeof elem === 'function' ||
249
- typeof elem === 'symbol') {
250
- write('null');
272
+ if (gap && !first) {
273
+ write('\n' + gap.repeat(depth));
251
274
  }
252
- else {
253
- yield* serializePrepared(elem, String(idx), depth + 1);
254
- }
255
- idx++;
256
- yield* flush();
275
+ write(']');
257
276
  }
258
- if (gap && !first) {
259
- write('\n' + gap.repeat(depth));
277
+ finally {
278
+ if (!completed && typeof iterator.return === 'function') {
279
+ try {
280
+ await iterator.return();
281
+ }
282
+ catch {
283
+ }
284
+ }
285
+ uncheckCycle(value);
260
286
  }
261
- write(']');
262
287
  return;
263
288
  }
264
289
  // 普通对象
@@ -277,19 +302,17 @@ export async function* stringifyStream(input, options = {}) {
277
302
  ? [...propertyList].filter((k) => Object.prototype.hasOwnProperty.call(value, k))
278
303
  : Object.keys(value);
279
304
  for (const k of keys) {
280
- // 1. 先 prepare
281
- let propValue = prepareValue(value[k], k);
282
- // 2. 如果是 Promise,先 await(关键!)
305
+ let rawValue = value[k];
306
+ // 1. 先等待原始值(如果它是 Promise)
307
+ if (rawValue instanceof Promise) {
308
+ rawValue = await Promise.resolve(rawValue);
309
+ }
310
+ // 2. 再执行 toJSON 和 replacer
311
+ let propValue = prepareValue(rawValue, k, value);
312
+ // 3. 如果 replacer 自身返回了 Promise,再等待它
283
313
  if (propValue instanceof Promise) {
284
314
  propValue = await Promise.resolve(propValue);
285
315
  }
286
- // 3. 现在再判断是否应该省略
287
- if (propValue === undefined ||
288
- typeof propValue === 'function' ||
289
- typeof propValue === 'symbol') {
290
- continue;
291
- }
292
- // 4. 可以安全地写 key 了
293
316
  if (!first)
294
317
  write(',');
295
318
  first = false;
@@ -298,7 +321,7 @@ export async function* stringifyStream(input, options = {}) {
298
321
  }
299
322
  writeJSONString(k);
300
323
  write(gap ? ': ' : ':');
301
- // 5. 直接序列化已经 prepare + await 过的值
324
+ // 4. 直接序列化已经 prepare + await 过的值
302
325
  yield* serializePrepared(propValue, k, depth + 1);
303
326
  yield* flush();
304
327
  }
@@ -308,7 +331,9 @@ export async function* stringifyStream(input, options = {}) {
308
331
  write('}');
309
332
  uncheckCycle(value);
310
333
  }
311
- yield* serialize(input, '', 0);
334
+ // 根值包装:与 JSON.stringify 的根对象处理方式一致
335
+ const root = { '': input };
336
+ yield* serialize(root[''], '', 0, root);
312
337
  yield* flush(true);
313
338
  }
314
339
  export async function stringify(input, options = {}) {
@@ -319,4 +344,3 @@ export async function stringify(input, options = {}) {
319
344
  }
320
345
  return chunks.join('');
321
346
  }
322
- //# sourceMappingURL=stringify-stream.js.map
@@ -6,4 +6,3 @@ export interface ReadJsonOptions {
6
6
  export declare function createJsonParser(options?: ReadJsonOptions): RequestHandler;
7
7
  export declare function readJson(req: Request, res: Response, parser: RequestHandler): Promise<unknown>;
8
8
  export type { NextFunction };
9
- //# sourceMappingURL=body.d.ts.map
@@ -25,4 +25,3 @@ export function readJson(req, res, parser) {
25
25
  }
26
26
  });
27
27
  }
28
- //# sourceMappingURL=body.js.map
@@ -1,3 +1,2 @@
1
1
  export { createExpressRouter } from './middleware.js';
2
2
  export type { ExpressOptions } from './middleware.js';
3
- //# sourceMappingURL=index.d.ts.map
@@ -1,2 +1 @@
1
1
  export { createExpressRouter } from './middleware.js';
2
- //# sourceMappingURL=index.js.map
@@ -9,4 +9,3 @@ export interface ExpressOptions {
9
9
  }
10
10
  export declare function createExpressRouter(repository: Repository, { mkInjectable, errorTransform, bodyLimit, useHtdoc, }?: ExpressOptions): Router;
11
11
  export type { RPCResponse };
12
- //# sourceMappingURL=middleware.d.ts.map
@@ -77,4 +77,3 @@ async function handleError(res, error) {
77
77
  },
78
78
  });
79
79
  }
80
- //# sourceMappingURL=middleware.js.map
@@ -1,4 +1,3 @@
1
1
  import type { Response } from 'express';
2
2
  import type { RPCResponse } from '../../types.js';
3
3
  export declare function respond(res: Response, payload: RPCResponse | undefined): Promise<void>;
4
- //# sourceMappingURL=respond.d.ts.map
@@ -122,4 +122,3 @@ async function respondNonStream(rpcRes, res) {
122
122
  if (!res.writableEnded && !res.destroyed)
123
123
  res.end();
124
124
  }
125
- //# sourceMappingURL=respond.js.map
@@ -1,2 +1 @@
1
1
  export { serveStdio, type StdioOptions } from './middleware.js';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1,2 +1 @@
1
1
  export { serveStdio } from './middleware.js';
2
- //# sourceMappingURL=index.js.map
@@ -31,4 +31,3 @@ export interface StdioOptions {
31
31
  * Resolves when the input stream ends.
32
32
  */
33
33
  export declare function serveStdio(options?: StdioOptions): Promise<void>;
34
- //# sourceMappingURL=middleware.d.ts.map
@@ -276,4 +276,3 @@ function isWs(code) {
276
276
  // space, \t, \n, \r
277
277
  return code === 0x20 || code === 0x09 || code === 0x0a || code === 0x0d;
278
278
  }
279
- //# sourceMappingURL=middleware.js.map
@@ -1,3 +1,2 @@
1
1
  export { attachWebSocket, type WSOptions } from './middleware.js';
2
2
  export { createWebSocketServer, type StandaloneWsOptions, type StandaloneWsHandle, } from './standalone.js';
3
- //# sourceMappingURL=index.d.ts.map
@@ -1,3 +1,2 @@
1
1
  export { attachWebSocket } from './middleware.js';
2
2
  export { createWebSocketServer, } from './standalone.js';
3
- //# sourceMappingURL=index.js.map