@kubb/plugin-faker 3.0.0-alpha.0
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 +21 -0
- package/README.md +44 -0
- package/dist/components.cjs +577 -0
- package/dist/components.cjs.map +1 -0
- package/dist/components.d.cts +23 -0
- package/dist/components.d.ts +23 -0
- package/dist/components.js +577 -0
- package/dist/components.js.map +1 -0
- package/dist/index.cjs +579 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +135 -0
- package/dist/index.d.ts +135 -0
- package/dist/index.js +579 -0
- package/dist/index.js.map +1 -0
- package/package.json +94 -0
- package/src/OperationGenerator.tsx +30 -0
- package/src/SchemaGenerator.tsx +31 -0
- package/src/components/OperationSchema.tsx +84 -0
- package/src/components/Schema.tsx +146 -0
- package/src/components/index.ts +2 -0
- package/src/index.ts +2 -0
- package/src/parser/index.ts +313 -0
- package/src/plugin.ts +153 -0
- package/src/types.ts +136 -0
package/package.json
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kubb/plugin-faker",
|
|
3
|
+
"version": "3.0.0-alpha.0",
|
|
4
|
+
"description": "Generator plugin-faker",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"faker",
|
|
7
|
+
"faker.js",
|
|
8
|
+
"mock",
|
|
9
|
+
"mocking",
|
|
10
|
+
"plugins",
|
|
11
|
+
"kubb",
|
|
12
|
+
"codegen",
|
|
13
|
+
"swagger",
|
|
14
|
+
"openapi"
|
|
15
|
+
],
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git://github.com/kubb-labs/kubb.git",
|
|
19
|
+
"directory": "packages/plugin-faker"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"author": "Stijn Van Hulle <stijn@stijnvanhulle.be",
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"type": "module",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"import": "./dist/index.js",
|
|
28
|
+
"require": "./dist/index.cjs",
|
|
29
|
+
"default": "./dist/index.cjs"
|
|
30
|
+
},
|
|
31
|
+
"./components": {
|
|
32
|
+
"import": "./dist/components.js",
|
|
33
|
+
"require": "./dist/components.cjs",
|
|
34
|
+
"default": "./dist/components.cjs"
|
|
35
|
+
},
|
|
36
|
+
"./package.json": "./package.json",
|
|
37
|
+
"./*": "./*"
|
|
38
|
+
},
|
|
39
|
+
"main": "dist/index.cjs",
|
|
40
|
+
"module": "dist/index.js",
|
|
41
|
+
"types": "./dist/index.d.ts",
|
|
42
|
+
"typesVersions": {
|
|
43
|
+
"*": {
|
|
44
|
+
"components": [
|
|
45
|
+
"./dist/components.d.ts"
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"files": [
|
|
50
|
+
"src",
|
|
51
|
+
"dist",
|
|
52
|
+
"!/**/**.test.**",
|
|
53
|
+
"!/**/__tests__/**"
|
|
54
|
+
],
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@kubb/core": "3.0.0-alpha.0",
|
|
57
|
+
"@kubb/fs": "3.0.0-alpha.0",
|
|
58
|
+
"@kubb/oas": "3.0.0-alpha.0",
|
|
59
|
+
"@kubb/parser-ts": "3.0.0-alpha.0",
|
|
60
|
+
"@kubb/plugin-oas": "3.0.0-alpha.0",
|
|
61
|
+
"@kubb/plugin-ts": "3.0.0-alpha.0",
|
|
62
|
+
"@kubb/react": "3.0.0-alpha.0"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@types/react": "^18.3.3",
|
|
66
|
+
"react": "^18.3.1",
|
|
67
|
+
"tsup": "^8.2.4",
|
|
68
|
+
"typescript": "^5.5.4",
|
|
69
|
+
"@kubb/config-biome": "3.0.0-alpha.0",
|
|
70
|
+
"@kubb/config-ts": "3.0.0-alpha.0",
|
|
71
|
+
"@kubb/config-tsup": "3.0.0-alpha.0"
|
|
72
|
+
},
|
|
73
|
+
"peerDependencies": {
|
|
74
|
+
"@kubb/react": "3.0.0-alpha.0"
|
|
75
|
+
},
|
|
76
|
+
"engines": {
|
|
77
|
+
"node": ">=20"
|
|
78
|
+
},
|
|
79
|
+
"publishConfig": {
|
|
80
|
+
"access": "public",
|
|
81
|
+
"registry": "https://registry.npmjs.org/"
|
|
82
|
+
},
|
|
83
|
+
"scripts": {
|
|
84
|
+
"build": "tsup",
|
|
85
|
+
"clean": "npx rimraf ./dist",
|
|
86
|
+
"lint": "bun biome lint .",
|
|
87
|
+
"lint:fix": "bun biome lint --apply-unsafe .",
|
|
88
|
+
"release": "pnpm publish --no-git-check",
|
|
89
|
+
"release:canary": "bash ../../.github/canary.sh && node ../../scripts/build.js canary && pnpm publish --no-git-check",
|
|
90
|
+
"start": "tsup --watch",
|
|
91
|
+
"test": "vitest --passWithNoTests",
|
|
92
|
+
"typecheck": "tsc -p ./tsconfig.json --noEmit --emitDeclarationOnly false"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { OperationGenerator as Generator } from '@kubb/plugin-oas'
|
|
2
|
+
import { Oas } from '@kubb/plugin-oas/components'
|
|
3
|
+
import { App, createRoot } from '@kubb/react'
|
|
4
|
+
|
|
5
|
+
import { OperationSchema } from './components/OperationSchema.tsx'
|
|
6
|
+
|
|
7
|
+
import type { Operation } from '@kubb/oas'
|
|
8
|
+
import type { OperationMethodResult } from '@kubb/plugin-oas'
|
|
9
|
+
import type { FileMeta, PluginFaker } from './types.ts'
|
|
10
|
+
|
|
11
|
+
export class OperationGenerator extends Generator<PluginFaker['resolvedOptions'], PluginFaker> {
|
|
12
|
+
async operation(operation: Operation, options: PluginFaker['resolvedOptions']): OperationMethodResult<FileMeta> {
|
|
13
|
+
const { oas, pluginManager, plugin, mode } = this.context
|
|
14
|
+
|
|
15
|
+
const root = createRoot({
|
|
16
|
+
logger: pluginManager.logger,
|
|
17
|
+
})
|
|
18
|
+
root.render(
|
|
19
|
+
<App pluginManager={pluginManager} plugin={{ ...plugin, options }} mode={mode}>
|
|
20
|
+
<Oas oas={oas} operations={[operation]} generator={this}>
|
|
21
|
+
<Oas.Operation operation={operation}>
|
|
22
|
+
<OperationSchema.File />
|
|
23
|
+
</Oas.Operation>
|
|
24
|
+
</Oas>
|
|
25
|
+
</App>,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
return root.files
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { SchemaObject } from '@kubb/oas'
|
|
2
|
+
import { SchemaGenerator as Generator } from '@kubb/plugin-oas'
|
|
3
|
+
import type { SchemaMethodResult } from '@kubb/plugin-oas'
|
|
4
|
+
import { Oas } from '@kubb/plugin-oas/components'
|
|
5
|
+
import { App, createRoot } from '@kubb/react'
|
|
6
|
+
import { Schema } from './components/Schema.tsx'
|
|
7
|
+
import type { FileMeta, PluginFaker } from './types.ts'
|
|
8
|
+
|
|
9
|
+
export class SchemaGenerator extends Generator<PluginFaker['resolvedOptions'], PluginFaker> {
|
|
10
|
+
async schema(name: string, schema: SchemaObject, options: PluginFaker['resolvedOptions']): SchemaMethodResult<FileMeta> {
|
|
11
|
+
const { oas, pluginManager, plugin, mode, output } = this.context
|
|
12
|
+
|
|
13
|
+
const root = createRoot({
|
|
14
|
+
logger: pluginManager.logger,
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const tree = this.parse({ schema, name })
|
|
18
|
+
|
|
19
|
+
root.render(
|
|
20
|
+
<App pluginManager={pluginManager} plugin={{ ...plugin, options }} mode={mode}>
|
|
21
|
+
<Oas oas={oas}>
|
|
22
|
+
<Oas.Schema name={name} value={schema} tree={tree}>
|
|
23
|
+
<Schema.File />
|
|
24
|
+
</Oas.Schema>
|
|
25
|
+
</Oas>
|
|
26
|
+
</App>,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
return root.files
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Oas } from '@kubb/plugin-oas/components'
|
|
2
|
+
import { useOas, useOperation, useOperationManager } from '@kubb/plugin-oas/hooks'
|
|
3
|
+
import { File, Parser, useApp } from '@kubb/react'
|
|
4
|
+
import { pluginTsName } from '@kubb/plugin-ts'
|
|
5
|
+
|
|
6
|
+
import { SchemaGenerator } from '../SchemaGenerator.tsx'
|
|
7
|
+
|
|
8
|
+
import type { OperationSchema as OperationSchemaType } from '@kubb/plugin-oas'
|
|
9
|
+
import type { ReactNode } from 'react'
|
|
10
|
+
import type { FileMeta, PluginFaker } from '../types.ts'
|
|
11
|
+
import { Schema } from './Schema.tsx'
|
|
12
|
+
|
|
13
|
+
type Props = {
|
|
14
|
+
description?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function OperationSchema({ description }: Props): ReactNode {
|
|
18
|
+
return <Schema withData={false} description={description} />
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type FileProps = {}
|
|
22
|
+
|
|
23
|
+
OperationSchema.File = function ({}: FileProps): ReactNode {
|
|
24
|
+
const { plugin, pluginManager, mode } = useApp<PluginFaker>()
|
|
25
|
+
|
|
26
|
+
const oas = useOas()
|
|
27
|
+
const { getSchemas, getFile } = useOperationManager()
|
|
28
|
+
const operation = useOperation()
|
|
29
|
+
|
|
30
|
+
const file = getFile(operation)
|
|
31
|
+
const schemas = getSchemas(operation)
|
|
32
|
+
const generator = new SchemaGenerator(plugin.options, {
|
|
33
|
+
oas,
|
|
34
|
+
plugin,
|
|
35
|
+
pluginManager,
|
|
36
|
+
mode,
|
|
37
|
+
override: plugin.options.override,
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const items = [schemas.pathParams, schemas.queryParams, schemas.headerParams, schemas.statusCodes, schemas.request, schemas.response].flat().filter(Boolean)
|
|
41
|
+
|
|
42
|
+
const mapItem = ({ name, schema, description, ...options }: OperationSchemaType, i: number) => {
|
|
43
|
+
// used for this.options.typed
|
|
44
|
+
const typeName = pluginManager.resolveName({
|
|
45
|
+
name,
|
|
46
|
+
pluginKey: [pluginTsName],
|
|
47
|
+
type: 'type',
|
|
48
|
+
})
|
|
49
|
+
const typeFileName = pluginManager.resolveName({
|
|
50
|
+
name: options.operationName || name,
|
|
51
|
+
pluginKey: [pluginTsName],
|
|
52
|
+
type: 'file',
|
|
53
|
+
})
|
|
54
|
+
const typePath = pluginManager.resolvePath({
|
|
55
|
+
baseName: typeFileName,
|
|
56
|
+
pluginKey: [pluginTsName],
|
|
57
|
+
options: { tag: options.operation?.getTags()[0]?.name },
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const tree = generator.parse({ schema, name })
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<Oas.Schema key={i} name={name} value={schema} tree={tree}>
|
|
64
|
+
{typeName && typePath && <File.Import extName={plugin.options.extName} isTypeOnly root={file.path} path={typePath} name={[typeName]} />}
|
|
65
|
+
{plugin.options.dateParser && <File.Import path={plugin.options.dateParser} name={plugin.options.dateParser} />}
|
|
66
|
+
|
|
67
|
+
{mode === 'split' && <Oas.Schema.Imports extName={plugin.options.extName} />}
|
|
68
|
+
<File.Source>
|
|
69
|
+
<OperationSchema description={description} />
|
|
70
|
+
</File.Source>
|
|
71
|
+
</Oas.Schema>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<Parser language="typescript">
|
|
77
|
+
<File<FileMeta> baseName={file.baseName} path={file.path} meta={file.meta}>
|
|
78
|
+
<File.Import name={['faker']} path="@faker-js/faker" />
|
|
79
|
+
{plugin.options.regexGenerator === 'randexp' && <File.Import name={'RandExp'} path={'randexp'} />}
|
|
80
|
+
{items.map(mapItem)}
|
|
81
|
+
</File>
|
|
82
|
+
</Parser>
|
|
83
|
+
)
|
|
84
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { Oas } from '@kubb/plugin-oas/components'
|
|
2
|
+
import { File, Function, useApp, useFile } from '@kubb/react'
|
|
3
|
+
import { pluginTsName } from '@kubb/plugin-ts'
|
|
4
|
+
|
|
5
|
+
import transformers from '@kubb/core/transformers'
|
|
6
|
+
import { schemaKeywords } from '@kubb/plugin-oas'
|
|
7
|
+
import { useSchema } from '@kubb/plugin-oas/hooks'
|
|
8
|
+
import type { ReactNode } from 'react'
|
|
9
|
+
import * as parserFaker from '../parser/index.ts'
|
|
10
|
+
import { pluginFakerName } from '../plugin.ts'
|
|
11
|
+
import type { PluginFaker } from '../types.ts'
|
|
12
|
+
|
|
13
|
+
type Props = {
|
|
14
|
+
description?: string
|
|
15
|
+
withData?: boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function Schema(props: Props): ReactNode {
|
|
19
|
+
const { withData, description } = props
|
|
20
|
+
const { tree, name } = useSchema()
|
|
21
|
+
const {
|
|
22
|
+
pluginManager,
|
|
23
|
+
plugin: {
|
|
24
|
+
options: { dateParser, regexGenerator, mapper, seed },
|
|
25
|
+
},
|
|
26
|
+
} = useApp<PluginFaker>()
|
|
27
|
+
|
|
28
|
+
// all checks are also inside this.schema(React)
|
|
29
|
+
const resolvedName = pluginManager.resolveName({
|
|
30
|
+
name,
|
|
31
|
+
pluginKey: [pluginFakerName],
|
|
32
|
+
type: 'function',
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const typeName = pluginManager.resolveName({
|
|
36
|
+
name,
|
|
37
|
+
pluginKey: [pluginTsName],
|
|
38
|
+
type: 'type',
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const fakerText = parserFaker.joinItems(
|
|
42
|
+
tree
|
|
43
|
+
.map((schema) => parserFaker.parse(undefined, schema, { name: resolvedName, typeName, seed, regexGenerator, mapper, withData, dateParser }))
|
|
44
|
+
.filter(Boolean),
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
let fakerDefaultOverride: '' | '[]' | '{}' | undefined = undefined
|
|
48
|
+
let fakerTextWithOverride = fakerText
|
|
49
|
+
|
|
50
|
+
if (withData && fakerText.startsWith('{')) {
|
|
51
|
+
fakerDefaultOverride = '{}'
|
|
52
|
+
fakerTextWithOverride = `{
|
|
53
|
+
...${fakerText},
|
|
54
|
+
...data
|
|
55
|
+
}`
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (withData && fakerText.startsWith('faker.helpers.arrayElements')) {
|
|
59
|
+
fakerDefaultOverride = '[]'
|
|
60
|
+
fakerTextWithOverride = `[
|
|
61
|
+
...${fakerText},
|
|
62
|
+
...data
|
|
63
|
+
]`
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const params = fakerDefaultOverride ? `data: NonNullable<Partial<${typeName}>> = ${fakerDefaultOverride}` : `data?: NonNullable<Partial<${typeName}>>`
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<>
|
|
70
|
+
<Function
|
|
71
|
+
export
|
|
72
|
+
name={resolvedName}
|
|
73
|
+
JSDoc={{ comments: [description ? `@description ${transformers.jsStringEscape(description)}` : undefined].filter(Boolean) }}
|
|
74
|
+
params={withData ? params : ''}
|
|
75
|
+
returnType={typeName ? `NonNullable<${typeName}>` : ''}
|
|
76
|
+
>
|
|
77
|
+
{seed ? `faker.seed(${JSON.stringify(seed)})` : ''}
|
|
78
|
+
<br />
|
|
79
|
+
<Function.Return>{fakerTextWithOverride}</Function.Return>
|
|
80
|
+
</Function>
|
|
81
|
+
<br />
|
|
82
|
+
</>
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
type FileProps = {}
|
|
87
|
+
|
|
88
|
+
Schema.File = function ({}: FileProps): ReactNode {
|
|
89
|
+
const { pluginManager } = useApp<PluginFaker>()
|
|
90
|
+
const { tree, schema } = useSchema()
|
|
91
|
+
|
|
92
|
+
const withData = tree.some(
|
|
93
|
+
(schema) =>
|
|
94
|
+
schema.keyword === schemaKeywords.array ||
|
|
95
|
+
schema.keyword === schemaKeywords.and ||
|
|
96
|
+
schema.keyword === schemaKeywords.object ||
|
|
97
|
+
schema.keyword === schemaKeywords.union ||
|
|
98
|
+
schema.keyword === schemaKeywords.tuple,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<Oas.Schema.File output={pluginManager.config.output.path}>
|
|
103
|
+
<Schema.Imports />
|
|
104
|
+
<File.Source>
|
|
105
|
+
<Schema description={schema?.description} withData={withData} />
|
|
106
|
+
</File.Source>
|
|
107
|
+
</Oas.Schema.File>
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
Schema.Imports = (): ReactNode => {
|
|
111
|
+
const {
|
|
112
|
+
pluginManager,
|
|
113
|
+
plugin: {
|
|
114
|
+
options: { extName, dateParser, regexGenerator },
|
|
115
|
+
},
|
|
116
|
+
} = useApp<PluginFaker>()
|
|
117
|
+
const { path: root } = useFile()
|
|
118
|
+
const { name, tree, schema } = useSchema()
|
|
119
|
+
|
|
120
|
+
// used for this.options.typed
|
|
121
|
+
const typeName = pluginManager.resolveName({
|
|
122
|
+
name,
|
|
123
|
+
pluginKey: [pluginTsName],
|
|
124
|
+
type: 'type',
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
const typeFileName = pluginManager.resolveName({
|
|
128
|
+
name: name,
|
|
129
|
+
pluginKey: [pluginTsName],
|
|
130
|
+
type: 'file',
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
const typePath = pluginManager.resolvePath({
|
|
134
|
+
baseName: typeFileName,
|
|
135
|
+
pluginKey: [pluginTsName],
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<>
|
|
140
|
+
<File.Import name={['faker']} path="@faker-js/faker" />
|
|
141
|
+
{regexGenerator === 'randexp' && <File.Import name={'RandExp'} path={'randexp'} />}
|
|
142
|
+
{dateParser && <File.Import path={dateParser} name={dateParser} />}
|
|
143
|
+
{typeName && typePath && <File.Import extName={extName} isTypeOnly root={root} path={typePath} name={[typeName]} />}
|
|
144
|
+
</>
|
|
145
|
+
)
|
|
146
|
+
}
|
package/src/index.ts
ADDED