@kubb/plugin-msw 5.0.0-alpha.8 → 5.0.0-beta.10
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/LICENSE +17 -10
- package/README.md +26 -7
- package/dist/components-BYvgvrY7.cjs +569 -0
- package/dist/components-BYvgvrY7.cjs.map +1 -0
- package/dist/components-Cm17DMTE.js +510 -0
- package/dist/components-Cm17DMTE.js.map +1 -0
- package/dist/components.cjs +1 -1
- package/dist/components.d.ts +17 -21
- package/dist/components.js +1 -1
- package/dist/generators-D9gvdP7Z.js +177 -0
- package/dist/generators-D9gvdP7Z.js.map +1 -0
- package/dist/generators-rZ99WaWQ.cjs +187 -0
- package/dist/generators-rZ99WaWQ.cjs.map +1 -0
- package/dist/generators.cjs +1 -1
- package/dist/generators.d.ts +4 -471
- package/dist/generators.js +1 -1
- package/dist/index.cjs +62 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +59 -65
- package/dist/index.js.map +1 -1
- package/dist/types-ItsHsMvC.d.ts +94 -0
- package/extension.yaml +233 -0
- package/package.json +57 -58
- package/src/components/Handlers.tsx +3 -3
- package/src/components/Mock.tsx +37 -28
- package/src/components/MockWithFaker.tsx +37 -24
- package/src/components/Response.tsx +23 -17
- package/src/generators/handlersGenerator.tsx +19 -19
- package/src/generators/mswGenerator.tsx +50 -60
- package/src/index.ts +1 -1
- package/src/plugin.ts +47 -86
- package/src/resolvers/resolverMsw.ts +28 -0
- package/src/types.ts +55 -27
- package/src/utils.ts +58 -0
- package/dist/components-8XBwMbFa.cjs +0 -343
- package/dist/components-8XBwMbFa.cjs.map +0 -1
- package/dist/components-DgtTZkWX.js +0 -277
- package/dist/components-DgtTZkWX.js.map +0 -1
- package/dist/generators-CY1SNd5X.cjs +0 -171
- package/dist/generators-CY1SNd5X.cjs.map +0 -1
- package/dist/generators-CvyZTxOm.js +0 -161
- package/dist/generators-CvyZTxOm.js.map +0 -1
- package/dist/types-MdHRNpgi.d.ts +0 -68
package/src/components/Mock.tsx
CHANGED
|
@@ -1,48 +1,57 @@
|
|
|
1
|
+
import { getPrimarySuccessResponse } from '@internals/shared'
|
|
1
2
|
import { URLPath } from '@internals/utils'
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { ast } from '@kubb/core'
|
|
4
|
+
import { functionPrinter } from '@kubb/plugin-ts'
|
|
5
|
+
import { File, Function } from '@kubb/renderer-jsx'
|
|
6
|
+
import type { KubbReactNode } from '@kubb/renderer-jsx/types'
|
|
7
|
+
import { getContentType, getMswMethod, getMswUrl, hasResponseSchema } from '../utils.ts'
|
|
5
8
|
|
|
6
9
|
type Props = {
|
|
7
|
-
/**
|
|
8
|
-
* Name of the function
|
|
9
|
-
*/
|
|
10
10
|
name: string
|
|
11
11
|
typeName: string
|
|
12
|
-
|
|
12
|
+
requestTypeName?: string
|
|
13
13
|
baseURL: string | undefined
|
|
14
|
-
|
|
14
|
+
node: ast.OperationNode
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
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
|
|
17
|
+
const declarationPrinter = functionPrinter({ mode: 'declaration' })
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
const
|
|
19
|
+
export function Mock({ baseURL = '', name, typeName, requestTypeName, node }: Props): KubbReactNode {
|
|
20
|
+
const method = getMswMethod(node)
|
|
21
|
+
const successResponse = getPrimarySuccessResponse(node)
|
|
22
|
+
const statusCode = successResponse ? Number(successResponse.statusCode) : 200
|
|
23
|
+
const contentType = getContentType(successResponse)
|
|
24
|
+
const url = new URLPath(getMswUrl(node)).toURLPath()
|
|
25
25
|
|
|
26
26
|
const headers = [contentType ? `'Content-Type': '${contentType}'` : undefined].filter(Boolean)
|
|
27
|
+
const responseHasSchema = hasResponseSchema(successResponse)
|
|
28
|
+
const dataType = responseHasSchema ? typeName : 'string | number | boolean | null | object'
|
|
27
29
|
|
|
28
|
-
const
|
|
30
|
+
const callbackType = requestTypeName
|
|
31
|
+
? `HttpResponseResolver<Record<string, string>, ${requestTypeName}, any>`
|
|
32
|
+
: `((info: Parameters<Parameters<typeof http.${method}>[1]>[0]) => Response | Promise<Response>)`
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
const params = declarationPrinter.print(
|
|
35
|
+
ast.createFunctionParameters({
|
|
36
|
+
params: [
|
|
37
|
+
ast.createFunctionParameter({
|
|
38
|
+
name: 'data',
|
|
39
|
+
type: ast.createParamsType({
|
|
40
|
+
variant: 'reference',
|
|
41
|
+
name: `${dataType} | ${callbackType}`,
|
|
42
|
+
}),
|
|
43
|
+
optional: true,
|
|
44
|
+
}),
|
|
45
|
+
],
|
|
46
|
+
}),
|
|
47
|
+
)
|
|
32
48
|
|
|
33
|
-
const
|
|
34
|
-
data: {
|
|
35
|
-
type: `${dataType} | ((
|
|
36
|
-
info: Parameters<Parameters<typeof http.${method}>[1]>[0],
|
|
37
|
-
) => Response | Promise<Response>)`,
|
|
38
|
-
optional: true,
|
|
39
|
-
},
|
|
40
|
-
})
|
|
49
|
+
const httpCall = requestTypeName ? `http.${method}<Record<string, string>, ${requestTypeName}, any>` : `http.${method}`
|
|
41
50
|
|
|
42
51
|
return (
|
|
43
52
|
<File.Source name={name} isIndexable isExportable>
|
|
44
|
-
<Function name={name} export params={params
|
|
45
|
-
{`return
|
|
53
|
+
<Function name={name} export params={params ?? ''}>
|
|
54
|
+
{`return ${httpCall}(\`${baseURL}${url.replace(/([^/]):/g, '$1\\\\:')}\`, function handler(info) {
|
|
46
55
|
if(typeof data === 'function') return data(info)
|
|
47
56
|
|
|
48
57
|
return new Response(JSON.stringify(data), {
|
|
@@ -1,43 +1,56 @@
|
|
|
1
|
+
import { getPrimarySuccessResponse } from '@internals/shared'
|
|
1
2
|
import { URLPath } from '@internals/utils'
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { ast } from '@kubb/core'
|
|
4
|
+
import { functionPrinter } from '@kubb/plugin-ts'
|
|
5
|
+
import { File, Function } from '@kubb/renderer-jsx'
|
|
6
|
+
import type { KubbReactNode } from '@kubb/renderer-jsx/types'
|
|
7
|
+
import { getContentType, getMswMethod, getMswUrl } from '../utils.ts'
|
|
5
8
|
|
|
6
9
|
type Props = {
|
|
7
|
-
/**
|
|
8
|
-
* Name of the function
|
|
9
|
-
*/
|
|
10
10
|
name: string
|
|
11
11
|
typeName: string
|
|
12
|
+
requestTypeName?: string
|
|
12
13
|
fakerName: string
|
|
13
14
|
baseURL: string | undefined
|
|
14
|
-
|
|
15
|
+
node: ast.OperationNode
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
|
|
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
|
|
18
|
+
const declarationPrinter = functionPrinter({ mode: 'declaration' })
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
const
|
|
20
|
+
export function MockWithFaker({ baseURL = '', name, fakerName, typeName, requestTypeName, node }: Props): KubbReactNode {
|
|
21
|
+
const method = getMswMethod(node)
|
|
22
|
+
const successResponse = getPrimarySuccessResponse(node)
|
|
23
|
+
const statusCode = successResponse ? Number(successResponse.statusCode) : 200
|
|
24
|
+
const contentType = getContentType(successResponse)
|
|
25
|
+
const url = new URLPath(getMswUrl(node)).toURLPath()
|
|
25
26
|
|
|
26
27
|
const headers = [contentType ? `'Content-Type': '${contentType}'` : undefined].filter(Boolean)
|
|
27
28
|
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
const callbackType = requestTypeName
|
|
30
|
+
? `HttpResponseResolver<Record<string, string>, ${requestTypeName}, any>`
|
|
31
|
+
: `((info: Parameters<Parameters<typeof http.${method}>[1]>[0]) => Response | Promise<Response>)`
|
|
32
|
+
|
|
33
|
+
const params = declarationPrinter.print(
|
|
34
|
+
ast.createFunctionParameters({
|
|
35
|
+
params: [
|
|
36
|
+
ast.createFunctionParameter({
|
|
37
|
+
name: 'data',
|
|
38
|
+
type: ast.createParamsType({
|
|
39
|
+
variant: 'reference',
|
|
40
|
+
name: `${typeName} | ${callbackType}`,
|
|
41
|
+
}),
|
|
42
|
+
optional: true,
|
|
43
|
+
}),
|
|
44
|
+
],
|
|
45
|
+
}),
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
const httpCall = requestTypeName ? `http.${method}<Record<string, string>, ${requestTypeName}, any>` : `http.${method}`
|
|
36
49
|
|
|
37
50
|
return (
|
|
38
51
|
<File.Source name={name} isIndexable isExportable>
|
|
39
|
-
<Function name={name} export params={params
|
|
40
|
-
{`return
|
|
52
|
+
<Function name={name} export params={params ?? ''}>
|
|
53
|
+
{`return ${httpCall}('${baseURL}${url.replace(/([^/]):/g, '$1\\\\:')}', function handler(info) {
|
|
41
54
|
if(typeof data === 'function') return data(info)
|
|
42
55
|
|
|
43
56
|
return new Response(JSON.stringify(data || ${fakerName}(data)), {
|
|
@@ -1,34 +1,40 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import { ast } from '@kubb/core'
|
|
2
|
+
import { functionPrinter } from '@kubb/plugin-ts'
|
|
3
|
+
import { File, Function } from '@kubb/renderer-jsx'
|
|
4
|
+
import type { KubbReactNode } from '@kubb/renderer-jsx/types'
|
|
5
|
+
import { getContentType, hasResponseSchema } from '../utils.ts'
|
|
4
6
|
|
|
5
7
|
type Props = {
|
|
6
8
|
typeName: string
|
|
7
|
-
operation: Operation
|
|
8
9
|
name: string
|
|
9
|
-
|
|
10
|
+
response: ast.ResponseNode
|
|
11
|
+
key?: string | number | null
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
const responseObject = operation.getResponseByStatusCode(statusCode) as OasTypes.ResponseObject
|
|
14
|
-
const contentType = Object.keys(responseObject.content || {})?.[0]
|
|
14
|
+
const declarationPrinter = functionPrinter({ mode: 'declaration' })
|
|
15
15
|
|
|
16
|
+
export function Response({ name, typeName, response }: Props): KubbReactNode {
|
|
17
|
+
const statusCode = Number(response.statusCode)
|
|
18
|
+
const contentType = getContentType(response)
|
|
16
19
|
const headers = [contentType ? `'Content-Type': '${contentType}'` : undefined].filter(Boolean)
|
|
17
20
|
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
const params = declarationPrinter.print(
|
|
22
|
+
ast.createFunctionParameters({
|
|
23
|
+
params: [
|
|
24
|
+
ast.createFunctionParameter({
|
|
25
|
+
name: 'data',
|
|
26
|
+
type: ast.createParamsType({ variant: 'reference', name: typeName }),
|
|
27
|
+
optional: !hasResponseSchema(response),
|
|
28
|
+
}),
|
|
29
|
+
],
|
|
30
|
+
}),
|
|
31
|
+
)
|
|
26
32
|
|
|
27
33
|
const responseName = `${name}Response${statusCode}`
|
|
28
34
|
|
|
29
35
|
return (
|
|
30
36
|
<File.Source name={responseName} isIndexable isExportable>
|
|
31
|
-
<Function name={responseName} export params={params
|
|
37
|
+
<Function name={responseName} export params={params ?? ''}>
|
|
32
38
|
{`
|
|
33
39
|
return new Response(JSON.stringify(data), {
|
|
34
40
|
status: ${statusCode},
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
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'
|
|
1
|
+
import { defineGenerator } from '@kubb/core'
|
|
2
|
+
import { File, jsxRenderer } from '@kubb/renderer-jsx'
|
|
6
3
|
import { Handlers } from '../components/Handlers.tsx'
|
|
7
4
|
import type { PluginMsw } from '../types'
|
|
8
5
|
|
|
9
|
-
export const handlersGenerator =
|
|
6
|
+
export const handlersGenerator = defineGenerator<PluginMsw>({
|
|
10
7
|
name: 'plugin-msw',
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
renderer: jsxRenderer,
|
|
9
|
+
operations(nodes, ctx) {
|
|
10
|
+
const { resolver, config, root, adapter } = ctx
|
|
11
|
+
const { output, group } = ctx.options
|
|
13
12
|
|
|
14
|
-
const
|
|
15
|
-
const {
|
|
13
|
+
const handlersName = resolver.resolveHandlersName()
|
|
14
|
+
const file = resolver.resolveFile({ name: resolver.resolvePathName(handlersName, 'file'), extname: '.ts' }, { root, output, group })
|
|
16
15
|
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
const imports = nodes.map((node) => {
|
|
17
|
+
const operationName = resolver.resolveHandlerName(node)
|
|
18
|
+
const operationFile = resolver.resolveFile(
|
|
19
|
+
{ name: resolver.resolveName(node.operationId), extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
20
|
+
{ root, output, group },
|
|
21
|
+
)
|
|
22
22
|
|
|
23
23
|
return <File.Import key={operationFile.path} name={[operationName]} root={file.path} path={operationFile.path} />
|
|
24
24
|
})
|
|
25
25
|
|
|
26
|
-
const handlers =
|
|
26
|
+
const handlers = nodes.map((node) => `${resolver.resolveHandlerName(node)}()`)
|
|
27
27
|
|
|
28
28
|
return (
|
|
29
29
|
<File
|
|
30
30
|
baseName={file.baseName}
|
|
31
31
|
path={file.path}
|
|
32
32
|
meta={file.meta}
|
|
33
|
-
banner={
|
|
34
|
-
footer={
|
|
33
|
+
banner={resolver.resolveBanner(adapter.inputNode, { output, config })}
|
|
34
|
+
footer={resolver.resolveFooter(adapter.inputNode, { output, config })}
|
|
35
35
|
>
|
|
36
36
|
{imports}
|
|
37
|
-
<Handlers name={
|
|
37
|
+
<Handlers name={handlersName} handlers={handlers} />
|
|
38
38
|
</File>
|
|
39
39
|
)
|
|
40
40
|
},
|
|
@@ -1,94 +1,84 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getOperationSuccessResponses, resolveResponseTypes } from '@internals/shared'
|
|
2
|
+
import { defineGenerator } from '@kubb/core'
|
|
2
3
|
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
4
|
import { pluginTsName } from '@kubb/plugin-ts'
|
|
7
|
-
import { File } from '@kubb/
|
|
5
|
+
import { File, jsxRenderer } from '@kubb/renderer-jsx'
|
|
8
6
|
import { Mock, MockWithFaker, Response } from '../components'
|
|
9
7
|
import type { PluginMsw } from '../types'
|
|
8
|
+
import { resolveFakerMeta } from '../utils.ts'
|
|
10
9
|
|
|
11
|
-
export const mswGenerator =
|
|
10
|
+
export const mswGenerator = defineGenerator<PluginMsw>({
|
|
12
11
|
name: 'msw',
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
} =
|
|
17
|
-
const driver = usePluginDriver()
|
|
18
|
-
|
|
19
|
-
const oas = useOas()
|
|
20
|
-
const { getSchemas, getName, getFile } = useOperationManager(generator)
|
|
12
|
+
renderer: jsxRenderer,
|
|
13
|
+
operation(node, ctx) {
|
|
14
|
+
const { driver, resolver, config, root, adapter } = ctx
|
|
15
|
+
const { output, parser, baseURL, group } = ctx.options
|
|
21
16
|
|
|
17
|
+
const fileName = resolver.resolveName(node.operationId)
|
|
22
18
|
const mock = {
|
|
23
|
-
name:
|
|
24
|
-
file:
|
|
19
|
+
name: resolver.resolveHandlerName(node),
|
|
20
|
+
file: resolver.resolveFile({ name: fileName, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path }, { root, output, group }),
|
|
25
21
|
}
|
|
26
22
|
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
const fakerPlugin = parser === 'faker' ? driver.getPlugin(pluginFakerName) : undefined
|
|
24
|
+
const faker =
|
|
25
|
+
parser === 'faker' && fakerPlugin
|
|
26
|
+
? resolveFakerMeta(node, {
|
|
27
|
+
root,
|
|
28
|
+
fakerResolver: driver.getResolver(pluginFakerName),
|
|
29
|
+
fakerOutput: fakerPlugin.options?.output ?? output,
|
|
30
|
+
fakerGroup: fakerPlugin.options?.group,
|
|
31
|
+
})
|
|
32
|
+
: undefined
|
|
33
|
+
|
|
34
|
+
const pluginTs = driver.getPlugin(pluginTsName)
|
|
35
|
+
if (!pluginTs) return null
|
|
36
|
+
const tsResolver = driver.getResolver(pluginTsName)
|
|
31
37
|
|
|
32
38
|
const type = {
|
|
33
|
-
file:
|
|
34
|
-
|
|
39
|
+
file: tsResolver.resolveFile(
|
|
40
|
+
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
41
|
+
{ root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group },
|
|
42
|
+
),
|
|
43
|
+
responseName: tsResolver.resolveResponseName(node),
|
|
35
44
|
}
|
|
36
45
|
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
for (const code of responseStatusCodes) {
|
|
42
|
-
if (code === 'default') {
|
|
43
|
-
types.push(['default', type.schemas.response.name])
|
|
44
|
-
continue
|
|
45
|
-
}
|
|
46
|
+
const types = resolveResponseTypes(node, tsResolver)
|
|
47
|
+
const successResponses = getOperationSuccessResponses(node)
|
|
48
|
+
const hasSuccessSchema = successResponses.some((response) => !!response.schema)
|
|
46
49
|
|
|
47
|
-
|
|
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
|
-
}
|
|
50
|
+
const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : undefined
|
|
55
51
|
|
|
56
52
|
return (
|
|
57
53
|
<File
|
|
58
54
|
baseName={mock.file.baseName}
|
|
59
55
|
path={mock.file.path}
|
|
60
56
|
meta={mock.file.meta}
|
|
61
|
-
banner={
|
|
62
|
-
footer={
|
|
57
|
+
banner={resolver.resolveBanner(adapter.inputNode, { output, config })}
|
|
58
|
+
footer={resolver.resolveFooter(adapter.inputNode, { output, config })}
|
|
63
59
|
>
|
|
64
60
|
<File.Import name={['http']} path="msw" />
|
|
65
|
-
<File.Import name={['
|
|
61
|
+
<File.Import name={['HttpResponseResolver']} isTypeOnly path="msw" />
|
|
66
62
|
<File.Import
|
|
67
|
-
name={Array.from(new Set([type.
|
|
63
|
+
name={Array.from(new Set([type.responseName, ...types.map((t) => t[1]), ...(requestName ? [requestName] : [])]))}
|
|
68
64
|
path={type.file.path}
|
|
69
65
|
root={mock.file.path}
|
|
70
66
|
isTypeOnly
|
|
71
67
|
/>
|
|
72
|
-
{parser === 'faker' && faker
|
|
73
|
-
<File.Import name={[faker.schemas.response.name]} root={mock.file.path} path={faker.file.path} />
|
|
74
|
-
)}
|
|
68
|
+
{parser === 'faker' && faker && <File.Import name={[faker.name]} root={mock.file.path} path={faker.file.path} />}
|
|
75
69
|
|
|
76
70
|
{types
|
|
77
71
|
.filter(([code]) => code !== 'default')
|
|
78
|
-
.map(([code, typeName]) =>
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
/>
|
|
89
|
-
)}
|
|
90
|
-
{parser === 'data' && (
|
|
91
|
-
<Mock name={mock.name} typeName={type.schemas.response.name} fakerName={faker.schemas.response.name} operation={operation} baseURL={baseURL} />
|
|
72
|
+
.map(([code, typeName]) => {
|
|
73
|
+
const response = node.responses.find((item) => item.statusCode === String(code))
|
|
74
|
+
if (!response) return null
|
|
75
|
+
return <Response key={typeName} typeName={typeName} response={response} name={mock.name} />
|
|
76
|
+
})}
|
|
77
|
+
|
|
78
|
+
{parser === 'faker' && faker && hasSuccessSchema ? (
|
|
79
|
+
<MockWithFaker name={mock.name} typeName={type.responseName} requestTypeName={requestName} fakerName={faker.name} node={node} baseURL={baseURL} />
|
|
80
|
+
) : (
|
|
81
|
+
<Mock name={mock.name} typeName={type.responseName} requestTypeName={requestName} node={node} baseURL={baseURL} />
|
|
92
82
|
)}
|
|
93
83
|
</File>
|
|
94
84
|
)
|
package/src/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { pluginMsw, pluginMswName } from './plugin.ts'
|
|
1
|
+
export { default, pluginMsw, pluginMswName } from './plugin.ts'
|
|
2
2
|
export type { PluginMsw } from './types.ts'
|
package/src/plugin.ts
CHANGED
|
@@ -1,115 +1,76 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
1
|
import { camelCase } from '@internals/utils'
|
|
3
|
-
import {
|
|
2
|
+
import { definePlugin, type Group } from '@kubb/core'
|
|
4
3
|
import { pluginFakerName } from '@kubb/plugin-faker'
|
|
5
|
-
import { OperationGenerator, pluginOasName } from '@kubb/plugin-oas'
|
|
6
4
|
import { pluginTsName } from '@kubb/plugin-ts'
|
|
7
5
|
import { handlersGenerator, mswGenerator } from './generators'
|
|
6
|
+
import { resolverMsw } from './resolvers/resolverMsw.ts'
|
|
8
7
|
import type { PluginMsw } from './types.ts'
|
|
9
8
|
|
|
10
9
|
export const pluginMswName = 'plugin-msw' satisfies PluginMsw['name']
|
|
11
10
|
|
|
12
|
-
export const pluginMsw =
|
|
11
|
+
export const pluginMsw = definePlugin<PluginMsw>((options) => {
|
|
13
12
|
const {
|
|
14
13
|
output = { path: 'handlers', barrelType: 'named' },
|
|
15
14
|
group,
|
|
16
15
|
exclude = [],
|
|
17
16
|
include,
|
|
18
17
|
override = [],
|
|
19
|
-
transformers = {},
|
|
20
18
|
handlers = false,
|
|
21
19
|
parser = 'data',
|
|
22
|
-
generators = [mswGenerator, handlers ? handlersGenerator : undefined].filter(Boolean),
|
|
23
|
-
contentType,
|
|
24
20
|
baseURL,
|
|
21
|
+
resolver: userResolver,
|
|
22
|
+
transformer: userTransformer,
|
|
23
|
+
generators: userGenerators = [],
|
|
25
24
|
} = options
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
|
26
|
+
const groupConfig = group
|
|
27
|
+
? ({
|
|
28
|
+
...group,
|
|
29
|
+
name: group.name
|
|
50
30
|
? group.name
|
|
51
|
-
: (ctx) => {
|
|
52
|
-
if (group
|
|
31
|
+
: (ctx: { group: string }) => {
|
|
32
|
+
if (group.type === 'path') {
|
|
53
33
|
return `${ctx.group.split('/')[1]}`
|
|
54
34
|
}
|
|
55
35
|
return `${camelCase(ctx.group)}Controller`
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
})
|
|
36
|
+
},
|
|
37
|
+
} satisfies Group)
|
|
38
|
+
: undefined
|
|
75
39
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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)
|
|
40
|
+
return {
|
|
41
|
+
name: pluginMswName,
|
|
42
|
+
options,
|
|
43
|
+
dependencies: [pluginTsName, parser === 'faker' ? pluginFakerName : undefined].filter((dependency): dependency is string => Boolean(dependency)),
|
|
44
|
+
hooks: {
|
|
45
|
+
'kubb:plugin:setup'(ctx) {
|
|
46
|
+
const resolver = userResolver ? { ...resolverMsw, ...userResolver } : resolverMsw
|
|
102
47
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
48
|
+
ctx.setOptions({
|
|
49
|
+
output,
|
|
50
|
+
parser,
|
|
51
|
+
baseURL,
|
|
52
|
+
group: groupConfig,
|
|
53
|
+
exclude,
|
|
54
|
+
include,
|
|
55
|
+
override,
|
|
56
|
+
handlers,
|
|
57
|
+
resolver,
|
|
58
|
+
})
|
|
59
|
+
ctx.setResolver(resolver)
|
|
60
|
+
if (userTransformer) {
|
|
61
|
+
ctx.setTransformer(userTransformer)
|
|
62
|
+
}
|
|
111
63
|
|
|
112
|
-
|
|
64
|
+
ctx.addGenerator(mswGenerator)
|
|
65
|
+
if (handlers) {
|
|
66
|
+
ctx.addGenerator(handlersGenerator)
|
|
67
|
+
}
|
|
68
|
+
for (const gen of userGenerators) {
|
|
69
|
+
ctx.addGenerator(gen)
|
|
70
|
+
}
|
|
71
|
+
},
|
|
113
72
|
},
|
|
114
73
|
}
|
|
115
74
|
})
|
|
75
|
+
|
|
76
|
+
export default pluginMsw
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { camelCase } from '@internals/utils'
|
|
2
|
+
import { defineResolver } from '@kubb/core'
|
|
3
|
+
import type { PluginMsw } from '../types.ts'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Naming convention resolver for MSW plugin.
|
|
7
|
+
*
|
|
8
|
+
* Provides default naming helpers using camelCase with a `handler` suffix.
|
|
9
|
+
*/
|
|
10
|
+
export const resolverMsw = defineResolver<PluginMsw>(() => ({
|
|
11
|
+
name: 'default',
|
|
12
|
+
pluginName: 'plugin-msw',
|
|
13
|
+
default(name, type) {
|
|
14
|
+
return camelCase(name, { isFile: type === 'file' })
|
|
15
|
+
},
|
|
16
|
+
resolveName(name) {
|
|
17
|
+
return camelCase(name, { suffix: 'handler' })
|
|
18
|
+
},
|
|
19
|
+
resolvePathName(name, type) {
|
|
20
|
+
return this.default(name, type)
|
|
21
|
+
},
|
|
22
|
+
resolveHandlerName(node) {
|
|
23
|
+
return this.resolveName(node.operationId)
|
|
24
|
+
},
|
|
25
|
+
resolveHandlersName() {
|
|
26
|
+
return 'handlers'
|
|
27
|
+
},
|
|
28
|
+
}))
|