@kubb/plugin-fetch 5.0.0-beta.85 → 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 CHANGED
@@ -71,31 +71,6 @@ function pascalCase(text, { prefix = "", suffix = "" } = {}) {
71
71
  return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
72
72
  }
73
73
  //#endregion
74
- //#region ../../internals/utils/src/fs.ts
75
- /**
76
- * Builds a nested file path from a dotted name. Splits on dots that precede a letter
77
- * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases
78
- * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.
79
- *
80
- * Empty segments are dropped before joining. They arise when the name starts with a dot
81
- * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to
82
- * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an
83
- * absolute path, letting generated files escape the configured output directory.
84
- *
85
- * @example Nested path from a dotted name
86
- * `toFilePath('pet.petId') // 'pet/petId'`
87
- *
88
- * @example PascalCase the final segment
89
- * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`
90
- *
91
- * @example Suffix applied to the final segment only
92
- * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`
93
- */
94
- function toFilePath(name, caseLast = camelCase) {
95
- const parts = name.split(/\.(?=[a-zA-Z])/);
96
- return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
97
- }
98
- //#endregion
99
74
  //#region ../../internals/utils/src/reserved.ts
100
75
  /**
101
76
  * JavaScript and Java reserved words.
@@ -219,6 +194,23 @@ function ensureValidVarName(name) {
219
194
  return `_${name}`;
220
195
  }
221
196
  //#endregion
197
+ //#region ../../internals/utils/src/codegen.ts
198
+ /**
199
+ * Builds a JSDoc comment block from an array of lines. Returns `fallback` when there are no
200
+ * comments.
201
+ *
202
+ * @example
203
+ * ```ts
204
+ * buildJSDoc(['@type string', '@example hello'])
205
+ * // '/**\n * @type string\n * @example hello\n *\/\n '
206
+ * ```
207
+ */
208
+ function buildJSDoc(comments, options = {}) {
209
+ const { indent = " * ", suffix = "\n ", fallback = " " } = options;
210
+ if (comments.length === 0) return fallback;
211
+ return `/**\n${comments.map((c) => `${indent}${c}`).join("\n")}\n */${suffix}`;
212
+ }
213
+ //#endregion
222
214
  //#region ../../internals/utils/src/url.ts
