@kubb/plugin-cypress 5.0.0-alpha.3 → 5.0.0-alpha.31

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/plugin-cypress",
3
- "version": "5.0.0-alpha.3",
3
+ "version": "5.0.0-alpha.31",
4
4
  "description": "Cypress test generator plugin for Kubb, creating end-to-end tests from OpenAPI specifications for automated API testing.",
5
5
  "keywords": [
6
6
  "cypress",
@@ -34,33 +34,10 @@
34
34
  "import": "./dist/index.js",
35
35
  "require": "./dist/index.cjs"
36
36
  },
37
- "./components": {
38
- "import": "./dist/components.js",
39
- "require": "./dist/components.cjs"
40
- },
41
- "./generators": {
42
- "import": "./dist/generators.js",
43
- "require": "./dist/generators.cjs"
44
- },
45
37
  "./package.json": "./package.json"
46
38
  },
47
39
  "types": "./dist/index.d.ts",
48
- "typesVersions": {
49
- "*": {
50
- "utils": [
51
- "./dist/utils.d.ts"
52
- ],
53
- "hooks": [
54
- "./dist/hooks.d.ts"
55
- ],
56
- "components": [
57
- "./dist/components.d.ts"
58
- ],
59
- "generators": [
60
- "./dist/generators.d.ts"
61
- ]
62
- }
63
- },
40
+ "typesVersions": {},
64
41
  "files": [
65
42
  "src",
66
43
  "dist",
@@ -76,11 +53,10 @@
76
53
  }
77
54
  ],
78
55
  "dependencies": {
79
- "@kubb/react-fabric": "0.13.3",
80
- "@kubb/core": "5.0.0-alpha.3",
81
- "@kubb/oas": "5.0.0-alpha.3",
82
- "@kubb/plugin-oas": "5.0.0-alpha.3",
83
- "@kubb/plugin-ts": "5.0.0-alpha.3"
56
+ "@kubb/react-fabric": "0.15.1",
57
+ "@kubb/ast": "5.0.0-alpha.31",
58
+ "@kubb/plugin-ts": "5.0.0-alpha.31",
59
+ "@kubb/core": "5.0.0-alpha.31"
84
60
  },
