@kubb/core 3.15.0 → 3.16.0

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 (66) hide show
  1. package/dist/{FileManager-HxsypMy8.d.cts → PluginManager-E3SghPP9.d.cts} +125 -161
  2. package/dist/{FileManager-Cm7Iylcx.d.ts → PluginManager-PDmRCu9k.d.ts} +125 -161
  3. package/dist/{chunk-7P6FFVGF.js → chunk-4V7HK7PT.js} +3 -3
  4. package/dist/{chunk-7P6FFVGF.js.map → chunk-4V7HK7PT.js.map} +1 -1
  5. package/dist/{chunk-TEEWO6UV.cjs → chunk-BHSTNFNQ.cjs} +2 -23
  6. package/dist/chunk-BHSTNFNQ.cjs.map +1 -0
  7. package/dist/{chunk-XTSQKCYI.js → chunk-CAZ37TGB.js} +93 -114
  8. package/dist/chunk-CAZ37TGB.js.map +1 -0
  9. package/dist/{chunk-MKN7YSK2.cjs → chunk-E4XLCCPK.cjs} +2 -20
  10. package/dist/chunk-E4XLCCPK.cjs.map +1 -0
  11. package/dist/{chunk-TJJOSCFA.cjs → chunk-MCNA6SYG.cjs} +5 -24
  12. package/dist/chunk-MCNA6SYG.cjs.map +1 -0
  13. package/dist/chunk-QR7CQIA3.cjs +943 -0
  14. package/dist/chunk-QR7CQIA3.cjs.map +1 -0
  15. package/dist/{chunk-CMKZBNCX.js → chunk-YRPOID7E.js} +2 -2
  16. package/dist/{chunk-CMKZBNCX.js.map → chunk-YRPOID7E.js.map} +1 -1
  17. package/dist/fs.cjs +9 -10
  18. package/dist/fs.d.cts +10 -2
  19. package/dist/fs.d.ts +10 -2
  20. package/dist/fs.js +1 -1
  21. package/dist/index.cjs +109 -260
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +9 -7
  24. package/dist/index.d.ts +9 -7
  25. package/dist/index.js +88 -83
  26. package/dist/index.js.map +1 -1
  27. package/dist/logger.cjs +6 -7
  28. package/dist/logger.js +2 -2
  29. package/dist/mocks.cjs +8 -11
  30. package/dist/mocks.cjs.map +1 -1
  31. package/dist/mocks.d.cts +2 -2
  32. package/dist/mocks.d.ts +2 -2
  33. package/dist/mocks.js +2 -2
  34. package/dist/{parser-CcELSk43.d.ts → parser-C1vOjVEd.d.ts} +2 -2
  35. package/dist/{parser-Dwb7eMU3.d.cts → parser-D6vU1kA9.d.cts} +2 -2
  36. package/dist/{prompt-55FJQYBV.cjs → prompt-U7M5G25C.cjs} +2 -4
  37. package/dist/prompt-U7M5G25C.cjs.map +1 -0
  38. package/dist/transformers.cjs +21 -22
  39. package/dist/{types-CX9JVw2n.d.cts → types-CA8nQKwM.d.cts} +1 -15
  40. package/dist/{types-CX9JVw2n.d.ts → types-CA8nQKwM.d.ts} +1 -15
  41. package/dist/utils.cjs +22 -19
  42. package/dist/utils.d.cts +15 -4
  43. package/dist/utils.d.ts +15 -4
  44. package/dist/utils.js +2 -2
  45. package/package.json +6 -6
  46. package/src/BarrelManager.ts +1 -20
  47. package/src/FileManager.ts +78 -121
  48. package/src/PluginManager.ts +40 -33
  49. package/src/PromiseManager.ts +2 -1
  50. package/src/__snapshots__/barrel.json +80 -6
  51. package/src/build.ts +57 -55
  52. package/src/fs/types.ts +0 -6
  53. package/src/index.ts +1 -1
  54. package/src/utils/Cache.ts +31 -0
  55. package/src/utils/executeStrategies.ts +9 -2
  56. package/src/utils/index.ts +1 -0
  57. package/src/utils/parser.ts +6 -7
  58. package/dist/chunk-FAQ7SBKL.cjs +0 -1636
  59. package/dist/chunk-FAQ7SBKL.cjs.map +0 -1
  60. package/dist/chunk-KZOJCFA7.cjs +0 -42
  61. package/dist/chunk-KZOJCFA7.cjs.map +0 -1
  62. package/dist/chunk-MKN7YSK2.cjs.map +0 -1
  63. package/dist/chunk-TEEWO6UV.cjs.map +0 -1
  64. package/dist/chunk-TJJOSCFA.cjs.map +0 -1
  65. package/dist/chunk-XTSQKCYI.js.map +0 -1
  66. package/dist/prompt-55FJQYBV.cjs.map +0 -1
