@orpc/openapi 0.0.0-next.f635909 → 0.0.0-next.f677f1d

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.
@@ -1,10 +1,10 @@
1
- import { fallbackORPCErrorStatus, fallbackORPCErrorMessage } from '@orpc/client';
1
+ import { isORPCErrorStatus, fallbackORPCErrorStatus, fallbackORPCErrorMessage } from '@orpc/client';
2
2
  import { toHttpPath } from '@orpc/client/standard';
3
3
  import { fallbackContractConfig, getEventIteratorSchemaDetails } from '@orpc/contract';
4
4
  import { standardizeHTTPPath, StandardOpenAPIJsonSerializer, getDynamicParams } from '@orpc/openapi-client/standard';
5
5
  import { isProcedure, resolveContractProcedures } from '@orpc/server';
6
- import { isObject, findDeepMatches, toArray, clone } from '@orpc/shared';
7
- import 'json-schema-typed/draft-2020-12';
6
+ import { isObject, stringifyJSON, findDeepMatches, toArray, clone, value } from '@orpc/shared';
7
+ import { TypeName } from '@orpc/interop/json-schema-typed/draft-2020-12';
8
8
 
9
9
  const OPERATION_EXTENDER_SYMBOL = Symbol("ORPC_OPERATION_EXTENDER");
