@kubb/plugin-ts 5.0.0-beta.77 → 5.0.0-beta.79
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 +73 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +73 -21
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.d.ts
CHANGED
|
@@ -126,6 +126,11 @@ type PrinterTsOptions = {
|
|
|
126
126
|
* Schema names that represent enums for suffixed key references.
|
|
127
127
|
*/
|
|
128
128
|
enumSchemaNames?: Set<string>;
|
|
129
|
+
/**
|
|
130
|
+
* Maps a component `$ref` path to its collision-resolved name, so a reference to a renamed
|
|
131
|
+
* component (e.g. `#/components/schemas/Order` → `OrderSchema`) emits the renamed name.
|
|
132
|
+
*/
|
|
133
|
+
nameMapping?: ReadonlyMap<string, string>;
|
|
129
134
|
/**
|
|
130
135
|
* Custom handler map for node type overrides.
|
|
131
136
|
*/
|
package/dist/index.js
CHANGED
|
@@ -98,7 +98,7 @@ function toFilePath(name, caseLast = camelCase) {
|
|
|
98
98
|
* JavaScript and Java reserved words.
|
|
99
99
|
* @link https://github.com/jonschlinkert/reserved/blob/master/index.js
|
|
100
100
|
*/
|
|
101
|
-
const reservedWords = new Set([
|
|
101
|
+
const reservedWords = /* @__PURE__ */ new Set([
|
|
102
102
|
"abstract",
|
|
103
103
|
"arguments",
|
|
104
104
|
"boolean",
|
|
@@ -220,19 +220,19 @@ function ensureValidVarName(name) {
|
|
|
220
220
|
/**
|
|
221
221
|
* `optionalType` values that cause a property's type to include `| undefined`.
|
|
222
222
|
*/
|
|
223
|
-
const OPTIONAL_ADDS_UNDEFINED = new Set(["undefined", "questionTokenAndUndefined"]);
|
|
223
|
+
const OPTIONAL_ADDS_UNDEFINED = /* @__PURE__ */ new Set(["undefined", "questionTokenAndUndefined"]);
|
|
224
224
|
/**
|
|
225
225
|
* `optionalType` values that render the property key with a `?` token.
|
|
226
226
|
*/
|
|
227
|
-
const OPTIONAL_ADDS_QUESTION_TOKEN = new Set(["questionToken", "questionTokenAndUndefined"]);
|
|
227
|
+
const OPTIONAL_ADDS_QUESTION_TOKEN = /* @__PURE__ */ new Set(["questionToken", "questionTokenAndUndefined"]);
|
|
228
228
|
/**
|
|
229
229
|
* `enum.type` values that append a `typeSuffix` to the generated enum type alias.
|
|
230
230
|
*/
|
|
231
|
-
const ENUM_TYPES_WITH_KEY_SUFFIX = new Set(["asConst"]);
|
|
231
|
+
const ENUM_TYPES_WITH_KEY_SUFFIX = /* @__PURE__ */ new Set(["asConst"]);
|
|
232
232
|
/**
|
|
233
233
|
* `enum.type` values that require a runtime value declaration (object, enum, or literal).
|
|
234
234
|
*/
|
|
235
|
-
const ENUM_TYPES_WITH_RUNTIME_VALUE = new Set([
|
|
235
|
+
const ENUM_TYPES_WITH_RUNTIME_VALUE = /* @__PURE__ */ new Set([
|
|
236
236
|
"enum",
|
|
237
237
|
"asConst",
|
|
238
238
|
"constEnum",
|
|
@@ -242,7 +242,7 @@ const ENUM_TYPES_WITH_RUNTIME_VALUE = new Set([
|
|
|
242
242
|
/**
|
|
243
243
|
* `enum.type` values whose type declaration is type-only (no runtime value emitted for the type alias).
|
|
244
244
|
*/
|
|
245
|
-
const ENUM_TYPES_WITH_TYPE_ONLY = new Set([
|
|
245
|
+
const ENUM_TYPES_WITH_TYPE_ONLY = /* @__PURE__ */ new Set([
|
|
246
246
|
"asConst",
|
|
247
247
|
"literal",
|
|
248
248
|
void 0
|
|
@@ -800,7 +800,7 @@ function buildIndexSignatures(node, propertyCount, print) {
|
|
|
800
800
|
* resolve to the same name, which TypeScript merges into a single value+type declaration.
|
|
801
801
|
*/
|
|
802
802
|
function getEnumNames({ node, enum: enumOptions, resolver }) {
|
|
803
|
-
const resolved = resolver.
|
|
803
|
+
const resolved = resolver.resolveTypeName(node.name);
|
|
804
804
|
return {
|
|
805
805
|
enumName: enumOptions.constCasing === "pascalCase" ? resolved : camelCase(node.name),
|
|
806
806
|
typeName: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumOptions.type) ? resolver.resolveEnumKeyName(node, enumOptions.typeSuffix) : resolved
|
|
@@ -870,6 +870,23 @@ function caseParams(params, casing) {
|
|
|
870
870
|
caseParamsCache.set(params, result);
|
|
871
871
|
return result;
|
|
872
872
|
}
|
|
873
|
+
/**
|
|
874
|
+
* Drops parameters that collapse to the same property identity once camelCased, keeping the first.
|
|
875
|
+
*
|
|
876
|
+
* Some specs declare the same parameter twice under different casings (for example AWS S3 lists both
|
|
877
|
+
* `max-uploads` and `MaxUploads`). Both resolve to one output property, so emitting both would yield
|
|
878
|
+
* an object type with a duplicate member, which TypeScript rejects. De-duplicate by the camelCased
|
|
879
|
+
* identity so the resulting group is collision-free regardless of the names each caller carries.
|
|
880
|
+
*/
|
|
881
|
+
function dedupeByCasedName(params) {
|
|
882
|
+
const seen = /* @__PURE__ */ new Set();
|
|
883
|
+
return params.filter((param) => {
|
|
884
|
+
const key = camelCase(param.name);
|
|
885
|
+
if (seen.has(key)) return false;
|
|
886
|
+
seen.add(key);
|
|
887
|
+
return true;
|
|
888
|
+
});
|
|
889
|
+
}
|
|
873
890
|
//#endregion
|
|
874
891
|
//#region ../../internals/shared/src/operation.ts
|
|
875
892
|
/**
|
|
@@ -923,10 +940,10 @@ function resolveContentTypeVariants(entries, baseName) {
|
|
|
923
940
|
function getOperationParameters(node, options = {}) {
|
|
924
941
|
const params = caseParams(node.parameters, options.paramsCasing === "original" ? void 0 : "camelcase");
|
|
925
942
|
return {
|
|
926
|
-
path: params.filter((param) => param.in === "path"),
|
|
927
|
-
query: params.filter((param) => param.in === "query"),
|
|
928
|
-
header: params.filter((param) => param.in === "header"),
|
|
929
|
-
cookie: params.filter((param) => param.in === "cookie")
|
|
943
|
+
path: dedupeByCasedName(params.filter((param) => param.in === "path")),
|
|
944
|
+
query: dedupeByCasedName(params.filter((param) => param.in === "query")),
|
|
945
|
+
header: dedupeByCasedName(params.filter((param) => param.in === "header")),
|
|
946
|
+
cookie: dedupeByCasedName(params.filter((param) => param.in === "cookie"))
|
|
930
947
|
};
|
|
931
948
|
}
|
|
932
949
|
//#endregion
|
|
@@ -1086,17 +1103,48 @@ function buildData(node, { resolver }) {
|
|
|
1086
1103
|
]
|
|
1087
1104
|
});
|
|
1088
1105
|
}
|
|
1106
|
+
/**
|
|
1107
|
+
* The schema a status occupies in the `<Name>Responses` record. A status that documents several
|
|
1108
|
+
* content types becomes a `{ contentType; data }` union so the runtime can surface the negotiated type
|
|
1109
|
+
* on `result.parsed`, while the standalone `<Name>StatusNNN` alias stays the plain body union that the
|
|
1110
|
+
* query hooks and `result.data` use.
|
|
1111
|
+
*/
|
|
1112
|
+
function buildResponseRecordEntry(node, res, resolver) {
|
|
1113
|
+
const statusName = resolver.resolveResponseStatusName(node, res.statusCode);
|
|
1114
|
+
const variants = (res.content ?? []).filter((entry) => entry.schema);
|
|
1115
|
+
if (variants.length <= 1) return ast.factory.createSchema({
|
|
1116
|
+
type: "ref",
|
|
1117
|
+
name: statusName
|
|
1118
|
+
});
|
|
1119
|
+
return ast.factory.createSchema({
|
|
1120
|
+
type: "union",
|
|
1121
|
+
members: resolveContentTypeVariants(variants, statusName).map((variant) => ast.factory.createSchema({
|
|
1122
|
+
type: "object",
|
|
1123
|
+
properties: [ast.factory.createProperty({
|
|
1124
|
+
name: "contentType",
|
|
1125
|
+
required: true,
|
|
1126
|
+
schema: ast.factory.createSchema({
|
|
1127
|
+
type: "enum",
|
|
1128
|
+
enumValues: [variant.contentType]
|
|
1129
|
+
})
|
|
1130
|
+
}), ast.factory.createProperty({
|
|
1131
|
+
name: "data",
|
|
1132
|
+
required: true,
|
|
1133
|
+
schema: ast.factory.createSchema({
|
|
1134
|
+
type: "ref",
|
|
1135
|
+
name: variant.name
|
|
1136
|
+
})
|
|
1137
|
+
})]
|
|
1138
|
+
}))
|
|
1139
|
+
});
|
|
1140
|
+
}
|
|
1089
1141
|
function buildResponses(node, { resolver }) {
|
|
1090
|
-
if (node.responses.length === 0) return null;
|
|
1091
1142
|
return ast.factory.createSchema({
|
|
1092
1143
|
type: "object",
|
|
1093
1144
|
properties: node.responses.map((res) => ast.factory.createProperty({
|
|
1094
1145
|
name: String(res.statusCode),
|
|
1095
1146
|
required: true,
|
|
1096
|
-
schema:
|
|
1097
|
-
type: "ref",
|
|
1098
|
-
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
1099
|
-
})
|
|
1147
|
+
schema: buildResponseRecordEntry(node, res, resolver)
|
|
1100
1148
|
}))
|
|
1101
1149
|
});
|
|
1102
1150
|
}
|
|
@@ -1200,8 +1248,8 @@ const printerTs = ast.createPrinter((options) => {
|
|
|
1200
1248
|
time: dateOrStringNode,
|
|
1201
1249
|
ref(node) {
|
|
1202
1250
|
if (!node.name) return null;
|
|
1203
|
-
const refName = node.ref ? extractRefName(node.ref) ?? node.name : node.name;
|
|
1204
|
-
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.resolveEnumKeyName({ name: refName }, this.options.enum.typeSuffix) : node.ref ? this.options.resolver.
|
|
1251
|
+
const refName = node.ref ? this.options.nameMapping?.get(node.ref) ?? extractRefName(node.ref) ?? node.name : node.name;
|
|
1252
|
+
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.resolveEnumKeyName({ name: refName }, this.options.enum.typeSuffix) : node.ref ? this.options.resolver.resolveTypeName(refName) : refName, void 0);
|
|
1205
1253
|
},
|
|
1206
1254
|
enum(node) {
|
|
1207
1255
|
const values = node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? [];
|
|
@@ -1209,7 +1257,7 @@ const printerTs = ast.createPrinter((options) => {
|
|
|
1209
1257
|
withParentheses: true,
|
|
1210
1258
|
nodes: values.filter((v) => v !== null && v !== void 0).map((value) => constToTypeNode(value, typeof value)).filter(isNonNullable)
|
|
1211
1259
|
}) ?? void 0;
|
|
1212
|
-
return createTypeReferenceNode(ENUM_TYPES_WITH_KEY_SUFFIX.has(this.options.enum.type) && this.options.enum.typeSuffix ? this.options.resolver.resolveEnumKeyName(node, this.options.enum.typeSuffix) : this.options.resolver.
|
|
1260
|
+
return createTypeReferenceNode(ENUM_TYPES_WITH_KEY_SUFFIX.has(this.options.enum.type) && this.options.enum.typeSuffix ? this.options.resolver.resolveEnumKeyName(node, this.options.enum.typeSuffix) : this.options.resolver.resolveTypeName(node.name), void 0);
|
|
1213
1261
|
},
|
|
1214
1262
|
union(node) {
|
|
1215
1263
|
const members = node.members ?? [];
|
|
@@ -1357,6 +1405,7 @@ const typeGenerator = defineGenerator({
|
|
|
1357
1405
|
description: node.description,
|
|
1358
1406
|
resolver,
|
|
1359
1407
|
enumSchemaNames,
|
|
1408
|
+
nameMapping: adapter.options.nameMapping,
|
|
1360
1409
|
nodes: printer?.nodes
|
|
1361
1410
|
});
|
|
1362
1411
|
return /* @__PURE__ */ jsxs(File, {
|
|
@@ -1439,6 +1488,7 @@ const typeGenerator = defineGenerator({
|
|
|
1439
1488
|
keysToOmit,
|
|
1440
1489
|
resolver,
|
|
1441
1490
|
enumSchemaNames,
|
|
1491
|
+
nameMapping: adapter.options.nameMapping,
|
|
1442
1492
|
nodes: printer?.nodes
|
|
1443
1493
|
});
|
|
1444
1494
|
return /* @__PURE__ */ jsxs(Fragment, { children: [imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
|
|
@@ -1459,8 +1509,10 @@ const typeGenerator = defineGenerator({
|
|
|
1459
1509
|
})] });
|
|
1460
1510
|
}
|
|
1461
1511
|
/**
|
|
1462
|
-
* Emits an individual type per content type plus a union alias under `baseName`.
|
|
1463
|
-
*
|
|
1512
|
+
* Emits an individual type per content type plus a plain union alias under `baseName`. Shared by
|
|
1513
|
+
* the request body and multi-content-type responses. The response record discriminates these
|
|
1514
|
+
* variants by content type in {@link buildResponses}; the standalone alias stays a plain union so
|
|
1515
|
+
* query hooks and `result.data` keep the bare body.
|
|
1464
1516
|
*/
|
|
1465
1517
|
function buildContentTypeVariants(entries, baseName, decorate) {
|
|
1466
1518
|
const variants = resolveContentTypeVariants(entries, baseName);
|