@kubb/core 5.0.0-alpha.7 → 5.0.0-alpha.71
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 +3 -2
- package/dist/PluginDriver-BXibeQk-.cjs +1036 -0
- package/dist/PluginDriver-BXibeQk-.cjs.map +1 -0
- package/dist/PluginDriver-DV3p2Hky.js +945 -0
- package/dist/PluginDriver-DV3p2Hky.js.map +1 -0
- package/dist/index.cjs +730 -1773
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +289 -240
- package/dist/index.js +717 -1741
- package/dist/index.js.map +1 -1
- package/dist/mocks.cjs +139 -0
- package/dist/mocks.cjs.map +1 -0
- package/dist/mocks.d.ts +74 -0
- package/dist/mocks.js +134 -0
- package/dist/mocks.js.map +1 -0
- package/dist/types-DWtkW2RX.d.ts +1915 -0
- package/package.json +51 -57
- package/src/FileManager.ts +115 -0
- package/src/FileProcessor.ts +86 -0
- package/src/Kubb.ts +205 -130
- package/src/PluginDriver.ts +326 -565
- package/src/constants.ts +20 -47
- package/src/createAdapter.ts +25 -0
- package/src/createKubb.ts +546 -0
- package/src/createRenderer.ts +57 -0
- package/src/createStorage.ts +58 -0
- package/src/defineGenerator.ts +88 -100
- package/src/defineLogger.ts +13 -3
- package/src/defineMiddleware.ts +64 -0
- package/src/defineParser.ts +45 -0
- package/src/definePlugin.ts +78 -7
- package/src/defineResolver.ts +521 -0
- package/src/devtools.ts +14 -14
- package/src/index.ts +13 -16
- package/src/mocks.ts +172 -0
- package/src/renderNode.ts +35 -0
- package/src/storages/fsStorage.ts +43 -13
- package/src/storages/memoryStorage.ts +6 -4
- package/src/types.ts +752 -226
- package/src/utils/diagnostics.ts +4 -1
- package/src/utils/isInputPath.ts +10 -0
- package/src/utils/packageJSON.ts +99 -0
- package/dist/PluginDriver-Dma9KhLK.d.ts +0 -1056
- package/dist/chunk-ByKO4r7w.cjs +0 -38
- package/dist/hooks.cjs +0 -102
- package/dist/hooks.cjs.map +0 -1
- package/dist/hooks.d.ts +0 -75
- package/dist/hooks.js +0 -97
- package/dist/hooks.js.map +0 -1
- package/src/PackageManager.ts +0 -180
- package/src/build.ts +0 -419
- package/src/config.ts +0 -56
- package/src/defineAdapter.ts +0 -22
- package/src/defineStorage.ts +0 -56
- package/src/errors.ts +0 -1
- package/src/hooks/index.ts +0 -4
- package/src/hooks/useKubb.ts +0 -138
- package/src/hooks/useMode.ts +0 -11
- package/src/hooks/usePlugin.ts +0 -11
- package/src/hooks/usePluginDriver.ts +0 -11
- package/src/utils/FunctionParams.ts +0 -155
- package/src/utils/TreeNode.ts +0 -215
- package/src/utils/executeStrategies.ts +0 -81
- package/src/utils/formatters.ts +0 -56
- package/src/utils/getBarrelFiles.ts +0 -141
- package/src/utils/getConfigs.ts +0 -30
- package/src/utils/getPlugins.ts +0 -23
- package/src/utils/linters.ts +0 -25
- package/src/utils/resolveOptions.ts +0 -93
package/src/hooks/useMode.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { KubbFile } from '@kubb/fabric-core/types'
|
|
2
|
-
import { useFabric } from '@kubb/react-fabric'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @deprecated use `useKubb` instead
|
|
6
|
-
*/
|
|
7
|
-
export function useMode(): KubbFile.Mode {
|
|
8
|
-
const { meta } = useFabric<{ mode: KubbFile.Mode }>()
|
|
9
|
-
|
|
10
|
-
return meta.mode
|
|
11
|
-
}
|
package/src/hooks/usePlugin.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { useFabric } from '@kubb/react-fabric'
|
|
2
|
-
import type { Plugin, PluginFactoryOptions } from '../types.ts'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @deprecated use useKubb instead
|
|
6
|
-
*/
|
|
7
|
-
export function usePlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>(): Plugin<TOptions> {
|
|
8
|
-
const { meta } = useFabric<{ plugin: Plugin<TOptions> }>()
|
|
9
|
-
|
|
10
|
-
return meta.plugin
|
|
11
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { useFabric } from '@kubb/react-fabric'
|
|
2
|
-
import type { PluginDriver } from '../PluginDriver.ts'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @deprecated use `useKubb` instead
|
|
6
|
-
*/
|
|
7
|
-
export function usePluginDriver(): PluginDriver {
|
|
8
|
-
const { meta } = useFabric<{ driver: PluginDriver }>()
|
|
9
|
-
|
|
10
|
-
return meta.driver
|
|
11
|
-
}
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import { camelCase } from '@internals/utils'
|
|
2
|
-
// TODO replace with @internals/utils
|
|
3
|
-
import { sortBy } from 'remeda'
|
|
4
|
-
|
|
5
|
-
type FunctionParamsASTWithoutType = {
|
|
6
|
-
name?: string
|
|
7
|
-
type?: string
|
|
8
|
-
/**
|
|
9
|
-
* @default true
|
|
10
|
-
*/
|
|
11
|
-
required?: boolean
|
|
12
|
-
/**
|
|
13
|
-
* @default true
|
|
14
|
-
*/
|
|
15
|
-
enabled?: boolean
|
|
16
|
-
default?: string
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
type FunctionParamsASTWithType = {
|
|
20
|
-
name?: never
|
|
21
|
-
type: string
|
|
22
|
-
/**
|
|
23
|
-
* @default true
|
|
24
|
-
*/
|
|
25
|
-
required?: boolean
|
|
26
|
-
/**
|
|
27
|
-
* @default true
|
|
28
|
-
*/
|
|
29
|
-
enabled?: boolean
|
|
30
|
-
default?: string
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* @deprecated
|
|
34
|
-
*/
|
|
35
|
-
export type FunctionParamsAST = FunctionParamsASTWithoutType | FunctionParamsASTWithType
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* @deprecated
|
|
39
|
-
*/
|
|
40
|
-
export class FunctionParams {
|
|
41
|
-
#items: Array<FunctionParamsAST | FunctionParamsAST[]> = []
|
|
42
|
-
|
|
43
|
-
get items(): FunctionParamsAST[] {
|
|
44
|
-
return this.#items.flat()
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
add(item: FunctionParamsAST | Array<FunctionParamsAST | FunctionParamsAST[] | undefined> | undefined): FunctionParams {
|
|
48
|
-
if (!item) {
|
|
49
|
-
return this
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (Array.isArray(item)) {
|
|
53
|
-
item
|
|
54
|
-
.filter((x): x is FunctionParamsAST | FunctionParamsAST[] => x !== undefined)
|
|
55
|
-
.forEach((it) => {
|
|
56
|
-
this.#items.push(it)
|
|
57
|
-
})
|
|
58
|
-
return this
|
|
59
|
-
}
|
|
60
|
-
this.#items.push(item)
|
|
61
|
-
|
|
62
|
-
return this
|
|
63
|
-
}
|
|
64
|
-
static #orderItems(items: Array<FunctionParamsAST | FunctionParamsAST[]>) {
|
|
65
|
-
return sortBy(
|
|
66
|
-
items.filter(Boolean),
|
|
67
|
-
[(item) => Array.isArray(item), 'desc'], // arrays (rest params) first
|
|
68
|
-
[(item) => !Array.isArray(item) && (item as FunctionParamsAST).default !== undefined, 'asc'], // no-default before has-default
|
|
69
|
-
[(item) => Array.isArray(item) || ((item as FunctionParamsAST).required ?? true), 'desc'], // required before optional
|
|
70
|
-
)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
static #addParams(acc: string[], item: FunctionParamsAST) {
|
|
74
|
-
const { enabled = true, name, type, required = true, ...rest } = item
|
|
75
|
-
|
|
76
|
-
if (!enabled) {
|
|
77
|
-
return acc
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (!name) {
|
|
81
|
-
// when name is not se we uses TypeScript generics
|
|
82
|
-
acc.push(`${type}${rest.default ? ` = ${rest.default}` : ''}`)
|
|
83
|
-
|
|
84
|
-
return acc
|
|
85
|
-
}
|
|
86
|
-
// TODO check why we still need the camelcase here
|
|
87
|
-
const parameterName = name.startsWith('{') ? name : camelCase(name)
|
|
88
|
-
|
|
89
|
-
if (type) {
|
|
90
|
-
if (required) {
|
|
91
|
-
acc.push(`${parameterName}: ${type}${rest.default ? ` = ${rest.default}` : ''}`)
|
|
92
|
-
} else {
|
|
93
|
-
acc.push(`${parameterName}?: ${type}`)
|
|
94
|
-
}
|
|
95
|
-
} else {
|
|
96
|
-
acc.push(`${parameterName}`)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return acc
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
static toObject(items: FunctionParamsAST[]): FunctionParamsAST {
|
|
103
|
-
let type: string[] = []
|
|
104
|
-
let name: string[] = []
|
|
105
|
-
|
|
106
|
-
const enabled = items.every((item) => item.enabled) ? items.at(0)?.enabled : true
|
|
107
|
-
const required = items.every((item) => item.required) ?? true
|
|
108
|
-
|
|
109
|
-
items.forEach((item) => {
|
|
110
|
-
name = FunctionParams.#addParams(name, { ...item, type: undefined })
|
|
111
|
-
if (items.some((item) => item.type)) {
|
|
112
|
-
type = FunctionParams.#addParams(type, item)
|
|
113
|
-
}
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
return {
|
|
117
|
-
name: `{ ${name.join(', ')} }`,
|
|
118
|
-
type: type.length ? `{ ${type.join('; ')} }` : undefined,
|
|
119
|
-
enabled,
|
|
120
|
-
required,
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
toObject(): FunctionParamsAST {
|
|
125
|
-
const items = FunctionParams.#orderItems(this.#items).flat()
|
|
126
|
-
|
|
127
|
-
return FunctionParams.toObject(items)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
static toString(items: (FunctionParamsAST | FunctionParamsAST[])[]): string {
|
|
131
|
-
const sortedData = FunctionParams.#orderItems(items)
|
|
132
|
-
|
|
133
|
-
return sortedData
|
|
134
|
-
.reduce((acc, item) => {
|
|
135
|
-
if (Array.isArray(item)) {
|
|
136
|
-
if (item.length <= 0) {
|
|
137
|
-
return acc
|
|
138
|
-
}
|
|
139
|
-
const subItems = FunctionParams.#orderItems(item) as FunctionParamsAST[]
|
|
140
|
-
const objectItem = FunctionParams.toObject(subItems)
|
|
141
|
-
|
|
142
|
-
return FunctionParams.#addParams(acc, objectItem)
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return FunctionParams.#addParams(acc, item)
|
|
146
|
-
}, [] as string[])
|
|
147
|
-
.join(', ')
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
toString(): string {
|
|
151
|
-
const items = FunctionParams.#orderItems(this.#items)
|
|
152
|
-
|
|
153
|
-
return FunctionParams.toString(items)
|
|
154
|
-
}
|
|
155
|
-
}
|
package/src/utils/TreeNode.ts
DELETED
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
|
-
import type { KubbFile } from '@kubb/fabric-core/types'
|
|
3
|
-
import { getMode } from '../PluginDriver.ts'
|
|
4
|
-
|
|
5
|
-
type BarrelData = {
|
|
6
|
-
file?: KubbFile.File
|
|
7
|
-
/**
|
|
8
|
-
* @deprecated use file instead
|
|
9
|
-
*/
|
|
10
|
-
type: KubbFile.Mode
|
|
11
|
-
path: string
|
|
12
|
-
name: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export class TreeNode {
|
|
16
|
-
data: BarrelData
|
|
17
|
-
parent?: TreeNode
|
|
18
|
-
children: Array<TreeNode> = []
|
|
19
|
-
#cachedLeaves?: Array<TreeNode> = undefined
|
|
20
|
-
|
|
21
|
-
constructor(data: BarrelData, parent?: TreeNode) {
|
|
22
|
-
this.data = data
|
|
23
|
-
this.parent = parent
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
addChild(data: BarrelData): TreeNode {
|
|
27
|
-
const child = new TreeNode(data, this)
|
|
28
|
-
if (!this.children) {
|
|
29
|
-
this.children = []
|
|
30
|
-
}
|
|
31
|
-
this.children.push(child)
|
|
32
|
-
return child
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
get root(): TreeNode {
|
|
36
|
-
if (!this.parent) {
|
|
37
|
-
return this
|
|
38
|
-
}
|
|
39
|
-
return this.parent.root
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
get leaves(): Array<TreeNode> {
|
|
43
|
-
if (!this.children || this.children.length === 0) {
|
|
44
|
-
// this is a leaf
|
|
45
|
-
return [this]
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (this.#cachedLeaves) {
|
|
49
|
-
return this.#cachedLeaves
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const leaves: TreeNode[] = []
|
|
53
|
-
for (const child of this.children) {
|
|
54
|
-
leaves.push(...child.leaves)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
this.#cachedLeaves = leaves
|
|
58
|
-
|
|
59
|
-
return leaves
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
forEach(callback: (treeNode: TreeNode) => void): this {
|
|
63
|
-
if (typeof callback !== 'function') {
|
|
64
|
-
throw new TypeError('forEach() callback must be a function')
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
callback(this)
|
|
68
|
-
|
|
69
|
-
for (const child of this.children) {
|
|
70
|
-
child.forEach(callback)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return this
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
findDeep(predicate?: (value: TreeNode, index: number, obj: TreeNode[]) => boolean): TreeNode | undefined {
|
|
77
|
-
if (typeof predicate !== 'function') {
|
|
78
|
-
throw new TypeError('find() predicate must be a function')
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return this.leaves.find(predicate)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
forEachDeep(callback: (treeNode: TreeNode) => void): void {
|
|
85
|
-
if (typeof callback !== 'function') {
|
|
86
|
-
throw new TypeError('forEach() callback must be a function')
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
this.leaves.forEach(callback)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
filterDeep(callback: (treeNode: TreeNode) => boolean): Array<TreeNode> {
|
|
93
|
-
if (typeof callback !== 'function') {
|
|
94
|
-
throw new TypeError('filter() callback must be a function')
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return this.leaves.filter(callback)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
mapDeep<T>(callback: (treeNode: TreeNode) => T): Array<T> {
|
|
101
|
-
if (typeof callback !== 'function') {
|
|
102
|
-
throw new TypeError('map() callback must be a function')
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return this.leaves.map(callback)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
public static build(files: KubbFile.File[], root?: string): TreeNode | null {
|
|
109
|
-
try {
|
|
110
|
-
const filteredTree = buildDirectoryTree(files, root)
|
|
111
|
-
|
|
112
|
-
if (!filteredTree) {
|
|
113
|
-
return null
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const treeNode = new TreeNode({
|
|
117
|
-
name: filteredTree.name,
|
|
118
|
-
path: filteredTree.path,
|
|
119
|
-
file: filteredTree.file,
|
|
120
|
-
type: getMode(filteredTree.path),
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
const recurse = (node: typeof treeNode, item: DirectoryTree) => {
|
|
124
|
-
const subNode = node.addChild({
|
|
125
|
-
name: item.name,
|
|
126
|
-
path: item.path,
|
|
127
|
-
file: item.file,
|
|
128
|
-
type: getMode(item.path),
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
if (item.children?.length) {
|
|
132
|
-
item.children?.forEach((child) => {
|
|
133
|
-
recurse(subNode, child)
|
|
134
|
-
})
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
filteredTree.children?.forEach((child) => {
|
|
139
|
-
recurse(treeNode, child)
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
return treeNode
|
|
143
|
-
} catch (error) {
|
|
144
|
-
throw new Error('Something went wrong with creating barrel files with the TreeNode class', { cause: error })
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
type DirectoryTree = {
|
|
150
|
-
name: string
|
|
151
|
-
path: string
|
|
152
|
-
file?: KubbFile.File
|
|
153
|
-
children: Array<DirectoryTree>
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const normalizePath = (p: string): string => p.replaceAll('\\', '/')
|
|
157
|
-
|
|
158
|
-
function buildDirectoryTree(files: Array<KubbFile.File>, rootFolder = ''): DirectoryTree | null {
|
|
159
|
-
const normalizedRootFolder = normalizePath(rootFolder)
|
|
160
|
-
const rootPrefix = normalizedRootFolder.endsWith('/') ? normalizedRootFolder : `${normalizedRootFolder}/`
|
|
161
|
-
|
|
162
|
-
const filteredFiles = files.filter((file) => {
|
|
163
|
-
const normalizedFilePath = normalizePath(file.path)
|
|
164
|
-
return rootFolder ? normalizedFilePath.startsWith(rootPrefix) && !normalizedFilePath.endsWith('.json') : !normalizedFilePath.endsWith('.json')
|
|
165
|
-
})
|
|
166
|
-
|
|
167
|
-
if (filteredFiles.length === 0) {
|
|
168
|
-
return null // No files match the root folder
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const root: DirectoryTree = {
|
|
172
|
-
name: rootFolder || '',
|
|
173
|
-
path: rootFolder || '',
|
|
174
|
-
children: [],
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
filteredFiles.forEach((file) => {
|
|
178
|
-
const relativePath = file.path.slice(rootFolder.length)
|
|
179
|
-
const parts = relativePath.split('/').filter(Boolean)
|
|
180
|
-
let currentLevel: DirectoryTree[] = root.children
|
|
181
|
-
let currentPath = normalizePath(rootFolder)
|
|
182
|
-
|
|
183
|
-
parts.forEach((part, index) => {
|
|
184
|
-
currentPath = path.posix.join(currentPath, part)
|
|
185
|
-
|
|
186
|
-
let existingNode = currentLevel.find((node) => node.name === part)
|
|
187
|
-
|
|
188
|
-
if (!existingNode) {
|
|
189
|
-
if (index === parts.length - 1) {
|
|
190
|
-
// If its the last part, its a file
|
|
191
|
-
existingNode = {
|
|
192
|
-
name: part,
|
|
193
|
-
file,
|
|
194
|
-
path: currentPath,
|
|
195
|
-
} as DirectoryTree
|
|
196
|
-
} else {
|
|
197
|
-
// Otherwise, its a folder
|
|
198
|
-
existingNode = {
|
|
199
|
-
name: part,
|
|
200
|
-
path: currentPath,
|
|
201
|
-
children: [],
|
|
202
|
-
} as DirectoryTree
|
|
203
|
-
}
|
|
204
|
-
currentLevel.push(existingNode)
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// Move to the next level if its a folder
|
|
208
|
-
if (!existingNode.file) {
|
|
209
|
-
currentLevel = existingNode.children
|
|
210
|
-
}
|
|
211
|
-
})
|
|
212
|
-
})
|
|
213
|
-
|
|
214
|
-
return root
|
|
215
|
-
}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import pLimit from 'p-limit'
|
|
2
|
-
|
|
3
|
-
type PromiseFunc<T = unknown, T2 = never> = (state?: T) => T2 extends never ? Promise<T> : Promise<T> | T2
|
|
4
|
-
|
|
5
|
-
type ValueOfPromiseFuncArray<TInput extends Array<unknown>> = TInput extends Array<PromiseFunc<infer X, infer Y>> ? X | Y : never
|
|
6
|
-
|
|
7
|
-
type SeqOutput<TInput extends Array<PromiseFunc<TValue, null>>, TValue> = Promise<Array<Awaited<ValueOfPromiseFuncArray<TInput>>>>
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Chains promises
|
|
11
|
-
*/
|
|
12
|
-
export function hookSeq<TInput extends Array<PromiseFunc<TValue, null>>, TValue, TOutput = SeqOutput<TInput, TValue>>(promises: TInput): TOutput {
|
|
13
|
-
return promises.filter(Boolean).reduce(
|
|
14
|
-
(promise, func) => {
|
|
15
|
-
if (typeof func !== 'function') {
|
|
16
|
-
throw new Error('HookSeq needs a function that returns a promise `() => Promise<unknown>`')
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return promise.then((state) => {
|
|
20
|
-
const calledFunc = func(state as TValue)
|
|
21
|
-
|
|
22
|
-
if (calledFunc) {
|
|
23
|
-
return calledFunc.then(Array.prototype.concat.bind(state) as (result: TValue) => TValue[])
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return state
|
|
27
|
-
})
|
|
28
|
-
},
|
|
29
|
-
Promise.resolve([] as Array<TValue>),
|
|
30
|
-
) as TOutput
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
type HookFirstOutput<TInput extends Array<PromiseFunc<TValue, null>>, TValue = unknown> = ValueOfPromiseFuncArray<TInput>
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Chains promises, first non-null result stops and returns
|
|
37
|
-
*/
|
|
38
|
-
export function hookFirst<TInput extends Array<PromiseFunc<TValue, null>>, TValue = unknown, TOutput = HookFirstOutput<TInput, TValue>>(
|
|
39
|
-
promises: TInput,
|
|
40
|
-
nullCheck: (state: unknown) => boolean = (state) => state !== null,
|
|
41
|
-
): TOutput {
|
|
42
|
-
let promise: Promise<unknown> = Promise.resolve(null) as Promise<unknown>
|
|
43
|
-
|
|
44
|
-
for (const func of promises.filter(Boolean)) {
|
|
45
|
-
promise = promise.then((state) => {
|
|
46
|
-
if (nullCheck(state)) {
|
|
47
|
-
return state
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return func(state as TValue)
|
|
51
|
-
})
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return promise as TOutput
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
type HookParallelOutput<TInput extends Array<PromiseFunc<TValue, null>>, TValue> = Promise<PromiseSettledResult<Awaited<ValueOfPromiseFuncArray<TInput>>>[]>
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Runs an array of promise functions with optional concurrency limit.
|
|
61
|
-
*/
|
|
62
|
-
export function hookParallel<TInput extends Array<PromiseFunc<TValue, null>>, TValue = unknown, TOutput = HookParallelOutput<TInput, TValue>>(
|
|
63
|
-
promises: TInput,
|
|
64
|
-
concurrency: number = Number.POSITIVE_INFINITY,
|
|
65
|
-
): TOutput {
|
|
66
|
-
const limit = pLimit(concurrency)
|
|
67
|
-
|
|
68
|
-
const tasks = promises.filter(Boolean).map((promise) => limit(() => promise()))
|
|
69
|
-
|
|
70
|
-
return Promise.allSettled(tasks) as TOutput
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export type Strategy = 'seq' | 'first' | 'parallel'
|
|
74
|
-
|
|
75
|
-
export type StrategySwitch<TStrategy extends Strategy, TInput extends Array<PromiseFunc<TValue, null>>, TValue> = TStrategy extends 'first'
|
|
76
|
-
? HookFirstOutput<TInput, TValue>
|
|
77
|
-
: TStrategy extends 'seq'
|
|
78
|
-
? SeqOutput<TInput, TValue>
|
|
79
|
-
: TStrategy extends 'parallel'
|
|
80
|
-
? HookParallelOutput<TInput, TValue>
|
|
81
|
-
: never
|
package/src/utils/formatters.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { x } from 'tinyexec'
|
|
2
|
-
import type { formatters } from '../constants.ts'
|
|
3
|
-
|
|
4
|
-
type Formatter = keyof typeof formatters
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Check if a formatter command is available in the system.
|
|
8
|
-
*
|
|
9
|
-
* @param formatter - The formatter to check ('biome', 'prettier', or 'oxfmt')
|
|
10
|
-
* @returns Promise that resolves to true if the formatter is available, false otherwise
|
|
11
|
-
*
|
|
12
|
-
* @remarks
|
|
13
|
-
* This function checks availability by running `<formatter> --version` command.
|
|
14
|
-
* All supported formatters (biome, prettier, oxfmt) implement the --version flag.
|
|
15
|
-
*/
|
|
16
|
-
async function isFormatterAvailable(formatter: Formatter): Promise<boolean> {
|
|
17
|
-
try {
|
|
18
|
-
// Try to get the version of the formatter to check if it's installed
|
|
19
|
-
await x(formatter, ['--version'], { nodeOptions: { stdio: 'ignore' } })
|
|
20
|
-
return true
|
|
21
|
-
} catch {
|
|
22
|
-
return false
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Detect which formatter is available in the system.
|
|
28
|
-
*
|
|
29
|
-
* @returns Promise that resolves to the first available formatter or undefined if none are found
|
|
30
|
-
*
|
|
31
|
-
* @remarks
|
|
32
|
-
* Checks in order of preference: biome, oxfmt, prettier.
|
|
33
|
-
* Uses the `--version` flag to detect if each formatter command is available.
|
|
34
|
-
* This is a reliable method as all supported formatters implement this flag.
|
|
35
|
-
*
|
|
36
|
-
* @example
|
|
37
|
-
* ```typescript
|
|
38
|
-
* const formatter = await detectFormatter()
|
|
39
|
-
* if (formatter) {
|
|
40
|
-
* console.log(`Using ${formatter} for formatting`)
|
|
41
|
-
* } else {
|
|
42
|
-
* console.log('No formatter found')
|
|
43
|
-
* }
|
|
44
|
-
* ```
|
|
45
|
-
*/
|
|
46
|
-
export async function detectFormatter(): Promise<Formatter | undefined> {
|
|
47
|
-
const formatterNames: Formatter[] = ['biome', 'oxfmt', 'prettier']
|
|
48
|
-
|
|
49
|
-
for (const formatter of formatterNames) {
|
|
50
|
-
if (await isFormatterAvailable(formatter)) {
|
|
51
|
-
return formatter
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return undefined
|
|
56
|
-
}
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
/** biome-ignore-all lint/suspicious/useIterableCallbackReturn: not needed */
|
|
2
|
-
import { join } from 'node:path'
|
|
3
|
-
import { getRelativePath } from '@internals/utils'
|
|
4
|
-
import type { KubbFile } from '@kubb/fabric-core/types'
|
|
5
|
-
import type { BarrelType } from '../types.ts'
|
|
6
|
-
import { TreeNode } from './TreeNode.ts'
|
|
7
|
-
|
|
8
|
-
export type FileMetaBase = {
|
|
9
|
-
pluginName?: string
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
type AddIndexesProps = {
|
|
13
|
-
type: BarrelType | false | undefined
|
|
14
|
-
/**
|
|
15
|
-
* Root based on root and output.path specified in the config
|
|
16
|
-
*/
|
|
17
|
-
root: string
|
|
18
|
-
/**
|
|
19
|
-
* Output for plugin
|
|
20
|
-
*/
|
|
21
|
-
output: {
|
|
22
|
-
path: string
|
|
23
|
-
}
|
|
24
|
-
group?: {
|
|
25
|
-
output: string
|
|
26
|
-
exportAs: string
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
meta?: FileMetaBase
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function getBarrelFilesByRoot(root: string | undefined, files: Array<KubbFile.ResolvedFile>): Array<KubbFile.File> {
|
|
33
|
-
const cachedFiles = new Map<KubbFile.Path, KubbFile.File>()
|
|
34
|
-
|
|
35
|
-
TreeNode.build(files, root)?.forEach((treeNode) => {
|
|
36
|
-
if (!treeNode || !treeNode.children || !treeNode.parent?.data.path) {
|
|
37
|
-
return
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const barrelFilePath = join(treeNode.parent?.data.path, 'index.ts') as KubbFile.Path
|
|
41
|
-
const barrelFile: KubbFile.File = {
|
|
42
|
-
path: barrelFilePath,
|
|
43
|
-
baseName: 'index.ts',
|
|
44
|
-
exports: [],
|
|
45
|
-
imports: [],
|
|
46
|
-
sources: [],
|
|
47
|
-
}
|
|
48
|
-
const previousBarrelFile = cachedFiles.get(barrelFile.path)
|
|
49
|
-
const leaves = treeNode.leaves
|
|
50
|
-
|
|
51
|
-
leaves.forEach((item) => {
|
|
52
|
-
if (!item.data.name) {
|
|
53
|
-
return
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const sources = item.data.file?.sources || []
|
|
57
|
-
|
|
58
|
-
sources.forEach((source) => {
|
|
59
|
-
if (!item.data.file?.path || !source.isIndexable || !source.name) {
|
|
60
|
-
return
|
|
61
|
-
}
|
|
62
|
-
const alreadyContainInPreviousBarrelFile = previousBarrelFile?.sources.some(
|
|
63
|
-
(item) => item.name === source.name && item.isTypeOnly === source.isTypeOnly,
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
if (alreadyContainInPreviousBarrelFile) {
|
|
67
|
-
return
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
barrelFile.exports!.push({
|
|
71
|
-
name: [source.name],
|
|
72
|
-
path: getRelativePath(treeNode.parent?.data.path, item.data.path),
|
|
73
|
-
isTypeOnly: source.isTypeOnly,
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
barrelFile.sources.push({
|
|
77
|
-
name: source.name,
|
|
78
|
-
isTypeOnly: source.isTypeOnly,
|
|
79
|
-
//TODO use parser to generate import
|
|
80
|
-
value: '',
|
|
81
|
-
isExportable: false,
|
|
82
|
-
isIndexable: false,
|
|
83
|
-
})
|
|
84
|
-
})
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
if (previousBarrelFile) {
|
|
88
|
-
previousBarrelFile.sources.push(...barrelFile.sources)
|
|
89
|
-
previousBarrelFile.exports?.push(...(barrelFile.exports || []))
|
|
90
|
-
} else {
|
|
91
|
-
cachedFiles.set(barrelFile.path, barrelFile)
|
|
92
|
-
}
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
return [...cachedFiles.values()]
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function trimExtName(text: string): string {
|
|
99
|
-
const dotIndex = text.lastIndexOf('.')
|
|
100
|
-
// Only strip when the dot is found and no path separator follows it
|
|
101
|
-
// (guards against stripping dots that are part of a directory name like /project.v2/gen)
|
|
102
|
-
if (dotIndex > 0 && !text.includes('/', dotIndex)) {
|
|
103
|
-
return text.slice(0, dotIndex)
|
|
104
|
-
}
|
|
105
|
-
return text
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export async function getBarrelFiles(files: Array<KubbFile.ResolvedFile>, { type, meta = {}, root, output }: AddIndexesProps): Promise<Array<KubbFile.File>> {
|
|
109
|
-
if (!type || type === 'propagate') {
|
|
110
|
-
return []
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const pathToBuildFrom = join(root, output.path)
|
|
114
|
-
|
|
115
|
-
if (trimExtName(pathToBuildFrom).endsWith('index')) {
|
|
116
|
-
return []
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const barrelFiles = getBarrelFilesByRoot(pathToBuildFrom, files)
|
|
120
|
-
|
|
121
|
-
if (type === 'all') {
|
|
122
|
-
return barrelFiles.map((file) => {
|
|
123
|
-
return {
|
|
124
|
-
...file,
|
|
125
|
-
exports: file.exports?.map((exportItem) => {
|
|
126
|
-
return {
|
|
127
|
-
...exportItem,
|
|
128
|
-
name: undefined,
|
|
129
|
-
}
|
|
130
|
-
}),
|
|
131
|
-
}
|
|
132
|
-
})
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return barrelFiles.map((indexFile) => {
|
|
136
|
-
return {
|
|
137
|
-
...indexFile,
|
|
138
|
-
meta,
|
|
139
|
-
}
|
|
140
|
-
})
|
|
141
|
-
}
|