@kubb/cli 4.11.2 → 4.12.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 (52) hide show
  1. package/dist/generate-BujndwJK.cjs +1256 -0
  2. package/dist/generate-BujndwJK.cjs.map +1 -0
  3. package/dist/generate-BvrG5K00.js +1249 -0
  4. package/dist/generate-BvrG5K00.js.map +1 -0
  5. package/dist/index.cjs +9 -35
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.js +7 -30
  8. package/dist/index.js.map +1 -1
  9. package/dist/{mcp-BIRDY8xn.js → mcp-LLlOFV3c.js} +5 -6
  10. package/dist/mcp-LLlOFV3c.js.map +1 -0
  11. package/dist/{mcp-BQjDRDXR.cjs → mcp-N1IVyiXf.cjs} +5 -7
  12. package/dist/mcp-N1IVyiXf.cjs.map +1 -0
  13. package/dist/package-Bhc6C7cQ.js +6 -0
  14. package/dist/package-Bhc6C7cQ.js.map +1 -0
  15. package/dist/package-KuCpJxHt.cjs +12 -0
  16. package/dist/package-KuCpJxHt.cjs.map +1 -0
  17. package/dist/{validate-0i6Q9eIy.js → validate-BptoQ-63.js} +5 -6
  18. package/dist/validate-BptoQ-63.js.map +1 -0
  19. package/dist/{validate-6F-VPZR7.cjs → validate-Dn6hZ7Z4.cjs} +5 -7
  20. package/dist/validate-Dn6hZ7Z4.cjs.map +1 -0
  21. package/package.json +7 -7
  22. package/src/commands/generate.ts +52 -65
  23. package/src/commands/mcp.ts +4 -5
  24. package/src/commands/validate.ts +4 -5
  25. package/src/index.ts +8 -23
  26. package/src/loggers/clackLogger.ts +433 -0
  27. package/src/loggers/envDetection.ts +28 -0
  28. package/src/loggers/fileSystemLogger.ts +79 -0
  29. package/src/loggers/githubActionsLogger.ts +310 -0
  30. package/src/loggers/index.ts +7 -0
  31. package/src/loggers/plainLogger.ts +274 -0
  32. package/src/loggers/types.ts +1 -0
  33. package/src/loggers/utils.ts +49 -0
  34. package/src/runners/generate.ts +196 -208
  35. package/src/utils/Writables.ts +12 -8
  36. package/src/utils/executeHooks.ts +11 -18
  37. package/src/utils/getCosmiConfig.ts +6 -1
  38. package/src/utils/getSummary.ts +20 -42
  39. package/src/utils/randomColour.ts +26 -0
  40. package/src/utils/watcher.ts +2 -4
  41. package/dist/generate-CYBFB3tU.js +0 -221
  42. package/dist/generate-CYBFB3tU.js.map +0 -1
  43. package/dist/generate-CpBJ2Y-n.js +0 -342
  44. package/dist/generate-CpBJ2Y-n.js.map +0 -1
  45. package/dist/generate-DpHvARzf.cjs +0 -345
  46. package/dist/generate-DpHvARzf.cjs.map +0 -1
  47. package/dist/generate-KUqCSnZp.cjs +0 -225
  48. package/dist/generate-KUqCSnZp.cjs.map +0 -1
  49. package/dist/mcp-BIRDY8xn.js.map +0 -1
  50. package/dist/mcp-BQjDRDXR.cjs.map +0 -1
  51. package/dist/validate-0i6Q9eIy.js.map +0 -1
  52. package/dist/validate-6F-VPZR7.cjs.map +0 -1
@@ -1,64 +1,21 @@
1
1
  import path from 'node:path'
2
2
  import process from 'node:process'
3
- import { type Config, safeBuild, setup } from '@kubb/core'
4
- import { createLogger, LogMapper } from '@kubb/core/logger'
5
- import { Presets, SingleBar } from 'cli-progress'
6
- import { execa } from 'execa'
3
+ import { type Config, type KubbEvents, LogLevel, safeBuild, setup } from '@kubb/core'
4
+ import type { AsyncEventEmitter } from '@kubb/core/utils'
7
5
  import pc from 'picocolors'
8
- import type { Args } from '../commands/generate.ts'
9
6
  import { executeHooks } from '../utils/executeHooks.ts'
10
- import { getSummary } from '../utils/getSummary.ts'
11
7
 
