@orpc/openapi 1.10.4 → 1.11.0

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/dist/index.d.mts CHANGED
@@ -66,6 +66,12 @@ declare function checkParamsSchema(schema: ObjectSchema, params: string[]): bool
66
66
  */
67
67
  declare function toOpenAPISchema(schema: JSONSchema): OpenAPI.SchemaObject & object;
68
68
  declare function resolveOpenAPIJsonSchemaRef(doc: OpenAPI.Document, schema: JSONSchema): JSONSchema;
69
+ /**
70
+ * Simplifies composed object JSON Schemas (using anyOf, oneOf, allOf) by flattening nested compositions
71
+ *
72
+ * @warning The result is looser than the original schema and may not fully validate the same data.
73
+ */
74
+ declare function simplifyComposedObjectJsonSchemasAndRefs(schema: JSONSchema, doc?: OpenAPI.Document): JSONSchema;
69
75
 
70
76
  declare function createJsonifiedRouterClient<T extends AnyRouter, TClientContext extends ClientContext>(router: Lazyable<T | undefined>, ...rest: MaybeOptionalOptions<CreateProcedureClientOptions<InferRouterInitialContext<T>, Schema<unknown, unknown>, ErrorMap, Meta, TClientContext>>): JsonifiedClient<RouterClient<T, TClientContext>>;
71
77
 
@@ -106,5 +112,5 @@ declare const oo: {
106
112
  spec: typeof customOpenAPIOperation;
107
113
  };
108
114
 
109
- export { LOGIC_KEYWORDS, applyCustomOpenAPIOperation, applySchemaOptionality, checkParamsSchema, createJsonifiedRouterClient, customOpenAPIOperation, expandArrayableSchema, expandUnionSchema, filterSchemaBranches, getCustomOpenAPIOperation, isAnySchema, isFileSchema, isObjectSchema, isPrimitiveSchema, oo, resolveOpenAPIJsonSchemaRef, separateObjectSchema, toOpenAPIContent, toOpenAPIEventIteratorContent, toOpenAPIMethod, toOpenAPIParameters, toOpenAPIPath, toOpenAPISchema };
115
+ export { LOGIC_KEYWORDS, applyCustomOpenAPIOperation, applySchemaOptionality, checkParamsSchema, createJsonifiedRouterClient, customOpenAPIOperation, expandArrayableSchema, expandUnionSchema, filterSchemaBranches, getCustomOpenAPIOperation, isAnySchema, isFileSchema, isObjectSchema, isPrimitiveSchema, oo, resolveOpenAPIJsonSchemaRef, separateObjectSchema, simplifyComposedObjectJsonSchemasAndRefs, toOpenAPIContent, toOpenAPIEventIteratorContent, toOpenAPIMethod, toOpenAPIParameters, toOpenAPIPath, toOpenAPISchema };
110
116
  export type { FileSchema, ObjectSchema, OverrideOperationValue };
package/dist/index.d.ts CHANGED
@@ -66,6 +66,12 @@ declare function checkParamsSchema(schema: ObjectSchema, params: string[]): bool
66
66
  */
67
67
  declare function toOpenAPISchema(schema: JSONSchema): OpenAPI.SchemaObject & object;
68
68
  declare function resolveOpenAPIJsonSchemaRef(doc: OpenAPI.Document, schema: JSONSchema): JSONSchema;
69
+ /**
70
+ * Simplifies composed object JSON Schemas (using anyOf, oneOf, allOf) by flattening nested compositions
71
+ *
72
+ * @warning The result is looser than the original schema and may not fully validate the same data.
73
+ */
74
+ declare function simplifyComposedObjectJsonSchemasAndRefs(schema: JSONSchema, doc?: OpenAPI.Document): JSONSchema;
69
75
 
70
76
  declare function createJsonifiedRouterClient<T extends AnyRouter, TClientContext extends ClientContext>(router: Lazyable<T | undefined>, ...rest: MaybeOptionalOptions<CreateProcedureClientOptions<InferRouterInitialContext<T>, Schema<unknown, unknown>, ErrorMap, Meta, TClientContext>>): JsonifiedClient<RouterClient<T, TClientContext>>;
71
77
 
@@ -106,5 +112,5 @@ declare const oo: {
106
112
  spec: typeof customOpenAPIOperation;
107
113
  };
