@kubb/core 1.1.10 → 1.1.12
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/index.cjs +44 -16
- package/dist/index.d.ts +18 -13
- package/dist/index.js +44 -17
- package/package.json +3 -4
- package/src/build.ts +0 -106
- package/src/config.ts +0 -15
- package/src/generators/Generator.ts +0 -23
- package/src/generators/SchemaGenerator.ts +0 -8
- package/src/generators/index.ts +0 -2
- package/src/index.ts +0 -12
- package/src/managers/fileManager/FileManager.ts +0 -127
- package/src/managers/fileManager/index.ts +0 -3
- package/src/managers/fileManager/types.ts +0 -40
- package/src/managers/fileManager/utils.ts +0 -167
- package/src/managers/index.ts +0 -2
- package/src/managers/pluginManager/ParallelPluginError.ts +0 -15
- package/src/managers/pluginManager/PluginError.ts +0 -11
- package/src/managers/pluginManager/PluginManager.ts +0 -472
- package/src/managers/pluginManager/index.ts +0 -5
- package/src/managers/pluginManager/types.ts +0 -25
- package/src/managers/pluginManager/validate.ts +0 -21
- package/src/plugin.ts +0 -110
- package/src/types.ts +0 -253
- package/src/utils/Queue.ts +0 -46
- package/src/utils/TreeNode.ts +0 -122
- package/src/utils/cache.ts +0 -33
- package/src/utils/clean.ts +0 -5
- package/src/utils/getEncodedText.ts +0 -3
- package/src/utils/getStackTrace.ts +0 -20
- package/src/utils/getUniqueName.ts +0 -9
- package/src/utils/index.ts +0 -18
- package/src/utils/isPromise.ts +0 -5
- package/src/utils/isURL.ts +0 -11
- package/src/utils/jsdoc.ts +0 -13
- package/src/utils/nameSorter.ts +0 -9
- package/src/utils/objectToParameters.ts +0 -28
- package/src/utils/read.ts +0 -45
- package/src/utils/renderTemplate.ts +0 -11
- package/src/utils/timeout.ts +0 -7
- package/src/utils/transformReservedWord.ts +0 -97
- package/src/utils/uniqueId.ts +0 -5
- package/src/utils/write.ts +0 -25
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
type Import = {
|
|
2
|
-
name: string | string[]
|
|
3
|
-
path: string
|
|
4
|
-
isTypeOnly?: boolean
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
type Export = {
|
|
8
|
-
name?: string | string[]
|
|
9
|
-
path: string
|
|
10
|
-
isTypeOnly?: boolean
|
|
11
|
-
asAlias?: boolean
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export type File = {
|
|
15
|
-
/**
|
|
16
|
-
* Name to be used to dynamicly create the fileName(based on input.path)
|
|
17
|
-
*/
|
|
18
|
-
fileName: string
|
|
19
|
-
/**
|
|
20
|
-
* Path will be full qualified path to a specified file
|
|
21
|
-
*/
|
|
22
|
-
path: string
|
|
23
|
-
source: string
|
|
24
|
-
imports?: Import[]
|
|
25
|
-
exports?: Export[]
|
|
26
|
-
/**
|
|
27
|
-
* This will call fileManager.add instead of fileManager.addOrAppend, adding the source when the files already exists
|
|
28
|
-
* @default `false`
|
|
29
|
-
*/
|
|
30
|
-
override?: boolean
|
|
31
|
-
meta?: {
|
|
32
|
-
pluginName?: string
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export type UUID = string
|
|
37
|
-
|
|
38
|
-
export type CacheStore = { id: UUID; file: File; status: Status }
|
|
39
|
-
|
|
40
|
-
export type Status = 'new' | 'success' | 'removed'
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import pathParser from 'node:path'
|
|
2
|
-
|
|
3
|
-
import { createExportDeclaration, createImportDeclaration, print } from '@kubb/ts-codegen'
|
|
4
|
-
|
|
5
|
-
import { TreeNode } from '../../utils/index.ts'
|
|
6
|
-
|
|
7
|
-
import type ts from 'typescript'
|
|
8
|
-
import type { Path } from '../../types.ts'
|
|
9
|
-
import type { PathMode, TreeNodeOptions } from '../../utils/index.ts'
|
|
10
|
-
import type { File } from './types.ts'
|
|
11
|
-
|
|
12
|
-
type TreeNodeData = { type: PathMode; path: Path; name: string }
|
|
13
|
-
|
|
14
|
-
export function writeIndexes(root: string, options: TreeNodeOptions = {}): File[] | null {
|
|
15
|
-
const tree = TreeNode.build<TreeNodeData>(root, { extensions: /\.ts/, ...options })
|
|
16
|
-
|
|
17
|
-
if (!tree) {
|
|
18
|
-
return null
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const fileReducer = (files: File[], currentTree: typeof tree) => {
|
|
22
|
-
if (!currentTree.children) {
|
|
23
|
-
return []
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (currentTree.children?.length > 1) {
|
|
27
|
-
const path = pathParser.resolve(currentTree.data.path, 'index.ts')
|
|
28
|
-
const exports = currentTree.children
|
|
29
|
-
.map((file) => {
|
|
30
|
-
if (!file) {
|
|
31
|
-
return undefined
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const importPath: string = file.data.type === 'directory' ? `./${file.data.name}` : `./${file.data.name.replace(/\.[^.]*$/, '')}`
|
|
35
|
-
|
|
36
|
-
// TODO weird hacky fix
|
|
37
|
-
if (importPath.includes('index') && path.includes('index')) {
|
|
38
|
-
return undefined
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return { path: importPath }
|
|
42
|
-
})
|
|
43
|
-
.filter(Boolean) as File['exports']
|
|
44
|
-
|
|
45
|
-
files.push({
|
|
46
|
-
path,
|
|
47
|
-
fileName: 'index.ts',
|
|
48
|
-
source: '',
|
|
49
|
-
exports,
|
|
50
|
-
})
|
|
51
|
-
} else {
|
|
52
|
-
currentTree.children?.forEach((child) => {
|
|
53
|
-
const path = pathParser.resolve(currentTree.data.path, 'index.ts')
|
|
54
|
-
const importPath = child.data.type === 'directory' ? `./${child.data.name}` : `./${child.data.name.replace(/\.[^.]*$/, '')}`
|
|
55
|
-
|
|
56
|
-
files.push({
|
|
57
|
-
path,
|
|
58
|
-
fileName: 'index.ts',
|
|
59
|
-
source: '',
|
|
60
|
-
exports: [{ path: importPath }],
|
|
61
|
-
})
|
|
62
|
-
})
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
currentTree.children.forEach((childItem) => {
|
|
66
|
-
fileReducer(files, childItem)
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
return files
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const files = fileReducer([], tree)
|
|
73
|
-
|
|
74
|
-
return files
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export function combineFiles(files: Array<File | null>): File[] {
|
|
78
|
-
return (files.filter(Boolean) as File[]).reduce((acc, curr: File) => {
|
|
79
|
-
const prevIndex = acc.findIndex((item) => item.path === curr.path)
|
|
80
|
-
|
|
81
|
-
if (prevIndex !== -1) {
|
|
82
|
-
const prev = acc[prevIndex]
|
|
83
|
-
acc[prevIndex] = {
|
|
84
|
-
...curr,
|
|
85
|
-
source: `${prev.source}\n${curr.source}`,
|
|
86
|
-
imports: [...(prev.imports || []), ...(curr.imports || [])],
|
|
87
|
-
exports: [...(prev.exports || []), ...(curr.exports || [])],
|
|
88
|
-
}
|
|
89
|
-
} else {
|
|
90
|
-
acc.push(curr)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return acc
|
|
94
|
-
}, [] as File[])
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export function getFileSource(file: File): string {
|
|
98
|
-
let { source } = file
|
|
99
|
-
|
|
100
|
-
// TODO make generic check
|
|
101
|
-
if (!file.fileName.endsWith('.ts')) {
|
|
102
|
-
return file.source
|
|
103
|
-
}
|
|
104
|
-
const imports: File['imports'] = []
|
|
105
|
-
const exports: File['exports'] = []
|
|
106
|
-
|
|
107
|
-
file.imports?.forEach((curr) => {
|
|
108
|
-
const existingImport = imports.find((imp) => imp.path === curr.path)
|
|
109
|
-
|
|
110
|
-
if (!existingImport) {
|
|
111
|
-
imports.push({
|
|
112
|
-
...curr,
|
|
113
|
-
name: Array.isArray(curr.name) ? [...new Set(curr.name)] : curr.name,
|
|
114
|
-
})
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (existingImport && !Array.isArray(existingImport.name) && existingImport.name !== curr.name) {
|
|
118
|
-
imports.push(curr)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (existingImport && Array.isArray(existingImport.name)) {
|
|
122
|
-
if (Array.isArray(curr.name)) {
|
|
123
|
-
existingImport.name = [...new Set([...existingImport.name, ...curr.name])]
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
file.exports?.forEach((curr) => {
|
|
129
|
-
const exists = exports.find((imp) => imp.path === curr.path)
|
|
130
|
-
if (!exists) {
|
|
131
|
-
exports.push({
|
|
132
|
-
...curr,
|
|
133
|
-
name: Array.isArray(curr.name) ? [...new Set(curr.name)] : curr.name,
|
|
134
|
-
})
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (exists && !Array.isArray(exists.name) && exists.name !== curr.name && exists.asAlias === curr.asAlias) {
|
|
138
|
-
exports.push(curr)
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (exists && Array.isArray(exists.name)) {
|
|
142
|
-
if (Array.isArray(curr.name)) {
|
|
143
|
-
exists.name = [...new Set([...exists.name, ...curr.name])]
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
const importNodes = imports.reduce((prev, curr) => {
|
|
149
|
-
return [...prev, createImportDeclaration({ name: curr.name, path: curr.path, isTypeOnly: curr.isTypeOnly })]
|
|
150
|
-
}, [] as ts.ImportDeclaration[])
|
|
151
|
-
const importSource = print(importNodes)
|
|
152
|
-
|
|
153
|
-
const exportNodes = exports.reduce((prev, curr) => {
|
|
154
|
-
return [...prev, createExportDeclaration({ name: curr.name, path: curr.path, isTypeOnly: curr.isTypeOnly, asAlias: curr.asAlias })]
|
|
155
|
-
}, [] as ts.ExportDeclaration[])
|
|
156
|
-
const exportSource = print(exportNodes)
|
|
157
|
-
|
|
158
|
-
if (importSource) {
|
|
159
|
-
source = `${importSource}\n${source}`
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (exportSource) {
|
|
163
|
-
source = `${exportSource}\n${source}`
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return source
|
|
167
|
-
}
|
package/src/managers/index.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { PluginError } from './PluginError.ts'
|
|
2
|
-
import type { PluginManager } from './PluginManager'
|
|
3
|
-
|
|
4
|
-
export class ParallelPluginError extends Error {
|
|
5
|
-
public errors: PluginError[]
|
|
6
|
-
|
|
7
|
-
public pluginManager: PluginManager
|
|
8
|
-
|
|
9
|
-
constructor(message: string, options: { cause?: Error; errors: PluginError[]; pluginManager: PluginManager }) {
|
|
10
|
-
super(message, { cause: options.cause })
|
|
11
|
-
|
|
12
|
-
this.errors = options.errors
|
|
13
|
-
this.pluginManager = options.pluginManager
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { PluginManager } from './PluginManager'
|
|
2
|
-
|
|
3
|
-
export class PluginError extends Error {
|
|
4
|
-
public pluginManager: PluginManager
|
|
5
|
-
|
|
6
|
-
constructor(message: string, options: { cause?: Error; pluginManager: PluginManager }) {
|
|
7
|
-
super(message, { cause: options.cause })
|
|
8
|
-
|
|
9
|
-
this.pluginManager = options.pluginManager
|
|
10
|
-
}
|
|
11
|
-
}
|
|
@@ -1,472 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/ban-types */
|
|
2
|
-
|
|
3
|
-
import { definePlugin } from '../../plugin.ts'
|
|
4
|
-
import { isPromise } from '../../utils/isPromise.ts'
|
|
5
|
-
import { Queue } from '../../utils/Queue.ts'
|
|
6
|
-
import { FileManager } from '../fileManager/FileManager.ts'
|
|
7
|
-
import { ParallelPluginError } from './ParallelPluginError.ts'
|
|
8
|
-
import { PluginError } from './PluginError.ts'
|
|
9
|
-
|
|
10
|
-
import type { CorePluginOptions } from '../../plugin.ts'
|
|
11
|
-
import type { KubbConfig, KubbPlugin, MaybePromise, PluginLifecycle, PluginLifecycleHooks, ResolveNameParams, ResolvePathParams } from '../../types.ts'
|
|
12
|
-
import type { QueueTask } from '../../utils/Queue.ts'
|
|
13
|
-
import type { Argument0, Executer, OnExecute, ParseResult, SafeParseResult, Strategy } from './types.ts'
|
|
14
|
-
|
|
15
|
-
// inspired by: https://github.com/rollup/rollup/blob/master/src/utils/PluginDriver.ts#
|
|
16
|
-
|
|
17
|
-
// This will make sure no input hook is omitted
|
|
18
|
-
const hookNames: {
|
|
19
|
-
[P in PluginLifecycleHooks]: 1
|
|
20
|
-
} = {
|
|
21
|
-
validate: 1,
|
|
22
|
-
buildStart: 1,
|
|
23
|
-
resolvePath: 1,
|
|
24
|
-
resolveName: 1,
|
|
25
|
-
load: 1,
|
|
26
|
-
transform: 1,
|
|
27
|
-
writeFile: 1,
|
|
28
|
-
buildEnd: 1,
|
|
29
|
-
}
|
|
30
|
-
export const hooks = Object.keys(hookNames) as [PluginLifecycleHooks]
|
|
31
|
-
|
|
32
|
-
type Options = { task: QueueTask; onExecute?: OnExecute<PluginLifecycleHooks> }
|
|
33
|
-
|
|
34
|
-
export class PluginManager {
|
|
35
|
-
public plugins: KubbPlugin[]
|
|
36
|
-
|
|
37
|
-
public readonly fileManager: FileManager
|
|
38
|
-
|
|
39
|
-
private readonly onExecute?: OnExecute
|
|
40
|
-
|
|
41
|
-
private readonly core: KubbPlugin<CorePluginOptions>
|
|
42
|
-
|
|
43
|
-
public queue: Queue
|
|
44
|
-
|
|
45
|
-
public executer: Executer | undefined
|
|
46
|
-
|
|
47
|
-
public executed: Executer[] = []
|
|
48
|
-
|
|
49
|
-
constructor(config: KubbConfig, options: Options) {
|
|
50
|
-
this.onExecute = options.onExecute
|
|
51
|
-
this.queue = new Queue(10)
|
|
52
|
-
|
|
53
|
-
this.fileManager = new FileManager({ task: options.task, queue: this.queue })
|
|
54
|
-
this.core = definePlugin({
|
|
55
|
-
config,
|
|
56
|
-
fileManager: this.fileManager,
|
|
57
|
-
load: this.load,
|
|
58
|
-
resolvePath: this.resolvePath,
|
|
59
|
-
resolveName: this.resolveName,
|
|
60
|
-
getExecuter: this.getExecuter.bind(this),
|
|
61
|
-
}) as KubbPlugin<CorePluginOptions> & {
|
|
62
|
-
api: CorePluginOptions['api']
|
|
63
|
-
}
|
|
64
|
-
this.plugins = [this.core, ...(config.plugins || [])]
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
getExecuter() {
|
|
68
|
-
return this.executer
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
resolvePath = (params: ResolvePathParams) => {
|
|
72
|
-
if (params.pluginName) {
|
|
73
|
-
return this.hookForPluginSync({
|
|
74
|
-
pluginName: params.pluginName,
|
|
75
|
-
hookName: 'resolvePath',
|
|
76
|
-
parameters: [params.fileName, params.directory, params.options],
|
|
77
|
-
})
|
|
78
|
-
}
|
|
79
|
-
return this.hookFirstSync({
|
|
80
|
-
hookName: 'resolvePath',
|
|
81
|
-
parameters: [params.fileName, params.directory, params.options],
|
|
82
|
-
}).result
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
resolveName = (params: ResolveNameParams) => {
|
|
86
|
-
if (params.pluginName) {
|
|
87
|
-
return this.hookForPluginSync({
|
|
88
|
-
pluginName: params.pluginName,
|
|
89
|
-
hookName: 'resolveName',
|
|
90
|
-
parameters: [params.name],
|
|
91
|
-
})
|
|
92
|
-
}
|
|
93
|
-
return this.hookFirstSync({
|
|
94
|
-
hookName: 'resolveName',
|
|
95
|
-
parameters: [params.name],
|
|
96
|
-
}).result
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
load = async (id: string) => {
|
|
100
|
-
return this.hookFirst({
|
|
101
|
-
hookName: 'load',
|
|
102
|
-
parameters: [id],
|
|
103
|
-
})
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
*
|
|
108
|
-
* Run only hook for a specific plugin name
|
|
109
|
-
*/
|
|
110
|
-
hookForPlugin<H extends PluginLifecycleHooks>({
|
|
111
|
-
pluginName,
|
|
112
|
-
hookName,
|
|
113
|
-
parameters,
|
|
114
|
-
}: {
|
|
115
|
-
pluginName: string
|
|
116
|
-
hookName: H
|
|
117
|
-
parameters: Parameters<PluginLifecycle[H]>
|
|
118
|
-
}): Promise<ReturnType<ParseResult<H>> | null> | null {
|
|
119
|
-
const plugin = this.getPlugin(hookName, pluginName)
|
|
120
|
-
|
|
121
|
-
return this.execute({
|
|
122
|
-
strategy: 'hookFirst',
|
|
123
|
-
hookName,
|
|
124
|
-
parameters,
|
|
125
|
-
plugin,
|
|
126
|
-
})
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
hookForPluginSync<H extends PluginLifecycleHooks>({
|
|
130
|
-
pluginName,
|
|
131
|
-
hookName,
|
|
132
|
-
parameters,
|
|
133
|
-
}: {
|
|
134
|
-
pluginName: string
|
|
135
|
-
hookName: H
|
|
136
|
-
parameters: Parameters<PluginLifecycle[H]>
|
|
137
|
-
}): ReturnType<ParseResult<H>> | null {
|
|
138
|
-
const plugin = this.getPlugin(hookName, pluginName)
|
|
139
|
-
|
|
140
|
-
return this.executeSync({
|
|
141
|
-
strategy: 'hookFirst',
|
|
142
|
-
hookName,
|
|
143
|
-
parameters,
|
|
144
|
-
plugin,
|
|
145
|
-
})
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
*
|
|
150
|
-
* Chains, first non-null result stops and returns
|
|
151
|
-
*/
|
|
152
|
-
hookFirst<H extends PluginLifecycleHooks>({
|
|
153
|
-
hookName,
|
|
154
|
-
parameters,
|
|
155
|
-
skipped,
|
|
156
|
-
}: {
|
|
157
|
-
hookName: H
|
|
158
|
-
parameters: Parameters<PluginLifecycle[H]>
|
|
159
|
-
skipped?: ReadonlySet<KubbPlugin> | null
|
|
160
|
-
}): Promise<SafeParseResult<H>> {
|
|
161
|
-
let promise: Promise<SafeParseResult<H>> = Promise.resolve(null as unknown as SafeParseResult<H>)
|
|
162
|
-
|
|
163
|
-
for (const plugin of this.getSortedPlugins(hookName)) {
|
|
164
|
-
if (skipped && skipped.has(plugin)) {
|
|
165
|
-
continue
|
|
166
|
-
}
|
|
167
|
-
promise = promise.then(async (parseResult) => {
|
|
168
|
-
if (parseResult?.result != null) {
|
|
169
|
-
return parseResult
|
|
170
|
-
}
|
|
171
|
-
const value = await this.execute<H>({
|
|
172
|
-
strategy: 'hookFirst',
|
|
173
|
-
hookName,
|
|
174
|
-
parameters,
|
|
175
|
-
plugin,
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
return Promise.resolve({
|
|
179
|
-
plugin,
|
|
180
|
-
result: value,
|
|
181
|
-
} as typeof parseResult)
|
|
182
|
-
})
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
return promise
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
*
|
|
190
|
-
* Chains, first non-null result stops and returns
|
|
191
|
-
*/
|
|
192
|
-
hookFirstSync<H extends PluginLifecycleHooks>({
|
|
193
|
-
hookName,
|
|
194
|
-
parameters,
|
|
195
|
-
skipped,
|
|
196
|
-
}: {
|
|
197
|
-
hookName: H
|
|
198
|
-
parameters: Parameters<PluginLifecycle[H]>
|
|
199
|
-
skipped?: ReadonlySet<KubbPlugin> | null
|
|
200
|
-
}): SafeParseResult<H> {
|
|
201
|
-
let parseResult: SafeParseResult<H> = null as unknown as SafeParseResult<H>
|
|
202
|
-
|
|
203
|
-
for (const plugin of this.getSortedPlugins(hookName)) {
|
|
204
|
-
if (skipped && skipped.has(plugin)) {
|
|
205
|
-
continue
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
parseResult = {
|
|
209
|
-
result: this.executeSync<H>({
|
|
210
|
-
strategy: 'hookFirst',
|
|
211
|
-
hookName,
|
|
212
|
-
parameters,
|
|
213
|
-
plugin,
|
|
214
|
-
}),
|
|
215
|
-
plugin,
|
|
216
|
-
} as SafeParseResult<H>
|
|
217
|
-
|
|
218
|
-
if (parseResult?.result != null) {
|
|
219
|
-
break
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
return parseResult
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
*
|
|
227
|
-
* Parallel, runs all plugins
|
|
228
|
-
*/
|
|
229
|
-
async hookParallel<H extends PluginLifecycleHooks, TOuput = void>({
|
|
230
|
-
hookName,
|
|
231
|
-
parameters,
|
|
232
|
-
}: {
|
|
233
|
-
hookName: H
|
|
234
|
-
parameters?: Parameters<PluginLifecycle[H]> | undefined
|
|
235
|
-
}): Promise<Awaited<TOuput>[]> {
|
|
236
|
-
const parallelPromises: Promise<TOuput>[] = []
|
|
237
|
-
|
|
238
|
-
for (const plugin of this.getSortedPlugins(hookName)) {
|
|
239
|
-
// TODO implement sequential with `buildStart` as an object({ sequential: boolean; handler: PluginContext["buildStart"] })
|
|
240
|
-
// if ((plugin[hookName] as { sequential?: boolean })?.sequential) {
|
|
241
|
-
// await Promise.all(parallelPromises)
|
|
242
|
-
// parallelPromises.length = 0
|
|
243
|
-
// await this.execute({
|
|
244
|
-
// strategy: 'hookParallel',
|
|
245
|
-
// hookName,
|
|
246
|
-
// parameters,
|
|
247
|
-
// plugin,
|
|
248
|
-
// })
|
|
249
|
-
// }
|
|
250
|
-
const promise: Promise<TOuput> | null = this.execute({ strategy: 'hookParallel', hookName, parameters, plugin })
|
|
251
|
-
|
|
252
|
-
if (promise) {
|
|
253
|
-
parallelPromises.push(promise)
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
const results = await Promise.allSettled(parallelPromises)
|
|
257
|
-
const errors = results.filter((result) => result.status === 'rejected').map((result) => (result as PromiseRejectedResult).reason) as PluginError[]
|
|
258
|
-
|
|
259
|
-
if (errors.length) {
|
|
260
|
-
throw new ParallelPluginError('Error', { errors, pluginManager: this })
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
return results.filter((result) => result.status === 'fulfilled').map((result) => (result as PromiseFulfilledResult<Awaited<TOuput>>).value)
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
*
|
|
268
|
-
* Chains, reduces returned value, handling the reduced value as the first hook argument
|
|
269
|
-
*/
|
|
270
|
-
hookReduceArg0<H extends PluginLifecycleHooks>({
|
|
271
|
-
hookName,
|
|
272
|
-
parameters,
|
|
273
|
-
reduce,
|
|
274
|
-
}: {
|
|
275
|
-
hookName: H
|
|
276
|
-
parameters: Parameters<PluginLifecycle[H]>
|
|
277
|
-
reduce: (reduction: Argument0<H>, result: ReturnType<ParseResult<H>>, plugin: KubbPlugin) => MaybePromise<Argument0<H> | null>
|
|
278
|
-
}): Promise<Argument0<H>> {
|
|
279
|
-
const [argument0, ...rest] = parameters
|
|
280
|
-
|
|
281
|
-
let promise: Promise<Argument0<H>> = Promise.resolve(argument0)
|
|
282
|
-
for (const plugin of this.getSortedPlugins(hookName)) {
|
|
283
|
-
promise = promise
|
|
284
|
-
.then((arg0) => {
|
|
285
|
-
const value = this.execute({
|
|
286
|
-
strategy: 'hookReduceArg0',
|
|
287
|
-
hookName,
|
|
288
|
-
parameters: [arg0, ...rest] as Parameters<PluginLifecycle[H]>,
|
|
289
|
-
plugin,
|
|
290
|
-
})
|
|
291
|
-
return value
|
|
292
|
-
})
|
|
293
|
-
.then((result) => reduce.call(this.core.api, argument0, result as ReturnType<ParseResult<H>>, plugin)) as Promise<Argument0<H>>
|
|
294
|
-
}
|
|
295
|
-
return promise
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* Chains plugins
|
|
300
|
-
*/
|
|
301
|
-
hookSeq<H extends PluginLifecycleHooks>({ hookName, parameters }: { hookName: H; parameters?: Parameters<PluginLifecycle[H]> }) {
|
|
302
|
-
let promise: Promise<void | null> = Promise.resolve()
|
|
303
|
-
for (const plugin of this.getSortedPlugins(hookName)) {
|
|
304
|
-
promise = promise.then(() =>
|
|
305
|
-
this.execute({
|
|
306
|
-
strategy: 'hookSeq',
|
|
307
|
-
hookName,
|
|
308
|
-
parameters,
|
|
309
|
-
plugin,
|
|
310
|
-
})
|
|
311
|
-
)
|
|
312
|
-
}
|
|
313
|
-
return promise.then(noReturn)
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
private getSortedPlugins(_hookName: keyof PluginLifecycle): KubbPlugin[] {
|
|
317
|
-
const plugins = [...this.plugins].filter((plugin) => plugin.name !== 'core')
|
|
318
|
-
|
|
319
|
-
return plugins
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
public getPlugin(hookName: keyof PluginLifecycle, pluginName: string): KubbPlugin {
|
|
323
|
-
const plugins = [...this.plugins]
|
|
324
|
-
|
|
325
|
-
const pluginByPluginName = plugins.find((item) => item.name === pluginName && item[hookName])
|
|
326
|
-
if (!pluginByPluginName) {
|
|
327
|
-
// fallback on the core plugin when there is no match
|
|
328
|
-
|
|
329
|
-
return this.core
|
|
330
|
-
}
|
|
331
|
-
return pluginByPluginName
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
private addExecuter(executer: Executer | undefined) {
|
|
335
|
-
this.onExecute?.call(this, executer)
|
|
336
|
-
|
|
337
|
-
if (executer) {
|
|
338
|
-
this.executed.push(executer)
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/**
|
|
343
|
-
* Run an async plugin hook and return the result.
|
|
344
|
-
* @param hookName Name of the plugin hook. Must be either in `PluginHooks` or `OutputPluginValueHooks`.
|
|
345
|
-
* @param args Arguments passed to the plugin hook.
|
|
346
|
-
* @param plugin The actual pluginObject to run.
|
|
347
|
-
*/
|
|
348
|
-
// Implementation signature
|
|
349
|
-
private execute<H extends PluginLifecycleHooks, TResult = void>({
|
|
350
|
-
strategy,
|
|
351
|
-
hookName,
|
|
352
|
-
parameters,
|
|
353
|
-
plugin,
|
|
354
|
-
}: {
|
|
355
|
-
strategy: Strategy
|
|
356
|
-
hookName: H
|
|
357
|
-
parameters: unknown[] | undefined
|
|
358
|
-
plugin: KubbPlugin
|
|
359
|
-
}): Promise<TResult> | null {
|
|
360
|
-
const hook = plugin[hookName]
|
|
361
|
-
|
|
362
|
-
if (!hook) {
|
|
363
|
-
return null
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
return Promise.resolve()
|
|
367
|
-
.then(() => {
|
|
368
|
-
// add current execution to the variable `this.executer` so we can track which plugin is getting called
|
|
369
|
-
this.executer = {
|
|
370
|
-
strategy,
|
|
371
|
-
hookName,
|
|
372
|
-
plugin,
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
if (typeof hook === 'function') {
|
|
376
|
-
const hookResult = (hook as Function).apply(this.core.api, parameters) as TResult
|
|
377
|
-
|
|
378
|
-
if (isPromise(hookResult)) {
|
|
379
|
-
return Promise.resolve(hookResult).then((result: TResult) => {
|
|
380
|
-
this.addExecuter({
|
|
381
|
-
strategy,
|
|
382
|
-
hookName,
|
|
383
|
-
plugin,
|
|
384
|
-
})
|
|
385
|
-
|
|
386
|
-
return result
|
|
387
|
-
})
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
return hookResult
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
this.addExecuter({
|
|
394
|
-
strategy,
|
|
395
|
-
hookName,
|
|
396
|
-
plugin,
|
|
397
|
-
})
|
|
398
|
-
|
|
399
|
-
return hook
|
|
400
|
-
})
|
|
401
|
-
.catch((e: Error) => {
|
|
402
|
-
this.catcher<H>(e, plugin, hookName)
|
|
403
|
-
}) as Promise<TResult>
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
/**
|
|
407
|
-
* Run a sync plugin hook and return the result.
|
|
408
|
-
* @param hookName Name of the plugin hook. Must be in `PluginHooks`.
|
|
409
|
-
* @param args Arguments passed to the plugin hook.
|
|
410
|
-
* @param plugin The acutal plugin
|
|
411
|
-
* @param replaceContext When passed, the plugin context can be overridden.
|
|
412
|
-
*/
|
|
413
|
-
private executeSync<H extends PluginLifecycleHooks>({
|
|
414
|
-
strategy,
|
|
415
|
-
hookName,
|
|
416
|
-
parameters,
|
|
417
|
-
plugin,
|
|
418
|
-
}: {
|
|
419
|
-
strategy: Strategy
|
|
420
|
-
hookName: H
|
|
421
|
-
parameters: Parameters<PluginLifecycle[H]>
|
|
422
|
-
plugin: KubbPlugin
|
|
423
|
-
}): ReturnType<ParseResult<H>> | null {
|
|
424
|
-
const hook = plugin[hookName]
|
|
425
|
-
|
|
426
|
-
if (!hook) {
|
|
427
|
-
return null
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
try {
|
|
431
|
-
// add current execution to the variable `this.executer` so we can track which plugin is getting called
|
|
432
|
-
this.executer = {
|
|
433
|
-
strategy,
|
|
434
|
-
hookName,
|
|
435
|
-
plugin,
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
if (typeof hook === 'function') {
|
|
439
|
-
const fn = (hook as Function).apply(this.core.api, parameters) as ReturnType<ParseResult<H>>
|
|
440
|
-
|
|
441
|
-
this.addExecuter({
|
|
442
|
-
strategy,
|
|
443
|
-
hookName,
|
|
444
|
-
plugin,
|
|
445
|
-
})
|
|
446
|
-
|
|
447
|
-
return fn
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
this.addExecuter({
|
|
451
|
-
strategy,
|
|
452
|
-
hookName,
|
|
453
|
-
plugin,
|
|
454
|
-
})
|
|
455
|
-
|
|
456
|
-
return hook
|
|
457
|
-
} catch (e) {
|
|
458
|
-
this.catcher<H>(e as Error, plugin, hookName)
|
|
459
|
-
|
|
460
|
-
return null as ReturnType<ParseResult<H>>
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
private catcher<H extends PluginLifecycleHooks>(e: Error, plugin: KubbPlugin, hookName: H) {
|
|
465
|
-
const text = `${e.message} (plugin: ${plugin.name}, hook: ${hookName})\n`
|
|
466
|
-
|
|
467
|
-
throw new PluginError(text, { cause: e, pluginManager: this })
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
472
|
-
function noReturn() {}
|