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

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.
@@ -1,113 +0,0 @@
1
- import { getOperationParameters } from '@internals/shared'
2
- import { camelCase, URLPath } from '@internals/utils'
3
- import { ast } from '@kubb/core'
4
- import type { ResolverTs } from '@kubb/plugin-ts'
5
- import { functionPrinter } from '@kubb/plugin-ts'
6
- import { File, Function } from '@kubb/renderer-jsx'
7
- import type { KubbReactNode } from '@kubb/renderer-jsx/types'
8
- import type { PluginCypress } from '../types.ts'
9
-
10
- type Props = {
11
- /**
12
- * Name of the function
13
- */
14
- name: string
15
- /**
16
- * AST operation node
17
- */
18
- node: ast.OperationNode
19
- /**
20
- * TypeScript resolver for resolving param/data/response type names
21
- */
22
- resolver: ResolverTs
23
- baseURL: string | null | undefined
24
- dataReturnType: PluginCypress['resolvedOptions']['dataReturnType']
25
- paramsCasing: PluginCypress['resolvedOptions']['paramsCasing']
26
- paramsType: PluginCypress['resolvedOptions']['paramsType']
27
- pathParamsType: PluginCypress['resolvedOptions']['pathParamsType']
28
- }
29
-
30
- const declarationPrinter = functionPrinter({ mode: 'declaration' })
31
-
32
- export function Request({ baseURL = '', name, dataReturnType, resolver, node, paramsType, pathParamsType, paramsCasing }: Props): KubbReactNode {
33
- if (!ast.isHttpOperationNode(node)) return null
34
- const paramsNode = ast.createOperationParams(node, {
35
- paramsType,
36
- pathParamsType,
37
- paramsCasing,
38
- resolver,
39
- extraParams: [
40
- ast.createFunctionParameter({
41
- name: 'options',
42
- type: ast.createParamsType({ variant: 'reference', name: 'Partial<Cypress.RequestOptions>' }),
43
- default: '{}',
44
- }),
45
- ],
46
- })
47
- const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
48
-
49
- const responseType = resolver.resolveResponseName(node)
50
- const returnType = dataReturnType === 'data' ? `Cypress.Chainable<${responseType}>` : `Cypress.Chainable<Cypress.Response<${responseType}>>`
51
-
52
- const casedPathParams = getOperationParameters(node, { paramsCasing }).path
53
- // Build a lookup keyed by camelCase-normalized name so that path-template names
54
- // (e.g. `{pet_id}`) correctly resolve to the function-parameter name (`petId`)
55
- // even when the OpenAPI spec has inconsistent casing between the two.
56
- const pathParamNameMap = new Map(casedPathParams.map((p) => [camelCase(p.name), p.name]))
57
-
58
- const urlPath = new URLPath(node.path, { casing: paramsCasing })
59
- const urlTemplate = urlPath.toTemplateString({
60
- prefix: baseURL,
61
- replacer: (param) => pathParamNameMap.get(camelCase(param)) ?? param,
62
- })
63
-
64
- const requestOptions: Array<string> = [`method: '${node.method}'`, `url: ${urlTemplate}`]
65
-
66
- const queryParams = getOperationParameters(node).query
67
- if (queryParams.length > 0) {
68
- const casedQueryParams = getOperationParameters(node, { paramsCasing }).query
69
- // When paramsCasing renames query params (e.g. page_size → pageSize), we must remap
70
- // the camelCase keys back to the original API names before passing them to `qs`.
71
- const needsQsTransform = casedQueryParams.some((p, i) => p.name !== queryParams[i]!.name)
72
- if (needsQsTransform) {
73
- const pairs = queryParams.map((orig, i) => `${orig.name}: params.${casedQueryParams[i]!.name}`).join(', ')
74
- requestOptions.push(`qs: params ? { ${pairs} } : undefined`)
75
- } else {
76
- requestOptions.push('qs: params')
77
- }
78
- }
79
-
80
- const headerParams = getOperationParameters(node).header
81
- if (headerParams.length > 0) {
82
- const casedHeaderParams = getOperationParameters(node, { paramsCasing }).header
83
- // When paramsCasing renames header params (e.g. x-api-key → xApiKey), we must remap
84
- // the camelCase keys back to the original API names before passing them to `headers`.
85
- const needsHeaderTransform = casedHeaderParams.some((p, i) => p.name !== headerParams[i]!.name)
86
- if (needsHeaderTransform) {
87
- const pairs = headerParams.map((orig, i) => `'${orig.name}': headers.${casedHeaderParams[i]!.name}`).join(', ')
88
- requestOptions.push(`headers: headers ? { ${pairs} } : undefined`)
89
- } else {
90
- requestOptions.push('headers')
91
- }
92
- }
93
-
94
- if (node.requestBody?.content?.[0]?.schema) {
95
- requestOptions.push('body: data')
96
- }
97
-
98
- requestOptions.push('...options')
99
-
100
- return (
101
- <File.Source name={name} isIndexable isExportable>
102
- <Function name={name} export params={paramsSignature} returnType={returnType}>
103
- {dataReturnType === 'data'
104
- ? `return cy.request<${responseType}>({
105
- ${requestOptions.join(',\n ')}
106
- }).then((res) => res.body)`
107
- : `return cy.request<${responseType}>({
108
- ${requestOptions.join(',\n ')}
109
- })`}
110
- </Function>
111
- </File.Source>
112
- )
113
- }
@@ -1,69 +0,0 @@
1
- import { resolveOperationTypeNames } from '@internals/shared'
2
- import { ast, defineGenerator } from '@kubb/core'
3
- import { pluginTsName } from '@kubb/plugin-ts'
4
- import { File, jsxRendererSync } from '@kubb/renderer-jsx'
5
- import { Request } from '../components/Request.tsx'
6
- import type { PluginCypress } from '../types.ts'
7
-
8
- /**
9
- * Built-in generator for `@kubb/plugin-cypress`. Emits one typed
10
- * `cy.request()` wrapper per OpenAPI operation, ready to call inside Cypress
11
- * test specs and custom commands.
12
- */
13
- export const cypressGenerator = defineGenerator<PluginCypress>({
14
- name: 'cypress',
15
- renderer: jsxRendererSync,
16
- operation(node, ctx) {
17
- if (!ast.isHttpOperationNode(node)) return null
18
- const { config, resolver, driver, root } = ctx
19
- const { output, baseURL, dataReturnType, paramsCasing, paramsType, pathParamsType, group } = ctx.options
20
-
21
- const pluginTs = driver.getPlugin(pluginTsName)
22
-
23
- if (!pluginTs) {
24
- return null
25
- }
26
-
27
- const tsResolver = driver.getResolver(pluginTsName)
28
-
29
- const importedTypeNames = resolveOperationTypeNames(node, tsResolver, { paramsCasing })
30
-
31
- const meta = {
32
- name: resolver.resolveName(node.operationId),
33
- file: resolver.resolveFile(
34
- { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
35
- { root, output, group: group ?? undefined },
36
- ),
37
- fileTs: tsResolver.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 ?? undefined,
43
- },
44
- ),
45
- } as const
46
-
47
- return (
48
- <File
49
- baseName={meta.file.baseName}
50
- path={meta.file.path}
51
- meta={meta.file.meta}
52
- banner={resolver.resolveBanner(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}
53
- footer={resolver.resolveFooter(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}
54
- >
55
- {meta.fileTs && importedTypeNames.length > 0 && <File.Import name={importedTypeNames} root={meta.file.path} path={meta.fileTs.path} isTypeOnly />}
56
- <Request
57
- name={meta.name}
58
- node={node}
59
- resolver={tsResolver}
60
- dataReturnType={dataReturnType}
61
- paramsCasing={paramsCasing}
62
- paramsType={paramsType}
63
- pathParamsType={pathParamsType}
64
- baseURL={baseURL}
65
- />
66
- </File>
67
- )
68
- },
69
- })
package/src/index.ts DELETED
@@ -1,9 +0,0 @@
1
- export { Request } from './components/Request.tsx'
2
-
3
- export { cypressGenerator } from './generators/cypressGenerator.tsx'
4
-
5
- export { default, pluginCypress, pluginCypressName } from './plugin.ts'
6
-
7
- export { resolverCypress } from './resolvers/resolverCypress.ts'
8
-
9
- export type { PluginCypress, ResolverCypress } from './types.ts'
package/src/plugin.ts DELETED
@@ -1,90 +0,0 @@
1
- import { createGroupConfig } from '@internals/shared'
2
- import { definePlugin } from '@kubb/core'
3
- import { pluginTsName } from '@kubb/plugin-ts'
4
- import { cypressGenerator } from './generators/cypressGenerator.tsx'
5
- import { resolverCypress } from './resolvers/resolverCypress.ts'
6
- import type { PluginCypress } from './types.ts'
7
-
8
- /**
9
- * Canonical plugin name for `@kubb/plugin-cypress`. Used for driver lookups and
10
- * cross-plugin dependency references.
11
- */
12
- export const pluginCypressName = 'plugin-cypress' satisfies PluginCypress['name']
13
-
14
- /**
15
- * Generates one typed `cy.request()` wrapper per OpenAPI operation. Each helper
16
- * has typed path params, body, query, and a typed response, so failing API
17
- * calls in Cypress show up at compile time instead of inside the test runner.
18
- *
19
- * @example
20
- * ```ts
21
- * import { defineConfig } from 'kubb'
22
- * import { pluginTs } from '@kubb/plugin-ts'
23
- * import { pluginCypress } from '@kubb/plugin-cypress'
24
- *
25
- * export default defineConfig({
26
- * input: { path: './petStore.yaml' },
27
- * output: { path: './src/gen' },
28
- * plugins: [
29
- * pluginTs(),
30
- * pluginCypress({
31
- * output: { path: './cypress' },
32
- * }),
33
- * ],
34
- * })
35
- * ```
36
- */
37
- export const pluginCypress = definePlugin<PluginCypress>((options) => {
38
- const {
39
- output = { path: 'cypress', barrelType: 'named' },
40
- group,
41
- exclude = [],
42
- include,
43
- override = [],
44
- dataReturnType = 'data',
45
- baseURL,
46
- paramsCasing,
47
- paramsType = 'inline',
48
- pathParamsType = paramsType === 'object' ? 'object' : options.pathParamsType || 'inline',
49
- resolver: userResolver,
50
- transformer: userTransformer,
51
- generators: userGenerators = [],
52
- } = options
53
-
54
- const groupConfig = createGroupConfig(group, { suffix: 'Requests' })
55
-
56
- return {
57
- name: pluginCypressName,
58
- options,
59
- dependencies: [pluginTsName],
60
- hooks: {
61
- 'kubb:plugin:setup'(ctx) {
62
- const resolver = userResolver ? { ...resolverCypress, ...userResolver } : resolverCypress
63
-
64
- ctx.setOptions({
65
- output,
66
- exclude,
67
- include,
68
- override,
69
- dataReturnType,
70
- group: groupConfig,
71
- baseURL,
72
- paramsCasing,
73
- paramsType,
74
- pathParamsType,
75
- resolver,
76
- })
77
- ctx.setResolver(resolver)
78
- if (userTransformer) {
79
- ctx.setTransformer(userTransformer)
80
- }
81
- ctx.addGenerator(cypressGenerator)
82
- for (const gen of userGenerators) {
83
- ctx.addGenerator(gen)
84
- }
85
- },
86
- },
87
- }
88
- })
89
-
90
- export default pluginCypress
@@ -1,29 +0,0 @@
1
- import { camelCase } from '@internals/utils'
2
- import { defineResolver } from '@kubb/core'
3
- import type { PluginCypress } from '../types.ts'
4
-
5
- /**
6
- * Default resolver used by `@kubb/plugin-cypress`. Decides the names and file
7
- * paths for every generated `cy.request()` wrapper. Functions and files use
8
- * camelCase, matching the convention from `@kubb/plugin-client`.
9
- *
10
- * @example Resolve a helper name
11
- * ```ts
12
- * import { resolverCypress } from '@kubb/plugin-cypress'
13
- *
14
- * resolverCypress.default('list pets', 'function') // 'listPets'
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
- resolvePathName(name, type) {
27
- return this.default(name, type)
28
- },
29
- }))
package/src/types.ts DELETED
@@ -1,127 +0,0 @@
1
- import type { ast, Exclude, Generator, Group, Include, Output, Override, PluginFactoryOptions, Resolver } from '@kubb/core'
2
-
3
- /**
4
- * Resolver for Cypress that provides naming methods for test functions.
5
- */
6
- export type ResolverCypress = Resolver & {
7
- /**
8
- * Resolves the function name for an operation.
9
- *
10
- * @example Resolving function names
11
- * `resolver.resolveName('show pet by id') // -> 'showPetById'`
12
- */
13
- resolveName(this: ResolverCypress, name: string): string
14
- /**
15
- * Resolves the output file name for a Cypress request module.
16
- */
17
- resolvePathName(this: ResolverCypress, name: string, type?: 'file' | 'function' | 'type' | 'const'): string
18
- }
19
-
20
- /**
21
- * Parameter handling mode that determines how path params and query/body params are arranged in function signatures.
22
- */
23
- type ParamsTypeOptions =
24
- | {
25
- /**
26
- * Every operation parameter is wrapped in a single destructured object argument.
27
- */
28
- paramsType: 'object'
29
- /**
30
- * `pathParamsType` has no effect when `paramsType` is `'object'`.
31
- */
32
- pathParamsType?: never
33
- }
34
- | {
35
- /**
36
- * Each parameter group is emitted as a separate positional function argument.
37
- */
38
- paramsType?: 'inline'
39
- /**
40
- * How URL path parameters are arranged inside the inline argument list.
41
- * - `'object'` groups them into one destructured object.
42
- * - `'inline'` emits each path param as its own argument.
43
- *
44
- * @default 'inline'
45
- */
46
- pathParamsType?: 'object' | 'inline'
47
- }
48
-
49
- export type Options = {
50
- /**
51
- * Where the generated Cypress helpers are written and how they are exported.
52
- *
53
- * @default { path: 'cypress', barrel: { type: 'named' } }
54
- */
55
- output?: Output
56
- /**
57
- * Shape of the value returned from each helper.
58
- * - `'data'` — only the response body.
59
- * - `'full'` — the full Cypress response object (headers, status, body).
60
- *
61
- * @default 'data'
62
- */
63
- dataReturnType?: 'data' | 'full'
64
- /**
65
- * Rename parameter properties in the generated helpers (path, query, headers).
66
- *
67
- * @note Must match the value of `paramsCasing` on `@kubb/plugin-ts`.
68
- */
69
- paramsCasing?: 'camelcase'
70
- /**
71
- * Base URL prepended to every request URL. When omitted, falls back to the
72
- * adapter's server URL (typically `servers[0].url`).
73
- */
74
- baseURL?: string
75
- /**
76
- * Split generated files into subfolders based on the operation's tag.
77
- */
78
- group?: Group
79
- /**
80
- * Skip operations matching at least one entry in the list.
81
- */
82
- exclude?: Array<Exclude>
83
- /**
84
- * Restrict generation to operations matching at least one entry in the list.
85
- */
86
- include?: Array<Include>
87
- /**
88
- * Apply a different options object to operations matching a pattern.
89
- */
90
- override?: Array<Override<ResolvedOptions>>
91
- /**
92
- * Override how helper names and file paths are built.
93
- */
94
- resolver?: Partial<ResolverCypress> & ThisType<ResolverCypress>
95
- /**
96
- * AST visitor applied to each operation node before printing.
97
- */
98
- transformer?: ast.Visitor
99
- /**
100
- * Custom generators that run alongside the built-in Cypress generators.
101
- */
102
- generators?: Array<Generator<PluginCypress>>
103
- } & ParamsTypeOptions
104
-
105
- type ResolvedOptions = {
106
- output: Output
107
- exclude: Array<Exclude>
108
- include: Array<Include> | undefined
109
- override: Array<Override<ResolvedOptions>>
110
- group: Group | null
111
- baseURL: Options['baseURL'] | undefined
112
- dataReturnType: NonNullable<Options['dataReturnType']>
113
- pathParamsType: NonNullable<NonNullable<Options['pathParamsType']>>
114
- paramsType: NonNullable<Options['paramsType']>
115
- paramsCasing: Options['paramsCasing']
116
- resolver: ResolverCypress
117
- }
118
-
119
- export type PluginCypress = PluginFactoryOptions<'plugin-cypress', Options, ResolvedOptions, ResolverCypress>
120
-
121
- declare global {
122
- namespace Kubb {
123
- interface PluginRegistry {
124
- 'plugin-cypress': PluginCypress
125
- }
126
- }
127
- }