@kubb/core 3.0.0-alpha.1 → 3.0.0-alpha.10

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 (96) hide show
  1. package/dist/{FileManager-EVJig-LT.d.ts → FileManager-BbUCeEyv.d.cts} +108 -94
  2. package/dist/{FileManager-DSLZ6ps7.d.cts → FileManager-CpuFz6eH.d.ts} +108 -94
  3. package/dist/chunk-2EU7DMPM.js +97 -0
  4. package/dist/chunk-2EU7DMPM.js.map +1 -0
  5. package/dist/chunk-5E2I6KH4.cjs +1071 -0
  6. package/dist/chunk-5E2I6KH4.cjs.map +1 -0
  7. package/dist/{chunk-67C6RBGQ.cjs → chunk-A6PCLWEY.cjs} +5 -5
  8. package/dist/{chunk-67C6RBGQ.cjs.map → chunk-A6PCLWEY.cjs.map} +1 -1
  9. package/dist/chunk-DID47EQD.cjs +102 -0
  10. package/dist/chunk-DID47EQD.cjs.map +1 -0
  11. package/dist/chunk-HBQM723K.js +1063 -0
  12. package/dist/chunk-HBQM723K.js.map +1 -0
  13. package/dist/chunk-L6YLVCKM.js +929 -0
  14. package/dist/chunk-L6YLVCKM.js.map +1 -0
  15. package/dist/{chunk-LM2YQC3T.cjs → chunk-M7NLNCSM.cjs} +71 -38
  16. package/dist/chunk-M7NLNCSM.cjs.map +1 -0
  17. package/dist/{chunk-3OXCZ5DJ.js → chunk-MU3CBCQT.js} +59 -35
  18. package/dist/chunk-MU3CBCQT.js.map +1 -0
  19. package/dist/chunk-NB4JMN75.cjs +1548 -0
  20. package/dist/chunk-NB4JMN75.cjs.map +1 -0
  21. package/dist/{chunk-XCPFG6DO.cjs → chunk-SEH6NUCX.cjs} +4 -28
  22. package/dist/chunk-SEH6NUCX.cjs.map +1 -0
  23. package/dist/index.cjs +496 -552
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +6 -19
  26. package/dist/index.d.ts +6 -19
  27. package/dist/index.js +438 -492
  28. package/dist/index.js.map +1 -1
  29. package/dist/{logger-DChjnJMn.d.cts → logger-DvbHXjIO.d.cts} +29 -19
  30. package/dist/{logger-DChjnJMn.d.ts → logger-DvbHXjIO.d.ts} +29 -19
  31. package/dist/logger.cjs +4 -5
  32. package/dist/logger.cjs.map +1 -1
  33. package/dist/logger.d.cts +1 -2
  34. package/dist/logger.d.ts +1 -2
  35. package/dist/logger.js +2 -4
  36. package/dist/mocks.cjs +25 -19
  37. package/dist/mocks.cjs.map +1 -1
  38. package/dist/mocks.d.cts +6 -9
  39. package/dist/mocks.d.ts +6 -9
  40. package/dist/mocks.js +21 -16
  41. package/dist/mocks.js.map +1 -1
  42. package/dist/prompt-DVQN7JTN.cjs +760 -0
  43. package/dist/prompt-DVQN7JTN.cjs.map +1 -0
  44. package/dist/prompt-WQQUN22Z.js +754 -0
  45. package/dist/prompt-WQQUN22Z.js.map +1 -0
  46. package/dist/transformers.cjs +198 -42
  47. package/dist/transformers.cjs.map +1 -1
  48. package/dist/transformers.d.cts +1 -3
  49. package/dist/transformers.d.ts +1 -3
  50. package/dist/transformers.js +155 -14
  51. package/dist/transformers.js.map +1 -1
  52. package/dist/utils.cjs +12 -4
  53. package/dist/utils.cjs.map +1 -1
  54. package/dist/utils.d.cts +31 -3
  55. package/dist/utils.d.ts +31 -3
  56. package/dist/utils.js +11 -4
  57. package/package.json +10 -10
  58. package/src/BarrelManager.ts +93 -107
  59. package/src/{Generator.ts → BaseGenerator.ts} +1 -1
  60. package/src/FileManager.ts +198 -297
  61. package/src/PackageManager.ts +1 -1
  62. package/src/PluginManager.ts +152 -101
  63. package/src/__snapshots__/barrel.json +91 -0
  64. package/src/__snapshots__/grouped.json +114 -0
  65. package/src/__snapshots__/ordered.json +62 -0
  66. package/src/build.ts +86 -171
  67. package/src/errors.ts +0 -11
  68. package/src/index.ts +1 -2
  69. package/src/logger.ts +76 -34
  70. package/src/plugin.ts +3 -3
  71. package/src/transformers/index.ts +2 -3
  72. package/src/transformers/trim.ts +0 -4
  73. package/src/types.ts +35 -35
  74. package/src/utils/TreeNode.ts +132 -50
  75. package/src/utils/executeStrategies.ts +1 -1
  76. package/src/utils/index.ts +2 -1
  77. package/src/utils/parser.ts +157 -0
  78. package/dist/chunk-3OXCZ5DJ.js.map +0 -1
  79. package/dist/chunk-5JZNFPUP.js +0 -309
  80. package/dist/chunk-5JZNFPUP.js.map +0 -1
  81. package/dist/chunk-ADC5UNZ5.cjs +0 -1227
  82. package/dist/chunk-ADC5UNZ5.cjs.map +0 -1
  83. package/dist/chunk-HMLY7DHA.js +0 -16
  84. package/dist/chunk-HMLY7DHA.js.map +0 -1
  85. package/dist/chunk-JKZG2IJR.js +0 -283
  86. package/dist/chunk-JKZG2IJR.js.map +0 -1
  87. package/dist/chunk-LM2YQC3T.cjs.map +0 -1
  88. package/dist/chunk-PZT4CTBV.cjs +0 -299
  89. package/dist/chunk-PZT4CTBV.cjs.map +0 -1
  90. package/dist/chunk-SA2GZKXS.js +0 -596
  91. package/dist/chunk-SA2GZKXS.js.map +0 -1
  92. package/dist/chunk-XCPFG6DO.cjs.map +0 -1
  93. package/dist/chunk-YTSNYMHW.cjs +0 -320
  94. package/dist/chunk-YTSNYMHW.cjs.map +0 -1
  95. package/schema.json +0 -86
  96. package/src/utils/getParser.ts +0 -17
