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

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 (102) 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 +96 -0
  4. package/dist/chunk-2EU7DMPM.js.map +1 -0
  5. package/dist/chunk-4X5FFJPJ.js +8 -13
  6. package/dist/chunk-4X5FFJPJ.js.map +1 -1
  7. package/dist/chunk-52WA2JF5.cjs +1536 -0
  8. package/dist/chunk-52WA2JF5.cjs.map +1 -0
  9. package/dist/chunk-ADFKVVPE.cjs +42 -0
  10. package/dist/chunk-ADFKVVPE.cjs.map +1 -0
  11. package/dist/{chunk-3OXCZ5DJ.js → chunk-E6CN2CZC.js} +63 -54
  12. package/dist/chunk-E6CN2CZC.js.map +1 -0
  13. package/dist/chunk-HBQM723K.js +1049 -0
  14. package/dist/chunk-HBQM723K.js.map +1 -0
  15. package/dist/{chunk-67C6RBGQ.cjs → chunk-HMCSWG5L.cjs} +25 -26
  16. package/dist/chunk-HMCSWG5L.cjs.map +1 -0
  17. package/dist/chunk-L6YLVCKM.js +894 -0
  18. package/dist/chunk-L6YLVCKM.js.map +1 -0
  19. package/dist/chunk-PJLUPV3P.cjs +1088 -0
  20. package/dist/chunk-PJLUPV3P.cjs.map +1 -0
  21. package/dist/chunk-TTDCUWK7.cjs +101 -0
  22. package/dist/chunk-TTDCUWK7.cjs.map +1 -0
  23. package/dist/{chunk-LM2YQC3T.cjs → chunk-YEVCYV36.cjs} +81 -51
  24. package/dist/chunk-YEVCYV36.cjs.map +1 -0
  25. package/dist/index.cjs +545 -610
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +6 -19
  28. package/dist/index.d.ts +6 -19
  29. package/dist/index.js +438 -522
  30. package/dist/index.js.map +1 -1
  31. package/dist/{logger-DChjnJMn.d.cts → logger-DvbHXjIO.d.cts} +29 -19
  32. package/dist/{logger-DChjnJMn.d.ts → logger-DvbHXjIO.d.ts} +29 -19
  33. package/dist/logger.cjs +25 -15
  34. package/dist/logger.cjs.map +1 -1
  35. package/dist/logger.d.cts +1 -2
  36. package/dist/logger.d.ts +1 -2
  37. package/dist/logger.js +3 -15
  38. package/dist/logger.js.map +1 -1
  39. package/dist/mocks.cjs +27 -26
  40. package/dist/mocks.cjs.map +1 -1
  41. package/dist/mocks.d.cts +6 -9
  42. package/dist/mocks.d.ts +6 -9
  43. package/dist/mocks.js +22 -24
  44. package/dist/mocks.js.map +1 -1
  45. package/dist/prompt-L5KFKY73.cjs +760 -0
  46. package/dist/prompt-L5KFKY73.cjs.map +1 -0
  47. package/dist/prompt-WQQUN22Z.js +749 -0
  48. package/dist/prompt-WQQUN22Z.js.map +1 -0
  49. package/dist/transformers.cjs +215 -49
  50. package/dist/transformers.cjs.map +1 -1
  51. package/dist/transformers.d.cts +1 -3
  52. package/dist/transformers.d.ts +1 -3
  53. package/dist/transformers.js +148 -35
  54. package/dist/transformers.js.map +1 -1
  55. package/dist/utils.cjs +65 -26
  56. package/dist/utils.cjs.map +1 -1
  57. package/dist/utils.d.cts +31 -3
  58. package/dist/utils.d.ts +31 -3
  59. package/dist/utils.js +3 -26
  60. package/dist/utils.js.map +1 -1
  61. package/package.json +10 -10
  62. package/src/BarrelManager.ts +93 -107
  63. package/src/{Generator.ts → BaseGenerator.ts} +1 -1
  64. package/src/FileManager.ts +198 -297
  65. package/src/PackageManager.ts +1 -1
  66. package/src/PluginManager.ts +152 -101
  67. package/src/__snapshots__/barrel.json +91 -0
  68. package/src/__snapshots__/grouped.json +114 -0
  69. package/src/__snapshots__/ordered.json +62 -0
  70. package/src/build.ts +86 -171
  71. package/src/errors.ts +0 -11
  72. package/src/index.ts +1 -2
  73. package/src/logger.ts +76 -34
  74. package/src/plugin.ts +3 -3
  75. package/src/transformers/index.ts +2 -3
  76. package/src/transformers/trim.ts +0 -4
  77. package/src/types.ts +35 -35
  78. package/src/utils/TreeNode.ts +132 -50
  79. package/src/utils/executeStrategies.ts +1 -1
  80. package/src/utils/index.ts +2 -1
  81. package/src/utils/parser.ts +157 -0
  82. package/dist/chunk-3OXCZ5DJ.js.map +0 -1
  83. package/dist/chunk-5JZNFPUP.js +0 -309
  84. package/dist/chunk-5JZNFPUP.js.map +0 -1
  85. package/dist/chunk-67C6RBGQ.cjs.map +0 -1
  86. package/dist/chunk-ADC5UNZ5.cjs +0 -1227
  87. package/dist/chunk-ADC5UNZ5.cjs.map +0 -1
  88. package/dist/chunk-HMLY7DHA.js +0 -16
  89. package/dist/chunk-HMLY7DHA.js.map +0 -1
  90. package/dist/chunk-JKZG2IJR.js +0 -283
  91. package/dist/chunk-JKZG2IJR.js.map +0 -1
  92. package/dist/chunk-LM2YQC3T.cjs.map +0 -1
  93. package/dist/chunk-PZT4CTBV.cjs +0 -299
  94. package/dist/chunk-PZT4CTBV.cjs.map +0 -1
  95. package/dist/chunk-SA2GZKXS.js +0 -596
  96. package/dist/chunk-SA2GZKXS.js.map +0 -1
  97. package/dist/chunk-XCPFG6DO.cjs +0 -66
  98. package/dist/chunk-XCPFG6DO.cjs.map +0 -1
  99. package/dist/chunk-YTSNYMHW.cjs +0 -320
  100. package/dist/chunk-YTSNYMHW.cjs.map +0 -1
  101. package/schema.json +0 -86
  102. package/src/utils/getParser.ts +0 -17
