@kubb/core 3.0.0-alpha.5 → 3.0.0-alpha.6

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 (73) hide show
  1. package/dist/{FileManager-tzl0YsYE.d.ts → FileManager-Ceski1W9.d.ts} +46 -33
  2. package/dist/{FileManager-jZpqETKU.d.cts → FileManager-wyXRkgIk.d.cts} +46 -33
  3. package/dist/chunk-2EU7DMPM.js +97 -0
  4. package/dist/chunk-2EU7DMPM.js.map +1 -0
  5. package/dist/chunk-5HN4LW3R.cjs +102 -0
  6. package/dist/chunk-5HN4LW3R.cjs.map +1 -0
  7. package/dist/{chunk-Z5CHJQJB.js → chunk-76UEJFFE.js} +1 -4
  8. package/dist/chunk-76UEJFFE.js.map +1 -0
  9. package/dist/{chunk-5JZNFPUP.js → chunk-AWAZR3D5.js} +61 -10
  10. package/dist/chunk-AWAZR3D5.js.map +1 -0
  11. package/dist/{chunk-FWU62YO5.cjs → chunk-DCZQYCCO.cjs} +216 -326
  12. package/dist/chunk-DCZQYCCO.cjs.map +1 -0
  13. package/dist/{chunk-YTSNYMHW.cjs → chunk-L3JJLZ5Q.cjs} +62 -11
  14. package/dist/chunk-L3JJLZ5Q.cjs.map +1 -0
  15. package/dist/{chunk-RBP2ASUX.cjs → chunk-LOLEBOMW.cjs} +1 -4
  16. package/dist/chunk-LOLEBOMW.cjs.map +1 -0
  17. package/dist/chunk-RIEGCND2.js +525 -0
  18. package/dist/chunk-RIEGCND2.js.map +1 -0
  19. package/dist/index.cjs +80 -69
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +4 -6
  22. package/dist/index.d.ts +4 -6
  23. package/dist/index.js +67 -58
  24. package/dist/index.js.map +1 -1
  25. package/dist/{logger-BnWJh6Yq.d.cts → logger-BWFeedRk.d.cts} +15 -5
  26. package/dist/{logger-BnWJh6Yq.d.ts → logger-BWFeedRk.d.ts} +15 -5
  27. package/dist/logger.cjs +2 -2
  28. package/dist/logger.d.cts +1 -2
  29. package/dist/logger.d.ts +1 -2
  30. package/dist/logger.js +1 -1
  31. package/dist/mocks.cjs +4 -6
  32. package/dist/mocks.cjs.map +1 -1
  33. package/dist/mocks.d.cts +3 -5
  34. package/dist/mocks.d.ts +3 -5
  35. package/dist/mocks.js +3 -5
  36. package/dist/mocks.js.map +1 -1
  37. package/dist/transformers.cjs +189 -33
  38. package/dist/transformers.cjs.map +1 -1
  39. package/dist/transformers.d.cts +1 -3
  40. package/dist/transformers.d.ts +1 -3
  41. package/dist/transformers.js +156 -14
  42. package/dist/transformers.js.map +1 -1
  43. package/dist/utils.cjs +6 -2
  44. package/dist/utils.cjs.map +1 -1
  45. package/dist/utils.d.cts +30 -3
  46. package/dist/utils.d.ts +30 -3
  47. package/dist/utils.js +7 -3
  48. package/package.json +9 -8
  49. package/src/BarrelManager.ts +24 -99
  50. package/src/FileManager.ts +156 -281
  51. package/src/PackageManager.ts +1 -1
  52. package/src/PluginManager.ts +89 -57
  53. package/src/build.ts +6 -19
  54. package/src/logger.ts +6 -8
  55. package/src/transformers/index.ts +2 -3
  56. package/src/transformers/trim.ts +0 -4
  57. package/src/types.ts +1 -1
  58. package/src/utils/TreeNode.ts +91 -26
  59. package/src/utils/executeStrategies.ts +1 -1
  60. package/src/utils/index.ts +2 -1
  61. package/src/utils/parser.ts +96 -0
  62. package/dist/chunk-5JZNFPUP.js.map +0 -1
  63. package/dist/chunk-CEWT73XF.js +0 -637
  64. package/dist/chunk-CEWT73XF.js.map +0 -1
  65. package/dist/chunk-FWU62YO5.cjs.map +0 -1
  66. package/dist/chunk-JKZG2IJR.js +0 -283
  67. package/dist/chunk-JKZG2IJR.js.map +0 -1
  68. package/dist/chunk-PZT4CTBV.cjs +0 -299
  69. package/dist/chunk-PZT4CTBV.cjs.map +0 -1
  70. package/dist/chunk-RBP2ASUX.cjs.map +0 -1
  71. package/dist/chunk-YTSNYMHW.cjs.map +0 -1
  72. package/dist/chunk-Z5CHJQJB.js.map +0 -1
  73. package/src/utils/getParser.ts +0 -17