10
10
  function customOpenAPIOperation(o, extend) {
@@ -114,13 +114,18 @@ function isAnySchema(schema) {
114
114
  return false;
115
115
  }
116
116
  function separateObjectSchema(schema, separatedProperties) {
117
- if (Object.keys(schema).some((k) => k !== "type" && k !== "properties" && k !== "required" && LOGIC_KEYWORDS.includes(k))) {
117
+ if (Object.keys(schema).some(
118
+ (k) => !["type", "properties", "required", "additionalProperties"].includes(k) && LOGIC_KEYWORDS.includes(k) && schema[k] !== void 0
119
+ )) {
118
120
  return [{ type: "object" }, schema];
119
121
  }
120
122
  const matched = { ...schema };
121
123
  const rest = { ...schema };
122
- matched.properties = schema.properties && Object.entries(schema.properties).filter(([key]) => separatedProperties.includes(key)).reduce((acc, [key, value]) => {
123
- acc[key] = value;
124
+ matched.properties = separatedProperties.reduce((acc, key) => {
125
+ const keySchema = schema.properties?.[key] ?? schema.additionalProperties;
126
+ if (keySchema !== void 0) {
127
+ acc[key] = keySchema;
128
+ }
124
129
  return acc;
125
130
  }, {});
126
131
  matched.required = schema.required?.filter((key) => separatedProperties.includes(key));
@@ -184,6 +189,57 @@ function applySchemaOptionality(required, schema) {
184
189
  ]
185
190
  };
186
191
  }
192
+ function expandUnionSchema(schema) {
193
+ if (typeof schema === "object") {
194
+ for (const keyword of ["anyOf", "oneOf"]) {
195
+ if (schema[keyword] && Object.keys(schema).every(
196
+ (k) => k === keyword || !LOGIC_KEYWORDS.includes(k)
197
+ )) {
198
+ return schema[keyword].flatMap((s) => expandUnionSchema(s));
199
+ }
200
+ }
201
+ }
202
+ return [schema];
203
+ }
204
+ function expandArrayableSchema(schema) {
205
+ const schemas = expandUnionSchema(schema);
206
+ if (schemas.length !== 2) {
207
+ return void 0;
208
+ }
209
+ const arraySchema = schemas.find(
210
+ (s) => typeof s === "object" && s.type === "array" && Object.keys(s).filter((k) => LOGIC_KEYWORDS.includes(k)).every((k) => k === "type" || k === "items")
211
+ );
212
+ if (arraySchema === void 0) {
213
+ return void 0;
214
+ }
215
+ const items1 = arraySchema.items;
216
+ const items2 = schemas.find((s) => s !== arraySchema);
217
+ if (stringifyJSON(items1) !== stringifyJSON(items2)) {
218
+ return void 0;
219
+ }
220
+ return [items2, arraySchema];
221
+ }
222
+ const PRIMITIVE_SCHEMA_TYPES = /* @__PURE__ */ new Set([
223
+ TypeName.String,
224
+ TypeName.Number,
225
+ TypeName.Integer,
226
+ TypeName.Boolean,
227
+ TypeName.Null
228
+ ]);
229
+ function isPrimitiveSchema(schema) {
230
+ return expandUnionSchema(schema).every((s) => {
231
+ if (typeof s === "boolean") {
232
+ return false;
233
+ }
234
+ if (typeof s.type === "string" && PRIMITIVE_SCHEMA_TYPES.has(s.type)) {
235
+ return true;
236
+ }
237
+ if (s.const !== void 0) {
238
+ return true;
239
+ }
240
+ return false;
241
+ });
242
+ }
187
243
 
188
244
  function toOpenAPIPath(path) {
189
245
  return standardizeHTTPPath(path).replace(/\/\{\+([^}]+)\}/g, "/{$1}");
@@ -256,13 +312,26 @@ function toOpenAPIParameters(schema, parameterIn) {
256
312
  const parameters = [];
257
313
  for (const key in schema.properties) {
258
314
  const keySchema = schema.properties[key];
315
+ let isDeepObjectStyle = true;
316
+ if (parameterIn !== "query") {
317
+ isDeepObjectStyle = false;
318
+ } else if (isPrimitiveSchema(keySchema)) {
319
+ isDeepObjectStyle = false;
320
+ } else {
321
+ const [item] = expandArrayableSchema(keySchema) ?? [];
322
+ if (item !== void 0 && isPrimitiveSchema(item)) {
323
+ isDeepObjectStyle = false;
324
+ }
325
+ }
259
326
  parameters.push({
260
327
  name: key,
261
328
  in: parameterIn,
262
329
  required: schema.required?.includes(key),
263
- style: parameterIn === "query" ? "deepObject" : void 0,
264
- explode: parameterIn === "query" ? true : void 0,
265
- schema: toOpenAPISchema(keySchema)
330
+ schema: toOpenAPISchema(keySchema),
331
+ style: isDeepObjectStyle ? "deepObject" : void 0,
332
+ explode: isDeepObjectStyle ? true : void 0,
333
+ allowEmptyValue: parameterIn === "query" ? true : void 0,
334
+ allowReserved: parameterIn === "query" ? true : void 0
266
335
  });
267
336
  }
268
337
  return parameters;
@@ -281,6 +350,15 @@ function checkParamsSchema(schema, params) {
281
350
  function toOpenAPISchema(schema) {
282
351
  return schema === true ? {} : schema === false ? { not: {} } : schema;
283
352
  }
353
+ const OPENAPI_JSON_SCHEMA_REF_PREFIX = "#/components/schemas/";
354
+ function resolveOpenAPIJsonSchemaRef(doc, schema) {
355
+ if (typeof schema !== "object" || !schema.$ref?.startsWith(OPENAPI_JSON_SCHEMA_REF_PREFIX)) {
356
+ return schema;
357
+ }
358
+ const name = schema.$ref.slice(OPENAPI_JSON_SCHEMA_REF_PREFIX.length);
359
+ const resolved = doc.components?.schemas?.[name];
360
+ return resolved ?? schema;
361
+ }
284
362
 
285
363
  class CompositeSchemaConverter {
286
364
  converters;
@@ -312,32 +390,50 @@ class OpenAPIGenerator {
312
390
  * @see {@link https://orpc.unnoq.com/docs/openapi/openapi-specification OpenAPI Specification Docs}
313
391
  */
314
392
  async generate(router, options = {}) {
393
+ const filter = options.filter ?? (({ contract, path }) => {
394
+ return !(options.exclude?.(contract, path) ?? false);
395
+ });
315
396
  const doc = {
316
397
  ...clone(options),
317
398
  info: options.info ?? { title: "API Reference", version: "0.0.0" },
318
- openapi: "3.1.1"
399
+ openapi: "3.1.1",
400
+ exclude: void 0,
401
+ filter: void 0,
402
+ commonSchemas: void 0
319
403
  };
404
+ const { baseSchemaConvertOptions, undefinedErrorJsonSchema } = await this.#resolveCommonSchemas(doc, options.commonSchemas);
320
405
  const contracts = [];
321
- await resolveContractProcedures({ path: [], router }, ({ contract, path }) => {
322
- contracts.push({ contract, path });
406
+ await resolveContractProcedures({ path: [], router }, (traverseOptions) => {
407
+ if (!value(filter, traverseOptions)) {
408
+ return;
409
+ }
410
+ contracts.push(traverseOptions);
323
411
  });
324
412
  const errors = [];
325
413
  for (const { contract, path } of contracts) {
326
- const operationId = path.join(".");
414
+ const stringPath = path.join(".");
327
415
  try {
328
416
  const def = contract["~orpc"];
329
417
  const method = toOpenAPIMethod(fallbackContractConfig("defaultMethod", def.route.method));
330
418
  const httpPath = toOpenAPIPath(def.route.path ?? toHttpPath(path));
331
- const operationObjectRef = {
332
- operationId,
333
- summary: def.route.summary,
334
- description: def.route.description,
335
- deprecated: def.route.deprecated,
336
- tags: def.route.tags?.map((tag) => tag)
337
- };
338
- await this.#request(operationObjectRef, def);
339
- await this.#successResponse(operationObjectRef, def);
340
- await this.#errorResponse(operationObjectRef, def);
419
+ let operationObjectRef;
420
+ if (def.route.spec !== void 0 && typeof def.route.spec !== "function") {
421
+ operationObjectRef = def.route.spec;
422
+ } else {
423
+ operationObjectRef = {
424
+ operationId: def.route.operationId ?? stringPath,
425
+ summary: def.route.summary,
426
+ description: def.route.description,
427
+ deprecated: def.route.deprecated,
428
+ tags: def.route.tags?.map((tag) => tag)
429
+ };
430
+ await this.#request(doc, operationObjectRef, def, baseSchemaConvertOptions);
431
+ await this.#successResponse(doc, operationObjectRef, def, baseSchemaConvertOptions);
432
+ await this.#errorResponse(operationObjectRef, def, baseSchemaConvertOptions, undefinedErrorJsonSchema);
433
+ }
434
+ if (typeof def.route.spec === "function") {
435
+ operationObjectRef = def.route.spec(operationObjectRef);
436
+ }
341
437
  doc.paths ??= {};
342
438
  doc.paths[httpPath] ??= {};
343
439
  doc.paths[httpPath][method] = applyCustomOpenAPIOperation(operationObjectRef, contract);
@@ -346,7 +442,7 @@ class OpenAPIGenerator {
346
442
  throw e;
347
443
  }
348
444
  errors.push(
349
- `[OpenAPIGenerator] Error occurred while generating OpenAPI for procedure at path: ${operationId}
445
+ `[OpenAPIGenerator] Error occurred while generating OpenAPI for procedure at path: ${stringPath}
350
446
  ${e.message}`
351
447
  );
352
448
  }
@@ -360,22 +456,96 @@ ${errors.join("\n\n")}`
360
456
  }
361
457
  return this.serializer.serialize(doc)[0];
362
458
  }
363
- async #request(ref, def) {
459
+ async #resolveCommonSchemas(doc, commonSchemas) {
460
+ let undefinedErrorJsonSchema = {
461
+ type: "object",
462
+ properties: {
463
+ defined: { const: false },
464
+ code: { type: "string" },
465
+ status: { type: "number" },
466
+ message: { type: "string" },
467
+ data: {}
468
+ },
469
+ required: ["defined", "code", "status", "message"]
470
+ };
471
+ const baseSchemaConvertOptions = {};
472
+ if (commonSchemas) {
473
+ baseSchemaConvertOptions.components = [];
474
+ for (const key in commonSchemas) {
475
+ const options = commonSchemas[key];
476
+ if (options.schema === void 0) {
477
+ continue;
478
+ }
479
+ const { schema, strategy = "input" } = options;
480
+ const [required, json] = await this.converter.convert(schema, { strategy });
481
+ const allowedStrategies = [strategy];
482
+ if (strategy === "input") {
483
+ const [outputRequired, outputJson] = await this.converter.convert(schema, { strategy: "output" });
484
+ if (outputRequired === required && stringifyJSON(outputJson) === stringifyJSON(json)) {
485
+ allowedStrategies.push("output");
486
+ }
487
+ } else if (strategy === "output") {
488
+ const [inputRequired, inputJson] = await this.converter.convert(schema, { strategy: "input" });
489
+ if (inputRequired === required && stringifyJSON(inputJson) === stringifyJSON(json)) {
490
+ allowedStrategies.push("input");
491
+ }
492
+ }
493
+ baseSchemaConvertOptions.components.push({
494
+ schema,
495
+ required,
496
+ ref: `#/components/schemas/${key}`,
497
+ allowedStrategies
498
+ });
499
+ }
500
+ doc.components ??= {};
501
+ doc.components.schemas ??= {};
502
+ for (const key in commonSchemas) {
503
+ const options = commonSchemas[key];
504
+ if (options.schema === void 0) {
505
+ if (options.error === "UndefinedError") {
506
+ doc.components.schemas[key] = toOpenAPISchema(undefinedErrorJsonSchema);
507
+ undefinedErrorJsonSchema = { $ref: `#/components/schemas/${key}` };
508
+ }
509
+ continue;
510
+ }
511
+ const { schema, strategy = "input" } = options;
512
+ const [, json] = await this.converter.convert(
513
+ schema,
514
+ {
515
+ ...baseSchemaConvertOptions,
516
+ strategy,
517
+ minStructureDepthForRef: 1
518
+ // not allow use $ref for root schemas
519
+ }
520
+ );
521
+ doc.components.schemas[key] = toOpenAPISchema(json);
522
+ }
523
+ }
524
+ return { baseSchemaConvertOptions, undefinedErrorJsonSchema };
525
+ }
526
+ async #request(doc, ref, def, baseSchemaConvertOptions) {
364
527
  const method = fallbackContractConfig("defaultMethod", def.route.method);
365
528
  const details = getEventIteratorSchemaDetails(def.inputSchema);
366
529
  if (details) {
367
530
  ref.requestBody = {
368
531
  required: true,
369
532
  content: toOpenAPIEventIteratorContent(
370
- await this.converter.convert(details.yields, { strategy: "input" }),
371
- await this.converter.convert(details.returns, { strategy: "input" })
533
+ await this.converter.convert(details.yields, { ...baseSchemaConvertOptions, strategy: "input" }),
534
+ await this.converter.convert(details.returns, { ...baseSchemaConvertOptions, strategy: "input" })
372
535
  )
373
536
  };
374
537
  return;
375
538
  }
376
539
  const dynamicParams = getDynamicParams(def.route.path)?.map((v) => v.name);
377
540
  const inputStructure = fallbackContractConfig("defaultInputStructure", def.route.inputStructure);
378
- let [required, schema] = await this.converter.convert(def.inputSchema, { strategy: "input" });
541
+ let [required, schema] = await this.converter.convert(
542
+ def.inputSchema,
543
+ {
544
+ ...baseSchemaConvertOptions,
545
+ strategy: "input",
546
+ minStructureDepthForRef: dynamicParams?.length || inputStructure === "detailed" ? 1 : 0
547
+ }
548
+ );
379
549
  if (isAnySchema(schema) && !dynamicParams?.length) {
380
550
  return;
381
551
  }
@@ -397,13 +567,14 @@ ${errors.join("\n\n")}`
397
567
  ref.parameters.push(...toOpenAPIParameters(paramsSchema, "path"));
398
568
  }
399
569
  if (method === "GET") {
400
- if (!isObjectSchema(schema)) {
570
+ const resolvedSchema = resolveOpenAPIJsonSchemaRef(doc, schema);
571
+ if (!isObjectSchema(resolvedSchema)) {
401
572
  throw new OpenAPIGeneratorError(
402
573
  'When method is "GET", input schema must satisfy: object | any | unknown'
403
574
  );
404
575
  }
405
576
  ref.parameters ??= [];
406
- ref.parameters.push(...toOpenAPIParameters(schema, "query"));
577
+ ref.parameters.push(...toOpenAPIParameters(resolvedSchema, "query"));
407
578
  } else {
408
579
  ref.requestBody = {
409
580
  required,
@@ -418,7 +589,8 @@ ${errors.join("\n\n")}`
418
589
  if (!isObjectSchema(schema)) {
419
590
  throw error;
420
591
  }
421
- if (dynamicParams?.length && (schema.properties?.params === void 0 || !isObjectSchema(schema.properties.params) || !checkParamsSchema(schema.properties.params, dynamicParams))) {
592
+ const resolvedParamSchema = schema.properties?.params !== void 0 ? resolveOpenAPIJsonSchemaRef(doc, schema.properties.params) : void 0;
593
+ if (dynamicParams?.length && (resolvedParamSchema === void 0 || !isObjectSchema(resolvedParamSchema) || !checkParamsSchema(resolvedParamSchema, dynamicParams))) {
422
594
  throw new OpenAPIGeneratorError(
423
595
  'When input structure is "detailed" and path has dynamic params, the "params" schema must be an object with all dynamic params as required.'
424
596
  );
@@ -426,12 +598,13 @@ ${errors.join("\n\n")}`
426
598
  for (const from of ["params", "query", "headers"]) {
427
599
  const fromSchema = schema.properties?.[from];
428
600
  if (fromSchema !== void 0) {
429
- if (!isObjectSchema(fromSchema)) {
601
+ const resolvedSchema = resolveOpenAPIJsonSchemaRef(doc, fromSchema);
602
+ if (!isObjectSchema(resolvedSchema)) {
430
603
  throw error;
431
604
  }
432
605
  const parameterIn = from === "params" ? "path" : from === "headers" ? "header" : "query";
433
606
  ref.parameters ??= [];
434
- ref.parameters.push(...toOpenAPIParameters(fromSchema, parameterIn));
607
+ ref.parameters.push(...toOpenAPIParameters(resolvedSchema, parameterIn));
435
608
  }
436
609
  }
437
610
  if (schema.properties?.body !== void 0) {
@@ -441,7 +614,7 @@ ${errors.join("\n\n")}`
441
614
  };
442
615
  }
443
616
  }
444
- async #successResponse(ref, def) {
617
+ async #successResponse(doc, ref, def, baseSchemaConvertOptions) {
445
618
  const outputSchema = def.outputSchema;
446
619
  const status = fallbackContractConfig("defaultSuccessStatus", def.route.successStatus);
447
620
  const description = fallbackContractConfig("defaultSuccessDescription", def.route?.successDescription);
@@ -452,46 +625,90 @@ ${errors.join("\n\n")}`
452
625
  ref.responses[status] = {
453
626
  description,
454
627
  content: toOpenAPIEventIteratorContent(
455
- await this.converter.convert(eventIteratorSchemaDetails.yields, { strategy: "output" }),
456
- await this.converter.convert(eventIteratorSchemaDetails.returns, { strategy: "output" })
628
+ await this.converter.convert(eventIteratorSchemaDetails.yields, { ...baseSchemaConvertOptions, strategy: "output" }),
629
+ await this.converter.convert(eventIteratorSchemaDetails.returns, { ...baseSchemaConvertOptions, strategy: "output" })
457
630
  )
458
631
  };
459
632
  return;
460
633
  }
461
- const [required, json] = await this.converter.convert(outputSchema, { strategy: "output" });
462
- ref.responses ??= {};
463
- ref.responses[status] = {
464
- description
465
- };
634
+ const [required, json] = await this.converter.convert(
635
+ outputSchema,
636
+ {
637
+ ...baseSchemaConvertOptions,
638
+ strategy: "output",
639
+ minStructureDepthForRef: outputStructure === "detailed" ? 1 : 0
640
+ }
641
+ );
466
642
  if (outputStructure === "compact") {
643
+ ref.responses ??= {};
644
+ ref.responses[status] = {
645
+ description
646
+ };
467
647
  ref.responses[status].content = toOpenAPIContent(applySchemaOptionality(required, json));
468
648
  return;
469
649
  }
470
- const error = new OpenAPIGeneratorError(
471
- 'When output structure is "detailed", output schema must satisfy: { headers?: Record<string, unknown>, body?: unknown }'
472
- );
473
- if (!isObjectSchema(json)) {
474
- throw error;
475
- }
476
- if (json.properties?.headers !== void 0) {
477
- if (!isObjectSchema(json.properties.headers)) {
650
+ const handledStatuses = /* @__PURE__ */ new Set();
651
+ for (const item of expandUnionSchema(json)) {
652
+ const error = new OpenAPIGeneratorError(`
653
+ When output structure is "detailed", output schema must satisfy:
654
+ {
655
+ status?: number, // must be a literal number and in the range of 200-399
656
+ headers?: Record<string, unknown>,
657
+ body?: unknown
658
+ }
659
+
660
+ But got: ${stringifyJSON(item)}
661
+ `);
662
+ if (!isObjectSchema(item)) {
478
663
  throw error;
479
664
  }
480
- for (const key in json.properties.headers.properties) {
481
- ref.responses[status].headers ??= {};
482
- ref.responses[status].headers[key] = {
483
- schema: toOpenAPISchema(json.properties.headers.properties[key]),
484
- required: json.properties.headers.required?.includes(key)
485
- };
665
+ let schemaStatus;
666
+ let schemaDescription;
667
+ if (item.properties?.status !== void 0) {
668
+ const statusSchema = resolveOpenAPIJsonSchemaRef(doc, item.properties.status);
669
+ if (typeof statusSchema !== "object" || statusSchema.const === void 0 || typeof statusSchema.const !== "number" || !Number.isInteger(statusSchema.const) || isORPCErrorStatus(statusSchema.const)) {
670
+ throw error;
671
+ }
672
+ schemaStatus = statusSchema.const;
673
+ schemaDescription = statusSchema.description;
674
+ }
675
+ const itemStatus = schemaStatus ?? status;
676
+ const itemDescription = schemaDescription ?? description;
677
+ if (handledStatuses.has(itemStatus)) {
678
+ throw new OpenAPIGeneratorError(`
679
+ When output structure is "detailed", each success status must be unique.
680
+ But got status: ${itemStatus} used more than once.
681
+ `);
682
+ }
683
+ handledStatuses.add(itemStatus);
684
+ ref.responses ??= {};
685
+ ref.responses[itemStatus] = {
686
+ description: itemDescription
687
+ };
688
+ if (item.properties?.headers !== void 0) {
689
+ const headersSchema = resolveOpenAPIJsonSchemaRef(doc, item.properties.headers);
690
+ if (!isObjectSchema(headersSchema)) {
691
+ throw error;
692
+ }
693
+ for (const key in headersSchema.properties) {
694
+ const headerSchema = headersSchema.properties[key];
695
+ if (headerSchema !== void 0) {
696
+ ref.responses[itemStatus].headers ??= {};
697
+ ref.responses[itemStatus].headers[key] = {
698
+ schema: toOpenAPISchema(headerSchema),
699
+ required: item.required?.includes("headers") && headersSchema.required?.includes(key)
700
+ };
701
+ }
702
+ }
703
+ }
704
+ if (item.properties?.body !== void 0) {
705
+ ref.responses[itemStatus].content = toOpenAPIContent(
706
+ applySchemaOptionality(item.required?.includes("body") ?? false, item.properties.body)
707
+ );
486
708
  }
487
- }
488
- if (json.properties?.body !== void 0) {
489
- ref.responses[status].content = toOpenAPIContent(
490
- applySchemaOptionality(json.required?.includes("body") ?? false, json.properties.body)
491
- );
492
709
  }
493
710
  }
494
- async #errorResponse(ref, def) {
711
+ async #errorResponse(ref, def, baseSchemaConvertOptions, undefinedErrorSchema) {
495
712
  const errorMap = def.errorMap;
496
713
  const errors = {};
497
714
  for (const code in errorMap) {
@@ -501,7 +718,7 @@ ${errors.join("\n\n")}`
501
718
  }
502
719
  const status = fallbackORPCErrorStatus(code, config.status);
503
720
  const message = fallbackORPCErrorMessage(code, config.message);
504
- const [dataRequired, dataSchema] = await this.converter.convert(config.data, { strategy: "output" });
721
+ const [dataRequired, dataSchema] = await this.converter.convert(config.data, { ...baseSchemaConvertOptions, strategy: "output" });
505
722
  errors[status] ??= [];
506
723
  errors[status].push({
507
724
  type: "object",
@@ -523,17 +740,7 @@ ${errors.join("\n\n")}`
523
740
  content: toOpenAPIContent({
524
741
  oneOf: [
525
742
  ...schemas,
526
- {
527
- type: "object",
528
- properties: {
529
- defined: { const: false },
530
- code: { type: "string" },
531
- status: { type: "number" },
532
- message: { type: "string" },
533
- data: {}
534
- },
535
- required: ["defined", "code", "status", "message"]
536
- }
743
+ undefinedErrorSchema
537
744
  ]
538
745
  })
539
746
  };
@@ -541,4 +748,4 @@ ${errors.join("\n\n")}`
541
748
  }
542
749
  }
543
750
 
544
- export { CompositeSchemaConverter as C, LOGIC_KEYWORDS as L, OpenAPIGenerator as O, applyCustomOpenAPIOperation as a, toOpenAPIMethod as b, customOpenAPIOperation as c, toOpenAPIContent as d, toOpenAPIEventIteratorContent as e, toOpenAPIParameters as f, getCustomOpenAPIOperation as g, checkParamsSchema as h, toOpenAPISchema as i, isFileSchema as j, isObjectSchema as k, isAnySchema as l, filterSchemaBranches as m, applySchemaOptionality as n, separateObjectSchema as s, toOpenAPIPath as t };
751
+ export { CompositeSchemaConverter as C, LOGIC_KEYWORDS as L, OpenAPIGenerator as O, applyCustomOpenAPIOperation as a, toOpenAPIMethod as b, customOpenAPIOperation as c, toOpenAPIContent as d, toOpenAPIEventIteratorContent as e, toOpenAPIParameters as f, getCustomOpenAPIOperation as g, checkParamsSchema as h, toOpenAPISchema as i, isFileSchema as j, isObjectSchema as k, isAnySchema as l, filterSchemaBranches as m, applySchemaOptionality as n, expandUnionSchema as o, expandArrayableSchema as p, isPrimitiveSchema as q, resolveOpenAPIJsonSchemaRef as r, separateObjectSchema as s, toOpenAPIPath as t };
@@ -0,0 +1,31 @@
1
+ import { StandardOpenAPIJsonSerializerOptions, StandardBracketNotationSerializerOptions } from '@orpc/openapi-client/standard';
2
+ import { TraverseContractProcedureCallbackOptions, AnyRouter, Context, Router } from '@orpc/server';
3
+ import { StandardMatcher, StandardMatchResult, StandardHandlerOptions, StandardHandler } from '@orpc/server/standard';
4
+ import { HTTPPath } from '@orpc/client';
5
+ import { Value } from '@orpc/shared';
6
+
7
+ interface StandardOpenAPIMatcherOptions {
8
+ /**
9
+ * Filter procedures. Return `false` to exclude a procedure from matching.
10
+ *
11
+ * @default true
12
+ */
13
+ filter?: Value<boolean, [options: TraverseContractProcedureCallbackOptions]>;
14
+ }
15
+ declare class StandardOpenAPIMatcher implements StandardMatcher {
16
+ private readonly filter;
17
+ private readonly tree;
18
+ private pendingRouters;
19
+ constructor(options?: StandardOpenAPIMatcherOptions);
20
+ init(router: AnyRouter, path?: readonly string[]): void;
21
+ match(method: string, pathname: HTTPPath): Promise<StandardMatchResult>;
22
+ }
23
+
24
+ interface StandardOpenAPIHandlerOptions<T extends Context> extends StandardHandlerOptions<T>, StandardOpenAPIJsonSerializerOptions, StandardBracketNotationSerializerOptions, StandardOpenAPIMatcherOptions {
25
+ }
26
+ declare class StandardOpenAPIHandler<T extends Context> extends StandardHandler<T> {
27
+ constructor(router: Router<any, T>, options: NoInfer<StandardOpenAPIHandlerOptions<T>>);
28
+ }
29
+
30
+ export { StandardOpenAPIHandler as a, StandardOpenAPIMatcher as c };
31
+ export type { StandardOpenAPIHandlerOptions as S, StandardOpenAPIMatcherOptions as b };
@@ -0,0 +1,31 @@
1
+ import { StandardOpenAPIJsonSerializerOptions, StandardBracketNotationSerializerOptions } from '@orpc/openapi-client/standard';
2
+ import { TraverseContractProcedureCallbackOptions, AnyRouter, Context, Router } from '@orpc/server';
3
+ import { StandardMatcher, StandardMatchResult, StandardHandlerOptions, StandardHandler } from '@orpc/server/standard';
4
+ import { HTTPPath } from '@orpc/client';
5
+ import { Value } from '@orpc/shared';
6
+
7
+ interface StandardOpenAPIMatcherOptions {
8
+ /**
9
+ * Filter procedures. Return `false` to exclude a procedure from matching.
10
+ *
11
+ * @default true
12
+ */
13
+ filter?: Value<boolean, [options: TraverseContractProcedureCallbackOptions]>;
14
+ }
15
+ declare class StandardOpenAPIMatcher implements StandardMatcher {
16
+ private readonly filter;
17
+ private readonly tree;
18
+ private pendingRouters;
19
+ constructor(options?: StandardOpenAPIMatcherOptions);
20
+ init(router: AnyRouter, path?: readonly string[]): void;
21
+ match(method: string, pathname: HTTPPath): Promise<StandardMatchResult>;
22
+ }
23
+
24
+ interface StandardOpenAPIHandlerOptions<T extends Context> extends StandardHandlerOptions<T>, StandardOpenAPIJsonSerializerOptions, StandardBracketNotationSerializerOptions, StandardOpenAPIMatcherOptions {
25
+ }
26
+ declare class StandardOpenAPIHandler<T extends Context> extends StandardHandler<T> {
27
+ constructor(router: Router<any, T>, options: NoInfer<StandardOpenAPIHandlerOptions<T>>);
28
+ }
29
+
30
+ export { StandardOpenAPIHandler as a, StandardOpenAPIMatcher as c };
31
+ export type { StandardOpenAPIHandlerOptions as S, StandardOpenAPIMatcherOptions as b };