@kubb/core 3.0.0-alpha.3 → 3.0.0-alpha.30

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 (112) hide show
  1. package/README.md +13 -4
  2. package/dist/{FileManager-Bw-FNS3q.d.cts → FileManager-CqvmdzNO.d.cts} +128 -90
  3. package/dist/{FileManager-BW--rO8q.d.ts → FileManager-DIArE3b0.d.ts} +128 -90
  4. package/dist/chunk-2EU7DMPM.js +96 -0
  5. package/dist/chunk-2EU7DMPM.js.map +1 -0
  6. package/dist/{chunk-34BPAXR2.cjs → chunk-2UQARE2O.cjs} +54 -37
  7. package/dist/chunk-2UQARE2O.cjs.map +1 -0
  8. package/dist/chunk-4X5FFJPJ.js +8 -13
  9. package/dist/chunk-4X5FFJPJ.js.map +1 -1
  10. package/dist/{chunk-3OXCZ5DJ.js → chunk-E6CN2CZC.js} +63 -54
  11. package/dist/chunk-E6CN2CZC.js.map +1 -0
  12. package/dist/{chunk-25NKJ3DV.js → chunk-HBQM723K.js} +13 -27
  13. package/dist/chunk-HBQM723K.js.map +1 -0
  14. package/dist/{chunk-LM2YQC3T.cjs → chunk-LLKRRIBF.cjs} +81 -51
  15. package/dist/chunk-LLKRRIBF.cjs.map +1 -0
  16. package/dist/chunk-MD2LDZ3Z.js +889 -0
  17. package/dist/chunk-MD2LDZ3Z.js.map +1 -0
  18. package/dist/chunk-OX2X7B4Z.cjs +101 -0
  19. package/dist/chunk-OX2X7B4Z.cjs.map +1 -0
  20. package/dist/{chunk-67C6RBGQ.cjs → chunk-RIW2LFFQ.cjs} +28 -29
  21. package/dist/chunk-RIW2LFFQ.cjs.map +1 -0
  22. package/dist/chunk-SX5FHSVT.cjs +1532 -0
  23. package/dist/chunk-SX5FHSVT.cjs.map +1 -0
  24. package/dist/chunk-VBGWLAET.cjs +42 -0
  25. package/dist/chunk-VBGWLAET.cjs.map +1 -0
  26. package/dist/index.cjs +553 -619
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +7 -22
  29. package/dist/index.d.ts +7 -22
  30. package/dist/index.js +444 -525
  31. package/dist/index.js.map +1 -1
  32. package/dist/{logger-DChjnJMn.d.cts → logger-DvbHXjIO.d.cts} +29 -19
  33. package/dist/{logger-DChjnJMn.d.ts → logger-DvbHXjIO.d.ts} +29 -19
  34. package/dist/logger.cjs +25 -15
  35. package/dist/logger.cjs.map +1 -1
  36. package/dist/logger.d.cts +1 -2
  37. package/dist/logger.d.ts +1 -2
  38. package/dist/logger.js +3 -15
  39. package/dist/logger.js.map +1 -1
  40. package/dist/mocks.cjs +42 -31
  41. package/dist/mocks.cjs.map +1 -1
  42. package/dist/mocks.d.cts +7 -9
  43. package/dist/mocks.d.ts +7 -9
  44. package/dist/mocks.js +35 -33
  45. package/dist/mocks.js.map +1 -1
  46. package/dist/{prompt-6FWP747F.cjs → prompt-2PN2F25D.cjs} +89 -89
  47. package/dist/prompt-2PN2F25D.cjs.map +1 -0
  48. package/dist/{prompt-HK3MWREM.js → prompt-WQQUN22Z.js} +9 -15
  49. package/dist/prompt-WQQUN22Z.js.map +1 -0
  50. package/dist/transformers.cjs +216 -49
  51. package/dist/transformers.cjs.map +1 -1
  52. package/dist/transformers.d.cts +2 -4
  53. package/dist/transformers.d.ts +2 -4
  54. package/dist/transformers.js +149 -35
  55. package/dist/transformers.js.map +1 -1
  56. package/dist/utils.cjs +65 -26
  57. package/dist/utils.cjs.map +1 -1
  58. package/dist/utils.d.cts +29 -3
  59. package/dist/utils.d.ts +29 -3
  60. package/dist/utils.js +3 -26
  61. package/dist/utils.js.map +1 -1
  62. package/package.json +11 -14
  63. package/src/BarrelManager.ts +95 -109
  64. package/src/{Generator.ts → BaseGenerator.ts} +1 -1
  65. package/src/FileManager.ts +199 -304
  66. package/src/PackageManager.ts +1 -1
  67. package/src/PluginManager.ts +152 -93
  68. package/src/PromiseManager.ts +1 -1
  69. package/src/__snapshots__/barrel.json +73 -0
  70. package/src/__snapshots__/grouped.json +120 -0
  71. package/src/__snapshots__/ordered.json +68 -0
  72. package/src/build.ts +86 -131
  73. package/src/config.ts +2 -4
  74. package/src/errors.ts +0 -11
  75. package/src/index.ts +2 -3
  76. package/src/logger.ts +76 -34
  77. package/src/plugin.ts +2 -5
  78. package/src/transformers/escape.ts +0 -10
  79. package/src/transformers/index.ts +2 -3
  80. package/src/transformers/stringify.ts +1 -1
  81. package/src/transformers/trim.ts +0 -4
  82. package/src/types.ts +52 -20
  83. package/src/utils/TreeNode.ts +132 -50
  84. package/src/utils/executeStrategies.ts +3 -3
  85. package/src/utils/index.ts +2 -1
  86. package/src/utils/parser.ts +156 -0
  87. package/dist/chunk-25NKJ3DV.js.map +0 -1
  88. package/dist/chunk-34BPAXR2.cjs.map +0 -1
  89. package/dist/chunk-3OXCZ5DJ.js.map +0 -1
  90. package/dist/chunk-5JZNFPUP.js +0 -309
  91. package/dist/chunk-5JZNFPUP.js.map +0 -1
  92. package/dist/chunk-67C6RBGQ.cjs.map +0 -1
  93. package/dist/chunk-ADC5UNZ5.cjs +0 -1227
  94. package/dist/chunk-ADC5UNZ5.cjs.map +0 -1
  95. package/dist/chunk-HMLY7DHA.js +0 -16
  96. package/dist/chunk-HMLY7DHA.js.map +0 -1
  97. package/dist/chunk-JKZG2IJR.js +0 -283
  98. package/dist/chunk-JKZG2IJR.js.map +0 -1
  99. package/dist/chunk-LM2YQC3T.cjs.map +0 -1
  100. package/dist/chunk-PZT4CTBV.cjs +0 -299
  101. package/dist/chunk-PZT4CTBV.cjs.map +0 -1
  102. package/dist/chunk-SA2GZKXS.js +0 -596
  103. package/dist/chunk-SA2GZKXS.js.map +0 -1
  104. package/dist/chunk-XCPFG6DO.cjs +0 -66
  105. package/dist/chunk-XCPFG6DO.cjs.map +0 -1
  106. package/dist/chunk-YTSNYMHW.cjs +0 -320
  107. package/dist/chunk-YTSNYMHW.cjs.map +0 -1
  108. package/dist/prompt-6FWP747F.cjs.map +0 -1
  109. package/dist/prompt-HK3MWREM.js.map +0 -1
  110. package/schema.json +0 -86
  111. package/src/utils/cache.ts +0 -35
  112. package/src/utils/getParser.ts +0 -17
