@trpc/openapi 11.15.1-alpha → 11.15.2-alpha

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
@@ -1,32 +1,100 @@
1
- //#region src/generate.d.ts
2
- /**
3
- * A minimal JSON Schema subset used for OpenAPI 3.1 schemas.
4
- */
5
- interface JsonSchema {
1
+ import { __export } from "./chunk-CJ2cON1m.mjs";
2
+ import { OpenAPIV3_1 } from "openapi-types";
3
+
4
+ //#region src/types.d.ts
5
+ declare namespace types_d_exports {
6
+ export { ArraySchemaObject, CallbackObject, ComponentsObject, DiscriminatorObject, Document, ExampleObject, ExternalDocumentationObject, HeaderObject, HttpMethods, LinkObject, MediaTypeObject, OperationObject, ParameterBaseObject, ParameterObject, PathItemObject, PathsObject, PrimitiveSchemaType, ReferenceObject, Replace, RequestBodyObject, ResponseObject, ResponsesObject, SchemaLike, SchemaObject, SchemaType, SecuritySchemeObject, XMLObject };
7
+ }
8
+ type Replace<TTarget, TReplaceWith> = Omit<TTarget, keyof TReplaceWith> & TReplaceWith;
9
+ type SchemaType = 'array' | 'boolean' | 'integer' | 'null' | 'number' | 'object' | 'string';
10
+ type PrimitiveSchemaType = SchemaType;
11
+ type HttpMethods = OpenAPIV3_1.HttpMethods;
12
+ type ReferenceObject = OpenAPIV3_1.ReferenceObject;
13
+ type ExampleObject = OpenAPIV3_1.ExampleObject;
14
+ type DiscriminatorObject = OpenAPIV3_1.DiscriminatorObject;
15
+ type ExternalDocumentationObject = OpenAPIV3_1.ExternalDocumentationObject;
16
+ type XMLObject = OpenAPIV3_1.XMLObject;
17
+ type LinkObject = OpenAPIV3_1.LinkObject;
18
+ type SecuritySchemeObject = OpenAPIV3_1.SecuritySchemeObject;
19
+ type SchemaObject = Replace<OpenAPIV3_1.BaseSchemaObject, {
6
20
  $ref?: string;
7
- $defs?: Record<string, JsonSchema>;
21
+ $defs?: Record<string, SchemaObject>;
22
+ $schema?: string;
8
23
  type?: string | string[];
9
- properties?: Record<string, JsonSchema>;
24
+ properties?: Record<string, SchemaObject>;
10
25
  required?: string[];
11
- items?: JsonSchema | false;
12
- prefixItems?: JsonSchema[];
26
+ items?: SchemaObject | false;
27
+ prefixItems?: SchemaObject[];
13
28
  const?: string | number | boolean | null;
14
29
  enum?: (string | number | boolean | null)[];
15
- oneOf?: JsonSchema[];
16
- anyOf?: JsonSchema[];
17
- allOf?: JsonSchema[];
18
- not?: JsonSchema;
19
- additionalProperties?: JsonSchema | boolean;
20
- discriminator?: {
21
- propertyName: string;
22
- mapping?: Record<string, string>;
23
- };
24
- format?: string;
25
- description?: string;
26
- minItems?: number;
27
- maxItems?: number;
28
- $schema?: string;
30
+ oneOf?: SchemaObject[];
31
+ anyOf?: SchemaObject[];
32
+ allOf?: SchemaObject[];
33
+ not?: SchemaObject;
34
+ additionalProperties?: boolean | SchemaObject;
35
+ discriminator?: DiscriminatorObject;
36
+ externalDocs?: ExternalDocumentationObject;
37
+ xml?: XMLObject;
38
+ contentMediaType?: string;
39
+ exclusiveMinimum?: boolean | number;
40
+ exclusiveMaximum?: boolean | number;
41
+ }>;
42
+ type SchemaLike = SchemaObject;
43
+ interface ArraySchemaObject extends SchemaObject {
44
+ type: 'array';
45
+ items: SchemaObject | false;
46
+ }
47
+ type MediaTypeObject = Replace<OpenAPIV3_1.MediaTypeObject, {
48
+ schema?: SchemaObject | ReferenceObject;
49
+ examples?: Record<string, ReferenceObject | ExampleObject>;
50
+ }>;
51
+ interface ParameterBaseObject extends Replace<OpenAPIV3_1.ParameterBaseObject, {
52
+ schema?: SchemaObject | ReferenceObject;
53
+ examples?: Record<string, ReferenceObject | ExampleObject>;
54
+ content?: Record<string, MediaTypeObject>;
55
+ }> {}
56
+ interface ParameterObject extends ParameterBaseObject {
57
+ name: string;
58
+ in: string;
29
59
  }
60
+ type HeaderObject = ParameterBaseObject;
61
+ type RequestBodyObject = Replace<OpenAPIV3_1.RequestBodyObject, {
62
+ content: Record<string, MediaTypeObject>;
63
+ }>;
64
+ type ResponseObject = Replace<OpenAPIV3_1.ResponseObject, {
65
+ headers?: Record<string, ReferenceObject | HeaderObject>;
66
+ content?: Record<string, MediaTypeObject>;
67
+ links?: Record<string, ReferenceObject | LinkObject>;
68
+ }>;
69
+ type ResponsesObject = Record<string, ReferenceObject | ResponseObject>;
70
+ type OperationObject<T extends {} = {}> = Replace<OpenAPIV3_1.OperationObject<T>, {
71
+ parameters?: (ReferenceObject | ParameterObject)[];
72
+ requestBody?: ReferenceObject | RequestBodyObject;
73
+ responses?: ResponsesObject;
74
+ callbacks?: Record<string, ReferenceObject | CallbackObject>;
75
+ }> & T;
76
+ type PathItemObject<T extends {} = {}> = Replace<OpenAPIV3_1.PathItemObject<T>, {
77
+ parameters?: (ReferenceObject | ParameterObject)[];
78
+ }> & { [method in HttpMethods]?: OperationObject<T> };
79
+ type PathsObject<T extends {} = {}, TPath extends {} = {}> = Record<string, (PathItemObject<T> & TPath) | undefined>;
80
+ type CallbackObject = Record<string, PathItemObject | ReferenceObject>;
81
+ type ComponentsObject = Replace<OpenAPIV3_1.ComponentsObject, {
82
+ schemas?: Record<string, SchemaObject>;
83
+ responses?: Record<string, ReferenceObject | ResponseObject>;
84
+ parameters?: Record<string, ReferenceObject | ParameterObject>;
85
+ requestBodies?: Record<string, ReferenceObject | RequestBodyObject>;
86
+ headers?: Record<string, ReferenceObject | HeaderObject>;
87
+ links?: Record<string, ReferenceObject | LinkObject>;
88
+ callbacks?: Record<string, ReferenceObject | CallbackObject>;
89
+ pathItems?: Record<string, ReferenceObject | PathItemObject>;
90
+ }>;
91
+ type Document<T extends {} = {}> = Replace<OpenAPIV3_1.Document<T>, {
92
+ paths?: PathsObject<T>;
93
+ components?: ComponentsObject;
94
+ }>;
95
+ //# sourceMappingURL=types.d.ts.map
96
+ //#endregion
97
+ //#region src/generate.d.ts
30
98
  interface GenerateOptions {
31
99
  /**
32
100
  * The name of the exported router symbol.
@@ -38,16 +106,6 @@ interface GenerateOptions {
38
106
  /** Version string for the generated OpenAPI `info` object. */
39
107
  version?: string;
40
108
  }
41
- interface OpenAPIDocument {
42
- openapi: string;
43
- jsonSchemaDialect?: string;
44
- info: {
45
- title: string;
46
- version: string;
47
- };
48
- paths: Record<string, Record<string, unknown>>;
49
- components: Record<string, unknown>;
50
- }
51
109
  /**
52
110
  * Analyse the given TypeScript router file using the TypeScript compiler and
53
111
  * return an OpenAPI 3.1 document describing all query and mutation procedures.
@@ -56,8 +114,9 @@ interface OpenAPIDocument {
56
114
  * the AppRouter.
57
115
  * @param options - Optional generation settings (export name, title, version).
58
116
  */
59
- declare function generateOpenAPIDocument(routerFilePath: string, options?: GenerateOptions): Promise<OpenAPIDocument>;
117
+ declare function generateOpenAPIDocument(routerFilePath: string, options?: GenerateOptions): Promise<Document>;
60
118
  //# sourceMappingURL=generate.d.ts.map
119
+
61
120
  //#endregion
62
- export { GenerateOptions, JsonSchema, OpenAPIDocument, generateOpenAPIDocument };
121
+ export { GenerateOptions, types_d_exports as OpenAPIV3_1, generateOpenAPIDocument };
63
122
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/generate.ts"],"sourcesContent":[],"mappings":";;AAcA;;AAEyB,UAFR,UAAA,CAEQ;EAAU,IAAzB,CAAA,EAAA,MAAA;EAAM,KAEc,CAAA,EAFpB,MAEoB,CAAA,MAAA,EAFL,UAEK,CAAA;EAAU,IAAzB,CAAA,EAAA,MAAA,GAAA,MAAA,EAAA;EAAM,UAEX,CAAA,EAFK,MAEL,CAAA,MAAA,EAFoB,UAEpB,CAAA;EAAU,QACJ,CAAA,EAAA,MAAA,EAAA;EAAU,KAGhB,CAAA,EAJA,UAIA,GAAA,KAAA;EAAU,WACV,CAAA,EAJM,UAIN,EAAA;EAAU,KACV,CAAA,EAAA,MAAA,GAAA,MAAA,GAAA,OAAA,GAAA,IAAA;EAAU,IACZ,CAAA,EAAA,CAAA,MAAA,GAAA,MAAA,GAAA,OAAA,GAAA,IAAA,CAAA,EAAA;EAAU,KACO,CAAA,EAJf,UAIe,EAAA;EAAU,KACiB,CAAA,EAJ1C,UAI0C,EAAA;EAAM,KAAA,CAAA,EAHhD,UAGgD,EAAA;EAsBzC,GAAA,CAAA,EAxBT,UAwBS;EAYA,oBAAe,CAAA,EAnCP,UAmCO,GAAA,OAAA;EAAA,aAAA,CAAA,EAAA;IAIR,YAAA,EAAA,MAAA;IAAf,OAAA,CAAA,EAtC2C,MAsC3C,CAAA,MAAA,EAAA,MAAA,CAAA;EAAM,CAAA;EACK,MAAA,CAAA,EAAA,MAAA;EAqmCE,WAAA,CAAA,EAAA,MAAA;EAAuB,QAAA,CAAA,EAAA,MAAA;EAAA,QAElC,CAAA,EAAA,MAAA;EAAoB,OACpB,CAAA,EAAA,MAAA;;AAAD,UAznCO,eAAA,CAynCP;;;;;;;;;;;UA7mCO,eAAA;;;;;;;SAIR,eAAe;cACV;;;;;;;;;;iBAqmCQ,uBAAA,mCAEX,kBACR,QAAQ"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/generate.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,4 +1,6 @@
1
- import { __toESM, require_objectSpread2 } from "./objectSpread2-UxrN8MPM.mjs";
1
+ import { __toESM } from "./chunk-CJ2cON1m.mjs";
2
+ import { require_objectSpread2 } from "./objectSpread2-Blgb1OZh.mjs";
3
+ import * as fs from "node:fs";
2
4
  import * as path from "node:path";
3
5
  import * as ts from "typescript";
4
6
  import { pathToFileURL } from "node:url";
@@ -42,8 +44,7 @@ const wrapperDefTypes = new Set([
42
44
  "readonly",
43
45
  "pipe",
44
46
  "transform",
45
- "promise",
46
- "lazy"
47
+ "promise"
47
48
  ]);
48
49
  /**
49
50
  * Extract the wrapped inner schema from a wrapper def.
@@ -85,13 +86,22 @@ function extractZodDescriptions(schema) {
85
86
  }
86
87
  walkZodShape(schema, "", {
87
88
  registry,
88
- map
89
+ map,
90
+ seenLazy: /* @__PURE__ */ new Set()
89
91
  });
