@kubb/core 1.1.11 → 1.1.13

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