@kubb/fabric-core 0.0.0-canary-20251126084918 → 0.0.0-canary-20251215181926

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 (65) hide show
  1. package/README.md +53 -23
  2. package/dist/{Fabric-BzIhBn8t.d.cts → Fabric-CEVrEuYU.d.ts} +113 -22
  3. package/dist/{Fabric-igvWKffO.d.ts → Fabric-CVnHPMqM.d.cts} +113 -22
  4. package/dist/{defaultParser-n9VW2iVf.cjs → defaultParser-CIF-0xIK.cjs} +3 -3
  5. package/dist/{defaultParser-n9VW2iVf.cjs.map → defaultParser-CIF-0xIK.cjs.map} +1 -1
  6. package/dist/{defaultParser-Csot2aaT.js → defaultParser-DPHcM2NR.js} +3 -3
  7. package/dist/{defaultParser-Csot2aaT.js.map → defaultParser-DPHcM2NR.js.map} +1 -1
  8. package/dist/defineParser-Bxv4mb-N.js +11 -0
  9. package/dist/{createParser-D_ANHZTa.js.map → defineParser-Bxv4mb-N.js.map} +1 -1
  10. package/dist/defineParser-DODGK4rM.cjs +17 -0
  11. package/dist/{createParser-C4IkyTs5.cjs.map → defineParser-DODGK4rM.cjs.map} +1 -1
  12. package/dist/{defineProperty-Bhq3jwZe.cjs → defineProperty-BOlj8-IY.cjs} +10 -10
  13. package/dist/{defineProperty-Bhq3jwZe.cjs.map → defineProperty-BOlj8-IY.cjs.map} +1 -1
  14. package/dist/{defineProperty-BQu382bn.js → defineProperty-D2uejjT1.js} +10 -10
  15. package/dist/{defineProperty-BQu382bn.js.map → defineProperty-D2uejjT1.js.map} +1 -1
  16. package/dist/index.cjs +75 -85
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +7 -22
  19. package/dist/index.d.ts +7 -22
  20. package/dist/index.js +76 -85
  21. package/dist/index.js.map +1 -1
  22. package/dist/parsers/typescript.cjs +2 -2
  23. package/dist/parsers/typescript.d.cts +2 -2
  24. package/dist/parsers/typescript.d.ts +2 -2
  25. package/dist/parsers/typescript.js +2 -2
  26. package/dist/parsers.cjs +5 -5
  27. package/dist/parsers.cjs.map +1 -1
  28. package/dist/parsers.d.cts +6 -6
  29. package/dist/parsers.d.ts +6 -6
  30. package/dist/parsers.js +5 -5
  31. package/dist/parsers.js.map +1 -1
  32. package/dist/plugins.cjs +33 -33
  33. package/dist/plugins.cjs.map +1 -1
  34. package/dist/plugins.d.cts +4 -4
  35. package/dist/plugins.d.ts +4 -4
  36. package/dist/plugins.js +33 -33
  37. package/dist/plugins.js.map +1 -1
  38. package/dist/types.d.cts +1 -1
  39. package/dist/types.d.ts +1 -1
  40. package/dist/{typescriptParser-BN1vEX-I.d.ts → typescriptParser-9jJzfPj-.d.ts} +2 -2
  41. package/dist/{typescriptParser-Cw2wm0gX.js → typescriptParser-BLX7eX2k.js} +3 -3
  42. package/dist/{typescriptParser-Cw2wm0gX.js.map → typescriptParser-BLX7eX2k.js.map} +1 -1
  43. package/dist/{typescriptParser-BlRK18rx.d.cts → typescriptParser-DCFNN4BL.d.cts} +2 -2
  44. package/dist/{typescriptParser-DRdx9q2o.cjs → typescriptParser-OjFZ_DeI.cjs} +3 -3
  45. package/dist/{typescriptParser-DRdx9q2o.cjs.map → typescriptParser-OjFZ_DeI.cjs.map} +1 -1
  46. package/package.json +1 -1
  47. package/src/Fabric.ts +117 -21
  48. package/src/FileManager.ts +4 -4
  49. package/src/FileProcessor.ts +5 -5
  50. package/src/createFabric.ts +96 -2
  51. package/src/index.ts +0 -1
  52. package/src/parsers/defaultParser.ts +2 -2
  53. package/src/parsers/{createParser.ts → defineParser.ts} +1 -1
  54. package/src/parsers/index.ts +1 -2
  55. package/src/parsers/tsxParser.ts +2 -2
  56. package/src/parsers/typescriptParser.ts +2 -2
  57. package/src/plugins/barrelPlugin.ts +3 -3
  58. package/src/plugins/{createPlugin.ts → definePlugin.ts} +1 -1
  59. package/src/plugins/fsPlugin.ts +3 -3
  60. package/src/plugins/graphPlugin.ts +3 -3
  61. package/src/plugins/index.ts +1 -1
  62. package/src/plugins/loggerPlugin.ts +37 -27
  63. package/dist/createParser-C4IkyTs5.cjs +0 -17
  64. package/dist/createParser-D_ANHZTa.js +0 -11
  65. package/src/defineFabric.ts +0 -119
