@kubb/core 3.0.0-alpha.3 → 3.0.0-alpha.30
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/README.md +13 -4
- package/dist/{FileManager-Bw-FNS3q.d.cts → FileManager-CqvmdzNO.d.cts} +128 -90
- package/dist/{FileManager-BW--rO8q.d.ts → FileManager-DIArE3b0.d.ts} +128 -90
- package/dist/chunk-2EU7DMPM.js +96 -0
- package/dist/chunk-2EU7DMPM.js.map +1 -0
- package/dist/{chunk-34BPAXR2.cjs → chunk-2UQARE2O.cjs} +54 -37
- package/dist/chunk-2UQARE2O.cjs.map +1 -0
- package/dist/chunk-4X5FFJPJ.js +8 -13
- package/dist/chunk-4X5FFJPJ.js.map +1 -1
- package/dist/{chunk-3OXCZ5DJ.js → chunk-E6CN2CZC.js} +63 -54
- package/dist/chunk-E6CN2CZC.js.map +1 -0
- package/dist/{chunk-25NKJ3DV.js → chunk-HBQM723K.js} +13 -27
- package/dist/chunk-HBQM723K.js.map +1 -0
- package/dist/{chunk-LM2YQC3T.cjs → chunk-LLKRRIBF.cjs} +81 -51
- package/dist/chunk-LLKRRIBF.cjs.map +1 -0
- package/dist/chunk-MD2LDZ3Z.js +889 -0
- package/dist/chunk-MD2LDZ3Z.js.map +1 -0
- package/dist/chunk-OX2X7B4Z.cjs +101 -0
- package/dist/chunk-OX2X7B4Z.cjs.map +1 -0
- package/dist/{chunk-67C6RBGQ.cjs → chunk-RIW2LFFQ.cjs} +28 -29
- package/dist/chunk-RIW2LFFQ.cjs.map +1 -0
- package/dist/chunk-SX5FHSVT.cjs +1532 -0
- package/dist/chunk-SX5FHSVT.cjs.map +1 -0
- package/dist/chunk-VBGWLAET.cjs +42 -0
- package/dist/chunk-VBGWLAET.cjs.map +1 -0
- package/dist/index.cjs +553 -619
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -22
- package/dist/index.d.ts +7 -22
- package/dist/index.js +444 -525
- package/dist/index.js.map +1 -1
- package/dist/{logger-DChjnJMn.d.cts → logger-DvbHXjIO.d.cts} +29 -19
- package/dist/{logger-DChjnJMn.d.ts → logger-DvbHXjIO.d.ts} +29 -19
- package/dist/logger.cjs +25 -15
- package/dist/logger.cjs.map +1 -1
- package/dist/logger.d.cts +1 -2
- package/dist/logger.d.ts +1 -2
- package/dist/logger.js +3 -15
- package/dist/logger.js.map +1 -1
- package/dist/mocks.cjs +42 -31
- package/dist/mocks.cjs.map +1 -1
- package/dist/mocks.d.cts +7 -9
- package/dist/mocks.d.ts +7 -9
- package/dist/mocks.js +35 -33
- package/dist/mocks.js.map +1 -1
- package/dist/{prompt-6FWP747F.cjs → prompt-2PN2F25D.cjs} +89 -89
- package/dist/prompt-2PN2F25D.cjs.map +1 -0
- package/dist/{prompt-HK3MWREM.js → prompt-WQQUN22Z.js} +9 -15
- package/dist/prompt-WQQUN22Z.js.map +1 -0
- package/dist/transformers.cjs +216 -49
- package/dist/transformers.cjs.map +1 -1
- package/dist/transformers.d.cts +2 -4
- package/dist/transformers.d.ts +2 -4
- package/dist/transformers.js +149 -35
- package/dist/transformers.js.map +1 -1
- package/dist/utils.cjs +65 -26
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +29 -3
- package/dist/utils.d.ts +29 -3
- package/dist/utils.js +3 -26
- package/dist/utils.js.map +1 -1
- package/package.json +11 -14
- package/src/BarrelManager.ts +95 -109
- package/src/{Generator.ts → BaseGenerator.ts} +1 -1
- package/src/FileManager.ts +199 -304
- package/src/PackageManager.ts +1 -1
- package/src/PluginManager.ts +152 -93
- package/src/PromiseManager.ts +1 -1
- package/src/__snapshots__/barrel.json +73 -0
- package/src/__snapshots__/grouped.json +120 -0
- package/src/__snapshots__/ordered.json +68 -0
- package/src/build.ts +86 -131
- package/src/config.ts +2 -4
- package/src/errors.ts +0 -11
- package/src/index.ts +2 -3
- package/src/logger.ts +76 -34
- package/src/plugin.ts +2 -5
- package/src/transformers/escape.ts +0 -10
- package/src/transformers/index.ts +2 -3
- package/src/transformers/stringify.ts +1 -1
- package/src/transformers/trim.ts +0 -4
- package/src/types.ts +52 -20
- package/src/utils/TreeNode.ts +132 -50
- package/src/utils/executeStrategies.ts +3 -3
- package/src/utils/index.ts +2 -1
- package/src/utils/parser.ts +156 -0
- package/dist/chunk-25NKJ3DV.js.map +0 -1
- package/dist/chunk-34BPAXR2.cjs.map +0 -1
- package/dist/chunk-3OXCZ5DJ.js.map +0 -1
- package/dist/chunk-5JZNFPUP.js +0 -309
- package/dist/chunk-5JZNFPUP.js.map +0 -1
- package/dist/chunk-67C6RBGQ.cjs.map +0 -1
- package/dist/chunk-ADC5UNZ5.cjs +0 -1227
- package/dist/chunk-ADC5UNZ5.cjs.map +0 -1
- package/dist/chunk-HMLY7DHA.js +0 -16
- package/dist/chunk-HMLY7DHA.js.map +0 -1
- package/dist/chunk-JKZG2IJR.js +0 -283
- package/dist/chunk-JKZG2IJR.js.map +0 -1
- package/dist/chunk-LM2YQC3T.cjs.map +0 -1
- package/dist/chunk-PZT4CTBV.cjs +0 -299
- package/dist/chunk-PZT4CTBV.cjs.map +0 -1
- package/dist/chunk-SA2GZKXS.js +0 -596
- package/dist/chunk-SA2GZKXS.js.map +0 -1
- package/dist/chunk-XCPFG6DO.cjs +0 -66
- package/dist/chunk-XCPFG6DO.cjs.map +0 -1
- package/dist/chunk-YTSNYMHW.cjs +0 -320
- package/dist/chunk-YTSNYMHW.cjs.map +0 -1
- package/dist/prompt-6FWP747F.cjs.map +0 -1
- package/dist/prompt-HK3MWREM.js.map +0 -1
- package/schema.json +0 -86
- package/src/utils/cache.ts +0 -35
- package/src/utils/getParser.ts +0 -17
package/src/plugin.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
2
|
|
|
3
|
-
import { createPluginCache } from './utils/cache.ts'
|
|
4
|
-
|
|
5
3
|
import type { FileManager } from './FileManager.ts'
|
|
6
4
|
import type { PluginManager } from './PluginManager.ts'
|
|
7
5
|
import type { Plugin, PluginContext, PluginFactoryOptions, UserPluginWithLifeCycle } from './types.ts'
|
|
@@ -46,7 +44,7 @@ export const pluginCore = createPlugin<PluginCore>((options) => {
|
|
|
46
44
|
return options.getPlugins()
|
|
47
45
|
},
|
|
48
46
|
get plugin() {
|
|
49
|
-
// see pluginManger.#execute where we override with `.call` the
|
|
47
|
+
// see pluginManger.#execute where we override with `.call` the context with the correct plugin
|
|
50
48
|
return options.plugin as NonNullable<Options['plugin']>
|
|
51
49
|
},
|
|
52
50
|
logger,
|
|
@@ -63,11 +61,10 @@ export const pluginCore = createPlugin<PluginCore>((options) => {
|
|
|
63
61
|
},
|
|
64
62
|
resolvePath,
|
|
65
63
|
resolveName,
|
|
66
|
-
cache: createPluginCache(),
|
|
67
64
|
}
|
|
68
65
|
},
|
|
69
66
|
resolvePath(baseName) {
|
|
70
|
-
const root = path.resolve(
|
|
67
|
+
const root = path.resolve(options.config.root, options.config.output.path)
|
|
71
68
|
|
|
72
69
|
return path.resolve(root, baseName)
|
|
73
70
|
},
|
|
@@ -29,13 +29,3 @@ export function jsStringEscape(input: any): string {
|
|
|
29
29
|
}
|
|
30
30
|
})
|
|
31
31
|
}
|
|
32
|
-
|
|
33
|
-
export function escapeStringRegexp(string: string) {
|
|
34
|
-
if (typeof string !== 'string') {
|
|
35
|
-
throw new TypeError('Expected a string')
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Escape characters with special meaning either inside or outside character sets.
|
|
39
|
-
// Use a simple backslash escape when it’s always valid, and a `\xnn` escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar.
|
|
40
|
-
return string.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d')
|
|
41
|
-
}
|
|
@@ -11,7 +11,7 @@ import { searchAndReplace } from './searchAndReplace.ts'
|
|
|
11
11
|
import { stringify, stringifyObject } from './stringify.ts'
|
|
12
12
|
import { toRegExp, toRegExpString } from './toRegExp.ts'
|
|
13
13
|
import { transformReservedWord } from './transformReservedWord.ts'
|
|
14
|
-
import { trim,
|
|
14
|
+
import { trim, trimQuotes } from './trim.ts'
|
|
15
15
|
|
|
16
16
|
export { camelCase, pascalCase, pathCase } from './casing.ts'
|
|
17
17
|
export { combineCodes } from './combineCodes.ts'
|
|
@@ -23,7 +23,7 @@ export { searchAndReplace } from './searchAndReplace.ts'
|
|
|
23
23
|
export { stringify, stringifyObject } from './stringify.ts'
|
|
24
24
|
export { toRegExp, toRegExpString } from './toRegExp.ts'
|
|
25
25
|
export { transformReservedWord } from './transformReservedWord.ts'
|
|
26
|
-
export { trim,
|
|
26
|
+
export { trim, trimQuotes } from './trim.ts'
|
|
27
27
|
export { merge } from 'remeda'
|
|
28
28
|
export { orderBy } from 'natural-orderby'
|
|
29
29
|
|
|
@@ -41,7 +41,6 @@ export default {
|
|
|
41
41
|
toRegExpString,
|
|
42
42
|
trim,
|
|
43
43
|
trimQuotes,
|
|
44
|
-
trimExtName,
|
|
45
44
|
JSDoc: {
|
|
46
45
|
createJSDocBlockText,
|
|
47
46
|
},
|
package/src/transformers/trim.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -3,7 +3,6 @@ import type { PossiblePromise } from '@kubb/types'
|
|
|
3
3
|
import type { FileManager } from './FileManager.ts'
|
|
4
4
|
import type { PluginManager } from './PluginManager.ts'
|
|
5
5
|
import type { Logger } from './logger.ts'
|
|
6
|
-
import type { Cache } from './utils/cache.ts'
|
|
7
6
|
|
|
8
7
|
// config
|
|
9
8
|
|
|
@@ -30,20 +29,25 @@ export type UserConfig = Omit<Config, 'root' | 'plugins'> & {
|
|
|
30
29
|
|
|
31
30
|
export type InputPath = {
|
|
32
31
|
/**
|
|
33
|
-
*
|
|
32
|
+
* Define your Swagger/OpenAPI file. This can be an absolute path or a path relative to the `root`.
|
|
34
33
|
*/
|
|
35
34
|
path: string
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
export type InputData = {
|
|
39
38
|
/**
|
|
40
|
-
* `string` or `object` containing
|
|
39
|
+
* `string` or `object` containing your Swagger/OpenAPI data.
|
|
41
40
|
*/
|
|
42
41
|
data: string | unknown
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
type Input = InputPath | InputData
|
|
46
45
|
|
|
46
|
+
type OutContext = {}
|
|
47
|
+
type OutExtension = (context: OutContext) => Record<KubbFile.Extname, KubbFile.Extname>
|
|
48
|
+
|
|
49
|
+
export type BarrelType = 'all' | 'named'
|
|
50
|
+
|
|
47
51
|
/**
|
|
48
52
|
* @private
|
|
49
53
|
*/
|
|
@@ -53,33 +57,44 @@ export type Config<TInput = Input> = {
|
|
|
53
57
|
*/
|
|
54
58
|
name?: string
|
|
55
59
|
/**
|
|
56
|
-
* Project root directory.
|
|
57
|
-
* the location of the config file itself.
|
|
60
|
+
* Project root directory. This can be an absolute path or a path relative to the location of your `kubb.config.ts` file.
|
|
58
61
|
* @default process.cwd()
|
|
59
62
|
*/
|
|
60
63
|
root: string
|
|
64
|
+
/**
|
|
65
|
+
* You can use `input.path` or `input.data` depending on the needs you have.
|
|
66
|
+
*/
|
|
61
67
|
input: TInput
|
|
62
68
|
output: {
|
|
63
69
|
/**
|
|
64
|
-
*
|
|
65
|
-
* This can be an absolute path, or a path relative based of the defined `root` option.
|
|
70
|
+
* The path where all generated files will be exported. This can be an absolute path or a path relative to the specified root option.
|
|
66
71
|
*/
|
|
67
72
|
path: string
|
|
68
73
|
/**
|
|
69
|
-
* Clean output directory before each build.
|
|
74
|
+
* Clean the output directory before each build.
|
|
70
75
|
*/
|
|
71
76
|
clean?: boolean
|
|
72
77
|
/**
|
|
73
|
-
*
|
|
74
|
-
* This is being used for the playground.
|
|
78
|
+
* Save files to the file system.
|
|
75
79
|
* @default true
|
|
76
80
|
*/
|
|
77
81
|
write?: boolean
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Override the extension to the generated imports and exports, default the plugin will add an extension
|
|
85
|
+
* @default `() => ({ '.ts': '.ts'})`
|
|
86
|
+
*/
|
|
87
|
+
extension?: OutExtension
|
|
88
|
+
/**
|
|
89
|
+
* Define what needs to exported, here you can also disable the export of barrel files.
|
|
90
|
+
* @default `'named'`
|
|
91
|
+
*/
|
|
92
|
+
barrelType?: BarrelType | false
|
|
78
93
|
}
|
|
79
94
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
95
|
+
* An array of Kubb plugins that will be used in the generation.
|
|
96
|
+
* Each plugin may include additional configurable options(defined in the plugin itself).
|
|
97
|
+
* If a plugin depends on another plugin, an error will be returned if the required dependency is missing. See pre for more details.
|
|
83
98
|
*/
|
|
84
99
|
plugins?: Array<Plugin>
|
|
85
100
|
/**
|
|
@@ -146,7 +161,7 @@ export type UserPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOpti
|
|
|
146
161
|
options: TOptions['resolvedOptions']
|
|
147
162
|
/**
|
|
148
163
|
* Specifies the preceding plugins for the current plugin. You can pass an array of preceding plugin names, and the current plugin will be executed after these plugins.
|
|
149
|
-
* Can be used to validate
|
|
164
|
+
* Can be used to validate dependent plugins.
|
|
150
165
|
*/
|
|
151
166
|
pre?: Array<string>
|
|
152
167
|
/**
|
|
@@ -178,7 +193,7 @@ export type Plugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>
|
|
|
178
193
|
key: TOptions['key']
|
|
179
194
|
/**
|
|
180
195
|
* Specifies the preceding plugins for the current plugin. You can pass an array of preceding plugin names, and the current plugin will be executed after these plugins.
|
|
181
|
-
* Can be used to validate
|
|
196
|
+
* Can be used to validate dependent plugins.
|
|
182
197
|
*/
|
|
183
198
|
pre?: Array<string>
|
|
184
199
|
/**
|
|
@@ -233,8 +248,6 @@ export type PluginLifecycleHooks = keyof PluginLifecycle
|
|
|
233
248
|
|
|
234
249
|
export type PluginParameter<H extends PluginLifecycleHooks> = Parameters<Required<PluginLifecycle>[H]>
|
|
235
250
|
|
|
236
|
-
export type PluginCache = Record<string, [number, unknown]>
|
|
237
|
-
|
|
238
251
|
export type ResolvePathParams<TOptions = object> = {
|
|
239
252
|
pluginKey?: Plugin['key']
|
|
240
253
|
baseName: string
|
|
@@ -253,15 +266,14 @@ export type ResolveNameParams = {
|
|
|
253
266
|
* `function` can be used used to customize the exported functions(use of camelCase)
|
|
254
267
|
* `type` is a special type for TypeScript(use of PascalCase)
|
|
255
268
|
*/
|
|
256
|
-
type?: 'file' | 'function' | 'type'
|
|
269
|
+
type?: 'file' | 'function' | 'type' | 'const'
|
|
257
270
|
}
|
|
258
271
|
|
|
259
272
|
export type PluginContext<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {
|
|
260
273
|
config: Config
|
|
261
|
-
cache: Cache<PluginCache>
|
|
262
274
|
fileManager: FileManager
|
|
263
275
|
pluginManager: PluginManager
|
|
264
|
-
addFile: (...file: Array<KubbFile.File>) => Promise<Array<KubbFile.
|
|
276
|
+
addFile: (...file: Array<KubbFile.File>) => Promise<Array<KubbFile.ResolvedFile>>
|
|
265
277
|
resolvePath: (params: ResolvePathParams<TOptions['resolvePathOptions']>) => KubbFile.OptionalPath
|
|
266
278
|
resolveName: (params: ResolveNameParams) => string
|
|
267
279
|
logger: Logger
|
|
@@ -274,3 +286,23 @@ export type PluginContext<TOptions extends PluginFactoryOptions = PluginFactoryO
|
|
|
274
286
|
*/
|
|
275
287
|
plugin: Plugin<TOptions>
|
|
276
288
|
}
|
|
289
|
+
|
|
290
|
+
export type Output = {
|
|
291
|
+
/**
|
|
292
|
+
* Output to save the generated files.
|
|
293
|
+
*/
|
|
294
|
+
path: string
|
|
295
|
+
/**
|
|
296
|
+
* Define what needs to exported, here you can also disable the export of barrel files.
|
|
297
|
+
* @default `'named'`
|
|
298
|
+
*/
|
|
299
|
+
barrelType?: BarrelType | false
|
|
300
|
+
/**
|
|
301
|
+
* Add a banner text in the beginning of every file
|
|
302
|
+
*/
|
|
303
|
+
banner?: string
|
|
304
|
+
/**
|
|
305
|
+
* Add a footer text in the beginning of every file
|
|
306
|
+
*/
|
|
307
|
+
footer?: string
|
|
308
|
+
}
|
package/src/utils/TreeNode.ts
CHANGED
|
@@ -1,28 +1,29 @@
|
|
|
1
|
-
import dirTree from 'directory-tree'
|
|
2
|
-
|
|
3
|
-
import { FileManager } from '../FileManager.ts'
|
|
4
|
-
|
|
5
1
|
import type * as KubbFile from '@kubb/fs/types'
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
export type TreeNodeOptions = DirectoryTreeOptions
|
|
9
|
-
|
|
10
|
-
type BarrelData = { type: KubbFile.Mode; path: KubbFile.Path; name: string }
|
|
11
|
-
|
|
12
|
-
export class TreeNode<T = BarrelData> {
|
|
13
|
-
public data: T
|
|
2
|
+
import { FileManager } from '../FileManager.ts'
|
|
14
3
|
|
|
15
|
-
|
|
4
|
+
type BarrelData = {
|
|
5
|
+
file?: KubbFile.File
|
|
6
|
+
/**
|
|
7
|
+
* @deprecated use file instead
|
|
8
|
+
*/
|
|
9
|
+
type: KubbFile.Mode
|
|
10
|
+
path: string
|
|
11
|
+
name: string
|
|
12
|
+
}
|
|
16
13
|
|
|
17
|
-
|
|
14
|
+
export class TreeNode {
|
|
15
|
+
data: BarrelData
|
|
16
|
+
parent?: TreeNode
|
|
17
|
+
children: Array<TreeNode> = []
|
|
18
|
+
#cachedLeaves?: Array<TreeNode> = undefined
|
|
18
19
|
|
|
19
|
-
constructor(data:
|
|
20
|
+
constructor(data: BarrelData, parent?: TreeNode) {
|
|
20
21
|
this.data = data
|
|
21
22
|
this.parent = parent
|
|
22
23
|
return this
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
addChild(data:
|
|
26
|
+
addChild(data: BarrelData): TreeNode {
|
|
26
27
|
const child = new TreeNode(data, this)
|
|
27
28
|
if (!this.children) {
|
|
28
29
|
this.children = []
|
|
@@ -31,51 +32,37 @@ export class TreeNode<T = BarrelData> {
|
|
|
31
32
|
return child
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
if (!
|
|
36
|
-
return null
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (data === this.data) {
|
|
35
|
+
get root(): TreeNode {
|
|
36
|
+
if (!this.parent) {
|
|
40
37
|
return this
|
|
41
38
|
}
|
|
42
|
-
|
|
43
|
-
if (this.children?.length) {
|
|
44
|
-
for (let i = 0, { length } = this.children, target: TreeNode<T> | null = null; i < length; i++) {
|
|
45
|
-
target = this.children[i]!.find(data)
|
|
46
|
-
if (target) {
|
|
47
|
-
return target
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return null
|
|
39
|
+
return this.parent.root
|
|
53
40
|
}
|
|
54
41
|
|
|
55
|
-
get leaves(): TreeNode
|
|
42
|
+
get leaves(): Array<TreeNode> {
|
|
56
43
|
if (!this.children || this.children.length === 0) {
|
|
57
44
|
// this is a leaf
|
|
58
45
|
return [this]
|
|
59
46
|
}
|
|
60
47
|
|
|
48
|
+
if (this.#cachedLeaves) {
|
|
49
|
+
return this.#cachedLeaves
|
|
50
|
+
}
|
|
51
|
+
|
|
61
52
|
// if not a leaf, return all children's leaves recursively
|
|
62
|
-
const leaves: TreeNode
|
|
53
|
+
const leaves: TreeNode[] = []
|
|
63
54
|
if (this.children) {
|
|
64
55
|
for (let i = 0, { length } = this.children; i < length; i++) {
|
|
65
56
|
leaves.push.apply(leaves, this.children[i]!.leaves)
|
|
66
57
|
}
|
|
67
58
|
}
|
|
68
|
-
return leaves
|
|
69
|
-
}
|
|
70
59
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
return this.parent.root
|
|
60
|
+
this.#cachedLeaves = leaves
|
|
61
|
+
|
|
62
|
+
return leaves
|
|
76
63
|
}
|
|
77
64
|
|
|
78
|
-
forEach(callback: (treeNode: TreeNode
|
|
65
|
+
forEach(callback: (treeNode: TreeNode) => void): this {
|
|
79
66
|
if (typeof callback !== 'function') {
|
|
80
67
|
throw new TypeError('forEach() callback must be a function')
|
|
81
68
|
}
|
|
@@ -93,13 +80,41 @@ export class TreeNode<T = BarrelData> {
|
|
|
93
80
|
return this
|
|
94
81
|
}
|
|
95
82
|
|
|
96
|
-
|
|
83
|
+
findDeep(predicate?: (value: TreeNode, index: number, obj: TreeNode[]) => boolean): TreeNode | undefined {
|
|
84
|
+
if (typeof predicate !== 'function') {
|
|
85
|
+
throw new TypeError('find() predicate must be a function')
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return this.leaves.find(predicate)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
forEachDeep(callback: (treeNode: TreeNode) => void): void {
|
|
92
|
+
if (typeof callback !== 'function') {
|
|
93
|
+
throw new TypeError('forEach() callback must be a function')
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
this.leaves.forEach(callback)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
filterDeep(callback: (treeNode: TreeNode) => boolean): Array<TreeNode> {
|
|
100
|
+
if (typeof callback !== 'function') {
|
|
101
|
+
throw new TypeError('filter() callback must be a function')
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return this.leaves.filter(callback)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
mapDeep<T>(callback: (treeNode: TreeNode) => T): Array<T> {
|
|
108
|
+
if (typeof callback !== 'function') {
|
|
109
|
+
throw new TypeError('map() callback must be a function')
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return this.leaves.map(callback)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
public static build(files: KubbFile.File[], root?: string): TreeNode | null {
|
|
97
116
|
try {
|
|
98
|
-
const
|
|
99
|
-
const filteredTree = dirTree(path, {
|
|
100
|
-
extensions: options.extensions,
|
|
101
|
-
exclude: [/node_modules/, ...exclude],
|
|
102
|
-
})
|
|
117
|
+
const filteredTree = buildDirectoryTree(files, root)
|
|
103
118
|
|
|
104
119
|
if (!filteredTree) {
|
|
105
120
|
return null
|
|
@@ -108,6 +123,7 @@ export class TreeNode<T = BarrelData> {
|
|
|
108
123
|
const treeNode = new TreeNode({
|
|
109
124
|
name: filteredTree.name,
|
|
110
125
|
path: filteredTree.path,
|
|
126
|
+
file: filteredTree.file,
|
|
111
127
|
type: FileManager.getMode(filteredTree.path),
|
|
112
128
|
})
|
|
113
129
|
|
|
@@ -115,6 +131,7 @@ export class TreeNode<T = BarrelData> {
|
|
|
115
131
|
const subNode = node.addChild({
|
|
116
132
|
name: item.name,
|
|
117
133
|
path: item.path,
|
|
134
|
+
file: item.file,
|
|
118
135
|
type: FileManager.getMode(item.path),
|
|
119
136
|
})
|
|
120
137
|
|
|
@@ -129,7 +146,72 @@ export class TreeNode<T = BarrelData> {
|
|
|
129
146
|
|
|
130
147
|
return treeNode
|
|
131
148
|
} catch (e) {
|
|
132
|
-
throw new Error('Something went wrong with creating
|
|
149
|
+
throw new Error('Something went wrong with creating barrel files with the TreeNode class', { cause: e })
|
|
133
150
|
}
|
|
134
151
|
}
|
|
135
152
|
}
|
|
153
|
+
|
|
154
|
+
export type DirectoryTree = {
|
|
155
|
+
name: string
|
|
156
|
+
path: string
|
|
157
|
+
file?: KubbFile.File
|
|
158
|
+
children: Array<DirectoryTree>
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function buildDirectoryTree(files: Array<KubbFile.File>, rootFolder = ''): DirectoryTree | null {
|
|
162
|
+
const rootPrefix = rootFolder.endsWith('/') ? rootFolder : `${rootFolder}/`
|
|
163
|
+
const filteredFiles = files.filter((file) => (rootFolder ? file.path.startsWith(rootPrefix) && !file.path.endsWith('.json') : !file.path.endsWith('.json')))
|
|
164
|
+
|
|
165
|
+
if (filteredFiles.length === 0) {
|
|
166
|
+
return null // No files match the root folder
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const root: DirectoryTree = {
|
|
170
|
+
name: rootFolder || '',
|
|
171
|
+
path: rootFolder || '',
|
|
172
|
+
children: [],
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
filteredFiles.forEach((file) => {
|
|
176
|
+
const path = file.path.slice(rootFolder.length)
|
|
177
|
+
const parts = path.split('/')
|
|
178
|
+
let currentLevel: DirectoryTree[] = root.children
|
|
179
|
+
let currentPath = rootFolder
|
|
180
|
+
|
|
181
|
+
parts.forEach((part, index) => {
|
|
182
|
+
if (index !== 0) {
|
|
183
|
+
currentPath += `/${part}`
|
|
184
|
+
} else {
|
|
185
|
+
currentPath += `${part}`
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
let existingNode = currentLevel.find((node) => node.name === part)
|
|
189
|
+
|
|
190
|
+
if (!existingNode) {
|
|
191
|
+
if (index === parts.length - 1) {
|
|
192
|
+
// If it's the last part, it's a file
|
|
193
|
+
existingNode = {
|
|
194
|
+
name: part,
|
|
195
|
+
file,
|
|
196
|
+
path: currentPath,
|
|
197
|
+
} as DirectoryTree
|
|
198
|
+
} else {
|
|
199
|
+
// Otherwise, it's a folder
|
|
200
|
+
existingNode = {
|
|
201
|
+
name: part,
|
|
202
|
+
path: currentPath,
|
|
203
|
+
children: [],
|
|
204
|
+
} as DirectoryTree
|
|
205
|
+
}
|
|
206
|
+
currentLevel.push(existingNode)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Move to the next level if it's a folder
|
|
210
|
+
if (!existingNode.file) {
|
|
211
|
+
currentLevel = existingNode.children
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
return root
|
|
217
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
type PromiseFunc<T = unknown, T2 = never> = (state?: T) => T2 extends never ? Promise<T> : Promise<T> | T2
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
type ValueOfPromiseFuncArray<TInput extends Array<unknown>> = TInput extends Array<PromiseFunc<infer X, infer Y>> ? X | Y : never
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
function noReturn(): void {}
|
|
6
6
|
|
|
7
|
-
type SeqOutput<TInput extends Array<PromiseFunc<TValue, null>>, TValue> = Array<Awaited<ValueOfPromiseFuncArray<TInput
|
|
7
|
+
type SeqOutput<TInput extends Array<PromiseFunc<TValue, null>>, TValue> = Promise<Array<Awaited<ValueOfPromiseFuncArray<TInput>>>>
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Chains promises
|
package/src/utils/index.ts
CHANGED
|
@@ -10,4 +10,5 @@ export { timeout } from './timeout.ts'
|
|
|
10
10
|
export { getUniqueName, setUniqueName } from './uniqueName.ts'
|
|
11
11
|
export type { URLObject } from './URLPath.ts'
|
|
12
12
|
export { URLPath } from './URLPath.ts'
|
|
13
|
-
export {
|
|
13
|
+
export { getFileParser, createFileImport, createFileExport, createFile, createFileParser } from './parser.ts'
|
|
14
|
+
export type { ParserModule } from './parser.ts'
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import type * as KubbFile from '@kubb/fs/types'
|
|
3
|
+
|
|
4
|
+
import { getRelativePath } from '@kubb/fs'
|
|
5
|
+
import hash from 'object-hash'
|
|
6
|
+
import { combineExports, combineImports, combineSources } from '../FileManager.ts'
|
|
7
|
+
import type { Logger } from '../logger.ts'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Helper to create a file with name and id set
|
|
11
|
+
*/
|
|
12
|
+
export function createFile<TMeta extends object = object>(file: KubbFile.File<TMeta>): KubbFile.ResolvedFile<TMeta> {
|
|
13
|
+
const extname = path.extname(file.baseName) as KubbFile.Extname
|
|
14
|
+
|
|
15
|
+
if (!extname) {
|
|
16
|
+
throw new Error(`No extname found for ${file.baseName}`)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const source = file.sources.map((item) => item.value).join('\n\n')
|
|
20
|
+
const exports = file.exports ? combineExports(file.exports) : []
|
|
21
|
+
const imports = file.imports && source ? combineImports(file.imports, exports, source) : []
|
|
22
|
+
const sources = file.sources ? combineSources(file.sources) : []
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
...file,
|
|
26
|
+
id: hash({ path: file.path }),
|
|
27
|
+
name: trimExtName(file.baseName),
|
|
28
|
+
extname,
|
|
29
|
+
imports: imports.map((item) => createFileImport(item)),
|
|
30
|
+
exports: exports.map((item) => createFileExport(item)),
|
|
31
|
+
sources: sources.map((item) => createFileSource(item)),
|
|
32
|
+
meta: file.meta || ({} as TMeta),
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Helper to create a fileImport with extname set
|
|
38
|
+
*/
|
|
39
|
+
function createFileSource(source: KubbFile.Source): KubbFile.Source {
|
|
40
|
+
return source
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Helper to create a fileImport with extname set
|
|
45
|
+
*/
|
|
46
|
+
export function createFileImport(imp: KubbFile.Import): KubbFile.ResolvedImport {
|
|
47
|
+
return {
|
|
48
|
+
...imp,
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Helper to create a fileExport with extname set
|
|
54
|
+
*/
|
|
55
|
+
export function createFileExport(exp: KubbFile.Export): KubbFile.ResolvedExport {
|
|
56
|
+
return {
|
|
57
|
+
...exp,
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type ParserModule<TMeta extends object = object> = {
|
|
62
|
+
format: (source: string) => Promise<string>
|
|
63
|
+
/**
|
|
64
|
+
* Convert a file to string
|
|
65
|
+
*/
|
|
66
|
+
print: (file: KubbFile.ResolvedFile<TMeta>, options: PrintOptions) => Promise<string>
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function createFileParser<TMeta extends object = object>(parser: ParserModule<TMeta>): ParserModule<TMeta> {
|
|
70
|
+
return parser
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
type PrintOptions = {
|
|
74
|
+
extname?: KubbFile.Extname
|
|
75
|
+
logger?: Logger
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const typeScriptParser = createFileParser({
|
|
79
|
+
async format(source) {
|
|
80
|
+
const module = await import('@kubb/parser-ts')
|
|
81
|
+
|
|
82
|
+
return module.format(source)
|
|
83
|
+
},
|
|
84
|
+
async print(file, options = { extname: '.ts' }) {
|
|
85
|
+
const module = await import('@kubb/parser-ts')
|
|
86
|
+
|
|
87
|
+
const source = file.sources.map((item) => item.value).join('\n\n')
|
|
88
|
+
|
|
89
|
+
const importNodes = file.imports
|
|
90
|
+
.map((item) => {
|
|
91
|
+
const importPath = item.root ? getRelativePath(item.root, item.path) : item.path
|
|
92
|
+
const hasExtname = !!path.extname(importPath)
|
|
93
|
+
|
|
94
|
+
return module.factory.createImportDeclaration({
|
|
95
|
+
name: item.name,
|
|
96
|
+
path: options.extname && hasExtname ? `${trimExtName(importPath)}${options.extname}` : trimExtName(importPath),
|
|
97
|
+
isTypeOnly: item.isTypeOnly,
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
.filter(Boolean)
|
|
101
|
+
|
|
102
|
+
const exportNodes = file.exports
|
|
103
|
+
.map((item) => {
|
|
104
|
+
const exportPath = item.path
|
|
105
|
+
|
|
106
|
+
const hasExtname = !!path.extname(exportPath)
|
|
107
|
+
|
|
108
|
+
return module.factory.createExportDeclaration({
|
|
109
|
+
name: item.name,
|
|
110
|
+
path: options.extname && hasExtname ? `${trimExtName(item.path)}${options.extname}` : trimExtName(item.path),
|
|
111
|
+
isTypeOnly: item.isTypeOnly,
|
|
112
|
+
asAlias: item.asAlias,
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
.filter(Boolean)
|
|
116
|
+
|
|
117
|
+
return [file.banner, module.print([...importNodes, ...exportNodes]), source, file.footer].join('\n')
|
|
118
|
+
},
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
const defaultParser = createFileParser({
|
|
122
|
+
async format(source) {
|
|
123
|
+
return source
|
|
124
|
+
},
|
|
125
|
+
async print(file) {
|
|
126
|
+
return file.sources.map((item) => item.value).join('\n\n')
|
|
127
|
+
},
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
const parsers: Record<KubbFile.Extname, ParserModule<any>> = {
|
|
131
|
+
'.ts': typeScriptParser,
|
|
132
|
+
'.js': typeScriptParser,
|
|
133
|
+
'.jsx': typeScriptParser,
|
|
134
|
+
'.tsx': typeScriptParser,
|
|
135
|
+
'.json': defaultParser,
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export async function getFileParser<TMeta extends object = object>(extname: KubbFile.Extname | undefined): Promise<ParserModule<TMeta>> {
|
|
139
|
+
if (!extname) {
|
|
140
|
+
return defaultParser
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const parser = parsers[extname]
|
|
144
|
+
|
|
145
|
+
if (!parser) {
|
|
146
|
+
console.warn(`[parser] No parser found for ${extname}, default parser will be used`)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return parser || defaultParser
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function trimExtName(text: string): string {
|
|
153
|
+
const extname = text.split('.').pop()
|
|
154
|
+
|
|
155
|
+
return text.replace(`.${extname}`, '')
|
|
156
|
+
}
|