108
114
 
109
- export { LOGIC_KEYWORDS, applyCustomOpenAPIOperation, applySchemaOptionality, checkParamsSchema, createJsonifiedRouterClient, customOpenAPIOperation, expandArrayableSchema, expandUnionSchema, filterSchemaBranches, getCustomOpenAPIOperation, isAnySchema, isFileSchema, isObjectSchema, isPrimitiveSchema, oo, resolveOpenAPIJsonSchemaRef, separateObjectSchema, toOpenAPIContent, toOpenAPIEventIteratorContent, toOpenAPIMethod, toOpenAPIParameters, toOpenAPIPath, toOpenAPISchema };
115
+ export { LOGIC_KEYWORDS, applyCustomOpenAPIOperation, applySchemaOptionality, checkParamsSchema, createJsonifiedRouterClient, customOpenAPIOperation, expandArrayableSchema, expandUnionSchema, filterSchemaBranches, getCustomOpenAPIOperation, isAnySchema, isFileSchema, isObjectSchema, isPrimitiveSchema, oo, resolveOpenAPIJsonSchemaRef, separateObjectSchema, simplifyComposedObjectJsonSchemasAndRefs, toOpenAPIContent, toOpenAPIEventIteratorContent, toOpenAPIMethod, toOpenAPIParameters, toOpenAPIPath, toOpenAPISchema };
110
116
  export type { FileSchema, ObjectSchema, OverrideOperationValue };
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { c as customOpenAPIOperation } from './shared/openapi.DrTcell5.mjs';
2
- export { C as CompositeSchemaConverter, L as LOGIC_KEYWORDS, O as OpenAPIGenerator, a as applyCustomOpenAPIOperation, n as applySchemaOptionality, h as checkParamsSchema, p as expandArrayableSchema, o as expandUnionSchema, m as filterSchemaBranches, g as getCustomOpenAPIOperation, l as isAnySchema, j as isFileSchema, k as isObjectSchema, q as isPrimitiveSchema, r as resolveOpenAPIJsonSchemaRef, s as separateObjectSchema, d as toOpenAPIContent, e as toOpenAPIEventIteratorContent, b as toOpenAPIMethod, f as toOpenAPIParameters, t as toOpenAPIPath, i as toOpenAPISchema } from './shared/openapi.DrTcell5.mjs';
1
+ import { c as customOpenAPIOperation } from './shared/openapi.CzHcOMxv.mjs';
2
+ export { C as CompositeSchemaConverter, L as LOGIC_KEYWORDS, O as OpenAPIGenerator, a as applyCustomOpenAPIOperation, o as applySchemaOptionality, h as checkParamsSchema, q as expandArrayableSchema, p as expandUnionSchema, n as filterSchemaBranches, g as getCustomOpenAPIOperation, l as isAnySchema, j as isFileSchema, k as isObjectSchema, u as isPrimitiveSchema, r as resolveOpenAPIJsonSchemaRef, m as separateObjectSchema, s as simplifyComposedObjectJsonSchemasAndRefs, d as toOpenAPIContent, e as toOpenAPIEventIteratorContent, b as toOpenAPIMethod, f as toOpenAPIParameters, t as toOpenAPIPath, i as toOpenAPISchema } from './shared/openapi.CzHcOMxv.mjs';
3
3
  import { createORPCErrorFromJson } from '@orpc/client';
4
4
  import { StandardOpenAPISerializer, StandardOpenAPIJsonSerializer, StandardBracketNotationSerializer } from '@orpc/openapi-client/standard';
5
5
  import { ORPCError, createRouterClient } from '@orpc/server';
@@ -1,5 +1,5 @@
1
1
  import { stringifyJSON, once, value } from '@orpc/shared';
2
- import { O as OpenAPIGenerator } from '../shared/openapi.DrTcell5.mjs';
2
+ import { O as OpenAPIGenerator } from '../shared/openapi.CzHcOMxv.mjs';
3
3
  import '@orpc/client';
4
4
  import '@orpc/client/standard';
5
5
  import '@orpc/contract';
@@ -359,6 +359,107 @@ function resolveOpenAPIJsonSchemaRef(doc, schema) {
359
359
  const resolved = doc.components?.schemas?.[name];
360
360
  return resolved ?? schema;
361
361
  }
