@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.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 /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
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.resolveTypeName(node.name);
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.resolveEnumKeyName(node, enumOptions.typeSuffix) : resolved
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
- ast.trimQuotes(v.name.toString()),
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) => [ast.trimQuotes(v.toString()), 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 ${ast.jsStringEscape(meta.description)}` : null,
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" ? ast.stringify(meta.default) : meta.default}` : null,
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
- function buildParams(node, { params, resolver }) {
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
- type: "ref",
1029
- name: resolver.resolveParamName(node, param),
1110
+ ...param.schema,
1030
1111
  optional: !param.required
1031
1112
  })
1032
1113
  }))
1033
1114
  });
1034
1115
  }
1035
- function buildData(node, { resolver }) {
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.resolveDataName(node)
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
- ...buildParams(node, {
1062
- params: pathParams,
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
- ...buildParams(node, {
1077
- params: queryParams,
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
- ...buildParams(node, {
1092
- params: headerParams,
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.resolveResponseStatusName(node, res.statusCode);
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.resolveResponseStatusName(node, res.statusCode)
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.resolveEnumKeyName({ name: refName }, this.options.enum.typeSuffix) : node.ref ? this.options.resolver.resolveTypeName(refName) : refName, void 0);
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.resolveEnumKeyName(node, this.options.enum.typeSuffix) : this.options.resolver.resolveTypeName(node.name), void 0);
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(schemaName),
1376
- path: resolver.resolveFile({
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.resolveEnumKeyName(node, enumOptions.typeSuffix) : resolver.resolveTypeName(node.name),
1389
- file: resolver.resolveFile({
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.resolveBanner(ctx.meta, {
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.resolveFooter(ctx.meta, {
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.resolveFile({
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(schemaName),
1471
- path: resolver.resolveFile({
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 paramTypes = params.map((param) => renderSchemaType({
1535
- schema: {
1536
- ...param.schema,
1537
- optional: !param.required
1538
- },
1539
- name: resolver.resolveParamName(node, param)
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.resolveDataName(node),
1645
+ name: resolver.response.body(node),
1553
1646
  keysToOmit: entry.keysToOmit
1554
1647
  });
1555
1648
  }
1556
- return buildContentTypeVariants(requestBodyContent, resolver.resolveDataName(node), (schema) => ({
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.resolveResponseStatusName(node, res.statusCode));
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.resolveResponseStatusName(node, res.statusCode),
1661
+ name: resolver.response.status(node, res.statusCode),
1569
1662
  keysToOmit: primary?.keysToOmit
1570
1663
  });
1571
1664
  });
1572
- const dataType = renderSchemaType({
1573
- schema: buildData({
1665
+ const optionsType = renderSchemaType({
1666
+ schema: buildOptions({
1574
1667
  ...node,
1575
1668
  parameters: params
1576
1669
  }, { resolver }),
1577
- name: resolver.resolveRequestConfigName(node)
1670
+ name: resolver.response.options(node)
1578
1671
  });
1579
1672
  const responsesType = renderSchemaType({
1580
1673
  schema: buildResponses(node, { resolver }),
1581
- name: resolver.resolveResponsesName(node)
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.resolveResponseName(node);
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(schemaName),
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.resolveBanner(ctx.meta, {
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.resolveFooter(ctx.meta, {
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
- paramTypes,
1720
+ paramGroupTypes,
1623
1721
  responseTypes,
1624
1722
  requestType,
1625
- dataType,
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` method is supplied by `defineResolver`. It uses PascalCase for
1641
- * type names and PascalCase file paths (dotted names become `/`-joined) for files.
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.default('list pets', 'type') // 'ListPets'
1648
- * resolverTs.resolvePathName('list pets', 'file') // 'ListPets'
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 = defineResolver(() => {
1653
- return {
1654
- name: "default",
1655
- pluginName: "plugin-ts",
1656
- default(name, type) {
1657
- if (type === "file") return toFilePath(name, pascalCase);
1658
- return ensureValidVarName(pascalCase(name));
1659
- },
1660
- resolveTypeName(name) {
1661
- return ensureValidVarName(pascalCase(name));
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
- resolveRequestConfigName(node) {
1677
- return this.resolveTypeName(`${node.operationId} RequestConfig`);
1763
+ path(node) {
1764
+ return this.name(`${node.operationId} Path`);
1678
1765
  },
1679
- resolveResponsesName(node) {
1680
- return this.resolveTypeName(`${node.operationId} Responses`);
1766
+ query(node) {
1767
+ return this.name(`${node.operationId} Query`);
1681
1768
  },
1682
- resolveResponseName(node) {
1683
- return this.resolveTypeName(`${node.operationId} Response`);
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
- resolveEnumKeyName(node, enumTypeSuffix = "key") {
1686
- return `${this.resolveTypeName(node.name ?? "")}${enumTypeSuffix}`;
1777
+ options(node) {
1778
+ return this.name(`${node.operationId} Options`);
1687
1779
  },
1688
- resolvePathParamsName(node, param) {
1689
- return this.resolveParamName(node, param);
1780
+ responses(node) {
1781
+ return this.name(`${node.operationId} Responses`);
1690
1782
  },
1691
- resolveQueryParamsName(node, param) {
1692
- return this.resolveParamName(node, param);
1783
+ response(node) {
1784
+ return this.name(`${node.operationId} Response`);
1693
1785
  },
1694
- resolveHeaderParamsName(node, param) {
1695
- return this.resolveParamName(node, param);
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.resolveParamName(node, param);
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.resolvePathParamsName,
2026
- query: resolver.resolveQueryParamsName,
2027
- header: resolver.resolveHeaderParamsName
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.resolveQueryParamsName : resolver.resolveHeaderParamsName).call(resolver, node, firstParam);
2046
- if (groupName === resolver.resolveParamName(node, firstParam)) return null;
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?.resolveDataName(node) ?? "unknown") : void 0;
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?.resolvePathParamsName(node, pathParams[0]);
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