@kubb/plugin-cypress 5.0.0-beta.64 → 5.0.0-beta.74

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/README.md CHANGED
@@ -22,9 +22,9 @@
22
22
 
23
23
  # @kubb/plugin-cypress
24
24
 
25
- ### Generate Cypress commands from OpenAPI
25
+ ### Generate Cypress commands with Kubb
26
26
 
27
- `@kubb/plugin-cypress` generates Cypress request commands from your OpenAPI specification. Each operation in the spec becomes a typed Cypress command, ready to use in your test files.
27
+ `@kubb/plugin-cypress` generates Cypress request commands with Kubb. Each operation becomes a typed Cypress command, ready to use in your test files.
28
28
 
29
29
  ## Installation
30
30
 
package/dist/index.cjs CHANGED
@@ -4,10 +4,9 @@ Object.defineProperties(exports, {
4
4
  });
5
5
  //#endregion
6
6
  let _kubb_core = require("@kubb/core");
7
- let _kubb_ast_utils = require("@kubb/ast/utils");
8
- let _kubb_plugin_ts = require("@kubb/plugin-ts");
9
7
  let _kubb_renderer_jsx = require("@kubb/renderer-jsx");
10
8
  let _kubb_renderer_jsx_jsx_runtime = require("@kubb/renderer-jsx/jsx-runtime");
9
+ let _kubb_plugin_ts = require("@kubb/plugin-ts");
11
10
  //#region ../../internals/utils/src/casing.ts
12
11
  /**
13
12
  * Shared implementation for camelCase and PascalCase conversion.
@@ -220,6 +219,22 @@ var Url = class Url {
220
219
  return `\`${prefix ?? ""}${result}\``;
221
220
  }
222
221
  /**
222
+ * Converts an OpenAPI/Swagger path to a template literal that reads each parameter off the
223
+ * grouped `path` request option, e.g. `/pet/{petId}` becomes `` `/pet/${path.petId}` ``. Parameter
224
+ * names are camelCased to match the generated `path` type, and `prefix` is prepended inside the
225
+ * literal. Shared by the client and cypress generators that pass a grouped `path` object.
226
+ *
227
+ * @example
228
+ * Url.toGroupedTemplateString('/pet/{petId}') // '`/pet/${path.petId}`'
229
+ */
230
+ static toGroupedTemplateString(path, { prefix } = {}) {
231
+ return Url.toTemplateString(path, {
232
+ prefix,
233
+ casing: "camelcase",
234
+ replacer: (name) => `path.${name}`
235
+ });
236
+ }
237
+ /**
223
238
  * Returns the path and its extracted params as a structured `URLObject`, or as a stringified
224
239
  * expression when `stringify` is set.
225
240
  *
@@ -247,9 +262,108 @@ var Url = class Url {
247
262
  }
248
263
  };
249
264
  //#endregion
265
+ //#region ../../internals/shared/src/params.ts
266
+ const caseParamsCache = /* @__PURE__ */ new WeakMap();
267
+ /**
268
+ * Applies camelCase to parameter names and returns a new array without mutating the input.
269
+ *
270
+ * Run it before handing parameters to schema builders so output property keys get the right casing
271
+ * while `OperationNode.parameters` stays intact for other consumers. When `casing` is unset, the
272
+ * original array is returned unchanged. Results are cached per input array.
273
+ */
274
+ function caseParams(params, casing) {
275
+ if (!casing) return params;
276
+ const cached = caseParamsCache.get(params);
277
+ if (cached) return cached;
278
+ const result = params.map((param) => ({
279
+ ...param,
280
+ name: camelCase(param.name)
281
+ }));
282
+ caseParamsCache.set(params, result);
283
+ return result;
284
+ }
285
+ function buildParamsMapping(originalParams, mappedParams) {
286
+ const mapping = {};
287
+ let hasChanged = false;
288
+ originalParams.forEach((param, i) => {
289
+ const mappedName = mappedParams[i]?.name ?? param.name;
290
+ mapping[param.name] = mappedName;
291
+ if (param.name !== mappedName) hasChanged = true;
292
+ });
293
+ return hasChanged ? mapping : null;
294
+ }
295
+ //#endregion
250
296
  //#region ../../internals/shared/src/operation.ts