@@ -0,0 +1,120 @@
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
+ "meta": {}
25
+ },
26
+ "path": "src/axios/file2.ts"
27
+ },
28
+ {
29
+ "name": "file1.ts",
30
+ "file": {
31
+ "path": "src/axios/file1.ts",
32
+ "baseName": "file2.ts",
33
+ "sources": [],
34
+ "id": "a9679944d24c174b2f2fd5b1f19c9861f1d35d0e",
35
+ "name": "file2",
36
+ "extname": ".ts",
37
+ "imports": [],
38
+ "exports": [],
39
+ "meta": {}
40
+ },
41
+ "path": "src/axios/file1.ts"
42
+ },
43
+ {
44
+ "name": "controller",
45
+ "path": "src/axios/controller",
46
+ "children": [
47
+ {
48
+ "name": "pet.ts",
49
+ "file": {
50
+ "path": "src/axios/controller/pet.ts",
51
+ "baseName": "pet.ts",
52
+ "sources": [],
53
+ "id": "8beaaf5e1b1a6b89a11589c2e3dc5fd7f5eb5e8c",
54
+ "name": "pet",
55
+ "extname": ".ts",
56
+ "imports": [],
57
+ "exports": [],
58
+ "meta": {}
59
+ },
60
+ "path": "src/axios/controller/pet.ts"
61
+ }
62
+ ]
63
+ },
64
+ {
65
+ "name": "index.ts",
66
+ "file": {
67
+ "path": "src/axios/index.ts",
68
+ "baseName": "index.ts",
69
+ "sources": [],
70
+ "id": "b077038b83c1ef4050649be406937a73c1f41ad3",
71
+ "name": "index",
72
+ "extname": ".ts",
73
+ "imports": [],
74
+ "exports": [],
75
+ "meta": {}
76
+ },
77
+ "path": "src/axios/index.ts"
78
+ }
79
+ ]
80
+ },
81
+ {
82
+ "name": "controller",
83
+ "path": "src/controller",
84
+ "children": [
85
+ {
86
+ "name": "test.ts",
87
+ "file": {
88
+ "path": "src/controller/test.ts",
89
+ "baseName": "test.ts",
90
+ "sources": [],
91
+ "id": "a2d277093a81a74c56c0d094071195302d6bb484",
92
+ "name": "test",
93
+ "extname": ".ts",
94
+ "imports": [],
95
+ "exports": [],
96
+ "meta": {}
97
+ },
98
+ "path": "src/controller/test.ts"
99
+ }
100
+ ]
101
+ },
102
+ {
103
+ "name": "test.ts",
104
+ "file": {
105
+ "path": "src/test.ts",
106
+ "baseName": "test.ts",
107
+ "sources": [],
108
+ "id": "f8e2d98f76d6e33f21aa686d674544b5c7d6fa3e",
109
+ "name": "test",
110
+ "extname": ".ts",
111
+ "imports": [],
112
+ "exports": [],
113
+ "meta": {}
114
+ },
115
+ "path": "src/test.ts"
116
+ }
117
+ ]
118
+ }
119
+ ]
120
+ }
@@ -0,0 +1,68 @@
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
+ "meta": {}
12
+ },
13
+ {
14
+ "path": "src/axios/file2.ts",
15
+ "baseName": "file2.ts",
16
+ "sources": [],
17
+ "id": "6af477de6b602aafbb2e1ce0011b1f411a7ab3a5",
18
+ "name": "file2",
19
+ "extname": ".ts",
20
+ "imports": [],
21
+ "exports": [],
22
+ "meta": {}
23
+ },
24
+ {
25
+ "path": "src/axios/file1.ts",
26
+ "baseName": "file2.ts",
27
+ "sources": [],
28
+ "id": "a9679944d24c174b2f2fd5b1f19c9861f1d35d0e",
29
+ "name": "file2",
30
+ "extname": ".ts",
31
+ "imports": [],
32
+ "exports": [],
33
+ "meta": {}
34
+ },
35
+ {
36
+ "path": "src/axios/index.ts",
37
+ "baseName": "index.ts",
38
+ "sources": [],
39
+ "id": "b077038b83c1ef4050649be406937a73c1f41ad3",
40
+ "name": "index",
41
+ "extname": ".ts",
42
+ "imports": [],
43
+ "exports": [],
44
+ "meta": {}
45
+ },
46
+ {
47
+ "path": "src/controller/test.ts",
48
+ "baseName": "test.ts",
49
+ "sources": [],
50
+ "id": "a2d277093a81a74c56c0d094071195302d6bb484",
51
+ "name": "test",
52
+ "extname": ".ts",
53
+ "imports": [],
54
+ "exports": [],
55
+ "meta": {}
56
+ },
57
+ {
58
+ "path": "src/axios/controller/pet.ts",
59
+ "baseName": "pet.ts",
60
+ "sources": [],
61
+ "id": "8beaaf5e1b1a6b89a11589c2e3dc5fd7f5eb5e8c",
62
+ "name": "pet",
63
+ "extname": ".ts",
64
+ "imports": [],
65
+ "exports": [],
66
+ "meta": {}
67
+ }
68
+ ]
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
5
  import { isInputPath } from './config.ts'