package/src/Fabric.ts CHANGED
@@ -37,39 +37,129 @@ export type FabricMode = 'sequential' | 'parallel'
37
37
 
38
38
  /**
39
39
  * Event definitions emitted during the Fabric lifecycle.
40
+ *
41
+ * These events allow plugins and external code to hook into different stages
42
+ * of the file generation process. All events are asynchronous and can be
43
+ * listened to using `fabric.context.on()` or `fabric.context.onOnce()`.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * fabric.context.on('lifecycle:start', async () => {
48
+ * console.log('Fabric started!')
49
+ * })
50
+ * ```
40
51
  */
41
52
  export interface FabricEvents {
42
- /** Called at the beginning of the app lifecycle. */
43
- start: []
53
+ /**
54
+ * Emitted when the Fabric application lifecycle begins.
55
+ * This is typically the first event fired when starting a Fabric run.
56
+ * Use this to perform initial setup or logging.
57
+ */
58
+ 'lifecycle:start': []
44
59
 
45
- /** Called at the end of the app lifecycle. */
46
- end: []
60
+ /**
61
+ * Emitted when the Fabric application lifecycle completes.
62
+ * This is typically the last event fired after all processing is done.
63
+ * Use this for cleanup tasks or final reporting.
64
+ */
65
+ 'lifecycle:end': []
47
66
 
48
- /** Called when Fabric is rendering. */
49
- render: [{ fabric: Fabric }]
67
+ /**
68
+ * Emitted when Fabric starts rendering (used with reactPlugin).
69
+ * Provides access to the Fabric instance for render-time operations.
70
+ *
71
+ * @property fabric - The current Fabric instance being rendered
72
+ */
73
+ 'lifecycle:render': [{ fabric: Fabric }]
50
74
 
51
- /** Called once before any files are processed. */
52
- 'process:start': [{ files: KubbFile.ResolvedFile[] }]
53
75
  /**
54
- * Called when FileManager is adding files to its cache
76
+ * Emitted once before file processing begins.
77
+ * Provides the complete list of files that will be processed.
78
+ * Use this to prepare for batch operations or display initial file counts.
79
+ *
80
+ * @property files - Array of all files queued for processing
81
+ */
82
+ 'files:processing:start': [{ files: KubbFile.ResolvedFile[] }]
83
+
84
+ /**
85
+ * Emitted when files are successfully added to the FileManager's internal cache.
86
+ * This happens after files pass through path and name resolution.
87
+ * Use this to track which files have been registered.
88
+ *
89
+ * @property files - Array of files that were just added to the cache
90
+ */
91
+ 'files:added': [{ files: KubbFile.ResolvedFile[] }]
92
+
93
+ /**
94
+ * Emitted during file path resolution, before a file is cached.
95
+ * Listeners can modify the file's path property to customize output location.
96
+ * This is called for each file being added via `addFile()` or `upsertFile()`.
97
+ *
98
+ * @property file - The file whose path is being resolved (mutable)
55
99
  */
56
- 'file:add': [{ files: KubbFile.ResolvedFile[] }]
57
100
  'file:resolve:path': [{ file: KubbFile.File }]
101
+
102
+ /**
103
+ * Emitted during file name resolution, before a file is cached.
104
+ * Listeners can modify the file's name-related properties to customize naming.
105
+ * This is called for each file being added via `addFile()` or `upsertFile()`.
106
+ *
107
+ * @property file - The file whose name is being resolved (mutable)
108
+ */
58
109
  'file:resolve:name': [{ file: KubbFile.File }]
59
- 'write:start': [{ files: KubbFile.ResolvedFile[] }]
60
- 'write:end': [{ files: KubbFile.ResolvedFile[] }]
61
110
 
62
- /** Called for each file when processing begins. */
63
- 'file:start': [{ file: KubbFile.ResolvedFile; index: number; total: number }]
111
+ /**
112
+ * Emitted just before files are written to disk.
113
+ * Provides all files that will be written in this batch.
114
+ * Use this to perform pre-write operations like creating directories.
115
+ *
116
+ * @property files - Array of files about to be written to disk
117
+ */
118
+ 'files:writing:start': [{ files: KubbFile.ResolvedFile[] }]
64
119
 
65
- /** Called for each file when processing completes. */
66
- 'file:end': [{ file: KubbFile.ResolvedFile; index: number; total: number }]
120
+ /**
121
+ * Emitted after all files have been successfully written to disk.
122
+ * Provides all files that were written in this batch.
123
+ * Use this for post-write operations like running formatters or reporting.
124
+ *
125
+ * @property files - Array of files that were written to disk
126
+ */
127
+ 'files:writing:end': [{ files: KubbFile.ResolvedFile[] }]
67
128
 
68
129
  /**
69
- * Called periodically (or per file) to indicate progress.
70
- * Useful for progress bars or logging.
130
+ * Emitted when an individual file starts being processed.
131
+ * This happens for each file in the queue, before parsing.
132
+ * Use this for per-file setup or detailed logging.
133
+ *
134
+ * @property file - The file starting processing
135
+ * @property index - Zero-based position of this file in the queue
136
+ * @property total - Total number of files to process
71
137
  */
72
- 'process:progress': [
138
+ 'file:processing:start': [{ file: KubbFile.ResolvedFile; index: number; total: number }]
139
+
140
+ /**
141
+ * Emitted when an individual file completes processing.
142
+ * This happens after the file has been parsed and handled.
143
+ * Use this for per-file cleanup or progress tracking.
144
+ *
145
+ * @property file - The file that finished processing
146
+ * @property index - Zero-based position of this file in the queue
147
+ * @property total - Total number of files to process
148
+ */
149
+ 'file:processing:end': [{ file: KubbFile.ResolvedFile; index: number; total: number }]
150
+
151
+ /**
152
+ * Emitted after each file is processed, providing progress metrics.
153
+ * This is the primary event for implementing progress bars or tracking.
154
+ * Plugins like fsPlugin use this to write files to disk.
155
+ *
156
+ * @property processed - Number of files processed so far
157
+ * @property total - Total number of files to process
158
+ * @property percentage - Completion percentage (0-100)
159
+ * @property source - Optional parsed source code of the file
160
+ * @property file - The file that was just processed
161
+ */
162
+ 'file:processing:update': [
73
163
  {
74
164
  processed: number
75
165
  total: number
@@ -79,8 +169,14 @@ export interface FabricEvents {
79
169
  },
80
170
  ]
81
171
 
82
- /** Called once all files have been processed successfully. */
83
- 'process:end': [{ files: KubbFile.ResolvedFile[] }]
172
+ /**
173
+ * Emitted once all files have been successfully processed.
174
+ * This marks the completion of the processing phase.
175
+ * Use this to perform batch operations on all processed files.
176
+ *
177
+ * @property files - Array of all files that were processed
178
+ */
179
+ 'files:processing:end': [{ files: KubbFile.ResolvedFile[] }]
84
180
  }
85
181
 
86
182
  /**
@@ -71,7 +71,7 @@ export class FileManager {
71
71
  resolvedFiles.push(resolvedFile)
72
72
  }
73
73
 
74
- await this.events.emit('file:add', { files: resolvedFiles })
74
+ await this.events.emit('files:added', { files: resolvedFiles })
75
75
 
76
76
  return resolvedFiles
77
77
  }
@@ -105,7 +105,7 @@ export class FileManager {
105
105
  resolvedFiles.push(resolvedFile)
106
106
  }
107
107
 
108
- await this.events.emit('file:add', { files: resolvedFiles })
108
+ await this.events.emit('files:added', { files: resolvedFiles })
109
109
 
110
110
  return resolvedFiles
111
111
  }
@@ -155,13 +155,13 @@ export class FileManager {
155
155
 
156
156
  //TODO add test and check if write of FileManager contains the newly added file
157
157
  async write(options: ProcessFilesProps): Promise<KubbFile.ResolvedFile[]> {
158
- await this.events.emit('write:start', { files: this.files })
158
+ await this.events.emit('files:writing:start', { files: this.files })
159
159
 
160
160
  const resolvedFiles = await this.processor.run(this.files, options)
161
161
 
162
162
  this.clear()
163
163
 
164
- await this.events.emit('write:end', { files: resolvedFiles })
164
+ await this.events.emit('files:writing:end', { files: resolvedFiles })
165
165
 
166
166
  return resolvedFiles
167
167
  }
@@ -60,20 +60,20 @@ export class FileProcessor {
60
60
  files: Array<KubbFile.ResolvedFile>,
61
61
  { parsers, mode = 'sequential', dryRun, extension }: ProcessFilesProps = {},
62
62
  ): Promise<KubbFile.ResolvedFile[]> {
63
- await this.events.emit('process:start', { files })
63
+ await this.events.emit('files:processing:start', { files })
64
64
 
65
65
  const total = files.length
66
66
  let processed = 0
67
67
 
68
68
  const processOne = async (resolvedFile: KubbFile.ResolvedFile, index: number) => {
69
- await this.events.emit('file:start', { file: resolvedFile, index, total })
69
+ await this.events.emit('file:processing:start', { file: resolvedFile, index, total })
70
70
 
71
71
  const source = dryRun ? undefined : await this.parse(resolvedFile, { extension, parsers })
72
72
 
73
73
  const currentProcessed = ++processed
74
74
  const percentage = (currentProcessed / total) * 100
75
75
 
76
- await this.events.emit('process:progress', {
76
+ await this.events.emit('file:processing:update', {
77
77
  file: resolvedFile,
78
78
  source,
79
79
  processed: currentProcessed,
@@ -81,7 +81,7 @@ export class FileProcessor {
81
81
  total,
82
82
  })
83
83
 
84
- await this.events.emit('file:end', { file: resolvedFile, index, total })
84
+ await this.events.emit('file:processing:end', { file: resolvedFile, index, total })
85
85
  }
86
86
 
87
87
  if (mode === 'sequential') {
@@ -101,7 +101,7 @@ export class FileProcessor {
101
101
  await Promise.all(promises)
102
102
  }
103
103
 
104
- await this.events.emit('process:end', { files })
104
+ await this.events.emit('files:processing:end', { files })
105
105
 
106
106
  return files
107
107
  }
@@ -1,3 +1,97 @@
1
- import { defineFabric } from './defineFabric.ts'
1
+ import { isFunction } from 'remeda'
2
+ import type { Fabric, FabricConfig, FabricContext, FabricEvents, FabricOptions } from './Fabric.ts'
3
+ import { FileManager } from './FileManager.ts'
4
+ import type * as KubbFile from './KubbFile.ts'
5
+ import type { Parser } from './parsers/types.ts'
6
+ import type { Plugin } from './plugins/types.ts'
7
+ import { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'
2
8
 
3
- export const createFabric = defineFabric()
9
+ /**
10
+ * Creates a new Fabric instance
11
+ *
12
+ * @example
13
+ * const fabric = createFabric()
14
+ * fabric.use(myPlugin())
15
+ */
16
+ export function createFabric<T extends FabricOptions>(config: FabricConfig<T> = { mode: 'sequential' } as FabricConfig<T>): Fabric<T> {
17
+ const events = new AsyncEventEmitter<FabricEvents>()
18
+ const installedPlugins = new Set<Plugin<any>>()
19
+ const installedParsers = new Map<KubbFile.Extname, Parser<any>>()
20
+ const installedParserNames = new Set<string>()
21
+ const fileManager = new FileManager({ events })
22
+
23
+ const context: FabricContext<T> = {
24
+ get files() {
25
+ return fileManager.files
26
+ },
27
+ async addFile(...files) {
28
+ await fileManager.add(...files)
29
+ },
30
+ config,
31
+ fileManager,
32
+ installedPlugins,
33
+ installedParsers,
34
+ on: events.on.bind(events),
35
+ off: events.off.bind(events),
36
+ onOnce: events.onOnce.bind(events),
37
+ removeAll: events.removeAll.bind(events),
38
+ emit: events.emit.bind(events),
39
+ } as FabricContext<T>
40
+
41
+ const fabric: Fabric<T> = {
42
+ context,
43
+ get files() {
44
+ return fileManager.files
45
+ },
46
+ async addFile(...files) {
47
+ await fileManager.add(...files)
48
+ },
49
+ async upsertFile(...files) {
50
+ await fileManager.upsert(...files)
51
+ },
52
+ async use(pluginOrParser, ...options) {
53
+ if (pluginOrParser.type === 'plugin') {
54
+ if (installedPlugins.has(pluginOrParser)) {
55
+ console.warn(`Plugin "${pluginOrParser.name}" already applied.`)
56
+ } else {
57
+ installedPlugins.add(pluginOrParser)
58
+ }
59
+
60
+ if (isFunction(pluginOrParser.inject)) {
61
+ const injecter = pluginOrParser.inject
62
+
63
+ const injected = (injecter as any)(context, ...options)
64
+ Object.assign(fabric, injected)
65
+ }
66
+ }
67
+
68
+ if (pluginOrParser.type === 'parser') {
69
+ if (installedParserNames.has(pluginOrParser.name)) {
70
+ console.warn(`Parser "${pluginOrParser.name}" already applied.`)
71
+ } else {
72
+ installedParserNames.add(pluginOrParser.name)
73
+ }
74
+
75
+ if (pluginOrParser.extNames) {
76
+ for (const extName of pluginOrParser.extNames) {
77
+ const existing = installedParsers.get(extName)
78
+ if (existing && existing.name !== pluginOrParser.name) {
79
+ console.warn(`Parser "${pluginOrParser.name}" is overriding parser "${existing.name}" for extension "${extName}".`)
80
+ }
81
+ installedParsers.set(extName, pluginOrParser)
82
+ }
83
+ }
84
+ }
85
+
86
+ if (isFunction(pluginOrParser.install)) {
87
+ const installer = pluginOrParser.install
88
+
89
+ await (installer as any)(context, ...options)
90
+ }
91
+
92
+ return fabric
93
+ },
94
+ } as Fabric<T>
95
+
96
+ return fabric
97
+ }
package/src/index.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  export { createFabric } from './createFabric.ts'
2
2
  export { createFile } from './createFile.ts'
3
- export { defineFabric } from './defineFabric.ts'
4
3
  // we need this to override the globals of `fabric.use`
5
4
  export type { Fabric } from './Fabric.ts'
6
5
  export { FileManager } from './FileManager.ts'
@@ -1,6 +1,6 @@
1
- import { createParser } from './createParser.ts'
1
+ import { defineParser } from './defineParser.ts'
2
2
 
3
- export const defaultParser = createParser({
3
+ export const defaultParser = defineParser({
4
4
  name: 'default',
5
5
  extNames: ['.json'],
6
6
  install() {},
@@ -1,6 +1,6 @@
1
1
  import type { Parser, UserParser } from './types.ts'
2
2
 
3
- export function createParser<TOptions = unknown, TMeta extends object = any>(parser: UserParser<TOptions, TMeta>): Parser<TOptions, TMeta> {
3
+ export function defineParser<TOptions = unknown, TMeta extends object = any>(parser: UserParser<TOptions, TMeta>): Parser<TOptions, TMeta> {
4
4
  return {
5
5
  type: 'parser',
6
6
  ...parser,
@@ -1,5 +1,4 @@
1
- export { createParser } from './createParser.ts'
2
-
3
1
  export { defaultParser } from './defaultParser.ts'
2
+ export { defineParser } from './defineParser.ts'
4
3
  export { tsxParser } from './tsxParser.ts'
5
4
  export { typescriptParser } from './typescriptParser.ts'
@@ -1,7 +1,7 @@
1
- import { createParser } from './createParser.ts'
1
+ import { defineParser } from './defineParser.ts'
2
2
  import { typescriptParser } from './typescriptParser.ts'
3
3
 
4
- export const tsxParser = createParser({
4
+ export const tsxParser = defineParser({
5
5
  name: 'tsx',
6
6
  extNames: ['.tsx', '.jsx'],
7
7
  install() {},
@@ -2,7 +2,7 @@ import path from 'node:path'
2
2
  import ts from 'typescript'
3
3
  import { getRelativePath } from '../utils/getRelativePath.ts'
4
4
  import { trimExtName } from '../utils/trimExtName.ts'
5
- import { createParser } from './createParser.ts'
5
+ import { defineParser } from './defineParser.ts'
6
6
 
7
7
  const { factory } = ts
8
8
 
@@ -122,7 +122,7 @@ export function createExport({
122
122
  )
123
123
  }
124
124
 
125
- export const typescriptParser = createParser({
125
+ export const typescriptParser = defineParser({
126
126
  name: 'typescript',
127
127
  extNames: ['.ts', '.js'],
128
128
  install() {},
@@ -5,7 +5,7 @@ import { createFile } from '../createFile.ts'
5
5
  import type * as KubbFile from '../KubbFile.ts'
6
6
  import { getRelativePath } from '../utils/getRelativePath.ts'
7
7
  import { TreeNode } from '../utils/TreeNode.ts'
8
- import { createPlugin } from './createPlugin.ts'
8
+ import { definePlugin } from './definePlugin.ts'
9
9
 
10
10
  type Mode = 'all' | 'named' | 'propagate' | false
11
11
 
@@ -144,7 +144,7 @@ export function getBarrelFiles({ files, root, mode }: GetBarrelFilesOptions): Ar
144
144
  return result
145
145
  }
146
146
 
147
- export const barrelPlugin = createPlugin<Options, ExtendOptions>({
147
+ export const barrelPlugin = definePlugin<Options, ExtendOptions>({
148
148
  name: 'barrel',
149
149
  install(ctx, options) {
150
150
  if (!options) {
@@ -155,7 +155,7 @@ export const barrelPlugin = createPlugin<Options, ExtendOptions>({
155
155
  return undefined
156
156
  }
157
157
 
158
- ctx.on('write:start', async ({ files }) => {
158
+ ctx.on('files:writing:start', async ({ files }) => {
159
159
  const root = options.root
160
160
  const barrelFiles = getBarrelFiles({ files, root, mode: options.mode })
161
161
 
@@ -1,6 +1,6 @@
1
1
  import type { Plugin, UserPlugin } from './types.ts'
2
2
 
3
- export function createPlugin<Options = unknown, TAppExtension extends Record<string, any> = {}>(
3
+ export function definePlugin<Options = unknown, TAppExtension extends Record<string, any> = {}>(
4
4
  plugin: UserPlugin<Options, TAppExtension>,
5
5
  ): Plugin<Options, TAppExtension> {
6
6
  return {
@@ -1,7 +1,7 @@
1
1
  import { resolve } from 'node:path'
2
2
  import fs from 'fs-extra'
3
3
  import type * as KubbFile from '../KubbFile.ts'
4
- import { createPlugin } from './createPlugin.ts'
4
+ import { definePlugin } from './definePlugin.ts'
5
5
 
6
6
  type WriteOptions = {
7
7
  extension?: Record<KubbFile.Extname, KubbFile.Extname | ''>
@@ -85,14 +85,14 @@ declare global {
85
85
  }
86
86
  }
87
87
 
88
- export const fsPlugin = createPlugin<Options, ExtendOptions>({
88
+ export const fsPlugin = definePlugin<Options, ExtendOptions>({
89
89
  name: 'fs',
90
90
  install(ctx, options = {}) {
91
91
  if (options.clean) {
92
92
  fs.removeSync(options.clean.path)
93
93
  }
94
94
 
95
- ctx.on('process:progress', async ({ file, source }) => {
95
+ ctx.on('file:processing:update', async ({ file, source }) => {
96
96
  if (options.onBeforeWrite) {
97
97
  await options.onBeforeWrite(file.path, source)
98
98
  }
@@ -6,7 +6,7 @@ import { createFile } from '../createFile.ts'
6
6
  import type * as KubbFile from '../KubbFile.ts'
7
7
  import { open } from '../utils/open.ts'
8
8
  import { type Graph, TreeNode } from '../utils/TreeNode.ts'
9
- import { createPlugin } from './createPlugin.ts'
9
+ import { definePlugin } from './definePlugin.ts'
10
10
 
11
11
  type Options = {
12
12
  root: string
@@ -84,14 +84,14 @@ async function serve(root: string) {
84
84
  })
85
85
  }
86
86
 
87
- export const graphPlugin = createPlugin<Options>({
87
+ export const graphPlugin = definePlugin<Options>({
88
88
  name: 'graph',
89
89
  install(ctx, options) {
90
90
  if (!options) {
91
91
  throw new Error('Graph plugin requires options.root and options.mode')
92
92
  }
93
93
 
94
- ctx.on('write:start', async ({ files }) => {
94
+ ctx.on('files:writing:start', async ({ files }) => {
95
95
  const root = options.root
96
96
 
97
97
  const graph = getGraph({ files, root })
@@ -1,5 +1,5 @@
1
1
  export { barrelPlugin } from './barrelPlugin.ts'
2
- export { createPlugin } from './createPlugin.ts'
2
+ export { definePlugin } from './definePlugin.ts'
3
3
  export { fsPlugin } from './fsPlugin.ts'
4
4
  export { graphPlugin } from './graphPlugin.ts'
5
5
  export { loggerPlugin } from './loggerPlugin.ts'
@@ -6,10 +6,9 @@ import { createConsola, type LogLevel } from 'consola'
6
6
  import { WebSocket, WebSocketServer } from 'ws'
7
7
  import type { FabricEvents } from '../Fabric.ts'
8
8
  import type * as KubbFile from '../KubbFile.ts'
9
- import { createPlugin } from './createPlugin.ts'
9
+ import { definePlugin } from './definePlugin.ts'
10
10
 
11
11
  type Broadcast = <T = unknown>(event: keyof FabricEvents | string, payload: T) => void
12
-
13
12
  type WebSocketOptions = {
14
13
  /**
15
14
  * Hostname to bind the websocket server to.
@@ -43,7 +42,10 @@ type Options = {
43
42
  websocket?: boolean | WebSocketOptions
44
43
  }
45
44
 
46
- function normalizeAddress(address: AddressInfo): { host: string; port: number } {
45
+ function normalizeAddress(address: AddressInfo): {
46
+ host: string
47
+ port: number
48
+ } {
47
49
  const host = address.address === '::' ? '127.0.0.1' : address.address
48
50
 
49
51
  return { host, port: address.port }
@@ -76,7 +78,7 @@ const createProgressBar = () =>
76
78
  Presets.shades_grey,
77
79
  )
78
80
 
79
- export const loggerPlugin = createPlugin<Options>({
81
+ export const loggerPlugin = definePlugin<Options>({
80
82
  name: 'logger',
81
83
  install(ctx, options = {}) {
82
84
  const { level, websocket = true, progress = true } = options
@@ -140,23 +142,23 @@ export const loggerPlugin = createPlugin<Options>({
140
142
 
141
143
  const formatPath = (path: string) => relative(process.cwd(), path)
142
144
 
143
- ctx.on('start', async () => {
145
+ ctx.on('lifecycle:start', async () => {
144
146
  logger.start('Starting Fabric run')
145
- broadcast('start', { timestamp: Date.now() })
147
+ broadcast('lifecycle:start', { timestamp: Date.now() })
146
148
  })
147
149
 
148
- ctx.on('render', async () => {
150
+ ctx.on('lifecycle:render', async () => {
149
151
  logger.info('Rendering application graph')
150
- broadcast('render', { timestamp: Date.now() })
152
+ broadcast('lifecycle:render', { timestamp: Date.now() })
151
153
  })
152
154
 
153
- ctx.on('file:add', async ({ files }) => {
155
+ ctx.on('files:added', async ({ files }) => {
154
156
  if (!files.length) {
155
157
  return
156
158
  }
157
159
 
158
160
  logger.info(`Queued ${pluralize('file', files.length)}`)
159
- broadcast('file:add', {
161
+ broadcast('files:added', {
160
162
  files: files.map(serializeFile),
161
163
  })
162
164
  })
@@ -171,9 +173,12 @@ export const loggerPlugin = createPlugin<Options>({
171
173
  broadcast('file:resolve:name', { file: serializeFile(file) })
172
174
  })
173
175
 
174
- ctx.on('process:start', async ({ files }) => {
176
+ ctx.on('files:processing:start', async ({ files }) => {
175
177
  logger.start(`Processing ${pluralize('file', files.length)}`)
176
- broadcast('process:start', { total: files.length, timestamp: Date.now() })
178
+ broadcast('files:processing:start', {
179
+ total: files.length,
180
+ timestamp: Date.now(),
181
+ })
177
182
 
178
183
  if (progressBar) {
179
184
  logger.pauseLogs()
@@ -181,20 +186,20 @@ export const loggerPlugin = createPlugin<Options>({
181
186
  }
182
187
  })
183
188
 
184
- ctx.on('file:start', async ({ file, index, total }) => {
189
+ ctx.on('file:processing:start', async ({ file, index, total }) => {
185
190
  logger.info(`Processing [${index + 1}/${total}] ${formatPath(file.path)}`)
186
- broadcast('file:start', {
191
+ broadcast('file:processing:start', {
187
192
  index,
188
193
  total,
189
194
  file: serializeFile(file),
190
195
  })
191
196
  })
192
197
 
193
- ctx.on('process:progress', async ({ processed, total, percentage, file }) => {
198
+ ctx.on('file:processing:update', async ({ processed, total, percentage, file }) => {
194
199
  const formattedPercentage = Number.isFinite(percentage) ? percentage.toFixed(1) : '0.0'
195
200
 
196
201
  logger.info(`Progress ${formattedPercentage}% (${processed}/${total}) → ${formatPath(file.path)}`)
197
- broadcast('process:progress', {
202
+ broadcast('file:processing:update', {
198
203
  processed,
199
204
  total,
200
205
  percentage,
@@ -202,36 +207,41 @@ export const loggerPlugin = createPlugin<Options>({
202
207
  })
203
208
 
204
209
  if (progressBar) {
205
- progressBar.increment(1, { message: `Writing ${formatPath(file.path)}` })
210
+ progressBar.increment(1, {
211
+ message: `Writing ${formatPath(file.path)}`,
212
+ })
206
213
  }
207
214
  })
208
215
 
209
- ctx.on('file:end', async ({ file, index, total }) => {
216
+ ctx.on('file:processing:end', async ({ file, index, total }) => {
210
217
  logger.success(`Finished [${index + 1}/${total}] ${formatPath(file.path)}`)
211
- broadcast('file:end', {
218
+ broadcast('file:processing:end', {
212
219
  index,
213
220
  total,
214
221
  file: serializeFile(file),
215
222
  })
216
223
  })
217
224
 
218
- ctx.on('write:start', async ({ files }) => {
225
+ ctx.on('files:writing:start', async ({ files }) => {
219
226
  logger.start(`Writing ${pluralize('file', files.length)} to disk`)
220
- broadcast('write:start', {
227
+ broadcast('files:writing:start', {
221
228
  files: files.map(serializeFile),
222
229
  })
223
230
  })
224
231
 
225
- ctx.on('write:end', async ({ files }) => {
232
+ ctx.on('files:writing:end', async ({ files }) => {
226
233
  logger.success(`Written ${pluralize('file', files.length)} to disk`)
227
- broadcast('write:end', {
234
+ broadcast('files:writing:end', {
228
235
  files: files.map(serializeFile),
229
236
  })
230
237
  })
231
238
 
232
- ctx.on('process:end', async ({ files }) => {
239
+ ctx.on('files:processing:end', async ({ files }) => {
233
240
  logger.success(`Processed ${pluralize('file', files.length)}`)
234
- broadcast('process:end', { total: files.length, timestamp: Date.now() })
241
+ broadcast('files:processing:end', {
242
+ total: files.length,
243
+ timestamp: Date.now(),
244
+ })
235
245
 
236
246
  if (progressBar) {
237
247
  progressBar.update(files.length, { message: 'Done ✅' })
@@ -241,9 +251,9 @@ export const loggerPlugin = createPlugin<Options>({
241
251
  }
242
252
  })
243
253
 
244
- ctx.on('end', async () => {
254
+ ctx.on('lifecycle:end', async () => {
245
255
  logger.success('Fabric run completed')
246
- broadcast('end', { timestamp: Date.now() })
256
+ broadcast('lifecycle:end', { timestamp: Date.now() })
247
257
 
248
258
  if (progressBar) {
249
259
  progressBar.stop()