@@ -1,101 +1,83 @@
1
- import crypto from 'node:crypto'
2
- import { extname, resolve } from 'node:path'
1
+ import { extname, join, relative } from 'node:path'
3
2
 
4
3
  import { orderBy } from 'natural-orderby'
5
- import PQueue from 'p-queue'
6
4
  import { isDeepEqual } from 'remeda'
7
5
 
8
- import { getRelativePath, read, write } from '@kubb/fs'
6
+ import { read, write } from '@kubb/fs'
9
7
  import { BarrelManager } from './BarrelManager.ts'
10
- import { searchAndReplace } from './transformers/searchAndReplace.ts'
11
- import { trimExtName } from './transformers/trim.ts'
12
8
 
13
9
  import type * as KubbFile from '@kubb/fs/types'
14
10
 
15
- import type { BaseName, File, UUID } from '@kubb/fs/src/types.ts'
11
+ import { trimExtName } from '@kubb/fs'
12
+ import type { ResolvedFile } from '@kubb/fs/types'
16
13
  import type { GreaterThan } from '@kubb/types'
17
- import type { BarrelManagerOptions } from './BarrelManager.ts'
14
+ import PQueue from 'p-queue'
18
15
  import type { Logger } from './logger.ts'
19
- import transformers from './transformers/index.ts'
20
- import type { Plugin } from './types.ts'
21
- import { getParser } from './utils'
22
-
23
- export type ResolvedFile<TMeta extends FileMetaBase = FileMetaBase, TBaseName extends BaseName = BaseName> = File<TMeta, TBaseName> & {
24
- /**
25
- * @default crypto.randomUUID()
26
- */
27
- id: UUID
28
- /**
29
- * Contains the first part of the baseName, generated based on baseName
30
- * @link https://nodejs.org/api/path.html#pathformatpathobject
31
- */
32
-
33
- name: string
34
- }
16
+ import type { Config, Plugin } from './types.ts'
17
+ import { createFile, getFileParser } from './utils'
18
+ import { type DirectoryTree, TreeNode, buildDirectoryTree } from './utils/TreeNode.ts'
35
19
 
36
20
  export type FileMetaBase = {
37
21
  pluginKey?: Plugin['key']
38
22
  }
39
23
 
