@kubb/plugin-client 5.0.0-beta.15 → 5.0.0-beta.25

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
@@ -257,12 +257,12 @@ var URLPath = class {
257
257
  get object() {
258
258
  return this.toObject();
259
259
  }
260
- /** Returns a map of path parameter names, or `undefined` when the path has no parameters.
260
+ /** Returns a map of path parameter names, or `null` when the path has no parameters.
261
261
  *
262
262
  * @example
263
263
  * ```ts
264
264
  * new URLPath('/pet/{petId}').params // { petId: 'petId' }
265
- * new URLPath('/pet').params // undefined
265
+ * new URLPath('/pet').params // null
266
266
  * ```
267
267
  */
268
268
  get params() {
@@ -300,12 +300,13 @@ var URLPath = class {
300
300
  * @example
301
301
  * new URLPath('/pet/{petId}').toTemplateString() // '`/pet/${petId}`'
302
302
  */
303
- toTemplateString({ prefix = "", replacer } = {}) {
304
- return `\`${prefix}${this.path.split(/\{([^}]+)\}/).map((part, i) => {
303
+ toTemplateString({ prefix, replacer } = {}) {
304
+ const result = this.path.split(/\{([^}]+)\}/).map((part, i) => {
305
305
  if (i % 2 === 0) return part;
306
306
  const param = this.#transformParam(part);
307
307
  return `\${${replacer ? replacer(param) : param}}`;
308
- }).join("")}\``;
308
+ }).join("");
309
+ return `\`${prefix ?? ""}${result}\``;
309
310
  }
310
311
  /**
311
312
  * Extracts all `{param}` segments from the path and returns them as a key-value map.
@@ -324,7 +325,7 @@ var URLPath = class {
324
325
  const key = replacer ? replacer(param) : param;
325
326
  params[key] = key;
326
327
  });
327
- return Object.keys(params).length > 0 ? params : void 0;
328
+ return Object.keys(params).length > 0 ? params : null;
328
329
  }
329
330
  /** Converts the OpenAPI path to Express-style colon syntax.
330
331
  *
@@ -340,9 +341,9 @@ var URLPath = class {
340
341
  //#endregion
341
342
  //#region ../../internals/shared/src/operation.ts
342
343
  function getOperationLink(node, link) {
343
- if (!link) return;
344
- if (typeof link === "function") return link(node);
345
- if (link === "urlPath") return node.path ? `{@link ${new URLPath(node.path).URL}}` : void 0;
344
+ if (!link) return null;
345
+ if (typeof link === "function") return link(node) ?? null;
346
+ if (link === "urlPath") return node.path ? `{@link ${new URLPath(node.path).URL}}` : null;
346
347
  return `{@link ${node.path.replaceAll("{", ":").replaceAll("}", "")}}`;
347
348
  }
348
349
  function getContentTypeInfo(node) {
@@ -357,9 +358,9 @@ function getContentTypeInfo(node) {
357
358
  };
358
359
  }
359
360
  function buildRequestConfigType(node, resolver) {
360
- const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : void 0;
361
+ const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null;
361
362
  const { isMultipleContentTypes, contentTypeUnion } = getContentTypeInfo(node);
362
- return `${requestName ? `Partial<RequestConfig<${requestName}>>` : "Partial<RequestConfig>"} & { ${["client?: Client", isMultipleContentTypes ? `contentType?: ${contentTypeUnion}` : void 0].filter(Boolean).join("; ")} }`;
363
+ return `${requestName ? `Partial<RequestConfig<${requestName}>>` : "Partial<RequestConfig>"} & { ${["client?: Client", isMultipleContentTypes ? `contentType?: ${contentTypeUnion}` : null].filter(Boolean).join("; ")} }`;
363
364
  }
364
365
  function buildOperationComments(node, options = {}) {
365
366
  const { link = "pathTemplate", linkPosition = "afterDeprecated", splitLines = false } = options;
@@ -389,11 +390,11 @@ function getOperationParameters(node, options = {}) {
389
390
  }
390
391
  function getStatusCodeNumber(statusCode) {
391
392
  const code = Number(statusCode);
392
- return Number.isNaN(code) ? void 0 : code;
393
+ return Number.isNaN(code) ? null : code;
393
394
  }
394
395
  function isErrorStatusCode(statusCode) {
395
396
  const code = getStatusCodeNumber(statusCode);
396
- return code !== void 0 && code >= 400;
397
+ return code !== null && code >= 400;
397
398
  }
398
399
  function resolveErrorNames(node, resolver) {
399
400
  return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
@@ -420,7 +421,7 @@ function resolveOperationTypeNames(node, resolver, options = {}) {
420
421
  ...query.map((param) => resolver.resolveQueryParamsName(node, param)),
421
422
  ...header.map((param) => resolver.resolveHeaderParamsName(node, param))
422
423
  ];
423
- const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : void 0, resolver.resolveResponseName(node)];
424
+ const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null, resolver.resolveResponseName(node)];
424
425
  const result = (options.order === "body-response-first" ? [
425
426
  ...bodyAndResponseNames,
426
427
  ...paramNames,
@@ -443,7 +444,7 @@ function buildParamsMapping(originalParams, mappedParams) {
443
444
  mapping[param.name] = mappedName;
444
445
  if (param.name !== mappedName) hasChanged = true;
445
446
  });
446
- return hasChanged ? mapping : void 0;
447
+ return hasChanged ? mapping : null;
447
448
  }
448
449
  //#endregion
449
450
  //#region src/functionParams.ts
@@ -456,18 +457,18 @@ function createType(type) {
456
457
  return type ? _kubb_core.ast.createParamsType({
457
458
  variant: "reference",
458
459
  name: type
459
- }) : void 0;
460
+ }) : null;
460
461
  }
461
462
  function createDeclarationLeaf(name, spec) {
462
463
  if (spec.default !== void 0) return _kubb_core.ast.createFunctionParameter({
463
464
  name,
464
- type: createType(spec.type),
465
+ type: createType(spec.type) ?? void 0,
465
466
  default: spec.default,
466
467
  rest: spec.mode === "inlineSpread"
467
468
  });
468
469
  return _kubb_core.ast.createFunctionParameter({
469
470
  name,
470
- type: createType(spec.type),
471
+ type: createType(spec.type) ?? void 0,
471
472
  optional: !!spec.optional,
472
473
  rest: spec.mode === "inlineSpread"
473
474
  });
@@ -476,14 +477,14 @@ function createDeclarationParam(name, spec) {
476
477
  if (isGroup(spec)) return _kubb_core.ast.createParameterGroup({
477
478
  inline: spec.mode === "inlineSpread",
478
479
  default: spec.default,
479
- properties: Object.entries(spec.children).filter(([, child]) => child !== void 0).map(([childName, child]) => createDeclarationLeaf(childName, child))
480
+ properties: Object.entries(spec.children).filter(([, child]) => child != null).map(([childName, child]) => createDeclarationLeaf(childName, child))
480
481
  });
481
482
  return createDeclarationLeaf(name, spec);
482
483
  }
483
484
  function createCallParam(name, spec) {
484
485
  if (isGroup(spec)) return _kubb_core.ast.createParameterGroup({
485
486
  inline: spec.mode === "inlineSpread",
486
- properties: Object.entries(spec.children).filter(([, child]) => child !== void 0).map(([childName, child]) => _kubb_core.ast.createFunctionParameter({
487
+ properties: Object.entries(spec.children).filter(([, child]) => child != null).map(([childName, child]) => _kubb_core.ast.createFunctionParameter({
487
488
  name: child?.mode === "inlineSpread" ? spec.mode === "inlineSpread" ? child.value ?? childName : `...${child.value ?? childName}` : child?.value ? `${childName}: ${child.value}` : childName,
488
489
  rest: spec.mode === "inlineSpread" && child?.mode === "inlineSpread"
489
490
  }))
@@ -498,7 +499,7 @@ function createCallParam(name, spec) {
498
499
  * Returns utilities to output constructor signatures (`toConstructor()`) or call expressions (`toCall()`).
499
500
  */
500
501
  function createFunctionParams(params) {
501
- const entries = Object.entries(params).filter(([, spec]) => spec !== void 0);
502
+ const entries = Object.entries(params).filter(([, spec]) => spec != null);
502
503
  return {
503
504
  toConstructor() {
504
505
  return declarationPrinter$4.print(_kubb_core.ast.createFunctionParameters({ params: entries.map(([name, spec]) => createDeclarationParam(name, spec)) })) ?? "";
@@ -536,7 +537,7 @@ function Url({ name, isExportable = true, isIndexable = true, baseURL, paramsTyp
536
537
  const paramsSignature = declarationPrinter$3.print(paramsNode) ?? "";
537
538
  const { path: originalPathParams } = getOperationParameters(node);
538
539
  const { path: casedPathParams } = getOperationParameters(node, { paramsCasing });
539
- const pathParamsMapping = paramsCasing ? buildParamsMapping(originalPathParams, casedPathParams) : void 0;
540
+ const pathParamsMapping = paramsCasing ? buildParamsMapping(originalPathParams, casedPathParams) : null;
540
541
  return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
541
542
  name,
542
543
  isExportable,
@@ -583,19 +584,19 @@ function Client({ name, isExportable = true, isIndexable = true, returnType, bas
583
584
  const isFormData = !isMultipleContentTypes && contentType === "multipart/form-data";
584
585
  const { path: originalPathParams, query: originalQueryParams, header: originalHeaderParams } = getOperationParameters(node);
585
586
  const { path: casedPathParams, query: casedQueryParams, header: casedHeaderParams } = getOperationParameters(node, { paramsCasing });
586
- const pathParamsMapping = paramsCasing && !urlName ? buildParamsMapping(originalPathParams, casedPathParams) : void 0;
587
- const queryParamsMapping = paramsCasing ? buildParamsMapping(originalQueryParams, casedQueryParams) : void 0;
588
- const headerParamsMapping = paramsCasing ? buildParamsMapping(originalHeaderParams, casedHeaderParams) : void 0;
589
- const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : void 0;
587
+ const pathParamsMapping = paramsCasing && !urlName ? buildParamsMapping(originalPathParams, casedPathParams) : null;
588
+ const queryParamsMapping = paramsCasing ? buildParamsMapping(originalQueryParams, casedQueryParams) : null;
589
+ const headerParamsMapping = paramsCasing ? buildParamsMapping(originalHeaderParams, casedHeaderParams) : null;
590
+ const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : null;
590
591
  const responseName = tsResolver.resolveResponseName(node);
591
- const queryParamsName = originalQueryParams.length > 0 ? tsResolver.resolveQueryParamsName(node, originalQueryParams[0]) : void 0;
592
- const headerParamsName = originalHeaderParams.length > 0 ? tsResolver.resolveHeaderParamsName(node, originalHeaderParams[0]) : void 0;
593
- const zodResponseName = zodResolver && parser === "zod" ? zodResolver.resolveResponseName?.(node) : void 0;
594
- const zodRequestName = zodResolver && parser === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : void 0;
592
+ const queryParamsName = originalQueryParams.length > 0 ? tsResolver.resolveQueryParamsName(node, originalQueryParams[0]) : null;
593
+ const headerParamsName = originalHeaderParams.length > 0 ? tsResolver.resolveHeaderParamsName(node, originalHeaderParams[0]) : null;
594
+ const zodResponseName = zodResolver && parser === "zod" ? zodResolver.resolveResponseName?.(node) : null;
595
+ const zodRequestName = zodResolver && parser === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null;
595
596
  const errorNames = node.responses.filter((r) => {
596
597
  return Number.parseInt(r.statusCode, 10) >= 400;
597
598
  }).map((r) => tsResolver.resolveResponseStatusName(node, r.statusCode));
598
- const headers = [!isMultipleContentTypes && contentType !== "application/json" && contentType !== "multipart/form-data" ? `'Content-Type': '${contentType}'` : void 0, headerParamsName ? headerParamsMapping ? "...mappedHeaders" : "...headers" : void 0].filter(Boolean);
599
+ const headers = [!isMultipleContentTypes && contentType !== "application/json" && contentType !== "multipart/form-data" ? `'Content-Type': '${contentType}'` : null, headerParamsName ? headerParamsMapping ? "...mappedHeaders" : "...headers" : null].filter(Boolean);
599
600
  const generics = [
600
601
  responseName,
601
602
  `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`,
@@ -623,12 +624,12 @@ function Client({ name, isExportable = true, isIndexable = true, returnType, bas
623
624
  children: {
624
625
  method: { value: JSON.stringify(node.method.toUpperCase()) },
625
626
  url: { value: urlName ? `${urlName}(${urlParamsCall}).url.toString()` : path.template },
626
- baseURL: baseURL && !urlName ? { value: `\`${baseURL}\`` } : void 0,
627
- params: queryParamsName ? queryParamsMapping ? { value: "mappedParams" } : {} : void 0,
628
- data: requestName ? { value: isMultipleContentTypes && hasFormData ? "contentType === 'multipart/form-data' ? formData as FormData : requestData" : isFormData ? "formData as FormData" : "requestData" } : void 0,
629
- contentType: isConfigurable && isMultipleContentTypes ? {} : void 0,
630
- requestConfig: isConfigurable ? { mode: "inlineSpread" } : void 0,
631
- headers: headers.length ? { value: isConfigurable ? `{ ${headers.join(", ")}, ...requestConfig.headers }` : `{ ${headers.join(", ")} }` } : void 0
627
+ baseURL: baseURL && !urlName ? { value: `\`${baseURL}\`` } : null,
628
+ params: queryParamsName ? queryParamsMapping ? { value: "mappedParams" } : {} : null,
629
+ data: requestName ? { value: isMultipleContentTypes && hasFormData ? "contentType === 'multipart/form-data' ? formData as FormData : requestData" : isFormData ? "formData as FormData" : "requestData" } : null,
630
+ contentType: isConfigurable && isMultipleContentTypes ? {} : null,
631
+ requestConfig: isConfigurable ? { mode: "inlineSpread" } : null,
632
+ headers: headers.length ? { value: isConfigurable ? `{ ${headers.join(", ")}, ...requestConfig.headers }` : `{ ${headers.join(", ")} }` } : null
632
633
  }
633
634
  } });
634
635
  const childrenElement = children ? children : /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
@@ -686,7 +687,7 @@ function Client({ name, isExportable = true, isIndexable = true, returnType, bas
686
687
  * Includes Content-Type (if not default) and spreads header parameters if present.
687
688
  */
688
689
  function buildHeaders(contentType, hasHeaderParams) {
689
- return [contentType !== "application/json" && contentType !== "multipart/form-data" ? `'Content-Type': '${contentType}'` : void 0, hasHeaderParams ? "...headers" : void 0].filter(Boolean);
690
+ return [contentType !== "application/json" && contentType !== "multipart/form-data" ? `'Content-Type': '${contentType}'` : null, hasHeaderParams ? "...headers" : null].filter(Boolean);
690
691
  }
691
692
  /**
692
693
  * Builds TypeScript generic parameters for a client method.
@@ -694,7 +695,7 @@ function buildHeaders(contentType, hasHeaderParams) {
694
695
  */
695
696
  function buildGenerics(node, tsResolver) {
696
697
  const responseName = tsResolver.resolveResponseName(node);
697
- const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : void 0;
698
+ const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : null;
698
699
  const errorNames = node.responses.filter((r) => Number.parseInt(r.statusCode, 10) >= 400).map((r) => tsResolver.resolveResponseStatusName(node, r.statusCode));
699
700
  return [
700
701
  responseName,
@@ -708,19 +709,19 @@ function buildGenerics(node, tsResolver) {
708
709
  */
709
710
  function buildClassClientParams({ node, path, baseURL, tsResolver, isFormData, isMultipleContentTypes, hasFormData, headers }) {
710
711
  const { query: queryParams } = getOperationParameters(node);
711
- const queryParamsName = queryParams.length > 0 ? tsResolver.resolveQueryParamsName(node, queryParams[0]) : void 0;
712
- const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : void 0;
712
+ const queryParamsName = queryParams.length > 0 ? tsResolver.resolveQueryParamsName(node, queryParams[0]) : null;
713
+ const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : null;
713
714
  return createFunctionParams({ config: {
714
715
  mode: "object",
715
716
  children: {
716
717
  requestConfig: { mode: "inlineSpread" },
717
718
  method: { value: JSON.stringify(node.method.toUpperCase()) },
718
719
  url: { value: path.template },
719
- baseURL: baseURL ? { value: JSON.stringify(baseURL) } : void 0,
720
- params: queryParamsName ? {} : void 0,
721
- data: requestName ? { value: isMultipleContentTypes && hasFormData ? "contentType === 'multipart/form-data' ? formData as FormData : requestData" : isFormData ? "formData as FormData" : "requestData" } : void 0,
722
- contentType: isMultipleContentTypes ? {} : void 0,
723
- headers: headers.length ? { value: `{ ${headers.join(", ")}, ...requestConfig.headers }` } : void 0
720
+ baseURL: baseURL ? { value: JSON.stringify(baseURL) } : null,
721
+ params: queryParamsName ? {} : null,
722
+ data: requestName ? { value: isMultipleContentTypes && hasFormData ? "contentType === 'multipart/form-data' ? formData as FormData : requestData" : isFormData ? "formData as FormData" : "requestData" } : null,
723
+ contentType: isMultipleContentTypes ? {} : null,
724
+ headers: headers.length ? { value: `{ ${headers.join(", ")}, ...requestConfig.headers }` } : null
724
725
  }
725
726
  } });
726
727
  }
@@ -729,7 +730,7 @@ function buildClassClientParams({ node, path, baseURL, tsResolver, isFormData, i
729
730
  * Applies Zod validation if configured, otherwise uses data directly.
730
731
  */
731
732
  function buildRequestDataLine({ parser, node, zodResolver }) {
732
- const zodRequestName = zodResolver && parser === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : void 0;
733
+ const zodRequestName = zodResolver && parser === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null;
733
734
  if (parser === "zod" && zodRequestName) return `const requestData = ${zodRequestName}.parse(data)`;
734
735
  if (node.requestBody?.content?.[0]?.schema) return "const requestData = data";
735
736
  return "";
@@ -746,7 +747,7 @@ function buildFormDataLine(isFormData, hasRequest) {
746
747
  * Applies Zod validation to response data if configured, otherwise returns raw response.
747
748
  */
748
749
  function buildReturnStatement({ dataReturnType, parser, node, zodResolver }) {
749
- const zodResponseName = zodResolver && parser === "zod" ? zodResolver.resolveResponseName?.(node) : void 0;
750
+ const zodResponseName = zodResolver && parser === "zod" ? zodResolver.resolveResponseName?.(node) : null;
750
751
  if (dataReturnType === "full" && parser === "zod" && zodResponseName) return `return {...res, data: ${zodResponseName}.parse(res.data)}`;
751
752
  if (dataReturnType === "data" && parser === "zod" && zodResponseName) return `return ${zodResponseName}.parse(res.data)`;
752
753
  if (dataReturnType === "full" && parser === "client") return "return res";
@@ -760,7 +761,7 @@ function generateMethod$1({ node, name, tsResolver, zodResolver, baseURL, dataRe
760
761
  const { defaultContentType: contentType, isMultipleContentTypes, hasFormData } = getContentTypeInfo(node);
761
762
  const isFormData = !isMultipleContentTypes && contentType === "multipart/form-data";
762
763
  const { header: headerParams } = getOperationParameters(node);
763
- const headerParamsName = headerParams.length > 0 ? tsResolver.resolveHeaderParamsName(node, headerParams[0]) : void 0;
764
+ const headerParamsName = headerParams.length > 0 ? tsResolver.resolveHeaderParamsName(node, headerParams[0]) : null;
764
765
  const headers = isMultipleContentTypes ? headerParamsName ? ["...headers"] : [] : buildHeaders(contentType, !!headerParamsName);
765
766
  const generics = buildGenerics(node, tsResolver);
766
767
  const paramsNode = buildClientParamsNode({
@@ -861,22 +862,27 @@ function resolveTypeImportNames$1(node, tsResolver) {
861
862
  }
862
863
  require_chunk.__name(resolveTypeImportNames$1, "resolveTypeImportNames");
863
864
  function resolveZodImportNames$1(node, zodResolver) {
864
- return [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : void 0].filter((n) => Boolean(n));
865
+ return [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null].filter((n) => Boolean(n));
865
866
  }
866
867
  require_chunk.__name(resolveZodImportNames$1, "resolveZodImportNames");
868
+ /**
869
+ * Built-in `operations` generator for `@kubb/plugin-client` when
870
+ * `clientType: 'class'`. Emits one class per tag, with one instance method
871
+ * per operation and a shared constructor for request configuration.
872
+ */
867
873
  const classClientGenerator = (0, _kubb_core.defineGenerator)({
868
874
  name: "classClient",
869
875
  renderer: _kubb_renderer_jsx.jsxRendererSync,
870
876
  operations(nodes, ctx) {
871
- const { config, driver, resolver, root, inputNode } = ctx;
877
+ const { config, driver, resolver, root } = ctx;
872
878
  const { output, group, dataReturnType, paramsCasing, paramsType, pathParamsType, parser, importPath, sdk } = ctx.options;
873
- const baseURL = ctx.options.baseURL ?? inputNode.meta?.baseURL;
879
+ const baseURL = ctx.options.baseURL ?? ctx.meta.baseURL;
874
880
  const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
875
881
  if (!pluginTs) return null;
876
882
  const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
877
883
  const tsPluginOptions = pluginTs.options;
878
- const pluginZod = parser === "zod" ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : void 0;
879
- const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : void 0;
884
+ const pluginZod = parser === "zod" ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : null;
885
+ const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : null;
880
886
  function buildOperationData(node) {
881
887
  const typeFile = tsResolver.resolveFile({
882
888
  name: node.operationId,
@@ -896,8 +902,8 @@ const classClientGenerator = (0, _kubb_core.defineGenerator)({
896
902
  }, {
897
903
  root,
898
904
  output: pluginZod.options?.output ?? output,
899
- group: pluginZod.options?.group
900
- }) : void 0;
905
+ group: pluginZod.options?.group ?? void 0
906
+ }) : null;
901
907
  return {
902
908
  node,
903
909
  name: resolver.resolveName(node.operationId),
@@ -918,7 +924,7 @@ const classClientGenerator = (0, _kubb_core.defineGenerator)({
918
924
  }, {
919
925
  root,
920
926
  output,
921
- group
927
+ group: group ?? void 0
922
928
  });
923
929
  const operationData = buildOperationData(operationNode);
924
930
  const previous = acc.find((item) => item.file.path === file.path);
@@ -929,7 +935,9 @@ const classClientGenerator = (0, _kubb_core.defineGenerator)({
929
935
  file,
930
936
  operations: [operationData]
931
937
  });
932
- } else if (tag) {
938
+ return acc;
939
+ }
940
+ if (tag) {
933
941
  const name = groupName;
934
942
  const file = resolver.resolveFile({
935
943
  name,
@@ -938,7 +946,7 @@ const classClientGenerator = (0, _kubb_core.defineGenerator)({
938
946
  }, {
939
947
  root,
940
948
  output,
941
- group
949
+ group: group ?? void 0
942
950
  });
943
951
  const operationData = buildOperationData(operationNode);
944
952
  const previous = acc.find((item) => item.file.path === file.path);
@@ -998,11 +1006,11 @@ const classClientGenerator = (0, _kubb_core.defineGenerator)({
998
1006
  baseName: file.baseName,
999
1007
  path: file.path,
1000
1008
  meta: file.meta,
1001
- banner: resolver.resolveBanner(inputNode, {
1009
+ banner: resolver.resolveBanner(ctx.meta, {
1002
1010
  output,
1003
1011
  config
1004
1012
  }),
1005
- footer: resolver.resolveFooter(inputNode, {
1013
+ footer: resolver.resolveFooter(ctx.meta, {
1006
1014
  output,
1007
1015
  config
1008
1016
  }),
@@ -1095,17 +1103,17 @@ const classClientGenerator = (0, _kubb_core.defineGenerator)({
1095
1103
  }, {
1096
1104
  root,
1097
1105
  output,
1098
- group
1106
+ group: group ?? void 0
1099
1107
  });
1100
1108
  files.push(/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
1101
1109
  baseName: sdkFile.baseName,
1102
1110
  path: sdkFile.path,
1103
1111
  meta: sdkFile.meta,
1104
- banner: resolver.resolveBanner(inputNode, {
1112
+ banner: resolver.resolveBanner(ctx.meta, {
1105
1113
  output,
1106
1114
  config
1107
1115
  }),
1108
- footer: resolver.resolveFooter(inputNode, {
1116
+ footer: resolver.resolveFooter(ctx.meta, {
1109
1117
  output,
1110
1118
  config
1111
1119
  }),
@@ -1140,20 +1148,25 @@ const classClientGenerator = (0, _kubb_core.defineGenerator)({
1140
1148
  });
1141
1149
  //#endregion
1142
1150
  //#region src/generators/clientGenerator.tsx
1151
+ /**
1152
+ * Built-in operation generator for `@kubb/plugin-client`. Emits one async
1153
+ * function per OpenAPI operation, plus the matching URL helper. Used when
1154
+ * `clientType: 'function'` (the default).
1155
+ */
1143
1156
  const clientGenerator = (0, _kubb_core.defineGenerator)({
1144
1157
  name: "client",
1145
1158
  renderer: _kubb_renderer_jsx.jsxRendererSync,
1146
1159
  operation(node, ctx) {
1147
- const { config, driver, resolver, root, inputNode } = ctx;
1160
+ const { config, driver, resolver, root } = ctx;
1148
1161
  const { output, urlType, dataReturnType, paramsCasing, paramsType, pathParamsType, parser, importPath, group } = ctx.options;
1149
- const baseURL = ctx.options.baseURL ?? inputNode.meta?.baseURL;
1162
+ const baseURL = ctx.options.baseURL ?? ctx.meta.baseURL;
1150
1163
  const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1151
1164
  if (!pluginTs) return null;
1152
1165
  const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
1153
- const pluginZod = parser === "zod" ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : void 0;
1154
- const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : void 0;
1166
+ const pluginZod = parser === "zod" ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : null;
1167
+ const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : null;
1155
1168
  const importedTypeNames = resolveOperationTypeNames(node, tsResolver, { paramsCasing });
1156
- const importedZodNames = zodResolver && parser === "zod" ? [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : void 0].filter((name) => Boolean(name)) : [];
1169
+ const importedZodNames = zodResolver && parser === "zod" ? [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null].filter((name) => Boolean(name)) : [];
1157
1170
  const meta = {
1158
1171
  name: resolver.resolveName(node.operationId),
1159
1172
  urlName: resolver.resolveUrlName(node),
@@ -1165,7 +1178,7 @@ const clientGenerator = (0, _kubb_core.defineGenerator)({
1165
1178
  }, {
1166
1179
  root,
1167
1180
  output,
1168
- group
1181
+ group: group ?? void 0
1169
1182
  }),
1170
1183
  fileTs: tsResolver.resolveFile({
1171
1184
  name: node.operationId,
@@ -1175,7 +1188,7 @@ const clientGenerator = (0, _kubb_core.defineGenerator)({
1175
1188
  }, {
1176
1189
  root,
1177
1190
  output: pluginTs.options?.output ?? output,
1178
- group: pluginTs.options?.group
1191
+ group: pluginTs.options?.group ?? void 0
1179
1192
  }),
1180
1193
  fileZod: zodResolver && pluginZod?.options ? zodResolver.resolveFile({
1181
1194
  name: node.operationId,
@@ -1185,19 +1198,19 @@ const clientGenerator = (0, _kubb_core.defineGenerator)({
1185
1198
  }, {
1186
1199
  root,
1187
1200
  output: pluginZod.options.output ?? output,
1188
- group: pluginZod.options?.group
1189
- }) : void 0
1201
+ group: pluginZod.options?.group ?? void 0
1202
+ }) : null
1190
1203
  };
1191
1204
  const hasFormData = node.requestBody?.content?.some((e) => e.contentType === "multipart/form-data") ?? false;
1192
1205
  return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
1193
1206
  baseName: meta.file.baseName,
1194
1207
  path: meta.file.path,
1195
1208
  meta: meta.file.meta,
1196
- banner: resolver.resolveBanner(inputNode, {
1209
+ banner: resolver.resolveBanner(ctx.meta, {
1197
1210
  output,
1198
1211
  config
1199
1212
  }),
1200
- footer: resolver.resolveFooter(inputNode, {
1213
+ footer: resolver.resolveFooter(ctx.meta, {
1201
1214
  output,
1202
1215
  config
1203
1216
  }),
@@ -1273,16 +1286,22 @@ const clientGenerator = (0, _kubb_core.defineGenerator)({
1273
1286
  });
1274
1287
  //#endregion
1275
1288
  //#region src/generators/groupedClientGenerator.tsx
1289
+ /**
1290
+ * Emits one aggregate file per tag/group when `group` is configured. Each
1291
+ * file re-exports every client function for that group, so callers can
1292
+ * `import { petController } from './gen/clients'` instead of importing
1293
+ * each operation individually.
1294
+ */
1276
1295
  const groupedClientGenerator = (0, _kubb_core.defineGenerator)({
1277
1296
  name: "groupedClient",
1278
1297
  renderer: _kubb_renderer_jsx.jsxRendererSync,
1279
1298
  operations(nodes, ctx) {
1280
- const { config, resolver, root, inputNode } = ctx;
1299
+ const { config, resolver, root } = ctx;
1281
1300
  const { output, group } = ctx.options;
1282
1301
  return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: nodes.reduce((acc, operationNode) => {
1283
1302
  if (group?.type === "tag") {
1284
1303
  const tag = operationNode.tags[0];
1285
- const name = tag ? group?.name?.({ group: camelCase(tag) }) : void 0;
1304
+ const name = tag ? group?.name?.({ group: camelCase(tag) }) : null;
1286
1305
  if (!tag || !name) return acc;
1287
1306
  const file = resolver.resolveFile({
1288
1307
  name,
@@ -1291,7 +1310,7 @@ const groupedClientGenerator = (0, _kubb_core.defineGenerator)({
1291
1310
  }, {
1292
1311
  root,
1293
1312
  output,
1294
- group
1313
+ group: group ?? void 0
1295
1314
  });
1296
1315
  const clientFile = resolver.resolveFile({
1297
1316
  name: operationNode.operationId,
@@ -1301,7 +1320,7 @@ const groupedClientGenerator = (0, _kubb_core.defineGenerator)({
1301
1320
  }, {
1302
1321
  root,
1303
1322
  output,
1304
- group
1323
+ group: group ?? void 0
1305
1324
  });
1306
1325
  const client = {
1307
1326
  name: resolver.resolveName(operationNode.operationId),
@@ -1321,11 +1340,11 @@ const groupedClientGenerator = (0, _kubb_core.defineGenerator)({
1321
1340
  baseName: file.baseName,
1322
1341
  path: file.path,
1323
1342
  meta: file.meta,
1324
- banner: resolver.resolveBanner(inputNode, {
1343
+ banner: resolver.resolveBanner(ctx.meta, {
1325
1344
  output,
1326
1345
  config
1327
1346
  }),
1328
- footer: resolver.resolveFooter(inputNode, {
1347
+ footer: resolver.resolveFooter(ctx.meta, {
1329
1348
  output,
1330
1349
  config
1331
1350
  }),
@@ -1370,11 +1389,17 @@ function Operations({ name, nodes }) {
1370
1389
  }
1371
1390
  //#endregion
1372
1391
  //#region src/generators/operationsGenerator.tsx
1392
+ /**
1393
+ * Generates an `operations.ts` file that re-exports every operation grouped
1394
+ * by HTTP method. Enabled when `pluginClient({ operations: true })`. Useful
1395
+ * for building meta-tooling on top of the generated client (route
1396
+ * registries, API explorers).
1397
+ */
1373
1398
  const operationsGenerator = (0, _kubb_core.defineGenerator)({
1374
1399
  name: "client",
1375
1400
  renderer: _kubb_renderer_jsx.jsxRendererSync,
1376
1401
  operations(nodes, ctx) {
1377
- const { config, resolver, root, inputNode } = ctx;
1402
+ const { config, resolver, root } = ctx;
1378
1403
  const { output, group } = ctx.options;
1379
1404
  const name = "operations";
1380
1405
  const file = resolver.resolveFile({
@@ -1383,17 +1408,17 @@ const operationsGenerator = (0, _kubb_core.defineGenerator)({
1383
1408
  }, {
1384
1409
  root,
1385
1410
  output,
1386
- group
1411
+ group: group ?? void 0
1387
1412
  });
1388
1413
  return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File, {
1389
1414
  baseName: file.baseName,
1390
1415
  path: file.path,
1391
1416
  meta: file.meta,
1392
- banner: resolver.resolveBanner(inputNode, {
1417
+ banner: resolver.resolveBanner(ctx.meta, {
1393
1418
  output,
1394
1419
  config
1395
1420
  }),
1396
- footer: resolver.resolveFooter(inputNode, {
1421
+ footer: resolver.resolveFooter(ctx.meta, {
1397
1422
  output,
1398
1423
  config
1399
1424
  }),
@@ -1412,7 +1437,7 @@ function generateMethod({ node, name, tsResolver, zodResolver, baseURL, dataRetu
1412
1437
  const { defaultContentType: contentType, isMultipleContentTypes, hasFormData } = getContentTypeInfo(node);
1413
1438
  const isFormData = !isMultipleContentTypes && contentType === "multipart/form-data";
1414
1439
  const { header: headerParams } = getOperationParameters(node);
1415
- const headerParamsName = headerParams.length > 0 ? tsResolver.resolveHeaderParamsName(node, headerParams[0]) : void 0;
1440
+ const headerParamsName = headerParams.length > 0 ? tsResolver.resolveHeaderParamsName(node, headerParams[0]) : null;
1416
1441
  const headers = isMultipleContentTypes ? headerParamsName ? ["...headers"] : [] : buildHeaders(contentType, !!headerParamsName);
1417
1442
  const generics = buildGenerics(node, tsResolver);
1418
1443
  const paramsNode = buildClientParamsNode({
@@ -1486,21 +1511,27 @@ function resolveTypeImportNames(node, tsResolver) {
1486
1511
  return resolveOperationTypeNames(node, tsResolver, { order: "body-response-first" });
1487
1512
  }
1488
1513
  function resolveZodImportNames(node, zodResolver) {
1489
- return [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : void 0].filter((n) => Boolean(n));
1514
+ return [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null].filter((n) => Boolean(n));
1490
1515
  }
1516
+ /**
1517
+ * Built-in `operations` generator for `@kubb/plugin-client` when
1518
+ * `clientType: 'staticClass'`. Emits one class per tag, with a static method
1519
+ * per operation so callers can use `Pet.getPetById(...)` without
1520
+ * instantiating the class.
1521
+ */
1491
1522
  const staticClassClientGenerator = (0, _kubb_core.defineGenerator)({
1492
1523
  name: "staticClassClient",
1493
1524
  renderer: _kubb_renderer_jsx.jsxRendererSync,
1494
1525
  operations(nodes, ctx) {
1495
- const { config, driver, resolver, root, inputNode } = ctx;
1526
+ const { config, driver, resolver, root } = ctx;
1496
1527
  const { output, group, dataReturnType, paramsCasing, paramsType, pathParamsType, parser, importPath } = ctx.options;
1497
- const baseURL = ctx.options.baseURL ?? inputNode.meta?.baseURL;
1528
+ const baseURL = ctx.options.baseURL ?? ctx.meta.baseURL;
1498
1529
  const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1499
1530
  if (!pluginTs) return null;
1500
1531
  const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
1501
1532
  const tsPluginOptions = pluginTs.options;
1502
- const pluginZod = parser === "zod" ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : void 0;
1503
- const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : void 0;
1533
+ const pluginZod = parser === "zod" ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : null;
1534
+ const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : null;
1504
1535
  function buildOperationData(node) {
1505
1536
  const typeFile = tsResolver.resolveFile({
1506
1537
  name: node.operationId,
@@ -1520,8 +1551,8 @@ const staticClassClientGenerator = (0, _kubb_core.defineGenerator)({
1520
1551
  }, {
1521
1552
  root,
1522
1553
  output: pluginZod.options?.output ?? output,
1523
- group: pluginZod.options?.group
1524
- }) : void 0;
1554
+ group: pluginZod.options?.group ?? void 0
1555
+ }) : null;
1525
1556
  return {
1526
1557
  node,
1527
1558
  name: resolver.resolveName(node.operationId),
@@ -1542,7 +1573,7 @@ const staticClassClientGenerator = (0, _kubb_core.defineGenerator)({
1542
1573
  }, {
1543
1574
  root,
1544
1575
  output,
1545
- group
1576
+ group: group ?? void 0
1546
1577
  });
1547
1578
  const operationData = buildOperationData(operationNode);
1548
1579
  const previous = acc.find((item) => item.file.path === file.path);
@@ -1552,7 +1583,9 @@ const staticClassClientGenerator = (0, _kubb_core.defineGenerator)({
1552
1583
  file,
1553
1584
  operations: [operationData]
1554
1585
  });
1555
- } else if (tag) {
1586
+ return acc;
1587
+ }
1588
+ if (tag) {
1556
1589
  const name = groupName;
1557
1590
  const file = resolver.resolveFile({
1558
1591
  name,
@@ -1561,7 +1594,7 @@ const staticClassClientGenerator = (0, _kubb_core.defineGenerator)({
1561
1594
  }, {
1562
1595
  root,
1563
1596
  output,
1564
- group
1597
+ group: group ?? void 0
1565
1598
  });
1566
1599
  const operationData = buildOperationData(operationNode);
1567
1600
  const previous = acc.find((item) => item.file.path === file.path);
@@ -1620,11 +1653,11 @@ const staticClassClientGenerator = (0, _kubb_core.defineGenerator)({
1620
1653
  baseName: file.baseName,
1621
1654
  path: file.path,
1622
1655
  meta: file.meta,
1623
- banner: resolver.resolveBanner(inputNode, {
1656
+ banner: resolver.resolveBanner(ctx.meta, {
1624
1657
  output,
1625
1658
  config
1626
1659
  }),
1627
- footer: resolver.resolveFooter(inputNode, {
1660
+ footer: resolver.resolveFooter(ctx.meta, {
1628
1661
  output,
1629
1662
  config
1630
1663
  }),
@@ -1715,12 +1748,18 @@ const staticClassClientGenerator = (0, _kubb_core.defineGenerator)({
1715
1748
  //#endregion
1716
1749
  //#region src/resolvers/resolverClient.ts
1717
1750
  /**
1718
- * Naming convention resolver for client plugin.
1751
+ * Default resolver used by `@kubb/plugin-client`. Decides the names and file
1752
+ * paths for every generated client function or class. Functions and files use
1753
+ * camelCase; classes and tag groups use PascalCase.
1719
1754
  *
1720
- * Provides default naming helpers using camelCase for functions and file paths.
1755
+ * @example Resolve client function and class names
1756
+ * ```ts
1757
+ * import { resolverClient } from '@kubb/plugin-client'
1721
1758
  *
1722
- * @example
1723
- * `resolverClient.default('list pets', 'function') // 'listPets'`
1759
+ * resolverClient.default('list pets', 'function') // 'listPets'
1760
+ * resolverClient.resolveClassName('pet') // 'Pet'
1761
+ * resolverClient.resolveUrlName(operationNode) // 'getShowPetByIdUrl'
1762
+ * ```
1724
1763
  */
1725
1764
  const resolverClient = (0, _kubb_core.defineResolver)(() => ({
1726
1765
  name: "default",
@@ -1751,19 +1790,32 @@ const resolverClient = (0, _kubb_core.defineResolver)(() => ({
1751
1790
  //#endregion
1752
1791
  //#region src/plugin.ts
1753
1792
  /**
1754
- * Canonical plugin name for `@kubb/plugin-client`, used in driver lookups and warnings.
1793
+ * Canonical plugin name for `@kubb/plugin-client`. Used for driver lookups and
1794
+ * cross-plugin dependency references.
1755
1795
  */
1756
1796
  const pluginClientName = "plugin-client";
1757
1797
  /**
1758
- * Generates type-safe HTTP client functions or classes from an OpenAPI specification.
1759
- * Creates client APIs by walking operations and delegating to generators.
1760
- * Writes barrel files based on the configured `barrelType`.
1798
+ * Generates one HTTP client function per OpenAPI operation. Each function has
1799
+ * typed path params, query params, body, and response, so callers use the API
1800
+ * like any other typed function. Ships with `axios` and `fetch` runtimes; bring
1801
+ * your own by setting `importPath`.
1761
1802
  *
1762
- * @example Client generator
1803
+ * @example
1763
1804
  * ```ts
1764
- * import pluginClient from '@kubb/plugin-client'
1805
+ * import { defineConfig } from 'kubb'
1806
+ * import { pluginTs } from '@kubb/plugin-ts'
1807
+ * import { pluginClient } from '@kubb/plugin-client'
1808
+ *
1765
1809
  * export default defineConfig({
1766
- * plugins: [pluginClient({ output: { path: 'clients' } })]
1810
+ * input: { path: './petStore.yaml' },
1811
+ * output: { path: './src/gen' },
1812
+ * plugins: [
1813
+ * pluginTs(),
1814
+ * pluginClient({
1815
+ * output: { path: './clients' },
1816
+ * client: 'fetch',
1817
+ * }),
1818
+ * ],
1767
1819
  * })
1768
1820
  * ```
1769
1821
  */
@@ -1775,8 +1827,8 @@ const pluginClient = (0, _kubb_core.definePlugin)((options) => {
1775
1827
  const resolvedImportPath = importPath ?? (!bundle ? `@kubb/plugin-client/clients/${client}` : void 0);
1776
1828
  const selectedGenerators = options.generators ?? [
1777
1829
  clientType === "staticClass" ? staticClassClientGenerator : clientType === "class" ? classClientGenerator : clientGenerator,
1778
- group && clientType === "function" ? groupedClientGenerator : void 0,
1779
- operations ? operationsGenerator : void 0
1830
+ group && clientType === "function" ? groupedClientGenerator : null,
1831
+ operations ? operationsGenerator : null
1780
1832
  ].filter((x) => Boolean(x));
1781
1833
  const groupConfig = group ? {
1782
1834
  ...group,
@@ -1784,11 +1836,11 @@ const pluginClient = (0, _kubb_core.definePlugin)((options) => {
1784
1836
  if (group.type === "path") return `${ctx.group.split("/")[1]}`;
1785
1837
  return `${camelCase(ctx.group)}Controller`;
1786
1838
  }
1787
- } : void 0;
1839
+ } : null;
1788
1840
  return {
1789
1841
  name: pluginClientName,
1790
1842
  options,
1791
- dependencies: [_kubb_plugin_ts.pluginTsName, parser === "zod" ? _kubb_plugin_zod.pluginZodName : void 0].filter((dependency) => Boolean(dependency)),
1843
+ dependencies: [_kubb_plugin_ts.pluginTsName, parser === "zod" ? _kubb_plugin_zod.pluginZodName : null].filter((dependency) => Boolean(dependency)),
1792
1844
  hooks: { "kubb:plugin:setup"(ctx) {
1793
1845
  const resolver = userResolver ? {
1794
1846
  ...resolverClient,