7
- import { LogLevel, createLogger, randomCliColour, LogMapper } from './logger.ts'
6
+ import { createLogger } from './logger.ts'
8
7
  import { URLPath } from './utils/URLPath.ts'
9
8
 
9
+ import { join, resolve } from 'node:path'
10
+ import { getRelativePath } from '@kubb/fs'
10
11
  import type { Logger } from './logger.ts'
11
- import type { PluginContext } from './types.ts'
12
- import { createConsola } from 'consola'
12
+ import type { Output, PluginContext } from './types.ts'
13
13
 
14
14
  type BuildOptions = {
15
15
  config: PluginContext['config']
@@ -29,16 +29,7 @@ type BuildOutput = {
29
29
  }
30
30
 
31
31
  async function setup(options: BuildOptions): Promise<PluginManager> {
32
- const {
33
- config,
34
- logger = createLogger({
35
- logLevel: LogLevel.silent,
36
- consola: createConsola({
37
- level: 3,
38
- }),
39
- }),
40
- } = options
41
- let count = 0
32
+ const { config, logger = createLogger() } = options
42
33
 
43
34
  try {
44
35
  if (isInputPath(config) && !new URLPath(config.input.path).isURL) {
@@ -46,157 +37,121 @@ async function setup(options: BuildOptions): Promise<PluginManager> {
46
37
  }
47
38
  } catch (e) {
48
39
  if (isInputPath(config)) {
49
- throw new Error(
50
- `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)}`,
51
- {
52
- cause: e,
53
- },
54
- )
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
+ })
55
43
  }
56
44
  }
57
45
 
58
46
  if (config.output.clean) {
59
47
  await clean(config.output.path)
48
+ await clean(join(config.root, '.kubb'))
60
49
  }
61
50
 
62
- const task = async (file: ResolvedFile): Promise<ResolvedFile> => {
63
- const { path } = file
64
-
65
- const source: string | null = await FileManager.getSource(file)
66
-
67
- if (source) {
68
- if (config.output.write || config.output.write === undefined) {
69
- await pluginManager.fileManager.write(path, source, { sanity: false })
70
- }
71
- }
72
-
73
- return {
74
- ...file,
75
- source: source || '',
76
- }
77
- }
78
-
79
- const pluginManager = new PluginManager(config, { logger, task })
80
-
81
- pluginManager.queue.on('add', () => {
82
- if (logger.logLevel !== LogLevel.info) {
83
- return
84
- }
85
-
86
- if (count === 0) {
87
- logger.emit('start', '💾 Writing')
88
- }
89
- })
90
-
91
- pluginManager.queue.on('active', () => {
92
- if (logger.logLevel !== LogLevel.info) {
93
- return
94
- }
95
-
96
- if (logger.spinner && pluginManager.queue.size > 0) {
97
- const text = `Item: ${count} Size: ${pluginManager.queue.size} Pending: ${pluginManager.queue.pending}`
98
-
99
- logger.spinner.suffixText = c.dim(text)
100
- }
101
- ++count
102
- })
103
-
104
- pluginManager.queue.on('completed', () => {
105
- if (logger.logLevel !== LogLevel.info) {
106
- return
107
- }
108
-
109
- if (logger.spinner) {
110
- const text = `Item: ${count} Size: ${pluginManager.queue.size} Pending: ${pluginManager.queue.pending}`
111
-
112
- logger.spinner.suffixText = c.dim(text)
113
- }
114
- })
115
-
116
- pluginManager.on('executed', (executer) => {
117
- const { hookName, plugin, output, parameters } = executer
118
-
119
- const logs = [
120
- `${randomCliColour(plugin.name)} Executing ${hookName}`,
121
- parameters && `${c.bgWhite('Parameters')} ${randomCliColour(plugin.name)} ${hookName}`,
122
- JSON.stringify(parameters, undefined, 2),
123
- output && `${c.bgWhite('Output')} ${randomCliColour(plugin.name)} ${hookName}`,
124
- output,
125
- ].filter(Boolean)
126
-
127
- logger.emit('debug', logs as string[])
128
- })
129
-
130
- return pluginManager
51
+ return new PluginManager(config, { logger })
131
52
  }
