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