90
92
  if (map.properties.size > 0) hasAny = true;
91
93
  return hasAny ? map : null;
92
94
  }
93
95
  function walkZodShape(schema, prefix, ctx) {
94
96
  const unwrapped = unwrapZodSchema(schema);
97
+ const def = unwrapped._zod.def;
98
+ if (def.type === "lazy" && "getter" in def) {
99
+ if (ctx.seenLazy.has(unwrapped)) return;
100
+ ctx.seenLazy.add(unwrapped);
101
+ const inner = def.getter();
102
+ if (isZodSchema(inner)) walkZodShape(inner, prefix, ctx);
103
+ return;
104
+ }
95
105
  const element = zodArrayElement(unwrapped);
96
106
  if (element) {
97
107
  var _elemMeta$description;
@@ -192,35 +202,80 @@ function isProcedure(value) {
192
202
  * Overlay description strings from a `DescriptionMap` onto an existing
193
203
  * JSON schema produced by the TypeScript type checker. Mutates in place.
194
204
  */
195
- function applyDescriptions(schema, descs) {
205
+ function applyDescriptions(schema, descs, schemas) {
196
206
  if (descs.self) schema.description = descs.self;
197
- for (const [propPath, description] of descs.properties) setNestedDescription(schema, propPath.split("."), description);
207
+ for (const [propPath, description] of descs.properties) setNestedDescription({
208
+ schema,
209
+ pathParts: propPath.split("."),
210
+ description,
211
+ schemas
212
+ });
213
+ }
214
+ function resolveSchemaRef(schema, schemas) {
215
+ var _schemas$refName;
216
+ const ref = schema.$ref;
217
+ if (!ref) return schema;
218
+ if (!schemas || !ref.startsWith("#/components/schemas/")) return null;
219
+ const refName = ref.slice(21);
220
+ return refName ? (_schemas$refName = schemas[refName]) !== null && _schemas$refName !== void 0 ? _schemas$refName : null : null;
221
+ }
222
+ function getArrayItemsSchema(schema) {
223
+ const items = schema.items;
224
+ if (schema.type !== "array" || items == null || items === false) return null;
225
+ return items;
198
226
  }
199
- function setNestedDescription(schema, pathParts, description) {
200
- var _schema$properties;
227
+ function getPropertySchema(schema, propertyName) {
228
+ var _schema$properties$pr, _schema$properties;
229
+ return (_schema$properties$pr = (_schema$properties = schema.properties) === null || _schema$properties === void 0 ? void 0 : _schema$properties[propertyName]) !== null && _schema$properties$pr !== void 0 ? _schema$properties$pr : null;
230
+ }
231
+ function setLeafDescription(schema, description) {
232
+ if (schema.$ref) {
233
+ var _schema$allOf;
234
+ const ref = schema.$ref;
235
+ delete schema.$ref;
236
+ schema.allOf = [{ $ref: ref }, ...(_schema$allOf = schema.allOf) !== null && _schema$allOf !== void 0 ? _schema$allOf : []];
237
+ }
238
+ schema.description = description;
239
+ }
240
+ function setNestedDescription({ schema, pathParts, description, schemas }) {
201
241
  if (pathParts.length === 0) return;
202
242
  const [head, ...rest] = pathParts;
203
243
  if (!head) return;
204
244
  if (head === "[]") {
205
- const items = schema.type === "array" && schema.items && typeof schema.items === "object" ? schema.items : null;
245
+ const items = getArrayItemsSchema(schema);
206
246
  if (!items) return;
207
- if (rest.length === 0) items.description = description;
208
- else setNestedDescription(items, rest, description);
247
+ if (rest.length === 0) setLeafDescription(items, description);
248
+ else {
249
+ var _resolveSchemaRef;
250
+ const target = (_resolveSchemaRef = resolveSchemaRef(items, schemas)) !== null && _resolveSchemaRef !== void 0 ? _resolveSchemaRef : items;
251
+ setNestedDescription({
252
+ schema: target,
253
+ pathParts: rest,
254
+ description,
255
+ schemas
256
+ });
257
+ }
209
258
  return;
210
259
  }
211
- const propSchema = (_schema$properties = schema.properties) === null || _schema$properties === void 0 ? void 0 : _schema$properties[head];
212
- if (!propSchema || typeof propSchema !== "object") return;
213
- if (rest.length === 0) propSchema.description = description;
260
+ const propSchema = getPropertySchema(schema, head);
261
+ if (!propSchema) return;
262
+ if (rest.length === 0) setLeafDescription(propSchema, description);
214
263
  else {
215
- const target = propSchema.type === "array" && propSchema.items && typeof propSchema.items === "object" ? propSchema.items : propSchema;
216
- setNestedDescription(target, rest, description);
264
+ var _getArrayItemsSchema, _resolveSchemaRef2;
265
+ const target = (_getArrayItemsSchema = getArrayItemsSchema(propSchema)) !== null && _getArrayItemsSchema !== void 0 ? _getArrayItemsSchema : propSchema;
266
+ const resolvedTarget = (_resolveSchemaRef2 = resolveSchemaRef(target, schemas)) !== null && _resolveSchemaRef2 !== void 0 ? _resolveSchemaRef2 : target;
267
+ setNestedDescription({
268
+ schema: resolvedTarget,
269
+ pathParts: rest,
270
+ description,
271
+ schemas
272
+ });
217
273
  }
218
274
  }
219
275
 
220
276
  //#endregion
221
277
  //#region src/generate.ts
222
278
  var import_objectSpread2 = __toESM(require_objectSpread2(), 1);
223
- const log = console;
224
279
  const PRIMITIVE_FLAGS = ts.TypeFlags.String | ts.TypeFlags.Number | ts.TypeFlags.Boolean | ts.TypeFlags.StringLiteral | ts.TypeFlags.NumberLiteral | ts.TypeFlags.BooleanLiteral;
225
280
  function hasFlag(type, flag) {
226
281
  return (type.getFlags() & flag) !== 0;
@@ -252,6 +307,7 @@ const ANONYMOUS_NAMES = new Set([
252
307
  "Object",
253
308
  ""
254
309
  ]);
310
+ const INTERNAL_COMPUTED_PROPERTY_SYMBOL = /^__@.*@\d+$/;
255
311
  /** Try to determine a meaningful name for a TS type (type alias or interface). */
256
312
  function getTypeName(type) {
257
313
  var _type$aliasSymbol, _type$getSymbol;
@@ -261,6 +317,21 @@ function getTypeName(type) {
261
317
  if (symName && !ANONYMOUS_NAMES.has(symName) && !symName.startsWith("__")) return symName;
262
318
  return null;
263
319
  }
320
+ function shouldSkipPropertySymbol(prop) {
321
+ var _prop$declarations$so, _prop$declarations;
322
+ return (_prop$declarations$so = (_prop$declarations = prop.declarations) === null || _prop$declarations === void 0 ? void 0 : _prop$declarations.some((declaration) => {
323
+ const declarationName = ts.getNameOfDeclaration(declaration);
324
+ if (!declarationName || !ts.isComputedPropertyName(declarationName)) return false;
325
+ return INTERNAL_COMPUTED_PROPERTY_SYMBOL.test(prop.getName());
326
+ })) !== null && _prop$declarations$so !== void 0 ? _prop$declarations$so : false;
327
+ }
328
+ function getReferencedSchema(schema, schemas) {
329
+ var _schemas$refName;
330
+ const ref = schema === null || schema === void 0 ? void 0 : schema.$ref;
331
+ if (!(ref === null || ref === void 0 ? void 0 : ref.startsWith("#/components/schemas/"))) return schema;
332
+ const refName = ref.slice(21);
333
+ return refName ? (_schemas$refName = schemas[refName]) !== null && _schemas$refName !== void 0 ? _schemas$refName : null : schema;
334
+ }
264
335
  function ensureUniqueName(name, existing) {
265
336
  if (!(name in existing)) return name;
266
337
  let i = 2;
@@ -270,6 +341,9 @@ function ensureUniqueName(name, existing) {
270
341
  function schemaRef(name) {
271
342
  return { $ref: `#/components/schemas/${name}` };
272
343
  }
344
+ function isSelfSchemaRef(schema, name) {
345
+ return schema.$ref === schemaRef(name).$ref;
346
+ }
273
347
  function isNonEmptySchema(s) {
274
348
  for (const _ in s) return true;
275
349
  return false;
@@ -278,21 +352,28 @@ function isNonEmptySchema(s) {
278
352
  * Convert a TS type to a JSON Schema. If the type has been pre-registered
279
353
  * (or has a meaningful TS name), it is stored in `ctx.schemas` and a `$ref`
280
354
  * is returned instead of an inline schema.
355
+ *
356
+ * Named types (type aliases, interfaces) are auto-registered before conversion
357
+ * so that recursive references (including through unions and intersections)
358
+ * resolve to a `$ref` instead of causing infinite recursion.
281
359
  */
282
360
  function typeToJsonSchema(type, ctx, depth = 0) {
283
- if (depth > 20) {
284
- log.warn(`[openapi] Schema conversion reached maximum depth (20) for type "${ctx.checker.typeToString(type)}". The resulting schema will be incomplete.`);
285
- return {};
286
- }
287
- const refName = ctx.typeToRef.get(type);
288
- if (refName) {
289
- if (refName in ctx.schemas) return schemaRef(refName);
290
- ctx.schemas[refName] = {};
361
+ const existingRef = ctx.typeToRef.get(type);
362
+ if (existingRef) {
363
+ const storedSchema = ctx.schemas[existingRef];
364
+ if (storedSchema && (isNonEmptySchema(storedSchema) || ctx.visited.has(type))) return schemaRef(existingRef);
365
+ ctx.schemas[existingRef] = storedSchema !== null && storedSchema !== void 0 ? storedSchema : {};
291
366
  const schema$1 = convertTypeToSchema(type, ctx, depth);
292
- ctx.schemas[refName] = schema$1;
293
- return schemaRef(refName);
367
+ if (!isSelfSchemaRef(schema$1, existingRef)) ctx.schemas[existingRef] = schema$1;
368
+ return schemaRef(existingRef);
294
369
  }
295
370
  const schema = convertTypeToSchema(type, ctx, depth);
371
+ const postConvertRef = ctx.typeToRef.get(type);
372
+ if (postConvertRef) {
373
+ const stored = ctx.schemas[postConvertRef];
374
+ if (stored && !isNonEmptySchema(stored) && !isSelfSchemaRef(schema, postConvertRef)) ctx.schemas[postConvertRef] = schema;
375
+ return schemaRef(postConvertRef);
376
+ }
296
377
  if (!schema.description && !schema.$ref && type.aliasSymbol) {
297
378
  const aliasJsDoc = getJsDocComment(type.aliasSymbol, ctx.checker);
298
379
  if (aliasJsDoc) schema.description = aliasJsDoc;
@@ -509,6 +590,7 @@ function convertPlainObject(type, ctx, depth) {
509
590
  const properties = {};
510
591
  const required = [];
511
592
  for (const prop of typeProps) {
593
+ if (shouldSkipPropertySymbol(prop)) continue;
512
594
  const propType = checker.getTypeOfSymbol(prop);
513
595
  const propSchema = typeToJsonSchema(propType, ctx, depth + 1);
514
596
  const jsDoc = getJsDocComment(prop, checker);
@@ -542,8 +624,18 @@ function convertTypeToSchema(type, ctx, depth) {
542
624
  const flags = type.getFlags();
543
625
  const primitive = convertPrimitiveOrLiteral(type, flags, ctx.checker);
544
626
  if (primitive) return primitive;
545
- if (type.isUnion()) return convertUnionType(type, ctx, depth);
546
- if (type.isIntersection()) return convertIntersectionType(type, ctx, depth);
627
+ if (type.isUnion()) {
628
+ ctx.visited.add(type);
629
+ const result = convertUnionType(type, ctx, depth);
630
+ ctx.visited.delete(type);
631
+ return result;
632
+ }
633
+ if (type.isIntersection()) {
634
+ ctx.visited.add(type);
635
+ const result = convertIntersectionType(type, ctx, depth);
636
+ ctx.visited.delete(type);
637
+ return result;
638
+ }
547
639
  if (isObjectType(type)) return convertObjectType(type, ctx, depth);
548
640
  return {};
549
641
  }
@@ -566,7 +658,69 @@ function isVoidLikeInput(inputType) {
566
658
  const isUnionOfVoids = inputType.isUnion() && inputType.types.every((t) => hasFlag(t, ts.TypeFlags.Void | ts.TypeFlags.Undefined));
567
659
  return isUnionOfVoids;
568
660
  }
661
+ function shouldIncludeProcedureInOpenAPI(type) {
662
+ return type !== "subscription";
663
+ }
664
+ function getProcedureInputTypeName(type, path$1) {
665
+ const directName = getTypeName(type);
666
+ if (directName) return directName;
667
+ for (const sym of [type.aliasSymbol, type.getSymbol()].filter((candidate) => !!candidate)) {
668
+ var _sym$declarations;
669
+ for (const declaration of (_sym$declarations = sym.declarations) !== null && _sym$declarations !== void 0 ? _sym$declarations : []) {
670
+ var _ts$getNameOfDeclarat;
671
+ const declarationName = (_ts$getNameOfDeclarat = ts.getNameOfDeclaration(declaration)) === null || _ts$getNameOfDeclarat === void 0 ? void 0 : _ts$getNameOfDeclarat.getText();
672
+ if (declarationName && !ANONYMOUS_NAMES.has(declarationName) && !declarationName.startsWith("__")) return declarationName;
673
+ }
674
+ }
675
+ const fallbackName = path$1.split(".").filter(Boolean).map((segment) => segment.split(/[^A-Za-z0-9]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("")).join("");
676
+ return `${fallbackName || "Procedure"}Input`;
677
+ }
678
+ function isUnknownLikeType(type) {
679
+ return hasFlag(type, ts.TypeFlags.Unknown | ts.TypeFlags.Any);
680
+ }
681
+ function isCollapsedProcedureInputType(type) {
682
+ return isUnknownLikeType(type) || isObjectType(type) && type.getProperties().length === 0 && !type.getStringIndexType();
683
+ }
684
+ function recoverProcedureInputType(def, checker) {
685
+ var _def$symbol$declarati;
686
+ let initializer = null;
687
+ for (const declaration of (_def$symbol$declarati = def.symbol.declarations) !== null && _def$symbol$declarati !== void 0 ? _def$symbol$declarati : []) {
688
+ if (ts.isPropertyAssignment(declaration)) {
689
+ initializer = declaration.initializer;
690
+ break;
691
+ }
692
+ if (ts.isVariableDeclaration(declaration) && declaration.initializer) {
693
+ initializer = declaration.initializer;
694
+ break;
695
+ }
696
+ }
697
+ if (!initializer) return null;
698
+ let recovered = null;
699
+ const visit = (expr) => {
700
+ if (!ts.isCallExpression(expr)) return;
701
+ const callee = expr.expression;
702
+ if (!ts.isPropertyAccessExpression(callee)) return;
703
+ visit(callee.expression);
704
+ if (callee.name.text !== "input") return;
705
+ const [parserExpr] = expr.arguments;
706
+ if (!parserExpr) return;
707
+ const parserType = checker.getTypeAtLocation(parserExpr);
708
+ const standardSym = parserType.getProperty("~standard");
709
+ if (!standardSym) return;
710
+ const standardType = checker.getTypeOfSymbolAtLocation(standardSym, parserExpr);
711
+ const typesSym = standardType.getProperty("types");
712
+ if (!typesSym) return;
713
+ const typesType = checker.getNonNullableType(checker.getTypeOfSymbolAtLocation(typesSym, parserExpr));
714
+ const outputSym = typesType.getProperty("output");
715
+ if (!outputSym) return;
716
+ const outputType = checker.getTypeOfSymbolAtLocation(outputSym, parserExpr);
717
+ if (!isUnknownLikeType(outputType)) recovered = outputType;
718
+ };
719
+ visit(initializer);
720
+ return recovered;
721
+ }
569
722
  function extractProcedure(def, ctx) {
723
+ var _recoverProcedureInpu;
570
724
  const { schemaCtx } = ctx;
571
725
  const { checker } = schemaCtx;
572
726
  const $typesSym = def.defType.getProperty("$types");
@@ -576,12 +730,29 @@ function extractProcedure(def, ctx) {
576
730
  const outputSym = $typesType.getProperty("output");
577
731
  const inputType = inputSym ? checker.getTypeOfSymbol(inputSym) : null;
578
732
  const outputType = outputSym ? checker.getTypeOfSymbol(outputSym) : null;
579
- const inputSchema = !inputType || isVoidLikeInput(inputType) ? null : typeToJsonSchema(inputType, schemaCtx);
733
+ const resolvedInputType = inputType && isCollapsedProcedureInputType(inputType) ? (_recoverProcedureInpu = recoverProcedureInputType(def, checker)) !== null && _recoverProcedureInpu !== void 0 ? _recoverProcedureInpu : inputType : inputType;
734
+ let inputSchema = null;
735
+ if (!resolvedInputType || isVoidLikeInput(resolvedInputType)) {} else {
736
+ const ensureRecoveredInputRegistration = (type) => {
737
+ if (schemaCtx.typeToRef.has(type)) return;
738
+ const refName = ensureUniqueName(getProcedureInputTypeName(type, def.path), schemaCtx.schemas);
739
+ schemaCtx.typeToRef.set(type, refName);
740
+ schemaCtx.schemas[refName] = {};
741
+ };
742
+ if (resolvedInputType !== inputType) ensureRecoveredInputRegistration(resolvedInputType);
743
+ const initialSchema = typeToJsonSchema(resolvedInputType, schemaCtx);
744
+ if (!isNonEmptySchema(initialSchema) && !schemaCtx.typeToRef.has(resolvedInputType)) {
745
+ ensureRecoveredInputRegistration(resolvedInputType);
746
+ inputSchema = typeToJsonSchema(resolvedInputType, schemaCtx);
747
+ } else inputSchema = initialSchema;
748
+ }
580
749
  const outputSchema = outputType ? typeToJsonSchema(outputType, schemaCtx) : null;
581
750
  const runtimeDescs = ctx.runtimeDescriptions.get(def.path);
582
751
  if (runtimeDescs) {
583
- if (inputSchema && runtimeDescs.input) applyDescriptions(inputSchema, runtimeDescs.input);
584
- if (outputSchema && runtimeDescs.output) applyDescriptions(outputSchema, runtimeDescs.output);
752
+ const resolvedInputSchema = getReferencedSchema(inputSchema, schemaCtx.schemas);
753
+ const resolvedOutputSchema = getReferencedSchema(outputSchema, schemaCtx.schemas);
754
+ if (resolvedInputSchema && runtimeDescs.input) applyDescriptions(resolvedInputSchema, runtimeDescs.input, schemaCtx.schemas);
755
+ if (resolvedOutputSchema && runtimeDescs.output) applyDescriptions(resolvedOutputSchema, runtimeDescs.output, schemaCtx.schemas);
585
756
  }
586
757
  ctx.procedures.push({
587
758
  path: def.path,
@@ -593,13 +764,33 @@ function extractProcedure(def, ctx) {
593
764
  }
594
765
  /** Extract the JSDoc comment text from a symbol, if any. */
595
766
  function getJsDocComment(sym, checker) {
767
+ var _sym$declarations2;
768
+ const isWithinPath = (candidate, parent) => {
769
+ const rel = path.relative(parent, candidate);
770
+ return rel !== "" && !rel.startsWith("..") && !path.isAbsolute(rel);
771
+ };
772
+ const normalize = (filePath) => filePath.replace(/\\/g, "/");
773
+ const workspaceRoot = normalize(process.cwd());
774
+ const declarations = (_sym$declarations2 = sym.declarations) !== null && _sym$declarations2 !== void 0 ? _sym$declarations2 : [];
775
+ const isExternalNodeModulesDeclaration = declarations.length > 0 && declarations.every((declaration) => {
776
+ const sourceFile = declaration.getSourceFile();
777
+ if (!sourceFile.isDeclarationFile) return false;
778
+ const declarationPath = normalize(sourceFile.fileName);
779
+ if (!declarationPath.includes("/node_modules/")) return false;
780
+ try {
781
+ const realPath = normalize(fs.realpathSync.native(sourceFile.fileName));
782
+ if (isWithinPath(realPath, workspaceRoot) && !realPath.includes("/node_modules/")) return false;
783
+ } catch (_unused) {}
784
+ return true;
785
+ });
786
+ if (isExternalNodeModulesDeclaration) return void 0;
596
787
  const parts = sym.getDocumentationComment(checker);
597
788
  if (parts.length === 0) return void 0;
598
789
  const text = parts.map((p) => p.text).join("");
599
790
  return text || void 0;
600
791
  }
601
792
  function walkType(opts) {
602
- const { type, ctx, currentPath, description } = opts;
793
+ const { type, ctx, currentPath, description, symbol } = opts;
603
794
  if (ctx.seen.has(type)) return;
604
795
  const defSym = type.getProperty("_def");
605
796
  if (!defSym) {
@@ -614,11 +805,14 @@ function walkType(opts) {
614
805
  const defType = checker.getTypeOfSymbol(defSym);
615
806
  const procedureTypeName = getProcedureTypeName(defType, checker);
616
807
  if (procedureTypeName) {
808
+ var _ref;
809
+ if (!shouldIncludeProcedureInOpenAPI(procedureTypeName)) return;
617
810
  extractProcedure({
618
811
  defType,
619
812
  typeName: procedureTypeName,
620
813
  path: currentPath,
621
- description
814
+ description,
815
+ symbol: (_ref = symbol !== null && symbol !== void 0 ? symbol : type.getSymbol()) !== null && _ref !== void 0 ? _ref : defSym
622
816
  }, ctx);
623
817
  return;
624
818
  }
@@ -642,7 +836,8 @@ function walkRecord(recordType, ctx, prefix) {
642
836
  type: propType,
643
837
  ctx,
644
838
  currentPath: fullPath,
645
- description
839
+ description,
840
+ symbol: prop
646
841
  });
647
842
  }
648
843
  }
@@ -720,8 +915,9 @@ function wrapInSuccessEnvelope(outputSchema) {
720
915
  };
721
916
  }
722
917
  function buildProcedureOperation(proc, method) {
918
+ const [tag = proc.path] = proc.path.split(".");
723
919
  const operation = (0, import_objectSpread2.default)((0, import_objectSpread2.default)({ operationId: proc.path }, proc.description ? { description: proc.description } : {}), {}, {
724
- tags: [proc.path.split(".")[0]],
920
+ tags: [tag],
725
921
  responses: {
726
922
  "200": {
727
923
  description: "Successful response",
@@ -731,14 +927,14 @@ function buildProcedureOperation(proc, method) {
731
927
  }
732
928
  });
733
929
  if (proc.inputSchema === null) return operation;
734
- if (method === "get") operation["parameters"] = [{
930
+ if (method === "get") operation.parameters = [{
735
931
  name: "input",
736
932
  in: "query",
737
933
  required: true,
738
934
  style: "deepObject",
739
935
  content: { "application/json": { schema: proc.inputSchema } }
740
936
  }];
741
- else operation["requestBody"] = {
937
+ else operation.requestBody = {
742
938
  required: true,
743
939
  content: { "application/json": { schema: proc.inputSchema } }
744
940
  };
@@ -749,7 +945,7 @@ function buildOpenAPIDocument(procedures, options, meta = { errorSchema: null })
749
945
  const paths = {};
750
946
  for (const proc of procedures) {
751
947
  var _paths$opPath;
752
- if (proc.type === "subscription") continue;
948
+ if (!shouldIncludeProcedureInOpenAPI(proc.type)) continue;
753
949
  const opPath = `/${proc.path}`;
754
950
  const method = proc.type === "query" ? "get" : "post";
755
951
  const pathItem = (_paths$opPath = paths[opPath]) !== null && _paths$opPath !== void 0 ? _paths$opPath : {};
@@ -765,7 +961,7 @@ function buildOpenAPIDocument(procedures, options, meta = { errorSchema: null })
765
961
  version: (_options$version = options.version) !== null && _options$version !== void 0 ? _options$version : "0.0.0"
766
962
  },
767
963
  paths,
768
- components: (0, import_objectSpread2.default)((0, import_objectSpread2.default)({}, hasNamedSchemas ? { schemas: meta.schemas } : {}), {}, { responses: { Error: {
964
+ components: (0, import_objectSpread2.default)((0, import_objectSpread2.default)({}, hasNamedSchemas && meta.schemas ? { schemas: meta.schemas } : {}), {}, { responses: { Error: {
769
965
  description: "Error response",
770
966
  content: { "application/json": { schema: {
771
967
  type: "object",
@@ -831,5 +1027,9 @@ async function generateOpenAPIDocument(routerFilePath, options = {}) {
831
1027
  }
832
1028
 
833
1029
  //#endregion
834
- export { generateOpenAPIDocument };
1030
+ //#region src/types.ts
1031
+ var types_exports = {};
1032
+
1033
+ //#endregion
1034
+ export { types_exports as OpenAPIV3_1, generateOpenAPIDocument };
835
1035
  //# sourceMappingURL=index.mjs.map