@kubb/plugin-msw 5.0.0-alpha.9 → 5.0.0-beta.100

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,57 +0,0 @@
1
- import { URLPath } from '@internals/utils'
2
- import type { OasTypes, Operation } from '@kubb/oas'
3
- import { File, Function, FunctionParams } from '@kubb/react-fabric'
4
- import type { FabricReactNode } from '@kubb/react-fabric/types'
5
-
6
- type Props = {
7
- /**
8
- * Name of the function
9
- */
10
- name: string
11
- typeName: string
12
- fakerName: string
13
- baseURL: string | undefined
14
- operation: Operation
15
- }
16
-
17
- export function MockWithFaker({ baseURL = '', name, fakerName, typeName, operation }: Props): FabricReactNode {
18
- const method = operation.method
19
- const successStatusCodes = operation.getResponseStatusCodes().filter((code) => code.startsWith('2'))
20
- const statusCode = successStatusCodes.length > 0 ? Number(successStatusCodes[0]) : 200
21
-
22
- const responseObject = operation.getResponseByStatusCode(statusCode) as OasTypes.ResponseObject
23
- const contentType = Object.keys(responseObject.content || {})?.[0]
24
- const url = new URLPath(operation.path).toURLPath().replace(/([^/]):/g, '$1\\\\:')
25
-
26
- const headers = [contentType ? `'Content-Type': '${contentType}'` : undefined].filter(Boolean)
27
-
28
- const params = FunctionParams.factory({
29
- data: {
30
- type: `${typeName} | ((
31
- info: Parameters<Parameters<typeof http.${method}>[1]>[0],
32
- ) => Response | Promise<Response>)`,
33
- optional: true,
34
- },
35
- })
36
-
37
- return (
38
- <File.Source name={name} isIndexable isExportable>
39
- <Function name={name} export params={params.toConstructor()}>
40
- {`return http.${method}('${baseURL}${url.replace(/([^/]):/g, '$1\\\\:')}', function handler(info) {
41
- if(typeof data === 'function') return data(info)
42
-
43
- return new Response(JSON.stringify(data || ${fakerName}(data)), {
44
- status: ${statusCode},
45
- ${
46
- headers.length
47
- ? ` headers: {
48
- ${headers.join(', \n')}
49
- },`
50
- : ''
51
- }
52
- })
53
- })`}
54
- </Function>
55
- </File.Source>
56
- )
57
- }
@@ -1,46 +0,0 @@
1
- import type { OasTypes, Operation } from '@kubb/oas'
2
- import { File, Function, FunctionParams } from '@kubb/react-fabric'
3
- import type { FabricReactNode } from '@kubb/react-fabric/types'
4
-
5
- type Props = {
6
- typeName: string
7
- operation: Operation
8
- name: string
9
- statusCode: number
10
- }
11
-
12
- export function Response({ name, typeName, operation, statusCode }: Props): FabricReactNode {
13
- const responseObject = operation.getResponseByStatusCode(statusCode) as OasTypes.ResponseObject
14
- const contentType = Object.keys(responseObject.content || {})?.[0]
15
-
16
- const headers = [contentType ? `'Content-Type': '${contentType}'` : undefined].filter(Boolean)
17
-
18
- const hasResponseSchema = contentType && responseObject?.content?.[contentType]?.schema !== undefined
19
-
20
- const params = FunctionParams.factory({
21
- data: {
22
- type: `${typeName}`,
23
- optional: !hasResponseSchema,
24
- },
25
- })
26
-
27
- const responseName = `${name}Response${statusCode}`
28
-
29
- return (
30
- <File.Source name={responseName} isIndexable isExportable>
31
- <Function name={responseName} export params={params.toConstructor()}>
32
- {`
33
- return new Response(JSON.stringify(data), {
34
- status: ${statusCode},
35
- ${
36
- headers.length
37
- ? ` headers: {
38
- ${headers.join(', \n')}
39
- },`
40
- : ''
41
- }
42
- })`}
43
- </Function>
44
- </File.Source>
45
- )
46
- }
@@ -1,4 +0,0 @@
1
- export { Handlers } from './Handlers.tsx'
2
- export { Mock } from './Mock.tsx'
3
- export { MockWithFaker } from './MockWithFaker.tsx'
4
- export { Response } from './Response.tsx'
@@ -1,41 +0,0 @@
1
- import { usePluginDriver } 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'
5
- import { File } from '@kubb/react-fabric'
6
- import { Handlers } from '../components/Handlers.tsx'
7
- import type { PluginMsw } from '../types'
8
-
9
- export const handlersGenerator = createReactGenerator<PluginMsw>({
10
- name: 'plugin-msw',
11
- Operations({ operations, generator, plugin }) {
12
- const driver = usePluginDriver()
13
-
14
- const oas = useOas()
15
- const { getName, getFile } = useOperationManager(generator)
16
-
17
- const file = driver.getFile({ name: 'handlers', extname: '.ts', pluginName: plugin.name })
18
-
19
- const imports = operations.map((operation) => {
20
- const operationFile = getFile(operation, { pluginName: plugin.name })
21
- const operationName = getName(operation, { pluginName: plugin.name, type: 'function' })
22
-
23
- return <File.Import key={operationFile.path} name={[operationName]} root={file.path} path={operationFile.path} />
24
- })
25
-
26
- const handlers = operations.map((operation) => `${getName(operation, { type: 'function', pluginName: plugin.name })}()`)
27
-
28
- return (
29
- <File
30
- baseName={file.baseName}
31
- path={file.path}
32
- meta={file.meta}
33
- banner={getBanner({ oas, output: plugin.options.output, config: driver.config })}
34
- footer={getFooter({ oas, output: plugin.options.output })}
35
- >
36
- {imports}
37
- <Handlers name={'handlers'} handlers={handlers} />
38
- </File>
39
- )
40
- },
41
- })
@@ -1,2 +0,0 @@
1
- export { handlersGenerator } from './handlersGenerator.tsx'
2
- export { mswGenerator } from './mswGenerator.tsx'
@@ -1,96 +0,0 @@
1
- import { usePluginDriver } from '@kubb/core/hooks'
2
- import { pluginFakerName } from '@kubb/plugin-faker'
3
- import { createReactGenerator } from '@kubb/plugin-oas/generators'
4
- import { useOas, useOperationManager } from '@kubb/plugin-oas/hooks'
5
- import { getBanner, getFooter } from '@kubb/plugin-oas/utils'
6
- import { pluginTsName } from '@kubb/plugin-ts'
7
- import { File } from '@kubb/react-fabric'
8
- import { Mock, MockWithFaker, Response } from '../components'
9
- import type { PluginMsw } from '../types'
10
-
11
- export const mswGenerator = createReactGenerator<PluginMsw>({
12
- name: 'msw',
13
- Operation({ operation, generator, plugin }) {
14
- const {
15
- options: { output, parser, baseURL },
16
- } = plugin
17
- const driver = usePluginDriver()
18
-
19
- const oas = useOas()
20
- const { getSchemas, getName, getFile } = useOperationManager(generator)
21
-
22
- const mock = {
23
- name: getName(operation, { type: 'function' }),
24
- file: getFile(operation),
25
- }
26
-
27
- const faker = {
28
- file: getFile(operation, { pluginName: pluginFakerName }),
29
- schemas: getSchemas(operation, { pluginName: pluginFakerName, type: 'function' }),
30
- }
31
-
32
- const type = {
33
- file: getFile(operation, { pluginName: pluginTsName }),
34
- schemas: getSchemas(operation, { pluginName: pluginTsName, type: 'type' }),
35
- }
36
-
37
- const responseStatusCodes = operation.getResponseStatusCodes()
38
-
39
- const types: [statusCode: number | 'default', typeName: string][] = []
40
-
41
- for (const code of responseStatusCodes) {
42
- if (code === 'default') {
43
- types.push(['default', type.schemas.response.name])
44
- continue
45
- }
46
-
47
- if (code.startsWith('2')) {
48
- types.push([Number(code), type.schemas.response.name])
49
- continue
50
- }
51
-
52
- const codeType = type.schemas.errors?.find((err) => err.statusCode === Number(code))
53
- if (codeType) types.push([Number(code), codeType.name])
54
- }
55
-
56
- return (
57
- <File
58
- baseName={mock.file.baseName}
59
- path={mock.file.path}
60
- meta={mock.file.meta}
61
- banner={getBanner({ oas, output, config: driver.config })}
62
- footer={getFooter({ oas, output })}
63
- >
64
- <File.Import name={['http']} path="msw" />
65
- <File.Import name={['ResponseResolver']} isTypeOnly path="msw" />
66
- <File.Import
67
- name={Array.from(new Set([type.schemas.response.name, ...types.map((t) => t[1])]))}
68
- path={type.file.path}
69
- root={mock.file.path}
70
- isTypeOnly
71
- />
72
- {parser === 'faker' && faker.file && faker.schemas.response && (
73
- <File.Import name={[faker.schemas.response.name]} root={mock.file.path} path={faker.file.path} />
74
- )}
75
-
76
- {types
77
- .filter(([code]) => code !== 'default')
78
- .map(([code, typeName]) => (
79
- <Response typeName={typeName} operation={operation} name={mock.name} statusCode={code as number} />
80
- ))}
81
- {parser === 'faker' && (
82
- <MockWithFaker
83
- name={mock.name}
84
- typeName={type.schemas.response.name}
85
- fakerName={faker.schemas.response.name}
86
- operation={operation}
87
- baseURL={baseURL}
88
- />
89
- )}
90
- {parser === 'data' && (
91
- <Mock name={mock.name} typeName={type.schemas.response.name} fakerName={faker.schemas.response.name} operation={operation} baseURL={baseURL} />
92
- )}
93
- </File>
94
- )
95
- },
96
- })
package/src/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export { pluginMsw, pluginMswName } from './plugin.ts'
2
- export type { PluginMsw } from './types.ts'
package/src/plugin.ts DELETED
@@ -1,115 +0,0 @@
1
- import path from 'node:path'
2
- import { camelCase } from '@internals/utils'
3
- import { createPlugin, type Group, getBarrelFiles, getMode } from '@kubb/core'
4
- import { pluginFakerName } from '@kubb/plugin-faker'
5
- import { OperationGenerator, pluginOasName } from '@kubb/plugin-oas'
6
- import { pluginTsName } from '@kubb/plugin-ts'
7
- import { handlersGenerator, mswGenerator } from './generators'
8
- import type { PluginMsw } from './types.ts'
9
-
10
- export const pluginMswName = 'plugin-msw' satisfies PluginMsw['name']
11
-
12
- export const pluginMsw = createPlugin<PluginMsw>((options) => {
13
- const {
14
- output = { path: 'handlers', barrelType: 'named' },
15
- group,
16
- exclude = [],
17
- include,
18
- override = [],
19
- transformers = {},
20
- handlers = false,
21
- parser = 'data',
22
- generators = [mswGenerator, handlers ? handlersGenerator : undefined].filter(Boolean),
23
- contentType,
24
- baseURL,
25
- } = options
26
-
27
- return {
28
- name: pluginMswName,
29
- options: {
30
- output,
31
- parser,
32
- group,
33
- baseURL,
34
- },
35
- pre: [pluginOasName, pluginTsName, parser === 'faker' ? pluginFakerName : undefined].filter(Boolean),
36
- resolvePath(baseName, pathMode, options) {
37
- const root = path.resolve(this.config.root, this.config.output.path)
38
- const mode = pathMode ?? getMode(path.resolve(root, output.path))
39
-
40
- if (mode === 'single') {
41
- /**
42
- * when output is a file then we will always append to the same file(output file), see fileManager.addOrAppend
43
- * Other plugins then need to call addOrAppend instead of just add from the fileManager class
44
- */
45
- return path.resolve(root, output.path)
46
- }
47
-
48
- if (group && (options?.group?.path || options?.group?.tag)) {
49
- const groupName: Group['name'] = group?.name
50
- ? group.name
51
- : (ctx) => {
52
- if (group?.type === 'path') {
53
- return `${ctx.group.split('/')[1]}`
54
- }
55
- return `${camelCase(ctx.group)}Controller`
56
- }
57
-
58
- return path.resolve(
59
- root,
60
- output.path,
61
- groupName({
62
- group: group.type === 'path' ? options.group.path! : options.group.tag!,
63
- }),
64
- baseName,
65
- )
66
- }
67
-
68
- return path.resolve(root, output.path, baseName)
69
- },
70
- resolveName(name, type) {
71
- const resolvedName = camelCase(name, {
72
- suffix: type ? 'handler' : undefined,
73
- isFile: type === 'file',
74
- })
75
-
76
- if (type) {
77
- return transformers?.name?.(resolvedName, type) || resolvedName
78
- }
79
-
80
- return resolvedName
81
- },
82
- async install() {
83
- const root = path.resolve(this.config.root, this.config.output.path)
84
- const mode = getMode(path.resolve(root, output.path))
85
- const oas = await this.getOas()
86
-
87
- const operationGenerator = new OperationGenerator(this.plugin.options, {
88
- fabric: this.fabric,
89
- oas,
90
- driver: this.driver,
91
- events: this.events,
92
- plugin: this.plugin,
93
- contentType,
94
- exclude,
95
- include,
96
- override,
97
- mode,
98
- })
99
-
100
- const files = await operationGenerator.build(...generators)
101
- await this.upsertFile(...files)
102
-
103
- const barrelFiles = await getBarrelFiles(this.fabric.files, {
104
- type: output.barrelType ?? 'named',
105
- root,
106
- output,
107
- meta: {
108
- pluginName: this.plugin.name,
109
- },
110
- })
111
-
112
- await this.upsertFile(...barrelFiles)
113
- },
114
- }
115
- })
package/src/types.ts DELETED
@@ -1,65 +0,0 @@
1
- import type { Group, Output, PluginFactoryOptions, ResolveNameParams } from '@kubb/core'
2
-
3
- import type { contentType, Oas } from '@kubb/oas'
4
- import type { Exclude, Include, Override, ResolvePathOptions } from '@kubb/plugin-oas'
5
- import type { Generator } from '@kubb/plugin-oas/generators'
6
-
7
- export type Options = {
8
- /**
9
- * Specify the export location for the files and define the behavior of the output
10
- * @default { path: 'mocks', barrelType: 'named' }
11
- */
12
- output?: Output<Oas>
13
- /**
14
- * Define which contentType should be used.
15
- * By default, the first JSON valid mediaType is used
16
- */
17
- contentType?: contentType
18
- baseURL?: string
19
- /**
20
- * Group the MSW mocks based on the provided name.
21
- */
22
- group?: Group
23
- /**
24
- * Array containing exclude parameters to exclude/skip tags/operations/methods/paths.
25
- */
26
- exclude?: Array<Exclude>
27
- /**
28
- * Array containing include parameters to include tags/operations/methods/paths.
29
- */
30
- include?: Array<Include>
31
- /**
32
- * Array containing override parameters to override `options` based on tags/operations/methods/paths.
33
- */
34
- override?: Array<Override<ResolvedOptions>>
35
- transformers?: {
36
- /**
37
- * Customize the names based on the type that is provided by the plugin.
38
- */
39
- name?: (name: ResolveNameParams['name'], type?: ResolveNameParams['type']) => string
40
- }
41
- /**
42
- * Create `handlers.ts` file with all handlers grouped by methods.
43
- * @default false
44
- */
45
- handlers?: boolean
46
- /**
47
- * Which parser should be used before returning the data to the Response of MSW.
48
- * - 'data' uses your custom data to generate the data for the response.
49
- * - 'faker' uses @kubb/plugin-faker to generate the data for the response.
50
- * @default 'data'
51
- */
52
- parser?: 'data' | 'faker'
53
- /**
54
- * Define some generators next to the msw generators
55
- */
56
- generators?: Array<Generator<PluginMsw>>
57
- }
58
- type ResolvedOptions = {
59
- output: Output<Oas>
60
- group: Options['group']
61
- parser: NonNullable<Options['parser']>
62
- baseURL: Options['baseURL'] | undefined
63
- }
64
-
65
- export type PluginMsw = PluginFactoryOptions<'plugin-msw', Options, ResolvedOptions, never, ResolvePathOptions>