package/dist/utils.cjs CHANGED
@@ -1,71 +1,74 @@
1
1
  'use strict';
2
2
 
3
- var chunkFAQ7SBKL_cjs = require('./chunk-FAQ7SBKL.cjs');
4
- require('./chunk-TEEWO6UV.cjs');
5
- require('./chunk-MKN7YSK2.cjs');
6
- require('./chunk-KZOJCFA7.cjs');
3
+ var chunkQR7CQIA3_cjs = require('./chunk-QR7CQIA3.cjs');
4
+ require('./chunk-BHSTNFNQ.cjs');
5
+ require('./chunk-E4XLCCPK.cjs');
7
6
 
8
7
 
9
8
 
9
+ Object.defineProperty(exports, "Cache", {
10
+ enumerable: true,
11
+ get: function () { return chunkQR7CQIA3_cjs.Cache; }
12
+ });
10
13
  Object.defineProperty(exports, "FunctionParams", {
11
14
  enumerable: true,
12
- get: function () { return chunkFAQ7SBKL_cjs.FunctionParams; }
15
+ get: function () { return chunkQR7CQIA3_cjs.FunctionParams; }
13
16
  });
14
17
  Object.defineProperty(exports, "URLPath", {
15
18
  enumerable: true,
16
- get: function () { return chunkFAQ7SBKL_cjs.URLPath; }
19
+ get: function () { return chunkQR7CQIA3_cjs.URLPath; }
17
20
  });
18
21
  Object.defineProperty(exports, "createFile", {
19
22
  enumerable: true,
20
- get: function () { return chunkFAQ7SBKL_cjs.createFile; }
23
+ get: function () { return chunkQR7CQIA3_cjs.createFile; }
21
24
  });
22
25
  Object.defineProperty(exports, "createFileExport", {
23
26
  enumerable: true,
24
- get: function () { return chunkFAQ7SBKL_cjs.createFileExport; }
27
+ get: function () { return chunkQR7CQIA3_cjs.createFileExport; }
25
28
  });
26
29
  Object.defineProperty(exports, "createFileImport", {
27
30
  enumerable: true,
28
- get: function () { return chunkFAQ7SBKL_cjs.createFileImport; }
31
+ get: function () { return chunkQR7CQIA3_cjs.createFileImport; }
29
32
  });
30
33
  Object.defineProperty(exports, "createFileParser", {
31
34
  enumerable: true,
32
- get: function () { return chunkFAQ7SBKL_cjs.createFileParser; }
35
+ get: function () { return chunkQR7CQIA3_cjs.createFileParser; }
33
36
  });
34
37
  Object.defineProperty(exports, "getDefaultBanner", {
35
38
  enumerable: true,
36
- get: function () { return chunkFAQ7SBKL_cjs.getDefaultBanner; }
39
+ get: function () { return chunkQR7CQIA3_cjs.getDefaultBanner; }
37
40
  });
38
41
  Object.defineProperty(exports, "getFileParser", {
39
42
  enumerable: true,
40
- get: function () { return chunkFAQ7SBKL_cjs.getFileParser; }
43
+ get: function () { return chunkQR7CQIA3_cjs.getFileParser; }
41
44
  });
42
45
  Object.defineProperty(exports, "getUniqueName", {
43
46
  enumerable: true,
44
- get: function () { return chunkFAQ7SBKL_cjs.getUniqueName; }
47
+ get: function () { return chunkQR7CQIA3_cjs.getUniqueName; }
45
48
  });
46
49
  Object.defineProperty(exports, "isPromise", {
47
50
  enumerable: true,
48
- get: function () { return chunkFAQ7SBKL_cjs.isPromise; }
51
+ get: function () { return chunkQR7CQIA3_cjs.isPromise; }
49
52
  });
50
53
  Object.defineProperty(exports, "isPromiseFulfilledResult", {
51
54
  enumerable: true,
52
- get: function () { return chunkFAQ7SBKL_cjs.isPromiseFulfilledResult; }
55
+ get: function () { return chunkQR7CQIA3_cjs.isPromiseFulfilledResult; }
53
56
  });