297
+ function getContentTypeInfo(node) {
298
+ const contentTypes = node.requestBody?.content?.map((e) => e.contentType) ?? [];
299
+ const isMultipleContentTypes = contentTypes.length > 1;
300
+ return {
301
+ contentTypes,
302
+ isMultipleContentTypes,
303
+ contentTypeUnion: isMultipleContentTypes ? contentTypes.map((ct) => JSON.stringify(ct)).join(" | ") : "",
304
+ defaultContentType: contentTypes[0] ?? "application/json",
305
+ hasFormData: contentTypes.some((ct) => ct === "multipart/form-data")
306
+ };
307
+ }
308
+ function buildRequestConfigType(node) {
309
+ const { isMultipleContentTypes, contentTypeUnion } = getContentTypeInfo(node);
310
+ const configType = `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`;
311
+ const contentTypeProp = isMultipleContentTypes ? `contentType?: ${contentTypeUnion}` : null;
312
+ return contentTypeProp ? `${configType} & { ${contentTypeProp} }` : configType;
313
+ }
314
+ /**
315
+ * Which of the grouped request options an operation carries.
316
+ */
317
+ function getRequestGroups(node) {
318
+ const { path, query, header } = getOperationParameters(node);
319
+ return {
320
+ path: path.length > 0,
321
+ query: query.length > 0,
322
+ body: Boolean(node.requestBody?.content?.[0]?.schema),
323
+ headers: header.length > 0
324
+ };
325
+ }
326
+ /**
327
+ * Resolves which grouped request options an operation carries together with whether each group
328
+ * holds a required member. The grouped parameter stays optional only when nothing inside it is
329
+ * required, matching the generated `RequestConfig` type.
330
+ */
331
+ function getRequestGroupOptionality(node) {
332
+ const groups = getRequestGroups(node);
333
+ const { path, query, header } = getOperationParameters(node);
334
+ const hasRequiredPath = path.some((param) => param.required);
335
+ const hasRequiredQuery = query.some((param) => param.required);
336
+ const hasRequiredHeader = header.some((param) => param.required);
337
+ return {
338
+ groups,
339
+ hasRequiredPath,
340
+ hasRequiredQuery,
341
+ hasRequiredHeader,
342
+ isOptional: !hasRequiredPath && !hasRequiredQuery && !hasRequiredHeader && !groups.body
343
+ };
344
+ }
345
+ /**
346
+ * Builds the grouped `{ path, query, body, headers }` parameter for a generated client
347
+ * function, typed from the operation's `RequestConfig` (minus `url`). Only the groups the
348
+ * operation actually has are destructured. The trailing `config` parameter carries the
349
+ * runtime `RequestConfig` overrides plus `client`.
350
+ */
351
+ function buildRequestParamsSignature(node, resolver, options = {}) {
352
+ const { isConfigurable = true } = options;
353
+ const { groups, isOptional } = getRequestGroupOptionality(node);
354
+ const names = [
355
+ "path",
356
+ "query",
357
+ "body",
358
+ "headers"
359
+ ].filter((key) => groups[key]);
360
+ return {
361
+ signature: [names.length > 0 ? `{ ${names.join(", ")} }: ${resolver.resolveRequestConfigName(node)}${isOptional ? " = {}" : ""}` : null, isConfigurable ? `config: ${buildRequestConfigType(node)} = {}` : null].filter(Boolean).join(", "),
362
+ groups
363
+ };
364
+ }
251
365
  function getOperationParameters(node, options = {}) {
252
- const params = (0, _kubb_ast_utils.caseParams)(node.parameters, options.paramsCasing);
366
+ const params = caseParams(node.parameters, options.paramsCasing === "original" ? void 0 : "camelcase");
253
367
  return {
254
368
  path: params.filter((param) => param.in === "path"),
255
369
  query: params.filter((param) => param.in === "query"),
@@ -273,7 +387,7 @@ function resolveStatusCodeNames(node, resolver) {
273
387
  }
274
388
  const typeNamesByResolver = /* @__PURE__ */ new WeakMap();
275
389
  function resolveOperationTypeNames(node, resolver, options = {}) {
276
- const cacheKey = `${node.operationId}\0${options.paramsCasing ?? ""}\0${options.order ?? ""}\0${options.responseStatusNames ?? ""}\0${(options.exclude ?? []).join(",")}`;
390
+ const cacheKey = `${node.operationId}\0${options.paramsCasing ?? ""}\0${options.order ?? ""}\0${options.responseStatusNames ?? ""}\0${options.includeParams === false ? "noparams" : ""}\0${(options.exclude ?? []).join(",")}`;
277
391
  let byResolver = typeNamesByResolver.get(resolver);
278
392
  if (byResolver) {
279
393
  const cached = byResolver.get(cacheKey);
@@ -285,7 +399,7 @@ function resolveOperationTypeNames(node, resolver, options = {}) {
285
399
  const { path, query, header } = getOperationParameters(node, { paramsCasing: options.paramsCasing });
286
400
  const responseStatusNames = options.responseStatusNames === "error" ? resolveErrorNames(node, resolver) : options.responseStatusNames === false ? [] : resolveStatusCodeNames(node, resolver);
287
401
  const exclude = new Set(options.exclude ?? []);
288
- const paramNames = [
402
+ const paramNames = options.includeParams === false ? [] : [
289
403
  ...path.map((param) => resolver.resolvePathParamsName(node, param)),
290
404
  ...query.map((param) => resolver.resolveQueryParamsName(node, param)),
291
405
  ...header.map((param) => resolver.resolveHeaderParamsName(node, param))
@@ -336,49 +450,31 @@ function createGroupConfig(group) {
336
450
  }
337
451
  //#endregion
338
452
  //#region src/components/Request.tsx
339
- const declarationPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
340
- function Request({ baseURL = "", name, dataReturnType, resolver, node, paramsType, pathParamsType, paramsCasing }) {
453
+ function Request({ baseURL = "", name, resolver, node }) {
341
454
  if (!_kubb_core.ast.isHttpOperationNode(node)) return null;
342
- const paramsNode = (0, _kubb_ast_utils.createOperationParams)(node, {
343
- paramsType,
344
- pathParamsType,
345
- paramsCasing,
346
- resolver,
347
- extraParams: [_kubb_core.ast.factory.createFunctionParameter({
348
- name: "options",
349
- type: "Partial<Cypress.RequestOptions>",
350
- default: "{}"
351
- })]
352
- });
353
- const paramsSignature = declarationPrinter.print(paramsNode) ?? "";
455
+ const { query: originalQueryParams, header: originalHeaderParams } = getOperationParameters(node, { paramsCasing: "original" });
456
+ const { query: casedQueryParams, header: casedHeaderParams } = getOperationParameters(node);
457
+ const queryParamsMapping = buildParamsMapping(originalQueryParams, casedQueryParams);
458
+ const headerParamsMapping = buildParamsMapping(originalHeaderParams, casedHeaderParams);
459
+ const { signature, groups } = buildRequestParamsSignature(node, resolver, { isConfigurable: false });
460
+ const paramsSignature = [signature, "options: Partial<Cypress.RequestOptions> = {}"].filter(Boolean).join(", ");
354
461
  const responseType = resolver.resolveResponseName(node);
355
- const returnType = dataReturnType === "data" ? `Cypress.Chainable<${responseType}>` : `Cypress.Chainable<Cypress.Response<${responseType}>>`;
356
- const casedPathParams = getOperationParameters(node, { paramsCasing }).path;
357
- const pathParamNameMap = new Map(casedPathParams.map((p) => [camelCase(p.name), p.name]));
358
- const urlTemplate = Url.toTemplateString(node.path, {
359
- prefix: baseURL,
360
- replacer: (param) => pathParamNameMap.get(camelCase(param)) ?? param,
361
- casing: paramsCasing
362
- });
462
+ const returnType = `Cypress.Chainable<${responseType}>`;
463
+ const urlTemplate = Url.toGroupedTemplateString(node.path, { prefix: baseURL });
363
464
  const requestOptions = [`method: '${node.method}'`, `url: ${urlTemplate}`];
364
- const queryParams = getOperationParameters(node).query;
365
- if (queryParams.length > 0) {
366
- const casedQueryParams = getOperationParameters(node, { paramsCasing }).query;
367
- if (casedQueryParams.some((p, i) => p.name !== queryParams[i].name)) {
368
- const pairs = queryParams.map((orig, i) => `${orig.name}: params.${casedQueryParams[i].name}`).join(", ");
369
- requestOptions.push(`qs: params ? { ${pairs} } : undefined`);
370
- } else requestOptions.push("qs: params");
371
- }
372
- const headerParams = getOperationParameters(node).header;
373
- if (headerParams.length > 0) {
374
- const casedHeaderParams = getOperationParameters(node, { paramsCasing }).header;
375
- if (casedHeaderParams.some((p, i) => p.name !== headerParams[i].name)) {
376
- const pairs = headerParams.map((orig, i) => `'${orig.name}': headers.${casedHeaderParams[i].name}`).join(", ");
377
- requestOptions.push(`headers: headers ? { ${pairs} } : undefined`);
378
- } else requestOptions.push("headers");
379
- }
380
- if (node.requestBody?.content?.[0]?.schema) requestOptions.push("body: data");
465
+ if (groups.query) if (queryParamsMapping) {
466
+ const pairs = Object.entries(queryParamsMapping).map(([originalName, camelCaseName]) => `${originalName}: query.${camelCaseName}`).join(", ");
467
+ requestOptions.push(`qs: query ? { ${pairs} } : undefined`);
468
+ } else requestOptions.push("qs: query");
469
+ if (groups.headers) if (headerParamsMapping) {
470
+ const pairs = Object.entries(headerParamsMapping).map(([originalName, camelCaseName]) => `'${originalName}': headers.${camelCaseName}`).join(", ");
471
+ requestOptions.push(`headers: headers ? { ${pairs} } : undefined`);
472
+ } else requestOptions.push("headers");
473
+ if (groups.body) requestOptions.push("body");
381
474
  requestOptions.push("...options");
475
+ const requestCall = `return cy.request<${responseType}>({
476
+ ${requestOptions.join(",\n ")}
477
+ }).then((res) => res.body)`;
382
478
  return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
383
479
  name,
384
480
  isIndexable: true,
@@ -388,11 +484,7 @@ function Request({ baseURL = "", name, dataReturnType, resolver, node, paramsTyp
388
484
  export: true,
389
485
  params: paramsSignature,
390
486
  returnType,
391
- children: dataReturnType === "data" ? `return cy.request<${responseType}>({
392
- ${requestOptions.join(",\n ")}
393
- }).then((res) => res.body)` : `return cy.request<${responseType}>({
394
- ${requestOptions.join(",\n ")}
395
- })`
487
+ children: requestCall
396
488
  })
397
489
  });
398
490
  }
@@ -409,11 +501,11 @@ const cypressGenerator = (0, _kubb_core.defineGenerator)({
409
501
  operation(node, ctx) {
410
502
  if (!_kubb_core.ast.isHttpOperationNode(node)) return null;
411
503
  const { config, resolver, driver, root } = ctx;
412
- const { output, baseURL, dataReturnType, paramsCasing, paramsType, pathParamsType, group } = ctx.options;
504
+ const { output, baseURL, group } = ctx.options;
413
505
  const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
414
506
  if (!pluginTs) return null;
415
507
  const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
416
- const importedTypeNames = resolveOperationTypeNames(node, tsResolver, { paramsCasing });
508
+ const importedTypeNames = [tsResolver.resolveRequestConfigName(node), ...resolveOperationTypeNames(node, tsResolver, { includeParams: false })];
417
509
  const meta = {
418
510
  name: resolver.resolveName(node.operationId),
419
511
  file: resolver.resolveFile({
@@ -466,10 +558,6 @@ const cypressGenerator = (0, _kubb_core.defineGenerator)({
466
558
  name: meta.name,
467
559
  node,
468
560
  resolver: tsResolver,
469
- dataReturnType,
470
- paramsCasing,
471
- paramsType,
472
- pathParamsType,
473
561
  baseURL
474
562
  })]
475
563
  });
@@ -480,7 +568,7 @@ const cypressGenerator = (0, _kubb_core.defineGenerator)({
480
568
  /**
481
569
  * Default resolver used by `@kubb/plugin-cypress`. Decides the names and file
482
570
  * paths for every generated `cy.request()` wrapper. Functions and files use
483
- * camelCase, matching the convention from `@kubb/plugin-client`.
571
+ * camelCase, matching the convention from `@kubb/plugin-axios` and `@kubb/plugin-fetch`.
484
572
  *
485
573
  * @example Resolve a helper name
486
574
  * ```ts
@@ -536,7 +624,7 @@ const pluginCypress = (0, _kubb_core.definePlugin)((options) => {
536
624
  const { output = {
537
625
  path: "cypress",
538
626
  barrel: { type: "named" }
539
- }, group, exclude = [], include, override = [], dataReturnType = "data", baseURL, paramsCasing, paramsType = "inline", pathParamsType = paramsType === "object" ? "object" : options.pathParamsType || "inline", resolver: userResolver, macros: userMacros, generators: userGenerators = [] } = options;
627
+ }, group, exclude = [], include, override = [], baseURL, resolver: userResolver, macros: userMacros } = options;
540
628
  const groupConfig = createGroupConfig(group);
541
629
  return {
542
630
  name: pluginCypressName,
@@ -552,18 +640,13 @@ const pluginCypress = (0, _kubb_core.definePlugin)((options) => {
552
640
  exclude,
553
641
  include,
554
642
  override,
555
- dataReturnType,
556
643
  group: groupConfig,
557
644
  baseURL,
558
- paramsCasing,
559
- paramsType,
560
- pathParamsType,
561
645
  resolver
562
646
  });
563
647
  ctx.setResolver(resolver);
564
648
  if (userMacros?.length) ctx.setMacros(userMacros);
565
649
  ctx.addGenerator(cypressGenerator);
566
- for (const gen of userGenerators) ctx.addGenerator(gen);
567
650
  } }
568
651
  };
569
652
  });
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["ast","File","Function","jsxRenderer","ast","pluginTsName","File","pluginTsName"],"sources":["../../../internals/utils/src/casing.ts","../../../internals/utils/src/fs.ts","../../../internals/utils/src/reserved.ts","../../../internals/utils/src/url.ts","../../../internals/shared/src/operation.ts","../../../internals/shared/src/group.ts","../src/components/Request.tsx","../src/generators/cypressGenerator.tsx","../src/resolvers/resolverCypress.ts","../src/plugin.ts"],"sourcesContent":["type Options = {\n /**\n * Text prepended before casing is applied.\n */\n prefix?: string\n /**\n * Text appended before casing is applied.\n */\n suffix?: string\n}\n\n/**\n * Shared implementation for camelCase and PascalCase conversion.\n * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)\n * and capitalizes each word according to `pascal`.\n *\n * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.\n */\nfunction toCamelOrPascal(text: string, pascal: boolean): string {\n return text\n .trim()\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .replace(/(\\d)([a-z])/g, '$1 $2')\n .split(/[\\s\\-_./\\\\:]+/)\n .filter(Boolean)\n .map((word, i) => {\n if (word.length > 1 && word === word.toUpperCase()) return word\n const head = i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()\n return head + word.slice(1)\n })\n .join('')\n .replace(/[^a-zA-Z0-9]/g, '')\n}\n\n/**\n * Converts `text` to camelCase.\n *\n * @example Word boundaries\n * `camelCase('hello-world') // 'helloWorld'`\n *\n * @example With a prefix\n * `camelCase('tag', { prefix: 'create' }) // 'createTag'`\n */\nexport function camelCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false)\n}\n\n/**\n * Converts `text` to PascalCase.\n *\n * @example Word boundaries\n * `pascalCase('hello-world') // 'HelloWorld'`\n *\n * @example With a suffix\n * `pascalCase('tag', { suffix: 'schema' }) // 'TagSchema'`\n */\nexport function pascalCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true)\n}\n\n/**\n * Converts `text` to snake_case.\n *\n * @example From camelCase\n * `snakeCase('helloWorld') // 'hello_world'`\n *\n * @example From mixed separators\n * `snakeCase('Hello-World') // 'hello_world'`\n */\nexport function snakeCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n const processed = `${prefix} ${text} ${suffix}`.trim()\n return processed\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[\\s\\-.]+/g, '_')\n .replace(/[^a-zA-Z0-9_]/g, '')\n .toLowerCase()\n .split('_')\n .filter(Boolean)\n .join('_')\n}\n\n/**\n * Converts `text` to SCREAMING_SNAKE_CASE.\n *\n * @example From camelCase\n * `screamingSnakeCase('helloWorld') // 'HELLO_WORLD'`\n */\nexport function screamingSnakeCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return snakeCase(text, { prefix, suffix }).toUpperCase()\n}\n","import { posix } from 'node:path'\nimport { camelCase } from './casing.ts'\n\nfunction toSlash(p: string): string {\n if (p.startsWith('\\\\\\\\?\\\\')) return p\n return p.replaceAll('\\\\', '/')\n}\n\n/**\n * Returns the relative path from `rootDir` to `filePath`, always using forward slashes\n * and prefixed with `./` when not already traversing upward.\n *\n * @example\n * ```ts\n * getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'\n * getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'\n * ```\n */\nexport function getRelativePath(rootDir?: string | null, filePath?: string | null): string {\n if (!rootDir || !filePath) {\n throw new Error(`Root and file should be filled in when retrieving the relativePath, ${rootDir || ''} ${filePath || ''}`)\n }\n\n const relativePath = posix.relative(toSlash(rootDir), toSlash(filePath))\n\n return relativePath.startsWith('../') ? relativePath : `./${relativePath}`\n}\n\n/**\n * Builds a nested file path from a dotted name. Splits on dots that precede a letter\n * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases\n * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.\n *\n * Empty segments are dropped before joining. They arise when the name starts with a dot\n * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to\n * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an\n * absolute path, letting generated files escape the configured output directory.\n *\n * @example Nested path from a dotted name\n * `toFilePath('pet.petId') // 'pet/petId'`\n *\n * @example PascalCase the final segment\n * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`\n *\n * @example Suffix applied to the final segment only\n * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`\n */\nexport function toFilePath(name: string, caseLast: (part: string) => string = camelCase): string {\n const parts = name.split(/\\.(?=[a-zA-Z])/)\n return parts\n .map((part, i) => (i === parts.length - 1 ? caseLast(part) : camelCase(part)))\n .filter(Boolean)\n .join('/')\n}\n","/**\n * JavaScript and Java reserved words.\n * @link https://github.com/jonschlinkert/reserved/blob/master/index.js\n */\nconst reservedWords = new Set([\n 'abstract',\n 'arguments',\n 'boolean',\n 'break',\n 'byte',\n 'case',\n 'catch',\n 'char',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'double',\n 'else',\n 'enum',\n 'eval',\n 'export',\n 'extends',\n 'false',\n 'final',\n 'finally',\n 'float',\n 'for',\n 'function',\n 'goto',\n 'if',\n 'implements',\n 'import',\n 'in',\n 'instanceof',\n 'int',\n 'interface',\n 'let',\n 'long',\n 'native',\n 'new',\n 'null',\n 'package',\n 'private',\n 'protected',\n 'public',\n 'return',\n 'short',\n 'static',\n 'super',\n 'switch',\n 'synchronized',\n 'this',\n 'throw',\n 'throws',\n 'transient',\n 'true',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'volatile',\n 'while',\n 'with',\n 'yield',\n 'Array',\n 'Date',\n 'hasOwnProperty',\n 'Infinity',\n 'isFinite',\n 'isNaN',\n 'isPrototypeOf',\n 'length',\n 'Math',\n 'name',\n 'NaN',\n 'Number',\n 'Object',\n 'prototype',\n 'String',\n 'toString',\n 'undefined',\n 'valueOf',\n] as const)\n\n/**\n * Returns `true` when `name` is a syntactically valid JavaScript variable name.\n *\n * @example\n * ```ts\n * isValidVarName('status') // true\n * isValidVarName('class') // false (reserved word)\n * isValidVarName('42foo') // false (starts with digit)\n * ```\n */\nexport function isValidVarName(name: string): boolean {\n if (!name || reservedWords.has(name as 'valueOf')) {\n return false\n }\n return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)\n}\n\n/**\n * Returns `name` when it's a syntactically valid JavaScript variable name,\n * otherwise prefixes it with `_` so the result is a valid identifier.\n *\n * Useful for sanitizing OpenAPI schema names or operation IDs that start with\n * a digit (e.g. `409`, `504AccountCancel`) before using them as exported\n * variable, type, or function names.\n *\n * @example\n * ```ts\n * ensureValidVarName('409') // '_409'\n * ensureValidVarName('504AccountCancel') // '_504AccountCancel'\n * ensureValidVarName('Pet') // 'Pet'\n * ensureValidVarName('class') // '_class'\n * ```\n */\nexport function ensureValidVarName(name: string): string {\n if (!name || isValidVarName(name)) {\n return name\n }\n return `_${name}`\n}\n","import { camelCase } from './casing.ts'\nimport { isValidVarName } from './reserved.ts'\n\nexport type URLObject = {\n /**\n * The resolved URL string (Express-style or template literal, depending on context).\n */\n url: string\n /**\n * Extracted path parameters as a key-value map, or `null` when the path has none.\n */\n params: Record<string, string> | null\n}\n\n/**\n * Supported identifier casing strategies for path parameters.\n */\nexport type PathCasing = 'camelcase'\n\ntype TemplateOptions = {\n /**\n * Literal text prepended inside the template literal, e.g. a base URL.\n */\n prefix?: string | null\n /**\n * Transform applied to each extracted parameter name before interpolation.\n */\n replacer?: (pathParam: string) => string\n /**\n * Casing strategy applied to path parameter names.\n */\n casing?: PathCasing\n}\n\ntype ObjectOptions = {\n /**\n * Controls whether the `url` is rendered as an Express path or a template literal.\n * @default 'path'\n */\n type?: 'path' | 'template'\n /**\n * Transform applied to each extracted parameter name.\n */\n replacer?: (pathParam: string) => string\n /**\n * When `true`, the result is serialized to a string expression instead of a plain object.\n */\n stringify?: boolean\n /**\n * Casing strategy applied to path parameter names.\n */\n casing?: PathCasing\n}\n\nfunction transformParam(raw: string, casing?: PathCasing): string {\n const param = isValidVarName(raw) ? raw : camelCase(raw)\n return casing === 'camelcase' ? camelCase(param) : param\n}\n\nfunction toParamsObject(\n path: string,\n { replacer, casing }: { replacer?: (pathParam: string) => string; casing?: PathCasing } = {},\n): Record<string, string> | null {\n const params: Record<string, string> = {}\n\n for (const match of path.matchAll(/\\{([^}]+)\\}/g)) {\n const param = transformParam(match[1]!, casing)\n const key = replacer ? replacer(param) : param\n params[key] = key\n }\n\n return Object.keys(params).length > 0 ? params : null\n}\n\n/**\n * Helpers for OpenAPI/Swagger paths, plus a thin wrapper over the native `URL`.\n */\nexport class Url {\n /**\n * Reports whether `url` is a parseable absolute URL. Delegates to the native `URL.canParse`.\n *\n * @example\n * Url.canParse('https://petstore.swagger.io/v2') // true\n * Url.canParse('/pet/{petId}') // false\n */\n static canParse(url: string, base?: string | URL): boolean {\n return URL.canParse(url, base)\n }\n\n /**\n * Converts an OpenAPI/Swagger path to Express-style colon syntax.\n *\n * @example\n * Url.toPath('/pet/{petId}') // '/pet/:petId'\n */\n static toPath(path: string): string {\n return path.replace(/\\{([^}]+)\\}/g, ':$1')\n }\n\n /**\n * Converts an OpenAPI/Swagger path to a TypeScript template literal string.\n * `prefix` is prepended inside the literal, `replacer` transforms each parameter name,\n * and `casing` controls parameter identifier casing.\n *\n * @example\n * Url.toTemplateString('/pet/{petId}') // '`/pet/${petId}`'\n *\n * @example\n * Url.toTemplateString('/pet/{petId}', { prefix: 'https://api' }) // '`https://api/pet/${petId}`'\n */\n static toTemplateString(path: string, { prefix, replacer, casing }: TemplateOptions = {}): string {\n const parts = path.split(/\\{([^}]+)\\}/)\n const result = parts\n .map((part, i) => {\n if (i % 2 === 0) return part\n const param = transformParam(part, casing)\n return `\\${${replacer ? replacer(param) : param}}`\n })\n .join('')\n\n return `\\`${prefix ?? ''}${result}\\``\n }\n\n /**\n * Returns the path and its extracted params as a structured `URLObject`, or as a stringified\n * expression when `stringify` is set.\n *\n * @example\n * Url.toObject('/pet/{petId}')\n * // { url: '/pet/:petId', params: { petId: 'petId' } }\n */\n static toObject(path: string, { type = 'path', replacer, stringify, casing }: ObjectOptions = {}): URLObject | string {\n const object: URLObject = {\n url: type === 'path' ? Url.toPath(path) : Url.toTemplateString(path, { replacer, casing }),\n params: toParamsObject(path, { replacer, casing }),\n }\n\n if (stringify) {\n if (type === 'template') {\n return JSON.stringify(object).replaceAll(\"'\", '').replaceAll(`\"`, '')\n }\n\n if (object.params) {\n return `{ url: '${object.url}', params: ${JSON.stringify(object.params).replaceAll(\"'\", '').replaceAll(`\"`, '')} }`\n }\n\n return `{ url: '${object.url}' }`\n }\n\n return object\n }\n}\n","import { Url } from '@internals/utils'\nimport { ast, type ResolverFileParams } from '@kubb/core'\nimport { caseParams } from '@kubb/ast/utils'\n\n/**\n * Builds the `ResolverFileParams` every operation generator passes to\n * `resolver.resolveFile`: a file named `name`, tagged by the operation's first\n * tag (or `'default'`), at the operation's path. Centralizes the entry object\n * that was repeated at dozens of call sites across the client and query plugins.\n *\n * @example\n * ```ts\n * resolver.resolveFile(operationFileEntry(node, node.operationId), { root, output, group })\n * ```\n */\nexport function operationFileEntry(node: ast.OperationNode, name: string, extname: ResolverFileParams['extname'] = '.ts'): ResolverFileParams {\n return {\n name,\n extname,\n tag: node.tags[0] ?? 'default',\n path: node.path,\n }\n}\n\nexport type ContentTypeInfo = {\n contentTypes: string[]\n isMultipleContentTypes: boolean\n contentTypeUnion: string\n defaultContentType: string\n hasFormData: boolean\n}\n\nexport type RequestConfigResolver = {\n resolveDataName(node: ast.OperationNode): string\n}\n\nexport type ResponseStatusNameResolver = {\n resolveResponseStatusName(node: ast.OperationNode, statusCode: ast.StatusCode): string\n}\n\nexport type ResponseNameResolver = ResponseStatusNameResolver & {\n resolveResponseName(node: ast.OperationNode): string\n}\n\nexport type OperationTypeNameResolver = RequestConfigResolver &\n ResponseNameResolver & {\n resolvePathParamsName(node: ast.OperationNode, param: ast.ParameterNode): string\n resolveQueryParamsName(node: ast.OperationNode, param: ast.ParameterNode): string\n resolveHeaderParamsName(node: ast.OperationNode, param: ast.ParameterNode): string\n }\n\nexport type OperationCommentLink = 'pathTemplate' | 'urlPath' | false | ((node: ast.OperationNode) => string | undefined)\n\nexport type BuildOperationCommentsOptions = {\n link?: OperationCommentLink\n linkPosition?: 'beforeDeprecated' | 'afterDeprecated'\n splitLines?: boolean\n}\n\ntype ResponseLike = {\n statusCode: ast.StatusCode | number | string\n}\n\nexport type OperationParameterGroups = Record<ast.ParameterNode['in'], Array<ast.ParameterNode>>\n\nexport type ResolveOperationTypeNameOptions = {\n paramsCasing?: 'camelcase'\n responseStatusNames?: boolean | 'error'\n exclude?: ReadonlyArray<string | undefined>\n order?: 'params-first' | 'body-response-first'\n}\n\nfunction getOperationLink(node: ast.OperationNode, link: OperationCommentLink): string | null {\n if (!link) {\n return null\n }\n\n if (typeof link === 'function') {\n return link(node) ?? null\n }\n\n if (link === 'urlPath') {\n return node.path ? `{@link ${Url.toPath(node.path)}}` : null\n }\n\n return node.path ? `{@link ${node.path.replaceAll('{', ':').replaceAll('}', '')}}` : null\n}\n\nexport function getContentTypeInfo(node: ast.OperationNode): ContentTypeInfo {\n const contentTypes = node.requestBody?.content?.map((e) => e.contentType) ?? []\n const isMultipleContentTypes = contentTypes.length > 1\n\n return {\n contentTypes,\n isMultipleContentTypes,\n contentTypeUnion: isMultipleContentTypes ? contentTypes.map((ct) => JSON.stringify(ct)).join(' | ') : '',\n defaultContentType: contentTypes[0] ?? 'application/json',\n hasFormData: contentTypes.some((ct) => ct === 'multipart/form-data'),\n }\n}\n\nexport type ResponseType = 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'\n\n/**\n * Derives the default `responseType` for an operation from its primary success response.\n *\n * Returns a value only when that response declares a single non-JSON content type — a binary type\n * (`application/octet-stream`, `application/pdf`, `image/*`, `audio/*`, `video/*`) maps to `'blob'`\n * and other `text/*` maps to `'text'`. Otherwise `undefined`, leaving the runtime client's\n * `Content-Type` auto-detection in charge.\n */\nexport function getResponseType(node: ast.OperationNode): ResponseType | undefined {\n const contentTypes = getPrimarySuccessResponse(node)?.content?.map((entry) => entry.contentType) ?? []\n if (contentTypes.length !== 1) return undefined\n\n const baseType = contentTypes[0]!.split(';')[0]!.trim().toLowerCase()\n if (baseType === 'application/json' || baseType.endsWith('+json') || baseType === 'text/json') return undefined\n if (baseType.startsWith('text/')) return 'text'\n if (baseType === 'application/octet-stream' || baseType === 'application/pdf' || /^(image|audio|video)\\//.test(baseType)) return 'blob'\n return undefined\n}\n\n/**\n * Maps a content type to the PascalCase suffix used to name per-content-type variants\n * (e.g. `application/json` → `Json`, `application/xml` → `Xml`, `multipart/form-data` → `FormData`).\n */\nexport function getContentTypeSuffix(contentType: string): string {\n const baseType = contentType.split(';')[0]!.trim()\n if (baseType === 'application/json') return 'Json'\n if (baseType === 'multipart/form-data') return 'FormData'\n if (baseType === 'application/x-www-form-urlencoded') return 'FormUrlEncoded'\n const subtype = baseType.split('/').pop() ?? baseType\n const parts = subtype.split(/[^a-zA-Z0-9]+/).filter(Boolean)\n if (parts.length === 0) return 'Unknown'\n return parts.map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join('')\n}\n\n/**\n * Appends a content-type suffix to a base name, keeping a trailing `Data` segment last\n * (e.g. `AddPetData` + `Json` → `AddPetJsonData`, `AddPetStatus200` + `Xml` → `AddPetStatus200Xml`).\n */\nexport function getPerContentTypeName(baseName: string, suffix: string): string {\n if (baseName.endsWith('Data')) {\n return suffix.endsWith('Data') ? baseName.slice(0, -4) + suffix : `${baseName.slice(0, -4)}${suffix}Data`\n }\n return baseName + suffix\n}\n\nexport type ContentVariantInput = { contentType: string; schema?: ast.SchemaNode | null; keysToOmit?: Array<string> | null }\nexport type ContentVariant = { name: string; suffix: string; schema: ast.SchemaNode; keysToOmit?: Array<string> | null; contentType: string }\n\n/**\n * Resolves per-content-type variant names for a set of content entries, deduplicating suffix\n * collisions with a numeric counter. Entries without a schema are skipped. The returned `suffix` is\n * the final (possibly counter-augmented) value, so callers can derive parallel names in another\n * namespace (e.g. plugin-faker deriving the matching plugin-ts type name).\n */\nexport function resolveContentTypeVariants(entries: Array<ContentVariantInput>, baseName: string): Array<ContentVariant> {\n const usedNames = new Set<string>()\n return entries\n .filter((entry) => entry.schema)\n .map((entry) => {\n const baseSuffix = getContentTypeSuffix(entry.contentType)\n let suffix = baseSuffix\n let name = getPerContentTypeName(baseName, suffix)\n let counter = 2\n while (usedNames.has(name)) {\n suffix = `${baseSuffix}${counter++}`\n name = getPerContentTypeName(baseName, suffix)\n }\n usedNames.add(name)\n return { name, suffix, schema: entry.schema!, keysToOmit: entry.keysToOmit, contentType: entry.contentType }\n })\n}\n\nexport function buildRequestConfigType(node: ast.OperationNode, resolver: RequestConfigResolver): string {\n const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null\n const { isMultipleContentTypes, contentTypeUnion } = getContentTypeInfo(node)\n const configType = requestName ? `Partial<RequestConfig<${requestName}>>` : 'Partial<RequestConfig>'\n const configProps = ['client?: Client', isMultipleContentTypes ? `contentType?: ${contentTypeUnion}` : null].filter(Boolean).join('; ')\n\n return `${configType} & { ${configProps} }`\n}\n\nexport function buildOperationComments(node: ast.OperationNode, options: BuildOperationCommentsOptions = {}): Array<string> {\n const { link = 'pathTemplate', linkPosition = 'afterDeprecated', splitLines = false } = options\n const linkComment = getOperationLink(node, link)\n const comments =\n linkPosition === 'beforeDeprecated'\n ? [node.description && `@description ${node.description}`, node.summary && `@summary ${node.summary}`, linkComment, node.deprecated && '@deprecated']\n : [node.description && `@description ${node.description}`, node.summary && `@summary ${node.summary}`, node.deprecated && '@deprecated', linkComment]\n\n const filteredComments = comments.filter((comment): comment is string => Boolean(comment))\n\n if (!splitLines) {\n return filteredComments\n }\n\n return filteredComments.flatMap((text) => text.split(/\\r?\\n/).map((line) => line.trim())).filter((comment): comment is string => Boolean(comment))\n}\n\nexport function getOperationParameters(node: ast.OperationNode, options: { paramsCasing?: 'camelcase' } = {}): OperationParameterGroups {\n const params = caseParams(node.parameters, options.paramsCasing)\n\n return {\n path: params.filter((param) => param.in === 'path'),\n query: params.filter((param) => param.in === 'query'),\n header: params.filter((param) => param.in === 'header'),\n cookie: params.filter((param) => param.in === 'cookie'),\n }\n}\n\nexport function getStatusCodeNumber(statusCode: ast.StatusCode | number | string): number | null {\n const code = Number(statusCode)\n\n return Number.isNaN(code) ? null : code\n}\n\nexport function isSuccessStatusCode(statusCode: ast.StatusCode | number | string): boolean {\n const code = getStatusCodeNumber(statusCode)\n\n return code !== null && code >= 200 && code < 300\n}\n\nexport function isErrorStatusCode(statusCode: ast.StatusCode | number | string): boolean {\n const code = getStatusCodeNumber(statusCode)\n\n return code !== null && code >= 400\n}\n\nexport function getSuccessResponses<TResponse extends ResponseLike>(responses: ReadonlyArray<TResponse>): Array<TResponse> {\n return responses.filter((response) => isSuccessStatusCode(response.statusCode))\n}\n\nexport function getOperationSuccessResponses(node: ast.OperationNode): Array<ast.ResponseNode> {\n return getSuccessResponses(node.responses)\n}\n\nexport function getPrimarySuccessResponse(node: ast.OperationNode): ast.ResponseNode | null {\n return getOperationSuccessResponses(node)[0] ?? null\n}\n\nexport function resolveErrorNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses\n .filter((response) => isErrorStatusCode(response.statusCode))\n .map((response) => resolver.resolveResponseStatusName(node, response.statusCode))\n}\n\nexport function resolveSuccessNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses\n .filter((response) => isSuccessStatusCode(response.statusCode))\n .map((response) => resolver.resolveResponseStatusName(node, response.statusCode))\n}\n\nexport function resolveStatusCodeNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses.map((response) => resolver.resolveResponseStatusName(node, response.statusCode))\n}\n\n/**\n * Builds the discriminated union type string for `dataReturnType: 'full'` return shapes.\n * Each member is `{ status: N; data: StatusNType; statusText: string }`.\n */\nexport function buildStatusUnionType(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string {\n const members = node.responses.map((r) => {\n const typeName = resolver.resolveResponseStatusName(node, r.statusCode)\n const statusCode = Number.parseInt(r.statusCode, 10)\n const statusLiteral = Number.isNaN(statusCode) ? 'number' : String(statusCode)\n return `{ status: ${statusLiteral}; data: ${typeName}; statusText: string }`\n })\n if (members.length === 1) return members[0]!\n return `(${members.join(' | ')})`\n}\n\nconst typeNamesByResolver = new WeakMap<OperationTypeNameResolver, Map<string, string[]>>()\n\nexport function resolveOperationTypeNames(\n node: ast.OperationNode,\n resolver: OperationTypeNameResolver,\n options: ResolveOperationTypeNameOptions = {},\n): string[] {\n const cacheKey = `${node.operationId}\\0${options.paramsCasing ?? ''}\\0${options.order ?? ''}\\0${options.responseStatusNames ?? ''}\\0${(options.exclude ?? []).join(',')}`\n let byResolver = typeNamesByResolver.get(resolver)\n if (byResolver) {\n const cached = byResolver.get(cacheKey)\n if (cached) return cached\n } else {\n byResolver = new Map()\n typeNamesByResolver.set(resolver, byResolver)\n }\n\n const { path, query, header } = getOperationParameters(node, { paramsCasing: options.paramsCasing })\n const responseStatusNames =\n options.responseStatusNames === 'error'\n ? resolveErrorNames(node, resolver)\n : options.responseStatusNames === false\n ? []\n : resolveStatusCodeNames(node, resolver)\n const exclude = new Set(options.exclude ?? [])\n const paramNames = [\n ...path.map((param) => resolver.resolvePathParamsName(node, param)),\n ...query.map((param) => resolver.resolveQueryParamsName(node, param)),\n ...header.map((param) => resolver.resolveHeaderParamsName(node, param)),\n ]\n const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null, resolver.resolveResponseName(node)]\n const names =\n options.order === 'body-response-first'\n ? [...bodyAndResponseNames, ...paramNames, ...responseStatusNames]\n : [...paramNames, ...bodyAndResponseNames, ...responseStatusNames]\n\n const result = names.filter((name): name is string => Boolean(name) && !exclude.has(name as string))\n byResolver.set(cacheKey, result)\n return result\n}\n\nexport function resolveResponseTypes(node: ast.OperationNode, resolver: ResponseNameResolver): Array<[statusCode: number | 'default', typeName: string]> {\n const types: Array<[number | 'default', string]> = []\n\n for (const response of node.responses) {\n if (response.statusCode === 'default') {\n types.push(['default', resolver.resolveResponseName(node)])\n continue\n }\n\n const code = getStatusCodeNumber(response.statusCode)\n if (code === null) {\n continue\n }\n\n types.push([code, isSuccessStatusCode(code) ? resolver.resolveResponseName(node) : resolver.resolveResponseStatusName(node, response.statusCode)])\n }\n\n return types\n}\n\nexport function findSuccessStatusCode(responses: Array<{ statusCode: ast.StatusCode | number | string }>): ast.StatusCode | null {\n for (const response of responses) {\n if (isSuccessStatusCode(response.statusCode)) {\n return response.statusCode as ast.StatusCode\n }\n }\n\n return null\n}\n","import { camelCase } from '@internals/utils'\nimport type { Group } from '@kubb/core'\n\n/**\n * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the\n * shared default naming so every plugin groups output consistently:\n *\n * - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).\n * - other groups use the camelCased group (`pet store` → `petStore`).\n *\n * A user-provided `group.name` always wins over the default namer, so callers stay in\n * control of their output folders. Returns `null` when grouping is disabled, matching the\n * per-plugin convention.\n *\n * @param group - The user-supplied group option, or `undefined` to disable grouping.\n *\n * @example\n * ```ts\n * createGroupConfig(group) // shared across every plugin\n * ```\n */\nexport function createGroupConfig(group: Group | undefined): Group | null {\n if (!group) {\n return null\n }\n\n const defaultName = (ctx: { group: string }): string => {\n if (group.type === 'path') {\n return `${ctx.group.split('/')[1]}`\n }\n\n return camelCase(ctx.group)\n }\n\n return {\n ...group,\n name: group.name ? group.name : defaultName,\n } satisfies Group\n}\n","import { getOperationParameters } from '@internals/shared'\nimport { camelCase, Url } from '@internals/utils'\nimport { createOperationParams } from '@kubb/ast/utils'\nimport { ast } from '@kubb/core'\nimport type { ResolverTs } from '@kubb/plugin-ts'\nimport { functionPrinter } from '@kubb/plugin-ts'\nimport { File, Function } from '@kubb/renderer-jsx'\nimport type { KubbReactNode } from '@kubb/renderer-jsx/types'\nimport type { PluginCypress } from '../types.ts'\n\ntype Props = {\n /**\n * Name of the function\n */\n name: string\n /**\n * AST operation node\n */\n node: ast.OperationNode\n /**\n * TypeScript resolver for resolving param/data/response type names\n */\n resolver: ResolverTs\n baseURL: string | null | undefined\n dataReturnType: PluginCypress['resolvedOptions']['dataReturnType']\n paramsCasing: PluginCypress['resolvedOptions']['paramsCasing']\n paramsType: PluginCypress['resolvedOptions']['paramsType']\n pathParamsType: PluginCypress['resolvedOptions']['pathParamsType']\n}\n\nconst declarationPrinter = functionPrinter({ mode: 'declaration' })\n\nexport function Request({ baseURL = '', name, dataReturnType, resolver, node, paramsType, pathParamsType, paramsCasing }: Props): KubbReactNode {\n if (!ast.isHttpOperationNode(node)) return null\n const paramsNode = createOperationParams(node, {\n paramsType,\n pathParamsType,\n paramsCasing,\n resolver,\n extraParams: [\n ast.factory.createFunctionParameter({\n name: 'options',\n type: 'Partial<Cypress.RequestOptions>',\n default: '{}',\n }),\n ],\n })\n const paramsSignature = declarationPrinter.print(paramsNode) ?? ''\n\n const responseType = resolver.resolveResponseName(node)\n const returnType = dataReturnType === 'data' ? `Cypress.Chainable<${responseType}>` : `Cypress.Chainable<Cypress.Response<${responseType}>>`\n\n const casedPathParams = getOperationParameters(node, { paramsCasing }).path\n // Build a lookup keyed by camelCase-normalized name so that path-template names\n // (e.g. `{pet_id}`) correctly resolve to the function-parameter name (`petId`)\n // even when the OpenAPI spec has inconsistent casing between the two.\n const pathParamNameMap = new Map(casedPathParams.map((p) => [camelCase(p.name), p.name]))\n\n const urlTemplate = Url.toTemplateString(node.path, {\n prefix: baseURL,\n replacer: (param) => pathParamNameMap.get(camelCase(param)) ?? param,\n casing: paramsCasing,\n })\n\n const requestOptions: Array<string> = [`method: '${node.method}'`, `url: ${urlTemplate}`]\n\n const queryParams = getOperationParameters(node).query\n if (queryParams.length > 0) {\n const casedQueryParams = getOperationParameters(node, { paramsCasing }).query\n // When paramsCasing renames query params (e.g. page_size → pageSize), we must remap\n // the camelCase keys back to the original API names before passing them to `qs`.\n const needsQsTransform = casedQueryParams.some((p, i) => p.name !== queryParams[i]!.name)\n if (needsQsTransform) {\n const pairs = queryParams.map((orig, i) => `${orig.name}: params.${casedQueryParams[i]!.name}`).join(', ')\n requestOptions.push(`qs: params ? { ${pairs} } : undefined`)\n } else {\n requestOptions.push('qs: params')\n }\n }\n\n const headerParams = getOperationParameters(node).header\n if (headerParams.length > 0) {\n const casedHeaderParams = getOperationParameters(node, { paramsCasing }).header\n // When paramsCasing renames header params (e.g. x-api-key → xApiKey), we must remap\n // the camelCase keys back to the original API names before passing them to `headers`.\n const needsHeaderTransform = casedHeaderParams.some((p, i) => p.name !== headerParams[i]!.name)\n if (needsHeaderTransform) {\n const pairs = headerParams.map((orig, i) => `'${orig.name}': headers.${casedHeaderParams[i]!.name}`).join(', ')\n requestOptions.push(`headers: headers ? { ${pairs} } : undefined`)\n } else {\n requestOptions.push('headers')\n }\n }\n\n if (node.requestBody?.content?.[0]?.schema) {\n requestOptions.push('body: data')\n }\n\n requestOptions.push('...options')\n\n return (\n <File.Source name={name} isIndexable isExportable>\n <Function name={name} export params={paramsSignature} returnType={returnType}>\n {dataReturnType === 'data'\n ? `return cy.request<${responseType}>({\n ${requestOptions.join(',\\n ')}\n}).then((res) => res.body)`\n : `return cy.request<${responseType}>({\n ${requestOptions.join(',\\n ')}\n})`}\n </Function>\n </File.Source>\n )\n}\n","import { resolveOperationTypeNames } from '@internals/shared'\nimport { ast, defineGenerator } from '@kubb/core'\nimport { pluginTsName } from '@kubb/plugin-ts'\nimport { File, jsxRenderer } from '@kubb/renderer-jsx'\nimport { Request } from '../components/Request.tsx'\nimport type { PluginCypress } from '../types.ts'\n\n/**\n * Built-in generator for `@kubb/plugin-cypress`. Emits one typed\n * `cy.request()` wrapper per OpenAPI operation, ready to call inside Cypress\n * test specs and custom commands.\n */\nexport const cypressGenerator = defineGenerator<PluginCypress>({\n name: 'cypress',\n renderer: jsxRenderer,\n operation(node, ctx) {\n if (!ast.isHttpOperationNode(node)) return null\n const { config, resolver, driver, root } = ctx\n const { output, baseURL, dataReturnType, paramsCasing, paramsType, pathParamsType, group } = ctx.options\n\n const pluginTs = driver.getPlugin(pluginTsName)\n\n if (!pluginTs) {\n return null\n }\n\n const tsResolver = driver.getResolver(pluginTsName)\n\n const importedTypeNames = resolveOperationTypeNames(node, tsResolver, { paramsCasing })\n\n const meta = {\n name: resolver.resolveName(node.operationId),\n file: resolver.resolveFile(\n { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },\n { root, output, group: group ?? undefined },\n ),\n fileTs: tsResolver.resolveFile(\n { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },\n {\n root,\n output: pluginTs.options?.output ?? output,\n group: pluginTs.options?.group ?? undefined,\n },\n ),\n } as const\n\n return (\n <File\n baseName={meta.file.baseName}\n path={meta.file.path}\n meta={meta.file.meta}\n banner={resolver.resolveBanner(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}\n footer={resolver.resolveFooter(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}\n >\n {meta.fileTs && importedTypeNames.length > 0 && <File.Import name={importedTypeNames} root={meta.file.path} path={meta.fileTs.path} isTypeOnly />}\n <Request\n name={meta.name}\n node={node}\n resolver={tsResolver}\n dataReturnType={dataReturnType}\n paramsCasing={paramsCasing}\n paramsType={paramsType}\n pathParamsType={pathParamsType}\n baseURL={baseURL}\n />\n </File>\n )\n },\n})\n","import { camelCase, toFilePath } from '@internals/utils'\nimport { defineResolver } from '@kubb/core'\nimport type { PluginCypress } from '../types.ts'\n\n/**\n * Default resolver used by `@kubb/plugin-cypress`. Decides the names and file\n * paths for every generated `cy.request()` wrapper. Functions and files use\n * camelCase, matching the convention from `@kubb/plugin-client`.\n *\n * @example Resolve a helper name\n * ```ts\n * import { resolverCypress } from '@kubb/plugin-cypress'\n *\n * resolverCypress.default('list pets', 'function') // 'listPets'\n * ```\n */\nexport const resolverCypress = defineResolver<PluginCypress>(() => ({\n name: 'default',\n pluginName: 'plugin-cypress',\n default(name, type) {\n return type === 'file' ? toFilePath(name) : camelCase(name)\n },\n resolveName(name) {\n return this.default(name, 'function')\n },\n resolvePathName(name, type) {\n return this.default(name, type)\n },\n}))\n","import { createGroupConfig } from '@internals/shared'\nimport { definePlugin } from '@kubb/core'\nimport { pluginTsName } from '@kubb/plugin-ts'\nimport { cypressGenerator } from './generators/cypressGenerator.tsx'\nimport { resolverCypress } from './resolvers/resolverCypress.ts'\nimport type { PluginCypress } from './types.ts'\n\n/**\n * Canonical plugin name for `@kubb/plugin-cypress`. Used for driver lookups and\n * cross-plugin dependency references.\n */\nexport const pluginCypressName = 'plugin-cypress' satisfies PluginCypress['name']\n\n/**\n * Generates one typed `cy.request()` wrapper per OpenAPI operation. Each helper\n * has typed path params, body, query, and a typed response, so failing API\n * calls in Cypress show up at compile time instead of inside the test runner.\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb'\n * import { pluginTs } from '@kubb/plugin-ts'\n * import { pluginCypress } from '@kubb/plugin-cypress'\n *\n * export default defineConfig({\n * input: { path: './petStore.yaml' },\n * output: { path: './src/gen' },\n * plugins: [\n * pluginTs(),\n * pluginCypress({\n * output: { path: './cypress' },\n * }),\n * ],\n * })\n * ```\n */\nexport const pluginCypress = definePlugin<PluginCypress>((options) => {\n const {\n output = { path: 'cypress', barrel: { type: 'named' } },\n group,\n exclude = [],\n include,\n override = [],\n dataReturnType = 'data',\n baseURL,\n paramsCasing,\n paramsType = 'inline',\n pathParamsType = paramsType === 'object' ? 'object' : options.pathParamsType || 'inline',\n resolver: userResolver,\n macros: userMacros,\n generators: userGenerators = [],\n } = options\n\n const groupConfig = createGroupConfig(group)\n\n return {\n name: pluginCypressName,\n options,\n dependencies: [pluginTsName],\n hooks: {\n 'kubb:plugin:setup'(ctx) {\n const resolver = userResolver ? { ...resolverCypress, ...userResolver } : resolverCypress\n\n ctx.setOptions({\n output,\n exclude,\n include,\n override,\n dataReturnType,\n group: groupConfig,\n baseURL,\n paramsCasing,\n paramsType,\n pathParamsType,\n resolver,\n })\n ctx.setResolver(resolver)\n if (userMacros?.length) {\n ctx.setMacros(userMacros)\n }\n ctx.addGenerator(cypressGenerator)\n for (const gen of userGenerators) {\n ctx.addGenerator(gen)\n }\n },\n },\n }\n})\n\nexport default pluginCypress\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["ast","File","Function","jsxRenderer","ast","pluginTsName","File","pluginTsName"],"sources":["../../../internals/utils/src/casing.ts","../../../internals/utils/src/fs.ts","../../../internals/utils/src/reserved.ts","../../../internals/utils/src/url.ts","../../../internals/shared/src/params.ts","../../../internals/shared/src/operation.ts","../../../internals/shared/src/group.ts","../src/components/Request.tsx","../src/generators/cypressGenerator.tsx","../src/resolvers/resolverCypress.ts","../src/plugin.ts"],"sourcesContent":["type Options = {\n /**\n * Text prepended before casing is applied.\n */\n prefix?: string\n /**\n * Text appended before casing is applied.\n */\n suffix?: string\n}\n\n/**\n * Shared implementation for camelCase and PascalCase conversion.\n * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)\n * and capitalizes each word according to `pascal`.\n *\n * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.\n */\nfunction toCamelOrPascal(text: string, pascal: boolean): string {\n return text\n .trim()\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .replace(/(\\d)([a-z])/g, '$1 $2')\n .split(/[\\s\\-_./\\\\:]+/)\n .filter(Boolean)\n .map((word, i) => {\n if (word.length > 1 && word === word.toUpperCase()) return word\n const head = i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()\n return head + word.slice(1)\n })\n .join('')\n .replace(/[^a-zA-Z0-9]/g, '')\n}\n\n/**\n * Converts `text` to camelCase.\n *\n * @example Word boundaries\n * `camelCase('hello-world') // 'helloWorld'`\n *\n * @example With a prefix\n * `camelCase('tag', { prefix: 'create' }) // 'createTag'`\n */\nexport function camelCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false)\n}\n\n/**\n * Converts `text` to PascalCase.\n *\n * @example Word boundaries\n * `pascalCase('hello-world') // 'HelloWorld'`\n *\n * @example With a suffix\n * `pascalCase('tag', { suffix: 'schema' }) // 'TagSchema'`\n */\nexport function pascalCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true)\n}\n\n/**\n * Converts `text` to snake_case.\n *\n * @example From camelCase\n * `snakeCase('helloWorld') // 'hello_world'`\n *\n * @example From mixed separators\n * `snakeCase('Hello-World') // 'hello_world'`\n */\nexport function snakeCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n const processed = `${prefix} ${text} ${suffix}`.trim()\n return processed\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[\\s\\-.]+/g, '_')\n .replace(/[^a-zA-Z0-9_]/g, '')\n .toLowerCase()\n .split('_')\n .filter(Boolean)\n .join('_')\n}\n\n/**\n * Converts `text` to SCREAMING_SNAKE_CASE.\n *\n * @example From camelCase\n * `screamingSnakeCase('helloWorld') // 'HELLO_WORLD'`\n */\nexport function screamingSnakeCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return snakeCase(text, { prefix, suffix }).toUpperCase()\n}\n","import { posix } from 'node:path'\nimport { camelCase } from './casing.ts'\n\nfunction toSlash(p: string): string {\n if (p.startsWith('\\\\\\\\?\\\\')) return p\n return p.replaceAll('\\\\', '/')\n}\n\n/**\n * Returns the relative path from `rootDir` to `filePath`, always using forward slashes\n * and prefixed with `./` when not already traversing upward.\n *\n * @example\n * ```ts\n * getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'\n * getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'\n * ```\n */\nexport function getRelativePath(rootDir?: string | null, filePath?: string | null): string {\n if (!rootDir || !filePath) {\n throw new Error(`Root and file should be filled in when retrieving the relativePath, ${rootDir || ''} ${filePath || ''}`)\n }\n\n const relativePath = posix.relative(toSlash(rootDir), toSlash(filePath))\n\n return relativePath.startsWith('../') ? relativePath : `./${relativePath}`\n}\n\n/**\n * Builds a nested file path from a dotted name. Splits on dots that precede a letter\n * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases\n * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.\n *\n * Empty segments are dropped before joining. They arise when the name starts with a dot\n * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to\n * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an\n * absolute path, letting generated files escape the configured output directory.\n *\n * @example Nested path from a dotted name\n * `toFilePath('pet.petId') // 'pet/petId'`\n *\n * @example PascalCase the final segment\n * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`\n *\n * @example Suffix applied to the final segment only\n * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`\n */\nexport function toFilePath(name: string, caseLast: (part: string) => string = camelCase): string {\n const parts = name.split(/\\.(?=[a-zA-Z])/)\n return parts\n .map((part, i) => (i === parts.length - 1 ? caseLast(part) : camelCase(part)))\n .filter(Boolean)\n .join('/')\n}\n","/**\n * JavaScript and Java reserved words.\n * @link https://github.com/jonschlinkert/reserved/blob/master/index.js\n */\nconst reservedWords = new Set([\n 'abstract',\n 'arguments',\n 'boolean',\n 'break',\n 'byte',\n 'case',\n 'catch',\n 'char',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'double',\n 'else',\n 'enum',\n 'eval',\n 'export',\n 'extends',\n 'false',\n 'final',\n 'finally',\n 'float',\n 'for',\n 'function',\n 'goto',\n 'if',\n 'implements',\n 'import',\n 'in',\n 'instanceof',\n 'int',\n 'interface',\n 'let',\n 'long',\n 'native',\n 'new',\n 'null',\n 'package',\n 'private',\n 'protected',\n 'public',\n 'return',\n 'short',\n 'static',\n 'super',\n 'switch',\n 'synchronized',\n 'this',\n 'throw',\n 'throws',\n 'transient',\n 'true',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'volatile',\n 'while',\n 'with',\n 'yield',\n 'Array',\n 'Date',\n 'hasOwnProperty',\n 'Infinity',\n 'isFinite',\n 'isNaN',\n 'isPrototypeOf',\n 'length',\n 'Math',\n 'name',\n 'NaN',\n 'Number',\n 'Object',\n 'prototype',\n 'String',\n 'toString',\n 'undefined',\n 'valueOf',\n] as const)\n\n/**\n * Returns `true` when `name` is a syntactically valid JavaScript variable name.\n *\n * @example\n * ```ts\n * isValidVarName('status') // true\n * isValidVarName('class') // false (reserved word)\n * isValidVarName('42foo') // false (starts with digit)\n * ```\n */\nexport function isValidVarName(name: string): boolean {\n if (!name || reservedWords.has(name as 'valueOf')) {\n return false\n }\n return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)\n}\n\n/**\n * Returns `name` when it's a syntactically valid JavaScript variable name,\n * otherwise prefixes it with `_` so the result is a valid identifier.\n *\n * Useful for sanitizing OpenAPI schema names or operation IDs that start with\n * a digit (e.g. `409`, `504AccountCancel`) before using them as exported\n * variable, type, or function names.\n *\n * @example\n * ```ts\n * ensureValidVarName('409') // '_409'\n * ensureValidVarName('504AccountCancel') // '_504AccountCancel'\n * ensureValidVarName('Pet') // 'Pet'\n * ensureValidVarName('class') // '_class'\n * ```\n */\nexport function ensureValidVarName(name: string): string {\n if (!name || isValidVarName(name)) {\n return name\n }\n return `_${name}`\n}\n","import { camelCase } from './casing.ts'\nimport { isValidVarName } from './reserved.ts'\n\nexport type URLObject = {\n /**\n * The resolved URL string (Express-style or template literal, depending on context).\n */\n url: string\n /**\n * Extracted path parameters as a key-value map, or `null` when the path has none.\n */\n params: Record<string, string> | null\n}\n\n/**\n * Supported identifier casing strategies for path parameters.\n */\nexport type PathCasing = 'camelcase'\n\ntype TemplateOptions = {\n /**\n * Literal text prepended inside the template literal, e.g. a base URL.\n */\n prefix?: string | null\n /**\n * Transform applied to each extracted parameter name before interpolation.\n */\n replacer?: (pathParam: string) => string\n /**\n * Casing strategy applied to path parameter names.\n */\n casing?: PathCasing\n}\n\ntype ObjectOptions = {\n /**\n * Controls whether the `url` is rendered as an Express path or a template literal.\n * @default 'path'\n */\n type?: 'path' | 'template'\n /**\n * Transform applied to each extracted parameter name.\n */\n replacer?: (pathParam: string) => string\n /**\n * When `true`, the result is serialized to a string expression instead of a plain object.\n */\n stringify?: boolean\n /**\n * Casing strategy applied to path parameter names.\n */\n casing?: PathCasing\n}\n\nfunction transformParam(raw: string, casing?: PathCasing): string {\n const param = isValidVarName(raw) ? raw : camelCase(raw)\n return casing === 'camelcase' ? camelCase(param) : param\n}\n\nfunction toParamsObject(\n path: string,\n { replacer, casing }: { replacer?: (pathParam: string) => string; casing?: PathCasing } = {},\n): Record<string, string> | null {\n const params: Record<string, string> = {}\n\n for (const match of path.matchAll(/\\{([^}]+)\\}/g)) {\n const param = transformParam(match[1]!, casing)\n const key = replacer ? replacer(param) : param\n params[key] = key\n }\n\n return Object.keys(params).length > 0 ? params : null\n}\n\n/**\n * Helpers for OpenAPI/Swagger paths, plus a thin wrapper over the native `URL`.\n */\nexport class Url {\n /**\n * Reports whether `url` is a parseable absolute URL. Delegates to the native `URL.canParse`.\n *\n * @example\n * Url.canParse('https://petstore.swagger.io/v2') // true\n * Url.canParse('/pet/{petId}') // false\n */\n static canParse(url: string, base?: string | URL): boolean {\n return URL.canParse(url, base)\n }\n\n /**\n * Converts an OpenAPI/Swagger path to Express-style colon syntax.\n *\n * @example\n * Url.toPath('/pet/{petId}') // '/pet/:petId'\n */\n static toPath(path: string): string {\n return path.replace(/\\{([^}]+)\\}/g, ':$1')\n }\n\n /**\n * Converts an OpenAPI/Swagger path to a TypeScript template literal string.\n * `prefix` is prepended inside the literal, `replacer` transforms each parameter name,\n * and `casing` controls parameter identifier casing.\n *\n * @example\n * Url.toTemplateString('/pet/{petId}') // '`/pet/${petId}`'\n *\n * @example\n * Url.toTemplateString('/pet/{petId}', { prefix: 'https://api' }) // '`https://api/pet/${petId}`'\n */\n static toTemplateString(path: string, { prefix, replacer, casing }: TemplateOptions = {}): string {\n const parts = path.split(/\\{([^}]+)\\}/)\n const result = parts\n .map((part, i) => {\n if (i % 2 === 0) return part\n const param = transformParam(part, casing)\n return `\\${${replacer ? replacer(param) : param}}`\n })\n .join('')\n\n return `\\`${prefix ?? ''}${result}\\``\n }\n\n /**\n * Converts an OpenAPI/Swagger path to a template literal that reads each parameter off the\n * grouped `path` request option, e.g. `/pet/{petId}` becomes `` `/pet/${path.petId}` ``. Parameter\n * names are camelCased to match the generated `path` type, and `prefix` is prepended inside the\n * literal. Shared by the client and cypress generators that pass a grouped `path` object.\n *\n * @example\n * Url.toGroupedTemplateString('/pet/{petId}') // '`/pet/${path.petId}`'\n */\n static toGroupedTemplateString(path: string, { prefix }: { prefix?: string | null } = {}): string {\n return Url.toTemplateString(path, { prefix, casing: 'camelcase', replacer: (name) => `path.${name}` })\n }\n\n /**\n * Returns the path and its extracted params as a structured `URLObject`, or as a stringified\n * expression when `stringify` is set.\n *\n * @example\n * Url.toObject('/pet/{petId}')\n * // { url: '/pet/:petId', params: { petId: 'petId' } }\n */\n static toObject(path: string, { type = 'path', replacer, stringify, casing }: ObjectOptions = {}): URLObject | string {\n const object: URLObject = {\n url: type === 'path' ? Url.toPath(path) : Url.toTemplateString(path, { replacer, casing }),\n params: toParamsObject(path, { replacer, casing }),\n }\n\n if (stringify) {\n if (type === 'template') {\n return JSON.stringify(object).replaceAll(\"'\", '').replaceAll(`\"`, '')\n }\n\n if (object.params) {\n return `{ url: '${object.url}', params: ${JSON.stringify(object.params).replaceAll(\"'\", '').replaceAll(`\"`, '')} }`\n }\n\n return `{ url: '${object.url}' }`\n }\n\n return object\n }\n}\n","import { camelCase } from '@internals/utils'\nimport type { ParameterNode } from '@kubb/ast'\n\nconst caseParamsCache = new WeakMap<Array<ParameterNode>, Array<ParameterNode>>()\n\n/**\n * Applies camelCase to parameter names and returns a new array without mutating the input.\n *\n * Run it before handing parameters to schema builders so output property keys get the right casing\n * while `OperationNode.parameters` stays intact for other consumers. When `casing` is unset, the\n * original array is returned unchanged. Results are cached per input array.\n */\nexport function caseParams(params: Array<ParameterNode>, casing: 'camelcase' | undefined): Array<ParameterNode> {\n if (!casing) return params\n\n const cached = caseParamsCache.get(params)\n if (cached) return cached\n\n const result = params.map((param) => ({ ...param, name: camelCase(param.name) }))\n caseParamsCache.set(params, result)\n return result\n}\n\nexport function buildParamsMapping<TParam extends { name: string }>(\n originalParams: ReadonlyArray<TParam>,\n mappedParams: ReadonlyArray<TParam>,\n): Record<string, string> | null {\n const mapping: Record<string, string> = {}\n let hasChanged = false\n\n originalParams.forEach((param, i) => {\n const mappedName = mappedParams[i]?.name ?? param.name\n mapping[param.name] = mappedName\n\n if (param.name !== mappedName) {\n hasChanged = true\n }\n })\n\n return hasChanged ? mapping : null\n}\n\nexport function buildTransformedParamsMapping<TParam extends { name: string }>(\n params: ReadonlyArray<TParam>,\n transformName: (name: string) => string,\n): Record<string, string> | null {\n if (!params.length) {\n return null\n }\n\n return buildParamsMapping(\n params,\n params.map((param) => ({ ...param, name: transformName(param.name) })),\n )\n}\n","import { Url } from '@internals/utils'\nimport { ast, type ResolverFileParams } from '@kubb/core'\nimport { caseParams } from './params.ts'\n\n/**\n * Builds the `ResolverFileParams` every operation generator passes to\n * `resolver.resolveFile`: a file named `name`, tagged by the operation's first\n * tag (or `'default'`), at the operation's path. Centralizes the entry object\n * that was repeated at dozens of call sites across the client and query plugins.\n *\n * @example\n * ```ts\n * resolver.resolveFile(operationFileEntry(node, node.operationId), { root, output, group })\n * ```\n */\nexport function operationFileEntry(node: ast.OperationNode, name: string, extname: ResolverFileParams['extname'] = '.ts'): ResolverFileParams {\n return {\n name,\n extname,\n tag: node.tags[0] ?? 'default',\n path: node.path,\n }\n}\n\nexport type ContentTypeInfo = {\n contentTypes: string[]\n isMultipleContentTypes: boolean\n contentTypeUnion: string\n defaultContentType: string\n hasFormData: boolean\n}\n\nexport type RequestConfigResolver = {\n resolveDataName(node: ast.OperationNode): string\n}\n\nexport type ResponseStatusNameResolver = {\n resolveResponseStatusName(node: ast.OperationNode, statusCode: ast.StatusCode): string\n}\n\nexport type ResponseNameResolver = ResponseStatusNameResolver & {\n resolveResponseName(node: ast.OperationNode): string\n}\n\nexport type OperationTypeNameResolver = RequestConfigResolver &\n ResponseNameResolver & {\n resolvePathParamsName(node: ast.OperationNode, param: ast.ParameterNode): string\n resolveQueryParamsName(node: ast.OperationNode, param: ast.ParameterNode): string\n resolveHeaderParamsName(node: ast.OperationNode, param: ast.ParameterNode): string\n }\n\n/**\n * Resolver interface for building operation parameters.\n *\n * `ResolverTs` from `@kubb/plugin-ts` satisfies this interface and can be passed directly.\n */\nexport type OperationParamsResolver = {\n /**\n * Resolves the type name for an individual parameter.\n *\n * @example Individual path parameter name\n * `resolver.resolveParamName(node, param) // → 'DeletePetPathPetId'`\n */\n resolveParamName(node: ast.OperationNode, param: ast.ParameterNode): string\n /**\n * Resolves the request body type name.\n *\n * @example Request body type name\n * `resolver.resolveDataName(node) // → 'CreatePetData'`\n */\n resolveDataName(node: ast.OperationNode): string\n /**\n * Resolves the grouped path parameters type name.\n * When the return value equals `resolveParamName`, no indexed access is emitted.\n *\n * @example Grouped path params type name\n * `resolver.resolvePathParamsName(node, param) // → 'DeletePetPathParams'`\n */\n resolvePathParamsName(node: ast.OperationNode, param: ast.ParameterNode): string\n /**\n * Resolves the grouped query parameters type name.\n * When the return value equals `resolveParamName`, an inline struct type is emitted instead.\n *\n * @example Grouped query params type name\n * `resolver.resolveQueryParamsName(node, param) // → 'FindPetsByStatusQueryParams'`\n */\n resolveQueryParamsName(node: ast.OperationNode, param: ast.ParameterNode): string\n /**\n * Resolves the grouped header parameters type name.\n * When the return value equals `resolveParamName`, an inline struct type is emitted instead.\n *\n * @example Grouped header params type name\n * `resolver.resolveHeaderParamsName(node, param) // → 'DeletePetHeaderParams'`\n */\n resolveHeaderParamsName(node: ast.OperationNode, param: ast.ParameterNode): string\n}\n\nexport type OperationCommentLink = 'pathTemplate' | 'urlPath' | false | ((node: ast.OperationNode) => string | undefined)\n\nexport type BuildOperationCommentsOptions = {\n link?: OperationCommentLink\n linkPosition?: 'beforeDeprecated' | 'afterDeprecated'\n splitLines?: boolean\n}\n\ntype ResponseLike = {\n statusCode: ast.StatusCode | number | string\n}\n\nexport type OperationParameterGroups = Record<ast.ParameterNode['in'], Array<ast.ParameterNode>>\n\nexport type ResolveOperationTypeNameOptions = {\n paramsCasing?: 'camelcase' | 'original'\n responseStatusNames?: boolean | 'error'\n exclude?: ReadonlyArray<string | undefined>\n order?: 'params-first' | 'body-response-first'\n /**\n * Include the individual `PathParams`/`QueryParams`/`HeaderParams` type names. Set to `false`\n * for clients that reference the grouped `RequestConfig` type instead of the per-group types.\n */\n includeParams?: boolean\n}\n\nfunction getOperationLink(node: ast.OperationNode, link: OperationCommentLink): string | null {\n if (!link) {\n return null\n }\n\n if (typeof link === 'function') {\n return link(node) ?? null\n }\n\n if (link === 'urlPath') {\n return node.path ? `{@link ${Url.toPath(node.path)}}` : null\n }\n\n return node.path ? `{@link ${node.path.replaceAll('{', ':').replaceAll('}', '')}}` : null\n}\n\nexport function getContentTypeInfo(node: ast.OperationNode): ContentTypeInfo {\n const contentTypes = node.requestBody?.content?.map((e) => e.contentType) ?? []\n const isMultipleContentTypes = contentTypes.length > 1\n\n return {\n contentTypes,\n isMultipleContentTypes,\n contentTypeUnion: isMultipleContentTypes ? contentTypes.map((ct) => JSON.stringify(ct)).join(' | ') : '',\n defaultContentType: contentTypes[0] ?? 'application/json',\n hasFormData: contentTypes.some((ct) => ct === 'multipart/form-data'),\n }\n}\n\nexport type ResponseType = 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'\n\n/**\n * Derives the default `responseType` for an operation from its primary success response.\n *\n * Returns a value only when that response declares a single non-JSON content type — a binary type\n * (`application/octet-stream`, `application/pdf`, `image/*`, `audio/*`, `video/*`) maps to `'blob'`\n * and other `text/*` maps to `'text'`. Otherwise `undefined`, leaving the runtime client's\n * `Content-Type` auto-detection in charge.\n */\nexport function getResponseType(node: ast.OperationNode): ResponseType | undefined {\n const contentTypes = getPrimarySuccessResponse(node)?.content?.map((entry) => entry.contentType) ?? []\n if (contentTypes.length !== 1) return undefined\n\n const baseType = contentTypes[0]!.split(';')[0]!.trim().toLowerCase()\n if (baseType === 'application/json' || baseType.endsWith('+json') || baseType === 'text/json') return undefined\n if (baseType.startsWith('text/')) return 'text'\n if (baseType === 'application/octet-stream' || baseType === 'application/pdf' || /^(image|audio|video)\\//.test(baseType)) return 'blob'\n return undefined\n}\n\n/**\n * Maps a content type to the PascalCase suffix used to name per-content-type variants\n * (e.g. `application/json` → `Json`, `application/xml` → `Xml`, `multipart/form-data` → `FormData`).\n */\nfunction getContentTypeSuffix(contentType: string): string {\n const baseType = contentType.split(';')[0]!.trim()\n if (baseType === 'application/json') return 'Json'\n if (baseType === 'multipart/form-data') return 'FormData'\n if (baseType === 'application/x-www-form-urlencoded') return 'FormUrlEncoded'\n const subtype = baseType.split('/').pop() ?? baseType\n const parts = subtype.split(/[^a-zA-Z0-9]+/).filter(Boolean)\n if (parts.length === 0) return 'Unknown'\n return parts.map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join('')\n}\n\n/**\n * Appends a content-type suffix to a base name, keeping a trailing `Data` segment last\n * (e.g. `AddPetData` + `Json` → `AddPetJsonData`, `AddPetStatus200` + `Xml` → `AddPetStatus200Xml`).\n */\nexport function getPerContentTypeName(baseName: string, suffix: string): string {\n if (baseName.endsWith('Data')) {\n return suffix.endsWith('Data') ? baseName.slice(0, -4) + suffix : `${baseName.slice(0, -4)}${suffix}Data`\n }\n return baseName + suffix\n}\n\nexport type ContentVariantInput = { contentType: string; schema?: ast.SchemaNode | null; keysToOmit?: Array<string> | null }\nexport type ContentVariant = { name: string; suffix: string; schema: ast.SchemaNode; keysToOmit?: Array<string> | null; contentType: string }\n\n/**\n * Resolves per-content-type variant names for a set of content entries, deduplicating suffix\n * collisions with a numeric counter. Entries without a schema are skipped. The returned `suffix` is\n * the final (possibly counter-augmented) value, so callers can derive parallel names in another\n * namespace (e.g. plugin-faker deriving the matching plugin-ts type name).\n */\nexport function resolveContentTypeVariants(entries: Array<ContentVariantInput>, baseName: string): Array<ContentVariant> {\n const usedNames = new Set<string>()\n return entries\n .filter((entry) => entry.schema)\n .map((entry) => {\n const baseSuffix = getContentTypeSuffix(entry.contentType)\n let suffix = baseSuffix\n let name = getPerContentTypeName(baseName, suffix)\n let counter = 2\n while (usedNames.has(name)) {\n suffix = `${baseSuffix}${counter++}`\n name = getPerContentTypeName(baseName, suffix)\n }\n usedNames.add(name)\n return { name, suffix, schema: entry.schema!, keysToOmit: entry.keysToOmit, contentType: entry.contentType }\n })\n}\n\nexport function buildRequestConfigType(node: ast.OperationNode): string {\n const { isMultipleContentTypes, contentTypeUnion } = getContentTypeInfo(node)\n // The request groups come from the grouped params, so `config` drops the data-shape keys to stay\n // assignable to `Options`, which omits them from `RequestConfig`.\n const configType = `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`\n const contentTypeProp = isMultipleContentTypes ? `contentType?: ${contentTypeUnion}` : null\n\n return contentTypeProp ? `${configType} & { ${contentTypeProp} }` : configType\n}\n\n/**\n * Builds the `client?:` option type shared by the generated query hooks (`useQuery`,\n * `useInfiniteQuery`, `useSWR`, ...). Unlike {@link buildRequestConfigType}, it never adds a\n * `contentType?:` member: query hooks wrap GET operations, which carry no request body to select a\n * content type for.\n */\nexport function buildClientOptionType(): string {\n return `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`\n}\n\nexport type RequestGroups = {\n path: boolean\n query: boolean\n body: boolean\n headers: boolean\n}\n\n/**\n * Which of the grouped request options an operation carries.\n */\nexport function getRequestGroups(node: ast.OperationNode): RequestGroups {\n const { path, query, header } = getOperationParameters(node)\n return {\n path: path.length > 0,\n query: query.length > 0,\n body: Boolean(node.requestBody?.content?.[0]?.schema),\n headers: header.length > 0,\n }\n}\n\nexport type RequestGroupOptionality = {\n groups: RequestGroups\n hasRequiredPath: boolean\n hasRequiredQuery: boolean\n hasRequiredHeader: boolean\n /**\n * Whether the grouped request parameter can default to `{}`. True only when no group carries a\n * required member, so every member is safe to omit.\n */\n isOptional: boolean\n}\n\n/**\n * Resolves which grouped request options an operation carries together with whether each group\n * holds a required member. The grouped parameter stays optional only when nothing inside it is\n * required, matching the generated `RequestConfig` type.\n */\nexport function getRequestGroupOptionality(node: ast.OperationNode): RequestGroupOptionality {\n const groups = getRequestGroups(node)\n const { path, query, header } = getOperationParameters(node)\n const hasRequiredPath = path.some((param) => param.required)\n const hasRequiredQuery = query.some((param) => param.required)\n const hasRequiredHeader = header.some((param) => param.required)\n\n return {\n groups,\n hasRequiredPath,\n hasRequiredQuery,\n hasRequiredHeader,\n isOptional: !hasRequiredPath && !hasRequiredQuery && !hasRequiredHeader && !groups.body,\n }\n}\n\nexport type RequestConfigNameResolver = RequestConfigResolver & {\n resolveRequestConfigName(node: ast.OperationNode): string\n}\n\n/**\n * Builds the grouped `{ path, query, body, headers }` parameter for a generated client\n * function, typed from the operation's `RequestConfig` (minus `url`). Only the groups the\n * operation actually has are destructured. The trailing `config` parameter carries the\n * runtime `RequestConfig` overrides plus `client`.\n */\nexport function buildRequestParamsSignature(\n node: ast.OperationNode,\n resolver: RequestConfigNameResolver,\n options: { isConfigurable?: boolean } = {},\n): { signature: string; groups: RequestGroups } {\n const { isConfigurable = true } = options\n const { groups, isOptional } = getRequestGroupOptionality(node)\n\n const names = (['path', 'query', 'body', 'headers'] as const).filter((key) => groups[key])\n\n const firstParam = names.length > 0 ? `{ ${names.join(', ')} }: ${resolver.resolveRequestConfigName(node)}${isOptional ? ' = {}' : ''}` : null\n const configParam = isConfigurable ? `config: ${buildRequestConfigType(node)} = {}` : null\n\n return {\n signature: [firstParam, configParam].filter(Boolean).join(', '),\n groups,\n }\n}\n\nexport function buildOperationComments(node: ast.OperationNode, options: BuildOperationCommentsOptions = {}): Array<string> {\n const { link = 'pathTemplate', linkPosition = 'afterDeprecated', splitLines = false } = options\n const linkComment = getOperationLink(node, link)\n const comments =\n linkPosition === 'beforeDeprecated'\n ? [node.description && `@description ${node.description}`, node.summary && `@summary ${node.summary}`, linkComment, node.deprecated && '@deprecated']\n : [node.description && `@description ${node.description}`, node.summary && `@summary ${node.summary}`, node.deprecated && '@deprecated', linkComment]\n\n const filteredComments = comments.filter((comment): comment is string => Boolean(comment))\n\n if (!splitLines) {\n return filteredComments\n }\n\n return filteredComments.flatMap((text) => text.split(/\\r?\\n/).map((line) => line.trim())).filter((comment): comment is string => Boolean(comment))\n}\n\nexport function getOperationParameters(node: ast.OperationNode, options: { paramsCasing?: 'camelcase' | 'original' } = {}): OperationParameterGroups {\n const params = caseParams(node.parameters, options.paramsCasing === 'original' ? undefined : 'camelcase')\n\n return {\n path: params.filter((param) => param.in === 'path'),\n query: params.filter((param) => param.in === 'query'),\n header: params.filter((param) => param.in === 'header'),\n cookie: params.filter((param) => param.in === 'cookie'),\n }\n}\n\nexport function getStatusCodeNumber(statusCode: ast.StatusCode | number | string): number | null {\n const code = Number(statusCode)\n\n return Number.isNaN(code) ? null : code\n}\n\nexport function isSuccessStatusCode(statusCode: ast.StatusCode | number | string): boolean {\n const code = getStatusCodeNumber(statusCode)\n\n return code !== null && code >= 200 && code < 300\n}\n\nexport function isErrorStatusCode(statusCode: ast.StatusCode | number | string): boolean {\n const code = getStatusCodeNumber(statusCode)\n\n return code !== null && code >= 400\n}\n\nexport function getSuccessResponses<TResponse extends ResponseLike>(responses: ReadonlyArray<TResponse>): Array<TResponse> {\n return responses.filter((response) => isSuccessStatusCode(response.statusCode))\n}\n\nexport function getOperationSuccessResponses(node: ast.OperationNode): Array<ast.ResponseNode> {\n return getSuccessResponses(node.responses)\n}\n\nexport function getPrimarySuccessResponse(node: ast.OperationNode): ast.ResponseNode | null {\n return getOperationSuccessResponses(node)[0] ?? null\n}\n\nexport function resolveErrorNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses\n .filter((response) => isErrorStatusCode(response.statusCode))\n .map((response) => resolver.resolveResponseStatusName(node, response.statusCode))\n}\n\nexport function resolveSuccessNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses\n .filter((response) => isSuccessStatusCode(response.statusCode))\n .map((response) => resolver.resolveResponseStatusName(node, response.statusCode))\n}\n\nexport function resolveStatusCodeNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses.map((response) => resolver.resolveResponseStatusName(node, response.statusCode))\n}\n\nconst typeNamesByResolver = new WeakMap<OperationTypeNameResolver, Map<string, string[]>>()\n\nexport function resolveOperationTypeNames(\n node: ast.OperationNode,\n resolver: OperationTypeNameResolver,\n options: ResolveOperationTypeNameOptions = {},\n): string[] {\n const cacheKey = `${node.operationId}\\0${options.paramsCasing ?? ''}\\0${options.order ?? ''}\\0${options.responseStatusNames ?? ''}\\0${options.includeParams === false ? 'noparams' : ''}\\0${(options.exclude ?? []).join(',')}`\n let byResolver = typeNamesByResolver.get(resolver)\n if (byResolver) {\n const cached = byResolver.get(cacheKey)\n if (cached) return cached\n } else {\n byResolver = new Map()\n typeNamesByResolver.set(resolver, byResolver)\n }\n\n const { path, query, header } = getOperationParameters(node, { paramsCasing: options.paramsCasing })\n const responseStatusNames =\n options.responseStatusNames === 'error'\n ? resolveErrorNames(node, resolver)\n : options.responseStatusNames === false\n ? []\n : resolveStatusCodeNames(node, resolver)\n const exclude = new Set(options.exclude ?? [])\n const paramNames =\n options.includeParams === false\n ? []\n : [\n ...path.map((param) => resolver.resolvePathParamsName(node, param)),\n ...query.map((param) => resolver.resolveQueryParamsName(node, param)),\n ...header.map((param) => resolver.resolveHeaderParamsName(node, param)),\n ]\n const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null, resolver.resolveResponseName(node)]\n const names =\n options.order === 'body-response-first'\n ? [...bodyAndResponseNames, ...paramNames, ...responseStatusNames]\n : [...paramNames, ...bodyAndResponseNames, ...responseStatusNames]\n\n const result = names.filter((name): name is string => Boolean(name) && !exclude.has(name as string))\n byResolver.set(cacheKey, result)\n return result\n}\n\nexport function resolveResponseTypes(node: ast.OperationNode, resolver: ResponseNameResolver): Array<[statusCode: number | 'default', typeName: string]> {\n const types: Array<[number | 'default', string]> = []\n\n for (const response of node.responses) {\n if (response.statusCode === 'default') {\n types.push(['default', resolver.resolveResponseName(node)])\n continue\n }\n\n const code = getStatusCodeNumber(response.statusCode)\n if (code === null) {\n continue\n }\n\n types.push([code, isSuccessStatusCode(code) ? resolver.resolveResponseName(node) : resolver.resolveResponseStatusName(node, response.statusCode)])\n }\n\n return types\n}\n\nexport function findSuccessStatusCode(responses: Array<{ statusCode: ast.StatusCode | number | string }>): ast.StatusCode | null {\n for (const response of responses) {\n if (isSuccessStatusCode(response.statusCode)) {\n return response.statusCode as ast.StatusCode\n }\n }\n\n return null\n}\n","import { camelCase } from '@internals/utils'\nimport type { Group } from '@kubb/core'\n\n/**\n * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the\n * shared default naming so every plugin groups output consistently:\n *\n * - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).\n * - other groups use the camelCased group (`pet store` → `petStore`).\n *\n * A user-provided `group.name` always wins over the default namer, so callers stay in\n * control of their output folders. Returns `null` when grouping is disabled, matching the\n * per-plugin convention.\n *\n * @param group - The user-supplied group option, or `undefined` to disable grouping.\n *\n * @example\n * ```ts\n * createGroupConfig(group) // shared across every plugin\n * ```\n */\nexport function createGroupConfig(group: Group | undefined): Group | null {\n if (!group) {\n return null\n }\n\n const defaultName = (ctx: { group: string }): string => {\n if (group.type === 'path') {\n return `${ctx.group.split('/')[1]}`\n }\n\n return camelCase(ctx.group)\n }\n\n return {\n ...group,\n name: group.name ? group.name : defaultName,\n } satisfies Group\n}\n","import { buildParamsMapping, buildRequestParamsSignature, getOperationParameters } from '@internals/shared'\nimport { Url } from '@internals/utils'\nimport { ast } from '@kubb/core'\nimport type { ResolverTs } from '@kubb/plugin-ts'\nimport { File, Function } from '@kubb/renderer-jsx'\nimport type { KubbReactNode } from '@kubb/renderer-jsx/types'\n\ntype Props = {\n /**\n * Name of the function\n */\n name: string\n /**\n * AST operation node\n */\n node: ast.OperationNode\n /**\n * TypeScript resolver for resolving param/data/response type names\n */\n resolver: ResolverTs\n baseURL: string | null | undefined\n}\n\nexport function Request({ baseURL = '', name, resolver, node }: Props): KubbReactNode {\n if (!ast.isHttpOperationNode(node)) return null\n\n const { query: originalQueryParams, header: originalHeaderParams } = getOperationParameters(node, { paramsCasing: 'original' })\n const { query: casedQueryParams, header: casedHeaderParams } = getOperationParameters(node)\n\n const queryParamsMapping = buildParamsMapping(originalQueryParams, casedQueryParams)\n const headerParamsMapping = buildParamsMapping(originalHeaderParams, casedHeaderParams)\n\n const { signature, groups } = buildRequestParamsSignature(node, resolver, { isConfigurable: false })\n const paramsSignature = [signature, 'options: Partial<Cypress.RequestOptions> = {}'].filter(Boolean).join(', ')\n\n const responseType = resolver.resolveResponseName(node)\n const returnType = `Cypress.Chainable<${responseType}>`\n\n // Reference the path object straight in the URL with camelCase placeholders.\n const urlTemplate = Url.toGroupedTemplateString(node.path, { prefix: baseURL })\n\n const requestOptions: Array<string> = [`method: '${node.method}'`, `url: ${urlTemplate}`]\n\n if (groups.query) {\n if (queryParamsMapping) {\n // When paramsCasing renames query params (e.g. page_size → pageSize), we must remap\n // the camelCase keys back to the original API names before passing them to `qs`.\n const pairs = Object.entries(queryParamsMapping)\n .map(([originalName, camelCaseName]) => `${originalName}: query.${camelCaseName}`)\n .join(', ')\n requestOptions.push(`qs: query ? { ${pairs} } : undefined`)\n } else {\n requestOptions.push('qs: query')\n }\n }\n\n if (groups.headers) {\n if (headerParamsMapping) {\n // When paramsCasing renames header params (e.g. x-api-key → xApiKey), we must remap\n // the camelCase keys back to the original API names before passing them to `headers`.\n const pairs = Object.entries(headerParamsMapping)\n .map(([originalName, camelCaseName]) => `'${originalName}': headers.${camelCaseName}`)\n .join(', ')\n requestOptions.push(`headers: headers ? { ${pairs} } : undefined`)\n } else {\n requestOptions.push('headers')\n }\n }\n\n if (groups.body) {\n requestOptions.push('body')\n }\n\n requestOptions.push('...options')\n\n const requestCall = `return cy.request<${responseType}>({\n ${requestOptions.join(',\\n ')}\n}).then((res) => res.body)`\n\n return (\n <File.Source name={name} isIndexable isExportable>\n <Function name={name} export params={paramsSignature} returnType={returnType}>\n {requestCall}\n </Function>\n </File.Source>\n )\n}\n","import { resolveOperationTypeNames } from '@internals/shared'\nimport { ast, defineGenerator } from '@kubb/core'\nimport { pluginTsName } from '@kubb/plugin-ts'\nimport { File, jsxRenderer } from '@kubb/renderer-jsx'\nimport { Request } from '../components/Request.tsx'\nimport type { PluginCypress } from '../types.ts'\n\n/**\n * Built-in generator for `@kubb/plugin-cypress`. Emits one typed\n * `cy.request()` wrapper per OpenAPI operation, ready to call inside Cypress\n * test specs and custom commands.\n */\nexport const cypressGenerator = defineGenerator<PluginCypress>({\n name: 'cypress',\n renderer: jsxRenderer,\n operation(node, ctx) {\n if (!ast.isHttpOperationNode(node)) return null\n const { config, resolver, driver, root } = ctx\n const { output, baseURL, group } = ctx.options\n\n const pluginTs = driver.getPlugin(pluginTsName)\n\n if (!pluginTs) {\n return null\n }\n\n const tsResolver = driver.getResolver(pluginTsName)\n\n const importedTypeNames = [tsResolver.resolveRequestConfigName(node), ...resolveOperationTypeNames(node, tsResolver, { includeParams: false })]\n\n const meta = {\n name: resolver.resolveName(node.operationId),\n file: resolver.resolveFile(\n { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },\n { root, output, group: group ?? undefined },\n ),\n fileTs: tsResolver.resolveFile(\n { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },\n {\n root,\n output: pluginTs.options?.output ?? output,\n group: pluginTs.options?.group ?? undefined,\n },\n ),\n } as const\n\n return (\n <File\n baseName={meta.file.baseName}\n path={meta.file.path}\n meta={meta.file.meta}\n banner={resolver.resolveBanner(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}\n footer={resolver.resolveFooter(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}\n >\n {meta.fileTs && importedTypeNames.length > 0 && <File.Import name={importedTypeNames} root={meta.file.path} path={meta.fileTs.path} isTypeOnly />}\n <Request name={meta.name} node={node} resolver={tsResolver} baseURL={baseURL} />\n </File>\n )\n },\n})\n","import { camelCase, toFilePath } from '@internals/utils'\nimport { defineResolver } from '@kubb/core'\nimport type { PluginCypress } from '../types.ts'\n\n/**\n * Default resolver used by `@kubb/plugin-cypress`. Decides the names and file\n * paths for every generated `cy.request()` wrapper. Functions and files use\n * camelCase, matching the convention from `@kubb/plugin-axios` and `@kubb/plugin-fetch`.\n *\n * @example Resolve a helper name\n * ```ts\n * import { resolverCypress } from '@kubb/plugin-cypress'\n *\n * resolverCypress.default('list pets', 'function') // 'listPets'\n * ```\n */\nexport const resolverCypress = defineResolver<PluginCypress>(() => ({\n name: 'default',\n pluginName: 'plugin-cypress',\n default(name, type) {\n return type === 'file' ? toFilePath(name) : camelCase(name)\n },\n resolveName(name) {\n return this.default(name, 'function')\n },\n resolvePathName(name, type) {\n return this.default(name, type)\n },\n}))\n","import { createGroupConfig } from '@internals/shared'\nimport { definePlugin } from '@kubb/core'\nimport { pluginTsName } from '@kubb/plugin-ts'\nimport { cypressGenerator } from './generators/cypressGenerator.tsx'\nimport { resolverCypress } from './resolvers/resolverCypress.ts'\nimport type { PluginCypress } from './types.ts'\n\n/**\n * Canonical plugin name for `@kubb/plugin-cypress`. Used for driver lookups and\n * cross-plugin dependency references.\n */\nexport const pluginCypressName = 'plugin-cypress' satisfies PluginCypress['name']\n\n/**\n * Generates one typed `cy.request()` wrapper per OpenAPI operation. Each helper\n * has typed path params, body, query, and a typed response, so failing API\n * calls in Cypress show up at compile time instead of inside the test runner.\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb'\n * import { pluginTs } from '@kubb/plugin-ts'\n * import { pluginCypress } from '@kubb/plugin-cypress'\n *\n * export default defineConfig({\n * input: { path: './petStore.yaml' },\n * output: { path: './src/gen' },\n * plugins: [\n * pluginTs(),\n * pluginCypress({\n * output: { path: './cypress' },\n * }),\n * ],\n * })\n * ```\n */\nexport const pluginCypress = definePlugin<PluginCypress>((options) => {\n const {\n output = { path: 'cypress', barrel: { type: 'named' } },\n group,\n exclude = [],\n include,\n override = [],\n baseURL,\n resolver: userResolver,\n macros: userMacros,\n } = options\n\n const groupConfig = createGroupConfig(group)\n\n return {\n name: pluginCypressName,\n options,\n dependencies: [pluginTsName],\n hooks: {\n 'kubb:plugin:setup'(ctx) {\n const resolver = userResolver ? { ...resolverCypress, ...userResolver } : resolverCypress\n\n ctx.setOptions({\n output,\n exclude,\n include,\n override,\n group: groupConfig,\n baseURL,\n resolver,\n })\n ctx.setResolver(resolver)\n if (userMacros?.length) {\n ctx.setMacros(userMacros)\n }\n ctx.addGenerator(cypressGenerator)\n },\n },\n }\n})\n\nexport default pluginCypress\n"],"mappings":"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"}