132
53
 
133
54
  export async function build(options: BuildOptions): Promise<BuildOutput> {
134
- const pluginManager = await setup(options)
135
-
136
- const { fileManager, logger } = pluginManager
137
-
138
- await pluginManager.hookParallel({
139
- hookName: 'buildStart',
140
- parameters: [options.config],
141
- })
55
+ const { files, pluginManager, error } = await safeBuild(options)
142
56
 
143
- await pluginManager.hookParallel({ hookName: 'buildEnd' })
144
-
145
- if (logger.logLevel === LogLevel.info) {
146
- logger.emit('end', '💾 Writing completed')
147
- }
148
-
149
- const files = await Promise.all(
150
- fileManager.files.map(async (file) => ({
151
- ...file,
152
- source: await FileManager.getSource(file),
153
- })),
154
- )
57
+ if (error) throw error
155
58
 
156
59
  return {
157
60
  files,
158
61
  pluginManager,
62
+ error,
159
63
  }
160
64
  }
161
65
 
162
66
  export async function safeBuild(options: BuildOptions): Promise<BuildOutput> {
67
+ let files = []
163
68
  const pluginManager = await setup(options)
164
69
 
165
- const { fileManager, logger } = pluginManager
166
-
167
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
+
168
82
  await pluginManager.hookParallel({
169
83
  hookName: 'buildStart',
170
84
  parameters: [options.config],
85
+ message: 'buildStart',
86
+ })
87
+
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)
171
93
  })
