@kubb/plugin-ts 5.0.0-beta.84 → 5.0.0-beta.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +223 -130
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +172 -140
- package/dist/index.js +223 -131
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as __name, t as __exportAll } from "./rolldown-runtime-CNktS9qV.js";
|
|
2
|
-
import { ast, defineGenerator, definePlugin, defineResolver } from "kubb/kit";
|
|
3
2
|
import { parserTs } from "@kubb/parser-ts";
|
|
4
3
|
import { File, jsxRenderer } from "kubb/jsx";
|
|
4
|
+
import { Resolver, ast, createResolver, defineGenerator, definePlugin } from "kubb/kit";
|
|
5
5
|
import ts from "typescript";
|
|
6
6
|
import { Fragment, jsx, jsxs } from "kubb/jsx/jsx-runtime";
|
|
7
7
|
//#region ../../internals/utils/src/casing.ts
|
|
@@ -192,7 +192,7 @@ const reservedWords = /* @__PURE__ */ new Set([
|
|
|
192
192
|
*/
|
|
193
193
|
function isValidVarName(name) {
|
|
194
194
|
if (!name || reservedWords.has(name)) return false;
|
|
195
|
-
return
|
|
195
|
+
return isIdentifier(name);
|
|
196
196
|
}
|
|
197
197
|
/**
|
|
198
198
|
* Returns `name` when it's a syntactically valid JavaScript variable name,
|
|
@@ -214,6 +214,83 @@ function ensureValidVarName(name) {
|
|
|
214
214
|
if (!name || isValidVarName(name)) return name;
|
|
215
215
|
return `_${name}`;
|
|
216
216
|
}
|
|
217
|
+
/**
|
|
218
|
+
* Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
|
|
219
|
+
*
|
|
220
|
+
* Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
|
|
221
|
+
* even though they are not valid variable names, so use this (not {@link isValidVarName}) when
|
|
222
|
+
* deciding whether an object key needs quoting.
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* ```ts
|
|
226
|
+
* isIdentifier('name') // true
|
|
227
|
+
* isIdentifier('x-total')// false
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
function isIdentifier(name) {
|
|
231
|
+
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
232
|
+
}
|
|
233
|
+
//#endregion
|
|
234
|
+
//#region ../../internals/utils/src/strings.ts
|
|
235
|
+
/**
|
|
236
|
+
* Strips a single matching pair of `"..."`, `'...'`, or `` `...` `` from both ends of `text`.
|
|
237
|
+
* Returns the string unchanged when no balanced quote pair is found.
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```ts
|
|
241
|
+
* trimQuotes('"hello"') // 'hello'
|
|
242
|
+
* trimQuotes('hello') // 'hello'
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
function trimQuotes(text) {
|
|
246
|
+
if (text.length >= 2) {
|
|
247
|
+
const first = text[0];
|
|
248
|
+
const last = text[text.length - 1];
|
|
249
|
+
if (first === "\"" && last === "\"" || first === "'" && last === "'" || first === "`" && last === "`") return text.slice(1, -1);
|
|
250
|
+
}
|
|
251
|
+
return text;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Serializes a primitive to a single-quoted string literal, stripping any surrounding quotes first.
|
|
255
|
+
*
|
|
256
|
+
* Escaping runs through `JSON.stringify`, then the result switches to single quotes so the generated
|
|
257
|
+
* code matches the repo style without a formatter.
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ```ts
|
|
261
|
+
* stringify('hello') // "'hello'"
|
|
262
|
+
* stringify('"hello"') // "'hello'"
|
|
263
|
+
* ```
|
|
264
|
+
*/
|
|
265
|
+
function stringify(value) {
|
|
266
|
+
if (value === void 0 || value === null) return "''";
|
|
267
|
+
return `'${JSON.stringify(trimQuotes(value.toString())).slice(1, -1).replace(/\\"/g, "\"").replace(/'/g, "\\'")}'`;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Escapes characters that are not allowed inside JS string literals, covering quotes, backslashes,
|
|
271
|
+
* and the Unicode line terminators U+2028 and U+2029.
|
|
272
|
+
*
|
|
273
|
+
* @see http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* ```ts
|
|
277
|
+
* jsStringEscape('say "hi"\nbye') // 'say \\"hi\\"\\nbye'
|
|
278
|
+
* ```
|
|
279
|
+
*/
|
|
280
|
+
function jsStringEscape(input) {
|
|
281
|
+
return `${input}`.replace(/["'\\\n\r\u2028\u2029]/g, (character) => {
|
|
282
|
+
switch (character) {
|
|
283
|
+
case "\"":
|
|
284
|
+
case "'":
|
|
285
|
+
case "\\": return `\\${character}`;
|
|
286
|
+
case "\n": return "\\n";
|
|
287
|
+
case "\r": return "\\r";
|
|
288
|
+
case "\u2028": return "\\u2028";
|
|
289
|
+
case "\u2029": return "\\u2029";
|
|
290
|
+
default: return "";
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
}
|
|
217
294
|
//#endregion
|
|
218
295
|
//#region src/constants.ts
|
|
219
296
|
/**
|
|
@@ -799,10 +876,10 @@ function buildIndexSignatures(node, propertyCount, print) {
|
|
|
799
876
|
* resolve to the same name, which TypeScript merges into a single value+type declaration.
|
|
800
877
|
*/
|
|
801
878
|
function getEnumNames({ node, enum: enumOptions, resolver }) {
|
|
802
|
-
const resolved = resolver.
|
|
879
|
+
const resolved = resolver.name(node.name);
|
|
803
880
|
return {
|
|
804
881
|
enumName: enumOptions.constCasing === "pascalCase" ? resolved : camelCase(node.name),
|
|
805
|
-
typeName: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumOptions.type) ? resolver.
|
|
882
|
+
typeName: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumOptions.type) ? resolver.enum.keyName(node, enumOptions.typeSuffix) : resolved
|
|
806
883
|
};
|
|
807
884
|
}
|
|
808
885
|
/**
|
|
@@ -826,10 +903,10 @@ function Enum({ node, enum: enumOptions, resolver }) {
|
|
|
826
903
|
name: enumName,
|
|
827
904
|
typeName,
|
|
828
905
|
enums: node.namedEnumValues?.map((v) => [
|
|
829
|
-
|
|
906
|
+
trimQuotes(v.name.toString()),
|
|
830
907
|
v.value,
|
|
831
908
|
v.description
|
|
832
|
-
]) ?? node.enumValues?.filter((v) => v !== null && v !== void 0).map((v) => [
|
|
909
|
+
]) ?? node.enumValues?.filter((v) => v !== null && v !== void 0).map((v) => [trimQuotes(v.toString()), v]) ?? [],
|
|
833
910
|
type: enumOptions.type,
|
|
834
911
|
enumKeyCasing: enumOptions.keyCasing
|
|
835
912
|
});
|
|
@@ -1007,32 +1084,36 @@ function buildPropertyJSDocComments(schema, optional) {
|
|
|
1007
1084
|
const formatComment = meta && "format" in meta && meta.format ? hasDescription ? [" ", `Format: \`${meta.format}\``] : ["@description", `Format: \`${meta.format}\``] : [];
|
|
1008
1085
|
const exampleValues = meta?.examples ?? [];
|
|
1009
1086
|
return [
|
|
1010
|
-
hasDescription ? `@description ${
|
|
1087
|
+
hasDescription ? `@description ${jsStringEscape(meta.description)}` : null,
|
|
1011
1088
|
...formatComment,
|
|
1012
1089
|
meta && "deprecated" in meta && meta.deprecated ? "@deprecated" : null,
|
|
1013
1090
|
!isArray && meta && "min" in meta && meta.min !== void 0 ? `@minLength ${meta.min}` : null,
|
|
1014
1091
|
!isArray && meta && "max" in meta && meta.max !== void 0 ? `@maxLength ${meta.max}` : null,
|
|
1015
1092
|
meta && "pattern" in meta && meta.pattern ? `@pattern ${meta.pattern}` : null,
|
|
1016
|
-
meta && "default" in meta && meta.default !== void 0 ? `@default ${"primitive" in meta && meta.primitive === "string" ?
|
|
1093
|
+
meta && "default" in meta && meta.default !== void 0 ? `@default ${"primitive" in meta && meta.primitive === "string" ? stringify(meta.default) : meta.default}` : null,
|
|
1017
1094
|
...exampleValues.map((example) => `@example ${example}`),
|
|
1018
1095
|
meta && "primitive" in meta && meta.primitive ? [`@type ${meta.primitive}`, optional ?? isSchemaOptional(schema) ? " | undefined" : null].filter(Boolean).join("") : null
|
|
1019
1096
|
].filter(Boolean);
|
|
1020
1097
|
}
|
|
1021
|
-
|
|
1098
|
+
/**
|
|
1099
|
+
* Builds the object schema for a group of parameters sharing one `in` location (path, query, or
|
|
1100
|
+
* header), embedding each param's own schema (and JSDoc) directly rather than referencing a
|
|
1101
|
+
* separate per-param type — the group itself is the only type these params get exported as.
|
|
1102
|
+
*/
|
|
1103
|
+
function buildParams({ params }) {
|
|
1022
1104
|
return ast.factory.createSchema({
|
|
1023
1105
|
type: "object",
|
|
1024
1106
|
properties: params.map((param) => ast.factory.createProperty({
|
|
1025
1107
|
name: param.name,
|
|
1026
1108
|
required: param.required,
|
|
1027
1109
|
schema: ast.factory.createSchema({
|
|
1028
|
-
|
|
1029
|
-
name: resolver.resolveParamName(node, param),
|
|
1110
|
+
...param.schema,
|
|
1030
1111
|
optional: !param.required
|
|
1031
1112
|
})
|
|
1032
1113
|
}))
|
|
1033
1114
|
});
|
|
1034
1115
|
}
|
|
1035
|
-
function
|
|
1116
|
+
function buildOptions(node, { resolver }) {
|
|
1036
1117
|
const { path: pathParams, query: queryParams, header: headerParams } = getOperationParameters(node, { paramsCasing: "original" });
|
|
1037
1118
|
const hasBody = Boolean(node.requestBody?.content?.[0]?.schema);
|
|
1038
1119
|
const hasRequiredPath = pathParams.some((param) => param.required);
|
|
@@ -1047,7 +1128,7 @@ function buildData(node, { resolver }) {
|
|
|
1047
1128
|
required: hasBody,
|
|
1048
1129
|
schema: hasBody ? ast.factory.createSchema({
|
|
1049
1130
|
type: "ref",
|
|
1050
|
-
name: resolver.
|
|
1131
|
+
name: resolver.response.body(node)
|
|
1051
1132
|
}) : ast.factory.createSchema({
|
|
1052
1133
|
type: "never",
|
|
1053
1134
|
primitive: void 0,
|
|
@@ -1058,10 +1139,8 @@ function buildData(node, { resolver }) {
|
|
|
1058
1139
|
name: "path",
|
|
1059
1140
|
required: hasRequiredPath,
|
|
1060
1141
|
schema: pathParams.length > 0 ? ast.factory.createSchema({
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
resolver
|
|
1064
|
-
}),
|
|
1142
|
+
type: "ref",
|
|
1143
|
+
name: resolver.param.path(node, pathParams[0]),
|
|
1065
1144
|
optional: !hasRequiredPath
|
|
1066
1145
|
}) : ast.factory.createSchema({
|
|
1067
1146
|
type: "never",
|
|
@@ -1073,10 +1152,8 @@ function buildData(node, { resolver }) {
|
|
|
1073
1152
|
name: "query",
|
|
1074
1153
|
required: hasRequiredQuery,
|
|
1075
1154
|
schema: queryParams.length > 0 ? ast.factory.createSchema({
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
resolver
|
|
1079
|
-
}),
|
|
1155
|
+
type: "ref",
|
|
1156
|
+
name: resolver.param.query(node, queryParams[0]),
|
|
1080
1157
|
optional: !hasRequiredQuery
|
|
1081
1158
|
}) : ast.factory.createSchema({
|
|
1082
1159
|
type: "never",
|
|
@@ -1088,10 +1165,8 @@ function buildData(node, { resolver }) {
|
|
|
1088
1165
|
name: "headers",
|
|
1089
1166
|
required: hasRequiredHeader,
|
|
1090
1167
|
schema: headerParams.length > 0 ? ast.factory.createSchema({
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
resolver
|
|
1094
|
-
}),
|
|
1168
|
+
type: "ref",
|
|
1169
|
+
name: resolver.param.headers(node, headerParams[0]),
|
|
1095
1170
|
optional: !hasRequiredHeader
|
|
1096
1171
|
}) : ast.factory.createSchema({
|
|
1097
1172
|
type: "never",
|
|
@@ -1109,7 +1184,7 @@ function buildData(node, { resolver }) {
|
|
|
1109
1184
|
* query hooks and `result.data` use.
|
|
1110
1185
|
*/
|
|
1111
1186
|
function buildResponseRecordEntry(node, res, resolver) {
|
|
1112
|
-
const statusName = resolver.
|
|
1187
|
+
const statusName = resolver.response.status(node, res.statusCode);
|
|
1113
1188
|
const variants = (res.content ?? []).filter((entry) => entry.schema);
|
|
1114
1189
|
if (variants.length <= 1) return ast.factory.createSchema({
|
|
1115
1190
|
type: "ref",
|
|
@@ -1154,7 +1229,7 @@ function buildResponseUnion(node, { resolver }) {
|
|
|
1154
1229
|
type: "union",
|
|
1155
1230
|
members: responsesWithSchema.map((res) => ast.factory.createSchema({
|
|
1156
1231
|
type: "ref",
|
|
1157
|
-
name: resolver.
|
|
1232
|
+
name: resolver.response.status(node, res.statusCode)
|
|
1158
1233
|
}))
|
|
1159
1234
|
});
|
|
1160
1235
|
}
|
|
@@ -1248,7 +1323,7 @@ const printerTs = ast.createPrinter((options) => {
|
|
|
1248
1323
|
ref(node) {
|
|
1249
1324
|
if (!node.name) return null;
|
|
1250
1325
|
const refName = node.ref ? this.options.nameMapping?.get(node.ref) ?? ast.extractRefName(node.ref) ?? node.name : node.name;
|
|
1251
|
-
return createTypeReferenceNode(node.ref && ENUM_TYPES_WITH_KEY_SUFFIX.has(this.options.enum.type) && this.options.enum.typeSuffix && this.options.enumSchemaNames?.has(refName) ? this.options.resolver.
|
|
1326
|
+
return createTypeReferenceNode(node.ref && ENUM_TYPES_WITH_KEY_SUFFIX.has(this.options.enum.type) && this.options.enum.typeSuffix && this.options.enumSchemaNames?.has(refName) ? this.options.resolver.enum.keyName({ name: refName }, this.options.enum.typeSuffix) : node.ref ? this.options.resolver.name(refName) : refName, void 0);
|
|
1252
1327
|
},
|
|
1253
1328
|
enum(node) {
|
|
1254
1329
|
const values = node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? [];
|
|
@@ -1256,7 +1331,7 @@ const printerTs = ast.createPrinter((options) => {
|
|
|
1256
1331
|
withParentheses: true,
|
|
1257
1332
|
nodes: values.filter((v) => v !== null && v !== void 0).map((value) => constToTypeNode(value, typeof value)).filter(isNonNullable)
|
|
1258
1333
|
}) ?? void 0;
|
|
1259
|
-
return createTypeReferenceNode(ENUM_TYPES_WITH_KEY_SUFFIX.has(this.options.enum.type) && this.options.enum.typeSuffix ? this.options.resolver.
|
|
1334
|
+
return createTypeReferenceNode(ENUM_TYPES_WITH_KEY_SUFFIX.has(this.options.enum.type) && this.options.enum.typeSuffix ? this.options.resolver.enum.keyName(node, this.options.enum.typeSuffix) : this.options.resolver.name(node.name), void 0);
|
|
1260
1335
|
},
|
|
1261
1336
|
union(node) {
|
|
1262
1337
|
const members = node.members ?? [];
|
|
@@ -1354,6 +1429,15 @@ const printerTs = ast.createPrinter((options) => {
|
|
|
1354
1429
|
//#endregion
|
|
1355
1430
|
//#region src/generators/typeGenerator.tsx
|
|
1356
1431
|
/**
|
|
1432
|
+
* Resolves the imported type name for a referenced schema. An enum schema emitted
|
|
1433
|
+
* as a `const` object imports its suffixed key alias (e.g. `StatusKey`); every other
|
|
1434
|
+
* schema imports its plain resolved name.
|
|
1435
|
+
*/
|
|
1436
|
+
function resolveImportName({ schemaName, enumOptions, enumSchemaNames, resolver }) {
|
|
1437
|
+
if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumOptions.type) && enumOptions.typeSuffix && enumSchemaNames.has(schemaName)) return resolver.enum.keyName({ name: schemaName }, enumOptions.typeSuffix);
|
|
1438
|
+
return resolver.name(schemaName);
|
|
1439
|
+
}
|
|
1440
|
+
/**
|
|
1357
1441
|
* Built-in generator for `@kubb/plugin-ts`. Emits one TypeScript file per
|
|
1358
1442
|
* schema in the spec plus per-operation request, response, and parameter
|
|
1359
1443
|
* types. Drop-replace with a custom `Generator<PluginTs>` to change how
|
|
@@ -1367,16 +1451,16 @@ const typeGenerator = defineGenerator({
|
|
|
1367
1451
|
const { adapter, config, resolver, root } = ctx;
|
|
1368
1452
|
if (!node.name) return;
|
|
1369
1453
|
const enumSchemaNames = new Set(ctx.meta.enumNames);
|
|
1370
|
-
function resolveImportName(schemaName) {
|
|
1371
|
-
if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumOptions.type) && enumOptions.typeSuffix && enumSchemaNames.has(schemaName)) return resolver.resolveEnumKeyName({ name: schemaName }, enumOptions.typeSuffix);
|
|
1372
|
-
return resolver.resolveTypeName(schemaName);
|
|
1373
|
-
}
|
|
1374
1454
|
const imports = adapter.getImports(node, (schemaName) => ({
|
|
1375
|
-
name: resolveImportName(
|
|
1376
|
-
|
|
1455
|
+
name: resolveImportName({
|
|
1456
|
+
schemaName,
|
|
1457
|
+
enumOptions,
|
|
1458
|
+
enumSchemaNames,
|
|
1459
|
+
resolver
|
|
1460
|
+
}),
|
|
1461
|
+
path: resolver.file({
|
|
1377
1462
|
name: schemaName,
|
|
1378
|
-
extname: ".ts"
|
|
1379
|
-
}, {
|
|
1463
|
+
extname: ".ts",
|
|
1380
1464
|
root,
|
|
1381
1465
|
output,
|
|
1382
1466
|
group: group ?? void 0
|
|
@@ -1385,11 +1469,10 @@ const typeGenerator = defineGenerator({
|
|
|
1385
1469
|
const enumNode = ast.narrowSchema(node, ast.schemaTypes.enum);
|
|
1386
1470
|
const isEnumSchema = !!enumNode && !isInlineConstEnum(enumNode, enumSchemaNames);
|
|
1387
1471
|
const meta = {
|
|
1388
|
-
name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumOptions.type) && isEnumSchema ? resolver.
|
|
1389
|
-
file: resolver.
|
|
1472
|
+
name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumOptions.type) && isEnumSchema ? resolver.enum.keyName(node, enumOptions.typeSuffix) : resolver.name(node.name),
|
|
1473
|
+
file: resolver.file({
|
|
1390
1474
|
name: node.name,
|
|
1391
|
-
extname: ".ts"
|
|
1392
|
-
}, {
|
|
1475
|
+
extname: ".ts",
|
|
1393
1476
|
root,
|
|
1394
1477
|
output,
|
|
1395
1478
|
group: group ?? void 0
|
|
@@ -1411,7 +1494,7 @@ const typeGenerator = defineGenerator({
|
|
|
1411
1494
|
baseName: meta.file.baseName,
|
|
1412
1495
|
path: meta.file.path,
|
|
1413
1496
|
meta: meta.file.meta,
|
|
1414
|
-
banner: resolver.
|
|
1497
|
+
banner: resolver.default.banner(ctx.meta, {
|
|
1415
1498
|
output,
|
|
1416
1499
|
config,
|
|
1417
1500
|
file: {
|
|
@@ -1419,7 +1502,7 @@ const typeGenerator = defineGenerator({
|
|
|
1419
1502
|
baseName: meta.file.baseName
|
|
1420
1503
|
}
|
|
1421
1504
|
}),
|
|
1422
|
-
footer: resolver.
|
|
1505
|
+
footer: resolver.default.footer(ctx.meta, {
|
|
1423
1506
|
output,
|
|
1424
1507
|
config,
|
|
1425
1508
|
file: {
|
|
@@ -1449,29 +1532,28 @@ const typeGenerator = defineGenerator({
|
|
|
1449
1532
|
const { enum: enumOptions, optionalType, arrayType, syntaxType, group, output, printer } = ctx.options;
|
|
1450
1533
|
const { adapter, config, resolver, root } = ctx;
|
|
1451
1534
|
const params = caseParams(node.parameters, "camelcase");
|
|
1452
|
-
const meta = { file: resolver.
|
|
1535
|
+
const meta = { file: resolver.file({
|
|
1453
1536
|
name: node.operationId,
|
|
1454
1537
|
extname: ".ts",
|
|
1455
1538
|
tag: node.tags[0] ?? "default",
|
|
1456
|
-
path: node.path
|
|
1457
|
-
}, {
|
|
1539
|
+
path: node.path,
|
|
1458
1540
|
root,
|
|
1459
1541
|
output,
|
|
1460
1542
|
group: group ?? void 0
|
|
1461
1543
|
}) };
|
|
1462
1544
|
const enumSchemaNames = new Set(ctx.meta.enumNames);
|
|
1463
|
-
function resolveImportName(schemaName) {
|
|
1464
|
-
if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumOptions.type) && enumOptions.typeSuffix && enumSchemaNames.has(schemaName)) return resolver.resolveEnumKeyName({ name: schemaName }, enumOptions.typeSuffix);
|
|
1465
|
-
return resolver.resolveTypeName(schemaName);
|
|
1466
|
-
}
|
|
1467
1545
|
function renderSchemaType({ schema, name, keysToOmit }) {
|
|
1468
1546
|
if (!schema) return null;
|
|
1469
1547
|
const imports = adapter.getImports(schema, (schemaName) => ({
|
|
1470
|
-
name: resolveImportName(
|
|
1471
|
-
|
|
1548
|
+
name: resolveImportName({
|
|
1549
|
+
schemaName,
|
|
1550
|
+
enumOptions,
|
|
1551
|
+
enumSchemaNames,
|
|
1552
|
+
resolver
|
|
1553
|
+
}),
|
|
1554
|
+
path: resolver.file({
|
|
1472
1555
|
name: schemaName,
|
|
1473
|
-
extname: ".ts"
|
|
1474
|
-
}, {
|
|
1556
|
+
extname: ".ts",
|
|
1475
1557
|
root,
|
|
1476
1558
|
output,
|
|
1477
1559
|
group: group ?? void 0
|
|
@@ -1531,13 +1613,24 @@ const typeGenerator = defineGenerator({
|
|
|
1531
1613
|
name: baseName
|
|
1532
1614
|
})] });
|
|
1533
1615
|
}
|
|
1534
|
-
const
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1616
|
+
const { path: pathParams, query: queryParams, header: headerParams } = getOperationParameters({
|
|
1617
|
+
...node,
|
|
1618
|
+
parameters: params
|
|
1619
|
+
}, { paramsCasing: "original" });
|
|
1620
|
+
const paramGroupTypes = [
|
|
1621
|
+
pathParams.length > 0 && renderSchemaType({
|
|
1622
|
+
schema: buildParams({ params: pathParams }),
|
|
1623
|
+
name: resolver.param.path(node, pathParams[0])
|
|
1624
|
+
}),
|
|
1625
|
+
queryParams.length > 0 && renderSchemaType({
|
|
1626
|
+
schema: buildParams({ params: queryParams }),
|
|
1627
|
+
name: resolver.param.query(node, queryParams[0])
|
|
1628
|
+
}),
|
|
1629
|
+
headerParams.length > 0 && renderSchemaType({
|
|
1630
|
+
schema: buildParams({ params: headerParams }),
|
|
1631
|
+
name: resolver.param.headers(node, headerParams[0])
|
|
1632
|
+
})
|
|
1633
|
+
];
|
|
1541
1634
|
const requestBodyContent = node.requestBody?.content ?? [];
|
|
1542
1635
|
function buildRequestType() {
|
|
1543
1636
|
if (requestBodyContent.length === 0) return null;
|
|
@@ -1549,11 +1642,11 @@ const typeGenerator = defineGenerator({
|
|
|
1549
1642
|
...entry.schema,
|
|
1550
1643
|
description: node.requestBody.description ?? entry.schema.description
|
|
1551
1644
|
},
|
|
1552
|
-
name: resolver.
|
|
1645
|
+
name: resolver.response.body(node),
|
|
1553
1646
|
keysToOmit: entry.keysToOmit
|
|
1554
1647
|
});
|
|
1555
1648
|
}
|
|
1556
|
-
return buildContentTypeVariants(requestBodyContent, resolver.
|
|
1649
|
+
return buildContentTypeVariants(requestBodyContent, resolver.response.body(node), (schema) => ({
|
|
1557
1650
|
...schema,
|
|
1558
1651
|
description: node.requestBody.description ?? schema.description
|
|
1559
1652
|
}));
|
|
@@ -1561,32 +1654,37 @@ const typeGenerator = defineGenerator({
|
|
|
1561
1654
|
const requestType = buildRequestType();
|
|
1562
1655
|
const responseTypes = node.responses.map((res) => {
|
|
1563
1656
|
const variants = (res.content ?? []).filter((entry) => entry.schema);
|
|
1564
|
-
if (variants.length > 1) return buildContentTypeVariants(variants, resolver.
|
|
1657
|
+
if (variants.length > 1) return buildContentTypeVariants(variants, resolver.response.status(node, res.statusCode));
|
|
1565
1658
|
const primary = variants[0] ?? res.content?.[0];
|
|
1566
1659
|
return renderSchemaType({
|
|
1567
1660
|
schema: primary?.schema ?? null,
|
|
1568
|
-
name: resolver.
|
|
1661
|
+
name: resolver.response.status(node, res.statusCode),
|
|
1569
1662
|
keysToOmit: primary?.keysToOmit
|
|
1570
1663
|
});
|
|
1571
1664
|
});
|
|
1572
|
-
const
|
|
1573
|
-
schema:
|
|
1665
|
+
const optionsType = renderSchemaType({
|
|
1666
|
+
schema: buildOptions({
|
|
1574
1667
|
...node,
|
|
1575
1668
|
parameters: params
|
|
1576
1669
|
}, { resolver }),
|
|
1577
|
-
name: resolver.
|
|
1670
|
+
name: resolver.response.options(node)
|
|
1578
1671
|
});
|
|
1579
1672
|
const responsesType = renderSchemaType({
|
|
1580
1673
|
schema: buildResponses(node, { resolver }),
|
|
1581
|
-
name: resolver.
|
|
1674
|
+
name: resolver.response.responses(node)
|
|
1582
1675
|
});
|
|
1583
1676
|
function buildResponseType() {
|
|
1584
1677
|
const hasSchema = (res) => (res.content ?? []).some((entry) => entry.schema);
|
|
1585
1678
|
if (!node.responses.some(hasSchema)) return null;
|
|
1586
|
-
const responseName = resolver.
|
|
1679
|
+
const responseName = resolver.response.response(node);
|
|
1587
1680
|
const responsesWithSchema = node.responses.filter(hasSchema);
|
|
1588
1681
|
if (new Set(responsesWithSchema.flatMap((res) => (res.content ?? []).flatMap((entry) => entry.schema ? adapter.getImports(entry.schema, (schemaName) => ({
|
|
1589
|
-
name: resolveImportName(
|
|
1682
|
+
name: resolveImportName({
|
|
1683
|
+
schemaName,
|
|
1684
|
+
enumOptions,
|
|
1685
|
+
enumSchemaNames,
|
|
1686
|
+
resolver
|
|
1687
|
+
}),
|
|
1590
1688
|
path: ""
|
|
1591
1689
|
})).flatMap((imp) => Array.isArray(imp.name) ? imp.name : [imp.name]) : []))).has(responseName)) return null;
|
|
1592
1690
|
return renderSchemaType({
|
|
@@ -1602,7 +1700,7 @@ const typeGenerator = defineGenerator({
|
|
|
1602
1700
|
baseName: meta.file.baseName,
|
|
1603
1701
|
path: meta.file.path,
|
|
1604
1702
|
meta: meta.file.meta,
|
|
1605
|
-
banner: resolver.
|
|
1703
|
+
banner: resolver.default.banner(ctx.meta, {
|
|
1606
1704
|
output,
|
|
1607
1705
|
config,
|
|
1608
1706
|
file: {
|
|
@@ -1610,7 +1708,7 @@ const typeGenerator = defineGenerator({
|
|
|
1610
1708
|
baseName: meta.file.baseName
|
|
1611
1709
|
}
|
|
1612
1710
|
}),
|
|
1613
|
-
footer: resolver.
|
|
1711
|
+
footer: resolver.default.footer(ctx.meta, {
|
|
1614
1712
|
output,
|
|
1615
1713
|
config,
|
|
1616
1714
|
file: {
|
|
@@ -1619,10 +1717,10 @@ const typeGenerator = defineGenerator({
|
|
|
1619
1717
|
}
|
|
1620
1718
|
}),
|
|
1621
1719
|
children: [
|
|
1622
|
-
|
|
1720
|
+
paramGroupTypes,
|
|
1623
1721
|
responseTypes,
|
|
1624
1722
|
requestType,
|
|
1625
|
-
|
|
1723
|
+
optionsType,
|
|
1626
1724
|
responsesType,
|
|
1627
1725
|
responseType
|
|
1628
1726
|
]
|
|
@@ -1637,64 +1735,61 @@ const typeGenerator = defineGenerator({
|
|
|
1637
1735
|
* to reference the exact names `plugin-ts` produces without duplicating the
|
|
1638
1736
|
* casing/file-layout rules.
|
|
1639
1737
|
*
|
|
1640
|
-
* The `default`
|
|
1641
|
-
* type names and PascalCase file paths (dotted names
|
|
1738
|
+
* The `default` helpers are supplied by `createResolver`. This plugin overrides the top-level `name`
|
|
1739
|
+
* to use PascalCase for value and type names and `file` to write PascalCase file paths (dotted names
|
|
1740
|
+
* become `/`-joined), and groups the operation-specific naming under the `param`, `response`, and
|
|
1741
|
+
* `enum` namespaces.
|
|
1642
1742
|
*
|
|
1643
1743
|
* @example Resolve a type and file name
|
|
1644
1744
|
* ```ts
|
|
1645
1745
|
* import { resolverTs } from '@kubb/plugin-ts'
|
|
1646
1746
|
*
|
|
1647
|
-
* resolverTs.
|
|
1648
|
-
* resolverTs.
|
|
1649
|
-
* resolverTs.resolveResponseStatusName(node, 200) // 'ListPetsStatus200'
|
|
1747
|
+
* resolverTs.name('list pets') // 'ListPets'
|
|
1748
|
+
* resolverTs.response.status(node, 200) // 'ListPetsStatus200'
|
|
1650
1749
|
* ```
|
|
1651
1750
|
*/
|
|
1652
|
-
const resolverTs =
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
resolvePathName(name, type) {
|
|
1664
|
-
if (type === "file") return toFilePath(name, pascalCase);
|
|
1665
|
-
return ensureValidVarName(pascalCase(name));
|
|
1666
|
-
},
|
|
1667
|
-
resolveParamName(node, param) {
|
|
1668
|
-
return this.resolveTypeName(`${node.operationId} ${param.in} ${param.name}`);
|
|
1669
|
-
},
|
|
1670
|
-
resolveResponseStatusName(node, statusCode) {
|
|
1671
|
-
return this.resolveTypeName(`${node.operationId} Status ${statusCode}`);
|
|
1672
|
-
},
|
|
1673
|
-
resolveDataName(node) {
|
|
1674
|
-
return this.resolveTypeName(`${node.operationId} Data`);
|
|
1751
|
+
const resolverTs = createResolver({
|
|
1752
|
+
pluginName: "plugin-ts",
|
|
1753
|
+
name(name) {
|
|
1754
|
+
return ensureValidVarName(pascalCase(name));
|
|
1755
|
+
},
|
|
1756
|
+
file: { baseName({ name, extname }) {
|
|
1757
|
+
return `${toFilePath(name, pascalCase)}${extname}`;
|
|
1758
|
+
} },
|
|
1759
|
+
param: {
|
|
1760
|
+
name(node, param) {
|
|
1761
|
+
return this.name(`${node.operationId} ${param.in} ${param.name}`);
|
|
1675
1762
|
},
|
|
1676
|
-
|
|
1677
|
-
return this.
|
|
1763
|
+
path(node) {
|
|
1764
|
+
return this.name(`${node.operationId} Path`);
|
|
1678
1765
|
},
|
|
1679
|
-
|
|
1680
|
-
return this.
|
|
1766
|
+
query(node) {
|
|
1767
|
+
return this.name(`${node.operationId} Query`);
|
|
1681
1768
|
},
|
|
1682
|
-
|
|
1683
|
-
return this.
|
|
1769
|
+
headers(node) {
|
|
1770
|
+
return this.name(`${node.operationId} Headers`);
|
|
1771
|
+
}
|
|
1772
|
+
},
|
|
1773
|
+
response: {
|
|
1774
|
+
status(node, statusCode) {
|
|
1775
|
+
return this.name(`${node.operationId} Status ${statusCode}`);
|
|
1684
1776
|
},
|
|
1685
|
-
|
|
1686
|
-
return
|
|
1777
|
+
options(node) {
|
|
1778
|
+
return this.name(`${node.operationId} Options`);
|
|
1687
1779
|
},
|
|
1688
|
-
|
|
1689
|
-
return this.
|
|
1780
|
+
responses(node) {
|
|
1781
|
+
return this.name(`${node.operationId} Responses`);
|
|
1690
1782
|
},
|
|
1691
|
-
|
|
1692
|
-
return this.
|
|
1783
|
+
response(node) {
|
|
1784
|
+
return this.name(`${node.operationId} Response`);
|
|
1693
1785
|
},
|
|
1694
|
-
|
|
1695
|
-
return this.
|
|
1786
|
+
body(node) {
|
|
1787
|
+
return this.name(`${node.operationId} Body`);
|
|
1696
1788
|
}
|
|
1697
|
-
}
|
|
1789
|
+
},
|
|
1790
|
+
enum: { keyName(node, enumTypeSuffix = "key") {
|
|
1791
|
+
return `${this.name(node.name ?? "")}${enumTypeSuffix}`;
|
|
1792
|
+
} }
|
|
1698
1793
|
});
|
|
1699
1794
|
//#endregion
|
|
1700
1795
|
//#region src/plugin.ts
|
|
@@ -1755,10 +1850,7 @@ const pluginTs = definePlugin((options) => {
|
|
|
1755
1850
|
syntaxType,
|
|
1756
1851
|
printer
|
|
1757
1852
|
});
|
|
1758
|
-
ctx.setResolver(userResolver ?
|
|
1759
|
-
...resolverTs,
|
|
1760
|
-
...userResolver
|
|
1761
|
-
} : resolverTs);
|
|
1853
|
+
ctx.setResolver(userResolver ? Resolver.merge(resolverTs, userResolver) : resolverTs);
|
|
1762
1854
|
if (userMacros?.length) ctx.setMacros(userMacros);
|
|
1763
1855
|
ctx.addGenerator(typeGenerator);
|
|
1764
1856
|
} }
|
|
@@ -2019,12 +2111,12 @@ function functionPrinter(options) {
|
|
|
2019
2111
|
*/
|
|
2020
2112
|
function resolveParamType({ node, param, resolver }) {
|
|
2021
2113
|
if (!resolver) return param.schema.primitive ?? "unknown";
|
|
2022
|
-
const individualName = resolver.
|
|
2114
|
+
const individualName = resolver.param.name(node, param);
|
|
2023
2115
|
const groupLocation = param.in === "path" || param.in === "query" || param.in === "header" ? param.in : void 0;
|
|
2024
2116
|
const groupResolvers = {
|
|
2025
|
-
path: resolver.
|
|
2026
|
-
query: resolver.
|
|
2027
|
-
header: resolver.
|
|
2117
|
+
path: resolver.param.path,
|
|
2118
|
+
query: resolver.param.query,
|
|
2119
|
+
header: resolver.param.headers
|
|
2028
2120
|
};
|
|
2029
2121
|
const groupName = groupLocation ? groupResolvers[groupLocation].call(resolver, node, param) : void 0;
|
|
2030
2122
|
if (groupName && groupName !== individualName) return createIndexedAccessType({
|
|
@@ -2042,8 +2134,8 @@ function resolveParamType({ node, param, resolver }) {
|
|
|
2042
2134
|
function resolveGroupType({ node, params, group, resolver }) {
|
|
2043
2135
|
if (!resolver || !params.length) return null;
|
|
2044
2136
|
const firstParam = params[0];
|
|
2045
|
-
const groupName = (group === "query" ? resolver.
|
|
2046
|
-
if (groupName === resolver.
|
|
2137
|
+
const groupName = (group === "query" ? resolver.param.query : resolver.param.headers).call(resolver, node, firstParam);
|
|
2138
|
+
if (groupName === resolver.param.name(node, firstParam)) return null;
|
|
2047
2139
|
return {
|
|
2048
2140
|
type: groupName,
|
|
2049
2141
|
optional: params.every((p) => !p.required)
|
|
@@ -2079,7 +2171,7 @@ function createOperationParams(node, options) {
|
|
|
2079
2171
|
optional: !param.required
|
|
2080
2172
|
});
|
|
2081
2173
|
const emptyObjectDefault = (props) => props.every((p) => p.optional) ? "{}" : void 0;
|
|
2082
|
-
const bodyType = node.requestBody?.content?.[0]?.schema ? wrapType(resolver?.
|
|
2174
|
+
const bodyType = node.requestBody?.content?.[0]?.schema ? wrapType(resolver?.response.body(node) ?? "unknown") : void 0;
|
|
2083
2175
|
const bodyProperty = bodyType ? [{
|
|
2084
2176
|
name: dataName,
|
|
2085
2177
|
type: bodyType,
|
|
@@ -2123,7 +2215,7 @@ function createOperationParams(node, options) {
|
|
|
2123
2215
|
}));
|
|
2124
2216
|
} else {
|
|
2125
2217
|
if (pathParamsType === "inlineSpread" && pathParams.length) {
|
|
2126
|
-
const spreadType = resolver?.
|
|
2218
|
+
const spreadType = resolver?.param.path(node, pathParams[0]);
|
|
2127
2219
|
params.push(createFunctionParameter({
|
|
2128
2220
|
name: pathName,
|
|
2129
2221
|
type: spreadType ? wrapType(spreadType) : void 0,
|
|
@@ -2191,6 +2283,6 @@ function buildTypeLiteral({ node, params, resolver }) {
|
|
|
2191
2283
|
})) });
|
|
2192
2284
|
}
|
|
2193
2285
|
//#endregion
|
|
2194
|
-
export { Enum, Type, createFunctionParameter, createFunctionParameters, createIndexedAccessType, createObjectBindingPattern, createOperationParams, createTypeLiteral, pluginTs as default, pluginTs, functionPrinter, pluginTsName, printerTs, renderType, resolverTs, typeGenerator };
|
|
2286
|
+
export { Enum, Type, buildParams, createFunctionParameter, createFunctionParameters, createIndexedAccessType, createObjectBindingPattern, createOperationParams, createTypeLiteral, pluginTs as default, pluginTs, functionPrinter, pluginTsName, printerTs, renderType, resolverTs, typeGenerator };
|
|
2195
2287
|
|
|
2196
2288
|
//# sourceMappingURL=index.js.map
|