54
57
  Object.defineProperty(exports, "isPromiseRejectedResult", {
55
58
  enumerable: true,
56
- get: function () { return chunkFAQ7SBKL_cjs.isPromiseRejectedResult; }
59
+ get: function () { return chunkQR7CQIA3_cjs.isPromiseRejectedResult; }
57
60
  });
58
61
  Object.defineProperty(exports, "renderTemplate", {
59
62
  enumerable: true,
60
- get: function () { return chunkFAQ7SBKL_cjs.renderTemplate; }
63
+ get: function () { return chunkQR7CQIA3_cjs.renderTemplate; }
61
64
  });
62
65
  Object.defineProperty(exports, "setUniqueName", {
63
66
  enumerable: true,
64
- get: function () { return chunkFAQ7SBKL_cjs.setUniqueName; }
67
+ get: function () { return chunkQR7CQIA3_cjs.setUniqueName; }
65
68
  });
66
69
  Object.defineProperty(exports, "timeout", {
67
70
  enumerable: true,
68
- get: function () { return chunkFAQ7SBKL_cjs.timeout; }
71
+ get: function () { return chunkQR7CQIA3_cjs.timeout; }
69
72
  });
70
73
  //# sourceMappingURL=utils.cjs.map
71
74
  //# sourceMappingURL=utils.cjs.map
package/dist/utils.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { a as PossiblePromise } from './FileManager-HxsypMy8.cjs';
2
- export { P as ParserModule, d as createFile, b as createFileExport, c as createFileImport, e as createFileParser, g as getDefaultBanner, a as getFileParser } from './parser-Dwb7eMU3.cjs';
3
- import './types-CX9JVw2n.cjs';
1
+ import { a as PossiblePromise } from './PluginManager-E3SghPP9.cjs';
2
+ export { P as ParserModule, d as createFile, b as createFileExport, c as createFileImport, e as createFileParser, g as getDefaultBanner, a as getFileParser } from './parser-D6vU1kA9.cjs';
3
+ import './types-CA8nQKwM.cjs';
4
4
  import './logger-BWq-oJU_.cjs';
5
5
  import 'consola/utils';
6
6
  import 'consola';
@@ -112,4 +112,15 @@ declare class URLPath {
112
112
  toURLPath(): string;
113
113
  }
114
114
 
115
- export { FunctionParams, type FunctionParamsAST, type URLObject, URLPath, getUniqueName, isPromise, isPromiseFulfilledResult, isPromiseRejectedResult, renderTemplate, setUniqueName, timeout };
115
+ declare class Cache<T> {
116
+ #private;
117
+ get(key: string): Promise<T | null>;
118
+ set(key: string, value: T): Promise<void>;
119
+ delete(key: string): Promise<void>;
120
+ clear(): Promise<void>;
121
+ keys(): Promise<string[]>;
122
+ values(): Promise<T[]>;
123
+ flush(): Promise<void>;
124
+ }
125
+
126
+ export { Cache, FunctionParams, type FunctionParamsAST, type URLObject, URLPath, getUniqueName, isPromise, isPromiseFulfilledResult, isPromiseRejectedResult, renderTemplate, setUniqueName, timeout };
package/dist/utils.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { a as PossiblePromise } from './FileManager-Cm7Iylcx.js';
2
- export { P as ParserModule, d as createFile, b as createFileExport, c as createFileImport, e as createFileParser, g as getDefaultBanner, a as getFileParser } from './parser-CcELSk43.js';
3
- import './types-CX9JVw2n.js';
1
+ import { a as PossiblePromise } from './PluginManager-PDmRCu9k.js';
2
+ export { P as ParserModule, d as createFile, b as createFileExport, c as createFileImport, e as createFileParser, g as getDefaultBanner, a as getFileParser } from './parser-C1vOjVEd.js';
3
+ import './types-CA8nQKwM.js';
4
4
  import './logger-BWq-oJU_.js';
5
5
  import 'consola/utils';
6
6
  import 'consola';
@@ -112,4 +112,15 @@ declare class URLPath {
112
112
  toURLPath(): string;
113
113
  }
114
114
 
