@kubb/fabric-core 0.0.0-canary-20251219212751 → 0.0.0-canary-20251230235043

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.
@@ -1,8 +1,8 @@
1
1
  import http from 'node:http'
2
2
  import type { AddressInfo } from 'node:net'
3
3
  import { relative } from 'node:path'
4
- import { Presets, SingleBar } from 'cli-progress'
5
- import { createConsola, type LogLevel } from 'consola'
4
+ import * as clack from '@clack/prompts'
5
+ import pc from 'picocolors'
6
6
  import { WebSocket, WebSocketServer } from 'ws'
7
7
  import type { FabricEvents } from '../Fabric.ts'
8
8
  import type * as KubbFile from '../KubbFile.ts'
@@ -23,10 +23,6 @@ type WebSocketOptions = {
23
23
  }
24
24
 
25
25
  type Options = {
26
- /**
27
- * Explicit consola log level.
28
- */
29
- level?: LogLevel
30
26
  /**
31
27
  * Toggle progress bar output.
32
28
  * @default true
@@ -64,28 +60,22 @@ function pluralize(word: string, count: number) {
64
60
  return `${count} ${word}${count === 1 ? '' : 's'}`
65
61
  }
66
62
 
67
- const defaultTag = 'Fabric'
68
-
69
- const createProgressBar = () =>
70
- new SingleBar(
71
- {
72
- format: '{bar} {percentage}% | {value}/{total} | {message}',
73
- barCompleteChar: '█',
74
- barIncompleteChar: '░',
75
- hideCursor: true,
76
- clearOnComplete: true,
77
- },
78
- Presets.shades_grey,
79
- )
63
+ const DEFAULT_PROGRESS_BAR_SIZE = 30
80
64
 
81
65
  export const loggerPlugin = definePlugin<Options>({
82
66
  name: 'logger',
83
67
  install(ctx, options = {}) {
84
- const { level, websocket = true, progress = true } = options
68
+ const { websocket = true, progress = true } = options
85
69
 
86
- const logger = createConsola(level !== undefined ? { level } : {}).withTag(defaultTag)
70
+ const state = {
71
+ spinner: clack.spinner(),
72
+ isSpinning: false,
73
+ progressBar: undefined as ReturnType<typeof clack.progress> | undefined,
74
+ }
87
75
 
88
- const progressBar = progress ? createProgressBar() : undefined
76
+ function formatPath(path: string) {
77
+ return relative(process.cwd(), path)
78
+ }
89
79
 
90
80
  let server: http.Server | undefined
91
81
  let wss: WebSocketServer | undefined
@@ -117,13 +107,13 @@ export const loggerPlugin = definePlugin<Options>({
117
107
  const { host: resolvedHost, port: resolvedPort } = normalizeAddress(addressInfo)
118
108
  const url = `ws://${resolvedHost}:${resolvedPort}`
119
109
 
120
- logger.info(`Logger websocket listening on ${url}`)
110
+ clack.log.info(`${pc.blue('ℹ')} Logger websocket listening on ${url}`)
121
111
  broadcast('websocket:ready', { url })
122
112
  }
123
113
  })
124
114
 
125
115
  wss.on('connection', (socket) => {
126
- logger.info('Logger websocket client connected')
116
+ clack.log.info(`${pc.blue('ℹ')} Logger websocket client connected`)
127
117
  socket.send(
128
118
  JSON.stringify({
129
119
  event: 'welcome',
@@ -136,19 +126,17 @@ export const loggerPlugin = definePlugin<Options>({
136
126
  })
137
127
 
138
128
  wss.on('error', (error) => {
139
- logger.error('Logger websocket error', error)
129
+ clack.log.error(`${pc.red('✗')} Logger websocket error: ${error.message}`)
140
130
  })
141
131
  }
142
132
 
143
- const formatPath = (path: string) => relative(process.cwd(), path)
144
-
145
133
  ctx.on('lifecycle:start', async () => {
146
- logger.start('Starting Fabric run')
134
+ clack.intro(`${pc.blue('Fabric')} ${pc.dim('Starting run')}`)
147
135
  broadcast('lifecycle:start', { timestamp: Date.now() })
148
136
  })
149
137
 
150
138
  ctx.on('lifecycle:render', async () => {
151
- logger.info('Rendering application graph')
139
+ clack.log.info(`${pc.blue('ℹ')} Rendering application graph`)
152
140
  broadcast('lifecycle:render', { timestamp: Date.now() })
153
141
  })
154
142
 
@@ -157,37 +145,44 @@ export const loggerPlugin = definePlugin<Options>({
157
145
  return
158
146
  }
159
147
 
160
- logger.info(`Queued ${pluralize('file', files.length)}`)
148
+ clack.log.info(`${pc.blue('ℹ')} Queued ${pluralize('file', files.length)}`)
161
149
  broadcast('files:added', {
162
150
  files: files.map(serializeFile),
163
151
  })
164
152
  })
165
153
 
166
154
  ctx.on('file:resolve:path', async (file) => {
167
- logger.info(`Resolving path for ${formatPath(file.path)}`)
155
+ clack.log.step(`Resolving path for ${pc.dim(formatPath(file.path))}`)
168
156
  broadcast('file:resolve:path', { file: serializeFile(file) })
169
157
  })
170
158
 
171
159
  ctx.on('file:resolve:name', async (file) => {
172
- logger.info(`Resolving name for ${formatPath(file.path)}`)
160
+ clack.log.step(`Resolving name for ${pc.dim(formatPath(file.path))}`)
173
161
  broadcast('file:resolve:name', { file: serializeFile(file) })
174
162
  })
175
163
 
176
164
  ctx.on('files:processing:start', async (files) => {
177
- logger.start(`Processing ${pluralize('file', files.length)}`)
165
+ clack.log.step(`Processing ${pc.green(pluralize('file', files.length))}`)
178
166
  broadcast('files:processing:start', {
179
167
  total: files.length,
180
168
  timestamp: Date.now(),
181
169
  })
182
170
 
183
- if (progressBar) {
184
- logger.pauseLogs()
185
- progressBar.start(files.length, 0, { message: 'Starting...' })
171
+ if (progress) {
172
+ state.progressBar = clack.progress({
173
+ style: 'block',
174
+ max: files.length,
175
+ size: DEFAULT_PROGRESS_BAR_SIZE,
176
+ })
177
+ state.progressBar.start(`Processing ${files.length} files`)
186
178
  }
187
179
  })
188
180
 
189
181
  ctx.on('file:processing:start', async (file, index, total) => {
190
- logger.info(`Processing [${index + 1}/${total}] ${formatPath(file.path)}`)
182
+ if (!state.progressBar) {
183
+ clack.log.step(`Processing ${pc.dim(`[${index + 1}/${total}]`)} ${formatPath(file.path)}`)
184
+ }
185
+
191
186
  broadcast('file:processing:start', {
192
187
  index,
193
188
  total,
@@ -196,9 +191,6 @@ export const loggerPlugin = definePlugin<Options>({
196
191
  })
197
192
 
198
193
  ctx.on('file:processing:update', async ({ processed, total, percentage, file }) => {
199
- const formattedPercentage = Number.isFinite(percentage) ? percentage.toFixed(1) : '0.0'
200
-
201
- logger.info(`Progress ${formattedPercentage}% (${processed}/${total}) → ${formatPath(file.path)}`)
202
194
  broadcast('file:processing:update', {
203
195
  processed,
204
196
  total,
@@ -206,15 +198,22 @@ export const loggerPlugin = definePlugin<Options>({
206
198
  file: serializeFile(file),
207
199
  })
208
200
 
209
- if (progressBar) {
210
- progressBar.increment(1, {
211
- message: `Writing ${formatPath(file.path)}`,
212
- })
201
+ if (state.progressBar) {
202
+ // undefined = auto-increment by 1
203
+ state.progressBar.advance(undefined, `Writing ${formatPath(file.path)}`)
204
+ } else {
205
+ const formattedPercentage = Number.isFinite(percentage) ? percentage.toFixed(1) : '0.0'
206
+ clack.log.step(`Progress ${pc.green(`${formattedPercentage}%`)} ${pc.dim(`(${processed}/${total})`)} → ${formatPath(file.path)}`)
213
207
  }
214
208
  })
215
209
 
216
210
  ctx.on('file:processing:end', async (file, index, total) => {
217
- logger.success(`Finished [${index + 1}/${total}] ${formatPath(file.path)}`)
211
+ if (state.progressBar) {
212
+ state.progressBar.message(`${pc.green('✓')} Finished ${pc.dim(`[${index + 1}/${total}]`)} ${formatPath(file.path)}`)
213
+ } else {
214
+ clack.log.success(`${pc.green('✓')} Finished ${pc.dim(`[${index + 1}/${total}]`)} ${formatPath(file.path)}`)
215
+ }
216
+
218
217
  broadcast('file:processing:end', {
219
218
  index,
220
219
  total,
@@ -223,43 +222,41 @@ export const loggerPlugin = definePlugin<Options>({
223
222
  })
224
223
 
225
224
  ctx.on('files:writing:start', async (files) => {
226
- logger.start(`Writing ${pluralize('file', files.length)} to disk`)
227
225
  broadcast('files:writing:start', {
228
226
  files: files.map(serializeFile),
229
227
  })
230
228
  })
231
229
 
232
230
  ctx.on('files:writing:end', async (files) => {
233
- logger.success(`Written ${pluralize('file', files.length)} to disk`)
234
231
  broadcast('files:writing:end', {
235
232
  files: files.map(serializeFile),
236
233
  })
237
234
  })
238
235
 
239
236
  ctx.on('files:processing:end', async (files) => {
240
- logger.success(`Processed ${pluralize('file', files.length)}`)
237
+ if (state.progressBar) {
238
+ state.progressBar.stop(`${pc.green('✓')} Processed ${pluralize('file', files.length)}`)
239
+ state.progressBar = undefined
240
+ } else {
241
+ clack.log.success(`${pc.green('✓')} Processed ${pluralize('file', files.length)}`)
242
+ }
243
+
241
244
  broadcast('files:processing:end', {
242
245
  total: files.length,
243
246
  timestamp: Date.now(),
244
247
  })
245
-
246
- if (progressBar) {
247
- progressBar.update(files.length, { message: 'Done ✅' })
248
- progressBar.stop()
249
-
250
- logger.resumeLogs()
251
- }
252
248
  })
253
249
 
254
250
  ctx.on('lifecycle:end', async () => {
255
- logger.success('Fabric run completed')
256
- broadcast('lifecycle:end', { timestamp: Date.now() })
257
-
258
- if (progressBar) {
259
- progressBar.stop()
260
- logger.resumeLogs()
251
+ if (state.progressBar) {
252
+ state.progressBar.stop()
253
+ state.progressBar = undefined
261
254
  }
262
255
 
256
+ clack.outro(`${pc.blue('Fabric')} ${pc.dim('completed')}`)
257
+
258
+ broadcast('lifecycle:end', { timestamp: Date.now() })
259
+
263
260
  const closures: Array<Promise<void>> = []
264
261
 
265
262
  if (wss) {
@@ -287,7 +284,7 @@ export const loggerPlugin = definePlugin<Options>({
287
284
 
288
285
  if (closures.length) {
289
286
  await Promise.allSettled(closures)
290
- logger.info('Logger websocket closed')
287
+ clack.log.info(`${pc.blue('ℹ')} Logger websocket closed`)
291
288
  }
292
289
  })
293
290
  },