@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/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/skills/openapi/SKILL.md +1 -1
- 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/README.md
CHANGED
|
@@ -50,9 +50,9 @@ npx @tanstack/intent@latest install
|
|
|
50
50
|
|
|
51
51
|
- [ ] SSE subscriptions
|
|
52
52
|
- [ ] non-json content types (might already work, needs tests)
|
|
53
|
-
- [ ] Improved handling of recursive/self-referencing types like trees/graphs - may be limited to 20 depth currently
|
|
54
53
|
- [ ] non-nodejs example
|
|
55
54
|
- [ ] an ai/mcp example
|
|
55
|
+
- [ ] investigate async generators support (types generate... poorly)
|
|
56
56
|
- [ ] Document breaking change detection via [oasdiff](https://github.com/oasdiff/oasdiff/blob/main/docs/BREAKING-CHANGES.md)
|
|
57
57
|
|
|
58
58
|
## Maybes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function() {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
};
|
|
11
|
+
var __export = (target, all) => {
|
|
12
|
+
for (var name in all) __defProp(target, name, {
|
|
13
|
+
get: all[name],
|
|
14
|
+
enumerable: true
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
var __copyProps = (to, from, except, desc) => {
|
|
18
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
19
|
+
key = keys[i];
|
|
20
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
21
|
+
get: ((k) => from[k]).bind(null, key),
|
|
22
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return to;
|
|
26
|
+
};
|
|
27
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
28
|
+
value: mod,
|
|
29
|
+
enumerable: true
|
|
30
|
+
}) : target, mod));
|
|
31
|
+
|
|
32
|
+
//#endregion
|
|
33
|
+
export { __commonJS, __export, __toESM };
|
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import * as fs$1 from "node:fs";
|
|
2
3
|
import * as fs from "node:fs";
|
|
3
4
|
import * as path$1 from "node:path";
|
|
4
5
|
import * as path from "node:path";
|
|
@@ -45,8 +46,7 @@ const wrapperDefTypes = new Set([
|
|
|
45
46
|
"readonly",
|
|
46
47
|
"pipe",
|
|
47
48
|
"transform",
|
|
48
|
-
"promise"
|
|
49
|
-
"lazy"
|
|
49
|
+
"promise"
|
|
50
50
|
]);
|
|
51
51
|
/**
|
|
52
52
|
* Extract the wrapped inner schema from a wrapper def.
|
|
@@ -88,13 +88,22 @@ function extractZodDescriptions(schema) {
|
|
|
88
88
|
}
|
|
89
89
|
walkZodShape(schema, "", {
|
|
90
90
|
registry,
|
|
91
|
-
map
|
|
91
|
+
map,
|
|
92
|
+
seenLazy: /* @__PURE__ */ new Set()
|
|
92
93
|
});
|
|
93
94
|
if (map.properties.size > 0) hasAny = true;
|
|
94
95
|
return hasAny ? map : null;
|
|
95
96
|
}
|
|
96
97
|
function walkZodShape(schema, prefix, ctx) {
|
|
97
98
|
const unwrapped = unwrapZodSchema(schema);
|
|
99
|
+
const def = unwrapped._zod.def;
|
|
100
|
+
if (def.type === "lazy" && "getter" in def) {
|
|
101
|
+
if (ctx.seenLazy.has(unwrapped)) return;
|
|
102
|
+
ctx.seenLazy.add(unwrapped);
|
|
103
|
+
const inner = def.getter();
|
|
104
|
+
if (isZodSchema(inner)) walkZodShape(inner, prefix, ctx);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
98
107
|
const element = zodArrayElement(unwrapped);
|
|
99
108
|
if (element) {
|
|
100
109
|
const unwrappedElement = unwrapZodSchema(element);
|
|
@@ -192,33 +201,74 @@ 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
|
+
const ref = schema.$ref;
|
|
215
|
+
if (!ref) return schema;
|
|
216
|
+
if (!schemas || !ref.startsWith("#/components/schemas/")) return null;
|
|
217
|
+
const refName = ref.slice(21);
|
|
218
|
+
return refName ? schemas[refName] ?? null : null;
|
|
219
|
+
}
|
|
220
|
+
function getArrayItemsSchema(schema) {
|
|
221
|
+
const items = schema.items;
|
|
222
|
+
if (schema.type !== "array" || items == null || items === false) return null;
|
|
223
|
+
return items;
|
|
198
224
|
}
|
|
199
|
-
function
|
|
225
|
+
function getPropertySchema(schema, propertyName) {
|
|
226
|
+
return schema.properties?.[propertyName] ?? null;
|
|
227
|
+
}
|
|
228
|
+
function setLeafDescription(schema, description) {
|
|
229
|
+
if (schema.$ref) {
|
|
230
|
+
const ref = schema.$ref;
|
|
231
|
+
delete schema.$ref;
|
|
232
|
+
schema.allOf = [{ $ref: ref }, ...schema.allOf ?? []];
|
|
233
|
+
}
|
|
234
|
+
schema.description = description;
|
|
235
|
+
}
|
|
236
|
+
function setNestedDescription({ schema, pathParts, description, schemas }) {
|
|
200
237
|
if (pathParts.length === 0) return;
|
|
201
238
|
const [head, ...rest] = pathParts;
|
|
202
239
|
if (!head) return;
|
|
203
240
|
if (head === "[]") {
|
|
204
|
-
const items = schema
|
|
241
|
+
const items = getArrayItemsSchema(schema);
|
|
205
242
|
if (!items) return;
|
|
206
|
-
if (rest.length === 0) items
|
|
207
|
-
else
|
|
243
|
+
if (rest.length === 0) setLeafDescription(items, description);
|
|
244
|
+
else {
|
|
245
|
+
const target = resolveSchemaRef(items, schemas) ?? items;
|
|
246
|
+
setNestedDescription({
|
|
247
|
+
schema: target,
|
|
248
|
+
pathParts: rest,
|
|
249
|
+
description,
|
|
250
|
+
schemas
|
|
251
|
+
});
|
|
252
|
+
}
|
|
208
253
|
return;
|
|
209
254
|
}
|
|
210
|
-
const propSchema = schema
|
|
211
|
-
if (!propSchema
|
|
212
|
-
if (rest.length === 0) propSchema
|
|
255
|
+
const propSchema = getPropertySchema(schema, head);
|
|
256
|
+
if (!propSchema) return;
|
|
257
|
+
if (rest.length === 0) setLeafDescription(propSchema, description);
|
|
213
258
|
else {
|
|
214
|
-
const target = propSchema
|
|
215
|
-
|
|
259
|
+
const target = getArrayItemsSchema(propSchema) ?? propSchema;
|
|
260
|
+
const resolvedTarget = resolveSchemaRef(target, schemas) ?? target;
|
|
261
|
+
setNestedDescription({
|
|
262
|
+
schema: resolvedTarget,
|
|
263
|
+
pathParts: rest,
|
|
264
|
+
description,
|
|
265
|
+
schemas
|
|
266
|
+
});
|
|
216
267
|
}
|
|
217
268
|
}
|
|
218
269
|
|
|
219
270
|
//#endregion
|
|
220
271
|
//#region src/generate.ts
|
|
221
|
-
const log = console;
|
|
222
272
|
const PRIMITIVE_FLAGS = ts.TypeFlags.String | ts.TypeFlags.Number | ts.TypeFlags.Boolean | ts.TypeFlags.StringLiteral | ts.TypeFlags.NumberLiteral | ts.TypeFlags.BooleanLiteral;
|
|
223
273
|
function hasFlag(type, flag) {
|
|
224
274
|
return (type.getFlags() & flag) !== 0;
|
|
@@ -250,6 +300,7 @@ const ANONYMOUS_NAMES = new Set([
|
|
|
250
300
|
"Object",
|
|
251
301
|
""
|
|
252
302
|
]);
|
|
303
|
+
const INTERNAL_COMPUTED_PROPERTY_SYMBOL = /^__@.*@\d+$/;
|
|
253
304
|
/** Try to determine a meaningful name for a TS type (type alias or interface). */
|
|
254
305
|
function getTypeName(type) {
|
|
255
306
|
const aliasName = type.aliasSymbol?.getName();
|
|
@@ -258,6 +309,19 @@ function getTypeName(type) {
|
|
|
258
309
|
if (symName && !ANONYMOUS_NAMES.has(symName) && !symName.startsWith("__")) return symName;
|
|
259
310
|
return null;
|
|
260
311
|
}
|
|
312
|
+
function shouldSkipPropertySymbol(prop) {
|
|
313
|
+
return prop.declarations?.some((declaration) => {
|
|
314
|
+
const declarationName = ts.getNameOfDeclaration(declaration);
|
|
315
|
+
if (!declarationName || !ts.isComputedPropertyName(declarationName)) return false;
|
|
316
|
+
return INTERNAL_COMPUTED_PROPERTY_SYMBOL.test(prop.getName());
|
|
317
|
+
}) ?? false;
|
|
318
|
+
}
|
|
319
|
+
function getReferencedSchema(schema, schemas) {
|
|
320
|
+
const ref = schema?.$ref;
|
|
321
|
+
if (!ref?.startsWith("#/components/schemas/")) return schema;
|
|
322
|
+
const refName = ref.slice(21);
|
|
323
|
+
return refName ? schemas[refName] ?? null : schema;
|
|
324
|
+
}
|
|
261
325
|
function ensureUniqueName(name, existing) {
|
|
262
326
|
if (!(name in existing)) return name;
|
|
263
327
|
let i = 2;
|
|
@@ -267,6 +331,9 @@ function ensureUniqueName(name, existing) {
|
|
|
267
331
|
function schemaRef(name) {
|
|
268
332
|
return { $ref: `#/components/schemas/${name}` };
|
|
269
333
|
}
|
|
334
|
+
function isSelfSchemaRef(schema, name) {
|
|
335
|
+
return schema.$ref === schemaRef(name).$ref;
|
|
336
|
+
}
|
|
270
337
|
function isNonEmptySchema(s) {
|
|
271
338
|
for (const _ in s) return true;
|
|
272
339
|
return false;
|
|
@@ -275,21 +342,28 @@ function isNonEmptySchema(s) {
|
|
|
275
342
|
* Convert a TS type to a JSON Schema. If the type has been pre-registered
|
|
276
343
|
* (or has a meaningful TS name), it is stored in `ctx.schemas` and a `$ref`
|
|
277
344
|
* is returned instead of an inline schema.
|
|
345
|
+
*
|
|
346
|
+
* Named types (type aliases, interfaces) are auto-registered before conversion
|
|
347
|
+
* so that recursive references (including through unions and intersections)
|
|
348
|
+
* resolve to a `$ref` instead of causing infinite recursion.
|
|
278
349
|
*/
|
|
279
350
|
function typeToJsonSchema(type, ctx, depth = 0) {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
if (refName) {
|
|
286
|
-
if (refName in ctx.schemas) return schemaRef(refName);
|
|
287
|
-
ctx.schemas[refName] = {};
|
|
351
|
+
const existingRef = ctx.typeToRef.get(type);
|
|
352
|
+
if (existingRef) {
|
|
353
|
+
const storedSchema = ctx.schemas[existingRef];
|
|
354
|
+
if (storedSchema && (isNonEmptySchema(storedSchema) || ctx.visited.has(type))) return schemaRef(existingRef);
|
|
355
|
+
ctx.schemas[existingRef] = storedSchema ?? {};
|
|
288
356
|
const schema$1 = convertTypeToSchema(type, ctx, depth);
|
|
289
|
-
ctx.schemas[
|
|
290
|
-
return schemaRef(
|
|
357
|
+
if (!isSelfSchemaRef(schema$1, existingRef)) ctx.schemas[existingRef] = schema$1;
|
|
358
|
+
return schemaRef(existingRef);
|
|
291
359
|
}
|
|
292
360
|
const schema = convertTypeToSchema(type, ctx, depth);
|
|
361
|
+
const postConvertRef = ctx.typeToRef.get(type);
|
|
362
|
+
if (postConvertRef) {
|
|
363
|
+
const stored = ctx.schemas[postConvertRef];
|
|
364
|
+
if (stored && !isNonEmptySchema(stored) && !isSelfSchemaRef(schema, postConvertRef)) ctx.schemas[postConvertRef] = schema;
|
|
365
|
+
return schemaRef(postConvertRef);
|
|
366
|
+
}
|
|
293
367
|
if (!schema.description && !schema.$ref && type.aliasSymbol) {
|
|
294
368
|
const aliasJsDoc = getJsDocComment(type.aliasSymbol, ctx.checker);
|
|
295
369
|
if (aliasJsDoc) schema.description = aliasJsDoc;
|
|
@@ -502,6 +576,7 @@ function convertPlainObject(type, ctx, depth) {
|
|
|
502
576
|
const properties = {};
|
|
503
577
|
const required = [];
|
|
504
578
|
for (const prop of typeProps) {
|
|
579
|
+
if (shouldSkipPropertySymbol(prop)) continue;
|
|
505
580
|
const propType = checker.getTypeOfSymbol(prop);
|
|
506
581
|
const propSchema = typeToJsonSchema(propType, ctx, depth + 1);
|
|
507
582
|
const jsDoc = getJsDocComment(prop, checker);
|
|
@@ -535,8 +610,18 @@ function convertTypeToSchema(type, ctx, depth) {
|
|
|
535
610
|
const flags = type.getFlags();
|
|
536
611
|
const primitive = convertPrimitiveOrLiteral(type, flags, ctx.checker);
|
|
537
612
|
if (primitive) return primitive;
|
|
538
|
-
if (type.isUnion())
|
|
539
|
-
|
|
613
|
+
if (type.isUnion()) {
|
|
614
|
+
ctx.visited.add(type);
|
|
615
|
+
const result = convertUnionType(type, ctx, depth);
|
|
616
|
+
ctx.visited.delete(type);
|
|
617
|
+
return result;
|
|
618
|
+
}
|
|
619
|
+
if (type.isIntersection()) {
|
|
620
|
+
ctx.visited.add(type);
|
|
621
|
+
const result = convertIntersectionType(type, ctx, depth);
|
|
622
|
+
ctx.visited.delete(type);
|
|
623
|
+
return result;
|
|
624
|
+
}
|
|
540
625
|
if (isObjectType(type)) return convertObjectType(type, ctx, depth);
|
|
541
626
|
return {};
|
|
542
627
|
}
|
|
@@ -559,6 +644,62 @@ function isVoidLikeInput(inputType) {
|
|
|
559
644
|
const isUnionOfVoids = inputType.isUnion() && inputType.types.every((t) => hasFlag(t, ts.TypeFlags.Void | ts.TypeFlags.Undefined));
|
|
560
645
|
return isUnionOfVoids;
|
|
561
646
|
}
|
|
647
|
+
function shouldIncludeProcedureInOpenAPI(type) {
|
|
648
|
+
return type !== "subscription";
|
|
649
|
+
}
|
|
650
|
+
function getProcedureInputTypeName(type, path$2) {
|
|
651
|
+
const directName = getTypeName(type);
|
|
652
|
+
if (directName) return directName;
|
|
653
|
+
for (const sym of [type.aliasSymbol, type.getSymbol()].filter((candidate) => !!candidate)) for (const declaration of sym.declarations ?? []) {
|
|
654
|
+
const declarationName = ts.getNameOfDeclaration(declaration)?.getText();
|
|
655
|
+
if (declarationName && !ANONYMOUS_NAMES.has(declarationName) && !declarationName.startsWith("__")) return declarationName;
|
|
656
|
+
}
|
|
657
|
+
const fallbackName = path$2.split(".").filter(Boolean).map((segment) => segment.split(/[^A-Za-z0-9]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("")).join("");
|
|
658
|
+
return `${fallbackName || "Procedure"}Input`;
|
|
659
|
+
}
|
|
660
|
+
function isUnknownLikeType(type) {
|
|
661
|
+
return hasFlag(type, ts.TypeFlags.Unknown | ts.TypeFlags.Any);
|
|
662
|
+
}
|
|
663
|
+
function isCollapsedProcedureInputType(type) {
|
|
664
|
+
return isUnknownLikeType(type) || isObjectType(type) && type.getProperties().length === 0 && !type.getStringIndexType();
|
|
665
|
+
}
|
|
666
|
+
function recoverProcedureInputType(def, checker) {
|
|
667
|
+
let initializer = null;
|
|
668
|
+
for (const declaration of def.symbol.declarations ?? []) {
|
|
669
|
+
if (ts.isPropertyAssignment(declaration)) {
|
|
670
|
+
initializer = declaration.initializer;
|
|
671
|
+
break;
|
|
672
|
+
}
|
|
673
|
+
if (ts.isVariableDeclaration(declaration) && declaration.initializer) {
|
|
674
|
+
initializer = declaration.initializer;
|
|
675
|
+
break;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
if (!initializer) return null;
|
|
679
|
+
let recovered = null;
|
|
680
|
+
const visit = (expr) => {
|
|
681
|
+
if (!ts.isCallExpression(expr)) return;
|
|
682
|
+
const callee = expr.expression;
|
|
683
|
+
if (!ts.isPropertyAccessExpression(callee)) return;
|
|
684
|
+
visit(callee.expression);
|
|
685
|
+
if (callee.name.text !== "input") return;
|
|
686
|
+
const [parserExpr] = expr.arguments;
|
|
687
|
+
if (!parserExpr) return;
|
|
688
|
+
const parserType = checker.getTypeAtLocation(parserExpr);
|
|
689
|
+
const standardSym = parserType.getProperty("~standard");
|
|
690
|
+
if (!standardSym) return;
|
|
691
|
+
const standardType = checker.getTypeOfSymbolAtLocation(standardSym, parserExpr);
|
|
692
|
+
const typesSym = standardType.getProperty("types");
|
|
693
|
+
if (!typesSym) return;
|
|
694
|
+
const typesType = checker.getNonNullableType(checker.getTypeOfSymbolAtLocation(typesSym, parserExpr));
|
|
695
|
+
const outputSym = typesType.getProperty("output");
|
|
696
|
+
if (!outputSym) return;
|
|
697
|
+
const outputType = checker.getTypeOfSymbolAtLocation(outputSym, parserExpr);
|
|
698
|
+
if (!isUnknownLikeType(outputType)) recovered = outputType;
|
|
699
|
+
};
|
|
700
|
+
visit(initializer);
|
|
701
|
+
return recovered;
|
|
702
|
+
}
|
|
562
703
|
function extractProcedure(def, ctx) {
|
|
563
704
|
const { schemaCtx } = ctx;
|
|
564
705
|
const { checker } = schemaCtx;
|
|
@@ -569,12 +710,29 @@ function extractProcedure(def, ctx) {
|
|
|
569
710
|
const outputSym = $typesType.getProperty("output");
|
|
570
711
|
const inputType = inputSym ? checker.getTypeOfSymbol(inputSym) : null;
|
|
571
712
|
const outputType = outputSym ? checker.getTypeOfSymbol(outputSym) : null;
|
|
572
|
-
const
|
|
713
|
+
const resolvedInputType = inputType && isCollapsedProcedureInputType(inputType) ? recoverProcedureInputType(def, checker) ?? inputType : inputType;
|
|
714
|
+
let inputSchema = null;
|
|
715
|
+
if (!resolvedInputType || isVoidLikeInput(resolvedInputType)) {} else {
|
|
716
|
+
const ensureRecoveredInputRegistration = (type) => {
|
|
717
|
+
if (schemaCtx.typeToRef.has(type)) return;
|
|
718
|
+
const refName = ensureUniqueName(getProcedureInputTypeName(type, def.path), schemaCtx.schemas);
|
|
719
|
+
schemaCtx.typeToRef.set(type, refName);
|
|
720
|
+
schemaCtx.schemas[refName] = {};
|
|
721
|
+
};
|
|
722
|
+
if (resolvedInputType !== inputType) ensureRecoveredInputRegistration(resolvedInputType);
|
|
723
|
+
const initialSchema = typeToJsonSchema(resolvedInputType, schemaCtx);
|
|
724
|
+
if (!isNonEmptySchema(initialSchema) && !schemaCtx.typeToRef.has(resolvedInputType)) {
|
|
725
|
+
ensureRecoveredInputRegistration(resolvedInputType);
|
|
726
|
+
inputSchema = typeToJsonSchema(resolvedInputType, schemaCtx);
|
|
727
|
+
} else inputSchema = initialSchema;
|
|
728
|
+
}
|
|
573
729
|
const outputSchema = outputType ? typeToJsonSchema(outputType, schemaCtx) : null;
|
|
574
730
|
const runtimeDescs = ctx.runtimeDescriptions.get(def.path);
|
|
575
731
|
if (runtimeDescs) {
|
|
576
|
-
|
|
577
|
-
|
|
732
|
+
const resolvedInputSchema = getReferencedSchema(inputSchema, schemaCtx.schemas);
|
|
733
|
+
const resolvedOutputSchema = getReferencedSchema(outputSchema, schemaCtx.schemas);
|
|
734
|
+
if (resolvedInputSchema && runtimeDescs.input) applyDescriptions(resolvedInputSchema, runtimeDescs.input, schemaCtx.schemas);
|
|
735
|
+
if (resolvedOutputSchema && runtimeDescs.output) applyDescriptions(resolvedOutputSchema, runtimeDescs.output, schemaCtx.schemas);
|
|
578
736
|
}
|
|
579
737
|
ctx.procedures.push({
|
|
580
738
|
path: def.path,
|
|
@@ -586,13 +744,32 @@ function extractProcedure(def, ctx) {
|
|
|
586
744
|
}
|
|
587
745
|
/** Extract the JSDoc comment text from a symbol, if any. */
|
|
588
746
|
function getJsDocComment(sym, checker) {
|
|
747
|
+
const isWithinPath = (candidate, parent) => {
|
|
748
|
+
const rel = path$1.relative(parent, candidate);
|
|
749
|
+
return rel !== "" && !rel.startsWith("..") && !path$1.isAbsolute(rel);
|
|
750
|
+
};
|
|
751
|
+
const normalize = (filePath) => filePath.replace(/\\/g, "/");
|
|
752
|
+
const workspaceRoot = normalize(process.cwd());
|
|
753
|
+
const declarations = sym.declarations ?? [];
|
|
754
|
+
const isExternalNodeModulesDeclaration = declarations.length > 0 && declarations.every((declaration) => {
|
|
755
|
+
const sourceFile = declaration.getSourceFile();
|
|
756
|
+
if (!sourceFile.isDeclarationFile) return false;
|
|
757
|
+
const declarationPath = normalize(sourceFile.fileName);
|
|
758
|
+
if (!declarationPath.includes("/node_modules/")) return false;
|
|
759
|
+
try {
|
|
760
|
+
const realPath = normalize(fs$1.realpathSync.native(sourceFile.fileName));
|
|
761
|
+
if (isWithinPath(realPath, workspaceRoot) && !realPath.includes("/node_modules/")) return false;
|
|
762
|
+
} catch {}
|
|
763
|
+
return true;
|
|
764
|
+
});
|
|
765
|
+
if (isExternalNodeModulesDeclaration) return void 0;
|
|
589
766
|
const parts = sym.getDocumentationComment(checker);
|
|
590
767
|
if (parts.length === 0) return void 0;
|
|
591
768
|
const text = parts.map((p) => p.text).join("");
|
|
592
769
|
return text || void 0;
|
|
593
770
|
}
|
|
594
771
|
function walkType(opts) {
|
|
595
|
-
const { type, ctx, currentPath, description } = opts;
|
|
772
|
+
const { type, ctx, currentPath, description, symbol } = opts;
|
|
596
773
|
if (ctx.seen.has(type)) return;
|
|
597
774
|
const defSym = type.getProperty("_def");
|
|
598
775
|
if (!defSym) {
|
|
@@ -607,11 +784,13 @@ function walkType(opts) {
|
|
|
607
784
|
const defType = checker.getTypeOfSymbol(defSym);
|
|
608
785
|
const procedureTypeName = getProcedureTypeName(defType, checker);
|
|
609
786
|
if (procedureTypeName) {
|
|
787
|
+
if (!shouldIncludeProcedureInOpenAPI(procedureTypeName)) return;
|
|
610
788
|
extractProcedure({
|
|
611
789
|
defType,
|
|
612
790
|
typeName: procedureTypeName,
|
|
613
791
|
path: currentPath,
|
|
614
|
-
description
|
|
792
|
+
description,
|
|
793
|
+
symbol: symbol ?? type.getSymbol() ?? defSym
|
|
615
794
|
}, ctx);
|
|
616
795
|
return;
|
|
617
796
|
}
|
|
@@ -635,7 +814,8 @@ function walkRecord(recordType, ctx, prefix) {
|
|
|
635
814
|
type: propType,
|
|
636
815
|
ctx,
|
|
637
816
|
currentPath: fullPath,
|
|
638
|
-
description
|
|
817
|
+
description,
|
|
818
|
+
symbol: prop
|
|
639
819
|
});
|
|
640
820
|
}
|
|
641
821
|
}
|
|
@@ -717,10 +897,11 @@ function wrapInSuccessEnvelope(outputSchema) {
|
|
|
717
897
|
};
|
|
718
898
|
}
|
|
719
899
|
function buildProcedureOperation(proc, method) {
|
|
900
|
+
const [tag = proc.path] = proc.path.split(".");
|
|
720
901
|
const operation = {
|
|
721
902
|
operationId: proc.path,
|
|
722
903
|
...proc.description ? { description: proc.description } : {},
|
|
723
|
-
tags: [
|
|
904
|
+
tags: [tag],
|
|
724
905
|
responses: {
|
|
725
906
|
"200": {
|
|
726
907
|
description: "Successful response",
|
|
@@ -730,14 +911,14 @@ function buildProcedureOperation(proc, method) {
|
|
|
730
911
|
}
|
|
731
912
|
};
|
|
732
913
|
if (proc.inputSchema === null) return operation;
|
|
733
|
-
if (method === "get") operation
|
|
914
|
+
if (method === "get") operation.parameters = [{
|
|
734
915
|
name: "input",
|
|
735
916
|
in: "query",
|
|
736
917
|
required: true,
|
|
737
918
|
style: "deepObject",
|
|
738
919
|
content: { "application/json": { schema: proc.inputSchema } }
|
|
739
920
|
}];
|
|
740
|
-
else operation
|
|
921
|
+
else operation.requestBody = {
|
|
741
922
|
required: true,
|
|
742
923
|
content: { "application/json": { schema: proc.inputSchema } }
|
|
743
924
|
};
|
|
@@ -746,7 +927,7 @@ function buildProcedureOperation(proc, method) {
|
|
|
746
927
|
function buildOpenAPIDocument(procedures, options, meta = { errorSchema: null }) {
|
|
747
928
|
const paths = {};
|
|
748
929
|
for (const proc of procedures) {
|
|
749
|
-
if (proc.type
|
|
930
|
+
if (!shouldIncludeProcedureInOpenAPI(proc.type)) continue;
|
|
750
931
|
const opPath = `/${proc.path}`;
|
|
751
932
|
const method = proc.type === "query" ? "get" : "post";
|
|
752
933
|
const pathItem = paths[opPath] ?? {};
|
|
@@ -763,7 +944,7 @@ function buildOpenAPIDocument(procedures, options, meta = { errorSchema: null })
|
|
|
763
944
|
},
|
|
764
945
|
paths,
|
|
765
946
|
components: {
|
|
766
|
-
...hasNamedSchemas ? { schemas: meta.schemas } : {},
|
|
947
|
+
...hasNamedSchemas && meta.schemas ? { schemas: meta.schemas } : {},
|
|
767
948
|
responses: { Error: {
|
|
768
949
|
description: "Error response",
|
|
769
950
|
content: { "application/json": { schema: {
|
package/dist/heyapi/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { __commonJS, __toESM
|
|
1
|
+
import { __commonJS, __toESM } from "../chunk-CJ2cON1m.mjs";
|
|
2
|
+
import { require_objectSpread2 } from "../objectSpread2-Blgb1OZh.mjs";
|
|
2
3
|
|
|
3
4
|
//#region ../../node_modules/.pnpm/@oxc-project+runtime@0.72.2/node_modules/@oxc-project/runtime/src/helpers/objectWithoutPropertiesLoose.js
|
|
4
5
|
var require_objectWithoutPropertiesLoose = __commonJS({ "../../node_modules/.pnpm/@oxc-project+runtime@0.72.2/node_modules/@oxc-project/runtime/src/helpers/objectWithoutPropertiesLoose.js"(exports, module) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["_objectWithoutProperties","transformer: DataTransformerOptions","opts?: TRPCHeyApiClientOptions","query: Record<string, unknown>","body: unknown","data: unknown","transformerOpts: DataTransformerOptions","error: unknown","client: HeyApiFetchClient","opts: TRPCHeyApiClientOptions &\n Omit<HeyApiConfig, keyof TRPCHeyApiClientConfig>"],"sources":["../../../../node_modules/.pnpm/@oxc-project+runtime@0.72.2/node_modules/@oxc-project/runtime/src/helpers/objectWithoutPropertiesLoose.js","../../../../node_modules/.pnpm/@oxc-project+runtime@0.72.2/node_modules/@oxc-project/runtime/src/helpers/objectWithoutProperties.js","../../src/heyapi/index.ts"],"sourcesContent":["function _objectWithoutPropertiesLoose(r, e) {\n if (null == r) return {};\n var t = {};\n for (var n in r) if ({}.hasOwnProperty.call(r, n)) {\n if (e.includes(n)) continue;\n t[n] = r[n];\n }\n return t;\n}\nmodule.exports = _objectWithoutPropertiesLoose, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var objectWithoutPropertiesLoose = require(\"./objectWithoutPropertiesLoose.js\");\nfunction _objectWithoutProperties(e, t) {\n if (null == e) return {};\n var o,\n r,\n i = objectWithoutPropertiesLoose(e, t);\n if (Object.getOwnPropertySymbols) {\n var s = Object.getOwnPropertySymbols(e);\n for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);\n }\n return i;\n}\nmodule.exports = _objectWithoutProperties, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","import type {\n FetchClient as HeyApiFetchClient,\n UserConfig,\n} from '@hey-api/openapi-ts';\nimport type {\n TRPCCombinedDataTransformer,\n TRPCDataTransformer,\n} from '@trpc/server';\n\nexport type DataTransformerOptions =\n | TRPCDataTransformer\n | TRPCCombinedDataTransformer;\n\ntype HeyAPIResolvers = Exclude<\n Extract<\n Exclude<UserConfig['plugins'], undefined | string>[number],\n { name: '@hey-api/typescript' }\n >['~resolvers'],\n undefined\n>;\n\nfunction resolveTransformer(\n transformer: DataTransformerOptions,\n): TRPCCombinedDataTransformer {\n if ('input' in transformer) {\n return transformer;\n }\n return { input: transformer, output: transformer };\n}\n\nexport interface TRPCHeyApiClientOptions {\n transformer?: DataTransformerOptions;\n}\n\nexport type HeyApiConfig = ReturnType<HeyApiFetchClient['getConfig']>;\nexport type TRPCHeyApiClientConfig = Required<\n Pick<HeyApiConfig, 'querySerializer'>\n> &\n Pick<HeyApiConfig, 'bodySerializer' | 'responseTransformer'>;\n\n/**\n * Returns the `~resolvers` object for the `@hey-api/typescript` plugin.\n *\n * Maps `date` and `date-time` string formats to `Date` so that the\n * generated SDK uses `Date` instead of `string` for those fields.\n *\n * @example\n * ```ts\n * import { createClient } from '@hey-api/openapi-ts';\n * import { createTRPCHeyApiTypeResolvers } from '@trpc/openapi/heyapi';\n *\n * await createClient({\n * plugins: [\n * { name: '@hey-api/typescript', '~resolvers': createTRPCHeyApiTypeResolvers() },\n * ],\n * });\n * ```\n */\nexport function createTRPCHeyApiTypeResolvers(): HeyAPIResolvers {\n return {\n string(ctx) {\n if (ctx.schema.format === 'date-time' || ctx.schema.format === 'date') {\n return ctx.$.type('Date');\n }\n return undefined;\n },\n number(ctx) {\n if (ctx.schema.format === 'bigint') {\n return ctx.$.type('bigint');\n }\n return undefined;\n },\n };\n}\n\n/**\n * @internal - Prefer `configureTRPCHeyApiClient`\n */\nexport function createTRPCHeyApiClientConfig(opts?: TRPCHeyApiClientOptions) {\n const transformer = opts?.transformer\n ? resolveTransformer(opts.transformer)\n : undefined;\n\n return {\n querySerializer: (query: Record<string, unknown>) => {\n const params = new URLSearchParams();\n\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined) {\n continue;\n }\n\n if (key === 'input' && transformer) {\n params.append(\n key,\n JSON.stringify(transformer.input.serialize(value)),\n );\n } else {\n params.append(key, JSON.stringify(value));\n }\n }\n\n return params.toString();\n },\n\n ...(transformer && {\n bodySerializer: (body: unknown) => {\n return JSON.stringify(transformer.input.serialize(body));\n },\n\n responseTransformer: async (data: unknown) => {\n if (!!data && typeof data === 'object' && 'result' in data) {\n const result = (data as any).result;\n if (!result.type || result.type === 'data') {\n result.data = transformer.output.deserialize(result.data);\n }\n }\n\n return data;\n },\n }),\n } as const satisfies TRPCHeyApiClientConfig;\n}\n\n/**\n * @internal - Prefer `configureTRPCHeyApiClient`\n */\nexport function createTRPCErrorInterceptor(\n transformerOpts: DataTransformerOptions,\n) {\n const transformer = resolveTransformer(transformerOpts);\n return (error: unknown) => {\n if (!!error && typeof error === 'object' && 'error' in error) {\n (error as any).error = transformer.output.deserialize(\n (error as any).error,\n );\n }\n return error;\n };\n}\n\n/**\n * Configures a hey-api client for use with a tRPC OpenAPI backend.\n *\n * Sets up querySerializer, bodySerializer, responseTransformer, and\n * an error interceptor (for transformer-based error deserialization)\n * in a single call.\n *\n * @example\n * ```ts\n * import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';\n * import superjson from 'superjson';\n * import { client } from './generated/client.gen';\n *\n * configureTRPCHeyApiClient(client, {\n * baseUrl: 'http://localhost:3000',\n * transformer: superjson,\n * });\n * ```\n */\nexport function configureTRPCHeyApiClient(\n client: HeyApiFetchClient,\n opts: TRPCHeyApiClientOptions &\n Omit<HeyApiConfig, keyof TRPCHeyApiClientConfig>,\n) {\n const { transformer, ...heyConfig } = opts;\n const trpcConfig = createTRPCHeyApiClientConfig({ transformer });\n\n client.setConfig({ ...heyConfig, ...trpcConfig });\n\n if (transformer) {\n client.interceptors.error.use(createTRPCErrorInterceptor(transformer));\n }\n}\n"],"x_google_ignoreList":[0,1],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["_objectWithoutProperties","transformer: DataTransformerOptions","opts?: TRPCHeyApiClientOptions","query: Record<string, unknown>","body: unknown","data: unknown","transformerOpts: DataTransformerOptions","error: unknown","client: HeyApiFetchClient","opts: TRPCHeyApiClientOptions &\n Omit<HeyApiConfig, keyof TRPCHeyApiClientConfig>"],"sources":["../../../../node_modules/.pnpm/@oxc-project+runtime@0.72.2/node_modules/@oxc-project/runtime/src/helpers/objectWithoutPropertiesLoose.js","../../../../node_modules/.pnpm/@oxc-project+runtime@0.72.2/node_modules/@oxc-project/runtime/src/helpers/objectWithoutProperties.js","../../src/heyapi/index.ts"],"sourcesContent":["function _objectWithoutPropertiesLoose(r, e) {\n if (null == r) return {};\n var t = {};\n for (var n in r) if ({}.hasOwnProperty.call(r, n)) {\n if (e.includes(n)) continue;\n t[n] = r[n];\n }\n return t;\n}\nmodule.exports = _objectWithoutPropertiesLoose, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var objectWithoutPropertiesLoose = require(\"./objectWithoutPropertiesLoose.js\");\nfunction _objectWithoutProperties(e, t) {\n if (null == e) return {};\n var o,\n r,\n i = objectWithoutPropertiesLoose(e, t);\n if (Object.getOwnPropertySymbols) {\n var s = Object.getOwnPropertySymbols(e);\n for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);\n }\n return i;\n}\nmodule.exports = _objectWithoutProperties, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","import type {\n FetchClient as HeyApiFetchClient,\n UserConfig,\n} from '@hey-api/openapi-ts';\nimport type {\n TRPCCombinedDataTransformer,\n TRPCDataTransformer,\n} from '@trpc/server';\n\nexport type DataTransformerOptions =\n | TRPCDataTransformer\n | TRPCCombinedDataTransformer;\n\ntype HeyAPIResolvers = Exclude<\n Extract<\n Exclude<UserConfig['plugins'], undefined | string>[number],\n { name: '@hey-api/typescript' }\n >['~resolvers'],\n undefined\n>;\n\nfunction resolveTransformer(\n transformer: DataTransformerOptions,\n): TRPCCombinedDataTransformer {\n if ('input' in transformer) {\n return transformer;\n }\n return { input: transformer, output: transformer };\n}\n\nexport interface TRPCHeyApiClientOptions {\n transformer?: DataTransformerOptions;\n}\n\nexport type HeyApiConfig = ReturnType<HeyApiFetchClient['getConfig']>;\nexport type TRPCHeyApiClientConfig = Required<\n Pick<HeyApiConfig, 'querySerializer'>\n> &\n Pick<HeyApiConfig, 'bodySerializer' | 'responseTransformer'>;\n\n/**\n * Returns the `~resolvers` object for the `@hey-api/typescript` plugin.\n *\n * Maps `date` and `date-time` string formats to `Date` so that the\n * generated SDK uses `Date` instead of `string` for those fields.\n *\n * @example\n * ```ts\n * import { createClient } from '@hey-api/openapi-ts';\n * import { createTRPCHeyApiTypeResolvers } from '@trpc/openapi/heyapi';\n *\n * await createClient({\n * plugins: [\n * { name: '@hey-api/typescript', '~resolvers': createTRPCHeyApiTypeResolvers() },\n * ],\n * });\n * ```\n */\nexport function createTRPCHeyApiTypeResolvers(): HeyAPIResolvers {\n return {\n string(ctx) {\n if (ctx.schema.format === 'date-time' || ctx.schema.format === 'date') {\n return ctx.$.type('Date');\n }\n return undefined;\n },\n number(ctx) {\n if (ctx.schema.format === 'bigint') {\n return ctx.$.type('bigint');\n }\n return undefined;\n },\n };\n}\n\n/**\n * @internal - Prefer `configureTRPCHeyApiClient`\n */\nexport function createTRPCHeyApiClientConfig(opts?: TRPCHeyApiClientOptions) {\n const transformer = opts?.transformer\n ? resolveTransformer(opts.transformer)\n : undefined;\n\n return {\n querySerializer: (query: Record<string, unknown>) => {\n const params = new URLSearchParams();\n\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined) {\n continue;\n }\n\n if (key === 'input' && transformer) {\n params.append(\n key,\n JSON.stringify(transformer.input.serialize(value)),\n );\n } else {\n params.append(key, JSON.stringify(value));\n }\n }\n\n return params.toString();\n },\n\n ...(transformer && {\n bodySerializer: (body: unknown) => {\n return JSON.stringify(transformer.input.serialize(body));\n },\n\n responseTransformer: async (data: unknown) => {\n if (!!data && typeof data === 'object' && 'result' in data) {\n const result = (data as any).result;\n if (!result.type || result.type === 'data') {\n result.data = transformer.output.deserialize(result.data);\n }\n }\n\n return data;\n },\n }),\n } as const satisfies TRPCHeyApiClientConfig;\n}\n\n/**\n * @internal - Prefer `configureTRPCHeyApiClient`\n */\nexport function createTRPCErrorInterceptor(\n transformerOpts: DataTransformerOptions,\n) {\n const transformer = resolveTransformer(transformerOpts);\n return (error: unknown) => {\n if (!!error && typeof error === 'object' && 'error' in error) {\n (error as any).error = transformer.output.deserialize(\n (error as any).error,\n );\n }\n return error;\n };\n}\n\n/**\n * Configures a hey-api client for use with a tRPC OpenAPI backend.\n *\n * Sets up querySerializer, bodySerializer, responseTransformer, and\n * an error interceptor (for transformer-based error deserialization)\n * in a single call.\n *\n * @example\n * ```ts\n * import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';\n * import superjson from 'superjson';\n * import { client } from './generated/client.gen';\n *\n * configureTRPCHeyApiClient(client, {\n * baseUrl: 'http://localhost:3000',\n * transformer: superjson,\n * });\n * ```\n */\nexport function configureTRPCHeyApiClient(\n client: HeyApiFetchClient,\n opts: TRPCHeyApiClientOptions &\n Omit<HeyApiConfig, keyof TRPCHeyApiClientConfig>,\n) {\n const { transformer, ...heyConfig } = opts;\n const trpcConfig = createTRPCHeyApiClientConfig({ transformer });\n\n client.setConfig({ ...heyConfig, ...trpcConfig });\n\n if (transformer) {\n client.interceptors.error.use(createTRPCErrorInterceptor(transformer));\n }\n}\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
|