362
+ function simplifyComposedObjectJsonSchemasAndRefs(schema, doc) {
363
+ if (doc) {
364
+ schema = resolveOpenAPIJsonSchemaRef(doc, schema);
365
+ }
366
+ if (typeof schema !== "object" || !schema.anyOf && !schema.oneOf && !schema.allOf) {
367
+ return schema;
368
+ }
369
+ const unionSchemas = [
370
+ ...toArray(schema.anyOf?.map((s) => simplifyComposedObjectJsonSchemasAndRefs(s, doc))),
371
+ ...toArray(schema.oneOf?.map((s) => simplifyComposedObjectJsonSchemasAndRefs(s, doc)))
372
+ ];
373
+ const objectUnionSchemas = [];
374
+ for (const u of unionSchemas) {
375
+ if (!isObjectSchema(u)) {
376
+ return schema;
377
+ }
378
+ objectUnionSchemas.push(u);
379
+ }
380
+ const mergedUnionPropertyMap = /* @__PURE__ */ new Map();
381
+ for (const u of objectUnionSchemas) {
382
+ if (u.properties) {
383
+ for (const [key, value] of Object.entries(u.properties)) {
384
+ let entry = mergedUnionPropertyMap.get(key);
385
+ if (!entry) {
386
+ const required = objectUnionSchemas.every((s) => s.required?.includes(key));
387
+ entry = { required, schemas: [] };
388
+ mergedUnionPropertyMap.set(key, entry);
389
+ }
390
+ entry.schemas.push(value);
391
+ }
392
+ }
393
+ }
394
+ const intersectionSchemas = toArray(schema.allOf?.map((s) => simplifyComposedObjectJsonSchemasAndRefs(s, doc)));
395
+ const objectIntersectionSchemas = [];
396
+ for (const u of intersectionSchemas) {
397
+ if (!isObjectSchema(u)) {
398
+ return schema;
399
+ }
400
+ objectIntersectionSchemas.push(u);
401
+ }
402
+ if (isObjectSchema(schema)) {
403
+ objectIntersectionSchemas.push(schema);
404
+ }
405
+ const mergedInteractionPropertyMap = /* @__PURE__ */ new Map();
406
+ for (const u of objectIntersectionSchemas) {
407
+ if (u.properties) {
408
+ for (const [key, value] of Object.entries(u.properties)) {
409
+ let entry = mergedInteractionPropertyMap.get(key);
410
+ if (!entry) {
411
+ const required = objectIntersectionSchemas.some((s) => s.required?.includes(key));
412
+ entry = { required, schemas: [] };
413
+ mergedInteractionPropertyMap.set(key, entry);
414
+ }
415
+ entry.schemas.push(value);
416
+ }
417
+ }
418
+ }
419
+ const resultObjectSchema = { type: "object", properties: {}, required: [] };
420
+ const keys = /* @__PURE__ */ new Set([
421
+ ...mergedUnionPropertyMap.keys(),
422
+ ...mergedInteractionPropertyMap.keys()
423
+ ]);
424
+ if (keys.size === 0) {
425
+ return schema;
426
+ }
427
+ const deduplicateSchemas = (schemas) => {
428
+ const seen = /* @__PURE__ */ new Set();
429
+ const result = [];
430
+ for (const schema2 of schemas) {
431
+ const key = stringifyJSON(schema2);
432
+ if (!seen.has(key)) {
433
+ seen.add(key);
434
+ result.push(schema2);
435
+ }
436
+ }
437
+ return result;
438
+ };
439
+ for (const key of keys) {
440
+ const unionEntry = mergedUnionPropertyMap.get(key);
441
+ const intersectionEntry = mergedInteractionPropertyMap.get(key);
442
+ resultObjectSchema.properties[key] = (() => {
443
+ const dedupedUnionSchemas = unionEntry ? deduplicateSchemas(unionEntry.schemas) : [];
444
+ const dedupedIntersectionSchemas = intersectionEntry ? deduplicateSchemas(intersectionEntry.schemas) : [];
445
+ if (!dedupedUnionSchemas.length) {
446
+ return dedupedIntersectionSchemas.length === 1 ? dedupedIntersectionSchemas[0] : { allOf: dedupedIntersectionSchemas };
447
+ }
448
+ if (!dedupedIntersectionSchemas.length) {
449
+ return dedupedUnionSchemas.length === 1 ? dedupedUnionSchemas[0] : { anyOf: dedupedUnionSchemas };
450
+ }
451
+ const allOf = deduplicateSchemas([
452
+ ...dedupedIntersectionSchemas,
453
+ dedupedUnionSchemas.length === 1 ? dedupedUnionSchemas[0] : { anyOf: dedupedUnionSchemas }
454
+ ]);
455
+ return allOf.length === 1 ? allOf[0] : { allOf };
456
+ })();
457
+ if (unionEntry?.required || intersectionEntry?.required) {
458
+ resultObjectSchema.required.push(key);
459
+ }
460
+ }
461
+ return resultObjectSchema;
462
+ }
362
463
 
