@kubb/core 5.0.0-alpha.30 → 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/dist/{PluginDriver-D110FoJ-.d.ts → PluginDriver-D0dY_hpJ.d.ts} +400 -46
- package/dist/{chunk-ByKO4r7w.cjs → chunk-MlS0t1Af.cjs} +15 -0
- package/dist/chunk-O_arW02_.js +17 -0
- package/dist/hooks.cjs +1 -1
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.ts +3 -4
- package/dist/hooks.js +1 -1
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +98 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +19 -140
- package/dist/index.js +92 -48
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/Kubb.ts +5 -5
- package/src/KubbFile.ts +143 -0
- package/src/PluginDriver.ts +11 -10
- package/src/build.ts +70 -45
- package/src/constants.ts +2 -2
- package/src/{config.ts → defineConfig.ts} +2 -8
- package/src/defineGenerator.ts +5 -5
- package/src/defineParser.ts +57 -0
- package/src/defineResolver.ts +10 -13
- package/src/hooks/useMode.ts +3 -3
- package/src/index.ts +4 -3
- package/src/renderNode.tsx +4 -4
- package/src/types.ts +85 -35
- package/src/utils/TreeNode.ts +7 -7
- package/src/utils/getBarrelFiles.ts +6 -9
- package/src/utils/getConfigs.ts +1 -1
- package/src/utils/isInputPath.ts +8 -0
- package/dist/chunk--u3MIqq1.js +0 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubb/core",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.31",
|
|
4
4
|
"description": "Core functionality for Kubb's plugin-based code generation system, providing the foundation for transforming OpenAPI specifications.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"remeda": "^2.33.7",
|
|
72
72
|
"semver": "^7.7.4",
|
|
73
73
|
"tinyexec": "^1.0.4",
|
|
74
|
-
"@kubb/ast": "5.0.0-alpha.
|
|
74
|
+
"@kubb/ast": "5.0.0-alpha.31"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
77
|
"@types/semver": "^7.7.1",
|
package/src/Kubb.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type * as KubbFile from './KubbFile.ts'
|
|
2
2
|
import type { Strategy } from './PluginDriver.ts'
|
|
3
3
|
import type { Config, Plugin, PluginLifecycleHooks } from './types'
|
|
4
4
|
|
|
@@ -76,7 +76,7 @@ export interface KubbEvents {
|
|
|
76
76
|
/**
|
|
77
77
|
* Emitted when code generation phase completes.
|
|
78
78
|
*/
|
|
79
|
-
'generation:end': [config: Config, files: Array<
|
|
79
|
+
'generation:end': [config: Config, files: Array<KubbFile.ResolvedFile>, sources: Map<KubbFile.Path, string>]
|
|
80
80
|
/**
|
|
81
81
|
* Emitted with a summary of the generation results.
|
|
82
82
|
* Contains summary lines, title, and success status.
|
|
@@ -160,7 +160,7 @@ export interface KubbEvents {
|
|
|
160
160
|
* Emitted when file processing starts.
|
|
161
161
|
* Contains the list of files to be processed.
|
|
162
162
|
*/
|
|
163
|
-
'files:processing:start': [files: Array<
|
|
163
|
+
'files:processing:start': [files: Array<KubbFile.ResolvedFile>]
|
|
164
164
|
/**
|
|
165
165
|
* Emitted for each file being processed, providing progress updates.
|
|
166
166
|
* Contains processed count, total count, percentage, and file details.
|
|
@@ -186,7 +186,7 @@ export interface KubbEvents {
|
|
|
186
186
|
/**
|
|
187
187
|
* The file being processed.
|
|
188
188
|
*/
|
|
189
|
-
file:
|
|
189
|
+
file: KubbFile.ResolvedFile
|
|
190
190
|
/**
|
|
191
191
|
* Kubb configuration (not present in Fabric).
|
|
192
192
|
* Provides access to the current config during file processing.
|
|
@@ -198,7 +198,7 @@ export interface KubbEvents {
|
|
|
198
198
|
* Emitted when file processing completes.
|
|
199
199
|
* Contains the list of processed files.
|
|
200
200
|
*/
|
|
201
|
-
'files:processing:end': [files: Array<
|
|
201
|
+
'files:processing:end': [files: Array<KubbFile.ResolvedFile>]
|
|
202
202
|
|
|
203
203
|
/**
|
|
204
204
|
* Emitted when a plugin starts executing.
|
package/src/KubbFile.ts
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
type ImportName =
|
|
2
|
+
| string
|
|
3
|
+
| Array<
|
|
4
|
+
| string
|
|
5
|
+
| {
|
|
6
|
+
propertyName: string
|
|
7
|
+
name?: string
|
|
8
|
+
}
|
|
9
|
+
>
|
|
10
|
+
|
|
11
|
+
export type Import = {
|
|
12
|
+
/**
|
|
13
|
+
* Import name to be used.
|
|
14
|
+
* @example ["useState"]
|
|
15
|
+
* @example "React"
|
|
16
|
+
*/
|
|
17
|
+
name: ImportName
|
|
18
|
+
/**
|
|
19
|
+
* Path for the import.
|
|
20
|
+
* @example '@kubb/core'
|
|
21
|
+
*/
|
|
22
|
+
path: string
|
|
23
|
+
/**
|
|
24
|
+
* Add type-only import prefix.
|
|
25
|
+
* - `true` generates `import type { Type } from './path'`
|
|
26
|
+
* - `false` generates `import { Type } from './path'`
|
|
27
|
+
* @default false
|
|
28
|
+
*/
|
|
29
|
+
isTypeOnly?: boolean
|
|
30
|
+
/**
|
|
31
|
+
* Import entire module as namespace.
|
|
32
|
+
* - `true` generates `import * as Name from './path'`
|
|
33
|
+
* - `false` generates standard import
|
|
34
|
+
* @default false
|
|
35
|
+
*/
|
|
36
|
+
isNameSpace?: boolean
|
|
37
|
+
/**
|
|
38
|
+
* When root is set it will compute a relative path with `getRelativePath(root, path)`.
|
|
39
|
+
*/
|
|
40
|
+
root?: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type Source = {
|
|
44
|
+
name?: string
|
|
45
|
+
value?: string
|
|
46
|
+
/**
|
|
47
|
+
* Make this source a type-only export.
|
|
48
|
+
* @default false
|
|
49
|
+
*/
|
|
50
|
+
isTypeOnly?: boolean
|
|
51
|
+
/**
|
|
52
|
+
* Include export keyword in source.
|
|
53
|
+
* @default false
|
|
54
|
+
*/
|
|
55
|
+
isExportable?: boolean
|
|
56
|
+
/**
|
|
57
|
+
* Include in barrel file generation.
|
|
58
|
+
* @default false
|
|
59
|
+
*/
|
|
60
|
+
isIndexable?: boolean
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export type Export = {
|
|
64
|
+
/**
|
|
65
|
+
* Export name to be used.
|
|
66
|
+
* @example ["useState"]
|
|
67
|
+
* @example "React"
|
|
68
|
+
*/
|
|
69
|
+
name?: string | Array<string>
|
|
70
|
+
/**
|
|
71
|
+
* Path for the export.
|
|
72
|
+
* @example '@kubb/core'
|
|
73
|
+
*/
|
|
74
|
+
path: string
|
|
75
|
+
/**
|
|
76
|
+
* Add type-only export prefix.
|
|
77
|
+
* - `true` generates `export type { Type } from './path'`
|
|
78
|
+
* - `false` generates `export { Type } from './path'`
|
|
79
|
+
* @default false
|
|
80
|
+
*/
|
|
81
|
+
isTypeOnly?: boolean
|
|
82
|
+
/**
|
|
83
|
+
* Export as aliased namespace.
|
|
84
|
+
* - `true` generates `export * as aliasName from './path'`
|
|
85
|
+
* - `false` generates standard export
|
|
86
|
+
* @default false
|
|
87
|
+
*/
|
|
88
|
+
asAlias?: boolean
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export type Extname = '.ts' | '.js' | '.tsx' | '.json' | `.${string}`
|
|
92
|
+
|
|
93
|
+
export type Mode = 'single' | 'split'
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Name to be used to dynamically create the baseName (based on input.path).
|
|
97
|
+
* Based on UNIX basename.
|
|
98
|
+
* @link https://nodejs.org/api/path.html#pathbasenamepath-suffix
|
|
99
|
+
*/
|
|
100
|
+
export type BaseName = `${string}.${string}`
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Fully qualified path to a specified file.
|
|
104
|
+
*/
|
|
105
|
+
export type Path = string
|
|
106
|
+
|
|
107
|
+
export type File<TMeta extends object = object> = {
|
|
108
|
+
/**
|
|
109
|
+
* Name used to create the path.
|
|
110
|
+
* Based on UNIX basename, `${name}${extname}`.
|
|
111
|
+
* @link https://nodejs.org/api/path.html#pathbasenamepath-suffix
|
|
112
|
+
*/
|
|
113
|
+
baseName: BaseName
|
|
114
|
+
/**
|
|
115
|
+
* Fully qualified path to the file.
|
|
116
|
+
*/
|
|
117
|
+
path: Path
|
|
118
|
+
sources: Array<Source>
|
|
119
|
+
imports: Array<Import>
|
|
120
|
+
exports: Array<Export>
|
|
121
|
+
/**
|
|
122
|
+
* Extra metadata used for barrel/index file generation.
|
|
123
|
+
*/
|
|
124
|
+
meta?: TMeta
|
|
125
|
+
banner?: string
|
|
126
|
+
footer?: string
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export type ResolvedFile<TMeta extends object = object> = File<TMeta> & {
|
|
130
|
+
/**
|
|
131
|
+
* Unique identifier, generated from a hash.
|
|
132
|
+
* @default hash
|
|
133
|
+
*/
|
|
134
|
+
id: string
|
|
135
|
+
/**
|
|
136
|
+
* First part of the `baseName`, derived from the file name.
|
|
137
|
+
* @link https://nodejs.org/api/path.html#pathformatpathobject
|
|
138
|
+
*/
|
|
139
|
+
name: string
|
|
140
|
+
extname: Extname
|
|
141
|
+
imports: Array<Import>
|
|
142
|
+
exports: Array<Export>
|
|
143
|
+
}
|
package/src/PluginDriver.ts
CHANGED
|
@@ -3,9 +3,10 @@ import { performance } from 'node:perf_hooks'
|
|
|
3
3
|
import type { AsyncEventEmitter } from '@internals/utils'
|
|
4
4
|
import { isPromiseRejectedResult, transformReservedWord } from '@internals/utils'
|
|
5
5
|
import type { RootNode } from '@kubb/ast/types'
|
|
6
|
-
import type {
|
|
6
|
+
import type { Fabric as FabricType } from '@kubb/fabric-core/types'
|
|
7
7
|
import { DEFAULT_STUDIO_URL } from './constants.ts'
|
|
8
8
|
import { openInStudio as openInStudioFn } from './devtools.ts'
|
|
9
|
+
import type * as KubbFile from './KubbFile.ts'
|
|
9
10
|
|
|
10
11
|
import type {
|
|
11
12
|
Adapter,
|
|
@@ -59,8 +60,8 @@ type Options = {
|
|
|
59
60
|
*/
|
|
60
61
|
export type GetFileOptions<TOptions = object> = {
|
|
61
62
|
name: string
|
|
62
|
-
mode?:
|
|
63
|
-
extname:
|
|
63
|
+
mode?: KubbFile.Mode
|
|
64
|
+
extname: KubbFile.Extname
|
|
64
65
|
pluginName: string
|
|
65
66
|
options?: TOptions
|
|
66
67
|
}
|
|
@@ -74,7 +75,7 @@ export type GetFileOptions<TOptions = object> = {
|
|
|
74
75
|
* getMode('src/gen/types') // 'split'
|
|
75
76
|
* ```
|
|
76
77
|
*/
|
|
77
|
-
export function getMode(fileOrFolder: string | undefined | null):
|
|
78
|
+
export function getMode(fileOrFolder: string | undefined | null): KubbFile.Mode {
|
|
78
79
|
if (!fileOrFolder) {
|
|
79
80
|
return 'split'
|
|
80
81
|
}
|
|
@@ -131,7 +132,7 @@ export class PluginDriver {
|
|
|
131
132
|
get root(): string {
|
|
132
133
|
return resolve(driver.config.root, driver.config.output.path)
|
|
133
134
|
},
|
|
134
|
-
getMode(output: { path: string }):
|
|
135
|
+
getMode(output: { path: string }): KubbFile.Mode {
|
|
135
136
|
return getMode(resolve(driver.config.root, driver.config.output.path, output.path))
|
|
136
137
|
},
|
|
137
138
|
events: driver.options.events,
|
|
@@ -139,10 +140,10 @@ export class PluginDriver {
|
|
|
139
140
|
getPlugin: driver.getPlugin.bind(driver),
|
|
140
141
|
requirePlugin: driver.requirePlugin.bind(driver),
|
|
141
142
|
driver: driver,
|
|
142
|
-
addFile: async (...files: Array<
|
|
143
|
+
addFile: async (...files: Array<KubbFile.File>) => {
|
|
143
144
|
await this.options.fabric.addFile(...files)
|
|
144
145
|
},
|
|
145
|
-
upsertFile: async (...files: Array<
|
|
146
|
+
upsertFile: async (...files: Array<KubbFile.File>) => {
|
|
146
147
|
await this.options.fabric.upsertFile(...files)
|
|
147
148
|
},
|
|
148
149
|
get rootNode(): RootNode | undefined {
|
|
@@ -206,7 +207,7 @@ export class PluginDriver {
|
|
|
206
207
|
/**
|
|
207
208
|
* @deprecated use resolvers context instead
|
|
208
209
|
*/
|
|
209
|
-
getFile<TOptions = object>({ name, mode, extname, pluginName, options }: GetFileOptions<TOptions>):
|
|
210
|
+
getFile<TOptions = object>({ name, mode, extname, pluginName, options }: GetFileOptions<TOptions>): KubbFile.File<{ pluginName: string }> {
|
|
210
211
|
const resolvedName = mode ? (mode === 'single' ? '' : this.resolveName({ name, pluginName, type: 'file' })) : name
|
|
211
212
|
|
|
212
213
|
const path = this.resolvePath({
|
|
@@ -222,7 +223,7 @@ export class PluginDriver {
|
|
|
222
223
|
|
|
223
224
|
return {
|
|
224
225
|
path,
|
|
225
|
-
baseName: basename(path) as
|
|
226
|
+
baseName: basename(path) as KubbFile.File['baseName'],
|
|
226
227
|
meta: {
|
|
227
228
|
pluginName,
|
|
228
229
|
},
|
|
@@ -235,7 +236,7 @@ export class PluginDriver {
|
|
|
235
236
|
/**
|
|
236
237
|
* @deprecated use resolvers context instead
|
|
237
238
|
*/
|
|
238
|
-
resolvePath = <TOptions = object>(params: ResolvePathParams<TOptions>):
|
|
239
|
+
resolvePath = <TOptions = object>(params: ResolvePathParams<TOptions>): KubbFile.Path => {
|
|
239
240
|
const root = resolve(this.config.root, this.config.output.path)
|
|
240
241
|
const defaultPath = resolve(root, params.baseName)
|
|
241
242
|
|
package/src/build.ts
CHANGED
|
@@ -2,12 +2,12 @@ import { dirname, relative, resolve } from 'node:path'
|
|
|
2
2
|
import { AsyncEventEmitter, BuildError, exists, formatMs, getElapsedMs, getRelativePath, URLPath } from '@internals/utils'
|
|
3
3
|
import { transform, walk } from '@kubb/ast'
|
|
4
4
|
import type { OperationNode } from '@kubb/ast/types'
|
|
5
|
-
import type {
|
|
5
|
+
import type { Fabric as FabricType } from '@kubb/fabric-core/types'
|
|
6
6
|
import { createFabric } from '@kubb/react-fabric'
|
|
7
|
-
import { typescriptParser } from '@kubb/react-fabric/parsers'
|
|
8
7
|
import { fsPlugin } from '@kubb/react-fabric/plugins'
|
|
9
|
-
import { isInputPath } from './config.ts'
|
|
10
8
|
import { BARREL_FILENAME, DEFAULT_BANNER, DEFAULT_CONCURRENCY, DEFAULT_EXTENSION, DEFAULT_STUDIO_URL } from './constants.ts'
|
|
9
|
+
import { defineParser } from './defineParser.ts'
|
|
10
|
+
import type * as KubbFile from './KubbFile.ts'
|
|
11
11
|
import { PluginDriver } from './PluginDriver.ts'
|
|
12
12
|
import { applyHookResult } from './renderNode.tsx'
|
|
13
13
|
import { fsStorage } from './storages/fsStorage.ts'
|
|
@@ -15,6 +15,7 @@ import type { AdapterSource, Config, KubbEvents, Plugin, PluginContext, Storage,
|
|
|
15
15
|
import { getDiagnosticInfo } from './utils/diagnostics.ts'
|
|
16
16
|
import type { FileMetaBase } from './utils/getBarrelFiles.ts'
|
|
17
17
|
import { getBarrelFiles } from './utils/getBarrelFiles.ts'
|
|
18
|
+
import { isInputPath } from './utils/isInputPath.ts'
|
|
18
19
|
|
|
19
20
|
type BuildOptions = {
|
|
20
21
|
config: UserConfig
|
|
@@ -30,7 +31,7 @@ type BuildOutput = {
|
|
|
30
31
|
*/
|
|
31
32
|
failedPlugins: Set<{ plugin: Plugin; error: Error }>
|
|
32
33
|
fabric: FabricType
|
|
33
|
-
files: Array<
|
|
34
|
+
files: Array<KubbFile.ResolvedFile>
|
|
34
35
|
driver: PluginDriver
|
|
35
36
|
/**
|
|
36
37
|
* Elapsed time in milliseconds for each plugin, keyed by plugin name.
|
|
@@ -40,7 +41,7 @@ type BuildOutput = {
|
|
|
40
41
|
/**
|
|
41
42
|
* Raw generated source, keyed by absolute file path.
|
|
42
43
|
*/
|
|
43
|
-
sources: Map<
|
|
44
|
+
sources: Map<KubbFile.Path, string>
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
/**
|
|
@@ -50,7 +51,8 @@ type SetupResult = {
|
|
|
50
51
|
events: AsyncEventEmitter<KubbEvents>
|
|
51
52
|
fabric: FabricType
|
|
52
53
|
driver: PluginDriver
|
|
53
|
-
sources: Map<
|
|
54
|
+
sources: Map<KubbFile.Path, string>
|
|
55
|
+
config: Config
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
/**
|
|
@@ -60,6 +62,7 @@ type SetupResult = {
|
|
|
60
62
|
* - Applies config defaults (`root`, `output.*`, `devtools`).
|
|
61
63
|
* - Creates the Fabric instance and wires storage, format, and lint hooks.
|
|
62
64
|
* - Runs the adapter (if configured) to produce the universal `RootNode`.
|
|
65
|
+
* When no adapter is supplied and `@kubb/adapter-oas` is installed as an
|
|
63
66
|
*
|
|
64
67
|
* Pass the returned {@link SetupResult} directly to {@link safeBuild} or {@link build}
|
|
65
68
|
* via the `overrides` argument to reuse the same infrastructure across multiple runs.
|
|
@@ -67,7 +70,7 @@ type SetupResult = {
|
|
|
67
70
|
export async function setup(options: BuildOptions): Promise<SetupResult> {
|
|
68
71
|
const { config: userConfig, events = new AsyncEventEmitter<KubbEvents>() } = options
|
|
69
72
|
|
|
70
|
-
const sources: Map<
|
|
73
|
+
const sources: Map<KubbFile.Path, string> = new Map<KubbFile.Path, string>()
|
|
71
74
|
const diagnosticInfo = getDiagnosticInfo()
|
|
72
75
|
|
|
73
76
|
if (Array.isArray(userConfig.input)) {
|
|
@@ -115,9 +118,15 @@ export async function setup(options: BuildOptions): Promise<SetupResult> {
|
|
|
115
118
|
}
|
|
116
119
|
}
|
|
117
120
|
|
|
118
|
-
|
|
121
|
+
if (!userConfig.adapter) {
|
|
122
|
+
throw new Error('Adapter should be defined')
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const config: Config = {
|
|
119
126
|
root: userConfig.root || process.cwd(),
|
|
120
127
|
...userConfig,
|
|
128
|
+
parsers: userConfig.parsers ?? [],
|
|
129
|
+
adapter: userConfig.adapter,
|
|
121
130
|
output: {
|
|
122
131
|
write: true,
|
|
123
132
|
barrelType: 'named',
|
|
@@ -138,19 +147,35 @@ export async function setup(options: BuildOptions): Promise<SetupResult> {
|
|
|
138
147
|
// storage or fall back to fsStorage (backwards-compatible default).
|
|
139
148
|
// Keys are root-relative (e.g. `src/gen/api/getPets.ts`) so fsStorage()
|
|
140
149
|
// needs no configuration — it resolves them against process.cwd().
|
|
141
|
-
const storage: Storage | null =
|
|
150
|
+
const storage: Storage | null = config.output.write === false ? null : (config.output.storage ?? fsStorage())
|
|
142
151
|
|
|
143
|
-
if (
|
|
152
|
+
if (config.output.clean) {
|
|
144
153
|
await events.emit('debug', {
|
|
145
154
|
date: new Date(),
|
|
146
|
-
logs: ['Cleaning output directories', ` • Output: ${
|
|
155
|
+
logs: ['Cleaning output directories', ` • Output: ${config.output.path}`],
|
|
147
156
|
})
|
|
148
|
-
await storage?.clear(resolve(
|
|
157
|
+
await storage?.clear(resolve(config.root, config.output.path))
|
|
149
158
|
}
|
|
150
159
|
|
|
151
160
|
const fabric = createFabric()
|
|
152
161
|
fabric.use(fsPlugin)
|
|
153
|
-
|
|
162
|
+
|
|
163
|
+
for (const parser of config.parsers) {
|
|
164
|
+
fabric.use(parser)
|
|
165
|
+
}
|
|
166
|
+
// Catch-all fallback: joins all source values for any unhandled extension
|
|
167
|
+
fabric.use(
|
|
168
|
+
defineParser({
|
|
169
|
+
name: 'fallback',
|
|
170
|
+
extNames: undefined,
|
|
171
|
+
parse(file) {
|
|
172
|
+
return file.sources
|
|
173
|
+
.map((item) => item.value)
|
|
174
|
+
.filter((value): value is string => value != null)
|
|
175
|
+
.join('\n\n')
|
|
176
|
+
},
|
|
177
|
+
}),
|
|
178
|
+
)
|
|
154
179
|
|
|
155
180
|
fabric.context.on('files:processing:start', (files) => {
|
|
156
181
|
events.emit('files:processing:start', files)
|
|
@@ -164,13 +189,13 @@ export async function setup(options: BuildOptions): Promise<SetupResult> {
|
|
|
164
189
|
const { file, source } = params
|
|
165
190
|
await events.emit('file:processing:update', {
|
|
166
191
|
...params,
|
|
167
|
-
config:
|
|
192
|
+
config: config,
|
|
168
193
|
source,
|
|
169
194
|
})
|
|
170
195
|
|
|
171
196
|
if (source) {
|
|
172
197
|
// Key is root-relative so it's meaningful for any backend (fs, S3, Redis…)
|
|
173
|
-
const key = relative(resolve(
|
|
198
|
+
const key = relative(resolve(config.root), file.path)
|
|
174
199
|
await storage?.setItem(key, source)
|
|
175
200
|
sources.set(file.path, source)
|
|
176
201
|
}
|
|
@@ -186,45 +211,45 @@ export async function setup(options: BuildOptions): Promise<SetupResult> {
|
|
|
186
211
|
|
|
187
212
|
await events.emit('debug', {
|
|
188
213
|
date: new Date(),
|
|
189
|
-
logs: [
|
|
190
|
-
'✓ Fabric initialized',
|
|
191
|
-
` • Storage: ${storage ? storage.name : 'disabled (dry-run)'}`,
|
|
192
|
-
` • Barrel type: ${definedConfig.output.barrelType || 'none'}`,
|
|
193
|
-
],
|
|
214
|
+
logs: ['✓ Fabric initialized', ` • Storage: ${storage ? storage.name : 'disabled (dry-run)'}`, ` • Barrel type: ${config.output.barrelType || 'none'}`],
|
|
194
215
|
})
|
|
195
216
|
|
|
196
|
-
const
|
|
217
|
+
const driver = new PluginDriver(config, {
|
|
197
218
|
fabric,
|
|
198
219
|
events,
|
|
199
220
|
concurrency: DEFAULT_CONCURRENCY,
|
|
200
221
|
})
|
|
201
222
|
|
|
202
|
-
// Run the adapter
|
|
203
|
-
if (definedConfig.adapter) {
|
|
204
|
-
const source = inputToAdapterSource(definedConfig)
|
|
223
|
+
// Run the adapter to produce the universal RootNode.
|
|
205
224
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
225
|
+
const adapter = config.adapter
|
|
226
|
+
if (!adapter) {
|
|
227
|
+
throw new Error('No adapter configured. Please provide an adapter in your kubb.config.ts.')
|
|
228
|
+
}
|
|
229
|
+
const source = inputToAdapterSource(config)
|
|
210
230
|
|
|
211
|
-
|
|
212
|
-
|
|
231
|
+
await events.emit('debug', {
|
|
232
|
+
date: new Date(),
|
|
233
|
+
logs: [`Running adapter: ${adapter.name}`],
|
|
234
|
+
})
|
|
213
235
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
236
|
+
driver.adapter = adapter
|
|
237
|
+
driver.rootNode = await adapter.parse(source)
|
|
238
|
+
|
|
239
|
+
await events.emit('debug', {
|
|
240
|
+
date: new Date(),
|
|
241
|
+
logs: [
|
|
242
|
+
`✓ Adapter '${adapter.name}' resolved RootNode`,
|
|
243
|
+
` • Schemas: ${driver.rootNode.schemas.length}`,
|
|
244
|
+
` • Operations: ${driver.rootNode.operations.length}`,
|
|
245
|
+
],
|
|
246
|
+
})
|
|
223
247
|
|
|
224
248
|
return {
|
|
249
|
+
config,
|
|
225
250
|
events,
|
|
226
251
|
fabric,
|
|
227
|
-
driver
|
|
252
|
+
driver,
|
|
228
253
|
sources,
|
|
229
254
|
}
|
|
230
255
|
}
|
|
@@ -266,7 +291,7 @@ export async function build(options: BuildOptions, overrides?: SetupResult): Pro
|
|
|
266
291
|
* - Each hook accepts a single handler **or an array** — all entries are called in sequence.
|
|
267
292
|
* - Nodes that are excluded by `exclude`/`include` plugin options are skipped automatically.
|
|
268
293
|
* - Return values are handled via `applyHookResult`: React elements are rendered,
|
|
269
|
-
* `
|
|
294
|
+
* `KubbFile.File[]` are written via upsert, and `void` is a no-op (manual handling).
|
|
270
295
|
* - Barrel files are generated automatically when `output.barrelType` is set.
|
|
271
296
|
*/
|
|
272
297
|
async function runPluginAstHooks(plugin: Plugin, context: PluginContext): Promise<void> {
|
|
@@ -422,7 +447,7 @@ export async function safeBuild(options: BuildOptions, overrides?: SetupResult):
|
|
|
422
447
|
existingBarrel?.exports?.flatMap((e) => (Array.isArray(e.name) ? e.name : [e.name])).filter((n): n is string => Boolean(n)) ?? [],
|
|
423
448
|
)
|
|
424
449
|
|
|
425
|
-
const rootFile:
|
|
450
|
+
const rootFile: KubbFile.File = {
|
|
426
451
|
path: rootPath,
|
|
427
452
|
baseName: BARREL_FILENAME,
|
|
428
453
|
exports: buildBarrelExports({ barrelFiles, rootDir, existingExports, config, driver }),
|
|
@@ -473,14 +498,14 @@ export async function safeBuild(options: BuildOptions, overrides?: SetupResult):
|
|
|
473
498
|
}
|
|
474
499
|
|
|
475
500
|
type BuildBarrelExportsParams = {
|
|
476
|
-
barrelFiles:
|
|
501
|
+
barrelFiles: KubbFile.ResolvedFile[]
|
|
477
502
|
rootDir: string
|
|
478
503
|
existingExports: Set<string>
|
|
479
504
|
config: Config
|
|
480
505
|
driver: PluginDriver
|
|
481
506
|
}
|
|
482
507
|
|
|
483
|
-
function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, driver }: BuildBarrelExportsParams):
|
|
508
|
+
function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, driver }: BuildBarrelExportsParams): KubbFile.Export[] {
|
|
484
509
|
const pluginNameMap = new Map<string, Plugin>()
|
|
485
510
|
for (const plugin of driver.plugins.values()) {
|
|
486
511
|
pluginNameMap.set(plugin.name, plugin)
|
|
@@ -512,7 +537,7 @@ function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, dri
|
|
|
512
537
|
name: exportName,
|
|
513
538
|
path: getRelativePath(rootDir, file.path),
|
|
514
539
|
isTypeOnly: config.output.barrelType === 'all' ? containsOnlyTypes : source.isTypeOnly,
|
|
515
|
-
} satisfies
|
|
540
|
+
} satisfies KubbFile.Export,
|
|
516
541
|
]
|
|
517
542
|
})
|
|
518
543
|
})
|
package/src/constants.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type * as KubbFile from './KubbFile.ts'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Base URL for the Kubb Studio web app.
|
|
@@ -23,7 +23,7 @@ export const DEFAULT_BANNER = 'simple' as const
|
|
|
23
23
|
/**
|
|
24
24
|
* Default file-extension mapping used when no explicit mapping is configured.
|
|
25
25
|
*/
|
|
26
|
-
export const DEFAULT_EXTENSION: Record<
|
|
26
|
+
export const DEFAULT_EXTENSION: Record<KubbFile.Extname, KubbFile.Extname | ''> = { '.ts': '.ts' }
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Characters recognized as path separators on both POSIX and Windows.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PossiblePromise } from '@internals/utils'
|
|
2
|
-
import type {
|
|
2
|
+
import type { UserConfig } from './types.ts'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* CLI options derived from command-line flags.
|
|
@@ -42,16 +42,10 @@ export type ConfigInput = PossiblePromise<UserConfig | UserConfig[]> | ((cli: CL
|
|
|
42
42
|
* root: 'src',
|
|
43
43
|
* plugins: [myPlugin()],
|
|
44
44
|
* }))
|
|
45
|
+
* @deprecated as of Kubb v5, @kubb/core will not expose `defineConfig` anymore. use the `kubb` package instead
|
|
45
46
|
*/
|
|
46
47
|
export function defineConfig(config: (cli: CLIOptions) => PossiblePromise<UserConfig | UserConfig[]>): typeof config
|
|
47
48
|
export function defineConfig(config: PossiblePromise<UserConfig | UserConfig[]>): typeof config
|
|
48
49
|
export function defineConfig(config: ConfigInput): ConfigInput {
|
|
49
50
|
return config
|
|
50
51
|
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Type guard to check if a given config has an `input.path`.
|
|
54
|
-
*/
|
|
55
|
-
export function isInputPath(config: UserConfig | undefined): config is UserConfig<InputPath> {
|
|
56
|
-
return typeof config?.input === 'object' && config.input !== null && 'path' in config.input
|
|
57
|
-
}
|
package/src/defineGenerator.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { PossiblePromise } from '@internals/utils'
|
|
2
2
|
import type { OperationNode, SchemaNode } from '@kubb/ast/types'
|
|
3
|
-
import type { FabricFile } from '@kubb/fabric-core/types'
|
|
4
3
|
import type { FabricReactNode } from '@kubb/react-fabric/types'
|
|
4
|
+
import type * as KubbFile from './KubbFile.ts'
|
|
5
5
|
import { applyHookResult } from './renderNode.tsx'
|
|
6
6
|
import type { GeneratorContext, PluginFactoryOptions } from './types.ts'
|
|
7
7
|
|
|
@@ -13,7 +13,7 @@ export type { GeneratorContext } from './types.ts'
|
|
|
13
13
|
* giving full access to `this.config`, `this.resolver`, `this.adapter`, `this.fabric`,
|
|
14
14
|
* `this.driver`, etc.
|
|
15
15
|
*
|
|
16
|
-
* Return a React element, an array of `
|
|
16
|
+
* Return a React element, an array of `KubbFile.File`, or `void` to handle file
|
|
17
17
|
* writing manually via `this.upsertFile`. Both React and core (non-React) generators
|
|
18
18
|
* use the same method signatures — the return type determines how output is handled.
|
|
19
19
|
*
|
|
@@ -43,7 +43,7 @@ export type Generator<TOptions extends PluginFactoryOptions = PluginFactoryOptio
|
|
|
43
43
|
this: GeneratorContext<TOptions>,
|
|
44
44
|
node: SchemaNode,
|
|
45
45
|
options: TOptions['resolvedOptions'],
|
|
46
|
-
) => PossiblePromise<FabricReactNode | Array<
|
|
46
|
+
) => PossiblePromise<FabricReactNode | Array<KubbFile.File> | void>
|
|
47
47
|
/**
|
|
48
48
|
* Called for each operation node in the AST walk.
|
|
49
49
|
* `this` is the parent plugin's context with `adapter` and `rootNode` guaranteed present.
|
|
@@ -52,7 +52,7 @@ export type Generator<TOptions extends PluginFactoryOptions = PluginFactoryOptio
|
|
|
52
52
|
this: GeneratorContext<TOptions>,
|
|
53
53
|
node: OperationNode,
|
|
54
54
|
options: TOptions['resolvedOptions'],
|
|
55
|
-
) => PossiblePromise<FabricReactNode | Array<
|
|
55
|
+
) => PossiblePromise<FabricReactNode | Array<KubbFile.File> | void>
|
|
56
56
|
/**
|
|
57
57
|
* Called once after all operations have been walked.
|
|
58
58
|
* `this` is the parent plugin's context with `adapter` and `rootNode` guaranteed present.
|
|
@@ -61,7 +61,7 @@ export type Generator<TOptions extends PluginFactoryOptions = PluginFactoryOptio
|
|
|
61
61
|
this: GeneratorContext<TOptions>,
|
|
62
62
|
nodes: Array<OperationNode>,
|
|
63
63
|
options: TOptions['resolvedOptions'],
|
|
64
|
-
) => PossiblePromise<FabricReactNode | Array<
|
|
64
|
+
) => PossiblePromise<FabricReactNode | Array<KubbFile.File> | void>
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
/**
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type * as KubbFile from './KubbFile.ts'
|
|
2
|
+
|
|
3
|
+
type PrintOptions = {
|
|
4
|
+
extname?: KubbFile.Extname
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type Parser<TMeta extends object = any> = {
|
|
8
|
+
name: string
|
|
9
|
+
type: 'parser'
|
|
10
|
+
/**
|
|
11
|
+
* File extensions this parser handles.
|
|
12
|
+
* Use `undefined` to create a catch-all fallback parser.
|
|
13
|
+
*
|
|
14
|
+
* @example ['.ts', '.js']
|
|
15
|
+
*/
|
|
16
|
+
extNames: Array<KubbFile.Extname> | undefined
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated Will be removed once Fabric no longer requires it.
|
|
19
|
+
* @default () => {}
|
|
20
|
+
*/
|
|
21
|
+
install(...args: unknown[]): void | Promise<void>
|
|
22
|
+
/**
|
|
23
|
+
* Convert a resolved file to a string.
|
|
24
|
+
*/
|
|
25
|
+
parse(file: KubbFile.ResolvedFile<TMeta>, options?: PrintOptions): Promise<string> | string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type UserParser<TMeta extends object = any> = Omit<Parser<TMeta>, 'type' | 'install'> & {
|
|
29
|
+
install?(...args: unknown[]): void | Promise<void>
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Defines a parser with type safety.
|
|
34
|
+
*
|
|
35
|
+
* Use this function to create parsers that transform generated files to strings
|
|
36
|
+
* based on their extension.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { defineParser } from '@kubb/core'
|
|
41
|
+
*
|
|
42
|
+
* export const jsonParser = defineParser({
|
|
43
|
+
* name: 'json',
|
|
44
|
+
* extNames: ['.json'],
|
|
45
|
+
* parse(file) {
|
|
46
|
+
* return file.sources.map((s) => s.value).join('\n')
|
|
47
|
+
* },
|
|
48
|
+
* })
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export function defineParser<TMeta extends object = any>(parser: UserParser<TMeta>): Parser<TMeta> {
|
|
52
|
+
return {
|
|
53
|
+
install() {},
|
|
54
|
+
type: 'parser',
|
|
55
|
+
...parser,
|
|
56
|
+
}
|
|
57
|
+
}
|