85
61
  "engines": {
86
62
  "node": ">=22"
@@ -1,8 +1,9 @@
1
- import { URLPath } from '@internals/utils'
2
- import { type HttpMethod, isAllOptional, isOptional } from '@kubb/oas'
3
- import type { OperationSchemas } from '@kubb/plugin-oas'
4
- import { getPathParams } from '@kubb/plugin-oas/utils'
5
- import { File, Function, FunctionParams } from '@kubb/react-fabric'
1
+ import { camelCase, URLPath } from '@internals/utils'
2
+ import { caseParams, createFunctionParameter, createOperationParams, createTypeNode } from '@kubb/ast'
3
+ import type { OperationNode } from '@kubb/ast/types'
4
+ import type { ResolverTs } from '@kubb/plugin-ts'
5
+ import { functionPrinter } from '@kubb/plugin-ts'
6
+ import { File, Function } from '@kubb/react-fabric'
6
7
  import type { FabricReactNode } from '@kubb/react-fabric/types'
7
8
  import type { PluginCypress } from '../types.ts'
8
9
 
@@ -11,137 +12,100 @@ type Props = {
11
12
  * Name of the function
12
13
  */
13
14
  name: string
14
- typeSchemas: OperationSchemas
15
- url: string
15
+ /**
16
+ * AST operation node
17
+ */
18
+ node: OperationNode
19
+ /**
20
+ * TypeScript resolver for resolving param/data/response type names
21
+ */
22
+ resolver: ResolverTs
16
23
  baseURL: string | undefined
17
24
  dataReturnType: PluginCypress['resolvedOptions']['dataReturnType']
18
25
  paramsCasing: PluginCypress['resolvedOptions']['paramsCasing']
19
26
  paramsType: PluginCypress['resolvedOptions']['paramsType']
20
27
  pathParamsType: PluginCypress['resolvedOptions']['pathParamsType']
21
- method: HttpMethod
22
- }
23
-
24
- type GetParamsProps = {
25
- paramsCasing: PluginCypress['resolvedOptions']['paramsCasing']
26
- paramsType: PluginCypress['resolvedOptions']['paramsType']
27
- pathParamsType: PluginCypress['resolvedOptions']['pathParamsType']
28
- typeSchemas: OperationSchemas
29
28
  }
30
29
 
31
- function getParams({ paramsType, paramsCasing, pathParamsType, typeSchemas }: GetParamsProps) {
32
- if (paramsType === 'object') {
33
- const pathParams = getPathParams(typeSchemas.pathParams, { typed: true, casing: paramsCasing })
34
-
35
- return FunctionParams.factory({
36
- data: {
37
- mode: 'object',
38
- children: {
39
- ...pathParams,
40
- data: typeSchemas.request?.name
41
- ? {
42
- type: typeSchemas.request?.name,
43
- optional: isOptional(typeSchemas.request?.schema),
44
- }
45
- : undefined,
46
- params: typeSchemas.queryParams?.name
47
- ? {
48
- type: typeSchemas.queryParams?.name,
49
- optional: isOptional(typeSchemas.queryParams?.schema),
50
- }
51
- : undefined,
52
- headers: typeSchemas.headerParams?.name
53
- ? {
54
- type: typeSchemas.headerParams?.name,
55
- optional: isOptional(typeSchemas.headerParams?.schema),
56
- }
57
- : undefined,
58
- },
59
- },
60
- options: {
61
- type: 'Partial<Cypress.RequestOptions>',
62
- default: '{}',
63
- },
64
- })
65
- }
66
-
67
- return FunctionParams.factory({
68
- pathParams: typeSchemas.pathParams?.name
69
- ? {
70
- mode: pathParamsType === 'object' ? 'object' : 'inlineSpread',
71
- children: getPathParams(typeSchemas.pathParams, { typed: true, casing: paramsCasing }),
72
- default: isAllOptional(typeSchemas.pathParams?.schema) ? '{}' : undefined,
73
- }
74
- : undefined,
75
- data: typeSchemas.request?.name
76
- ? {
77
- type: typeSchemas.request?.name,
78
- optional: isOptional(typeSchemas.request?.schema),
79
- }
80
- : undefined,
81
- params: typeSchemas.queryParams?.name
82
- ? {
83
- type: typeSchemas.queryParams?.name,
84
- optional: isOptional(typeSchemas.queryParams?.schema),
85
- }
86
- : undefined,
87
- headers: typeSchemas.headerParams?.name
88
- ? {
89
- type: typeSchemas.headerParams?.name,
90
- optional: isOptional(typeSchemas.headerParams?.schema),
91
- }
92
- : undefined,
93
- options: {
94
- type: 'Partial<Cypress.RequestOptions>',
95
- default: '{}',
96
- },
30
+ const declarationPrinter = functionPrinter({ mode: 'declaration' })
31
+
32
+ export function Request({ baseURL = '', name, dataReturnType, resolver, node, paramsType, pathParamsType, paramsCasing }: Props): FabricReactNode {
33
+ const paramsNode = createOperationParams(node, {
34
+ paramsType,
35
+ pathParamsType,
36
+ paramsCasing,
37
+ resolver,
38
+ extraParams: [
39
+ createFunctionParameter({ name: 'options', type: createTypeNode({ variant: 'reference', name: 'Partial<Cypress.RequestOptions>' }), default: '{}' }),
40
+ ],
97
41
  })
98
- }
99
-
100
- export function Request({ baseURL = '', name, dataReturnType, typeSchemas, url, method, paramsType, paramsCasing, pathParamsType }: Props): FabricReactNode {
101
- const path = new URLPath(url, { casing: paramsCasing })
102
-
103
- const params = getParams({ paramsType, paramsCasing, pathParamsType, typeSchemas })
42
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
104
43
 
105
- const returnType =
106
- dataReturnType === 'data' ? `Cypress.Chainable<${typeSchemas.response.name}>` : `Cypress.Chainable<Cypress.Response<${typeSchemas.response.name}>>`
44
+ const responseType = resolver.resolveResponseName(node)
45
+ const returnType = dataReturnType === 'data' ? `Cypress.Chainable<${responseType}>` : `Cypress.Chainable<Cypress.Response<${responseType}>>`
107
46
 
108
- // Build the URL template string - this will convert /pets/:petId to /pets/${petId}
109
- const urlTemplate = path.toTemplateString({ prefix: baseURL })
110
-
111
- // Build request options object
112
- const requestOptions: string[] = [`method: '${method}'`, `url: ${urlTemplate}`]
47
+ const casedPathParams = caseParams(
48
+ node.parameters.filter((p) => p.in === 'path'),
49
+ paramsCasing,
50
+ )
51
+ // Build a lookup keyed by camelCase-normalized name so that path-template names
52
+ // (e.g. `{pet_id}`) correctly resolve to the function-parameter name (`petId`)
53
+ // even when the OpenAPI spec has inconsistent casing between the two.
54
+ const pathParamNameMap = new Map(casedPathParams.map((p) => [camelCase(p.name), p.name]))
55
+
56
+ const urlPath = new URLPath(node.path, { casing: paramsCasing })
57
+ const urlTemplate = urlPath.toTemplateString({
58
+ prefix: baseURL,
59
+ replacer: (param) => pathParamNameMap.get(camelCase(param)) ?? param,
60
+ })
113
61
 
114
- // Add query params if they exist
115
- if (typeSchemas.queryParams?.name) {
116
- requestOptions.push('qs: params')
62
+ const requestOptions: string[] = [`method: '${node.method}'`, `url: ${urlTemplate}`]
63
+
64
+ const queryParams = node.parameters.filter((p) => p.in === 'query')
65
+ if (queryParams.length > 0) {
66
+ const casedQueryParams = caseParams(queryParams, paramsCasing)
67
+ // When paramsCasing renames query params (e.g. page_size → pageSize), we must remap
68
+ // the camelCase keys back to the original API names before passing them to `qs`.
69
+ const needsQsTransform = casedQueryParams.some((p, i) => p.name !== queryParams[i]!.name)
70
+ if (needsQsTransform) {
71
+ const pairs = queryParams.map((orig, i) => `${orig.name}: params.${casedQueryParams[i]!.name}`).join(', ')
72
+ requestOptions.push(`qs: params ? { ${pairs} } : undefined`)
73
+ } else {
74
+ requestOptions.push('qs: params')
75
+ }
117
76
  }
118
77
 
119
- // Add headers if they exist
120
- if (typeSchemas.headerParams?.name) {
121
- requestOptions.push('headers')
78
+ const headerParams = node.parameters.filter((p) => p.in === 'header')
79
+ if (headerParams.length > 0) {
80
+ const casedHeaderParams = caseParams(headerParams, paramsCasing)
81
+ // When paramsCasing renames header params (e.g. x-api-key → xApiKey), we must remap
82
+ // the camelCase keys back to the original API names before passing them to `headers`.
83
+ const needsHeaderTransform = casedHeaderParams.some((p, i) => p.name !== headerParams[i]!.name)
84
+ if (needsHeaderTransform) {
85
+ const pairs = headerParams.map((orig, i) => `'${orig.name}': headers.${casedHeaderParams[i]!.name}`).join(', ')
86
+ requestOptions.push(`headers: headers ? { ${pairs} } : undefined`)
87
+ } else {
88
+ requestOptions.push('headers')
89
+ }
122
90
  }
123
91
 
124
- // Add body if request schema exists
125
- if (typeSchemas.request?.name) {
92
+ if (node.requestBody?.schema) {
126
93
  requestOptions.push('body: data')
127
94
  }
128
95
 
129
- // Spread additional Cypress options
130
96
  requestOptions.push('...options')
131
97
 
132
98
  return (
133
99
  <File.Source name={name} isIndexable isExportable>
134
- <Function name={name} export params={params.toConstructor()} returnType={returnType}>
100
+ <Function name={name} export params={paramsSignature} returnType={returnType}>
135
101
  {dataReturnType === 'data'
136
- ? `return cy.request<${typeSchemas.response.name}>({
102
+ ? `return cy.request<${responseType}>({
137
103
  ${requestOptions.join(',\n ')}
138
104
  }).then((res) => res.body)`
139
- : `return cy.request<${typeSchemas.response.name}>({
105
+ : `return cy.request<${responseType}>({
140
106
  ${requestOptions.join(',\n ')}
141
107
  })`}
142
108
  </Function>
143
109
  </File.Source>
144
110
  )
145
111
  }
146
-
147
- Request.getParams = getParams
@@ -1,64 +1,69 @@
1
- import { usePluginManager } from '@kubb/core/hooks'
2
- import { createReactGenerator } from '@kubb/plugin-oas/generators'
3
- import { useOas, useOperationManager } from '@kubb/plugin-oas/hooks'
4
- import { getBanner, getFooter } from '@kubb/plugin-oas/utils'
1
+ import { caseParams } from '@kubb/ast'
2
+ import { defineGenerator } from '@kubb/core'
5
3
  import { pluginTsName } from '@kubb/plugin-ts'
6
4
  import { File } from '@kubb/react-fabric'
7
- import { Request } from '../components'
8
- import type { PluginCypress } from '../types'
5
+ import { Request } from '../components/Request.tsx'
6
+ import type { PluginCypress } from '../types.ts'
9
7
 
10
- export const cypressGenerator = createReactGenerator<PluginCypress>({
8
+ export const cypressGenerator = defineGenerator<PluginCypress>({
11
9
  name: 'cypress',
12
- Operation({ operation, generator, plugin }) {
13
- const {
14
- options: { output, baseURL, dataReturnType, paramsCasing, paramsType, pathParamsType },
15
- } = plugin
16
- const pluginManager = usePluginManager()
10
+ operation(node, options) {
11
+ const { adapter, config, resolver, driver, root } = this
12
+ const { output, baseURL, dataReturnType, paramsCasing, paramsType, pathParamsType, group } = options
17
13
 
18
- const oas = useOas()
19
- const { getSchemas, getName, getFile } = useOperationManager(generator)
14
+ const pluginTs = driver.getPlugin(pluginTsName)
20
15
 
21
- const request = {
22
- name: getName(operation, { type: 'function' }),
23
- file: getFile(operation),
16
+ if (!pluginTs?.resolver) {
17
+ return null
24
18
  }
25
19
 
26
- const type = {
27
- file: getFile(operation, { pluginName: pluginTsName }),
28
- schemas: getSchemas(operation, { pluginName: pluginTsName, type: 'type' }),
29
- }
20
+ const casedParams = caseParams(node.parameters, paramsCasing)
21
+
22
+ const pathParams = casedParams.filter((p) => p.in === 'path')
23
+ const queryParams = casedParams.filter((p) => p.in === 'query')
24
+ const headerParams = casedParams.filter((p) => p.in === 'header')
25
+
26
+ const importedTypeNames = [
27
+ ...pathParams.map((p) => pluginTs.resolver.resolvePathParamsName(node, p)),
28
+ ...queryParams.map((p) => pluginTs.resolver.resolveQueryParamsName(node, p)),
29
+ ...headerParams.map((p) => pluginTs.resolver.resolveHeaderParamsName(node, p)),
30
+ node.requestBody?.schema ? pluginTs.resolver.resolveDataName(node) : undefined,
31
+ pluginTs.resolver.resolveResponseName(node),
32
+ ].filter(Boolean)
33
+
34
+ const meta = {
35
+ name: resolver.resolveName(node.operationId),
36
+ file: resolver.resolveFile({ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path }, { root, output, group }),
37
+ fileTs: pluginTs.resolver.resolveFile(
38
+ { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
39
+ {
40
+ root,
41
+ output: pluginTs.options?.output ?? output,
42
+ group: pluginTs.options?.group,
43
+ },
44
+ ),
45
+ } as const
30
46
 
31
47
  return (
32
48
  <File
33
- baseName={request.file.baseName}
34
- path={request.file.path}
35
- meta={request.file.meta}
36
- banner={getBanner({ oas, output, config: pluginManager.config })}
37
- footer={getFooter({ oas, output })}
49
+ baseName={meta.file.baseName}
50
+ path={meta.file.path}
51
+ meta={meta.file.meta}
52
+ banner={resolver.resolveBanner(adapter.rootNode, { output, config })}
53
+ footer={resolver.resolveFooter(adapter.rootNode, { output, config })}
38
54
  >
39
- <File.Import
40
- name={[
41
- type.schemas.request?.name,
42
- type.schemas.response.name,
43
- type.schemas.pathParams?.name,
44
- type.schemas.queryParams?.name,
45
- type.schemas.headerParams?.name,
46
- ...(type.schemas.statusCodes?.map((item) => item.name) || []),
47
- ].filter(Boolean)}
48
- root={request.file.path}
49
- path={type.file.path}
50
- isTypeOnly
51
- />
55
+ {meta.fileTs && importedTypeNames.length > 0 && (
56
+ <File.Import name={Array.from(new Set(importedTypeNames))} root={meta.file.path} path={meta.fileTs.path} isTypeOnly />
57
+ )}
52
58
  <Request
53
- name={request.name}
59
+ name={meta.name}
60
+ node={node}
61
+ resolver={pluginTs.resolver}
54
62
  dataReturnType={dataReturnType}
55
63
  paramsCasing={paramsCasing}
56
64
  paramsType={paramsType}
57
65
  pathParamsType={pathParamsType}
58
- typeSchemas={type.schemas}
59
- method={operation.method}
60
66
  baseURL={baseURL}
61
- url={operation.path}
62
67
  />
63
68
  </File>
64
69
  )
package/src/index.ts CHANGED
@@ -1,2 +1,9 @@
1
+ export { Request } from './components/Request.tsx'
2
+
3
+ export { cypressGenerator } from './generators/cypressGenerator.tsx'
4
+
1
5
  export { pluginCypress, pluginCypressName } from './plugin.ts'
2
- export type { PluginCypress } from './types.ts'
6
+
7
+ export { resolverCypress } from './resolvers/resolverCypress.ts'
8
+
9
+ export type { PluginCypress, ResolverCypress } from './types.ts'
package/src/plugin.ts CHANGED
@@ -1,119 +1,109 @@
1
- import path from 'node:path'
2
1
  import { camelCase } from '@internals/utils'
3
- import { definePlugin, type Group, getBarrelFiles, getMode } from '@kubb/core'
4
- import { OperationGenerator, pluginOasName } from '@kubb/plugin-oas'
2
+ import { createPlugin, type Group, getPreset, mergeGenerators } from '@kubb/core'
5
3
  import { pluginTsName } from '@kubb/plugin-ts'
6
- import { cypressGenerator } from './generators'
4
+ import { version } from '../package.json'
5
+ import { presets } from './presets.ts'
7
6
  import type { PluginCypress } from './types.ts'
8
7
 
8
+ /**
9
+ * Canonical plugin name for `@kubb/plugin-cypress`, used to identify the plugin
10
+ * in driver lookups and warnings.
11
+ */
9
12
  export const pluginCypressName = 'plugin-cypress' satisfies PluginCypress['name']
10
13
 
11
- export const pluginCypress = definePlugin<PluginCypress>((options) => {
14
+ /**
15
+ * The `@kubb/plugin-cypress` plugin factory.
16
+ *
17
+ * Generates Cypress `cy.request()` test functions from an OpenAPI/AST `RootNode`.
18
+ * Walks operations, delegates rendering to the active generators,
19
+ * and writes barrel files based on `output.barrelType`.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * import { pluginCypress } from '@kubb/plugin-cypress'
24
+ *
25
+ * export default defineConfig({
26
+ * plugins: [pluginCypress({ output: { path: 'cypress' } })],
27
+ * })
28
+ * ```
29
+ */
30
+ export const pluginCypress = createPlugin<PluginCypress>((options) => {
12
31
  const {
13
32
  output = { path: 'cypress', barrelType: 'named' },
14
33
  group,
15
- dataReturnType = 'data',
16
34
  exclude = [],
17
35
  include,
18
36
  override = [],
19
- transformers = {},
20
- generators = [cypressGenerator].filter(Boolean),
21
- contentType,
37
+ dataReturnType = 'data',
22
38
  baseURL,
23
39
  paramsCasing,
24
40
  paramsType = 'inline',
25
41
  pathParamsType = paramsType === 'object' ? 'object' : options.pathParamsType || 'inline',
42
+ compatibilityPreset = 'default',
43
+ resolver: userResolver,
44
+ transformer: userTransformer,
45
+ generators: userGenerators = [],
26
46
  } = options
27
47
 
28
- return {
29
- name: pluginCypressName,
30
- options: {
31
- output,
32
- dataReturnType,
33
- group,
34
- baseURL,
48
+ const preset = getPreset({
49
+ preset: compatibilityPreset,
50
+ presets,
51
+ resolver: userResolver,
52
+ transformer: userTransformer,
53
+ generators: userGenerators,
54
+ })
35
55
 
36
- paramsCasing,
37
- paramsType,
38
- pathParamsType,
39
- },
40
- pre: [pluginOasName, pluginTsName].filter(Boolean),
41
- resolvePath(baseName, pathMode, options) {
42
- const root = path.resolve(this.config.root, this.config.output.path)
43
- const mode = pathMode ?? getMode(path.resolve(root, output.path))
44
-
45
- if (mode === 'single') {
46
- /**
47
- * when output is a file then we will always append to the same file(output file), see fileManager.addOrAppend
48
- * Other plugins then need to call addOrAppend instead of just add from the fileManager class
49
- */
50
- return path.resolve(root, output.path)
51
- }
56
+ const generators = preset.generators ?? []
57
+ const mergedGenerator = mergeGenerators(generators)
52
58
 
53
- if (group && (options?.group?.path || options?.group?.tag)) {
54
- const groupName: Group['name'] = group?.name
55
- ? group.name
56
- : (ctx) => {
57
- if (group?.type === 'path') {
58
- return `${ctx.group.split('/')[1]}`
59
- }
60
- return `${camelCase(ctx.group)}Requests`
61
- }
62
-
63
- return path.resolve(
64
- root,
65
- output.path,
66
- groupName({
67
- group: group.type === 'path' ? options.group.path! : options.group.tag!,
68
- }),
69
- baseName,
70
- )
71
- }
72
-
73
- return path.resolve(root, output.path, baseName)
59
+ return {
60
+ name: pluginCypressName,
61
+ version,
62
+ get resolver() {
63
+ return preset.resolver
74
64
  },
75
- resolveName(name, type) {
76
- const resolvedName = camelCase(name, {
77
- isFile: type === 'file',
78
- })
79
-
80
- if (type) {
81
- return transformers?.name?.(resolvedName, type) || resolvedName
82
- }
83
-
84
- return resolvedName
65
+ get transformer() {
66
+ return preset.transformer
85
67
  },
86
- async install() {
87
- const root = path.resolve(this.config.root, this.config.output.path)
88
- const mode = getMode(path.resolve(root, output.path))
89
- const oas = await this.getOas()
90
-
91
- const operationGenerator = new OperationGenerator(this.plugin.options, {
92
- fabric: this.fabric,
93
- oas,
94
- pluginManager: this.pluginManager,
95
- events: this.events,
96
- plugin: this.plugin,
97
- contentType,
68
+ get options() {
69
+ return {
70
+ output,
98
71
  exclude,
99
72
  include,
100
73
  override,
101
- mode,
102
- })
103
-
104
- const files = await operationGenerator.build(...generators)
105
- await this.upsertFile(...files)
106
-
107
- const barrelFiles = await getBarrelFiles(this.fabric.files, {
108
- type: output.barrelType ?? 'named',
109
- root,
110
- output,
111
- meta: {
112
- pluginName: this.plugin.name,
113
- },
114
- })
115
-
116
- await this.upsertFile(...barrelFiles)
74
+ dataReturnType,
75
+ group: group
76
+ ? ({
77
+ ...group,
78
+ name: group.name
79
+ ? group.name
80
+ : (ctx: { group: string }) => {
81
+ if (group.type === 'path') {
82
+ return `${ctx.group.split('/')[1]}`
83
+ }
84
+ return `${camelCase(ctx.group)}Requests`
85
+ },
86
+ } satisfies Group)
87
+ : undefined,
88
+ baseURL,
89
+ paramsCasing,
90
+ paramsType,
91
+ pathParamsType,
92
+ resolver: preset.resolver,
93
+ }
94
+ },
95
+ pre: [pluginTsName].filter(Boolean),
96
+ async schema(node, options) {
97
+ return mergedGenerator.schema?.call(this, node, options)
98
+ },
99
+ async operation(node, options) {
100
+ return mergedGenerator.operation?.call(this, node, options)
101
+ },
102
+ async operations(nodes, options) {
103
+ return mergedGenerator.operations?.call(this, nodes, options)
104
+ },
105
+ async buildStart() {
106
+ await this.openInStudio({ ast: true })
117
107
  },
118
108
  }
119
109
  })
package/src/presets.ts ADDED
@@ -0,0 +1,23 @@
1
+ import { definePresets } from '@kubb/core'
2
+ import { cypressGenerator } from './generators/cypressGenerator.tsx'
3
+ import { resolverCypress } from './resolvers/resolverCypress.ts'
4
+ import type { ResolverCypress } from './types.ts'
5
+
6
+ /**
7
+ * Built-in preset registry for `@kubb/plugin-cypress`.
8
+ *
9
+ * - `default` — uses `resolverCypress` and `cypressGenerator`.
10
+ * - `kubbV4` — uses `resolverCypress` and `cypressGenerator`.
11
+ */
12
+ export const presets = definePresets<ResolverCypress>({
13
+ default: {
14
+ name: 'default',
15
+ resolver: resolverCypress,
16
+ generators: [cypressGenerator],
17
+ },
18
+ kubbV4: {
19
+ name: 'kubbV4',
20
+ resolver: resolverCypress,
21
+ generators: [cypressGenerator],
22
+ },
23
+ })
@@ -0,0 +1,26 @@
1
+ import { camelCase } from '@internals/utils'
2
+ import { defineResolver } from '@kubb/core'
3
+ import type { PluginCypress } from '../types.ts'
4
+
5
+ /**
6
+ * Resolver for `@kubb/plugin-cypress` that provides the default naming
7
+ * and path-resolution helpers used by the plugin.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import { resolverCypress } from '@kubb/plugin-cypress'
12
+ *
13
+ * resolverCypress.default('list pets', 'function') // -> 'listPets'
14
+ * resolverCypress.resolveName('show pet by id') // -> 'showPetById'
15
+ * ```
16
+ */
17
+ export const resolverCypress = defineResolver<PluginCypress>(() => ({
18
+ name: 'default',
19
+ pluginName: 'plugin-cypress',
20
+ default(name, type) {
21
+ return camelCase(name, { isFile: type === 'file' })
22
+ },
23
+ resolveName(name) {
24
+ return this.default(name, 'function')
25
+ },
26
+ }))