@kubb/plugin-ts 5.0.0-beta.3 → 5.0.0-beta.31
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 +26 -5
- package/dist/index.cjs +416 -117
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +81 -58
- package/dist/index.js +415 -120
- package/dist/index.js.map +1 -1
- package/extension.yaml +1078 -0
- package/package.json +11 -13
- package/src/components/Enum.tsx +3 -3
- package/src/factory.ts +23 -20
- package/src/generators/typeGenerator.tsx +100 -39
- package/src/plugin.ts +20 -21
- package/src/printers/printerTs.ts +31 -30
- package/src/resolvers/resolverTs.ts +28 -25
- package/src/types.ts +44 -37
- package/src/utils.ts +23 -13
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "./chunk--u3MIqq1.js";
|
|
2
|
-
import {
|
|
3
|
-
import { File,
|
|
1
|
+
import { t as __name } from "./chunk--u3MIqq1.js";
|
|
2
|
+
import { parserTs } from "@kubb/parser-ts";
|
|
3
|
+
import { File, jsxRendererSync } from "@kubb/renderer-jsx";
|
|
4
4
|
import { ast, defineGenerator, definePlugin, defineResolver } from "@kubb/core";
|
|
5
5
|
import { isNumber } from "remeda";
|
|
6
6
|
import ts from "typescript";
|
|
@@ -141,6 +141,129 @@ function stringify(value) {
|
|
|
141
141
|
return JSON.stringify(trimQuotes(value.toString()));
|
|
142
142
|
}
|
|
143
143
|
//#endregion
|
|
144
|
+
//#region ../../internals/utils/src/reserved.ts
|
|
145
|
+
/**
|
|
146
|
+
* JavaScript and Java reserved words.
|
|
147
|
+
* @link https://github.com/jonschlinkert/reserved/blob/master/index.js
|
|
148
|
+
*/
|
|
149
|
+
const reservedWords = new Set([
|
|
150
|
+
"abstract",
|
|
151
|
+
"arguments",
|
|
152
|
+
"boolean",
|
|
153
|
+
"break",
|
|
154
|
+
"byte",
|
|
155
|
+
"case",
|
|
156
|
+
"catch",
|
|
157
|
+
"char",
|
|
158
|
+
"class",
|
|
159
|
+
"const",
|
|
160
|
+
"continue",
|
|
161
|
+
"debugger",
|
|
162
|
+
"default",
|
|
163
|
+
"delete",
|
|
164
|
+
"do",
|
|
165
|
+
"double",
|
|
166
|
+
"else",
|
|
167
|
+
"enum",
|
|
168
|
+
"eval",
|
|
169
|
+
"export",
|
|
170
|
+
"extends",
|
|
171
|
+
"false",
|
|
172
|
+
"final",
|
|
173
|
+
"finally",
|
|
174
|
+
"float",
|
|
175
|
+
"for",
|
|
176
|
+
"function",
|
|
177
|
+
"goto",
|
|
178
|
+
"if",
|
|
179
|
+
"implements",
|
|
180
|
+
"import",
|
|
181
|
+
"in",
|
|
182
|
+
"instanceof",
|
|
183
|
+
"int",
|
|
184
|
+
"interface",
|
|
185
|
+
"let",
|
|
186
|
+
"long",
|
|
187
|
+
"native",
|
|
188
|
+
"new",
|
|
189
|
+
"null",
|
|
190
|
+
"package",
|
|
191
|
+
"private",
|
|
192
|
+
"protected",
|
|
193
|
+
"public",
|
|
194
|
+
"return",
|
|
195
|
+
"short",
|
|
196
|
+
"static",
|
|
197
|
+
"super",
|
|
198
|
+
"switch",
|
|
199
|
+
"synchronized",
|
|
200
|
+
"this",
|
|
201
|
+
"throw",
|
|
202
|
+
"throws",
|
|
203
|
+
"transient",
|
|
204
|
+
"true",
|
|
205
|
+
"try",
|
|
206
|
+
"typeof",
|
|
207
|
+
"var",
|
|
208
|
+
"void",
|
|
209
|
+
"volatile",
|
|
210
|
+
"while",
|
|
211
|
+
"with",
|
|
212
|
+
"yield",
|
|
213
|
+
"Array",
|
|
214
|
+
"Date",
|
|
215
|
+
"hasOwnProperty",
|
|
216
|
+
"Infinity",
|
|
217
|
+
"isFinite",
|
|
218
|
+
"isNaN",
|
|
219
|
+
"isPrototypeOf",
|
|
220
|
+
"length",
|
|
221
|
+
"Math",
|
|
222
|
+
"name",
|
|
223
|
+
"NaN",
|
|
224
|
+
"Number",
|
|
225
|
+
"Object",
|
|
226
|
+
"prototype",
|
|
227
|
+
"String",
|
|
228
|
+
"toString",
|
|
229
|
+
"undefined",
|
|
230
|
+
"valueOf"
|
|
231
|
+
]);
|
|
232
|
+
/**
|
|
233
|
+
* Returns `true` when `name` is a syntactically valid JavaScript variable name.
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* ```ts
|
|
237
|
+
* isValidVarName('status') // true
|
|
238
|
+
* isValidVarName('class') // false (reserved word)
|
|
239
|
+
* isValidVarName('42foo') // false (starts with digit)
|
|
240
|
+
* ```
|
|
241
|
+
*/
|
|
242
|
+
function isValidVarName(name) {
|
|
243
|
+
if (!name || reservedWords.has(name)) return false;
|
|
244
|
+
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Returns `name` when it's a syntactically valid JavaScript variable name,
|
|
248
|
+
* otherwise prefixes it with `_` so the result is a valid identifier.
|
|
249
|
+
*
|
|
250
|
+
* Useful for sanitizing OpenAPI schema names or operation IDs that start with
|
|
251
|
+
* a digit (e.g. `409`, `504AccountCancel`) before using them as exported
|
|
252
|
+
* variable, type, or function names.
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* ```ts
|
|
256
|
+
* ensureValidVarName('409') // '_409'
|
|
257
|
+
* ensureValidVarName('504AccountCancel') // '_504AccountCancel'
|
|
258
|
+
* ensureValidVarName('Pet') // 'Pet'
|
|
259
|
+
* ensureValidVarName('class') // '_class'
|
|
260
|
+
* ```
|
|
261
|
+
*/
|
|
262
|
+
function ensureValidVarName(name) {
|
|
263
|
+
if (!name || isValidVarName(name)) return name;
|
|
264
|
+
return `_${name}`;
|
|
265
|
+
}
|
|
266
|
+
//#endregion
|
|
144
267
|
//#region src/constants.ts
|
|
145
268
|
/**
|
|
146
269
|
* `optionalType` values that cause a property's type to include `| undefined`.
|
|
@@ -203,6 +326,10 @@ const syntaxKind = {
|
|
|
203
326
|
literalType: SyntaxKind.LiteralType,
|
|
204
327
|
stringLiteral: SyntaxKind.StringLiteral
|
|
205
328
|
};
|
|
329
|
+
function isNonNullable$1(value) {
|
|
330
|
+
return value !== null && value !== void 0;
|
|
331
|
+
}
|
|
332
|
+
__name(isNonNullable$1, "isNonNullable");
|
|
206
333
|
function isValidIdentifier(str) {
|
|
207
334
|
if (!str.length || str.trim() !== str) return false;
|
|
208
335
|
const node = ts.parseIsolatedEntityName(str, ts.ScriptTarget.Latest);
|
|
@@ -272,7 +399,7 @@ function createUnionDeclaration({ nodes, withParentheses }) {
|
|
|
272
399
|
* Supports optional markers, readonly modifiers, and type annotations.
|
|
273
400
|
*/
|
|
274
401
|
function createPropertySignature({ readOnly, modifiers = [], name, questionToken, type }) {
|
|
275
|
-
return factory.createPropertySignature([...modifiers, readOnly ? factory.createToken(ts.SyntaxKind.ReadonlyKeyword) : void 0].filter(
|
|
402
|
+
return factory.createPropertySignature([...modifiers, readOnly ? factory.createToken(ts.SyntaxKind.ReadonlyKeyword) : void 0].filter((modifier) => modifier !== void 0), propertyName(name), createQuestionToken(questionToken), type);
|
|
276
403
|
}
|
|
277
404
|
/**
|
|
278
405
|
* Creates a function parameter declaration with optional markers, rest parameters, and type annotations.
|
|
@@ -370,8 +497,8 @@ function createEnumDeclaration({ type = "enum", name, typeName, enums, enumKeyCa
|
|
|
370
497
|
}
|
|
371
498
|
if (typeof value === "boolean") return factory.createLiteralTypeNode(value ? factory.createTrue() : factory.createFalse());
|
|
372
499
|
if (value) return factory.createLiteralTypeNode(factory.createStringLiteral(value.toString()));
|
|
373
|
-
}).filter(
|
|
374
|
-
if (type === "enum" || type === "constEnum") return [void 0, factory.createEnumDeclaration([factory.createToken(ts.SyntaxKind.ExportKeyword), type === "constEnum" ? factory.createToken(ts.SyntaxKind.ConstKeyword) : void 0].filter(
|
|
500
|
+
}).filter((node) => node !== void 0)))];
|
|
501
|
+
if (type === "enum" || type === "constEnum") return [void 0, factory.createEnumDeclaration([factory.createToken(ts.SyntaxKind.ExportKeyword), type === "constEnum" ? factory.createToken(ts.SyntaxKind.ConstKeyword) : void 0].filter((modifier) => modifier !== void 0), factory.createIdentifier(typeName), enums.map(([key, value]) => {
|
|
375
502
|
let initializer = factory.createStringLiteral(value?.toString());
|
|
376
503
|
if (Number.parseInt(value.toString(), 10) === value && isNumber(Number.parseInt(value.toString(), 10))) if (value < 0) initializer = factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value)));
|
|
377
504
|
else initializer = factory.createNumericLiteral(value);
|
|
@@ -384,7 +511,7 @@ function createEnumDeclaration({ type = "enum", name, typeName, enums, enumKeyCa
|
|
|
384
511
|
const casingKey = applyEnumKeyCasing(key.toString(), enumKeyCasing);
|
|
385
512
|
return factory.createEnumMember(propertyName(casingKey), initializer);
|
|
386
513
|
}
|
|
387
|
-
}).filter(
|
|
514
|
+
}).filter((member) => member !== void 0))];
|
|
388
515
|
const identifierName = name;
|
|
389
516
|
if (enums.length === 0) return [void 0, factory.createTypeAliasDeclaration([factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createIdentifier(typeName), void 0, factory.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword))];
|
|
390
517
|
return [factory.createVariableStatement([factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier(identifierName), void 0, void 0, factory.createAsExpression(factory.createObjectLiteralExpression(enums.map(([key, value]) => {
|
|
@@ -396,7 +523,7 @@ function createEnumDeclaration({ type = "enum", name, typeName, enums, enumKeyCa
|
|
|
396
523
|
const casingKey = applyEnumKeyCasing(key.toString(), enumKeyCasing);
|
|
397
524
|
return factory.createPropertyAssignment(propertyName(casingKey), initializer);
|
|
398
525
|
}
|
|
399
|
-
}).filter(
|
|
526
|
+
}).filter((property) => property !== void 0), true), factory.createTypeReferenceNode(factory.createIdentifier("const"), void 0)))], ts.NodeFlags.Const)), factory.createTypeAliasDeclaration([factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createIdentifier(typeName), void 0, factory.createIndexedAccessTypeNode(factory.createParenthesizedType(factory.createTypeQueryNode(factory.createIdentifier(identifierName), void 0)), factory.createTypeOperatorNode(ts.SyntaxKind.KeyOfKeyword, factory.createTypeQueryNode(factory.createIdentifier(identifierName), void 0))))];
|
|
400
527
|
}
|
|
401
528
|
/**
|
|
402
529
|
* Creates a TypeScript `Omit<T, Keys>` type reference node.
|
|
@@ -536,14 +663,14 @@ function dateOrStringNode(node) {
|
|
|
536
663
|
* Maps an array of `SchemaNode`s through the printer, filtering out `null` and `undefined` results.
|
|
537
664
|
*/
|
|
538
665
|
function buildMemberNodes(members, print) {
|
|
539
|
-
return (members ?? []).map(print).filter(
|
|
666
|
+
return (members ?? []).map(print).filter(isNonNullable$1);
|
|
540
667
|
}
|
|
541
668
|
/**
|
|
542
669
|
* Builds a TypeScript tuple type node from an array schema's `items`,
|
|
543
670
|
* applying min/max slice and optional/rest element rules.
|
|
544
671
|
*/
|
|
545
672
|
function buildTupleNode(node, print) {
|
|
546
|
-
let items = (node.items ?? []).map(print).filter(
|
|
673
|
+
let items = (node.items ?? []).map(print).filter(isNonNullable$1);
|
|
547
674
|
const restNode = node.rest ? print(node.rest) ?? void 0 : void 0;
|
|
548
675
|
const { min, max } = node;
|
|
549
676
|
if (max !== void 0) {
|
|
@@ -630,13 +757,13 @@ function Enum({ node, enumType, enumTypeSuffix, enumKeyCasing, resolver }) {
|
|
|
630
757
|
isExportable: true,
|
|
631
758
|
isIndexable: true,
|
|
632
759
|
isTypeOnly: false,
|
|
633
|
-
children:
|
|
760
|
+
children: parserTs.print(nameNode)
|
|
634
761
|
}), /* @__PURE__ */ jsx(File.Source, {
|
|
635
762
|
name: typeName,
|
|
636
763
|
isIndexable: true,
|
|
637
764
|
isExportable: ENUM_TYPES_WITH_RUNTIME_VALUE.has(enumType),
|
|
638
765
|
isTypeOnly: ENUM_TYPES_WITH_TYPE_ONLY.has(enumType),
|
|
639
|
-
children:
|
|
766
|
+
children: parserTs.print(typeNode)
|
|
640
767
|
})] });
|
|
641
768
|
}
|
|
642
769
|
//#endregion
|
|
@@ -676,6 +803,98 @@ function Type({ name, node, printer, enumType, enumTypeSuffix, enumKeyCasing, re
|
|
|
676
803
|
})] });
|
|
677
804
|
}
|
|
678
805
|
//#endregion
|
|
806
|
+
//#region ../../internals/shared/src/operation.ts
|
|
807
|
+
/**
|
|
808
|
+
* Maps a content type to the PascalCase suffix used to name per-content-type variants
|
|
809
|
+
* (e.g. `application/json` → `Json`, `application/xml` → `Xml`, `multipart/form-data` → `FormData`).
|
|
810
|
+
*/
|
|
811
|
+
function getContentTypeSuffix(contentType) {
|
|
812
|
+
const baseType = contentType.split(";")[0].trim();
|
|
813
|
+
if (baseType === "application/json") return "Json";
|
|
814
|
+
if (baseType === "multipart/form-data") return "FormData";
|
|
815
|
+
if (baseType === "application/x-www-form-urlencoded") return "FormUrlEncoded";
|
|
816
|
+
const parts = (baseType.split("/").pop() ?? baseType).split(/[^a-zA-Z0-9]+/).filter(Boolean);
|
|
817
|
+
if (parts.length === 0) return "Unknown";
|
|
818
|
+
return parts.map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* Appends a content-type suffix to a base name, keeping a trailing `Data` segment last
|
|
822
|
+
* (e.g. `AddPetData` + `Json` → `AddPetJsonData`, `AddPetStatus200` + `Xml` → `AddPetStatus200Xml`).
|
|
823
|
+
*/
|
|
824
|
+
function getPerContentTypeName(baseName, suffix) {
|
|
825
|
+
if (baseName.endsWith("Data")) return suffix.endsWith("Data") ? baseName.slice(0, -4) + suffix : `${baseName.slice(0, -4)}${suffix}Data`;
|
|
826
|
+
return baseName + suffix;
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* Resolves per-content-type variant names for a set of content entries, deduplicating suffix
|
|
830
|
+
* collisions with a numeric counter. Entries without a schema are skipped. The returned `suffix` is
|
|
831
|
+
* the final (possibly counter-augmented) value, so callers can derive parallel names in another
|
|
832
|
+
* namespace (e.g. plugin-faker deriving the matching plugin-ts type name).
|
|
833
|
+
*/
|
|
834
|
+
function resolveContentTypeVariants(entries, baseName) {
|
|
835
|
+
const usedNames = /* @__PURE__ */ new Set();
|
|
836
|
+
return entries.filter((entry) => entry.schema).map((entry) => {
|
|
837
|
+
const baseSuffix = getContentTypeSuffix(entry.contentType);
|
|
838
|
+
let suffix = baseSuffix;
|
|
839
|
+
let name = getPerContentTypeName(baseName, suffix);
|
|
840
|
+
let counter = 2;
|
|
841
|
+
while (usedNames.has(name)) {
|
|
842
|
+
suffix = `${baseSuffix}${counter++}`;
|
|
843
|
+
name = getPerContentTypeName(baseName, suffix);
|
|
844
|
+
}
|
|
845
|
+
usedNames.add(name);
|
|
846
|
+
return {
|
|
847
|
+
name,
|
|
848
|
+
suffix,
|
|
849
|
+
schema: entry.schema,
|
|
850
|
+
keysToOmit: entry.keysToOmit,
|
|
851
|
+
contentType: entry.contentType
|
|
852
|
+
};
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
function getOperationParameters(node, options = {}) {
|
|
856
|
+
const params = ast.caseParams(node.parameters, options.paramsCasing);
|
|
857
|
+
return {
|
|
858
|
+
path: params.filter((param) => param.in === "path"),
|
|
859
|
+
query: params.filter((param) => param.in === "query"),
|
|
860
|
+
header: params.filter((param) => param.in === "header"),
|
|
861
|
+
cookie: params.filter((param) => param.in === "cookie")
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
//#endregion
|
|
865
|
+
//#region ../../internals/shared/src/group.ts
|
|
866
|
+
/**
|
|
867
|
+
* Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
|
|
868
|
+
* shared default naming so every plugin groups output consistently:
|
|
869
|
+
*
|
|
870
|
+
* - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).
|
|
871
|
+
* - other groups use `${camelCase(group)}${suffix}` (e.g. `petController`).
|
|
872
|
+
*
|
|
873
|
+
* Returns `null` when grouping is disabled, matching the per-plugin convention.
|
|
874
|
+
*
|
|
875
|
+
* @param group - The user-supplied group option, or `undefined` to disable grouping.
|
|
876
|
+
* @param options.suffix - Appended to non-`path` group names, e.g. `'Controller'` or `'Requests'`.
|
|
877
|
+
* @param options.honorName - When `true`, a user-provided `group.name` overrides the default namer.
|
|
878
|
+
*
|
|
879
|
+
* @example
|
|
880
|
+
* ```ts
|
|
881
|
+
* createGroupConfig(group, { suffix: 'Controller' }) // plugin-ts, plugin-zod
|
|
882
|
+
* createGroupConfig(group, { suffix: 'Controller', honorName: true }) // plugin-faker, plugin-client, …
|
|
883
|
+
* createGroupConfig(group, { suffix: 'Requests', honorName: true }) // plugin-cypress, plugin-mcp
|
|
884
|
+
* ```
|
|
885
|
+
*/
|
|
886
|
+
function createGroupConfig(group, options) {
|
|
887
|
+
if (!group) return null;
|
|
888
|
+
const defaultName = (ctx) => {
|
|
889
|
+
if (group.type === "path") return `${ctx.group.split("/")[1]}`;
|
|
890
|
+
return `${camelCase(ctx.group)}${options.suffix}`;
|
|
891
|
+
};
|
|
892
|
+
return {
|
|
893
|
+
...group,
|
|
894
|
+
name: options.honorName && group.name ? group.name : defaultName
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
//#endregion
|
|
679
898
|
//#region src/utils.ts
|
|
680
899
|
/**
|
|
681
900
|
* Collects JSDoc annotation strings for a schema node.
|
|
@@ -687,15 +906,18 @@ function Type({ name, node, printer, enumType, enumTypeSuffix, enumKeyCasing, re
|
|
|
687
906
|
function buildPropertyJSDocComments(schema) {
|
|
688
907
|
const meta = ast.syncSchemaRef(schema);
|
|
689
908
|
const isArray = meta?.primitive === "array";
|
|
909
|
+
const hasDescription = meta && "description" in meta && meta.description;
|
|
910
|
+
const formatComment = meta && "format" in meta && meta.format ? hasDescription ? [" ", `Format: \`${meta.format}\``] : ["@description", `Format: \`${meta.format}\``] : [];
|
|
690
911
|
return [
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
!isArray && meta && "
|
|
695
|
-
meta && "
|
|
696
|
-
meta && "
|
|
697
|
-
meta && "
|
|
698
|
-
meta && "
|
|
912
|
+
hasDescription ? `@description ${jsStringEscape(meta.description)}` : null,
|
|
913
|
+
...formatComment,
|
|
914
|
+
meta && "deprecated" in meta && meta.deprecated ? "@deprecated" : null,
|
|
915
|
+
!isArray && meta && "min" in meta && meta.min !== void 0 ? `@minLength ${meta.min}` : null,
|
|
916
|
+
!isArray && meta && "max" in meta && meta.max !== void 0 ? `@maxLength ${meta.max}` : null,
|
|
917
|
+
meta && "pattern" in meta && meta.pattern ? `@pattern ${meta.pattern}` : null,
|
|
918
|
+
meta && "default" in meta && meta.default !== void 0 ? `@default ${"primitive" in meta && meta.primitive === "string" ? stringify(meta.default) : meta.default}` : null,
|
|
919
|
+
meta && "example" in meta && meta.example !== void 0 ? `@example ${meta.example}` : null,
|
|
920
|
+
meta && "primitive" in meta && meta.primitive ? [`@type ${meta.primitive}`, "optional" in schema && schema.optional ? " | undefined" : null].filter(Boolean).join("") : null
|
|
699
921
|
].filter(Boolean);
|
|
700
922
|
}
|
|
701
923
|
function buildParams(node, { params, resolver }) {
|
|
@@ -712,9 +934,7 @@ function buildParams(node, { params, resolver }) {
|
|
|
712
934
|
});
|
|
713
935
|
}
|
|
714
936
|
function buildData(node, { resolver }) {
|
|
715
|
-
const pathParams
|
|
716
|
-
const queryParams = node.parameters.filter((p) => p.in === "query");
|
|
717
|
-
const headerParams = node.parameters.filter((p) => p.in === "header");
|
|
937
|
+
const { path: pathParams, query: queryParams, header: headerParams } = getOperationParameters(node);
|
|
718
938
|
return ast.createSchema({
|
|
719
939
|
type: "object",
|
|
720
940
|
deprecated: node.deprecated,
|
|
@@ -796,7 +1016,7 @@ function buildResponses(node, { resolver }) {
|
|
|
796
1016
|
});
|
|
797
1017
|
}
|
|
798
1018
|
function buildResponseUnion(node, { resolver }) {
|
|
799
|
-
const responsesWithSchema = node.responses.filter((res) => res.schema);
|
|
1019
|
+
const responsesWithSchema = node.responses.filter((res) => res.content?.some((entry) => entry.schema));
|
|
800
1020
|
if (responsesWithSchema.length === 0) return null;
|
|
801
1021
|
return ast.createSchema({
|
|
802
1022
|
type: "union",
|
|
@@ -808,6 +1028,9 @@ function buildResponseUnion(node, { resolver }) {
|
|
|
808
1028
|
}
|
|
809
1029
|
//#endregion
|
|
810
1030
|
//#region src/printers/printerTs.ts
|
|
1031
|
+
function isNonNullable(value) {
|
|
1032
|
+
return value !== null && value !== void 0;
|
|
1033
|
+
}
|
|
811
1034
|
/**
|
|
812
1035
|
* TypeScript type printer built with `definePrinter`.
|
|
813
1036
|
*
|
|
@@ -860,7 +1083,7 @@ const printerTs = ast.definePrinter((options) => {
|
|
|
860
1083
|
date: dateOrStringNode,
|
|
861
1084
|
time: dateOrStringNode,
|
|
862
1085
|
ref(node) {
|
|
863
|
-
if (!node.name) return;
|
|
1086
|
+
if (!node.name) return null;
|
|
864
1087
|
const refName = node.ref ? ast.extractRefName(node.ref) ?? node.name : node.name;
|
|
865
1088
|
return createTypeReferenceNode(node.ref && ENUM_TYPES_WITH_KEY_SUFFIX.has(this.options.enumType) && this.options.enumTypeSuffix && this.options.enumSchemaNames?.has(refName) ? this.options.resolver.resolveEnumKeyName({ name: refName }, this.options.enumTypeSuffix) : node.ref ? this.options.resolver.default(refName, "type") : refName, void 0);
|
|
866
1089
|
},
|
|
@@ -868,7 +1091,7 @@ const printerTs = ast.definePrinter((options) => {
|
|
|
868
1091
|
const values = node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? [];
|
|
869
1092
|
if (this.options.enumType === "inlineLiteral" || !node.name) return createUnionDeclaration({
|
|
870
1093
|
withParentheses: true,
|
|
871
|
-
nodes: values.filter((v) => v !== null && v !== void 0).map((value) => constToTypeNode(value, typeof value)).filter(
|
|
1094
|
+
nodes: values.filter((v) => v !== null && v !== void 0).map((value) => constToTypeNode(value, typeof value)).filter(isNonNullable)
|
|
872
1095
|
}) ?? void 0;
|
|
873
1096
|
return createTypeReferenceNode(ENUM_TYPES_WITH_KEY_SUFFIX.has(this.options.enumType) && this.options.enumTypeSuffix ? this.options.resolver.resolveEnumKeyName(node, this.options.enumTypeSuffix) : this.options.resolver.default(node.name, "type"), void 0);
|
|
874
1097
|
},
|
|
@@ -886,7 +1109,7 @@ const printerTs = ast.definePrinter((options) => {
|
|
|
886
1109
|
withParentheses: true
|
|
887
1110
|
});
|
|
888
1111
|
return this.transform(m);
|
|
889
|
-
}).filter(
|
|
1112
|
+
}).filter(isNonNullable)
|
|
890
1113
|
}) ?? void 0;
|
|
891
1114
|
return createUnionDeclaration({
|
|
892
1115
|
withParentheses: true,
|
|
@@ -897,16 +1120,16 @@ const printerTs = ast.definePrinter((options) => {
|
|
|
897
1120
|
return createIntersectionDeclaration({
|
|
898
1121
|
withParentheses: true,
|
|
899
1122
|
nodes: buildMemberNodes(node.members, this.transform)
|
|
900
|
-
}) ??
|
|
1123
|
+
}) ?? null;
|
|
901
1124
|
},
|
|
902
1125
|
array(node) {
|
|
903
1126
|
return createArrayDeclaration({
|
|
904
|
-
nodes: (node.items ?? []).map((item) => this.transform(item)).filter(
|
|
1127
|
+
nodes: (node.items ?? []).map((item) => this.transform(item)).filter(isNonNullable),
|
|
905
1128
|
arrayType: this.options.arrayType
|
|
906
|
-
}) ??
|
|
1129
|
+
}) ?? null;
|
|
907
1130
|
},
|
|
908
1131
|
tuple(node) {
|
|
909
|
-
return buildTupleNode(node, this.transform);
|
|
1132
|
+
return buildTupleNode(node, this.transform) ?? null;
|
|
910
1133
|
},
|
|
911
1134
|
object(node) {
|
|
912
1135
|
const { transform, options } = this;
|
|
@@ -933,46 +1156,54 @@ const printerTs = ast.definePrinter((options) => {
|
|
|
933
1156
|
},
|
|
934
1157
|
print(node) {
|
|
935
1158
|
const { name, syntaxType = "type", description, keysToOmit } = this.options;
|
|
936
|
-
|
|
937
|
-
if (!
|
|
1159
|
+
const transformed = this.transform(node);
|
|
1160
|
+
if (!transformed) return null;
|
|
938
1161
|
const meta = ast.syncSchemaRef(node);
|
|
939
1162
|
if (!name) {
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
return
|
|
1163
|
+
const withNullable = meta.nullable ? createUnionDeclaration({ nodes: [transformed, keywordTypeNodes.null] }) : transformed;
|
|
1164
|
+
const result = (meta.nullish || meta.optional) && addsUndefined ? createUnionDeclaration({ nodes: [withNullable, keywordTypeNodes.undefined] }) : withNullable;
|
|
1165
|
+
return parserTs.print(result);
|
|
943
1166
|
}
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
1167
|
+
const inner = (() => {
|
|
1168
|
+
const omitted = keysToOmit?.length ? createOmitDeclaration({
|
|
1169
|
+
keys: keysToOmit,
|
|
1170
|
+
type: transformed,
|
|
1171
|
+
nonNullable: true
|
|
1172
|
+
}) : transformed;
|
|
1173
|
+
const withNullable = meta.nullable ? createUnionDeclaration({ nodes: [omitted, keywordTypeNodes.null] }) : omitted;
|
|
1174
|
+
return meta.nullish || meta.optional ? createUnionDeclaration({ nodes: [withNullable, keywordTypeNodes.undefined] }) : withNullable;
|
|
1175
|
+
})();
|
|
1176
|
+
const typeNode = createTypeDeclaration({
|
|
953
1177
|
name,
|
|
954
1178
|
isExportable: true,
|
|
955
1179
|
type: inner,
|
|
956
|
-
syntax:
|
|
1180
|
+
syntax: syntaxType === "type" || inner.kind === syntaxKind.union || !!keysToOmit?.length ? "type" : "interface",
|
|
957
1181
|
comments: buildPropertyJSDocComments({
|
|
958
1182
|
...meta,
|
|
959
1183
|
description
|
|
960
1184
|
})
|
|
961
|
-
})
|
|
1185
|
+
});
|
|
1186
|
+
return parserTs.print(typeNode);
|
|
962
1187
|
}
|
|
963
1188
|
};
|
|
964
1189
|
});
|
|
965
1190
|
//#endregion
|
|
966
1191
|
//#region src/generators/typeGenerator.tsx
|
|
1192
|
+
/**
|
|
1193
|
+
* Built-in generator for `@kubb/plugin-ts`. Emits one TypeScript file per
|
|
1194
|
+
* schema in the spec plus per-operation request, response, and parameter
|
|
1195
|
+
* types. Drop-replace with a custom `Generator<PluginTs>` to change how
|
|
1196
|
+
* TypeScript output is produced.
|
|
1197
|
+
*/
|
|
967
1198
|
const typeGenerator = defineGenerator({
|
|
968
1199
|
name: "typescript",
|
|
969
|
-
renderer:
|
|
1200
|
+
renderer: jsxRendererSync,
|
|
970
1201
|
schema(node, ctx) {
|
|
971
1202
|
const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, printer } = ctx.options;
|
|
972
1203
|
const { adapter, config, resolver, root } = ctx;
|
|
973
1204
|
if (!node.name) return;
|
|
974
1205
|
const mode = ctx.getMode(output);
|
|
975
|
-
const enumSchemaNames = new Set(
|
|
1206
|
+
const enumSchemaNames = new Set(ctx.meta.enumNames);
|
|
976
1207
|
function resolveImportName(schemaName) {
|
|
977
1208
|
if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && enumTypeSuffix && enumSchemaNames.has(schemaName)) return resolver.resolveEnumKeyName({ name: schemaName }, enumTypeSuffix);
|
|
978
1209
|
return resolver.resolveTypeName(schemaName);
|
|
@@ -985,7 +1216,7 @@ const typeGenerator = defineGenerator({
|
|
|
985
1216
|
}, {
|
|
986
1217
|
root,
|
|
987
1218
|
output,
|
|
988
|
-
group
|
|
1219
|
+
group: group ?? void 0
|
|
989
1220
|
}).path
|
|
990
1221
|
}));
|
|
991
1222
|
const isEnumSchema = !!ast.narrowSchema(node, ast.schemaTypes.enum);
|
|
@@ -997,7 +1228,7 @@ const typeGenerator = defineGenerator({
|
|
|
997
1228
|
}, {
|
|
998
1229
|
root,
|
|
999
1230
|
output,
|
|
1000
|
-
group
|
|
1231
|
+
group: group ?? void 0
|
|
1001
1232
|
})
|
|
1002
1233
|
};
|
|
1003
1234
|
const schemaPrinter = printerTs({
|
|
@@ -1016,13 +1247,21 @@ const typeGenerator = defineGenerator({
|
|
|
1016
1247
|
baseName: meta.file.baseName,
|
|
1017
1248
|
path: meta.file.path,
|
|
1018
1249
|
meta: meta.file.meta,
|
|
1019
|
-
banner: resolver.resolveBanner(
|
|
1250
|
+
banner: resolver.resolveBanner(ctx.meta, {
|
|
1020
1251
|
output,
|
|
1021
|
-
config
|
|
1252
|
+
config,
|
|
1253
|
+
file: {
|
|
1254
|
+
path: meta.file.path,
|
|
1255
|
+
baseName: meta.file.baseName
|
|
1256
|
+
}
|
|
1022
1257
|
}),
|
|
1023
|
-
footer: resolver.resolveFooter(
|
|
1258
|
+
footer: resolver.resolveFooter(ctx.meta, {
|
|
1024
1259
|
output,
|
|
1025
|
-
config
|
|
1260
|
+
config,
|
|
1261
|
+
file: {
|
|
1262
|
+
path: meta.file.path,
|
|
1263
|
+
baseName: meta.file.baseName
|
|
1264
|
+
}
|
|
1026
1265
|
}),
|
|
1027
1266
|
children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
|
|
1028
1267
|
root: meta.file.path,
|
|
@@ -1057,9 +1296,9 @@ const typeGenerator = defineGenerator({
|
|
|
1057
1296
|
}, {
|
|
1058
1297
|
root,
|
|
1059
1298
|
output,
|
|
1060
|
-
group
|
|
1299
|
+
group: group ?? void 0
|
|
1061
1300
|
}) };
|
|
1062
|
-
const enumSchemaNames = new Set(
|
|
1301
|
+
const enumSchemaNames = new Set(ctx.meta.enumNames);
|
|
1063
1302
|
function resolveImportName(schemaName) {
|
|
1064
1303
|
if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && enumTypeSuffix && enumSchemaNames.has(schemaName)) return resolver.resolveEnumKeyName({ name: schemaName }, enumTypeSuffix);
|
|
1065
1304
|
return resolver.resolveTypeName(schemaName);
|
|
@@ -1074,7 +1313,7 @@ const typeGenerator = defineGenerator({
|
|
|
1074
1313
|
}, {
|
|
1075
1314
|
root,
|
|
1076
1315
|
output,
|
|
1077
|
-
group
|
|
1316
|
+
group: group ?? void 0
|
|
1078
1317
|
}).path
|
|
1079
1318
|
}));
|
|
1080
1319
|
const schemaPrinter = printerTs({
|
|
@@ -1109,23 +1348,63 @@ const typeGenerator = defineGenerator({
|
|
|
1109
1348
|
printer: schemaPrinter
|
|
1110
1349
|
})] });
|
|
1111
1350
|
}
|
|
1351
|
+
/**
|
|
1352
|
+
* Emits an individual type per content type plus a union alias under `baseName`.
|
|
1353
|
+
* Shared by the request body and multi-content-type responses.
|
|
1354
|
+
*/
|
|
1355
|
+
function buildContentTypeVariants(entries, baseName, decorate) {
|
|
1356
|
+
const variants = resolveContentTypeVariants(entries, baseName);
|
|
1357
|
+
const unionSchema = ast.createSchema({
|
|
1358
|
+
type: "union",
|
|
1359
|
+
members: variants.map((variant) => ast.createSchema({
|
|
1360
|
+
type: "ref",
|
|
1361
|
+
name: variant.name
|
|
1362
|
+
}))
|
|
1363
|
+
});
|
|
1364
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [variants.map((variant) => renderSchemaType({
|
|
1365
|
+
schema: decorate ? decorate(variant.schema) : variant.schema,
|
|
1366
|
+
name: variant.name,
|
|
1367
|
+
keysToOmit: variant.keysToOmit
|
|
1368
|
+
})), renderSchemaType({
|
|
1369
|
+
schema: unionSchema,
|
|
1370
|
+
name: baseName
|
|
1371
|
+
})] });
|
|
1372
|
+
}
|
|
1112
1373
|
const paramTypes = params.map((param) => renderSchemaType({
|
|
1113
1374
|
schema: param.schema,
|
|
1114
1375
|
name: resolver.resolveParamName(node, param)
|
|
1115
1376
|
}));
|
|
1116
|
-
const
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1377
|
+
const requestBodyContent = node.requestBody?.content ?? [];
|
|
1378
|
+
function buildRequestType() {
|
|
1379
|
+
if (requestBodyContent.length === 0) return null;
|
|
1380
|
+
if (requestBodyContent.length === 1) {
|
|
1381
|
+
const entry = requestBodyContent[0];
|
|
1382
|
+
if (!entry.schema) return null;
|
|
1383
|
+
return renderSchemaType({
|
|
1384
|
+
schema: {
|
|
1385
|
+
...entry.schema,
|
|
1386
|
+
description: node.requestBody.description ?? entry.schema.description
|
|
1387
|
+
},
|
|
1388
|
+
name: resolver.resolveDataName(node),
|
|
1389
|
+
keysToOmit: entry.keysToOmit
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1392
|
+
return buildContentTypeVariants(requestBodyContent, resolver.resolveDataName(node), (schema) => ({
|
|
1393
|
+
...schema,
|
|
1394
|
+
description: node.requestBody.description ?? schema.description
|
|
1395
|
+
}));
|
|
1396
|
+
}
|
|
1397
|
+
const requestType = buildRequestType();
|
|
1398
|
+
const responseTypes = node.responses.map((res) => {
|
|
1399
|
+
const variants = (res.content ?? []).filter((entry) => entry.schema);
|
|
1400
|
+
if (variants.length > 1) return buildContentTypeVariants(variants, resolver.resolveResponseStatusName(node, res.statusCode));
|
|
1401
|
+
const primary = variants[0] ?? res.content?.[0];
|
|
1402
|
+
return renderSchemaType({
|
|
1403
|
+
schema: primary?.schema ?? null,
|
|
1404
|
+
name: resolver.resolveResponseStatusName(node, res.statusCode),
|
|
1405
|
+
keysToOmit: primary?.keysToOmit
|
|
1406
|
+
});
|
|
1407
|
+
});
|
|
1129
1408
|
const dataType = renderSchemaType({
|
|
1130
1409
|
schema: buildData({
|
|
1131
1410
|
...node,
|
|
@@ -1137,14 +1416,15 @@ const typeGenerator = defineGenerator({
|
|
|
1137
1416
|
schema: buildResponses(node, { resolver }),
|
|
1138
1417
|
name: resolver.resolveResponsesName(node)
|
|
1139
1418
|
});
|
|
1140
|
-
|
|
1141
|
-
|
|
1419
|
+
function buildResponseType() {
|
|
1420
|
+
const hasSchema = (res) => (res.content ?? []).some((entry) => entry.schema);
|
|
1421
|
+
if (!node.responses.some(hasSchema)) return null;
|
|
1142
1422
|
const responseName = resolver.resolveResponseName(node);
|
|
1143
|
-
const responsesWithSchema = node.responses.filter(
|
|
1144
|
-
if (new Set(responsesWithSchema.flatMap((res) => res.schema ? adapter.getImports(
|
|
1423
|
+
const responsesWithSchema = node.responses.filter(hasSchema);
|
|
1424
|
+
if (new Set(responsesWithSchema.flatMap((res) => (res.content ?? []).flatMap((entry) => entry.schema ? adapter.getImports(entry.schema, (schemaName) => ({
|
|
1145
1425
|
name: resolveImportName(schemaName),
|
|
1146
1426
|
path: ""
|
|
1147
|
-
})).flatMap((imp) => Array.isArray(imp.name) ? imp.name : [imp.name]) : [])).has(responseName)) return null;
|
|
1427
|
+
})).flatMap((imp) => Array.isArray(imp.name) ? imp.name : [imp.name]) : []))).has(responseName)) return null;
|
|
1148
1428
|
return renderSchemaType({
|
|
1149
1429
|
schema: {
|
|
1150
1430
|
...buildResponseUnion(node, { resolver }),
|
|
@@ -1152,18 +1432,27 @@ const typeGenerator = defineGenerator({
|
|
|
1152
1432
|
},
|
|
1153
1433
|
name: responseName
|
|
1154
1434
|
});
|
|
1155
|
-
}
|
|
1435
|
+
}
|
|
1436
|
+
const responseType = buildResponseType();
|
|
1156
1437
|
return /* @__PURE__ */ jsxs(File, {
|
|
1157
1438
|
baseName: meta.file.baseName,
|
|
1158
1439
|
path: meta.file.path,
|
|
1159
1440
|
meta: meta.file.meta,
|
|
1160
|
-
banner: resolver.resolveBanner(
|
|
1441
|
+
banner: resolver.resolveBanner(ctx.meta, {
|
|
1161
1442
|
output,
|
|
1162
|
-
config
|
|
1443
|
+
config,
|
|
1444
|
+
file: {
|
|
1445
|
+
path: meta.file.path,
|
|
1446
|
+
baseName: meta.file.baseName
|
|
1447
|
+
}
|
|
1163
1448
|
}),
|
|
1164
|
-
footer: resolver.resolveFooter(
|
|
1449
|
+
footer: resolver.resolveFooter(ctx.meta, {
|
|
1165
1450
|
output,
|
|
1166
|
-
config
|
|
1451
|
+
config,
|
|
1452
|
+
file: {
|
|
1453
|
+
path: meta.file.path,
|
|
1454
|
+
baseName: meta.file.baseName
|
|
1455
|
+
}
|
|
1167
1456
|
}),
|
|
1168
1457
|
children: [
|
|
1169
1458
|
paramTypes,
|
|
@@ -1179,86 +1468,98 @@ const typeGenerator = defineGenerator({
|
|
|
1179
1468
|
//#endregion
|
|
1180
1469
|
//#region src/resolvers/resolverTs.ts
|
|
1181
1470
|
/**
|
|
1182
|
-
*
|
|
1183
|
-
*
|
|
1184
|
-
*
|
|
1471
|
+
* Default resolver used by `@kubb/plugin-ts`. Decides the names and file paths
|
|
1472
|
+
* for every generated TypeScript type. Import this in other plugins that need
|
|
1473
|
+
* to reference the exact names `plugin-ts` produces without duplicating the
|
|
1474
|
+
* casing/file-layout rules.
|
|
1185
1475
|
*
|
|
1186
|
-
* The `default` method is
|
|
1187
|
-
*
|
|
1476
|
+
* The `default` method is supplied by `defineResolver`. It uses PascalCase for
|
|
1477
|
+
* type names and PascalCase-with-isFile for files.
|
|
1188
1478
|
*
|
|
1189
|
-
* @example
|
|
1479
|
+
* @example Resolve a type and file name
|
|
1190
1480
|
* ```ts
|
|
1191
|
-
* import {
|
|
1481
|
+
* import { resolverTs } from '@kubb/plugin-ts'
|
|
1192
1482
|
*
|
|
1193
|
-
*
|
|
1194
|
-
*
|
|
1195
|
-
*
|
|
1483
|
+
* resolverTs.default('list pets', 'type') // 'ListPets'
|
|
1484
|
+
* resolverTs.resolvePathName('list pets', 'file') // 'ListPets'
|
|
1485
|
+
* resolverTs.resolveResponseStatusName(node, 200) // 'ListPetsStatus200'
|
|
1196
1486
|
* ```
|
|
1197
1487
|
*/
|
|
1198
|
-
const resolverTs = defineResolver((
|
|
1488
|
+
const resolverTs = defineResolver(() => {
|
|
1199
1489
|
return {
|
|
1200
1490
|
name: "default",
|
|
1201
1491
|
pluginName: "plugin-ts",
|
|
1202
1492
|
default(name, type) {
|
|
1203
|
-
|
|
1493
|
+
const resolved = pascalCase(name, { isFile: type === "file" });
|
|
1494
|
+
return type === "file" ? resolved : ensureValidVarName(resolved);
|
|
1204
1495
|
},
|
|
1205
1496
|
resolveTypeName(name) {
|
|
1206
|
-
return pascalCase(name);
|
|
1497
|
+
return ensureValidVarName(pascalCase(name));
|
|
1207
1498
|
},
|
|
1208
1499
|
resolvePathName(name, type) {
|
|
1209
|
-
|
|
1500
|
+
const resolved = pascalCase(name, { isFile: type === "file" });
|
|
1501
|
+
return type === "file" ? resolved : ensureValidVarName(resolved);
|
|
1210
1502
|
},
|
|
1211
1503
|
resolveParamName(node, param) {
|
|
1212
|
-
return
|
|
1504
|
+
return this.resolveTypeName(`${node.operationId} ${param.in} ${param.name}`);
|
|
1213
1505
|
},
|
|
1214
1506
|
resolveResponseStatusName(node, statusCode) {
|
|
1215
|
-
return
|
|
1507
|
+
return this.resolveTypeName(`${node.operationId} Status ${statusCode}`);
|
|
1216
1508
|
},
|
|
1217
1509
|
resolveDataName(node) {
|
|
1218
|
-
return
|
|
1510
|
+
return this.resolveTypeName(`${node.operationId} Data`);
|
|
1219
1511
|
},
|
|
1220
1512
|
resolveRequestConfigName(node) {
|
|
1221
|
-
return
|
|
1513
|
+
return this.resolveTypeName(`${node.operationId} RequestConfig`);
|
|
1222
1514
|
},
|
|
1223
1515
|
resolveResponsesName(node) {
|
|
1224
|
-
return
|
|
1516
|
+
return this.resolveTypeName(`${node.operationId} Responses`);
|
|
1225
1517
|
},
|
|
1226
1518
|
resolveResponseName(node) {
|
|
1227
|
-
return
|
|
1519
|
+
return this.resolveTypeName(`${node.operationId} Response`);
|
|
1228
1520
|
},
|
|
1229
1521
|
resolveEnumKeyName(node, enumTypeSuffix = "key") {
|
|
1230
|
-
return `${
|
|
1522
|
+
return `${this.resolveTypeName(node.name ?? "")}${enumTypeSuffix}`;
|
|
1231
1523
|
},
|
|
1232
1524
|
resolvePathParamsName(node, param) {
|
|
1233
|
-
return
|
|
1525
|
+
return this.resolveParamName(node, param);
|
|
1234
1526
|
},
|
|
1235
1527
|
resolveQueryParamsName(node, param) {
|
|
1236
|
-
return
|
|
1528
|
+
return this.resolveParamName(node, param);
|
|
1237
1529
|
},
|
|
1238
1530
|
resolveHeaderParamsName(node, param) {
|
|
1239
|
-
return
|
|
1531
|
+
return this.resolveParamName(node, param);
|
|
1240
1532
|
}
|
|
1241
1533
|
};
|
|
1242
1534
|
});
|
|
1243
1535
|
//#endregion
|
|
1244
1536
|
//#region src/plugin.ts
|
|
1245
1537
|
/**
|
|
1246
|
-
* Canonical plugin name for `@kubb/plugin-ts
|
|
1538
|
+
* Canonical plugin name for `@kubb/plugin-ts`. Used for driver lookups and
|
|
1539
|
+
* cross-plugin dependency references.
|
|
1247
1540
|
*/
|
|
1248
1541
|
const pluginTsName = "plugin-ts";
|
|
1249
1542
|
/**
|
|
1250
|
-
*
|
|
1251
|
-
*
|
|
1252
|
-
*
|
|
1253
|
-
*
|
|
1254
|
-
* and writes barrel files based on `output.barrelType`.
|
|
1543
|
+
* Generates TypeScript `type` aliases and `interface` declarations from an
|
|
1544
|
+
* OpenAPI spec. The foundation that every other Kubb plugin builds on:
|
|
1545
|
+
* clients, query hooks, mocks, and validators all reference the names this
|
|
1546
|
+
* plugin produces.
|
|
1255
1547
|
*
|
|
1256
1548
|
* @example
|
|
1257
1549
|
* ```ts
|
|
1258
|
-
* import
|
|
1550
|
+
* import { defineConfig } from 'kubb'
|
|
1551
|
+
* import { pluginTs } from '@kubb/plugin-ts'
|
|
1259
1552
|
*
|
|
1260
1553
|
* export default defineConfig({
|
|
1261
|
-
*
|
|
1554
|
+
* input: { path: './petStore.yaml' },
|
|
1555
|
+
* output: { path: './src/gen' },
|
|
1556
|
+
* plugins: [
|
|
1557
|
+
* pluginTs({
|
|
1558
|
+
* output: { path: './types' },
|
|
1559
|
+
* enumType: 'asConst',
|
|
1560
|
+
* optionalType: 'questionTokenAndUndefined',
|
|
1561
|
+
* }),
|
|
1562
|
+
* ],
|
|
1262
1563
|
* })
|
|
1263
1564
|
* ```
|
|
1264
1565
|
*/
|
|
@@ -1267,13 +1568,7 @@ const pluginTs = definePlugin((options) => {
|
|
|
1267
1568
|
path: "types",
|
|
1268
1569
|
barrelType: "named"
|
|
1269
1570
|
}, group, exclude = [], include, override = [], enumType = "asConst", enumTypeSuffix = "Key", enumKeyCasing = "none", optionalType = "questionToken", arrayType = "array", syntaxType = "type", paramsCasing, printer, resolver: userResolver, transformer: userTransformer, generators: userGenerators = [] } = options;
|
|
1270
|
-
const groupConfig = group
|
|
1271
|
-
...group,
|
|
1272
|
-
name: (ctx) => {
|
|
1273
|
-
if (group.type === "path") return `${ctx.group.split("/")[1]}`;
|
|
1274
|
-
return `${camelCase(ctx.group)}Controller`;
|
|
1275
|
-
}
|
|
1276
|
-
} : void 0;
|
|
1571
|
+
const groupConfig = createGroupConfig(group, { suffix: "Controller" });
|
|
1277
1572
|
return {
|
|
1278
1573
|
name: pluginTsName,
|
|
1279
1574
|
options,
|