@@ -0,0 +1,114 @@
1
+ {
2
+ "name": "",
3
+ "path": "",
4
+ "children": [
5
+ {
6
+ "name": "src",
7
+ "path": "src",
8
+ "children": [
9
+ {
10
+ "name": "axios",
11
+ "path": "src/axios",
12
+ "children": [
13
+ {
14
+ "name": "file2.ts",
15
+ "file": {
16
+ "path": "src/axios/file2.ts",
17
+ "baseName": "file2.ts",
18
+ "sources": [],
19
+ "id": "6af477de6b602aafbb2e1ce0011b1f411a7ab3a5",
20
+ "name": "file2",
21
+ "extName": ".ts",
22
+ "imports": [],
23
+ "exports": []
24
+ },
25
+ "path": "src/axios/file2.ts"
26
+ },
27
+ {
28
+ "name": "file1.ts",
29
+ "file": {
30
+ "path": "src/axios/file1.ts",
31
+ "baseName": "file2.ts",
32
+ "sources": [],
33
+ "id": "a9679944d24c174b2f2fd5b1f19c9861f1d35d0e",
34
+ "name": "file2",
35
+ "extName": ".ts",
36
+ "imports": [],
37
+ "exports": []
38
+ },
39
+ "path": "src/axios/file1.ts"
40
+ },
41
+ {
42
+ "name": "controller",
43
+ "path": "src/axios/controller",
44
+ "children": [
45
+ {
46
+ "name": "pet.ts",
47
+ "file": {
48
+ "path": "src/axios/controller/pet.ts",
49
+ "baseName": "pet.ts",
50
+ "sources": [],
51
+ "id": "8beaaf5e1b1a6b89a11589c2e3dc5fd7f5eb5e8c",
52
+ "name": "pet",
53
+ "extName": ".ts",
54
+ "imports": [],
55
+ "exports": []
56
+ },
57
+ "path": "src/axios/controller/pet.ts"
58
+ }
59
+ ]
60
+ },
61
+ {
62
+ "name": "index.ts",
63
+ "file": {
64
+ "path": "src/axios/index.ts",
65
+ "baseName": "index.ts",
66
+ "sources": [],
67
+ "id": "b077038b83c1ef4050649be406937a73c1f41ad3",
68
+ "name": "index",
69
+ "extName": ".ts",
70
+ "imports": [],
71
+ "exports": []
72
+ },
73
+ "path": "src/axios/index.ts"
74
+ }
75
+ ]
76
+ },
77
+ {
78
+ "name": "controller",
79
+ "path": "src/controller",
80
+ "children": [
81
+ {
82
+ "name": "test.ts",
83
+ "file": {
84
+ "path": "src/controller/test.ts",
85
+ "baseName": "test.ts",
86
+ "sources": [],
87
+ "id": "a2d277093a81a74c56c0d094071195302d6bb484",
88
+ "name": "test",
89
+ "extName": ".ts",
90
+ "imports": [],
91
+ "exports": []
92
+ },
93
+ "path": "src/controller/test.ts"
94
+ }
95
+ ]
96
+ },
97
+ {
98
+ "name": "test.ts",
99
+ "file": {
100
+ "path": "src/test.ts",
101
+ "baseName": "test.ts",
102
+ "sources": [],
103
+ "id": "f8e2d98f76d6e33f21aa686d674544b5c7d6fa3e",
104
+ "name": "test",
105
+ "extName": ".ts",
106
+ "imports": [],
107
+ "exports": []
108
+ },
109
+ "path": "src/test.ts"
110
+ }
111
+ ]
112
+ }
113
+ ]
114
+ }
@@ -0,0 +1,62 @@
1
+ [
2
+ {
3
+ "path": "src/test.ts",
4
+ "baseName": "test.ts",
5
+ "sources": [],
6
+ "id": "f8e2d98f76d6e33f21aa686d674544b5c7d6fa3e",
7
+ "name": "test",
8
+ "extName": ".ts",
9
+ "imports": [],
10
+ "exports": []
11
+ },
12
+ {
13
+ "path": "src/axios/file2.ts",
14
+ "baseName": "file2.ts",
15
+ "sources": [],
16
+ "id": "6af477de6b602aafbb2e1ce0011b1f411a7ab3a5",
17
+ "name": "file2",
18
+ "extName": ".ts",
19
+ "imports": [],
20
+ "exports": []
21
+ },
22
+ {
23
+ "path": "src/axios/file1.ts",
24
+ "baseName": "file2.ts",
25
+ "sources": [],
26
+ "id": "a9679944d24c174b2f2fd5b1f19c9861f1d35d0e",
27
+ "name": "file2",
28
+ "extName": ".ts",
29
+ "imports": [],
30
+ "exports": []
31
+ },
32
+ {
33
+ "path": "src/axios/index.ts",
34
+ "baseName": "index.ts",
35
+ "sources": [],
36
+ "id": "b077038b83c1ef4050649be406937a73c1f41ad3",
37
+ "name": "index",
38
+ "extName": ".ts",
39
+ "imports": [],
40
+ "exports": []
41
+ },
42
+ {
43
+ "path": "src/controller/test.ts",
44
+ "baseName": "test.ts",
45
+ "sources": [],
46
+ "id": "a2d277093a81a74c56c0d094071195302d6bb484",
47
+ "name": "test",
48
+ "extName": ".ts",
49
+ "imports": [],
50
+ "exports": []
51
+ },
52
+ {
53
+ "path": "src/axios/controller/pet.ts",
54
+ "baseName": "pet.ts",
55
+ "sources": [],
56
+ "id": "8beaaf5e1b1a6b89a11589c2e3dc5fd7f5eb5e8c",
57
+ "name": "pet",
58
+ "extName": ".ts",
59
+ "imports": [],
60
+ "exports": []
61
+ }
62
+ ]
package/src/build.ts CHANGED
@@ -1,15 +1,15 @@
1
- import c from 'tinyrainbow'
2
-
3
1
  import { clean, read } from '@kubb/fs'
