@kubb/plugin-cypress 5.0.0-beta.3 → 5.0.0-beta.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -16,26 +16,32 @@ type ResolverCypress = Resolver & {
16
16
  * `resolver.resolveName('show pet by id') // -> 'showPetById'`
17
17
  */
18
18
  resolveName(this: ResolverCypress, name: string): string;
19
+ /**
20
+ * Resolves the output file name for a Cypress request module.
21
+ */
22
+ resolvePathName(this: ResolverCypress, name: string, type?: 'file' | 'function' | 'type' | 'const'): string;
19
23
  };
20
24
  /**
21
25
  * Parameter handling mode that determines how path params and query/body params are arranged in function signatures.
22
26
  */
23
27
  type ParamsTypeOptions = {
24
28
  /**
25
- * All parameters merged into a single destructured object.
29
+ * Every operation parameter is wrapped in a single destructured object argument.
26
30
  */
27
31
  paramsType: 'object';
28
32
  /**
29
- * Not applicable when all parameters are merged into a single object.
33
+ * `pathParamsType` has no effect when `paramsType` is `'object'`.
30
34
  */
31
35
  pathParamsType?: never;
32
36
  } | {
33
37
  /**
34
- * Each parameter group emitted as a separate function argument.
38
+ * Each parameter group is emitted as a separate positional function argument.
35
39
  */
36
40
  paramsType?: 'inline';
37
41
  /**
38
- * How path parameters are arranged: grouped in an object or spread inline.
42
+ * How URL path parameters are arranged inside the inline argument list.
43
+ * - `'object'` groups them into one destructured object.
44
+ * - `'inline'` emits each path param as its own argument.
39
45
  *
40
46
  * @default 'inline'
41
47
  */
@@ -43,50 +49,56 @@ type ParamsTypeOptions = {
43
49
  };
44
50
  type Options = {
45
51
  /**
46
- * Specify the export location for the files and define the behavior of the output.
47
- * @default { path: 'cypress', barrelType: 'named' }
52
+ * Where the generated Cypress helpers are written and how they are exported.
53
+ *
54
+ * @default { path: 'cypress', barrel: { type: 'named' } }
48
55
  */
49
56
  output?: Output;
50
57
  /**
51
- * Return type when calling cy.request: response data only or full response.
58
+ * Shape of the value returned from each helper.
59
+ * - `'data'` — only the response body.
60
+ * - `'full'` — the full Cypress response object (headers, status, body).
52
61
  *
53
62
  * @default 'data'
54
63
  */
55
64
  dataReturnType?: 'data' | 'full';
56
65
  /**
57
- * Apply casing to parameter names.
66
+ * Rename parameter properties in the generated helpers (path, query, headers).
67
+ *
68
+ * @note Must match the value of `paramsCasing` on `@kubb/plugin-ts`.
58
69
  */
59
70
  paramsCasing?: 'camelcase';
60
71
  /**
61
- * Base URL prepended to every generated request URL.
72
+ * Base URL prepended to every request URL. When omitted, falls back to the
73
+ * adapter's server URL (typically `servers[0].url`).
62
74
  */
63
75
  baseURL?: string;
64
76
  /**
65
- * Group the Cypress requests based on the provided name.
77
+ * Split generated files into subfolders based on the operation's tag.
66
78
  */
67
79
  group?: Group;
68
80
  /**
69
- * Tags, operations, or paths to exclude from generation.
81
+ * Skip operations matching at least one entry in the list.
70
82
  */
71
83
  exclude?: Array<Exclude>;
72
84
  /**
73
- * Tags, operations, or paths to include in generation.
85
+ * Restrict generation to operations matching at least one entry in the list.
74
86
  */
75
87
  include?: Array<Include>;
76
88
  /**
77
- * Override options for specific tags, operations, or paths.
89
+ * Apply a different options object to operations matching a pattern.
78
90
  */
79
91
  override?: Array<Override<ResolvedOptions>>;
80
92
  /**
81
- * Override naming conventions for function names and types.
93
+ * Override how helper names and file paths are built.
82
94
  */
83
95
  resolver?: Partial<ResolverCypress> & ThisType<ResolverCypress>;
84
96
  /**
85
- * AST visitor to transform generated nodes.
97
+ * AST visitor applied to each operation node before printing.
86
98
  */
87
99
  transformer?: ast.Visitor;
88
100
  /**
89
- * Additional generators alongside the default generators.
101
+ * Custom generators that run alongside the built-in Cypress generators.
90
102
  */
91
103
  generators?: Array<Generator<PluginCypress>>;
92
104
  } & ParamsTypeOptions;
@@ -95,7 +107,7 @@ type ResolvedOptions = {
95
107
  exclude: Array<Exclude>;
96
108
  include: Array<Include> | undefined;
97
109
  override: Array<Override<ResolvedOptions>>;
98
- group: Group | undefined;
110
+ group: Group | null;
99
111
  baseURL: Options['baseURL'] | undefined;
100
112
  dataReturnType: NonNullable<Options['dataReturnType']>;
101
113
  pathParamsType: NonNullable<NonNullable<Options['pathParamsType']>>;
@@ -126,7 +138,7 @@ type Props = {
126
138
  * TypeScript resolver for resolving param/data/response type names
127
139
  */
128
140
  resolver: ResolverTs;
129
- baseURL: string | undefined;
141
+ baseURL: string | null | undefined;
130
142
  dataReturnType: PluginCypress['resolvedOptions']['dataReturnType'];
131
143
  paramsCasing: PluginCypress['resolvedOptions']['paramsCasing'];
132
144
  paramsType: PluginCypress['resolvedOptions']['paramsType'];
@@ -144,27 +156,39 @@ declare function Request({
144
156
  }: Props): KubbReactNode;
145
157
  //#endregion
146
158
  //#region src/generators/cypressGenerator.d.ts
159
+ /**
160
+ * Built-in generator for `@kubb/plugin-cypress`. Emits one typed
161
+ * `cy.request()` wrapper per OpenAPI operation, ready to call inside Cypress
162
+ * test specs and custom commands.
163
+ */
147
164
  declare const cypressGenerator: _$_kubb_core0.Generator<PluginCypress, unknown>;
148
165
  //#endregion
149
166
  //#region src/plugin.d.ts
150
167
  /**
151
- * Canonical plugin name for `@kubb/plugin-cypress`, used to identify the plugin
152
- * in driver lookups and warnings.
168
+ * Canonical plugin name for `@kubb/plugin-cypress`. Used for driver lookups and
169
+ * cross-plugin dependency references.
153
170
  */
154
171
  declare const pluginCypressName = "plugin-cypress";
155
172
  /**
156
- * The `@kubb/plugin-cypress` plugin factory.
157
- *
158
- * Generates Cypress `cy.request()` test functions from an OpenAPI/AST `RootNode`.
159
- * Walks operations, delegates rendering to the active generators,
160
- * and writes barrel files based on `output.barrelType`.
173
+ * Generates one typed `cy.request()` wrapper per OpenAPI operation. Each helper
174
+ * has typed path params, body, query, and a typed response, so failing API
175
+ * calls in Cypress show up at compile time instead of inside the test runner.
161
176
  *
162
177
  * @example
163
178
  * ```ts
164
- * import pluginCypress from '@kubb/plugin-cypress'
179
+ * import { defineConfig } from 'kubb'
180
+ * import { pluginTs } from '@kubb/plugin-ts'
181
+ * import { pluginCypress } from '@kubb/plugin-cypress'
165
182
  *
166
183
  * export default defineConfig({
167
- * plugins: [pluginCypress({ output: { path: 'cypress' } })],
184
+ * input: { path: './petStore.yaml' },
185
+ * output: { path: './src/gen' },
186
+ * plugins: [
187
+ * pluginTs(),
188
+ * pluginCypress({
189
+ * output: { path: './cypress' },
190
+ * }),
191
+ * ],
168
192
  * })
169
193
  * ```
170
194
  */
@@ -172,12 +196,16 @@ declare const pluginCypress: (options?: Options | undefined) => _$_kubb_core0.Pl
172
196
  //#endregion
173
197
  //#region src/resolvers/resolverCypress.d.ts
174
198
  /**
175
- * Naming convention resolver for Cypress plugin.
199
+ * Default resolver used by `@kubb/plugin-cypress`. Decides the names and file
200
+ * paths for every generated `cy.request()` wrapper. Functions and files use
201
+ * camelCase, matching the convention from `@kubb/plugin-client`.
176
202
  *
177
- * Provides default naming helpers using camelCase for functions and file paths.
203
+ * @example Resolve a helper name
204
+ * ```ts
205
+ * import { resolverCypress } from '@kubb/plugin-cypress'
178
206
  *
179
- * @example
180
- * `resolverCypress.default('list pets', 'function') // → 'listPets'`
207
+ * resolverCypress.default('list pets', 'function') // 'listPets'
208
+ * ```
181
209
  */
182
210
  declare const resolverCypress: ResolverCypress;
183
211
  //#endregion
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import "./chunk--u3MIqq1.js";
2
2
  import { ast, defineGenerator, definePlugin, defineResolver } from "@kubb/core";
3
3
  import { functionPrinter, pluginTsName } from "@kubb/plugin-ts";
4
- import { File, Function, jsxRenderer } from "@kubb/renderer-jsx";
4
+ import { File, Function, jsxRendererSync } from "@kubb/renderer-jsx";
5
5
  import { jsx, jsxs } from "@kubb/renderer-jsx/jsx-runtime";
6
6
  //#region ../../internals/utils/src/casing.ts
7
7
  /**
@@ -214,16 +214,16 @@ var URLPath = class {
214
214
  get object() {
215
215
  return this.toObject();
216
216
  }
217
- /** Returns a map of path parameter names, or `undefined` when the path has no parameters.
217
+ /** Returns a map of path parameter names, or `null` when the path has no parameters.
218
218
  *
219
219
  * @example
220
220
  * ```ts
221
221
  * new URLPath('/pet/{petId}').params // { petId: 'petId' }
222
- * new URLPath('/pet').params // undefined
222
+ * new URLPath('/pet').params // null
223
223
  * ```
224
224
  */
225
225
  get params() {
226
- return this.getParams();
226
+ return this.toParamsObject();
227
227
  }
228
228
  #transformParam(raw) {
229
229
  const param = isValidVarName(raw) ? raw : camelCase(raw);
@@ -241,7 +241,7 @@ var URLPath = class {
241
241
  toObject({ type = "path", replacer, stringify } = {}) {
242
242
  const object = {
243
243
  url: type === "path" ? this.toURLPath() : this.toTemplateString({ replacer }),
244
- params: this.getParams()
244
+ params: this.toParamsObject()
245
245
  };
246
246
  if (stringify) {
247
247
  if (type === "template") return JSON.stringify(object).replaceAll("'", "").replaceAll(`"`, "");
@@ -257,12 +257,13 @@ var URLPath = class {
257
257
  * @example
258
258
  * new URLPath('/pet/{petId}').toTemplateString() // '`/pet/${petId}`'
259
259
  */
260
- toTemplateString({ prefix = "", replacer } = {}) {
261
- return `\`${prefix}${this.path.split(/\{([^}]+)\}/).map((part, i) => {
260
+ toTemplateString({ prefix, replacer } = {}) {
261
+ const result = this.path.split(/\{([^}]+)\}/).map((part, i) => {
262
262
  if (i % 2 === 0) return part;
263
263
  const param = this.#transformParam(part);
264
264
  return `\${${replacer ? replacer(param) : param}}`;
265
- }).join("")}\``;
265
+ }).join("");
266
+ return `\`${prefix ?? ""}${result}\``;
266
267
  }
267
268
  /**
268
269
  * Extracts all `{param}` segments from the path and returns them as a key-value map.
@@ -271,17 +272,17 @@ var URLPath = class {
271
272
  *
272
273
  * @example
273
274
  * ```ts
274
- * new URLPath('/pet/{petId}/tag/{tagId}').getParams()
275
+ * new URLPath('/pet/{petId}/tag/{tagId}').toParamsObject()
275
276
  * // { petId: 'petId', tagId: 'tagId' }
276
277
  * ```
277
278
  */
278
- getParams(replacer) {
279
+ toParamsObject(replacer) {
279
280
  const params = {};
280
281
  this.#eachParam((_raw, param) => {
281
282
  const key = replacer ? replacer(param) : param;
282
283
  params[key] = key;
283
284
  });
284
- return Object.keys(params).length > 0 ? params : void 0;
285
+ return Object.keys(params).length > 0 ? params : null;
285
286
  }
286
287
  /** Converts the OpenAPI path to Express-style colon syntax.
287
288
  *
@@ -295,6 +296,63 @@ var URLPath = class {
295
296
  }
296
297
  };
297
298
  //#endregion
299
+ //#region ../../internals/shared/src/operation.ts
300
+ function getOperationParameters(node, options = {}) {
301
+ const params = ast.caseParams(node.parameters, options.paramsCasing);
302
+ return {
303
+ path: params.filter((param) => param.in === "path"),
304
+ query: params.filter((param) => param.in === "query"),
305
+ header: params.filter((param) => param.in === "header"),
306
+ cookie: params.filter((param) => param.in === "cookie")
307
+ };
308
+ }
309
+ function getStatusCodeNumber(statusCode) {
310
+ const code = Number(statusCode);
311
+ return Number.isNaN(code) ? null : code;
312
+ }
313
+ function isErrorStatusCode(statusCode) {
314
+ const code = getStatusCodeNumber(statusCode);
315
+ return code !== null && code >= 400;
316
+ }
317
+ function resolveErrorNames(node, resolver) {
318
+ return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
319
+ }
320
+ function resolveStatusCodeNames(node, resolver) {
321
+ return node.responses.map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
322
+ }
323
+ const typeNamesByResolver = /* @__PURE__ */ new WeakMap();
324
+ function resolveOperationTypeNames(node, resolver, options = {}) {
325
+ const cacheKey = `${node.operationId}\0${options.paramsCasing ?? ""}\0${options.order ?? ""}\0${options.responseStatusNames ?? ""}\0${(options.exclude ?? []).join(",")}`;
326
+ let byResolver = typeNamesByResolver.get(resolver);
327
+ if (byResolver) {
328
+ const cached = byResolver.get(cacheKey);
329
+ if (cached) return cached;
330
+ } else {
331
+ byResolver = /* @__PURE__ */ new Map();
332
+ typeNamesByResolver.set(resolver, byResolver);
333
+ }
334
+ const { path, query, header } = getOperationParameters(node, { paramsCasing: options.paramsCasing });
335
+ const responseStatusNames = options.responseStatusNames === "error" ? resolveErrorNames(node, resolver) : options.responseStatusNames === false ? [] : resolveStatusCodeNames(node, resolver);
336
+ const exclude = new Set(options.exclude ?? []);
337
+ const paramNames = [
338
+ ...path.map((param) => resolver.resolvePathParamsName(node, param)),
339
+ ...query.map((param) => resolver.resolveQueryParamsName(node, param)),
340
+ ...header.map((param) => resolver.resolveHeaderParamsName(node, param))
341
+ ];
342
+ const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null, resolver.resolveResponseName(node)];
343
+ const result = (options.order === "body-response-first" ? [
344
+ ...bodyAndResponseNames,
345
+ ...paramNames,
346
+ ...responseStatusNames
347
+ ] : [
348
+ ...paramNames,
349
+ ...bodyAndResponseNames,
350
+ ...responseStatusNames
351
+ ]).filter((name) => Boolean(name) && !exclude.has(name));
352
+ byResolver.set(cacheKey, result);
353
+ return result;
354
+ }
355
+ //#endregion
298
356
  //#region src/components/Request.tsx
299
357
  const declarationPrinter = functionPrinter({ mode: "declaration" });
300
358
  function Request({ baseURL = "", name, dataReturnType, resolver, node, paramsType, pathParamsType, paramsCasing }) {
@@ -315,24 +373,24 @@ function Request({ baseURL = "", name, dataReturnType, resolver, node, paramsTyp
315
373
  const paramsSignature = declarationPrinter.print(paramsNode) ?? "";
316
374
  const responseType = resolver.resolveResponseName(node);
317
375
  const returnType = dataReturnType === "data" ? `Cypress.Chainable<${responseType}>` : `Cypress.Chainable<Cypress.Response<${responseType}>>`;
318
- const casedPathParams = ast.caseParams(node.parameters.filter((p) => p.in === "path"), paramsCasing);
376
+ const casedPathParams = getOperationParameters(node, { paramsCasing }).path;
319
377
  const pathParamNameMap = new Map(casedPathParams.map((p) => [camelCase(p.name), p.name]));
320
378
  const urlTemplate = new URLPath(node.path, { casing: paramsCasing }).toTemplateString({
321
379
  prefix: baseURL,
322
380
  replacer: (param) => pathParamNameMap.get(camelCase(param)) ?? param
323
381
  });
324
382
  const requestOptions = [`method: '${node.method}'`, `url: ${urlTemplate}`];
325
- const queryParams = node.parameters.filter((p) => p.in === "query");
383
+ const queryParams = getOperationParameters(node).query;
326
384
  if (queryParams.length > 0) {
327
- const casedQueryParams = ast.caseParams(queryParams, paramsCasing);
385
+ const casedQueryParams = getOperationParameters(node, { paramsCasing }).query;
328
386
  if (casedQueryParams.some((p, i) => p.name !== queryParams[i].name)) {
329
387
  const pairs = queryParams.map((orig, i) => `${orig.name}: params.${casedQueryParams[i].name}`).join(", ");
330
388
  requestOptions.push(`qs: params ? { ${pairs} } : undefined`);
331
389
  } else requestOptions.push("qs: params");
332
390
  }
333
- const headerParams = node.parameters.filter((p) => p.in === "header");
391
+ const headerParams = getOperationParameters(node).header;
334
392
  if (headerParams.length > 0) {
335
- const casedHeaderParams = ast.caseParams(headerParams, paramsCasing);
393
+ const casedHeaderParams = getOperationParameters(node, { paramsCasing }).header;
336
394
  if (casedHeaderParams.some((p, i) => p.name !== headerParams[i].name)) {
337
395
  const pairs = headerParams.map((orig, i) => `'${orig.name}': headers.${casedHeaderParams[i].name}`).join(", ");
338
396
  requestOptions.push(`headers: headers ? { ${pairs} } : undefined`);
@@ -359,26 +417,21 @@ function Request({ baseURL = "", name, dataReturnType, resolver, node, paramsTyp
359
417
  }
360
418
  //#endregion
361
419
  //#region src/generators/cypressGenerator.tsx
420
+ /**
421
+ * Built-in generator for `@kubb/plugin-cypress`. Emits one typed
422
+ * `cy.request()` wrapper per OpenAPI operation, ready to call inside Cypress
423
+ * test specs and custom commands.
424
+ */
362
425
  const cypressGenerator = defineGenerator({
363
426
  name: "cypress",
364
- renderer: jsxRenderer,
427
+ renderer: jsxRendererSync,
365
428
  operation(node, ctx) {
366
- const { adapter, config, resolver, driver, root } = ctx;
429
+ const { config, resolver, driver, root } = ctx;
367
430
  const { output, baseURL, dataReturnType, paramsCasing, paramsType, pathParamsType, group } = ctx.options;
368
431
  const pluginTs = driver.getPlugin(pluginTsName);
369
432
  if (!pluginTs) return null;
370
433
  const tsResolver = driver.getResolver(pluginTsName);
371
- const casedParams = ast.caseParams(node.parameters, paramsCasing);
372
- const pathParams = casedParams.filter((p) => p.in === "path");
373
- const queryParams = casedParams.filter((p) => p.in === "query");
374
- const headerParams = casedParams.filter((p) => p.in === "header");
375
- const importedTypeNames = [
376
- ...pathParams.map((p) => tsResolver.resolvePathParamsName(node, p)),
377
- ...queryParams.map((p) => tsResolver.resolveQueryParamsName(node, p)),
378
- ...headerParams.map((p) => tsResolver.resolveHeaderParamsName(node, p)),
379
- node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : void 0,
380
- tsResolver.resolveResponseName(node)
381
- ].filter(Boolean);
434
+ const importedTypeNames = resolveOperationTypeNames(node, tsResolver, { paramsCasing });
382
435
  const meta = {
383
436
  name: resolver.resolveName(node.operationId),
384
437
  file: resolver.resolveFile({
@@ -389,7 +442,7 @@ const cypressGenerator = defineGenerator({
389
442
  }, {
390
443
  root,
391
444
  output,
392
- group
445
+ group: group ?? void 0
393
446
  }),
394
447
  fileTs: tsResolver.resolveFile({
395
448
  name: node.operationId,
@@ -399,23 +452,31 @@ const cypressGenerator = defineGenerator({
399
452
  }, {
400
453
  root,
401
454
  output: pluginTs.options?.output ?? output,
402
- group: pluginTs.options?.group
455
+ group: pluginTs.options?.group ?? void 0
403
456
  })
404
457
  };
405
458
  return /* @__PURE__ */ jsxs(File, {
406
459
  baseName: meta.file.baseName,
407
460
  path: meta.file.path,
408
461
  meta: meta.file.meta,
409
- banner: resolver.resolveBanner(adapter.inputNode, {
462
+ banner: resolver.resolveBanner(ctx.meta, {
410
463
  output,
411
- config
464
+ config,
465
+ file: {
466
+ path: meta.file.path,
467
+ baseName: meta.file.baseName
468
+ }
412
469
  }),
413
- footer: resolver.resolveFooter(adapter.inputNode, {
470
+ footer: resolver.resolveFooter(ctx.meta, {
414
471
  output,
415
- config
472
+ config,
473
+ file: {
474
+ path: meta.file.path,
475
+ baseName: meta.file.baseName
476
+ }
416
477
  }),
417
478
  children: [meta.fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
418
- name: Array.from(new Set(importedTypeNames)),
479
+ name: importedTypeNames,
419
480
  root: meta.file.path,
420
481
  path: meta.fileTs.path,
421
482
  isTypeOnly: true
@@ -435,43 +496,57 @@ const cypressGenerator = defineGenerator({
435
496
  //#endregion
436
497
  //#region src/resolvers/resolverCypress.ts
437
498
  /**
438
- * Naming convention resolver for Cypress plugin.
499
+ * Default resolver used by `@kubb/plugin-cypress`. Decides the names and file
500
+ * paths for every generated `cy.request()` wrapper. Functions and files use
501
+ * camelCase, matching the convention from `@kubb/plugin-client`.
439
502
  *
440
- * Provides default naming helpers using camelCase for functions and file paths.
503
+ * @example Resolve a helper name
504
+ * ```ts
505
+ * import { resolverCypress } from '@kubb/plugin-cypress'
441
506
  *
442
- * @example
443
- * `resolverCypress.default('list pets', 'function') // → 'listPets'`
507
+ * resolverCypress.default('list pets', 'function') // 'listPets'
508
+ * ```
444
509
  */
445
- const resolverCypress = defineResolver((ctx) => ({
510
+ const resolverCypress = defineResolver(() => ({
446
511
  name: "default",
447
512
  pluginName: "plugin-cypress",
448
513
  default(name, type) {
449
514
  return camelCase(name, { isFile: type === "file" });
450
515
  },
451
516
  resolveName(name) {
452
- return ctx.default(name, "function");
517
+ return this.default(name, "function");
518
+ },
519
+ resolvePathName(name, type) {
520
+ return this.default(name, type);
453
521
  }
454
522
  }));
455
523
  //#endregion
456
524
  //#region src/plugin.ts
457
525
  /**
458
- * Canonical plugin name for `@kubb/plugin-cypress`, used to identify the plugin
459
- * in driver lookups and warnings.
526
+ * Canonical plugin name for `@kubb/plugin-cypress`. Used for driver lookups and
527
+ * cross-plugin dependency references.
460
528
  */
461
529
  const pluginCypressName = "plugin-cypress";
462
530
  /**
463
- * The `@kubb/plugin-cypress` plugin factory.
464
- *
465
- * Generates Cypress `cy.request()` test functions from an OpenAPI/AST `RootNode`.
466
- * Walks operations, delegates rendering to the active generators,
467
- * and writes barrel files based on `output.barrelType`.
531
+ * Generates one typed `cy.request()` wrapper per OpenAPI operation. Each helper
532
+ * has typed path params, body, query, and a typed response, so failing API
533
+ * calls in Cypress show up at compile time instead of inside the test runner.
468
534
  *
469
535
  * @example
470
536
  * ```ts
471
- * import pluginCypress from '@kubb/plugin-cypress'
537
+ * import { defineConfig } from 'kubb'
538
+ * import { pluginTs } from '@kubb/plugin-ts'
539
+ * import { pluginCypress } from '@kubb/plugin-cypress'
472
540
  *
473
541
  * export default defineConfig({
474
- * plugins: [pluginCypress({ output: { path: 'cypress' } })],
542
+ * input: { path: './petStore.yaml' },
543
+ * output: { path: './src/gen' },
544
+ * plugins: [
545
+ * pluginTs(),
546
+ * pluginCypress({
547
+ * output: { path: './cypress' },
548
+ * }),
549
+ * ],
475
550
  * })
476
551
  * ```
477
552
  */
@@ -486,7 +561,7 @@ const pluginCypress = definePlugin((options) => {
486
561
  if (group.type === "path") return `${ctx.group.split("/")[1]}`;
487
562
  return `${camelCase(ctx.group)}Requests`;
488
563
  }
489
- } : void 0;
564
+ } : null;
490
565
  return {
491
566
  name: pluginCypressName,
492
567
  options,