115
- export { FunctionParams, type FunctionParamsAST, type URLObject, URLPath, getUniqueName, isPromise, isPromiseFulfilledResult, isPromiseRejectedResult, renderTemplate, setUniqueName, timeout };
115
+ declare class Cache<T> {
116
+ #private;
117
+ get(key: string): Promise<T | null>;
118
+ set(key: string, value: T): Promise<void>;
119
+ delete(key: string): Promise<void>;
120
+ clear(): Promise<void>;
121
+ keys(): Promise<string[]>;
122
+ values(): Promise<T[]>;
123
+ flush(): Promise<void>;
124
+ }
125
+
126
+ export { Cache, FunctionParams, type FunctionParamsAST, type URLObject, URLPath, getUniqueName, isPromise, isPromiseFulfilledResult, isPromiseRejectedResult, renderTemplate, setUniqueName, timeout };
package/dist/utils.js CHANGED
@@ -1,5 +1,5 @@
1
- export { FunctionParams, URLPath, createFile, createFileExport, createFileImport, createFileParser, getDefaultBanner, getFileParser, getUniqueName, isPromise, isPromiseFulfilledResult, isPromiseRejectedResult, renderTemplate, setUniqueName, timeout } from './chunk-XTSQKCYI.js';
1
+ export { Cache, FunctionParams, URLPath, createFile, createFileExport, createFileImport, createFileParser, getDefaultBanner, getFileParser, getUniqueName, isPromise, isPromiseFulfilledResult, isPromiseRejectedResult, renderTemplate, setUniqueName, timeout } from './chunk-CAZ37TGB.js';
2
2
  import './chunk-GBYHPDPK.js';
3
- import './chunk-CMKZBNCX.js';
3
+ import './chunk-YRPOID7E.js';
4
4
  //# sourceMappingURL=utils.js.map
5
5
  //# sourceMappingURL=utils.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/core",
3
- "version": "3.15.0",
3
+ "version": "3.16.0",
4
4
  "description": "Core functionality for Kubb's plugin-based code generation system, providing the foundation for transforming OpenAPI specifications.",
5
5
  "keywords": [
6
6
  "typescript",
@@ -93,11 +93,11 @@
93
93
  "js-runtime": "^0.0.8",
94
94
  "natural-orderby": "^5.0.0",
95
95
  "object-hash": "^3.0.0",
96
- "p-queue": "^8.1.0",
97
- "remeda": "^2.25.0",
96
+ "p-limit": "^6.2.0",
97
+ "remeda": "^2.26.0",
98
98
  "seedrandom": "^3.0.5",
99
99
  "semver": "^7.7.2",
100
- "@kubb/parser-ts": "3.15.0"
100
+ "@kubb/parser-ts": "3.16.0"
101
101
  },
102
102
  "devDependencies": {
103
103
  "@types/fs-extra": "^11.0.4",
@@ -108,8 +108,8 @@
108
108
  "prettier": "^3.6.2",
109
109
  "tsup": "^8.5.0",
110
110
  "typescript": "^5.8.3",
111
- "@kubb/config-ts": "3.15.0",
112
- "@kubb/config-tsup": "3.15.0"
111
+ "@kubb/config-tsup": "3.16.0",
112
+ "@kubb/config-ts": "3.16.0"
113
113
  },
