@kubb/core 5.0.0-alpha.6 → 5.0.0-alpha.60

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.
Files changed (72) hide show
  1. package/README.md +3 -2
  2. package/dist/PluginDriver-Bc0HQM8V.js +948 -0
  3. package/dist/PluginDriver-Bc0HQM8V.js.map +1 -0
  4. package/dist/PluginDriver-Dyl2fwfQ.cjs +1039 -0
  5. package/dist/PluginDriver-Dyl2fwfQ.cjs.map +1 -0
  6. package/dist/index.cjs +691 -1798
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.ts +279 -265
  9. package/dist/index.js +678 -1765
  10. package/dist/index.js.map +1 -1
  11. package/dist/mocks.cjs +138 -0
  12. package/dist/mocks.cjs.map +1 -0
  13. package/dist/mocks.d.ts +74 -0
  14. package/dist/mocks.js +133 -0
  15. package/dist/mocks.js.map +1 -0
  16. package/dist/types-i0b4_23K.d.ts +1903 -0
  17. package/package.json +51 -57
  18. package/src/FileManager.ts +110 -0
  19. package/src/FileProcessor.ts +86 -0
  20. package/src/Kubb.ts +205 -130
  21. package/src/PluginDriver.ts +424 -0
  22. package/src/constants.ts +20 -47
  23. package/src/createAdapter.ts +25 -0
  24. package/src/createKubb.ts +527 -0
  25. package/src/createRenderer.ts +57 -0
  26. package/src/createStorage.ts +58 -0
  27. package/src/defineGenerator.ts +88 -100
  28. package/src/defineLogger.ts +13 -3
  29. package/src/defineMiddleware.ts +59 -0
  30. package/src/defineParser.ts +45 -0
  31. package/src/definePlugin.ts +78 -7
  32. package/src/defineResolver.ts +521 -0
  33. package/src/devtools.ts +14 -14
  34. package/src/index.ts +13 -17
  35. package/src/mocks.ts +171 -0
  36. package/src/renderNode.ts +35 -0
  37. package/src/storages/fsStorage.ts +40 -11
  38. package/src/storages/memoryStorage.ts +4 -3
  39. package/src/types.ts +738 -218
  40. package/src/utils/diagnostics.ts +4 -1
  41. package/src/utils/isInputPath.ts +10 -0
  42. package/src/utils/packageJSON.ts +99 -0
  43. package/dist/PluginManager-vZodFEMe.d.ts +0 -1056
  44. package/dist/chunk-ByKO4r7w.cjs +0 -38
  45. package/dist/hooks.cjs +0 -60
  46. package/dist/hooks.cjs.map +0 -1
  47. package/dist/hooks.d.ts +0 -64
  48. package/dist/hooks.js +0 -56
  49. package/dist/hooks.js.map +0 -1
  50. package/src/BarrelManager.ts +0 -74
  51. package/src/PackageManager.ts +0 -180
  52. package/src/PluginManager.ts +0 -667
  53. package/src/PromiseManager.ts +0 -40
  54. package/src/build.ts +0 -419
  55. package/src/config.ts +0 -56
  56. package/src/defineAdapter.ts +0 -22
  57. package/src/defineStorage.ts +0 -56
  58. package/src/errors.ts +0 -1
  59. package/src/hooks/index.ts +0 -4
  60. package/src/hooks/useKubb.ts +0 -55
  61. package/src/hooks/useMode.ts +0 -11
  62. package/src/hooks/usePlugin.ts +0 -11
  63. package/src/hooks/usePluginManager.ts +0 -11
  64. package/src/utils/FunctionParams.ts +0 -155
  65. package/src/utils/TreeNode.ts +0 -215
  66. package/src/utils/executeStrategies.ts +0 -81
  67. package/src/utils/formatters.ts +0 -56
  68. package/src/utils/getBarrelFiles.ts +0 -79
  69. package/src/utils/getConfigs.ts +0 -30
  70. package/src/utils/getPlugins.ts +0 -23
  71. package/src/utils/linters.ts +0 -25
  72. package/src/utils/resolveOptions.ts +0 -93