@@ -1,5 +1,4 @@
1
- import { readSync } from '@kubb/fs'
2
- import { FileManager, type ResolvedFile } from './FileManager.ts'
1
+ import { FileManager } from './FileManager.ts'
3
2
  import { isPromise, isPromiseRejectedResult } from './PromiseManager.ts'
4
3
  import { PromiseManager } from './PromiseManager.ts'
5
4
  import { ValidationPluginError } from './errors.ts'
@@ -81,6 +80,7 @@ export class PluginManager {
81
80
 
82
81
  readonly executed: Array<Executer> = []
83
82
  readonly logger: Logger
83
+ readonly options: Options
84
84
  readonly #core: Plugin<PluginCore>
85
85
 
86
86
  readonly #usedPluginNames: Record<string, number> = {}
@@ -88,6 +88,7 @@ export class PluginManager {
88
88
 
89
89
  constructor(config: Config, options: Options) {
90
90
  this.config = config
91
+ this.options = options
91
92
  this.logger = options.logger
92
93
  this.fileManager = new FileManager()
93
94
  this.#promiseManager = new PromiseManager({
@@ -117,7 +118,6 @@ export class PluginManager {
117
118
  }
118
119
 
119
120
  getFile<TOptions = object>({ name, mode, extName, pluginKey, options }: GetFileProps<TOptions>): KubbFile.File<{ pluginKey: Plugin['key'] }> {
120
- let source = ''
121
121
  const baseName = `${name}${extName}` as const
122
122
  const path = this.resolvePath({ baseName, mode, pluginKey, options })
123
123
 
@@ -125,19 +125,13 @@ export class PluginManager {
125
125
  throw new Error(`Filepath should be defined for resolvedName "${name}" and pluginKey [${JSON.stringify(pluginKey)}]`)
126
126
  }
127
127
 
128
- try {
129
- source = readSync(path)
130
- } catch (_e) {
131
- //
132
- }
133
-
134
128
  return {
135
129
  path,
136
130
  baseName,
137
131
  meta: {
138
132
  pluginKey,
139
133
  },
140
- source,
134
+ sources: [],
141
135
  }
142
136
  }
143
137
 
@@ -150,11 +144,13 @@ export class PluginManager {
150
144
  })
151
145
 
152
146
  if (paths && paths?.length > 1) {
153
- this.logger.emit('debug', [
154
- `Cannot return a path where the 'pluginKey' ${
155
- params.pluginKey ? JSON.stringify(params.pluginKey) : '"'
156
- } is not unique enough\n\nPaths: ${JSON.stringify(paths, undefined, 2)}\n\nFalling back on the first item.\n`,
157
- ])
147
+ this.logger.emit('debug', {
148
+ logs: [
149
+ `Cannot return a path where the 'pluginKey' ${
150
+ params.pluginKey ? JSON.stringify(params.pluginKey) : '"'
151
+ } is not unique enough\n\nPaths: ${JSON.stringify(paths, undefined, 2)}\n\nFalling back on the first item.\n`,
152
+ ],
153
+ })
158
154
  }
159
155
 
160
156
  return paths?.at(0)
@@ -173,11 +169,13 @@ export class PluginManager {
173
169
  })
174
170
 
175
171
  if (names && names?.length > 1) {
176
- this.logger.emit('debug', [
177
- `Cannot return a name where the 'pluginKey' ${
178
- params.pluginKey ? JSON.stringify(params.pluginKey) : '"'
179
- } is not unique enough\n\nNames: ${JSON.stringify(names, undefined, 2)}\n\nFalling back on the first item.\n`,
180
- ])
172
+ this.logger.emit('debug', {
173
+ logs: [
174
+ `Cannot return a name where the 'pluginKey' ${
175
+ params.pluginKey ? JSON.stringify(params.pluginKey) : '"'
176
+ } is not unique enough\n\nNames: ${JSON.stringify(names, undefined, 2)}\n\nFalling back on the first item.\n`,
177
+ ],
178
+ })
181
179
  }
182
180
 
183
181
  return transformReservedWord(names?.at(0) || params.name)
@@ -201,7 +199,7 @@ export class PluginManager {
201
199
  /**
202
200
  * Run a specific hookName for plugin x.
203
201
  */
204
- hookForPlugin<H extends PluginLifecycleHooks>({
202
+ async hookForPlugin<H extends PluginLifecycleHooks>({
205
203
  pluginKey,
206
204
  hookName,
207
205
  parameters,
@@ -209,9 +207,11 @@ export class PluginManager {
209
207
  pluginKey: Plugin['key']
210
208
  hookName: H
211
209
  parameters: PluginParameter<H>
212
- }): Promise<Array<ReturnType<ParseResult<H>> | null>> | null {
210
+ }): Promise<Array<ReturnType<ParseResult<H>> | null>> {
213
211
  const plugins = this.getPluginsByKey(hookName, pluginKey)
214
212
 
213
+ this.logger.emit('progress_start', { id: hookName, size: plugins.length })
214
+
215
215
  const promises = plugins
216
216
  .map((plugin) => {
217
217
  return this.#execute<H>({
@@ -223,7 +223,11 @@ export class PluginManager {
223
223
  })
224
224
  .filter(Boolean)
225
225
 
226
- return Promise.all(promises)
226
+ const items = await Promise.all(promises)
227
+
228
+ this.logger.emit('progress_stop', { id: hookName })
229
+
230
+ return items
227
231
  }
228
232
  /**
229
233
  * Run a specific hookName for plugin x.
@@ -240,7 +244,7 @@ export class PluginManager {
240
244
  }): Array<ReturnType<ParseResult<H>>> | null {
241
245
  const plugins = this.getPluginsByKey(hookName, pluginKey)
242
246
 
243
- return plugins
247
+ const result = plugins
244
248
  .map((plugin) => {
245
249
  return this.#executeSync<H>({
246
250
  strategy: 'hookFirst',
@@ -250,6 +254,8 @@ export class PluginManager {
250
254
  })
251
255
  })
252
256
  .filter(Boolean)
257
+
258
+ return result
253
259
  }
254
260
 
255
261
  /**
@@ -264,27 +270,33 @@ export class PluginManager {
264
270
  parameters: PluginParameter<H>
265
271
  skipped?: ReadonlySet<Plugin> | null
266
272
  }): Promise<SafeParseResult<H>> {
267
- const promises = this.#getSortedPlugins()
268
- .filter((plugin) => {
269
- return skipped ? skipped.has(plugin) : true
270
- })
271
- .map((plugin) => {
272
- return async () => {
273
- const value = await this.#execute<H>({
274
- strategy: 'hookFirst',
275
- hookName,
276
- parameters,
277
- plugin,
278
- })
273
+ const plugins = this.#getSortedPlugins(hookName).filter((plugin) => {
274
+ return skipped ? skipped.has(plugin) : true
275
+ })
279
276
 
280
- return Promise.resolve({
281
- plugin,
282
- result: value,
283
- } as SafeParseResult<H>)
284
- }
285
- })
277
+ this.logger.emit('progress_start', { id: hookName, size: plugins.length })
286
278
 
287
- return this.#promiseManager.run('first', promises)
279
+ const promises = plugins.map((plugin) => {
280
+ return async () => {
281
+ const value = await this.#execute<H>({
282
+ strategy: 'hookFirst',
283
+ hookName,
284
+ parameters,
285
+ plugin,
286
+ })
287
+
288
+ return Promise.resolve({
289
+ plugin,
290
+ result: value,
291
+ } as SafeParseResult<H>)
292
+ }
293
+ })
294
+
295
+ const result = await this.#promiseManager.run('first', promises)
296
+
297
+ this.logger.emit('progress_stop', { id: hookName })
298
+
299
+ return result
288
300
  }
289
301
 
290
302
  /**
@@ -300,12 +312,11 @@ export class PluginManager {
300
312
  skipped?: ReadonlySet<Plugin> | null
301
313
  }): SafeParseResult<H> {
302
314
  let parseResult: SafeParseResult<H> = null as unknown as SafeParseResult<H>
315
+ const plugins = this.#getSortedPlugins(hookName).filter((plugin) => {
316
+ return skipped ? skipped.has(plugin) : true
317
+ })
303
318
 
304
- for (const plugin of this.#getSortedPlugins()) {
305
- if (skipped?.has(plugin)) {
306
- continue
307
- }
308
-
319
+ for (const plugin of plugins) {
309
320
  parseResult = {
310
321
  result: this.#executeSync<H>({
311
322
  strategy: 'hookFirst',
@@ -320,6 +331,7 @@ export class PluginManager {
320
331
  break
321
332
  }
322
333
  }
334
+
323
335
  return parseResult
324
336
  }
325
337
 
@@ -333,7 +345,10 @@ export class PluginManager {
333
345
  hookName: H
334
346
  parameters?: Parameters<RequiredPluginLifecycle[H]> | undefined
335
347
  }): Promise<Awaited<TOuput>[]> {
336
- const promises = this.#getSortedPlugins().map((plugin) => {
348
+ const plugins = this.#getSortedPlugins(hookName)
349
+ this.logger.emit('progress_start', { id: hookName, size: plugins.length })
350
+
351
+ const promises = plugins.map((plugin) => {
337
352
  return () =>
338
353
  this.#execute({
339
354
  strategy: 'hookParallel',
@@ -347,12 +362,14 @@ export class PluginManager {
347
362
 
348
363
  results.forEach((result, index) => {
349
364
  if (isPromiseRejectedResult<Error>(result)) {
350
- const plugin = this.#getSortedPlugins()[index]
365
+ const plugin = this.#getSortedPlugins(hookName)[index]
351
366
 
352
367
  this.#catcher<H>(result.reason, plugin, hookName)
353
368
  }
354
369
  })
355
370
 
371
+ this.logger.emit('progress_stop', { id: hookName })
372
+
356
373
  return results.filter((result) => result.status === 'fulfilled').map((result) => (result as PromiseFulfilledResult<Awaited<TOuput>>).value)
357
374
  }
358
375
 
@@ -369,9 +386,10 @@ export class PluginManager {
369
386
  reduce: (reduction: Argument0<H>, result: ReturnType<ParseResult<H>>, plugin: Plugin) => PossiblePromise<Argument0<H> | null>
370
387
  }): Promise<Argument0<H>> {
371
388
  const [argument0, ...rest] = parameters
389
+ const plugins = this.#getSortedPlugins(hookName)
372
390
 
373
391
  let promise: Promise<Argument0<H>> = Promise.resolve(argument0)
374
- for (const plugin of this.#getSortedPlugins()) {
392
+ for (const plugin of plugins) {
375
393
  promise = promise
376
394
  .then((arg0) => {
377
395
  const value = this.#execute({
@@ -392,7 +410,10 @@ export class PluginManager {
392
410
  * Chains plugins
393
411
  */
394
412
  async hookSeq<H extends PluginLifecycleHooks>({ hookName, parameters }: { hookName: H; parameters?: PluginParameter<H> }): Promise<void> {
395
- const promises = this.#getSortedPlugins().map((plugin) => {
413
+ const plugins = this.#getSortedPlugins(hookName)
414
+ this.logger.emit('progress_start', { id: hookName, size: plugins.length })
415
+
416
+ const promises = plugins.map((plugin) => {
396
417
  return () =>
397
418
  this.#execute({
398
419
  strategy: 'hookSeq',
@@ -402,7 +423,9 @@ export class PluginManager {
402
423
  })
403
424
  })
404
425
 
405
- return this.#promiseManager.run('seq', promises)
426
+ await this.#promiseManager.run('seq', promises)
427
+
428
+ this.logger.emit('progress_stop', { id: hookName })
406
429
  }
407
430
 
408
431
  #getSortedPlugins(hookName?: keyof PluginLifecycle): Plugin[] {
@@ -411,7 +434,7 @@ export class PluginManager {
411
434
  if (hookName) {
412
435
  const containsHookName = plugins.some((item) => item[hookName])
413
436
  if (!containsHookName) {
414
- this.logger.emit('info', `No hook ${hookName} found`)
437
+ this.logger.emit('debug', { logs: [`No hook ${hookName} found`] })
415
438
  }
416
439
 
417
440
  return plugins.filter((item) => item[hookName])
@@ -466,9 +489,13 @@ export class PluginManager {
466
489
  const corePlugin = plugins.find((plugin) => plugin.name === 'core' && plugin[hookName])
467
490
 
468
491
  if (corePlugin) {
469
- this.logger.emit('warning', `No hook '${hookName}' for pluginKey '${JSON.stringify(pluginKey)}' found, falling back on the '@kubb/core' plugin`)
492
+ this.logger.emit('debug', {
493
+ logs: [`No hook '${hookName}' for pluginKey '${JSON.stringify(pluginKey)}' found, falling back on the '@kubb/core' plugin`],
494
+ })
470
495
  } else {
471
- this.logger.emit('warning', `No hook '${hookName}' for pluginKey '${JSON.stringify(pluginKey)}' found, no fallback found in the '@kubb/core' plugin`)
496
+ this.logger.emit('debug', {
497
+ logs: [`No hook '${hookName}' for pluginKey '${JSON.stringify(pluginKey)}' found, no fallback found in the '@kubb/core' plugin`],
498
+ })
472
499
  }
473
500
  return corePlugin ? [corePlugin] : []
474
501
  }
@@ -480,6 +507,8 @@ export class PluginManager {
480
507
  if (executer) {
481
508
  this.events.emit('executed', executer)
482
509
  this.executed.push(executer)
510
+
511
+ this.logger.emit('progress', { id: executer.hookName, data: `${executer.plugin.name}` })
483
512
  }
484
513
  }
485
514
 
@@ -509,8 +538,11 @@ export class PluginManager {
509
538
  }
510
539
 
511
540
  this.events.emit('execute', { strategy, hookName, parameters, plugin })
541
+ const promise = new Promise((resolve) => {
542
+ resolve(undefined)
543
+ })
512
544
 
513
- const task = Promise.resolve()
545
+ const task = promise
514
546
  .then(() => {
515
547
  if (typeof hook === 'function') {
516
548
  const possiblePromiseResult = (hook as Function).apply({ ...this.#core.context, plugin }, parameters) as Promise<ReturnType<ParseResult<H>>>
package/src/build.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import c from 'tinyrainbow'
2
2
 
3
- import { clean, read, write } from '@kubb/fs'
3
+ import { clean, read } from '@kubb/fs'
4
4
  import { type FileManager, processFiles } from './FileManager.ts'
5
5
  import { PluginManager } from './PluginManager.ts'
6
6
  import { isInputPath } from './config.ts'
7
- import { createLogger, randomCliColour } from './logger.ts'
7
+ import { createLogger } from './logger.ts'
8
8
  import { URLPath } from './utils/URLPath.ts'
9
9
 
10
10
  import type { Logger } from './logger.ts'
@@ -49,23 +49,7 @@ async function setup(options: BuildOptions): Promise<PluginManager> {
49
49
  await clean(config.output.path)
50
50
  }
51
51
 
52
- const pluginManager = new PluginManager(config, { logger })
53
-
54
- pluginManager.on('executed', (executer) => {
55
- const { hookName, plugin, output, parameters } = executer
56
-
57
- const logs = [
58
- `${randomCliColour(plugin.name)} Executing ${hookName}`,
59
- parameters && `${c.bgWhite('Parameters')} ${randomCliColour(plugin.name)} ${hookName}`,
60
- JSON.stringify(parameters, undefined, 2),
61
- output && `${c.bgWhite('Output')} ${randomCliColour(plugin.name)} ${hookName}`,
62
- output,
63
- ].filter(Boolean)
64
-
65
- logger.emit('debug', logs as string[])
66
- })
67
-
68
- return pluginManager
52
+ return new PluginManager(config, { logger })
69
53
  }
70
54
 
71
55
  export async function build(options: BuildOptions): Promise<BuildOutput> {
@@ -77,6 +61,7 @@ export async function build(options: BuildOptions): Promise<BuildOutput> {
77
61
  })
78
62
 
79
63
  const files = await processFiles({
64
+ config: options.config,
80
65
  dryRun: !options.config.output.write,
81
66
  files: pluginManager.fileManager.files,
82
67
  logger: pluginManager.logger,
@@ -100,7 +85,9 @@ export async function safeBuild(options: BuildOptions): Promise<BuildOutput> {
100
85
  parameters: [options.config],
101
86
  })
102
87
 
88
+ //TODO set extName here instead of the files, extName is private. All exports will have extName, it's up the the process to hide.override the name
103
89
  files = await processFiles({
90
+ config: options.config,
104
91
  dryRun: !options.config.output.write,
105
92
  files: pluginManager.fileManager.files,
106
93
  logger: pluginManager.logger,
package/src/logger.ts CHANGED
@@ -3,18 +3,20 @@ import c, { createColors } from 'tinyrainbow'
3
3
 
4
4
  import { EventEmitter } from './utils/EventEmitter.ts'
5
5
 
6
- import { type ConsolaInstance, createConsola, type LogLevel } from 'consola'
7
- import type { Formatter } from 'tinyrainbow'
8
6
  import type * as KubbFile from '@kubb/fs/src/types.ts'
7
+ import { type ConsolaInstance, type LogLevel, createConsola } from 'consola'
8
+ import type { Formatter } from 'tinyrainbow'
9
9
 
10
10
  type Events = {
11
11
  start: [message: string]
12
12
  success: [message: string]
13
13
  error: [message: string, cause: Error]
14
14
  warning: [message: string]
15
- debug: [logs: string[]]
15
+ debug: [{ logs: string[]; override?: boolean; fileName?: string }]
16
16
  info: [message: string]
17
- progress: [{ count: number; size: number; file: KubbFile.File }]
17
+ progress_start: [{ id: string; size: number }]
18
+ progress: [{ id: string; count?: number; data?: string }]
19
+ progress_stop: [{ id: string }]
18
20
  }
19
21
 
20
22
  export const LogMapper = {
@@ -73,10 +75,6 @@ export function createLogger({ logLevel = 3, name, consola: _consola }: Props =
73
75
  consola.info(c.yellow(message))
74
76
  })
75
77
 
76
- events.on('debug', (message) => {
77
- consola.debug(c.yellow(message))
78
- })
79
-
80
78
  events.on('error', (message, cause) => {
81
79
  const error = new Error(message || 'Something went wrong')
82
80
  error.cause = cause
@@ -11,7 +11,7 @@ import { searchAndReplace } from './searchAndReplace.ts'
11
11
  import { stringify, stringifyObject } from './stringify.ts'
12
12
  import { toRegExp, toRegExpString } from './toRegExp.ts'
13
13
  import { transformReservedWord } from './transformReservedWord.ts'
14
- import { trim, trimExtName, trimQuotes } from './trim.ts'
14
+ import { trim, trimQuotes } from './trim.ts'
15
15
 
16
16
  export { camelCase, pascalCase, pathCase } from './casing.ts'
17
17
  export { combineCodes } from './combineCodes.ts'
@@ -23,7 +23,7 @@ export { searchAndReplace } from './searchAndReplace.ts'
23
23
  export { stringify, stringifyObject } from './stringify.ts'
24
24
  export { toRegExp, toRegExpString } from './toRegExp.ts'
25
25
  export { transformReservedWord } from './transformReservedWord.ts'
26
- export { trim, trimExtName, trimQuotes } from './trim.ts'
26
+ export { trim, trimQuotes } from './trim.ts'
27
27
  export { merge } from 'remeda'
28
28
  export { orderBy } from 'natural-orderby'
29
29
 
@@ -41,7 +41,6 @@ export default {
41
41
  toRegExpString,
42
42
  trim,
43
43
  trimQuotes,
44
- trimExtName,
45
44
  JSDoc: {
46
45
  createJSDocBlockText,
47
46
  },
@@ -16,7 +16,3 @@ export function trimQuotes(text: string): string {
16
16
 
17
17
  return text
18
18
  }
19
-
20
- export function trimExtName(text: string): string {
21
- return text.replace(/\.[^/.]+$/, '')
22
- }
package/src/types.ts CHANGED
@@ -261,7 +261,7 @@ export type PluginContext<TOptions extends PluginFactoryOptions = PluginFactoryO
261
261
  cache: Cache<PluginCache>
262
262
  fileManager: FileManager
263
263
  pluginManager: PluginManager
264
- addFile: (...file: Array<KubbFile.File>) => Promise<Array<KubbFile.File>>
264
+ addFile: (...file: Array<KubbFile.File>) => Promise<Array<KubbFile.ResolvedFile>>
265
265
  resolvePath: (params: ResolvePathParams<TOptions['resolvePathOptions']>) => KubbFile.OptionalPath
266
266
  resolveName: (params: ResolveNameParams) => string
267
267
  logger: Logger
@@ -1,28 +1,30 @@
1
- import dirTree from 'directory-tree'
2
-
3
- import { FileManager } from '../FileManager.ts'
4
-
5
1
  import type * as KubbFile from '@kubb/fs/types'
6
- import type { DirectoryTree, DirectoryTreeOptions } from 'directory-tree'
7
-
8
- export type TreeNodeOptions = DirectoryTreeOptions
2
+ import { FileManager } from '../FileManager.ts'
9
3
 
10
- type BarrelData = { type: KubbFile.Mode; path: KubbFile.Path; name: string }
4
+ type BarrelData = {
5
+ file?: KubbFile.File
6
+ /**
7
+ * @deprecated use file instead
8
+ */
9
+ type: KubbFile.Mode
10
+ path: string
11
+ name: string
12
+ }
11
13
 
12
- export class TreeNode<T = BarrelData> {
13
- public data: T
14
+ export class TreeNode {
15
+ public data: BarrelData
14
16
 
15
- public parent?: TreeNode<T>
17
+ public parent?: TreeNode
16
18
 
17
- public children: Array<TreeNode<T>> = []
19
+ public children: Array<TreeNode> = []
18
20
 
19
- constructor(data: T, parent?: TreeNode<T>) {
21
+ constructor(data: BarrelData, parent?: TreeNode) {
20
22
  this.data = data
21
23
  this.parent = parent
22
24
  return this
23
25
  }
24
26
 
25
- addChild(data: T): TreeNode<T> {
27
+ addChild(data: BarrelData): TreeNode {
26
28
  const child = new TreeNode(data, this)
27
29
  if (!this.children) {
28
30
  this.children = []
@@ -31,7 +33,7 @@ export class TreeNode<T = BarrelData> {
31
33
  return child
32
34
  }
33
35
 
34
- find(data?: T): TreeNode<T> | null {
36
+ find(data?: BarrelData): TreeNode | null {
35
37
  if (!data) {
36
38
  return null
37
39
  }
@@ -41,7 +43,7 @@ export class TreeNode<T = BarrelData> {
41
43
  }
42
44
 
43
45
  if (this.children?.length) {
44
- for (let i = 0, { length } = this.children, target: TreeNode<T> | null = null; i < length; i++) {
46
+ for (let i = 0, { length } = this.children, target: TreeNode | null = null; i < length; i++) {
45
47
  target = this.children[i]!.find(data)
46
48
  if (target) {
47
49
  return target
@@ -52,14 +54,14 @@ export class TreeNode<T = BarrelData> {
52
54
  return null
53
55
  }
54
56
 
55
- get leaves(): TreeNode<T>[] {
57
+ get leaves(): Array<TreeNode> {
56
58
  if (!this.children || this.children.length === 0) {
57
59
  // this is a leaf
58
60
  return [this]
59
61
  }
60
62
 
61
63
  // if not a leaf, return all children's leaves recursively
62
- const leaves: TreeNode<T>[] = []
64
+ const leaves: TreeNode[] = []
63
65
  if (this.children) {
64
66
  for (let i = 0, { length } = this.children; i < length; i++) {
65
67
  leaves.push.apply(leaves, this.children[i]!.leaves)
@@ -68,14 +70,14 @@ export class TreeNode<T = BarrelData> {
68
70
  return leaves
69
71
  }
70
72
 
71
- get root(): TreeNode<T> {
73
+ get root(): TreeNode {
72
74
  if (!this.parent) {
73
75
  return this
74
76
  }
75
77
  return this.parent.root
76
78
  }
77
79
 
78
- forEach(callback: (treeNode: TreeNode<T>) => void): this {
80
+ forEach(callback: (treeNode: TreeNode) => void): this {
79
81
  if (typeof callback !== 'function') {
80
82
  throw new TypeError('forEach() callback must be a function')
81
83
  }
@@ -93,13 +95,9 @@ export class TreeNode<T = BarrelData> {
93
95
  return this
94
96
  }
95
97
 
96
- public static build(path: string, options: TreeNodeOptions = {}): TreeNode | null {
98
+ public static build(files: KubbFile.File[], root?: string): TreeNode | null {
97
99
  try {
98
- const exclude = Array.isArray(options.exclude) ? options.exclude : [options.exclude].filter(Boolean)
99
- const filteredTree = dirTree(path, {
100
- extensions: options.extensions,
101
- exclude: [/node_modules/, ...exclude],
102
- })
100
+ const filteredTree = buildDirectoryTree(files, root)
103
101
 
104
102
  if (!filteredTree) {
105
103
  return null
@@ -108,6 +106,7 @@ export class TreeNode<T = BarrelData> {
108
106
  const treeNode = new TreeNode({
109
107
  name: filteredTree.name,
110
108
  path: filteredTree.path,
109
+ file: filteredTree.file,
111
110
  type: FileManager.getMode(filteredTree.path),
112
111
  })
113
112
 
@@ -115,6 +114,7 @@ export class TreeNode<T = BarrelData> {
115
114
  const subNode = node.addChild({
116
115
  name: item.name,
117
116
  path: item.path,
117
+ file: item.file,
118
118
  type: FileManager.getMode(item.path),
119
119
  })
120
120
 
@@ -133,3 +133,68 @@ export class TreeNode<T = BarrelData> {
133
133
  }
134
134
  }
135
135
  }
136
+
137
+ export type DirectoryTree = {
138
+ name: string
139
+ path: string
140
+ file?: KubbFile.File
141
+ children: Array<DirectoryTree>
142
+ }
143
+
144
+ export function buildDirectoryTree(files: Array<KubbFile.File>, rootFolder = ''): DirectoryTree | null {
145
+ const rootPrefix = rootFolder.endsWith('/') ? rootFolder : `${rootFolder}/`
146
+ const filteredFiles = files.filter((file) => (rootFolder ? file.path.startsWith(rootPrefix) && !file.path.endsWith('.json') : !file.path.endsWith('.json')))
147
+
148
+ if (filteredFiles.length === 0) {
149
+ return null // No files match the root folder
150
+ }
151
+
152
+ const root: DirectoryTree = {
153
+ name: rootFolder || '',
154
+ path: rootFolder || '',
155
+ children: [],
156
+ }
157
+
158
+ filteredFiles.forEach((file) => {
159
+ const path = file.path.slice(rootFolder.length)
160
+ const parts = path.split('/')
161
+ let currentLevel: DirectoryTree[] = root.children
162
+ let currentPath = rootFolder
163
+
164
+ parts.forEach((part, index) => {
165
+ if (index !== 0) {
166
+ currentPath += `/${part}`
167
+ } else {
168
+ currentPath += `${part}`
169
+ }
170
+
171
+ let existingNode = currentLevel.find((node) => node.name === part)
172
+
173
+ if (!existingNode) {
174
+ if (index === parts.length - 1) {
175
+ // If it's the last part, it's a file
176
+ existingNode = {
177
+ name: part,
178
+ file,
179
+ path: currentPath,
180
+ } as DirectoryTree
181
+ } else {
182
+ // Otherwise, it's a folder
183
+ existingNode = {
184
+ name: part,
185
+ path: currentPath,
186
+ children: [],
187
+ } as DirectoryTree
188
+ }
189
+ currentLevel.push(existingNode)
190
+ }
191
+
192
+ // Move to the next level if it's a folder
193
+ if (!existingNode.file) {
194
+ currentLevel = existingNode.children
195
+ }
196
+ })
197
+ })
198
+
199
+ return root
200
+ }
@@ -4,7 +4,7 @@ export type ValueOfPromiseFuncArray<TInput extends Array<unknown>> = TInput exte
4
4
 
5
5
  export function noReturn(): void {}
6
6
 
7
- type SeqOutput<TInput extends Array<PromiseFunc<TValue, null>>, TValue> = Array<Awaited<ValueOfPromiseFuncArray<TInput>>>
7
+ type SeqOutput<TInput extends Array<PromiseFunc<TValue, null>>, TValue> = Promise<Array<Awaited<ValueOfPromiseFuncArray<TInput>>>>
8
8
 
9
9
  /**
10
10
  * Chains promises
@@ -10,4 +10,5 @@ export { timeout } from './timeout.ts'
10
10
  export { getUniqueName, setUniqueName } from './uniqueName.ts'
11
11
  export type { URLObject } from './URLPath.ts'
12
12
  export { URLPath } from './URLPath.ts'
13
- export { getParser } from './getParser.ts'
13
+ export { getFileParser, createFile, createFileParser } from './parser.ts'
14
+ export type { ParserModule } from './parser.ts'