223
215
  function transformParam(raw, casing) {
224
216
  const param = isValidVarName(raw) ? raw : camelCase(raw);
@@ -399,13 +391,13 @@ function buildParamsRemapExpression({ source, mapping }) {
399
391
  //#region ../../internals/shared/src/operation.ts
400
392
  /**
401
393
  * Builds the `ResolverFileParams` every operation generator passes to
402
- * `resolver.resolveFile`: a file named `name`, tagged by the operation's first
394
+ * `resolver.file`: a file named `name`, tagged by the operation's first
403
395
  * tag (or `'default'`), at the operation's path. Centralizes the entry object
404
396
  * that was repeated at dozens of call sites across the client and query plugins.
405
397
  *
406
398
  * @example
407
399
  * ```ts
408
- * resolver.resolveFile(operationFileEntry(node, node.operationId), { root, output, group })
400
+ * resolver.file(operationFileEntry(node, node.operationId), { root, output, group })
409
401
  * ```
410
402
  */
411
403
  function operationFileEntry(node, name, extname = ".ts") {
@@ -628,7 +620,7 @@ function resolveResponseValidator(validator) {
628
620
  * `<operation>ResponseSchema` is used; error bodies are never zod-parsed.
629
621
  */
630
622
  function buildZodResponseParse(node, zodResolver) {
631
- const name = zodResolver.resolveResponseName?.(node);
623
+ const name = zodResolver.response.response(node);
632
624
  return name ? {
633
625
  expression: name,
634
626
  importNames: [name]
@@ -641,7 +633,7 @@ function buildZodResponseParse(node, zodResolver) {
641
633
  */
642
634
  function buildZodErrorParse(node, zodResolver) {
643
635
  if (!node.responses.some((res) => !isSuccessStatusCode(res.statusCode) && res.content?.some((entry) => entry.schema))) return null;
644
- const name = zodResolver.resolveErrorName?.(node);
636
+ const name = zodResolver.response.error?.(node);
645
637
  return name ? {
646
638
  expression: name,
647
639
  importNames: [name]
@@ -758,7 +750,7 @@ function buildParamsRemap({ node }) {
758
750
  * `buildRequestResultGenerics({ node, tsResolver }) // 'AddPetResponses, ThrowOnError'`
759
751
  */
760
752
  function buildRequestResultGenerics({ node, tsResolver }) {
761
- return `${tsResolver.resolveResponsesName(node)}, ThrowOnError`;
753
+ return `${tsResolver.response.responses(node)}, ThrowOnError`;
762
754
  }
763
755
  //#endregion
764
756
  //#region ../../internals/client/src/builders/returnStatement.ts
@@ -781,30 +773,30 @@ function buildReturnStatement({ node, tsResolver, callConfig }) {
781
773
  const declarationPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
782
774
  /**
783
775
  * Builds the grouped-options signature for one operation: a single `options` object whose `TData`
784
- * is the plugin-ts `<Name>RequestConfig` (carrying a literal `url`), and a `RequestResult` return type
776
+ * is the plugin-ts `<Name>Options` (carrying a literal `url`), and a `RequestResult` return type
785
777
  * keyed to the plugin-ts per-status responses record. There are no positional arguments.
786
778
  *
787
- * The generated file imports `<Name>RequestConfig` and `<Name>Responses` and uses them directly, so no
779
+ * The generated file imports `<Name>Options` and `<Name>Responses` and uses them directly, so no
788
780
  * per-operation input type has to be emitted.
789
781
  */
790
782
  function buildGroupedOptionsSignature({ node, tsResolver }) {
791
- const requestConfigName = tsResolver.resolveRequestConfigName(node);
792
- const responsesName = tsResolver.resolveResponsesName(node);
783
+ const optionsName = tsResolver.response.options(node);
784
+ const responsesName = tsResolver.response.responses(node);
793
785
  const resultGenerics = buildRequestResultGenerics({
794
786
  node,
795
787
  tsResolver
796
788
  });
797
789
  const { isOptional } = getRequestGroupOptionality(node);
798
790
  return {
799
- dataTypeName: requestConfigName,
791
+ dataTypeName: optionsName,
800
792
  paramsSignature: declarationPrinter.print((0, _kubb_plugin_ts.createFunctionParameters)({ params: [(0, _kubb_plugin_ts.createFunctionParameter)({
801
793
  name: "options",
802
- type: `Options<${requestConfigName}, ThrowOnError>`,
794
+ type: `Options<${optionsName}, ThrowOnError>`,
803
795
  ...isOptional ? { default: "{}" } : {}
804
796
  })] })) ?? "",
805
797
  returnType: `Promise<RequestResult<${resultGenerics}>>`,
806
798
  generics: ["ThrowOnError extends boolean = true"],
807
- importedTypeNames: [requestConfigName, responsesName]
799
+ importedTypeNames: [optionsName, responsesName]
808
800
  };
809
801
  }
810
802
  //#endregion
@@ -870,7 +862,7 @@ function buildStyles({ node }) {
870
862
  function buildValidatorHooks({ node, validator, zodResolver }) {
871
863
  const importedZodNames = [];
872
864
  const hasRequestBody = Boolean(node.requestBody?.content?.[0]?.schema);
873
- const zodRequestName = zodResolver && resolveRequestValidator(validator) === "zod" && hasRequestBody ? zodResolver.resolveDataName?.(node) : null;
865
+ const zodRequestName = zodResolver && resolveRequestValidator(validator) === "zod" && hasRequestBody ? zodResolver.response.body(node) : null;
874
866
  const request = zodRequestName ?? null;
875
867
  if (zodRequestName) importedZodNames.push(zodRequestName);
876
868
  const responseParse = zodResolver && resolveResponseValidator(validator) === "zod" ? buildZodResponseParse(node, zodResolver) : null;
@@ -930,7 +922,7 @@ function Operation({ name, node, tsResolver, zodResolver, validator, security, i
930
922
  "...config",
931
923
  ...buildParamsRemap({ node })
932
924
  ].filter(Boolean).join(", ")} }`;
933
- const eventType = `SuccessOf<${tsResolver.resolveResponsesName(node)}>`;
925
+ const eventType = `SuccessOf<${tsResolver.response.responses(node)}>`;
934
926
  const returnType = eventStream ? `Promise<EventStreamResult<${eventType}>>` : signature.returnType;
935
927
  const returnStatement = eventStream ? `return toEventStream<${eventType}>(request(${callConfig}))` : buildReturnStatement({
936
928
  node,
@@ -1008,7 +1000,7 @@ function buildSdkMethod({ node, name, tsResolver, zodResolver, validator, securi
1008
1000
  })
1009
1001
  });
1010
1002
  const generics = signature.generics.length ? `<${signature.generics.join(", ")}>` : "";
1011
- const jsdoc = kubb_kit.ast.buildJSDoc(buildOperationComments(node, {
1003
+ const jsdoc = buildJSDoc(buildOperationComments(node, {
1012
1004
  link: "urlPath",
1013
1005
  linkPosition: "beforeDeprecated",
1014
1006
  splitLines: true
@@ -1078,15 +1070,15 @@ function SdkFacade({ name, isExportable = true, isIndexable = true, members, chi
1078
1070
  //#endregion
1079
1071
  //#region ../../internals/client/src/generators/sdkGenerator.tsx
1080
1072
  function resolveTypeImportNames(node, tsResolver) {
1081
- return [tsResolver.resolveRequestConfigName(node), tsResolver.resolveResponsesName(node)];
1073
+ return [tsResolver.response.options(node), tsResolver.response.responses(node)];
1082
1074
  }
1083
1075
  function resolveZodImportNames(node, zodResolver, validator) {
1084
1076
  const { query: queryParams } = getOperationParameters(node, { paramsCasing: "original" });
1085
1077
  return [
1086
- resolveResponseValidator(validator) === "zod" ? zodResolver.resolveResponseName?.(node) : null,
1078
+ resolveResponseValidator(validator) === "zod" ? zodResolver.response.response(node) : null,
1087
1079
  resolveResponseValidator(validator) === "zod" ? buildZodErrorParse(node, zodResolver)?.expression ?? null : null,
1088
- resolveRequestValidator(validator) === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null,
1089
- resolveQueryParamsValidator(validator) === "zod" && queryParams.length > 0 ? zodResolver.resolveQueryParamsName?.(node, queryParams[0]) : null
1080
+ resolveRequestValidator(validator) === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.response.body(node) : null,
1081
+ resolveQueryParamsValidator(validator) === "zod" && queryParams.length > 0 ? zodResolver.param.query(node, queryParams[0]) : null
1090
1082
  ].filter((n) => Boolean(n));
1091
1083
  }
1092
1084
  /**
@@ -1103,12 +1095,14 @@ function buildControllers(nodes, ctx) {
1103
1095
  const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : null;
1104
1096
  const document = ctx.adapter.document;
1105
1097
  function buildOperationData(node) {
1106
- const typeFile = tsResolver.resolveFile(operationFileEntry(node, node.operationId), {
1098
+ const typeFile = tsResolver.file({
1099
+ ...operationFileEntry(node, node.operationId),
1107
1100
  root,
1108
1101
  output: tsPluginOptions?.output ?? output,
1109
1102
  group: tsPluginOptions?.group
1110
1103
  });
1111
- const zodFile = zodResolver && pluginZod?.options ? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
1104
+ const zodFile = zodResolver && pluginZod?.options ? zodResolver.file({
1105
+ ...operationFileEntry(node, node.operationId),
1112
1106
  root,
1113
1107
  output: pluginZod.options?.output ?? output,
1114
1108
  group: pluginZod.options?.group ?? void 0
@@ -1120,7 +1114,7 @@ function buildControllers(nodes, ctx) {
1120
1114
  }) : void 0;
1121
1115
  return {
1122
1116
  node,
1123
- name: resolver.resolveName(node.operationId),
1117
+ name: resolver.name(node.operationId),
1124
1118
  tsResolver,
1125
1119
  zodResolver,
1126
1120
  typeFile,
@@ -1131,12 +1125,11 @@ function buildControllers(nodes, ctx) {
1131
1125
  return nodes.reduce((acc, operationNode) => {
1132
1126
  if (!kubb_kit.ast.isHttpOperationNode(operationNode)) return acc;
1133
1127
  const tag = operationNode.tags[0];
1134
- const name = tag ? group?.name?.({ group: camelCase(tag) }) ?? resolver.resolveGroupName(tag) : resolver.resolveClassName("ApiClient");
1135
- const file = resolver.resolveFile({
1128
+ const name = tag ? group?.name?.({ group: camelCase(tag) }) ?? resolver.groupName(tag) : resolver.className("ApiClient");
1129
+ const file = resolver.file({
1136
1130
  name,
1137
1131
  extname: ".ts",
1138
- tag
1139
- }, {
1132
+ tag,
1140
1133
  root,
1141
1134
  output,
1142
1135
  group: group ?? void 0
@@ -1190,7 +1183,7 @@ function createSdkGenerator() {
1190
1183
  if (!ctx.driver.getPlugin(_kubb_plugin_ts.pluginTsName) || !sdk) return null;
1191
1184
  const controllers = buildControllers(nodes, ctx);
1192
1185
  const clientPath = node_path.default.resolve(root, ".kubb/client.ts");
1193
- const banner = (file) => resolver.resolveBanner(ctx.meta, {
1186
+ const banner = (file) => resolver.default.banner(ctx.meta, {
1194
1187
  output,
1195
1188
  config,
1196
1189
  file: {
@@ -1198,7 +1191,7 @@ function createSdkGenerator() {
1198
1191
  baseName: file.baseName
1199
1192
  }
1200
1193
  });
1201
- const footer = (file) => resolver.resolveFooter(ctx.meta, {
1194
+ const footer = (file) => resolver.default.footer(ctx.meta, {
1202
1195
  output,
1203
1196
  config,
1204
1197
  file: {
@@ -1265,28 +1258,26 @@ function createSdkGenerator() {
1265
1258
  ]
1266
1259
  }, file.path);
1267
1260
  };
1268
- if (sdk.mode === "flat") return renderClassFile(resolver.resolveClassName(sdk.name ?? "sdk"), resolver.resolveFile({
1261
+ if (sdk.mode === "flat") return renderClassFile(resolver.className(sdk.name ?? "sdk"), resolver.file({
1269
1262
  name: sdk.name ?? "sdk",
1270
- extname: ".ts"
1271
- }, {
1263
+ extname: ".ts",
1272
1264
  root,
1273
1265
  output,
1274
1266
  group: group ?? void 0
1275
1267
  }), controllers.flatMap((controller) => controller.operations));
1276
1268
  const classFiles = controllers.map(({ name, file, operations: ops }) => renderClassFile(name, file, ops));
1277
1269
  if (!sdk.name) return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx_jsx_runtime.Fragment, { children: classFiles });
1278
- const sdkFile = resolver.resolveFile({
1270
+ const sdkFile = resolver.file({
1279
1271
  name: sdk.name,
1280
- extname: ".ts"
1281
- }, {
1272
+ extname: ".ts",
1282
1273
  root,
1283
1274
  output,
1284
1275
  group: group ?? void 0
1285
1276
  });
1286
- const facadeName = resolver.resolveClassName(sdk.name);
1277
+ const facadeName = resolver.className(sdk.name);
1287
1278
  const members = controllers.map(({ name, tag }) => ({
1288
1279
  className: name,
1289
- propName: resolver.resolveClientPropertyName(tag ?? name)
1280
+ propName: resolver.propertyName(tag ?? name)
1290
1281
  }));
1291
1282
  return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx_jsx_runtime.Fragment, { children: [classFiles, /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx.File, {
1292
1283
  baseName: sdkFile.baseName,
@@ -1326,38 +1317,27 @@ const defaultMacros = [kubb_kit.ast.macroSimplifyUnion];
1326
1317
  //#endregion
1327
1318
  //#region ../../internals/client/src/resolver.ts
1328
1319
  /**
1329
- * Default resolver shared by the client plugins. Functions and files use camelCase; classes and
1330
- * tag groups use PascalCase.
1320
+ * Default resolver shared by the client plugins. Functions and files inherit the built-in camelCase
1321
+ * `name` and `file`; classes and tag groups use PascalCase.
1331
1322
  *
1332
1323
  * @example
1333
1324
  * ```ts
1334
- * resolverClient.resolveName('show pet by id') // 'showPetById'
1335
- * resolverClient.resolveGroupName('pet') // 'PetClient'
1325
+ * resolverClient.name('show pet by id') // 'showPetById'
1326
+ * resolverClient.groupName('pet') // 'PetClient'
1336
1327
  * ```
1337
1328
  */
1338
- const resolverClient = (0, kubb_kit.defineResolver)(() => ({
1339
- name: "default",
1329
+ const resolverClient = (0, kubb_kit.createResolver)({
1340
1330
  pluginName: "plugin-contract-client",
1341
- default(name, type) {
1342
- if (type === "file") return toFilePath(name);
1343
- return ensureValidVarName(camelCase(name));
1344
- },
1345
- resolveName(name) {
1346
- return this.default(name, "function");
1347
- },
1348
- resolvePathName(name, type) {
1349
- return this.default(name, type);
1350
- },
1351
- resolveClassName(name) {
1331
+ className(name) {
1352
1332
  return ensureValidVarName(pascalCase(name));
1353
1333
  },
1354
- resolveGroupName(name) {
1334
+ groupName(name) {
1355
1335
  return ensureValidVarName(pascalCase(`${name} Client`));
1356
1336
  },
1357
- resolveClientPropertyName(name) {
1337
+ propertyName(name) {
1358
1338
  return ensureValidVarName(camelCase(name));
1359
1339
  }
1360
- }));
1340
+ });
1361
1341
  //#endregion
1362
1342
  //#region src/generators/clientGenerator.tsx
1363
1343
  /**
@@ -1378,25 +1358,28 @@ const clientGenerator = (0, kubb_kit.defineGenerator)({
1378
1358
  const pluginZod = resolveResponseValidator(validator) === "zod" || resolveRequestValidator(validator) === "zod" ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : null;
1379
1359
  const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : null;
1380
1360
  const hasRequestBody = Boolean(node.requestBody?.content?.[0]?.schema);
1381
- const importedTypeNames = [tsResolver.resolveRequestConfigName(node), tsResolver.resolveResponsesName(node)];
1361
+ const importedTypeNames = [tsResolver.response.options(node), tsResolver.response.responses(node)];
1382
1362
  const importedZodNames = zodResolver ? [
1383
- resolveResponseValidator(validator) === "zod" ? zodResolver.resolveResponseName?.(node) : null,
1363
+ resolveResponseValidator(validator) === "zod" ? zodResolver.response.response?.(node) : null,
1384
1364
  resolveResponseValidator(validator) === "zod" ? buildZodErrorParse(node, zodResolver)?.expression ?? null : null,
1385
- resolveRequestValidator(validator) === "zod" && hasRequestBody ? zodResolver.resolveDataName?.(node) : null
1365
+ resolveRequestValidator(validator) === "zod" && hasRequestBody ? zodResolver.response.body?.(node) : null
1386
1366
  ].filter((name) => Boolean(name)) : [];
1387
1367
  const meta = {
1388
- name: resolver.resolveName(node.operationId),
1389
- file: resolver.resolveFile(operationFileEntry(node, node.operationId), {
1368
+ name: resolver.name(node.operationId),
1369
+ file: resolver.file({
1370
+ ...operationFileEntry(node, node.operationId),
1390
1371
  root,
1391
1372
  output,
1392
1373
  group: group ?? void 0
1393
1374
  }),
1394
- fileTs: tsResolver.resolveFile(operationFileEntry(node, node.operationId), {
1375
+ fileTs: tsResolver.file({
1376
+ ...operationFileEntry(node, node.operationId),
1395
1377
  root,
1396
1378
  output: pluginTs.options?.output ?? output,
1397
1379
  group: pluginTs.options?.group ?? void 0
1398
1380
  }),
1399
- fileZod: zodResolver && pluginZod?.options ? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
1381
+ fileZod: zodResolver && pluginZod?.options ? zodResolver.file({
1382
+ ...operationFileEntry(node, node.operationId),
1400
1383
  root,
1401
1384
  output: pluginZod.options.output ?? output,
1402
1385
  group: pluginZod.options?.group ?? void 0
@@ -1413,7 +1396,7 @@ const clientGenerator = (0, kubb_kit.defineGenerator)({
1413
1396
  baseName: meta.file.baseName,
1414
1397
  path: meta.file.path,
1415
1398
  meta: meta.file.meta,
1416
- banner: resolver.resolveBanner(ctx.meta, {
1399
+ banner: resolver.default.banner(ctx.meta, {
1417
1400
  output,
1418
1401
  config,
1419
1402
  file: {
@@ -1421,7 +1404,7 @@ const clientGenerator = (0, kubb_kit.defineGenerator)({
1421
1404
  baseName: meta.file.baseName
1422
1405
  }
1423
1406
  }),
1424
- footer: resolver.resolveFooter(ctx.meta, {
1407
+ footer: resolver.default.footer(ctx.meta, {
1425
1408
  output,
1426
1409
  config,
1427
1410
  file: {
@@ -1525,10 +1508,7 @@ const pluginFetch = (0, kubb_kit.definePlugin)((options) => {
1525
1508
  mode: sdk.mode ?? "tag",
1526
1509
  name: sdk.name
1527
1510
  } : void 0,
1528
- resolver: userResolver ? {
1529
- ...resolverClient,
1530
- ...userResolver
1531
- } : resolverClient
1511
+ resolver: userResolver ? kubb_kit.Resolver.merge(resolverClient, userResolver) : resolverClient
1532
1512
  };
1533
1513
  const selectedGenerators = resolved.sdk ? [createSdkGenerator()] : [clientGenerator];
1534
1514
  return {