4
- import { FileManager, type ResolvedFile } from './FileManager.ts'
2
+ import type * as KubbFile from '@kubb/fs/types'
3
+ import { FileManager, processFiles } from './FileManager.ts'
5
4
  import { PluginManager } from './PluginManager.ts'
6
- import { isPromise } from './PromiseManager.ts'
7
5
  import { isInputPath } from './config.ts'
8
- import { LogLevel, createLogger, randomCliColour } from './logger.ts'
6
+ import { createLogger } from './logger.ts'
9
7
  import { URLPath } from './utils/URLPath.ts'
10
8
 
9
+ import { join, resolve } from 'node:path'
10
+ import { getRelativePath } from '@kubb/fs'
11
11
  import type { Logger } from './logger.ts'
12
- import type { Plugin, PluginContext, PluginParameter, TransformResult } from './types.ts'
12
+ import type { PluginContext } from './types.ts'
13
13
 
14
14
  type BuildOptions = {
15
15
  config: PluginContext['config']
@@ -28,18 +28,8 @@ type BuildOutput = {
28
28
  error?: Error
29
29
  }
30
30
 
31
- async function transformReducer(
32
- this: PluginContext,
33
- _previousCode: string,
34
- result: TransformResult | Promise<TransformResult>,
35
- _plugin: Plugin,
36
- ): Promise<string | null> {
37
- return result
38
- }
39
-
40
31
  async function setup(options: BuildOptions): Promise<PluginManager> {
41
- const { config, logger = createLogger({ logLevel: LogLevel.silent }) } = options
42
- let count = 0
32
+ const { config, logger = createLogger() } = options
43
33
 
44
34
  try {
45
35
  if (isInputPath(config) && !new URLPath(config.input.path).isURL) {
@@ -47,196 +37,121 @@ async function setup(options: BuildOptions): Promise<PluginManager> {
47
37
  }
48
38
  } catch (e) {
49
39
  if (isInputPath(config)) {
50
- throw new Error(
51
- `Cannot read file/URL defined in \`input.path\` or set with \`kubb generate PATH\` in the CLI of your Kubb config ${c.dim(config.input.path)}`,
52
- {
53
- cause: e,
54
- },
55
- )
40
+ throw new Error(`Cannot read file/URL defined in \`input.path\` or set with \`kubb generate PATH\` in the CLI of your Kubb config ${config.input.path}`, {
41
+ cause: e,
42
+ })
56
43
  }
57
44
  }
58
45
 
59
46
  if (config.output.clean) {
60
47
  await clean(config.output.path)
48
+ await clean(join(config.root, '.kubb'))
61
49
  }
62
50
 
63
- const task = async (file: ResolvedFile): Promise<ResolvedFile> => {
64
- const { path } = file
65
-
66
- let source: string | null = await FileManager.getSource(file)
67
-
68
- const { result: loadedResult } = await pluginManager.hookFirst({
69
- hookName: 'load',
70
- parameters: [path],
71
- })
72
- if (loadedResult && isPromise(loadedResult)) {
73
- source = await loadedResult
74
- }
75
- if (loadedResult && !isPromise(loadedResult)) {
76
- source = loadedResult
77
- }
78
-
79
- if (source) {
80
- source = await pluginManager.hookReduceArg0({
81
- hookName: 'transform',
82
- parameters: [path, source],
83
- reduce: transformReducer,
84
- })
85
-
86
- if (config.output.write || config.output.write === undefined) {
87
- if (file.meta?.pluginKey) {
88
- // run only for pluginKey defined in the meta of the file
89
- await pluginManager.hookForPlugin({
90
- pluginKey: file.meta?.pluginKey,
91
- hookName: 'writeFile',
92
- parameters: [path, source],
93
- })
94
- }
95
-
96
- await pluginManager.hookFirst({
97
- hookName: 'writeFile',
98
- parameters: [path, source],
99
- })
100
- }
101
- }
102
-
103
- return {
104
- ...file,
105
- source: source || '',
106
- }
107
- }
108
-
109
- const pluginManager = new PluginManager(config, { logger, task })
110
-
111
- pluginManager.on('execute', (executer) => {
112
- const { hookName, parameters, plugin } = executer
113
-
114
- if (hookName === 'writeFile') {
115
- const [code] = parameters as PluginParameter<'writeFile'>
116
-
117
- logger.emit('debug', [`PluginKey ${c.dim(JSON.stringify(plugin.key))} \nwith source\n\n${code}`])
118
- }
119
- })
120
-
121
- pluginManager.queue.on('add', () => {
122
- if (logger.logLevel !== LogLevel.info) {
123
- return
124
- }
125
-
126
- if (count === 0) {
127
- logger.emit('start', '💾 Writing')
128
- }
129
- })
130
-
131
- pluginManager.queue.on('active', () => {
132
- if (logger.logLevel !== LogLevel.info) {
133
- return
134
- }
135
-
136
- if (logger.spinner && pluginManager.queue.size > 0) {
137
- const text = `Item: ${count} Size: ${pluginManager.queue.size} Pending: ${pluginManager.queue.pending}`
138
-
139
- logger.spinner.suffixText = c.dim(text)
140
- }
141
- ++count
142
- })
143
-
144
- pluginManager.queue.on('completed', () => {
145
- if (logger.logLevel !== LogLevel.info) {
146
- return
147
- }
148
-
149
- if (logger.spinner) {
150
- const text = `Item: ${count} Size: ${pluginManager.queue.size} Pending: ${pluginManager.queue.pending}`
151
-
152
- logger.spinner.suffixText = c.dim(text)
153
- }
154
- })
155
-
156
- pluginManager.on('executed', (executer) => {
157
- const { hookName, plugin, output, parameters } = executer
158
-
159
- const logs = [
160
- `${randomCliColour(plugin.name)} Executing ${hookName}`,
161
- parameters && `${c.bgWhite('Parameters')} ${randomCliColour(plugin.name)} ${hookName}`,
162
- JSON.stringify(parameters, undefined, 2),
163
- output && `${c.bgWhite('Output')} ${randomCliColour(plugin.name)} ${hookName}`,
164
- output,
165
- ].filter(Boolean)
166
-
167
- logger.emit('debug', logs as string[])
168
- })
169
-
170
- return pluginManager
51
+ return new PluginManager(config, { logger })
171
52
  }
172
53
 
173
54
  export async function build(options: BuildOptions): Promise<BuildOutput> {
174
- const pluginManager = await setup(options)
175
-
176
- const { fileManager, logger } = pluginManager
177
-
178
- await pluginManager.hookParallel({
179
- hookName: 'buildStart',
180
- parameters: [options.config],
181
- })
55
+ const { files, pluginManager, error } = await safeBuild(options)
182
56
 
183
- await pluginManager.hookParallel({ hookName: 'buildEnd' })
184
-
185
- if (logger.logLevel === LogLevel.info) {
186
- logger.emit('end', '💾 Writing completed')
187
- }
188
-
189
- const files = await Promise.all(
190
- fileManager.files.map(async (file) => ({
191
- ...file,
192
- source: await FileManager.getSource(file),
193
- })),
194
- )
57
+ if (error) throw error
195
58
 
196
59
  return {
197
60
  files,
198
61
  pluginManager,
62
+ error,
199
63
  }
200
64
  }
201
65
 
202
66
  export async function safeBuild(options: BuildOptions): Promise<BuildOutput> {
67
+ let files = []
203
68
  const pluginManager = await setup(options)
204
69
 
205
- const { fileManager, logger } = pluginManager
206
-
207
70
  try {
71
+ pluginManager.events.on('executing', ({ plugin, message }) => {
72
+ pluginManager.logger.emit('debug', { date: new Date(), logs: [`Executing pluginKey ${plugin.key?.join('.')} | ${message}`] })
73
+ })
74
+
75
+ pluginManager.events.on('executed', ({ plugin, message, output }) => {
76
+ pluginManager.logger.emit('debug', {
77
+ date: new Date(),
78
+ logs: [`Executed pluginKey ${plugin.key?.join('.')} | ${message} | ${JSON.stringify(output, undefined, 2)}`],
79
+ })
80
+ })
81
+
208
82
  await pluginManager.hookParallel({
209
83
  hookName: 'buildStart',
210
84
  parameters: [options.config],
85
+ message: 'buildStart',
211
86
  })
212
87
 
213
- await pluginManager.hookParallel({ hookName: 'buildEnd' })
88
+ // create root barrel file
89
+ const root = resolve(options.config.root)
90
+ const rootPath = resolve(root, options.config.output.path, 'index.ts')
91
+ const barrelFiles = pluginManager.fileManager.files.filter((file) => {
92
+ return file.sources.some((source) => source.isIndexable)
93
+ })
214
94
 
215
- if (logger.logLevel === LogLevel.info) {
216
- logger.emit('end', '💾 Writing completed')
95
+ const rootFile: KubbFile.File = {
96
+ path: rootPath,
97
+ baseName: 'index.ts',
98
+ exports: barrelFiles
99
+ .flatMap((file) => {
100
+ return file.sources
101
+ ?.map((source) => {
102
+ if (!file.path || !source.isIndexable) {
103
+ return undefined
104
+ }
105
+
106
+ // validate of the file is coming from plugin x, needs pluginKey on every file TODO update typing
107
+ const plugin = pluginManager.plugins.find((item) => {
108
+ const meta = file.meta as any
109
+ return item.name === meta?.pluginKey?.[0]
110
+ })
111
+
112
+ if (plugin?.output?.exportType === false) {
113
+ return undefined
114
+ }
115
+
116
+ if (FileManager.getMode(plugin?.output?.path) === 'single') {
117
+ return undefined
118
+ }
119
+ return {
120
+ name: options.config.output.exportType === 'barrel' ? undefined : [source.name],
121
+ path: getRelativePath(rootPath, file.path),
122
+ isTypeOnly: source.isTypeOnly,
123
+ } as KubbFile.Export
124
+ })
125
+ .filter(Boolean)
126
+ })
127
+ .filter(Boolean),
128
+ sources: [],
129
+ meta: {},
217
130
  }
218
- } catch (e) {
219
- const files = await Promise.all(
220
- fileManager.files.map(async (file) => ({
221
- ...file,
222
- source: await FileManager.getSource(file),
223
- })),
224
- )
225
131
 
132
+ if (options.config.output.exportType) {
133
+ await pluginManager.fileManager.add(rootFile)
134
+ }
135
+
136
+ //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
137
+ files = await processFiles({
138
+ config: options.config,
139
+ dryRun: !options.config.output.write,
140
+ files: pluginManager.fileManager.files,
141
+ logger: pluginManager.logger,
142
+ })
143
+
144
+ await pluginManager.hookParallel({ hookName: 'buildEnd', message: `Build stopped for ${options.config.name}` })
145
+
146
+ pluginManager.fileManager.clear()
147
+ } catch (e) {
226
148
  return {
227
- files,
149
+ files: [],
228
150
  pluginManager,
229
151
  error: e as Error,
230
152
  }
231
153
  }
232
154
 
233
- const files = await Promise.all(
234
- fileManager.files.map(async (file) => ({
235
- ...file,
236
- source: await FileManager.getSource(file),
237
- })),
238
- )
239
-
240
155
  return {
241
156
  files,
242
157
  pluginManager,
package/src/errors.ts CHANGED
@@ -1,12 +1 @@
1
- /**
2
- * Behaves as an Error to log a warning in the console(still stops the execution)
3
- */
4
- export class Warning extends Error {
5
- constructor(message?: string, options?: { cause: Error }) {
6
- super(message, { cause: options?.cause })
7
-
8
- this.name = 'Warning'
9
- }
10
- }
11
-
12
1
  export class ValidationPluginError extends Error {}
package/src/index.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  export { build, build as default, safeBuild } from './build.ts'
2
2
  export { defineConfig, isInputPath } from './config.ts'
3
- export { Warning } from './errors.ts'
4
3
  export { FileManager } from './FileManager.ts'
5
4
  export type { FileMetaBase } from './FileManager.ts'
6
- export { Generator } from './Generator.ts'
5
+ export { BaseGenerator } from './BaseGenerator.ts'
7
6
  export { PackageManager } from './PackageManager.ts'
8
7
  export { createPlugin } from './plugin.ts'
9
8
  export { PluginManager } from './PluginManager.ts'
package/src/logger.ts CHANGED
@@ -3,16 +3,24 @@ import c, { createColors } from 'tinyrainbow'
3
3
 
4
4
  import { EventEmitter } from './utils/EventEmitter.ts'
5
5
 
6
- import type { ConsolaInstance } from 'consola'
7
- import type { Ora } from 'ora'
6
+ import { resolve } from 'node:path'
7
+ import { write } from '@kubb/fs'
8
+ import { type ConsolaInstance, type LogLevel, createConsola } from 'consola'
8
9
  import type { Formatter } from 'tinyrainbow'
9
10
 
10
- //TODO replace with verbose flag and debug flag
11
- export const LogLevel = {
12
- silent: 'silent',
13
- info: 'info',
14
- debug: 'debug',
15
- } as const
11
+ type DebugEvent = { date: Date; logs: string[]; fileName?: string }
12
+
13
+ type Events = {
14
+ start: [message: string]
15
+ success: [message: string]
16
+ error: [message: string, cause: Error]
17
+ warning: [message: string]
18
+ debug: [DebugEvent]
19
+ info: [message: string]
20
+ progress_start: [{ id: string; size: number; message?: string }]
21
+ progressed: [{ id: string; message?: string }]
22
+ progress_stop: [{ id: string }]
23
+ }
16
24
 
17
25
  export const LogMapper = {
18
26
  silent: Number.NEGATIVE_INFINITY,
@@ -20,54 +28,65 @@ export const LogMapper = {
20
28
  debug: 4,
21
29
  } as const
22
30
 
23
- export type LogLevel = keyof typeof LogLevel
24
-
25
- type Events = {
26
- start: [message: string]
27
- end: [message: string]
28
- error: [message: string, cause: Error]
29
- warning: [message: string]
30
- debug: [logs: string[]]
31
- }
32
31
  export type Logger = {
33
32
  /**
34
33
  * Optional config name to show in CLI output
35
34
  */
36
35
  name?: string
37
36
  logLevel: LogLevel
38
- spinner?: Ora
39
37
  consola?: ConsolaInstance
40
38
  on: EventEmitter<Events>['on']
41
39
  emit: EventEmitter<Events>['emit']
40
+ writeLogs: () => Promise<string[]>
42
41
  }
43
42
 
44
43
  type Props = {
45
44
  name?: string
46
- logLevel: LogLevel
47
- spinner?: Ora
45
+ logLevel?: LogLevel
48
46
  consola?: ConsolaInstance
49
47
  }
50
48
 
51
- export function createLogger({ logLevel, name, spinner, consola }: Props): Logger {
49
+ export function createLogger({ logLevel = 3, name, consola: _consola }: Props = {}): Logger {
52
50
  const events = new EventEmitter<Events>()
51
+ const startDate = Date.now()
52
+ const cachedLogs = new Set<DebugEvent>()
53
+
54
+ const consola =
55
+ _consola ||
56
+ createConsola({
57
+ level: logLevel,
58
+ formatOptions: {
59
+ colors: true,
60
+ date: true,
61
+ columns: 80,
62
+ compact: logLevel !== LogMapper.debug,
63
+ },
64
+ }).withTag(name ? randomCliColour(name) : '')
65
+
66
+ consola?.wrapConsole()
53
67
 
54
68
  events.on('start', (message) => {
55
- if (spinner) {
56
- spinner.start(message)
57
- }
69
+ consola.start(message)
58
70
  })
59
71
 
60
- events.on('end', (message) => {
61
- if (spinner) {
62
- spinner.suffixText = ''
63
- spinner.succeed(message)
64
- }
72
+ events.on('success', (message) => {
73
+ consola.success(message)
65
74
  })
66
75
 
67
76
  events.on('warning', (message) => {
68
- if (spinner) {
69
- spinner.warn(c.yellow(message))
77
+ consola.warn(c.yellow(message))
78
+ })
79
+
80
+ events.on('info', (message) => {
81
+ consola.info(c.yellow(message))
82
+ })
83
+
84
+ events.on('debug', (message) => {
85
+ if (message.logs.join('\n\n').length <= 100 && logLevel === LogMapper.debug) {
86
+ console.log(message.logs.join('\n\n'))
70
87
  }
88
+
89
+ cachedLogs.add(message)
71
90
  })
72
91
 
73
92
  events.on('error', (message, cause) => {
@@ -77,17 +96,40 @@ export function createLogger({ logLevel, name, spinner, consola }: Props): Logge
77
96
  throw error
78
97
  })
79
98
 
99
+ if (consola) {
100
+ consola.level = logLevel
101
+ }
102
+
80
103
  const logger: Logger = {
81
104
  name,
82
105
  logLevel,
83
- spinner,
84
106
  consola,
85
- on: (...args) => {
107
+ on(...args) {
86
108
  return events.on(...args)
87
109
  },
88
- emit: (...args) => {
110
+ emit(...args) {
89
111
  return events.emit(...args)
90
112
  },
113
+ async writeLogs() {
114
+ const files: Record<string, string[]> = {}
115
+
116
+ cachedLogs.forEach((log) => {
117
+ const fileName = resolve(process.cwd(), '.kubb', log.fileName || `kubb-${startDate}.log`)
118
+
119
+ if (!files[fileName]) {
120
+ files[fileName] = []
121
+ }
122
+
123
+ files[fileName] = [...files[fileName], `[${log.date.toLocaleString()}]: ${log.logs.join('\n\n')}`]
124
+ })
125
+ await Promise.all(
126
+ Object.entries(files).map(async ([fileName, logs]) => {
127
+ return write(fileName, logs.join('\n'))
128
+ }),
129
+ )
130
+
131
+ return Object.keys(files)
132
+ },
91
133
  }
92
134
 
93
135
  return logger