12
8
  type GenerateProps = {
13
9
  input?: string
14
10
  config: Config
15
- args: Args
16
- progressCache: Map<string, SingleBar>
11
+ events: AsyncEventEmitter<KubbEvents>
12
+ logLevel: number
17
13
  }
18
14
 
19
- export async function generate({ input, config, progressCache, args }: GenerateProps): Promise<void> {
20
- const hrStart = process.hrtime()
21
- const logLevel = LogMapper[args.logLevel as keyof typeof LogMapper] || 3
22
-
23
- const logger = createLogger({
24
- logLevel,
25
- name: config.name,
26
- })
27
-
15
+ export async function generate({ input, config, events, logLevel }: GenerateProps): Promise<void> {
28
16
  const { root = process.cwd(), ...userConfig } = config
29
17
  const inputPath = input ?? ('path' in userConfig.input ? userConfig.input.path : undefined)
30
-
31
- if (logger.logLevel !== LogMapper.debug) {
32
- logger.on('progress_start', ({ id, size, message = '' }) => {
33
- logger.consola?.pauseLogs()
34
- const payload = { id, message }
35
- const progressBar = new SingleBar(
36
- {
37
- format: '{percentage}% {bar} {value}/{total} | {message}',
38
- barsize: 30,
39
- clearOnComplete: true,
40
- emptyOnZero: true,
41
- },
42
- Presets.shades_grey,
43
- )
44
-
45
- if (!progressCache.has(id)) {
46
- progressCache.set(id, progressBar)
47
- progressBar.start(size, 1, payload)
48
- }
49
- })
50
-
51
- logger.on('progress_stop', ({ id }) => {
52
- progressCache.get(id)?.stop()
53
- logger.consola?.resumeLogs()
54
- })
55
-
56
- logger.on('progressed', ({ id, message = '' }) => {
57
- const payload = { id, message }
58
-
59
- progressCache.get(id)?.increment(1, payload)
60
- })
61
- }
18
+ const hrStart = process.hrtime()
62
19
 
63
20
  const definedConfig: Config = {
64
21
  root,
@@ -80,45 +37,31 @@ export async function generate({ input, config, progressCache, args }: GenerateP
80
37
  },
81
38
  }
82
39
 
40
+ await events.emit('generation:start', definedConfig)
41
+
42
+ await events.emit('info', config.name ? `Setup generation ${pc.bold(config.name)}` : 'Setup generation', inputPath)
43
+
83
44
  const { fabric, pluginManager } = await setup({
84
45
  config: definedConfig,
85
- logger,
46
+ events,
86
47
  })
87
48
 
88
- logger.emit('start', `Building ${logger.logLevel !== LogMapper.silent ? pc.dim(inputPath!) : ''}`)
49
+ await events.emit('info', config.name ? `Build generation ${pc.bold(config.name)}` : 'Build generation', inputPath)
89
50
 
90
51
  const { files, failedPlugins, pluginTimings, error } = await safeBuild(
91
52
  {
92
53
  config: definedConfig,
93
- logger,
54
+ events,
94
55
  },
95
- { pluginManager, fabric, logger },
56
+ { pluginManager, fabric, events },
96
57
  )
97
58
 
98
- if (logger.logLevel >= LogMapper.debug) {
99
- logger.consola?.start('Writing logs')
100
-
101
- await logger.writeLogs()
102
-
103
- logger.consola?.success('Written logs')
104
- }
105
-
106
- const summary = getSummary({
107
- failedPlugins,
108
- filesCreated: files.length,
109
- config: definedConfig,
110
- status: failedPlugins.size > 0 || error ? 'failed' : 'success',
111
- hrStart,
112
- pluginTimings: logger.logLevel >= LogMapper.verbose ? pluginTimings : undefined,
113
- })
59
+ await events.emit('info', 'Load summary')
114
60
 
115
61
  // Handle build failures (either from failed plugins or general errors)
116
- const hasFailures = failedPlugins.size > 0 || error
117
-
118
- if (hasFailures && logger.consola) {
119
- logger.consola?.resumeLogs()
120
- logger.consola?.log(`✗ Build failed ${logger.logLevel !== LogMapper.silent ? pc.dim(inputPath!) : ''}`)
121
62
 
63
+ const hasFailures = failedPlugins.size > 0 || error
64
+ if (hasFailures) {
122
65
  // Collect all errors from failed plugins and general error
123
66
  const allErrors: Error[] = [
124
67
  error,
@@ -128,166 +71,211 @@ export async function generate({ input, config, progressCache, args }: GenerateP
128
71
  ].filter(Boolean)
129
72
 
130
73
  allErrors.forEach((err) => {
131
- // Display error causes in debug mode
132
- if (logger.logLevel >= LogMapper.debug && err.cause) {
133
- logger.consola?.error(err.cause)
134
- }
135
-
136
- logger.consola?.error(err)
74
+ events.emit('error', err)
137
75
  })
138
76
 
139
- logger.consola?.box({
140
- title: `${config.name || ''}`,
141
- message: summary.join(''),
142
- style: {
143
- padding: 2,
144
- borderColor: 'red',
145
- borderStyle: 'rounded',
146
- },
77
+ await events.emit('generation:end', definedConfig)
78
+
79
+ await events.emit('generation:summary', definedConfig, {
80
+ failedPlugins,
81
+ filesCreated: files.length,
82
+ status: failedPlugins.size > 0 || error ? 'failed' : 'success',
83
+ hrStart,
84
+ pluginTimings: logLevel >= LogLevel.verbose ? pluginTimings : undefined,
147
85
  })
148
86
 
149
87
  process.exit(1)
150
88
  }
151
89
 
90
+ await events.emit('success', 'Generation successfully', inputPath)
91
+ await events.emit('generation:end', definedConfig)
92
+
152
93
  // formatting
153
- if (config.output.format === 'prettier') {
154
- logger?.emit('start', `Formatting with ${config.output.format}`)
155
- logger?.emit('debug', {
156
- date: new Date(),
157
- logs: [`Running prettier on ${path.resolve(definedConfig.root, definedConfig.output.path)}`],
158
- })
94
+ if (config.output.format) {
95
+ await events.emit('format:start')
96
+
97
+ await events.emit(
98
+ 'info',
99
+ [
100
+ `Formatting with ${pc.dim(config.output.format as string)}`,
101
+ logLevel >= LogLevel.info ? `on ${pc.dim(path.resolve(definedConfig.root, definedConfig.output.path))}` : undefined,
102
+ ]
103
+ .filter(Boolean)
104
+ .join(' '),
105
+ )
106
+
107
+ if (config.output.format === 'prettier') {
108
+ try {
109
+ await events.emit(
110
+ 'hook:execute',
111
+ {
112
+ command: 'prettier',
113
+ args: ['--ignore-unknown', '--write', path.resolve(definedConfig.root, definedConfig.output.path)],
114
+ },
115
+ async () => {
116
+ await events.emit(
117
+ 'success',
118
+ [
119
+ `Formatting with ${pc.dim(config.output.format as string)}`,
120
+ logLevel >= LogLevel.info ? `on ${pc.dim(path.resolve(definedConfig.root, definedConfig.output.path))}` : undefined,
121
+ 'successfully',
122
+ ]
123
+ .filter(Boolean)
124
+ .join(' '),
125
+ )
126
+ },
127
+ )
128
+ } catch (e) {
129
+ await events.emit('error', e as Error)
130
+ }
159
131
 
160
- try {
161
- await execa('prettier', ['--ignore-unknown', '--write', path.resolve(definedConfig.root, definedConfig.output.path)])
162
- logger?.emit('debug', {
163
- date: new Date(),
164
- logs: ['Prettier formatting completed successfully'],
165
- })
166
- } catch (e) {
167
- logger.consola?.warn('Prettier not found')
168
- logger.consola?.error(e)
169
- logger?.emit('debug', {
170
- date: new Date(),
171
- logs: [`Prettier formatting failed: ${(e as Error).message}`],
172
- })
132
+ await events.emit('success', `Formatted with ${config.output.format}`)
173
133
  }
174
134
 
175
- logger?.emit('success', `Formatted with ${config.output.format}`)
176
- }
177
-
178
- if (config.output.format === 'biome') {
179
- logger?.emit('start', `Formatting with ${config.output.format}`)
180
- logger?.emit('debug', {
181
- date: new Date(),
182
- logs: [`Running biome format on ${path.resolve(definedConfig.root, definedConfig.output.path)}`],
183
- })
184
-
185
- try {
186
- await execa('biome', ['format', '--write', path.resolve(definedConfig.root, definedConfig.output.path)])
187
- logger?.emit('debug', {
188
- date: new Date(),
189
- logs: ['Biome formatting completed successfully'],
190
- })
191
- } catch (e) {
192
- logger.consola?.warn('Biome not found')
193
- logger.consola?.error(e)
194
- logger?.emit('debug', {
195
- date: new Date(),
196
- logs: [`Biome formatting failed: ${(e as Error).message}`],
197
- })
135
+ if (config.output.format === 'biome') {
136
+ try {
137
+ await events.emit(
138
+ 'hook:execute',
139
+ {
140
+ command: 'biome',
141
+ args: ['format', '--write', path.resolve(definedConfig.root, definedConfig.output.path)],
142
+ },
143
+ async () => {
144
+ await events.emit(
145
+ 'success',
146
+ [
147
+ `Formatting with ${pc.dim(config.output.format as string)}`,
148
+ logLevel >= LogLevel.info ? `on ${pc.dim(path.resolve(definedConfig.root, definedConfig.output.path))}` : undefined,
149
+ 'successfully',
150
+ ]
151
+ .filter(Boolean)
152
+ .join(' '),
153
+ )
154
+ },
155
+ )
156
+ } catch (e) {
157
+ const error = new Error('Biome not found')
158
+ error.cause = e
159
+ await events.emit('error', error)
160
+ }
198
161
  }
199
162
 
200
- logger?.emit('success', `Formatted with ${config.output.format}`)
163
+ await events.emit('format:end')
201
164
  }
202
165
 
203
166
  // linting
204
- if (config.output.lint === 'eslint') {
205
- logger?.emit('start', `Linting with ${config.output.lint}`)
206
- logger?.emit('debug', {
207
- date: new Date(),
208
- logs: [`Running eslint on ${path.resolve(definedConfig.root, definedConfig.output.path)}`],
209
- })
210
-
211
- try {
212
- await execa('eslint', [path.resolve(definedConfig.root, definedConfig.output.path), '--fix'])
213
- logger?.emit('debug', {
214
- date: new Date(),
215
- logs: ['ESLint linting completed successfully'],
216
- })
217
- } catch (e) {
218
- logger.consola?.warn('Eslint not found')
219
- logger.consola?.error(e)
220
- logger?.emit('debug', {
221
- date: new Date(),
222
- logs: [`ESLint linting failed: ${(e as Error).message}`],
223
- })
167
+ if (config.output.lint) {
168
+ await events.emit('lint:start')
169
+
170
+ await events.emit(
171
+ 'info',
172
+ [
173
+ `Linting with ${pc.dim(config.output.lint as string)}`,
174
+ logLevel >= LogLevel.info ? `on ${pc.dim(path.resolve(definedConfig.root, definedConfig.output.path))}` : undefined,
175
+ ]
176
+ .filter(Boolean)
177
+ .join(' '),
178
+ )
179
+
180
+ if (config.output.lint === 'eslint') {
181
+ try {
182
+ await events.emit(
183
+ 'hook:execute',
184
+ {
185
+ command: 'eslint',
186
+ args: [path.resolve(definedConfig.root, definedConfig.output.path), '--fix'],
187
+ },
188
+ async () => {
189
+ await events.emit(
190
+ 'success',
191
+ [
192
+ `Linted with ${pc.dim(config.output.lint as string)}`,
193
+ logLevel >= LogLevel.info ? `on ${pc.dim(path.resolve(definedConfig.root, definedConfig.output.path))}` : undefined,
194
+ 'successfully',
195
+ ]
196
+ .filter(Boolean)
197
+ .join(' '),
198
+ )
199
+ },
200
+ )
201
+ } catch (e) {
202
+ const error = new Error('Eslint not found')
203
+ error.cause = e
204
+ await events.emit('error', error)
205
+ }
224
206
  }
225
207
 
226
- logger?.emit('success', `Linted with ${config.output.lint}`)
227
- }
228
-
229
- if (config.output.lint === 'biome') {
230
- logger?.emit('start', `Linting with ${config.output.lint}`)
231
- logger?.emit('debug', {
232
- date: new Date(),
233
- logs: [`Running biome lint on ${path.resolve(definedConfig.root, definedConfig.output.path)}`],
234
- })
235
-
236
- try {
237
- await execa('biome', ['lint', '--fix', path.resolve(definedConfig.root, definedConfig.output.path)])
238
- logger?.emit('debug', {
239
- date: new Date(),
240
- logs: ['Biome linting completed successfully'],
241
- })
242
- } catch (e) {
243
- logger.consola?.warn('Biome not found')
244
- logger.consola?.error(e)
245
- logger?.emit('debug', {
246
- date: new Date(),
247
- logs: [`✗ Biome linting failed: ${(e as Error).message}`],
248
- })
208
+ if (config.output.lint === 'biome') {
209
+ try {
210
+ await events.emit(
211
+ 'hook:execute',
212
+ {
213
+ command: 'biome',
214
+ args: ['lint', '--fix', path.resolve(definedConfig.root, definedConfig.output.path)],
215
+ },
216
+ async () => {
217
+ await events.emit(
218
+ 'success',
219
+ [
220
+ `Linted with ${pc.dim(config.output.lint as string)}`,
221
+ logLevel >= LogLevel.info ? `on ${pc.dim(path.resolve(definedConfig.root, definedConfig.output.path))}` : undefined,
222
+ 'successfully',
223
+ ]
224
+ .filter(Boolean)
225
+ .join(' '),
226
+ )
227
+ },
228
+ )
229
+ } catch (e) {
230
+ const error = new Error('Biome not found')
231
+ error.cause = e
232
+ await events.emit('error', error)
233
+ }
249
234
  }
250
235
 
251
- logger?.emit('success', `Linted with ${config.output.lint}`)
252
- }
253
-
254
- if (config.output.lint === 'oxlint') {
255
- logger?.emit('start', `Linting with ${config.output.lint}`)
256
- logger?.emit('debug', {
257
- date: new Date(),
258
- logs: [`Running oxlint on ${path.resolve(definedConfig.root, definedConfig.output.path)}`],
259
- })
260
-
261
- try {
262
- await execa('oxlint', ['--fix', path.resolve(definedConfig.root, definedConfig.output.path)])
263
- logger?.emit('debug', {
264
- date: new Date(),
265
- logs: ['Oxlint linting completed successfully'],
266
- })
267
- } catch (e) {
268
- logger.consola?.warn('Oxlint not found')
269
- logger.consola?.error(e)
270
- logger?.emit('debug', {
271
- date: new Date(),
272
- logs: [`✗ Oxlint linting failed: ${(e as Error).message}`],
273
- })
236
+ if (config.output.lint === 'oxlint') {
237
+ try {
238
+ await events.emit(
239
+ 'hook:execute',
240
+ {
241
+ command: 'oxlint',
242
+ args: ['--fix', path.resolve(definedConfig.root, definedConfig.output.path)],
243
+ },
244
+ async () => {
245
+ await events.emit(
246
+ 'success',
247
+ [
248
+ `Linted with ${pc.dim(config.output.lint as string)}`,
249
+ logLevel >= LogLevel.info ? `on ${pc.dim(path.resolve(definedConfig.root, definedConfig.output.path))}` : undefined,
250
+ 'successfully',
251
+ ]
252
+ .filter(Boolean)
253
+ .join(' '),
254
+ )
255
+ },
256
+ )
257
+ } catch (e) {
258
+ const error = new Error('Oxlint not found')
259
+ error.cause = e
260
+ await events.emit('error', error)
261
+ }
274
262
  }
275
263
 
276
- logger?.emit('success', `Linted with ${config.output.lint}`)
264
+ await events.emit('lint:end')
277
265
  }
278
266
 
279
267
  if (config.hooks) {
280
- await executeHooks({ hooks: config.hooks, logger })
268
+ await events.emit('hooks:start')
269
+ await executeHooks({ hooks: config.hooks, events })
270
+
271
+ await events.emit('hooks:end')
281
272
  }
282
273
 
283
- logger.consola?.log(`⚡ Build completed ${logger.logLevel !== LogMapper.silent ? pc.dim(inputPath!) : ''}`)
284
- logger.consola?.box({
285
- title: `${config.name || ''}`,
286
- message: summary.join(''),
287
- style: {
288
- padding: 2,
289
- borderColor: 'green',
290
- borderStyle: 'rounded',
291
- },
274
+ await events.emit('generation:summary', definedConfig, {
275
+ failedPlugins,
276
+ filesCreated: files.length,
277
+ status: failedPlugins.size > 0 || error ? 'failed' : 'success',
278
+ hrStart,
279
+ pluginTimings,
292
280
  })
293
281
  }
@@ -1,18 +1,22 @@
1
- import * as process from 'node:process'
2
1
  import type { WritableOptions } from 'node:stream'
3
2
  import { Writable } from 'node:stream'
4
- import type { ConsolaInstance } from 'consola'
3
+ import type * as clack from '@clack/prompts'
5
4
  import pc from 'picocolors'
6
5
 
7
- export class ConsolaWritable extends Writable {
8
- consola: ConsolaInstance | undefined
9
- command: string
10
- constructor(consola: ConsolaInstance | undefined, command: string, opts?: WritableOptions) {
6
+ export class ClackWritable extends Writable {
7
+ taskLog: ReturnType<typeof clack.taskLog>
8
+ constructor(taskLog: ReturnType<typeof clack.taskLog>, opts?: WritableOptions) {
11
9
  super(opts)
12
10
 
13
- this.command = command
14
- this.consola = consola
11
+ this.taskLog = taskLog
15
12
  }
13
+ _write(chunk: any, _encoding: BufferEncoding, callback: (error?: Error | null) => void): void {
14
+ this.taskLog.message(`${pc.dim(chunk?.toString())}`)
15
+ callback()
16
+ }
17
+ }
18
+
19
+ export class StdoutWritable extends Writable {
16
20
  _write(chunk: any, _encoding: BufferEncoding, callback: (error?: Error | null) => void): void {
17
21
  process.stdout.write(`${pc.dim(chunk?.toString())}`)
18
22
 
@@ -1,37 +1,30 @@
1
- import type { Config } from '@kubb/core'
2
- import type { Logger } from '@kubb/core/logger'
3
- import { LogMapper } from '@kubb/core/logger'
4
- import { execa } from 'execa'
1
+ import type { Config, KubbEvents } from '@kubb/core'
2
+ import type { AsyncEventEmitter } from '@kubb/core/utils'
3
+
5
4
  import pc from 'picocolors'
6
5
  import { parseArgsStringToArgv } from 'string-argv'
7
- import { ConsolaWritable } from './Writables.ts'
8
6
 
9
7
  type ExecutingHooksProps = {
10
8
  hooks: NonNullable<Config['hooks']>
11
- logger: Logger
9
+ events: AsyncEventEmitter<KubbEvents>
12
10
  }
13
11
 
14
- export async function executeHooks({ hooks, logger }: ExecutingHooksProps): Promise<void> {
12
+ export async function executeHooks({ hooks, events }: ExecutingHooksProps): Promise<void> {
15
13
  const commands = Array.isArray(hooks.done) ? hooks.done : [hooks.done].filter(Boolean)
16
14
 
17
15
  for (const command of commands) {
18
- const consolaWritable = new ConsolaWritable(logger.consola!, command)
19
- const [cmd, ..._args] = [...parseArgsStringToArgv(command)]
16
+ const [cmd, ...args] = [...parseArgsStringToArgv(command)]
20
17
 
21
18
  if (!cmd) {
22
19
  continue
23
20
  }
24
21
 
25
- logger?.emit('start', `Executing hook ${logger.logLevel !== LogMapper.silent ? pc.dim(command) : ''}`)
22
+ await events.emit('hook:start', command)
26
23
 
27
- await execa(cmd, _args, {
28
- detached: true,
29
- stdout: logger?.logLevel === LogMapper.silent ? undefined : ['pipe', consolaWritable],
30
- stripFinalNewline: true,
31
- })
24
+ await events.emit('hook:execute', { command: cmd, args }, async () => {
25
+ await events.emit('success', `${pc.dim(command)} successfully executed`)
32
26
 
33
- logger?.emit('success', `Executed hook ${logger.logLevel !== LogMapper.silent ? pc.dim(command) : ''}`)
27
+ await events.emit('hook:end', command)
28
+ })
34
29
  }
35
-
36
- logger?.emit('success', 'Executed hooks')
37
30
  }
@@ -23,6 +23,7 @@ const tsLoader = async (configFile: string) => {
23
23
  }
24
24
 
25
25
  export async function getCosmiConfig(moduleName: string, config?: string): Promise<CosmiconfigResult> {
26
+ let result: CosmiconfigResult
26
27
  const searchPlaces = [
27
28
  'package.json',
28
29
  `.${moduleName}rc`,
@@ -56,7 +57,11 @@ export async function getCosmiConfig(moduleName: string, config?: string): Promi
56
57
  },
57
58
  })
58
59
 
59
- const result = config ? await explorer.load(config) : await explorer.search()
60
+ try {
61
+ result = config ? ((await explorer.load(config)) as CosmiconfigResult) : ((await explorer.search()) as CosmiconfigResult)
62
+ } catch (e) {
63
+ throw new Error('Config failed loading', { cause: e })
64
+ }
60
65
 
61
66
  if (result?.isEmpty || !result || !result.config) {
62
67
  throw new Error('Config not defined, create a kubb.config.js or pass through your config with the option --config')