40
- type FileWithMeta<TMeta extends FileMetaBase = FileMetaBase> = KubbFile.File<TMeta>
41
-
42
- type CacheItem = ResolvedFile & {
43
- cancel?: () => void
44
- }
45
-
46
- type AddResult<T extends Array<FileWithMeta>> = Promise<Awaited<GreaterThan<T['length'], 1> extends true ? Promise<ResolvedFile[]> : Promise<ResolvedFile>>>
24
+ type AddResult<T extends Array<KubbFile.File>> = Promise<Awaited<GreaterThan<T['length'], 1> extends true ? Promise<ResolvedFile[]> : Promise<ResolvedFile>>>
47
25
 
48
26
  type AddIndexesProps = {
49
27
  /**
50
28
  * Root based on root and output.path specified in the config
51
29
  */
52
30
  root: string
31
+ files: KubbFile.File[]
53
32
  /**
54
33
  * Output for plugin
55
34
  */
56
35
  output: {
57
36
  path: string
58
- exportAs?: string
59
37
  extName?: KubbFile.Extname
38
+ exportAs?: string
60
39
  exportType?: 'barrel' | 'barrelNamed' | false
61
40
  }
62
- logger: Logger
63
- options?: BarrelManagerOptions
64
- meta?: FileWithMeta['meta']
65
- }
41
+ group?: {
42
+ output: string
43
+ exportAs: string
44
+ }
45
+ logger?: Logger
66
46
 
67
- type Options = {
68
- queue?: PQueue
69
- task?: (file: ResolvedFile) => Promise<ResolvedFile>
47
+ meta?: FileMetaBase
70
48
  }
71
49
 