172
94
 
173
- await pluginManager.hookParallel({ hookName: 'buildEnd' })
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.key === meta?.pluginKey
110
+ })
111
+ const pluginOptions = (plugin?.options as { output?: Output }) ?? {}
112
+
113
+ if (pluginOptions.output?.barrelType === false) {
114
+ return undefined
115
+ }
116
+
117
+ if (FileManager.getMode(pluginOptions.output?.path) === 'single') {
118
+ return undefined
119
+ }
120
+ return {
121
+ name: pluginOptions.output?.barrelType === 'all' ? undefined : [source.name],
122
+ path: getRelativePath(rootPath, file.path),
123
+ isTypeOnly: source.isTypeOnly,
124
+ } as KubbFile.Export
125
+ })
126
+ .filter(Boolean)
127
+ })
128
+ .filter(Boolean),
129
+ sources: [],
130
+ meta: {},
131
+ }
174
132
 
175
- if (logger.logLevel === LogLevel.info) {
176
- logger.emit('end', '💾 Writing completed')
133
+ if (options.config.output.barrelType) {
134
+ await pluginManager.fileManager.add(rootFile)
177
135
  }
178
- } catch (e) {
179
- const files = await Promise.all(
180
- fileManager.files.map(async (file) => ({
181
- ...file,
182
- source: await FileManager.getSource(file),
183
- })),
184
- )
185
136
 
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) {
186
148
  return {
187
- files,
149
+ files: [],
188
150
  pluginManager,
189
151
  error: e as Error,
190
152
  }
191
153
  }
192
154
 
193
- const files = await Promise.all(
194
- fileManager.files.map(async (file) => ({
195
- ...file,
196
- source: await FileManager.getSource(file),
197
- })),
198
- )
199
-
200
155
  return {
201
156
  files,
202
157
  pluginManager,
package/src/config.ts CHANGED
@@ -29,9 +29,7 @@ type Args = {
29
29
  }
30
30
 
31
31
  /**
32
- * Type helper to make it easier to use kubb.config.js
33
- * accepts a direct {@link Config} object, or a function that returns it.
34
- * The function receives a {@link ConfigEnv} object that exposes two properties:
32
+ * Type helper to make it easier to use vite.config.ts accepts a direct UserConfig object, or a function that returns it. The function receives a ConfigEnv object.
35
33
  */
36
34
  export function defineConfig(
37
35
  options:
@@ -45,5 +43,5 @@ export function defineConfig(
45
43
  }
46
44
 
47
45
  export function isInputPath(result: Config | undefined): result is Config<InputPath> {
48
- return !!result && 'path' in (result as any)
46
+ return !!result && 'path' in (result?.input as any)
49
47
  }
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
- export { FileManager } from './FileManager.ts'
3
+ export { FileManager, getSource } 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