114
114
  "engines": {
115
115
  "node": ">=20"
@@ -18,13 +18,11 @@ export class BarrelManager {
18
18
  return this
19
19
  }
20
20
 
21
- getFiles({ files: generatedFiles, root, meta }: { files: KubbFile.File[]; root?: string; meta?: FileMetaBase | undefined }): Array<KubbFile.File> {
21
+ getFiles({ files: generatedFiles, root }: { files: KubbFile.File[]; root?: string; meta?: FileMetaBase | undefined }): Array<KubbFile.File> {
22
22
  const { logger } = this.#options
23
23
 
24
24
  const cachedFiles = new Map<KubbFile.Path, KubbFile.File>()
25
25
 
26
- logger?.emit('debug', { date: new Date(), logs: [`Start barrel generation for pluginKey ${meta?.pluginKey?.join('.')} and root '${root}'`] })
27
-
28
26
  TreeNode.build(generatedFiles, root)?.forEach((treeNode) => {
29
27
  if (!treeNode || !treeNode.children || !treeNode.parent?.data.path) {
30
28
  return undefined
@@ -97,23 +95,6 @@ export class BarrelManager {
97
95
  })
98
96
  })
99
97
 
100
- logger?.emit('debug', {
101
- date: new Date(),
102
- logs: [
103
- `Generating barrelFile '${getRelativePath(root, barrelFile.path)}' for '${getRelativePath(root, treeNode.data?.path)}' with ${barrelFile.sources.length} indexable exports: '${barrelFile.sources?.map((source) => source.name).join(', ')}'`,
104
- ],
105
- })
106
-
107
- logger?.emit('debug', {
108
- date: new Date(),
109
- logs: [
110
- `Generated barrelFile '${getRelativePath(root, barrelFile.path)}' for '${getRelativePath(root, treeNode.data?.path)}' with exports: '${cachedFiles
111
- .get(barrelFile.path)
112
- ?.sources?.map((source) => source.name)
113
- .join(', ')}'`,
114
- ],
115
- })
116
-
117
98
  if (previousBarrelFile) {
118
99
  previousBarrelFile.sources.push(...barrelFile.sources)
119
100
  previousBarrelFile.exports?.push(...(barrelFile.exports || []))
@@ -1,18 +1,19 @@
1
1
  import { extname, join, relative } from 'node:path'
2
2
 
3
3
  import { orderBy } from 'natural-orderby'
4
- import PQueue from 'p-queue'
5
4
  import { isDeepEqual, uniqueBy } from 'remeda'
5
+ import pLimit from 'p-limit'
6
+
6
7
  import { BarrelManager } from './BarrelManager.ts'
7
8
 
8
9
  import type { KubbFile } from './fs/index.ts'
9
- import { read, trimExtName, write } from './fs/index.ts'
10
+ import { trimExtName, write } from './fs/index.ts'
10
11
  import type { ResolvedFile } from './fs/types.ts'
11
12
  import type { Logger } from './logger.ts'
12
13
  import type { BarrelType, Config, Plugin } from './types.ts'
13
14
  import { createFile, getFileParser } from './utils'
14
- import { buildDirectoryTree, type DirectoryTree, TreeNode } from './utils/TreeNode.ts'
15
15
  import type { GreaterThan } from './utils/types.ts'
16
+ import { Cache } from './utils/Cache.ts'
16
17
 
17
18
  export type FileMetaBase = {
18
19
  pluginKey?: Plugin['key']
@@ -26,7 +27,6 @@ type AddIndexesProps = {
26
27
  * Root based on root and output.path specified in the config
27
28
  */
28
29
  root: string
29
- files: KubbFile.File[]
30
30
  /**
31
31
  * Output for plugin
32
32
  */
@@ -42,47 +42,46 @@ type AddIndexesProps = {
42
42
  meta?: FileMetaBase
43
43
  }
44
44
 
45
+ type WriteFilesProps = {
46
+ root: Config['root']
47
+ extension?: Record<KubbFile.Extname, KubbFile.Extname | ''>
48
+ logger?: Logger
49
+ dryRun?: boolean
50
+ }
51
+
45
52
  export class FileManager {
46
- #filesByPath: Map<KubbFile.Path, KubbFile.ResolvedFile> = new Map()
53
+ #cache = new Cache<KubbFile.ResolvedFile>()
54
+ #limit = pLimit(100)
55
+
47
56
  constructor() {
48
57
  return this
49
58
  }
50
59
 
51
- get files(): Array<KubbFile.ResolvedFile> {
52
- return [...this.#filesByPath.values()]
53
- }
60
+ async add<T extends Array<KubbFile.File> = Array<KubbFile.File>>(...files: T): AddResult<T> {
61
+ const resolvedFiles: KubbFile.ResolvedFile[] = []
54
62
 
55
- get orderedFiles(): Array<KubbFile.ResolvedFile> {
56
- return orderBy(
57
- [...this.#filesByPath.values()],
58
- [
59
- (v) => v?.meta && 'pluginKey' in v.meta && !v.meta.pluginKey,
60
- (v) => v.path.length,
61
- (v) => trimExtName(v.path).endsWith('index'),
62
- (v) => trimExtName(v.baseName),
63
- (v) => v.path.split('.').pop(),
64
- ],
65
- )
66
- }
63
+ const mergedFiles = new Map<string, KubbFile.File>()
67
64
 
68
- get groupedFiles(): DirectoryTree | null {
69
- return buildDirectoryTree([...this.#filesByPath.values()])
70
- }
65
+ files.forEach((file) => {
66
+ const existing = mergedFiles.get(file.path)
67
+ if (existing) {
68
+ mergedFiles.set(file.path, mergeFile(existing, file))
69
+ } else {
70
+ mergedFiles.set(file.path, file)
71
+ }
72
+ })
71
73
 
72
- get treeNode(): TreeNode | null {
73
- return TreeNode.build([...this.#filesByPath.values()])
74
- }
74
+ for (const file of mergedFiles.values()) {
75
+ const existing = await this.#cache.get(file.path)
75
76
 
76
- async add<T extends Array<KubbFile.File> = Array<KubbFile.File>>(...files: T): AddResult<T> {
77
- const promises = files.map((file) => {
78
- if (file.override) {
79
- return this.#add(file)
80
- }
77
+ const merged = existing ? mergeFile(existing, file) : file
78
+ const resolvedFile = createFile(merged)
81
79
 
82
- return this.#addOrAppend(file)
83
- })
80
+ await this.#cache.set(resolvedFile.path, resolvedFile)
81
+ await this.#cache.flush()
84
82
 
85
- const resolvedFiles = await Promise.all(promises)
83
+ resolvedFiles.push(resolvedFile)
84
+ }
86
85
 
87
86
  if (files.length > 1) {
88
87
  return resolvedFiles as unknown as AddResult<T>
@@ -91,52 +90,68 @@ export class FileManager {
91
90
  return resolvedFiles[0] as unknown as AddResult<T>
92
91
  }
93
92
 
94
- async #add(file: KubbFile.File): Promise<ResolvedFile> {
95
- const resolvedFile = createFile(file)
96
-
97
- this.#filesByPath.set(resolvedFile.path, resolvedFile)
93
+ async getByPath(path: KubbFile.Path): Promise<KubbFile.ResolvedFile | null> {
94
+ return this.#cache.get(path)
95
+ }
98
96
 
99
- return resolvedFile
97
+ async deleteByPath(path: KubbFile.Path): Promise<void> {
98
+ await this.#cache.delete(path)
100
99
  }
101
100
 
102
- clear() {
103
- this.#filesByPath.clear()
101
+ async clear(): Promise<void> {
102
+ await this.#cache.clear()
104
103
  }
105
104
 
106
- async #addOrAppend(file: KubbFile.File): Promise<ResolvedFile> {
107
- const previousFile = this.#filesByPath.get(file.path)
105
+ async getFiles(): Promise<Array<KubbFile.ResolvedFile>> {
106
+ const cachedKeys = await this.#cache.keys()
108
107
 
109
- if (previousFile) {
110
- this.#filesByPath.delete(previousFile.path)
108
+ // order by path length and if file is a barrel file
109
+ const keys = orderBy(cachedKeys, [(v) => v.length, (v) => trimExtName(v).endsWith('index')])
111
110
 
112
- return this.#add(mergeFile(previousFile, file))
113
- }
114
- return this.#add(file)
115
- }
111
+ const filesTasks = keys.map((key) =>
112
+ this.#limit(async () => {
113
+ const file = await this.#cache.get(key)
114
+ return file as KubbFile.ResolvedFile
115
+ }),
116
+ )
116
117
 
117
- getCacheById(id: string): KubbFile.File | undefined {
118
- return [...this.#filesByPath.values()].find((file) => file.id === id)
119
- }
118
+ const files = await Promise.all(filesTasks)
120
119
 
121
- getByPath(path: KubbFile.Path): KubbFile.ResolvedFile | undefined {
122
- return this.#filesByPath.get(path)
120
+ return files.filter(Boolean)
123
121
  }
124
122
 
125
- deleteByPath(path: KubbFile.Path): void {
126
- const cacheItem = this.getByPath(path)
127
- if (!cacheItem) {
128
- return
129
- }
123
+ async processFiles({ dryRun, root, extension, logger }: WriteFilesProps): Promise<Array<KubbFile.ResolvedFile>> {
124
+ const files = await this.getFiles()
130
125
 
131
- this.#filesByPath.delete(path)
132
- }
126
+ logger?.emit('progress_start', { id: 'files', size: files.length, message: 'Writing files ...' })
127
+
128
+ const promises = files.map((file) => {
129
+ return this.#limit(async () => {
130
+ const message = file ? `Writing ${relative(root, file.path)}` : ''
131
+ const extname = extension?.[file.extname] || undefined
132
+
133
+ if (!dryRun) {
134
+ const source = await getSource(file, { logger, extname })
135
+ await write(file.path, source, { sanity: false })
136
+ }
137
+
138
+ logger?.emit('progressed', { id: 'files', message })
139
+ })
140
+ })
141
+
142
+ await Promise.all(promises)
133
143
 
134
- async getBarrelFiles({ type, files, meta = {}, root, output, logger }: AddIndexesProps): Promise<KubbFile.File[]> {
144
+ logger?.emit('progress_stop', { id: 'files' })
145
+
146
+ return files
147
+ }
148
+ async getBarrelFiles({ type, meta = {}, root, output, logger }: AddIndexesProps): Promise<KubbFile.File[]> {
135
149
  if (!type || type === 'propagate') {
136
150
  return []
137
151
  }
138
152
 
139
153
  const barrelManager = new BarrelManager({ logger })
154
+ const files = await this.getFiles()
140
155
 
141
156
  const pathToBuildFrom = join(root, output.path)
142
157
 
@@ -170,14 +185,6 @@ export class FileManager {
170
185
  })
171
186
  }
172
187
 
173
- async write(...params: Parameters<typeof write>): ReturnType<typeof write> {
174
- return write(...params)
175
- }
176
-
177
- async read(...params: Parameters<typeof read>): ReturnType<typeof read> {
178
- return read(...params)
179
- }
180
-
181
188
  // statics
182
189
  static getMode(path: string | undefined | null): KubbFile.Mode {
183
190
  if (!path) {
@@ -285,7 +292,7 @@ export function combineImports(imports: Array<KubbFile.Import>, exports: Array<K
285
292
  }
286
293
 
287
294
  const checker = (name?: string) => {
288
- return name && !!source.includes(name)
295
+ return name && source.includes(name)
289
296
  }
290
297
 
291
298
  return checker(importName) || exports.some(({ name }) => (Array.isArray(name) ? name.some(checker) : checker(name)))
@@ -343,53 +350,3 @@ export function combineImports(imports: Array<KubbFile.Import>, exports: Array<K
343
350
  [] as Array<KubbFile.Import>,
344
351
  )
345
352
  }
346
-
347
- type WriteFilesProps = {
348
- root: Config['root']
349
- files: Array<KubbFile.ResolvedFile>
350
- extension?: Record<KubbFile.Extname, KubbFile.Extname | ''>
351
- logger?: Logger
352
- dryRun?: boolean
353
- }
354
- /**
355
- * Global queue
356
- */
357
- const queue = new PQueue({ concurrency: 100 })
358
-
359
- export async function processFiles({ dryRun, root, extension, logger, files }: WriteFilesProps) {
360
- const orderedFiles = orderBy(files, [
361
- (v) => v?.meta && 'pluginKey' in v.meta && !v.meta.pluginKey,
362
- (v) => v.path.length,
363
- (v) => trimExtName(v.path).endsWith('index'),
364
- ])
365
-
366
- logger?.emit('debug', {
367
- date: new Date(),
368
- logs: [JSON.stringify({ files: orderedFiles }, null, 2)],
369
- fileName: 'kubb-files.log',
370
- })
371
-
372
- if (!dryRun) {
373
- const size = orderedFiles.length
374
-
375
- logger?.emit('progress_start', { id: 'files', size, message: 'Writing files ...' })
376
- const promises = orderedFiles.map(async (file) => {
377
- await queue.add(async () => {
378
- const message = file ? `Writing ${relative(root, file.path)}` : ''
379
- const extname = extension?.[file.extname] || undefined
380
-
381
- const source = await getSource(file, { logger, extname })
382
-
383
- await write(file.path, source, { sanity: false })
384
-
385
- logger?.emit('progressed', { id: 'files', message })
386
- })
387
- })
388
-
389
- await Promise.all(promises)
390
-
391
- logger?.emit('progress_stop', { id: 'files' })
392
- }
393
-
394
- return files
395
- }
@@ -1,5 +1,5 @@
1
1
  import { FileManager } from './FileManager.ts'
2
- import { isPromise, isPromiseRejectedResult } from './PromiseManager.ts'
2
+ import { isPromiseRejectedResult } from './PromiseManager.ts'
3
3
  import { PromiseManager } from './PromiseManager.ts'
4
4
  import { ValidationPluginError } from './errors.ts'
5
5
  import { pluginCore } from './plugin.ts'
@@ -50,6 +50,10 @@ type SafeParseResult<H extends PluginLifecycleHooks, Result = ReturnType<ParseRe
50
50
 
51
51
  type Options = {
52
52
  logger: Logger
53
+ /**
54
+ * @default Number.POSITIVE_INFINITY
55
+ */
56
+ concurrency?: number
53
57
  }
54
58
 
55
59
  type Events = {
@@ -215,19 +219,21 @@ export class PluginManager {
215
219
 
216
220
  this.logger.emit('progress_start', { id: hookName, size: plugins.length, message: 'Running plugins...' })
217
221
 
218
- const promises = plugins
219
- .map((plugin) => {
220
- return this.#execute<H>({
221
- strategy: 'hookFirst',
222
- hookName,
223
- parameters,
224
- plugin,
225
- message,
226
- })
222
+ const items: Array<ReturnType<ParseResult<H>>> = []
223
+
224
+ for (const plugin of plugins) {
225
+ const result = await this.#execute<H>({
226
+ strategy: 'hookFirst',
227
+ hookName,
228
+ parameters,
229
+ plugin,
230
+ message,
227
231
  })
228
- .filter(Boolean)
229
232
 
230
- const items = await Promise.all(promises)
233
+ if (result !== undefined && result !== null) {
234
+ items.push(result)
235
+ }
236
+ }
231
237
 
232
238
  this.logger.emit('progress_stop', { id: hookName })
233
239
 
@@ -374,7 +380,7 @@ export class PluginManager {
374
380
  }) as Promise<TOuput>
375
381
  })
376
382
 
377
- const results = await this.#promiseManager.run('parallel', promises)
383
+ const results = await this.#promiseManager.run('parallel', promises, { concurrency: this.options.concurrency })
378
384
 
379
385
  results.forEach((result, index) => {
380
386
  if (isPromiseRejectedResult<Error>(result)) {
@@ -540,25 +546,27 @@ export class PluginManager {
540
546
  }
541
547
 
542
548
  this.events.emit('executing', { strategy, hookName, parameters, plugin, message })
543
- const promise = new Promise((resolve) => {
544
- resolve(undefined)
545
- })
546
549
 
547
- const task = promise
548
- .then(() => {
550
+ const task = (async () => {
551
+ try {
549
552
  if (typeof hook === 'function') {
550
- const possiblePromiseResult = (hook as Function).apply({ ...this.#core.context, plugin }, parameters) as Promise<ReturnType<ParseResult<H>>>
553
+ const result = await Promise.resolve((hook as Function).apply({ ...this.#core.context, plugin }, parameters))
551
554
 
552
- if (isPromise(possiblePromiseResult)) {
553
- return Promise.resolve(possiblePromiseResult)
554
- }
555
- return possiblePromiseResult
555
+ output = result
556
+
557
+ this.#addExecutedToCallStack({
558
+ parameters,
559
+ output,
560
+ strategy,
561
+ hookName,
562
+ plugin,
563
+ message,
564
+ })
565
+
566
+ return result
556
567
  }
557
568
 
558
- return hook
559
- })
560
- .then((result) => {
561
- output = result
569
+ output = hook
562
570
 
563
571
  this.#addExecutedToCallStack({
564
572
  parameters,
@@ -569,13 +577,12 @@ export class PluginManager {
569
577
  message,
570
578
  })
571
579
 
572
- return result
573
- })
574
- .catch((e: Error) => {
575
- this.#catcher<H>(e, plugin, hookName)
576
-
580
+ return hook
581
+ } catch (e) {
582
+ this.#catcher<H>(e as Error, plugin, hookName)
577
583
  return null
578
- })
584
+ }
585
+ })()
579
586
 
580
587
  return task
581
588
  }
@@ -21,6 +21,7 @@ export class PromiseManager<TState = any> {
21
21
  run<TInput extends Array<PromiseFunc<TValue, null>>, TValue, TStrategy extends Strategy, TOutput = StrategySwitch<TStrategy, TInput, TValue>>(
22
22
  strategy: TStrategy,
23
23
  promises: TInput,
24
+ { concurrency = Number.POSITIVE_INFINITY }: { concurrency?: number } = {},
24
25
  ): TOutput {
25
26
  if (strategy === 'seq') {
26
27
  return hookSeq<TInput, TValue, TOutput>(promises)
@@ -31,7 +32,7 @@ export class PromiseManager<TState = any> {
31
32
  }
32
33
 
33
34
  if (strategy === 'parallel') {
34
- return hookParallel<TInput, TValue, TOutput>(promises)
35
+ return hookParallel<TInput, TValue, TOutput>(promises, concurrency)
35
36
  }
36
37
 
37
38
  throw new Error(`${strategy} not implemented`)