363
464
  class CompositeSchemaConverter {
364
465
  converters;
@@ -539,13 +640,15 @@ ${errors.join("\n\n")}`
539
640
  def.inputSchema,
540
641
  {
541
642
  ...baseSchemaConvertOptions,
542
- strategy: "input",
543
- minStructureDepthForRef: dynamicParams?.length || inputStructure === "detailed" ? 1 : 0
643
+ strategy: "input"
544
644
  }
545
645
  );
546
646
  if (isAnySchema(schema) && !dynamicParams?.length) {
547
647
  return;
548
648
  }
649
+ if (inputStructure === "detailed" || inputStructure === "compact" && (dynamicParams?.length || method === "GET")) {
650
+ schema = simplifyComposedObjectJsonSchemasAndRefs(schema, doc);
651
+ }
549
652
  if (inputStructure === "compact") {
550
653
  if (dynamicParams?.length) {
551
654
  const error2 = new OpenAPIGeneratorError(
@@ -564,14 +667,13 @@ ${errors.join("\n\n")}`
564
667
  ref.parameters.push(...toOpenAPIParameters(paramsSchema, "path"));
565
668
  }
566
669
  if (method === "GET") {
567
- const resolvedSchema = resolveOpenAPIJsonSchemaRef(doc, schema);
568
- if (!isObjectSchema(resolvedSchema)) {
670
+ if (!isObjectSchema(schema)) {
569
671
  throw new OpenAPIGeneratorError(
570
672
  'When method is "GET", input schema must satisfy: object | any | unknown'
571
673
  );
572
674
  }
573
675
  ref.parameters ??= [];
574
- ref.parameters.push(...toOpenAPIParameters(resolvedSchema, "query"));
676
+ ref.parameters.push(...toOpenAPIParameters(schema, "query"));
575
677
  } else {
576
678
  ref.requestBody = {
577
679
  required,
@@ -586,7 +688,7 @@ ${errors.join("\n\n")}`
586
688
  if (!isObjectSchema(schema)) {
587
689
  throw error;
588
690
  }
589
- const resolvedParamSchema = schema.properties?.params !== void 0 ? resolveOpenAPIJsonSchemaRef(doc, schema.properties.params) : void 0;
691
+ const resolvedParamSchema = schema.properties?.params !== void 0 ? simplifyComposedObjectJsonSchemasAndRefs(schema.properties.params, doc) : void 0;
590
692
  if (dynamicParams?.length && (resolvedParamSchema === void 0 || !isObjectSchema(resolvedParamSchema) || !checkParamsSchema(resolvedParamSchema, dynamicParams))) {
591
693
  throw new OpenAPIGeneratorError(
592
694
  'When input structure is "detailed" and path has dynamic params, the "params" schema must be an object with all dynamic params as required.'
@@ -595,7 +697,7 @@ ${errors.join("\n\n")}`
595
697
  for (const from of ["params", "query", "headers"]) {
596
698
  const fromSchema = schema.properties?.[from];
597
699
  if (fromSchema !== void 0) {
598
- const resolvedSchema = resolveOpenAPIJsonSchemaRef(doc, fromSchema);
700
+ const resolvedSchema = simplifyComposedObjectJsonSchemasAndRefs(fromSchema, doc);
599
701
  if (!isObjectSchema(resolvedSchema)) {
600
702
  throw error;
601
703
  }
@@ -656,13 +758,14 @@ ${errors.join("\n\n")}`
656
758
 
657
759
  But got: ${stringifyJSON(item)}
658
760
  `);
659
- if (!isObjectSchema(item)) {
761
+ const simplifiedItem = simplifyComposedObjectJsonSchemasAndRefs(item, doc);
762
+ if (!isObjectSchema(simplifiedItem)) {
660
763
  throw error;
661
764
  }
662
765
  let schemaStatus;
663
766
  let schemaDescription;
664
- if (item.properties?.status !== void 0) {
665
- const statusSchema = resolveOpenAPIJsonSchemaRef(doc, item.properties.status);
767
+ if (simplifiedItem.properties?.status !== void 0) {
768
+ const statusSchema = resolveOpenAPIJsonSchemaRef(doc, simplifiedItem.properties.status);
666
769
  if (typeof statusSchema !== "object" || statusSchema.const === void 0 || typeof statusSchema.const !== "number" || !Number.isInteger(statusSchema.const) || isORPCErrorStatus(statusSchema.const)) {
667
770
  throw error;
668
771
  }
@@ -682,8 +785,8 @@ ${errors.join("\n\n")}`
682
785
  ref.responses[itemStatus] = {
683
786
  description: itemDescription
684
787
  };
685
- if (item.properties?.headers !== void 0) {
686
- const headersSchema = resolveOpenAPIJsonSchemaRef(doc, item.properties.headers);
788
+ if (simplifiedItem.properties?.headers !== void 0) {
789
+ const headersSchema = simplifyComposedObjectJsonSchemasAndRefs(simplifiedItem.properties.headers, doc);
687
790
  if (!isObjectSchema(headersSchema)) {
688
791
  throw error;
689
792
  }
@@ -693,14 +796,14 @@ ${errors.join("\n\n")}`
693
796
  ref.responses[itemStatus].headers ??= {};
694
797
  ref.responses[itemStatus].headers[key] = {
695
798
  schema: toOpenAPISchema(headerSchema),
696
- required: item.required?.includes("headers") && headersSchema.required?.includes(key)
799
+ required: simplifiedItem.required?.includes("headers") && headersSchema.required?.includes(key)
697
800
  };
698
801
  }
699
802
  }
700
803
  }
701
- if (item.properties?.body !== void 0) {
804
+ if (simplifiedItem.properties?.body !== void 0) {
702
805
  ref.responses[itemStatus].content = toOpenAPIContent(
703
- applySchemaOptionality(item.required?.includes("body") ?? false, item.properties.body)
806
+ applySchemaOptionality(simplifiedItem.required?.includes("body") ?? false, simplifiedItem.properties.body)
704
807
  );
705
808
  }
706
809
  }
@@ -747,4 +850,4 @@ ${errors.join("\n\n")}`
747
850
  }
748
851
  }
749
852
 
750
- 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 };
853
+ 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, separateObjectSchema as m, filterSchemaBranches as n, applySchemaOptionality as o, expandUnionSchema as p, expandArrayableSchema as q, resolveOpenAPIJsonSchemaRef as r, simplifyComposedObjectJsonSchemasAndRefs as s, toOpenAPIPath as t, isPrimitiveSchema as u };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orpc/openapi",
3
3
  "type": "module",
4
- "version": "1.10.4",
4
+ "version": "1.11.0",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orpc.unnoq.com",
7
7
  "repository": {
@@ -55,13 +55,13 @@
55
55
  ],
56
56
  "dependencies": {
57
57
  "rou3": "^0.7.10",
58
- "@orpc/client": "1.10.4",
59
- "@orpc/interop": "1.10.4",
60
- "@orpc/contract": "1.10.4",
61
- "@orpc/openapi-client": "1.10.4",
62
- "@orpc/shared": "1.10.4",
63
- "@orpc/standard-server": "1.10.4",
64
- "@orpc/server": "1.10.4"
58
+ "@orpc/client": "1.11.0",
59
+ "@orpc/contract": "1.11.0",
60
+ "@orpc/interop": "1.11.0",
61
+ "@orpc/openapi-client": "1.11.0",
62
+ "@orpc/shared": "1.11.0",
63
+ "@orpc/server": "1.11.0",
64
+ "@orpc/standard-server": "1.11.0"
65
65
  },
66
66
  "devDependencies": {
67
67
  "fastify": "^5.6.1",