72
50
  export class FileManager {
73
- #cache: Map<KubbFile.Path, CacheItem[]> = new Map()
74
-
75
- #task: Options['task']
76
- #queue: PQueue
77
-
78
- constructor({ task = async (file) => file, queue = new PQueue() }: Options = {}) {
79
- this.#task = task
80
- this.#queue = queue
81
-
51
+ #filesByPath: Map<KubbFile.Path, KubbFile.ResolvedFile> = new Map()
52
+ #files: Set<KubbFile.ResolvedFile> = new Set()
53
+ constructor() {
82
54
  return this
83
55
  }
84
56
 
85
- get files(): Array<FileWithMeta> {
86
- const files: Array<FileWithMeta> = []
87
- this.#cache.forEach((item) => {
88
- files.push(...item.flat(1))
89
- })
57
+ get files(): Array<KubbFile.ResolvedFile> {
58
+ return Array.from(this.#files)
59
+ }
90
60
 
91
- return files
61
+ get orderedFiles(): Array<KubbFile.ResolvedFile> {
62
+ return orderBy(Array.from(this.#files), [
63
+ (v) => v?.meta && 'pluginKey' in v.meta && !v.meta.pluginKey,
64
+ (v) => v.path.length,
65
+ (v) => trimExtName(v.path).endsWith('index'),
66
+ (v) => trimExtName(v.baseName),
67
+ (v) => v.path.split('.').pop(),
68
+ ])
92
69
  }
93
- get isExecuting(): boolean {
94
- return this.#queue.size !== 0 && this.#queue.pending !== 0
70
+
71
+ get groupedFiles(): DirectoryTree | null {
72
+ return buildDirectoryTree(Array.from(this.#files))
73
+ }
74
+
75
+ get treeNode(): TreeNode | null {
76
+ return TreeNode.build(Array.from(this.#files))
95
77
  }
96
78
 
97
- async add<T extends Array<FileWithMeta> = Array<FileWithMeta>>(...files: T): AddResult<T> {
98
- const promises = combineFiles(files).map((file) => {
79
+ async add<T extends Array<KubbFile.File> = Array<KubbFile.File>>(...files: T): AddResult<T> {
80
+ const promises = files.map((file) => {
99
81
  if (file.override) {
100
82
  return this.#add(file)
101
83
  }
@@ -112,270 +94,161 @@ export class FileManager {
112
94
  return resolvedFiles[0] as unknown as AddResult<T>
113
95
  }
114
96
 
115
- async #add(file: FileWithMeta): Promise<ResolvedFile> {
116
- const controller = new AbortController()
117
- const resolvedFile: ResolvedFile = {
118
- id: crypto.randomUUID(),
119
- name: trimExtName(file.baseName),
120
- ...file,
121
- }
122
-
123
- if (resolvedFile.exports?.length) {
124
- const folder = resolvedFile.path.replace(resolvedFile.baseName, '')
125
-
126
- resolvedFile.exports = resolvedFile.exports.filter((exportItem) => {
127
- const exportedFile = this.files.find((file) => file.path.includes(resolve(folder, exportItem.path)))
128
-
129
- if (exportedFile) {
130
- return exportedFile.exportable
131
- }
97
+ async #add(file: KubbFile.File): Promise<ResolvedFile> {
98
+ const resolvedFile = createFile(file)
132
99
 
133
- return true
134
- })
135
- }
100
+ this.#filesByPath.set(resolvedFile.path, resolvedFile)
101
+ this.#files.add(resolvedFile)
136
102
 
137
- this.#cache.set(resolvedFile.path, [{ cancel: () => controller.abort(), ...resolvedFile }])
103
+ return resolvedFile
104
+ }
138
105
 
139
- return this.#queue.add(
140
- async () => {
141
- return this.#task?.(resolvedFile)
142
- },
143
- { signal: controller.signal },
144
- ) as Promise<ResolvedFile>
106
+ clear() {
107
+ this.#filesByPath.clear()
108
+ this.#files.clear()
145
109
  }
146
110
 
147
- async #addOrAppend(file: FileWithMeta): Promise<ResolvedFile> {
148
- const previousCaches = this.#cache.get(file.path)
149
- const previousCache = previousCaches ? previousCaches.at(previousCaches.length - 1) : undefined
111
+ async #addOrAppend(file: KubbFile.File): Promise<ResolvedFile> {
112
+ const previousFile = this.#filesByPath.get(file.path)
150
113
 
151
- if (previousCache) {
152
- this.#cache.delete(previousCache.path)
114
+ if (previousFile) {
115
+ this.#filesByPath.delete(previousFile.path)
116
+ this.#files.delete(previousFile)
153
117
 
154
- return this.#add({
155
- ...file,
156
- source: previousCache.source && file.source ? `${previousCache.source}\n${file.source}` : '',
157
- imports: [...(previousCache.imports || []), ...(file.imports || [])],
158
- exports: [...(previousCache.exports || []), ...(file.exports || [])],
159
- env: { ...(previousCache.env || {}), ...(file.env || {}) },
160
- })
118
+ return this.#add(mergeFile(previousFile, file))
161
119
  }
162
120
  return this.#add(file)
163
121
  }
164
122
 
165
- async addIndexes({ root, output, meta, logger, options = {} }: AddIndexesProps): Promise<void> {
166
- const { exportType = 'barrel' } = output
167
- // ^?
168
- if (exportType === false) {
169
- return undefined
170
- }
171
-
172
- const pathToBuildFrom = resolve(root, output.path)
123
+ getCacheById(id: string): KubbFile.File | undefined {
124
+ let cache: KubbFile.File | undefined
173
125
 
174
- if (transformers.trimExtName(pathToBuildFrom).endsWith('index')) {
175
- logger.emit('warning', 'Output has the same fileName as the barrelFiles, please disable barrel generation')
176
- return
177
- }
178
-
179
- const exportPath = output.path.startsWith('./') ? trimExtName(output.path) : `./${trimExtName(output.path)}`
180
- const mode = FileManager.getMode(output.path)
181
- const barrelManager = new BarrelManager({
182
- extName: output.extName,
183
- ...options,
126
+ this.#files.forEach((file) => {
127
+ if (file.id === id) {
128
+ cache = file
129
+ }
184
130
  })
185
- let files = barrelManager.getIndexes(pathToBuildFrom)
131
+ return cache
132
+ }
186
133
 
187
- if (!files) {
188
- return undefined
189
- }
134
+ getByPath(path: KubbFile.Path): KubbFile.ResolvedFile | undefined {
135
+ return this.#filesByPath.get(path)
136
+ }
190
137
 
191
- if (exportType === 'barrelNamed') {
192
- files = files.map((file) => {
193
- if (file.exports) {
194
- return {
195
- ...file,
196
- exports: barrelManager.getNamedExports(pathToBuildFrom, file.exports),
197
- }
198
- }
199
- return file
200
- })
138
+ deleteByPath(path: KubbFile.Path): void {
139
+ const cacheItem = this.getByPath(path)
140
+ if (!cacheItem) {
141
+ return
201
142
  }
202
143
 
203
- await Promise.all(
204
- files.map((file) => {
205
- return this.#addOrAppend({
206
- ...file,
207
- meta: meta ? meta : file.meta,
208
- })
209
- }),
210
- )
211
-
212
- const rootPath = mode === 'split' ? `${exportPath}/index${output.extName || ''}` : `${exportPath}${output.extName || ''}`
213
- const rootFile: FileWithMeta = {
214
- path: resolve(root, 'index.ts'),
215
- baseName: 'index.ts',
216
- source: '',
217
- exports: [
218
- output.exportAs
219
- ? {
220
- name: output.exportAs,
221
- asAlias: true,
222
- path: rootPath,
223
- isTypeOnly: options.isTypeOnly,
224
- }
225
- : {
226
- path: rootPath,
227
- isTypeOnly: options.isTypeOnly,
228
- },
229
- ],
230
- exportable: true,
231
- }
144
+ this.#filesByPath.delete(path)
145
+ this.#files.delete(cacheItem)
146
+ }
232
147
 
233
- if (exportType === 'barrelNamed' && !output.exportAs && rootFile.exports?.[0]) {
234
- rootFile.exports = barrelManager.getNamedExport(root, rootFile.exports[0])
148
+ async getBarrelFiles({ files, meta, root, output, logger }: AddIndexesProps): Promise<KubbFile.File[]> {
149
+ const { exportType = 'barrelNamed' } = output
150
+ const barrelManager = new BarrelManager({ logger })
151
+
152
+ if (exportType === false) {
153
+ return []
235
154
  }
236
155
 
237
- await this.#addOrAppend({
238
- ...rootFile,
239
- meta: meta ? meta : rootFile.meta,
240
- })
241
- }
156
+ const pathToBuildFrom = join(root, output.path)
242
157
 
243
- getCacheByUUID(UUID: KubbFile.UUID): FileWithMeta | undefined {
244
- let cache: FileWithMeta | undefined
158
+ if (trimExtName(pathToBuildFrom).endsWith('index')) {
159
+ logger?.emit('warning', 'Output has the same fileName as the barrelFiles, please disable barrel generation')
245
160
 
246
- this.#cache.forEach((files) => {
247
- cache = files.find((item) => item.id === UUID)
248
- })
249
- return cache
250
- }
161
+ return []
162
+ }
251
163
 
252
- get(path: KubbFile.Path): Array<FileWithMeta> | undefined {
253
- return this.#cache.get(path)
254
- }
164
+ const barrelFiles = barrelManager.getFiles({ files, root: pathToBuildFrom, meta })
255
165
 
256
- remove(path: KubbFile.Path): void {
257
- const cacheItem = this.get(path)
258
- if (!cacheItem) {
259
- return
166
+ if (exportType === 'barrel') {
167
+ return barrelFiles.map((file) => {
168
+ return {
169
+ ...file,
170
+ exports: file.exports?.map((exportItem) => {
171
+ return {
172
+ ...exportItem,
173
+ name: undefined,
174
+ }
175
+ }),
176
+ }
177
+ })
260
178
  }
261
179
 
262
- this.#cache.delete(path)
180
+ return barrelFiles.map((indexFile) => {
181
+ return {
182
+ ...indexFile,
183
+ meta,
184
+ }
185
+ })
263
186
  }
264
187
 
265
- async write(...params: Parameters<typeof write>): Promise<string | undefined> {
188
+ async write(...params: Parameters<typeof write>): ReturnType<typeof write> {
266
189
  return write(...params)
267
190
  }
268
191
 
269
- async read(...params: Parameters<typeof read>): Promise<string> {
192
+ async read(...params: Parameters<typeof read>): ReturnType<typeof read> {
270
193
  return read(...params)
271
194
  }
272
195
 
273
196
  // statics
274
-
275
- static async getSource<TMeta extends FileMetaBase = FileMetaBase>(file: FileWithMeta<TMeta>): Promise<string> {
276
- return getSource<TMeta>(file)
277
- }
278
-
279
- static combineFiles<TMeta extends FileMetaBase = FileMetaBase>(files: Array<FileWithMeta<TMeta> | null>): Array<FileWithMeta<TMeta>> {
280
- return combineFiles<TMeta>(files)
281
- }
282
197
  static getMode(path: string | undefined | null): KubbFile.Mode {
283
198
  if (!path) {
284
199
  return 'split'
285
200
  }
286
201
  return extname(path) ? 'single' : 'split'
287
202
  }
203
+ }
288
204
 
289
- static get extensions(): Array<KubbFile.Extname> {
290
- return ['.js', '.ts', '.tsx']
291
- }
205
+ type GetSourceOptions = {
206
+ logger?: Logger
207
+ }
208
+
209
+ export async function getSource<TMeta extends FileMetaBase = FileMetaBase>(file: ResolvedFile<TMeta>, { logger }: GetSourceOptions = {}): Promise<string> {
210
+ const parser = await getFileParser(file.extName)
211
+
212
+ return parser.print(file, { logger })
213
+ }
292
214
 
293
- static isJavascript(baseName: string): boolean {
294
- return FileManager.extensions.some((extension) => baseName.endsWith(extension))
215
+ export function mergeFile<TMeta extends FileMetaBase = FileMetaBase>(a: KubbFile.File<TMeta>, b: KubbFile.File<TMeta>): KubbFile.File<TMeta> {
216
+ return {
217
+ ...a,
218
+ sources: [...(a.sources || []), ...(b.sources || [])],
219
+ imports: [...(a.imports || []), ...(b.imports || [])],
220
+ exports: [...(a.exports || []), ...(b.exports || [])],
295
221
  }
296
222
  }
297
223
 
298
- function combineFiles<TMeta extends FileMetaBase = FileMetaBase>(files: Array<FileWithMeta<TMeta> | null>): Array<FileWithMeta<TMeta>> {
299
- return files.filter(Boolean).reduce(
300
- (acc, file: FileWithMeta<TMeta>) => {
301
- const prevIndex = acc.findIndex((item) => item.path === file.path)
224
+ export function combineSources(sources: Array<KubbFile.Source>): Array<KubbFile.Source> {
225
+ return sources.reduce(
226
+ (prev, curr) => {
227
+ const prevByName = prev.findLast((imp) => imp.name === curr.name)
228
+ const prevByPathAndIsExportable = prev.findLast((imp) => imp.name === curr.name && imp.isExportable)
302
229
 
303
- if (prevIndex === -1) {
304
- return [...acc, file]
230
+ if (prevByPathAndIsExportable) {
231
+ // we already have an export that has the same name but uses `isExportable` (export type ...)
232
+ return [...prev, curr]
305
233
  }
306
234
 
307
- const prev = acc[prevIndex]
235
+ if (prevByName) {
236
+ prevByName.value = curr.value
237
+ prevByName.isExportable = curr.isExportable
238
+ prevByName.isTypeOnly = curr.isTypeOnly
239
+ prevByName.isIndexable = curr.isIndexable
308
240
 
309
- if (prev && file.override) {
310
- acc[prevIndex] = {
311
- imports: [],
312
- exports: [],
313
- ...file,
314
- }
315
- return acc
316
- }
317
-
318
- if (prev) {
319
- acc[prevIndex] = {
320
- ...file,
321
- source: prev.source && file.source ? `${prev.source}\n${file.source}` : '',
322
- imports: [...(prev.imports || []), ...(file.imports || [])],
323
- exports: [...(prev.exports || []), ...(file.exports || [])],
324
- env: { ...(prev.env || {}), ...(file.env || {}) },
325
- }
241
+ return prev
326
242
  }
327
243
 
328
- return acc
244
+ return [...prev, curr]
329
245
  },
330
- [] as Array<FileWithMeta<TMeta>>,
331
- )
332
- }
333
-
334
- export async function getSource<TMeta extends FileMetaBase = FileMetaBase>(file: FileWithMeta<TMeta>): Promise<string> {
335
- // only use .js, .ts or .tsx files for ESM imports
336
-
337
- if (file.language ? !['typescript', 'javascript'].includes(file.language) : !FileManager.isJavascript(file.baseName)) {
338
- return file.source
339
- }
340
-
341
- const parser = await getParser(file.language)
342
-
343
- const exports = file.exports ? combineExports(file.exports) : []
344
- // imports should be defined and source should contain code or we have imports without them being used
345
- const imports = file.imports && file.source ? combineImports(file.imports, exports, file.source) : []
346
-
347
- const importNodes = imports
348
- .filter((item) => {
349
- const path = item.root ? getRelativePath(item.root, item.path) : item.path
350
- // trim extName
351
- return path !== trimExtName(file.path)
352
- })
353
- .map((item) => {
354
- const path = item.root ? getRelativePath(item.root, item.path) : item.path
355
-
356
- return parser.factory.createImportDeclaration({
357
- name: item.name,
358
- path: item.extName ? `${path}${item.extName}` : path,
359
- isTypeOnly: item.isTypeOnly,
360
- })
361
- })
362
- const exportNodes = exports.map((item) =>
363
- parser.factory.createExportDeclaration({
364
- name: item.name,
365
- path: item.extName ? `${item.path}${item.extName}` : item.path,
366
- isTypeOnly: item.isTypeOnly,
367
- asAlias: item.asAlias,
368
- }),
246
+ [] as Array<KubbFile.Source>,
369
247
  )
370
-
371
- const source = [parser.print([...importNodes, ...exportNodes]), getEnvSource(file.source, file.env)].join('\n')
372
-
373
- // do some basic linting with the ts compiler
374
- return parser.print([], { source, noEmitHelpers: false })
375
248
  }
376
249
 
377
250
  export function combineExports(exports: Array<KubbFile.Export>): Array<KubbFile.Export> {
378
- const combinedExports = orderBy(exports, [(v) => !v.isTypeOnly], ['asc']).reduce(
251
+ const combinedExports = exports.reduce(
379
252
  (prev, curr) => {
380
253
  const name = curr.name
381
254
  const prevByPath = prev.findLast((imp) => imp.path === curr.path)
@@ -390,6 +263,7 @@ export function combineExports(exports: Array<KubbFile.Export>): Array<KubbFile.
390
263
  (imp) => imp.path === curr.path && isDeepEqual(imp.name, name) && imp.isTypeOnly === curr.isTypeOnly && imp.asAlias === curr.asAlias,
391
264
  )
392
265
 
266
+ // we already have an item that was unique enough or name field is empty or prev asAlias is set but current has no changes
393
267
  if (uniquePrev || (Array.isArray(name) && !name.length) || (prevByPath?.asAlias && !curr.asAlias)) {
394
268
  return prev
395
269
  }
@@ -404,6 +278,7 @@ export function combineExports(exports: Array<KubbFile.Export>): Array<KubbFile.
404
278
  ]
405
279
  }
406
280
 
281
+ // merge all names when prev and current both have the same isTypeOnly set
407
282
  if (prevByPath && Array.isArray(prevByPath.name) && Array.isArray(curr.name) && prevByPath.isTypeOnly === curr.isTypeOnly) {
408
283
  prevByPath.name = [...new Set([...prevByPath.name, ...curr.name])]
409
284
 
@@ -415,11 +290,17 @@ export function combineExports(exports: Array<KubbFile.Export>): Array<KubbFile.
415
290
  [] as Array<KubbFile.Export>,
416
291
  )
417
292
 
418
- return orderBy(combinedExports, [(v) => !v.isTypeOnly, (v) => v.asAlias], ['desc', 'desc'])
293
+ return orderBy(combinedExports, [
294
+ (v) => !!Array.isArray(v.name),
295
+ (v) => !v.isTypeOnly,
296
+ (v) => v.path,
297
+ (v) => !!v.name,
298
+ (v) => (Array.isArray(v.name) ? orderBy(v.name) : v.name),
299
+ ])
419
300
  }
420
301
 
421
302
  export function combineImports(imports: Array<KubbFile.Import>, exports: Array<KubbFile.Export>, source?: string): Array<KubbFile.Import> {
422
- const combinedImports = orderBy(imports, [(v) => !v.isTypeOnly], ['asc']).reduce(
303
+ const combinedImports = imports.reduce(
423
304
  (prev, curr) => {
424
305
  let name = Array.isArray(curr.name) ? [...new Set(curr.name)] : curr.name
425
306
 
@@ -438,6 +319,7 @@ export function combineImports(imports: Array<KubbFile.Import>, exports: Array<K
438
319
  return prev
439
320
  }
440
321
 
322
+ // merge all names and check if the importName is being used in the generated source and if not filter those imports out
441
323
  if (Array.isArray(name)) {
442
324
  name = name.filter((item) => (typeof item === 'string' ? hasImportInSource(item) : hasImportInSource(item.propertyName)))
443
325
  }
@@ -451,10 +333,12 @@ export function combineImports(imports: Array<KubbFile.Import>, exports: Array<K
451
333
  return prev
452
334
  }
453
335
 
336
+ // already unique enough or name is empty
454
337
  if (uniquePrev || (Array.isArray(name) && !name.length)) {
455
338
  return prev
456
339
  }
457
340
 
341
+ // new item, append name
458
342
  if (!prevByPath) {
459
343
  return [
460
344
  ...prev,
@@ -465,12 +349,14 @@ export function combineImports(imports: Array<KubbFile.Import>, exports: Array<K
465
349
  ]
466
350
  }
467
351
 
352
+ // merge all names when prev and current both have the same isTypeOnly set
468
353
  if (prevByPath && Array.isArray(prevByPath.name) && Array.isArray(name) && prevByPath.isTypeOnly === curr.isTypeOnly) {
469
354
  prevByPath.name = [...new Set([...prevByPath.name, ...name])]
470
355
 
471
356
  return prev
472
357
  }
473
358
 
359
+ // no import was found in the source, ignore import
474
360
  if (!Array.isArray(name) && name && !hasImportInSource(name)) {
475
361
  return prev
476
362
  }
@@ -480,43 +366,58 @@ export function combineImports(imports: Array<KubbFile.Import>, exports: Array<K
480
366
  [] as Array<KubbFile.Import>,
481
367
  )
482
368
 
483
- return orderBy(combinedImports, [(v) => !v.isTypeOnly], ['desc'])
369
+ return orderBy(combinedImports, [
370
+ (v) => !!Array.isArray(v.name),
371
+ (v) => !v.isTypeOnly,
372
+ (v) => v.path,
373
+ (v) => !!v.name,
374
+ (v) => (Array.isArray(v.name) ? orderBy(v.name) : v.name),
375
+ ])
376
+ }
377
+ type WriteFilesProps = {
378
+ config: Config
379
+ files: Array<KubbFile.ResolvedFile>
380
+ logger: Logger
381
+ dryRun?: boolean
484
382
  }
383
+ /**
384
+ * Global queue
385
+ */
386
+ const queue = new PQueue({ concurrency: 100 })
485
387
 
486
- function getEnvSource(source: string, env: NodeJS.ProcessEnv | undefined): string {
487
- if (!env) {
488
- return source
489
- }
388
+ export async function processFiles({ dryRun, config, logger, files }: WriteFilesProps) {
389
+ const orderedFiles = orderBy(files, [
390
+ (v) => v?.meta && 'pluginKey' in v.meta && !v.meta.pluginKey,
391
+ (v) => v.path.length,
392
+ (v) => trimExtName(v.path).endsWith('index'),
393
+ ])
490
394
 
491
- const keys = Object.keys(env)
395
+ logger.emit('debug', {
396
+ date: new Date(),
397
+ logs: [JSON.stringify({ files: orderedFiles }, null, 2)],
398
+ fileName: 'kubb-files.log',
399
+ })
492
400
 
493
- if (!keys.length) {
494
- return source
495
- }
401
+ if (!dryRun) {
402
+ const size = orderedFiles.length
496
403
 
497
- return keys.reduce((prev, key: string) => {
498
- const environmentValue = env[key]
499
- const replaceBy = environmentValue ? `'${environmentValue.replaceAll('"', '')?.replaceAll("'", '')}'` : 'undefined'
404
+ logger.emit('progress_start', { id: 'files', size, message: 'Writing files ...' })
405
+ const promises = orderedFiles.map(async (file) => {
406
+ await queue.add(async () => {
407
+ const message = file ? `Writing ${relative(config.root, file.path)}` : ''
500
408
 
501
- if (key.toUpperCase() !== key) {
502
- throw new TypeError(`Environment should be in upperCase for ${key}`)
503
- }
409
+ const source = await getSource(file, { logger })
504
410
 
505
- if (typeof replaceBy === 'string') {
506
- prev = searchAndReplace({
507
- text: prev.replaceAll(`process.env.${key}`, replaceBy),
508
- replaceBy,
509
- prefix: 'process.env',
510
- key,
511
- })
512
- // removes `declare const ...`
513
- prev = searchAndReplace({
514
- text: prev.replaceAll(/(declare const).*\n/gi, ''),
515
- replaceBy,
516
- key,
411
+ await write(file.path, source, { sanity: false })
412
+
413
+ logger.emit('progressed', { id: 'files', message })
517
414
  })
518
- }
415
+ })
416
+
417
+ await Promise.all(promises)
418
+
419
+ logger.emit('progress_stop', { id: 'files' })
420
+ }
519
421
 
520
- return prev
521
- }, source)
422
+ return files
522
423
  }
@@ -68,7 +68,7 @@ export class PackageManager {
68
68
 
69
69
  return module?.default ?? module
70
70
  } catch (e) {
71
- console.log(e)
71
+ console.error(e)
72
72
  return undefined
73
73
  }
74
74
  }