@@ -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
- }
@@ -1,215 +0,0 @@
1
- import path from 'node:path'
2
- import type { KubbFile } from '@kubb/fabric-core/types'
3
- import { getMode } from '../PluginManager.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
@@ -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,79 +0,0 @@
1
- import { join } from 'node:path'
2
- import type { KubbFile } from '@kubb/fabric-core/types'
3
- import { BarrelManager } from '../BarrelManager.ts'
4
- import type { BarrelType } from '../types.ts'
5
-
6
- export type FileMetaBase = {
7
- pluginName?: string
8
- }
9
-
10
- type AddIndexesProps = {
11
- type: BarrelType | false | undefined
12
- /**
13
- * Root based on root and output.path specified in the config
14
- */
15
- root: string
16
- /**
17
- * Output for plugin
18
- */
19
- output: {
20
- path: string
21
- }
22
- group?: {
23
- output: string
24
- exportAs: string
25
- }
26
-
27
- meta?: FileMetaBase
28
- }
29
-
30
- function trimExtName(text: string): string {
31
- const dotIndex = text.lastIndexOf('.')
32
- // Only strip when the dot is found and no path separator follows it
33
- // (guards against stripping dots that are part of a directory name like /project.v2/gen)
34
- if (dotIndex > 0 && !text.includes('/', dotIndex)) {
35
- return text.slice(0, dotIndex)
36
- }
37
- return text
38
- }
39
-
40
- export async function getBarrelFiles(files: Array<KubbFile.ResolvedFile>, { type, meta = {}, root, output }: AddIndexesProps): Promise<KubbFile.File[]> {
41
- if (!type || type === 'propagate') {
42
- return []
43
- }
44
-
45
- const barrelManager = new BarrelManager()
46
-
47
- const pathToBuildFrom = join(root, output.path)
48
-
49
- if (trimExtName(pathToBuildFrom).endsWith('index')) {
50
- return []
51
- }
52
-
53
- const barrelFiles = barrelManager.getFiles({
54
- files,
55
- root: pathToBuildFrom,
56
- meta,
57
- })
58
-
59
- if (type === 'all') {
60
- return barrelFiles.map((file) => {
61
- return {
62
- ...file,
63
- exports: file.exports?.map((exportItem) => {
64
- return {
65
- ...exportItem,
66
- name: undefined,
67
- }
68
- }),
69
- }
70
- })
71
- }
72
-
73
- return barrelFiles.map((indexFile) => {
74
- return {
75
- ...indexFile,
76
- meta,
77
- }
78
- })
79
- }
@@ -1,30 +0,0 @@
1
- import type { CLIOptions, ConfigInput } from '../config.ts'
2
- import type { Config, UserConfig } from '../types.ts'
3
- import { getPlugins } from './getPlugins.ts'
4
-
5
- /**
6
- * Converting UserConfig to Config Array without a change in the object beside the JSON convert.
7
- */
8
- export async function getConfigs(config: ConfigInput | UserConfig, args: CLIOptions): Promise<Array<Config>> {
9
- const resolvedConfig: Promise<UserConfig | Array<UserConfig>> =
10
- typeof config === 'function' ? Promise.resolve(config(args as CLIOptions)) : Promise.resolve(config)
11
-
12
- let userConfigs = await resolvedConfig
13
-
14
- if (!Array.isArray(userConfigs)) {
15
- userConfigs = [userConfigs]
16
- }
17
-
18
- const results: Array<Config> = []
19
-
20
- for (const item of userConfigs) {
21
- const plugins = item.plugins ? await getPlugins(item.plugins) : undefined
22
-
23
- results.push({
24
- ...item,
25
- plugins,
26
- } as Config)
27
- }
28
-
29
- return results
30
- }
@@ -1,23 +0,0 @@
1
- import type { UnknownUserPlugin, UserConfig } from '../types.ts'
2
-
3
- type PluginsArray = Array<Omit<UnknownUserPlugin, 'inject'>>
4
-
5
- function isJSONPlugins(plugins: UserConfig['plugins']): boolean {
6
- return Array.isArray(plugins) && plugins.some((plugin) => Array.isArray(plugin) && typeof (plugin as unknown[])[0] === 'string')
7
- }
8
-
9
- function isObjectPlugins(plugins: UserConfig['plugins']): boolean {
10
- return plugins instanceof Object && !Array.isArray(plugins)
11
- }
12
-
13
- export function getPlugins(plugins: UserConfig['plugins']): Promise<PluginsArray | undefined> {
14
- if (isObjectPlugins(plugins)) {
15
- throw new Error('Object plugins are not supported anymore, best to use http://kubb.dev/getting-started/configure#json')
16
- }
17
-
18
- if (isJSONPlugins(plugins)) {
19
- throw new Error('JSON plugins are not supported anymore, best to use http://kubb.dev/getting-started/configure#json')
20
- }
21
-
22
- return Promise.resolve(plugins)
23
- }
@@ -1,25 +0,0 @@
1
- import { x } from 'tinyexec'
2
- import type { linters } from '../constants.ts'
3
-
4
- type Linter = keyof typeof linters
5
-
6
- async function isLinterAvailable(linter: Linter): Promise<boolean> {
7
- try {
8
- await x(linter, ['--version'], { nodeOptions: { stdio: 'ignore' } })
9
- return true
10
- } catch {
11
- return false
12
- }
13
- }
14
-
15
- export async function detectLinter(): Promise<Linter | undefined> {
16
- const linterNames: Linter[] = ['biome', 'oxlint', 'eslint']
17
-
18
- for (const linter of linterNames) {
19
- if (await isLinterAvailable(linter)) {
20
- return linter
21
- }
22
- }
23
-
24
- return undefined
25
- }