@kubb/fabric-core 0.5.4 → 0.6.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 (61) 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/index.cjs +73 -83
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.cts +7 -22
  15. package/dist/index.d.ts +7 -22
  16. package/dist/index.js +74 -83
  17. package/dist/index.js.map +1 -1
  18. package/dist/parsers/typescript.cjs +2 -2
  19. package/dist/parsers/typescript.d.cts +2 -2
  20. package/dist/parsers/typescript.d.ts +2 -2
  21. package/dist/parsers/typescript.js +2 -2
  22. package/dist/parsers.cjs +5 -5
  23. package/dist/parsers.cjs.map +1 -1
  24. package/dist/parsers.d.cts +6 -6
  25. package/dist/parsers.d.ts +6 -6
  26. package/dist/parsers.js +5 -5
  27. package/dist/parsers.js.map +1 -1
  28. package/dist/plugins.cjs +32 -32
  29. package/dist/plugins.cjs.map +1 -1
  30. package/dist/plugins.d.cts +4 -4
  31. package/dist/plugins.d.ts +4 -4
  32. package/dist/plugins.js +32 -32
  33. package/dist/plugins.js.map +1 -1
  34. package/dist/types.d.cts +1 -1
  35. package/dist/types.d.ts +1 -1
  36. package/dist/{typescriptParser-BN1vEX-I.d.ts → typescriptParser-9jJzfPj-.d.ts} +2 -2
  37. package/dist/{typescriptParser-Cw2wm0gX.js → typescriptParser-BLX7eX2k.js} +3 -3
  38. package/dist/{typescriptParser-Cw2wm0gX.js.map → typescriptParser-BLX7eX2k.js.map} +1 -1
  39. package/dist/{typescriptParser-BlRK18rx.d.cts → typescriptParser-DCFNN4BL.d.cts} +2 -2
  40. package/dist/{typescriptParser-DRdx9q2o.cjs → typescriptParser-OjFZ_DeI.cjs} +3 -3
  41. package/dist/{typescriptParser-DRdx9q2o.cjs.map → typescriptParser-OjFZ_DeI.cjs.map} +1 -1
  42. package/package.json +1 -1
  43. package/src/Fabric.ts +117 -21
  44. package/src/FileManager.ts +4 -4
  45. package/src/FileProcessor.ts +5 -5
  46. package/src/createFabric.ts +96 -2
  47. package/src/index.ts +0 -1
  48. package/src/parsers/defaultParser.ts +2 -2
  49. package/src/parsers/{createParser.ts → defineParser.ts} +1 -1
  50. package/src/parsers/index.ts +1 -2
  51. package/src/parsers/tsxParser.ts +2 -2
  52. package/src/parsers/typescriptParser.ts +2 -2
  53. package/src/plugins/barrelPlugin.ts +3 -3
  54. package/src/plugins/{createPlugin.ts → definePlugin.ts} +1 -1
  55. package/src/plugins/fsPlugin.ts +3 -3
  56. package/src/plugins/graphPlugin.ts +3 -3
  57. package/src/plugins/index.ts +1 -1
  58. package/src/plugins/loggerPlugin.ts +37 -27
  59. package/dist/createParser-C4IkyTs5.cjs +0 -17
  60. package/dist/createParser-D_ANHZTa.js +0 -11
  61. package/src/defineFabric.ts +0 -119
@@ -1 +1 @@
1
- {"version":3,"file":"plugins.js","names":["result: Array<TreeNode<TData>>","stack: Array<TreeNode<TData>>","nodes: Array<{ id: string; label: string }>","edges: Array<{ from: string; to: string }>","stack: Array<TreeNode<BarrelData>>","filteredFiles: Array<KubbFile.File>","indexableSources: Array<KubbFile.Source>","barrelFiles: Array<KubbFile.ResolvedFile>","exports: Array<KubbFile.Export>","path","path","server: http.Server | undefined","wss: WebSocketServer | undefined","broadcast: Broadcast","path","closures: Array<Promise<void>>","resolve"],"sources":["../src/utils/TreeNode.ts","../src/plugins/createPlugin.ts","../src/plugins/barrelPlugin.ts","../src/plugins/fsPlugin.ts","../src/utils/open.ts","../src/plugins/graphPlugin.ts","../src/plugins/loggerPlugin.ts"],"sourcesContent":["import type * as KubbFile from '../KubbFile.ts'\n\ntype BarrelData = {\n file?: KubbFile.File\n path: string\n name: string\n}\n\nexport type Graph = {\n nodes: Array<{ id: string; label: string }>\n edges: Array<{ from: string; to: string }>\n}\n\nexport class TreeNode<TData = unknown> {\n data: TData\n parent?: TreeNode<TData>\n children: Array<TreeNode<TData>> = []\n #childrenMap = new Map<string, TreeNode<TData>>()\n #cachedLeaves?: Array<TreeNode<TData>>\n\n constructor(data: TData, parent?: TreeNode<TData>) {\n this.data = data\n this.parent = parent\n }\n\n addChild(data: TData): TreeNode<TData> {\n const child = new TreeNode(data, this)\n this.children.push(child)\n // Update Map if data has a name property (for BarrelData)\n if (typeof data === 'object' && data !== null && 'name' in data) {\n this.#childrenMap.set((data as { name: string }).name, child)\n }\n this.#cachedLeaves = undefined // invalidate cached leaves\n return child\n }\n\n getChildByName(name: string): TreeNode<TData> | undefined {\n return this.#childrenMap.get(name)\n }\n\n get leaves(): Array<TreeNode<TData>> {\n if (this.#cachedLeaves) return this.#cachedLeaves\n if (this.children.length === 0) return [this]\n\n const result: Array<TreeNode<TData>> = []\n const stack: Array<TreeNode<TData>> = [...this.children]\n const visited = new Set<TreeNode<TData>>()\n\n while (stack.length > 0) {\n const node = stack.pop()!\n if (visited.has(node)) {\n continue\n }\n visited.add(node)\n\n if (node.children.length > 0) {\n stack.push(...node.children)\n } else {\n result.push(node)\n }\n }\n\n this.#cachedLeaves = result\n return result\n }\n\n forEach(callback: (node: TreeNode<TData>) => void): this {\n const stack: Array<TreeNode<TData>> = [this]\n\n for (let i = 0; i < stack.length; i++) {\n const node = stack[i]!\n callback(node)\n\n if (node.children.length > 0) {\n stack.push(...node.children)\n }\n }\n\n return this\n }\n\n findDeep(predicate: (node: TreeNode<TData>) => boolean): TreeNode<TData> | undefined {\n for (const leaf of this.leaves) {\n if (predicate(leaf)) return leaf\n }\n return undefined\n }\n\n static toGraph(root: TreeNode<BarrelData>): Graph {\n const nodes: Array<{ id: string; label: string }> = []\n const edges: Array<{ from: string; to: string }> = []\n\n const stack: Array<TreeNode<BarrelData>> = [root]\n\n for (let i = 0; i < stack.length; i++) {\n const node = stack[i]!\n\n nodes.push({\n id: node.data.path,\n label: node.data.name,\n })\n\n const children = node.children\n if (children.length > 0) {\n for (let j = 0, len = children.length; j < len; j++) {\n const child = children[j]!\n edges.push({\n from: node.data.path,\n to: child.data.path,\n })\n stack.push(child)\n }\n }\n }\n\n return { nodes, edges }\n }\n\n static fromFiles(files: Array<KubbFile.File>, rootFolder = ''): TreeNode<BarrelData> | null {\n const normalizePath = (p: string): string => p.replace(/\\\\/g, '/')\n const normalizedRoot = normalizePath(rootFolder)\n const rootPrefix = normalizedRoot.endsWith('/') ? normalizedRoot : `${normalizedRoot}/`\n\n const normalizedPaths = new Map<KubbFile.File, string>()\n const filteredFiles: Array<KubbFile.File> = []\n for (const file of files) {\n const filePath = normalizedPaths.get(file) ?? normalizePath(file.path)\n normalizedPaths.set(file, filePath)\n if (!filePath.endsWith('.json') && (!rootFolder || filePath.startsWith(rootPrefix))) {\n filteredFiles.push(file)\n }\n }\n\n if (filteredFiles.length === 0) {\n return null\n }\n\n const treeNode = new TreeNode<BarrelData>({\n name: rootFolder || '',\n path: rootFolder || '',\n file: undefined,\n })\n\n for (const file of filteredFiles) {\n const filePath = normalizedPaths.get(file)!\n const relPath = filePath.slice(rootPrefix.length)\n const parts = relPath.split('/')\n\n let current = treeNode\n let currentPath = rootFolder\n\n for (const [index, part] of parts.entries()) {\n const isLast = index === parts.length - 1\n currentPath += (currentPath.endsWith('/') ? '' : '/') + part\n\n let next = current.getChildByName(part)\n\n if (!next) {\n next = current.addChild({\n name: part,\n path: currentPath,\n file: isLast ? file : undefined,\n })\n }\n\n current = next\n }\n }\n\n return treeNode\n }\n}\n","import type { Plugin, UserPlugin } from './types.ts'\n\nexport function createPlugin<Options = unknown, TAppExtension extends Record<string, any> = {}>(\n plugin: UserPlugin<Options, TAppExtension>,\n): Plugin<Options, TAppExtension> {\n return {\n type: 'plugin',\n ...plugin,\n }\n}\n","/** biome-ignore-all lint/suspicious/useIterableCallbackReturn: not needed */\n\nimport path from 'node:path'\nimport { createFile } from '../createFile.ts'\nimport type * as KubbFile from '../KubbFile.ts'\nimport { getRelativePath } from '../utils/getRelativePath.ts'\nimport { TreeNode } from '../utils/TreeNode.ts'\nimport { createPlugin } from './createPlugin.ts'\n\ntype Mode = 'all' | 'named' | 'propagate' | false\n\ntype Options = {\n root: string\n mode: Mode\n dryRun?: boolean\n}\n\ntype WriteEntryOptions = {\n root: string\n mode: Mode\n}\n\ntype ExtendOptions = {\n /**\n * `fabric.writeEntry` should be called before `fabric.write`\n */\n writeEntry(options: WriteEntryOptions): Promise<void>\n}\n\ndeclare global {\n namespace Kubb {\n interface Fabric {\n /**\n * `fabric.writeEntry` should be called before `fabric.write`\n */\n writeEntry(options: WriteEntryOptions): Promise<void>\n }\n }\n}\n\ntype GetBarrelFilesOptions = {\n files: KubbFile.File[]\n root: string\n mode: Mode\n}\n\nexport function getBarrelFiles({ files, root, mode }: GetBarrelFilesOptions): Array<KubbFile.File> {\n // Do not generate when propagating or disabled\n if (mode === 'propagate' || mode === false) {\n return []\n }\n\n const indexableSourcesMap = new Map<KubbFile.File, Array<KubbFile.Source>>()\n\n for (const file of files) {\n const indexableSources: Array<KubbFile.Source> = []\n for (const source of file.sources || []) {\n if (source.isIndexable && source.name) {\n indexableSources.push(source)\n }\n }\n if (indexableSources.length > 0) {\n indexableSourcesMap.set(file, indexableSources)\n }\n }\n\n const cachedFiles = new Map<KubbFile.Path, KubbFile.File>()\n const dedupe = new Map<KubbFile.Path, Set<string>>()\n\n const treeNode = TreeNode.fromFiles(files, root)\n\n if (!treeNode) {\n return []\n }\n\n treeNode.forEach((node) => {\n // Only create a barrel for directory-like nodes that have a parent with a path\n if (!node?.children || !node.parent?.data.path) {\n return\n }\n\n const parentPath = node.parent.data.path as KubbFile.Path\n const barrelPath = path.join(parentPath, 'index.ts') as KubbFile.Path\n\n let barrelFile = cachedFiles.get(barrelPath)\n if (!barrelFile) {\n barrelFile = createFile({\n path: barrelPath,\n baseName: 'index.ts',\n exports: [],\n sources: [],\n })\n cachedFiles.set(barrelPath, barrelFile)\n dedupe.set(barrelPath, new Set<string>())\n }\n\n const seen = dedupe.get(barrelPath)!\n\n for (const leaf of node.leaves) {\n const file = leaf.data.file\n if (!file || !file.path) {\n continue\n }\n\n const indexableSources = indexableSourcesMap.get(file)\n if (!indexableSources) {\n continue\n }\n\n for (const source of indexableSources) {\n const key = `${source.name}|${source.isTypeOnly ? '1' : '0'}`\n if (seen.has(key)) {\n continue\n }\n seen.add(key)\n\n // Always compute relative path from the parent directory to the file path\n barrelFile!.exports!.push({\n name: [source.name!],\n path: getRelativePath(parentPath, file.path),\n isTypeOnly: source.isTypeOnly,\n })\n\n barrelFile!.sources.push({\n name: source.name!,\n isTypeOnly: source.isTypeOnly,\n value: '', // TODO use parser to generate import\n isExportable: mode === 'all' || mode === 'named',\n isIndexable: mode === 'all' || mode === 'named',\n })\n }\n }\n })\n\n const result = [...cachedFiles.values()]\n\n if (mode === 'all') {\n return result.map((file) => ({\n ...file,\n exports: file.exports?.map((e) => ({ ...e, name: undefined })),\n }))\n }\n\n return result\n}\n\nexport const barrelPlugin = createPlugin<Options, ExtendOptions>({\n name: 'barrel',\n install(ctx, options) {\n if (!options) {\n throw new Error('Barrel plugin requires options.root and options.mode')\n }\n\n if (!options.mode) {\n return undefined\n }\n\n ctx.on('write:start', async ({ files }) => {\n const root = options.root\n const barrelFiles = getBarrelFiles({ files, root, mode: options.mode })\n\n await ctx.fileManager.add(...barrelFiles)\n })\n },\n inject(ctx, options) {\n if (!options) {\n throw new Error('Barrel plugin requires options.root and options.mode')\n }\n\n return {\n async writeEntry({ root, mode }) {\n if (!mode || mode === 'propagate') {\n return undefined\n }\n\n const rootPath = path.resolve(root, 'index.ts')\n\n const barrelFiles: Array<KubbFile.ResolvedFile> = []\n for (const file of ctx.files) {\n for (const source of file.sources) {\n if (source.isIndexable) {\n barrelFiles.push(file)\n\n break\n }\n }\n }\n\n const fileTypeCache = new Map<KubbFile.ResolvedFile, boolean>()\n for (const file of barrelFiles) {\n fileTypeCache.set(\n file,\n file.sources.every((source) => source.isTypeOnly),\n )\n }\n\n const exports: Array<KubbFile.Export> = []\n for (const file of barrelFiles) {\n const containsOnlyTypes = fileTypeCache.get(file) ?? false\n\n for (const source of file.sources) {\n if (!file.path || !source.isIndexable) {\n continue\n }\n\n exports.push({\n name: mode === 'all' ? undefined : [source.name],\n path: getRelativePath(rootPath, file.path),\n isTypeOnly: mode === 'all' ? containsOnlyTypes : source.isTypeOnly,\n } as KubbFile.Export)\n }\n }\n\n const entryFile = createFile({\n path: rootPath,\n baseName: 'index.ts',\n exports,\n sources: [],\n })\n\n await ctx.addFile(entryFile)\n\n await ctx.fileManager.write({\n mode: ctx.config.mode,\n dryRun: options.dryRun,\n parsers: ctx.installedParsers,\n })\n },\n }\n },\n})\n","import { resolve } from 'node:path'\nimport fs from 'fs-extra'\nimport type * as KubbFile from '../KubbFile.ts'\nimport { createPlugin } from './createPlugin.ts'\n\ntype WriteOptions = {\n extension?: Record<KubbFile.Extname, KubbFile.Extname | ''>\n}\n\ntype Options = {\n dryRun?: boolean\n /**\n * Optional callback that is invoked whenever a file is written by the plugin.\n * Useful for tests to observe write operations without spying on internal functions.\n */\n onBeforeWrite?: (path: string, data: string | undefined) => void | Promise<void>\n clean?: {\n path: string\n }\n}\n\ntype ExtendOptions = {\n write(options?: WriteOptions): Promise<void>\n}\n\nexport async function write(path: string, data: string | undefined, options: { sanity?: boolean } = {}): Promise<string | undefined> {\n if (typeof Bun !== 'undefined') {\n if (!data || data?.trim() === '') {\n return undefined\n }\n\n await Bun.write(resolve(path), data.trim())\n\n if (options?.sanity) {\n const file = Bun.file(resolve(path))\n const savedData = await file.text()\n\n if (savedData?.toString() !== data?.toString()) {\n throw new Error(`Sanity check failed for ${path}\\n\\nData[${data.length}]:\\n${data}\\n\\nSaved[${savedData.length}]:\\n${savedData}\\n`)\n }\n\n return savedData\n }\n\n return data\n }\n\n if (!data || data?.trim() === '') {\n return undefined\n }\n\n try {\n const oldContent = await fs.readFile(resolve(path), {\n encoding: 'utf-8',\n })\n if (oldContent?.toString() === data?.toString()) {\n return\n }\n } catch (_err) {\n /* empty */\n }\n\n await fs.outputFile(resolve(path), data.trim(), { encoding: 'utf-8' })\n\n if (options?.sanity) {\n const savedData = await fs.readFile(resolve(path), {\n encoding: 'utf-8',\n })\n\n if (savedData?.toString() !== data?.toString()) {\n throw new Error(`Sanity check failed for ${path}\\n\\nData[${data.length}]:\\n${data}\\n\\nSaved[${savedData.length}]:\\n${savedData}\\n`)\n }\n\n return savedData\n }\n\n return data\n}\n\ndeclare global {\n namespace Kubb {\n interface Fabric {\n write(options?: WriteOptions): Promise<void>\n }\n }\n}\n\nexport const fsPlugin = createPlugin<Options, ExtendOptions>({\n name: 'fs',\n install(ctx, options = {}) {\n if (options.clean) {\n fs.removeSync(options.clean.path)\n }\n\n ctx.on('process:progress', async ({ file, source }) => {\n if (options.onBeforeWrite) {\n await options.onBeforeWrite(file.path, source)\n }\n await write(file.path, source, { sanity: false })\n })\n },\n inject(ctx, { dryRun } = {}) {\n return {\n async write(\n options = {\n extension: { '.ts': '.ts' },\n },\n ) {\n await ctx.fileManager.write({\n mode: ctx.config.mode,\n extension: options.extension,\n dryRun,\n parsers: ctx.installedParsers,\n })\n },\n }\n },\n})\n","import { spawn } from 'node:child_process'\n\nconst spawnBin = (bin: string, args: string[]): Promise<boolean> => {\n return new Promise((resolve) => {\n const process = spawn(bin, args, {\n detached: true,\n shell: false,\n windowsHide: true,\n })\n\n process.on('close', (code) => {\n resolve(!code)\n })\n })\n}\n\ntype Options = {\n app?: string\n}\n\nexport async function open(path: string, options?: Options): Promise<boolean> {\n const app = options?.app\n\n if (process.platform === 'win32') {\n return spawnBin('cmd.exe', ['/c', 'start', app || '', path.replace(/[&^]/g, '^$&')])\n }\n\n if (process.platform === 'linux') {\n return spawnBin(app || 'xdg-open', [path])\n }\n if (process.platform === 'darwin') {\n return spawnBin('open', app ? ['-a', app, path] : [path])\n }\n\n throw new Error(`Unsupported platform, could not open \"${path}\"`)\n}\n","import http from 'node:http'\nimport type { AddressInfo } from 'node:net'\nimport path from 'node:path'\nimport handler from 'serve-handler'\nimport { createFile } from '../createFile.ts'\nimport type * as KubbFile from '../KubbFile.ts'\nimport { open } from '../utils/open.ts'\nimport { type Graph, TreeNode } from '../utils/TreeNode.ts'\nimport { createPlugin } from './createPlugin.ts'\n\ntype Options = {\n root: string\n /**\n * @default false\n */\n open?: boolean\n}\n\ntype GetGraphOptions = {\n files: KubbFile.File[]\n root: string\n}\n\nexport function getGraph({ files, root }: GetGraphOptions): Graph | undefined {\n const treeNode = TreeNode.fromFiles(files, root)\n\n if (!treeNode) {\n return undefined\n }\n\n return TreeNode.toGraph(treeNode)\n}\nconst html = `\n <!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <title>File Graph</title>\n <script type=\"module\">\n import { Network } from 'https://cdn.jsdelivr.net/npm/vis-network/standalone/esm/vis-network.min.js'\n\n async function main() {\n const res = await fetch('./graph.json')\n const { nodes, edges } = await res.json()\n const container = document.getElementById('graph')\n\n const network = new Network(\n container,\n { nodes, edges },\n {\n layout: { hierarchical: { direction: 'UD', sortMethod: 'directed' } },\n nodes: { shape: 'box', font: { face: 'monospace' } },\n edges: { arrows: 'to' },\n physics: false,\n },\n )\n }\n\n main()\n </script>\n <style>\n html, body, #graph { height: 100%; margin: 0; }\n </style>\n </head>\n <body>\n <div id=\"graph\"></div>\n </body>\n</html>\n`\n\nasync function serve(root: string) {\n const server = http.createServer((req, res) => {\n return handler(req, res, {\n public: root,\n cleanUrls: true,\n })\n })\n\n server.listen(0, async () => {\n const { port } = server.address() as AddressInfo\n console.log(`Running on http://localhost:${port}/graph.html`)\n\n await open(`http://localhost:${port}/graph.html`)\n })\n}\n\nexport const graphPlugin = createPlugin<Options>({\n name: 'graph',\n install(ctx, options) {\n if (!options) {\n throw new Error('Graph plugin requires options.root and options.mode')\n }\n\n ctx.on('write:start', async ({ files }) => {\n const root = options.root\n\n const graph = getGraph({ files, root })\n\n if (!graph) {\n return undefined\n }\n\n const graphFile = createFile({\n baseName: 'graph.json',\n path: path.join(root, 'graph.json'),\n sources: [\n {\n name: 'graph',\n value: JSON.stringify(graph, null, 2),\n },\n ],\n })\n\n const graphHtmlFile = createFile({\n baseName: 'graph.html',\n path: path.join(root, 'graph.html'),\n sources: [\n {\n name: 'graph',\n value: html,\n },\n ],\n })\n\n await ctx.addFile(graphFile, graphHtmlFile)\n\n if (options.open) {\n await serve(root)\n }\n })\n },\n})\n","import http from 'node:http'\nimport type { AddressInfo } from 'node:net'\nimport { relative } from 'node:path'\nimport { Presets, SingleBar } from 'cli-progress'\nimport { createConsola, type LogLevel } from 'consola'\nimport { WebSocket, WebSocketServer } from 'ws'\nimport type { FabricEvents } from '../Fabric.ts'\nimport type * as KubbFile from '../KubbFile.ts'\nimport { createPlugin } from './createPlugin.ts'\n\ntype Broadcast = <T = unknown>(event: keyof FabricEvents | string, payload: T) => void\n\ntype WebSocketOptions = {\n /**\n * Hostname to bind the websocket server to.\n * @default '127.0.0.1'\n */\n host?: string\n /**\n * Port to bind the websocket server to.\n * @default 0 (random available port)\n */\n port?: number\n}\n\ntype Options = {\n /**\n * Explicit consola log level.\n */\n level?: LogLevel\n /**\n * Toggle progress bar output.\n * @default true\n */\n progress?: boolean\n /**\n * Toggle or configure the websocket broadcast server.\n * When `true`, a websocket server is started on an ephemeral port.\n * When `false`, websocket support is disabled.\n * When providing an object, the server uses the supplied host and port.\n * @default true\n */\n websocket?: boolean | WebSocketOptions\n}\n\nfunction normalizeAddress(address: AddressInfo): { host: string; port: number } {\n const host = address.address === '::' ? '127.0.0.1' : address.address\n\n return { host, port: address.port }\n}\n\nfunction serializeFile(file: KubbFile.File | KubbFile.ResolvedFile) {\n return {\n path: file.path,\n baseName: file.baseName,\n name: 'name' in file ? file.name : undefined,\n extname: 'extname' in file ? file.extname : undefined,\n }\n}\n\nfunction pluralize(word: string, count: number) {\n return `${count} ${word}${count === 1 ? '' : 's'}`\n}\n\nconst defaultTag = 'Fabric'\n\nconst createProgressBar = () =>\n new SingleBar(\n {\n format: '{bar} {percentage}% | {value}/{total} | {message}',\n barCompleteChar: '█',\n barIncompleteChar: '░',\n hideCursor: true,\n clearOnComplete: true,\n },\n Presets.shades_grey,\n )\n\nexport const loggerPlugin = createPlugin<Options>({\n name: 'logger',\n install(ctx, options = {}) {\n const { level, websocket = true, progress = true } = options\n\n const logger = createConsola(level !== undefined ? { level } : {}).withTag(defaultTag)\n\n const progressBar = progress ? createProgressBar() : undefined\n\n let server: http.Server | undefined\n let wss: WebSocketServer | undefined\n\n const broadcast: Broadcast = (event, payload) => {\n if (!wss) {\n return\n }\n\n const message = JSON.stringify({ event, payload })\n\n for (const client of wss.clients) {\n if (client.readyState === WebSocket.OPEN) {\n client.send(message)\n }\n }\n }\n\n if (websocket) {\n const { host = '127.0.0.1', port = 0 } = typeof websocket === 'boolean' ? {} : websocket\n\n server = http.createServer()\n wss = new WebSocketServer({ server })\n\n server.listen(port, host, () => {\n const addressInfo = server?.address()\n\n if (addressInfo && typeof addressInfo === 'object') {\n const { host: resolvedHost, port: resolvedPort } = normalizeAddress(addressInfo)\n const url = `ws://${resolvedHost}:${resolvedPort}`\n\n logger.info(`Logger websocket listening on ${url}`)\n broadcast('websocket:ready', { url })\n }\n })\n\n wss.on('connection', (socket) => {\n logger.info('Logger websocket client connected')\n socket.send(\n JSON.stringify({\n event: 'welcome',\n payload: {\n message: 'Connected to Fabric log stream',\n timestamp: Date.now(),\n },\n }),\n )\n })\n\n wss.on('error', (error) => {\n logger.error('Logger websocket error', error)\n })\n }\n\n const formatPath = (path: string) => relative(process.cwd(), path)\n\n ctx.on('start', async () => {\n logger.start('Starting Fabric run')\n broadcast('start', { timestamp: Date.now() })\n })\n\n ctx.on('render', async () => {\n logger.info('Rendering application graph')\n broadcast('render', { timestamp: Date.now() })\n })\n\n ctx.on('file:add', async ({ files }) => {\n if (!files.length) {\n return\n }\n\n logger.info(`Queued ${pluralize('file', files.length)}`)\n broadcast('file:add', {\n files: files.map(serializeFile),\n })\n })\n\n ctx.on('file:resolve:path', async ({ file }) => {\n logger.info(`Resolving path for ${formatPath(file.path)}`)\n broadcast('file:resolve:path', { file: serializeFile(file) })\n })\n\n ctx.on('file:resolve:name', async ({ file }) => {\n logger.info(`Resolving name for ${formatPath(file.path)}`)\n broadcast('file:resolve:name', { file: serializeFile(file) })\n })\n\n ctx.on('process:start', async ({ files }) => {\n logger.start(`Processing ${pluralize('file', files.length)}`)\n broadcast('process:start', { total: files.length, timestamp: Date.now() })\n\n if (progressBar) {\n logger.pauseLogs()\n progressBar.start(files.length, 0, { message: 'Starting...' })\n }\n })\n\n ctx.on('file:start', async ({ file, index, total }) => {\n logger.info(`Processing [${index + 1}/${total}] ${formatPath(file.path)}`)\n broadcast('file:start', {\n index,\n total,\n file: serializeFile(file),\n })\n })\n\n ctx.on('process:progress', async ({ processed, total, percentage, file }) => {\n const formattedPercentage = Number.isFinite(percentage) ? percentage.toFixed(1) : '0.0'\n\n logger.info(`Progress ${formattedPercentage}% (${processed}/${total}) → ${formatPath(file.path)}`)\n broadcast('process:progress', {\n processed,\n total,\n percentage,\n file: serializeFile(file),\n })\n\n if (progressBar) {\n progressBar.increment(1, { message: `Writing ${formatPath(file.path)}` })\n }\n })\n\n ctx.on('file:end', async ({ file, index, total }) => {\n logger.success(`Finished [${index + 1}/${total}] ${formatPath(file.path)}`)\n broadcast('file:end', {\n index,\n total,\n file: serializeFile(file),\n })\n })\n\n ctx.on('write:start', async ({ files }) => {\n logger.start(`Writing ${pluralize('file', files.length)} to disk`)\n broadcast('write:start', {\n files: files.map(serializeFile),\n })\n })\n\n ctx.on('write:end', async ({ files }) => {\n logger.success(`Written ${pluralize('file', files.length)} to disk`)\n broadcast('write:end', {\n files: files.map(serializeFile),\n })\n })\n\n ctx.on('process:end', async ({ files }) => {\n logger.success(`Processed ${pluralize('file', files.length)}`)\n broadcast('process:end', { total: files.length, timestamp: Date.now() })\n\n if (progressBar) {\n progressBar.update(files.length, { message: 'Done ✅' })\n progressBar.stop()\n\n logger.resumeLogs()\n }\n })\n\n ctx.on('end', async () => {\n logger.success('Fabric run completed')\n broadcast('end', { timestamp: Date.now() })\n\n if (progressBar) {\n progressBar.stop()\n logger.resumeLogs()\n }\n\n const closures: Array<Promise<void>> = []\n\n if (wss) {\n const wsServer = wss\n\n closures.push(\n new Promise((resolve) => {\n for (const client of wsServer.clients) {\n client.close()\n }\n wsServer.close(() => resolve())\n }),\n )\n }\n\n if (server) {\n const httpServer = server\n\n closures.push(\n new Promise((resolve) => {\n httpServer.close(() => resolve())\n }),\n )\n }\n\n if (closures.length) {\n await Promise.allSettled(closures)\n logger.info('Logger websocket closed')\n }\n })\n },\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"plugins.js","names":["result: Array<TreeNode<TData>>","stack: Array<TreeNode<TData>>","nodes: Array<{ id: string; label: string }>","edges: Array<{ from: string; to: string }>","stack: Array<TreeNode<BarrelData>>","filteredFiles: Array<KubbFile.File>","indexableSources: Array<KubbFile.Source>","barrelFiles: Array<KubbFile.ResolvedFile>","exports: Array<KubbFile.Export>","path","path","server: http.Server | undefined","wss: WebSocketServer | undefined","broadcast: Broadcast","path","closures: Array<Promise<void>>","resolve"],"sources":["../src/utils/TreeNode.ts","../src/plugins/definePlugin.ts","../src/plugins/barrelPlugin.ts","../src/plugins/fsPlugin.ts","../src/utils/open.ts","../src/plugins/graphPlugin.ts","../src/plugins/loggerPlugin.ts"],"sourcesContent":["import type * as KubbFile from '../KubbFile.ts'\n\ntype BarrelData = {\n file?: KubbFile.File\n path: string\n name: string\n}\n\nexport type Graph = {\n nodes: Array<{ id: string; label: string }>\n edges: Array<{ from: string; to: string }>\n}\n\nexport class TreeNode<TData = unknown> {\n data: TData\n parent?: TreeNode<TData>\n children: Array<TreeNode<TData>> = []\n #childrenMap = new Map<string, TreeNode<TData>>()\n #cachedLeaves?: Array<TreeNode<TData>>\n\n constructor(data: TData, parent?: TreeNode<TData>) {\n this.data = data\n this.parent = parent\n }\n\n addChild(data: TData): TreeNode<TData> {\n const child = new TreeNode(data, this)\n this.children.push(child)\n // Update Map if data has a name property (for BarrelData)\n if (typeof data === 'object' && data !== null && 'name' in data) {\n this.#childrenMap.set((data as { name: string }).name, child)\n }\n this.#cachedLeaves = undefined // invalidate cached leaves\n return child\n }\n\n getChildByName(name: string): TreeNode<TData> | undefined {\n return this.#childrenMap.get(name)\n }\n\n get leaves(): Array<TreeNode<TData>> {\n if (this.#cachedLeaves) return this.#cachedLeaves\n if (this.children.length === 0) return [this]\n\n const result: Array<TreeNode<TData>> = []\n const stack: Array<TreeNode<TData>> = [...this.children]\n const visited = new Set<TreeNode<TData>>()\n\n while (stack.length > 0) {\n const node = stack.pop()!\n if (visited.has(node)) {\n continue\n }\n visited.add(node)\n\n if (node.children.length > 0) {\n stack.push(...node.children)\n } else {\n result.push(node)\n }\n }\n\n this.#cachedLeaves = result\n return result\n }\n\n forEach(callback: (node: TreeNode<TData>) => void): this {\n const stack: Array<TreeNode<TData>> = [this]\n\n for (let i = 0; i < stack.length; i++) {\n const node = stack[i]!\n callback(node)\n\n if (node.children.length > 0) {\n stack.push(...node.children)\n }\n }\n\n return this\n }\n\n findDeep(predicate: (node: TreeNode<TData>) => boolean): TreeNode<TData> | undefined {\n for (const leaf of this.leaves) {\n if (predicate(leaf)) return leaf\n }\n return undefined\n }\n\n static toGraph(root: TreeNode<BarrelData>): Graph {\n const nodes: Array<{ id: string; label: string }> = []\n const edges: Array<{ from: string; to: string }> = []\n\n const stack: Array<TreeNode<BarrelData>> = [root]\n\n for (let i = 0; i < stack.length; i++) {\n const node = stack[i]!\n\n nodes.push({\n id: node.data.path,\n label: node.data.name,\n })\n\n const children = node.children\n if (children.length > 0) {\n for (let j = 0, len = children.length; j < len; j++) {\n const child = children[j]!\n edges.push({\n from: node.data.path,\n to: child.data.path,\n })\n stack.push(child)\n }\n }\n }\n\n return { nodes, edges }\n }\n\n static fromFiles(files: Array<KubbFile.File>, rootFolder = ''): TreeNode<BarrelData> | null {\n const normalizePath = (p: string): string => p.replace(/\\\\/g, '/')\n const normalizedRoot = normalizePath(rootFolder)\n const rootPrefix = normalizedRoot.endsWith('/') ? normalizedRoot : `${normalizedRoot}/`\n\n const normalizedPaths = new Map<KubbFile.File, string>()\n const filteredFiles: Array<KubbFile.File> = []\n for (const file of files) {\n const filePath = normalizedPaths.get(file) ?? normalizePath(file.path)\n normalizedPaths.set(file, filePath)\n if (!filePath.endsWith('.json') && (!rootFolder || filePath.startsWith(rootPrefix))) {\n filteredFiles.push(file)\n }\n }\n\n if (filteredFiles.length === 0) {\n return null\n }\n\n const treeNode = new TreeNode<BarrelData>({\n name: rootFolder || '',\n path: rootFolder || '',\n file: undefined,\n })\n\n for (const file of filteredFiles) {\n const filePath = normalizedPaths.get(file)!\n const relPath = filePath.slice(rootPrefix.length)\n const parts = relPath.split('/')\n\n let current = treeNode\n let currentPath = rootFolder\n\n for (const [index, part] of parts.entries()) {\n const isLast = index === parts.length - 1\n currentPath += (currentPath.endsWith('/') ? '' : '/') + part\n\n let next = current.getChildByName(part)\n\n if (!next) {\n next = current.addChild({\n name: part,\n path: currentPath,\n file: isLast ? file : undefined,\n })\n }\n\n current = next\n }\n }\n\n return treeNode\n }\n}\n","import type { Plugin, UserPlugin } from './types.ts'\n\nexport function definePlugin<Options = unknown, TAppExtension extends Record<string, any> = {}>(\n plugin: UserPlugin<Options, TAppExtension>,\n): Plugin<Options, TAppExtension> {\n return {\n type: 'plugin',\n ...plugin,\n }\n}\n","/** biome-ignore-all lint/suspicious/useIterableCallbackReturn: not needed */\n\nimport path from 'node:path'\nimport { createFile } from '../createFile.ts'\nimport type * as KubbFile from '../KubbFile.ts'\nimport { getRelativePath } from '../utils/getRelativePath.ts'\nimport { TreeNode } from '../utils/TreeNode.ts'\nimport { definePlugin } from './definePlugin.ts'\n\ntype Mode = 'all' | 'named' | 'propagate' | false\n\ntype Options = {\n root: string\n mode: Mode\n dryRun?: boolean\n}\n\ntype WriteEntryOptions = {\n root: string\n mode: Mode\n}\n\ntype ExtendOptions = {\n /**\n * `fabric.writeEntry` should be called before `fabric.write`\n */\n writeEntry(options: WriteEntryOptions): Promise<void>\n}\n\ndeclare global {\n namespace Kubb {\n interface Fabric {\n /**\n * `fabric.writeEntry` should be called before `fabric.write`\n */\n writeEntry(options: WriteEntryOptions): Promise<void>\n }\n }\n}\n\ntype GetBarrelFilesOptions = {\n files: KubbFile.File[]\n root: string\n mode: Mode\n}\n\nexport function getBarrelFiles({ files, root, mode }: GetBarrelFilesOptions): Array<KubbFile.File> {\n // Do not generate when propagating or disabled\n if (mode === 'propagate' || mode === false) {\n return []\n }\n\n const indexableSourcesMap = new Map<KubbFile.File, Array<KubbFile.Source>>()\n\n for (const file of files) {\n const indexableSources: Array<KubbFile.Source> = []\n for (const source of file.sources || []) {\n if (source.isIndexable && source.name) {\n indexableSources.push(source)\n }\n }\n if (indexableSources.length > 0) {\n indexableSourcesMap.set(file, indexableSources)\n }\n }\n\n const cachedFiles = new Map<KubbFile.Path, KubbFile.File>()\n const dedupe = new Map<KubbFile.Path, Set<string>>()\n\n const treeNode = TreeNode.fromFiles(files, root)\n\n if (!treeNode) {\n return []\n }\n\n treeNode.forEach((node) => {\n // Only create a barrel for directory-like nodes that have a parent with a path\n if (!node?.children || !node.parent?.data.path) {\n return\n }\n\n const parentPath = node.parent.data.path as KubbFile.Path\n const barrelPath = path.join(parentPath, 'index.ts') as KubbFile.Path\n\n let barrelFile = cachedFiles.get(barrelPath)\n if (!barrelFile) {\n barrelFile = createFile({\n path: barrelPath,\n baseName: 'index.ts',\n exports: [],\n sources: [],\n })\n cachedFiles.set(barrelPath, barrelFile)\n dedupe.set(barrelPath, new Set<string>())\n }\n\n const seen = dedupe.get(barrelPath)!\n\n for (const leaf of node.leaves) {\n const file = leaf.data.file\n if (!file || !file.path) {\n continue\n }\n\n const indexableSources = indexableSourcesMap.get(file)\n if (!indexableSources) {\n continue\n }\n\n for (const source of indexableSources) {\n const key = `${source.name}|${source.isTypeOnly ? '1' : '0'}`\n if (seen.has(key)) {\n continue\n }\n seen.add(key)\n\n // Always compute relative path from the parent directory to the file path\n barrelFile!.exports!.push({\n name: [source.name!],\n path: getRelativePath(parentPath, file.path),\n isTypeOnly: source.isTypeOnly,\n })\n\n barrelFile!.sources.push({\n name: source.name!,\n isTypeOnly: source.isTypeOnly,\n value: '', // TODO use parser to generate import\n isExportable: mode === 'all' || mode === 'named',\n isIndexable: mode === 'all' || mode === 'named',\n })\n }\n }\n })\n\n const result = [...cachedFiles.values()]\n\n if (mode === 'all') {\n return result.map((file) => ({\n ...file,\n exports: file.exports?.map((e) => ({ ...e, name: undefined })),\n }))\n }\n\n return result\n}\n\nexport const barrelPlugin = definePlugin<Options, ExtendOptions>({\n name: 'barrel',\n install(ctx, options) {\n if (!options) {\n throw new Error('Barrel plugin requires options.root and options.mode')\n }\n\n if (!options.mode) {\n return undefined\n }\n\n ctx.on('files:writing:start', async ({ files }) => {\n const root = options.root\n const barrelFiles = getBarrelFiles({ files, root, mode: options.mode })\n\n await ctx.fileManager.add(...barrelFiles)\n })\n },\n inject(ctx, options) {\n if (!options) {\n throw new Error('Barrel plugin requires options.root and options.mode')\n }\n\n return {\n async writeEntry({ root, mode }) {\n if (!mode || mode === 'propagate') {\n return undefined\n }\n\n const rootPath = path.resolve(root, 'index.ts')\n\n const barrelFiles: Array<KubbFile.ResolvedFile> = []\n for (const file of ctx.files) {\n for (const source of file.sources) {\n if (source.isIndexable) {\n barrelFiles.push(file)\n\n break\n }\n }\n }\n\n const fileTypeCache = new Map<KubbFile.ResolvedFile, boolean>()\n for (const file of barrelFiles) {\n fileTypeCache.set(\n file,\n file.sources.every((source) => source.isTypeOnly),\n )\n }\n\n const exports: Array<KubbFile.Export> = []\n for (const file of barrelFiles) {\n const containsOnlyTypes = fileTypeCache.get(file) ?? false\n\n for (const source of file.sources) {\n if (!file.path || !source.isIndexable) {\n continue\n }\n\n exports.push({\n name: mode === 'all' ? undefined : [source.name],\n path: getRelativePath(rootPath, file.path),\n isTypeOnly: mode === 'all' ? containsOnlyTypes : source.isTypeOnly,\n } as KubbFile.Export)\n }\n }\n\n const entryFile = createFile({\n path: rootPath,\n baseName: 'index.ts',\n exports,\n sources: [],\n })\n\n await ctx.addFile(entryFile)\n\n await ctx.fileManager.write({\n mode: ctx.config.mode,\n dryRun: options.dryRun,\n parsers: ctx.installedParsers,\n })\n },\n }\n },\n})\n","import { resolve } from 'node:path'\nimport fs from 'fs-extra'\nimport type * as KubbFile from '../KubbFile.ts'\nimport { definePlugin } from './definePlugin.ts'\n\ntype WriteOptions = {\n extension?: Record<KubbFile.Extname, KubbFile.Extname | ''>\n}\n\ntype Options = {\n dryRun?: boolean\n /**\n * Optional callback that is invoked whenever a file is written by the plugin.\n * Useful for tests to observe write operations without spying on internal functions.\n */\n onBeforeWrite?: (path: string, data: string | undefined) => void | Promise<void>\n clean?: {\n path: string\n }\n}\n\ntype ExtendOptions = {\n write(options?: WriteOptions): Promise<void>\n}\n\nexport async function write(path: string, data: string | undefined, options: { sanity?: boolean } = {}): Promise<string | undefined> {\n if (typeof Bun !== 'undefined') {\n if (!data || data?.trim() === '') {\n return undefined\n }\n\n await Bun.write(resolve(path), data.trim())\n\n if (options?.sanity) {\n const file = Bun.file(resolve(path))\n const savedData = await file.text()\n\n if (savedData?.toString() !== data?.toString()) {\n throw new Error(`Sanity check failed for ${path}\\n\\nData[${data.length}]:\\n${data}\\n\\nSaved[${savedData.length}]:\\n${savedData}\\n`)\n }\n\n return savedData\n }\n\n return data\n }\n\n if (!data || data?.trim() === '') {\n return undefined\n }\n\n try {\n const oldContent = await fs.readFile(resolve(path), {\n encoding: 'utf-8',\n })\n if (oldContent?.toString() === data?.toString()) {\n return\n }\n } catch (_err) {\n /* empty */\n }\n\n await fs.outputFile(resolve(path), data.trim(), { encoding: 'utf-8' })\n\n if (options?.sanity) {\n const savedData = await fs.readFile(resolve(path), {\n encoding: 'utf-8',\n })\n\n if (savedData?.toString() !== data?.toString()) {\n throw new Error(`Sanity check failed for ${path}\\n\\nData[${data.length}]:\\n${data}\\n\\nSaved[${savedData.length}]:\\n${savedData}\\n`)\n }\n\n return savedData\n }\n\n return data\n}\n\ndeclare global {\n namespace Kubb {\n interface Fabric {\n write(options?: WriteOptions): Promise<void>\n }\n }\n}\n\nexport const fsPlugin = definePlugin<Options, ExtendOptions>({\n name: 'fs',\n install(ctx, options = {}) {\n if (options.clean) {\n fs.removeSync(options.clean.path)\n }\n\n ctx.on('file:processing:update', async ({ file, source }) => {\n if (options.onBeforeWrite) {\n await options.onBeforeWrite(file.path, source)\n }\n await write(file.path, source, { sanity: false })\n })\n },\n inject(ctx, { dryRun } = {}) {\n return {\n async write(\n options = {\n extension: { '.ts': '.ts' },\n },\n ) {\n await ctx.fileManager.write({\n mode: ctx.config.mode,\n extension: options.extension,\n dryRun,\n parsers: ctx.installedParsers,\n })\n },\n }\n },\n})\n","import { spawn } from 'node:child_process'\n\nconst spawnBin = (bin: string, args: string[]): Promise<boolean> => {\n return new Promise((resolve) => {\n const process = spawn(bin, args, {\n detached: true,\n shell: false,\n windowsHide: true,\n })\n\n process.on('close', (code) => {\n resolve(!code)\n })\n })\n}\n\ntype Options = {\n app?: string\n}\n\nexport async function open(path: string, options?: Options): Promise<boolean> {\n const app = options?.app\n\n if (process.platform === 'win32') {\n return spawnBin('cmd.exe', ['/c', 'start', app || '', path.replace(/[&^]/g, '^$&')])\n }\n\n if (process.platform === 'linux') {\n return spawnBin(app || 'xdg-open', [path])\n }\n if (process.platform === 'darwin') {\n return spawnBin('open', app ? ['-a', app, path] : [path])\n }\n\n throw new Error(`Unsupported platform, could not open \"${path}\"`)\n}\n","import http from 'node:http'\nimport type { AddressInfo } from 'node:net'\nimport path from 'node:path'\nimport handler from 'serve-handler'\nimport { createFile } from '../createFile.ts'\nimport type * as KubbFile from '../KubbFile.ts'\nimport { open } from '../utils/open.ts'\nimport { type Graph, TreeNode } from '../utils/TreeNode.ts'\nimport { definePlugin } from './definePlugin.ts'\n\ntype Options = {\n root: string\n /**\n * @default false\n */\n open?: boolean\n}\n\ntype GetGraphOptions = {\n files: KubbFile.File[]\n root: string\n}\n\nexport function getGraph({ files, root }: GetGraphOptions): Graph | undefined {\n const treeNode = TreeNode.fromFiles(files, root)\n\n if (!treeNode) {\n return undefined\n }\n\n return TreeNode.toGraph(treeNode)\n}\nconst html = `\n <!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <title>File Graph</title>\n <script type=\"module\">\n import { Network } from 'https://cdn.jsdelivr.net/npm/vis-network/standalone/esm/vis-network.min.js'\n\n async function main() {\n const res = await fetch('./graph.json')\n const { nodes, edges } = await res.json()\n const container = document.getElementById('graph')\n\n const network = new Network(\n container,\n { nodes, edges },\n {\n layout: { hierarchical: { direction: 'UD', sortMethod: 'directed' } },\n nodes: { shape: 'box', font: { face: 'monospace' } },\n edges: { arrows: 'to' },\n physics: false,\n },\n )\n }\n\n main()\n </script>\n <style>\n html, body, #graph { height: 100%; margin: 0; }\n </style>\n </head>\n <body>\n <div id=\"graph\"></div>\n </body>\n</html>\n`\n\nasync function serve(root: string) {\n const server = http.createServer((req, res) => {\n return handler(req, res, {\n public: root,\n cleanUrls: true,\n })\n })\n\n server.listen(0, async () => {\n const { port } = server.address() as AddressInfo\n console.log(`Running on http://localhost:${port}/graph.html`)\n\n await open(`http://localhost:${port}/graph.html`)\n })\n}\n\nexport const graphPlugin = definePlugin<Options>({\n name: 'graph',\n install(ctx, options) {\n if (!options) {\n throw new Error('Graph plugin requires options.root and options.mode')\n }\n\n ctx.on('files:writing:start', async ({ files }) => {\n const root = options.root\n\n const graph = getGraph({ files, root })\n\n if (!graph) {\n return undefined\n }\n\n const graphFile = createFile({\n baseName: 'graph.json',\n path: path.join(root, 'graph.json'),\n sources: [\n {\n name: 'graph',\n value: JSON.stringify(graph, null, 2),\n },\n ],\n })\n\n const graphHtmlFile = createFile({\n baseName: 'graph.html',\n path: path.join(root, 'graph.html'),\n sources: [\n {\n name: 'graph',\n value: html,\n },\n ],\n })\n\n await ctx.addFile(graphFile, graphHtmlFile)\n\n if (options.open) {\n await serve(root)\n }\n })\n },\n})\n","import http from 'node:http'\nimport type { AddressInfo } from 'node:net'\nimport { relative } from 'node:path'\nimport { Presets, SingleBar } from 'cli-progress'\nimport { createConsola, type LogLevel } from 'consola'\nimport { WebSocket, WebSocketServer } from 'ws'\nimport type { FabricEvents } from '../Fabric.ts'\nimport type * as KubbFile from '../KubbFile.ts'\nimport { definePlugin } from './definePlugin.ts'\n\ntype Broadcast = <T = unknown>(event: keyof FabricEvents | string, payload: T) => void\ntype WebSocketOptions = {\n /**\n * Hostname to bind the websocket server to.\n * @default '127.0.0.1'\n */\n host?: string\n /**\n * Port to bind the websocket server to.\n * @default 0 (random available port)\n */\n port?: number\n}\n\ntype Options = {\n /**\n * Explicit consola log level.\n */\n level?: LogLevel\n /**\n * Toggle progress bar output.\n * @default true\n */\n progress?: boolean\n /**\n * Toggle or configure the websocket broadcast server.\n * When `true`, a websocket server is started on an ephemeral port.\n * When `false`, websocket support is disabled.\n * When providing an object, the server uses the supplied host and port.\n * @default true\n */\n websocket?: boolean | WebSocketOptions\n}\n\nfunction normalizeAddress(address: AddressInfo): {\n host: string\n port: number\n} {\n const host = address.address === '::' ? '127.0.0.1' : address.address\n\n return { host, port: address.port }\n}\n\nfunction serializeFile(file: KubbFile.File | KubbFile.ResolvedFile) {\n return {\n path: file.path,\n baseName: file.baseName,\n name: 'name' in file ? file.name : undefined,\n extname: 'extname' in file ? file.extname : undefined,\n }\n}\n\nfunction pluralize(word: string, count: number) {\n return `${count} ${word}${count === 1 ? '' : 's'}`\n}\n\nconst defaultTag = 'Fabric'\n\nconst createProgressBar = () =>\n new SingleBar(\n {\n format: '{bar} {percentage}% | {value}/{total} | {message}',\n barCompleteChar: '█',\n barIncompleteChar: '░',\n hideCursor: true,\n clearOnComplete: true,\n },\n Presets.shades_grey,\n )\n\nexport const loggerPlugin = definePlugin<Options>({\n name: 'logger',\n install(ctx, options = {}) {\n const { level, websocket = true, progress = true } = options\n\n const logger = createConsola(level !== undefined ? { level } : {}).withTag(defaultTag)\n\n const progressBar = progress ? createProgressBar() : undefined\n\n let server: http.Server | undefined\n let wss: WebSocketServer | undefined\n\n const broadcast: Broadcast = (event, payload) => {\n if (!wss) {\n return\n }\n\n const message = JSON.stringify({ event, payload })\n\n for (const client of wss.clients) {\n if (client.readyState === WebSocket.OPEN) {\n client.send(message)\n }\n }\n }\n\n if (websocket) {\n const { host = '127.0.0.1', port = 0 } = typeof websocket === 'boolean' ? {} : websocket\n\n server = http.createServer()\n wss = new WebSocketServer({ server })\n\n server.listen(port, host, () => {\n const addressInfo = server?.address()\n\n if (addressInfo && typeof addressInfo === 'object') {\n const { host: resolvedHost, port: resolvedPort } = normalizeAddress(addressInfo)\n const url = `ws://${resolvedHost}:${resolvedPort}`\n\n logger.info(`Logger websocket listening on ${url}`)\n broadcast('websocket:ready', { url })\n }\n })\n\n wss.on('connection', (socket) => {\n logger.info('Logger websocket client connected')\n socket.send(\n JSON.stringify({\n event: 'welcome',\n payload: {\n message: 'Connected to Fabric log stream',\n timestamp: Date.now(),\n },\n }),\n )\n })\n\n wss.on('error', (error) => {\n logger.error('Logger websocket error', error)\n })\n }\n\n const formatPath = (path: string) => relative(process.cwd(), path)\n\n ctx.on('lifecycle:start', async () => {\n logger.start('Starting Fabric run')\n broadcast('lifecycle:start', { timestamp: Date.now() })\n })\n\n ctx.on('lifecycle:render', async () => {\n logger.info('Rendering application graph')\n broadcast('lifecycle:render', { timestamp: Date.now() })\n })\n\n ctx.on('files:added', async ({ files }) => {\n if (!files.length) {\n return\n }\n\n logger.info(`Queued ${pluralize('file', files.length)}`)\n broadcast('files:added', {\n files: files.map(serializeFile),\n })\n })\n\n ctx.on('file:resolve:path', async ({ file }) => {\n logger.info(`Resolving path for ${formatPath(file.path)}`)\n broadcast('file:resolve:path', { file: serializeFile(file) })\n })\n\n ctx.on('file:resolve:name', async ({ file }) => {\n logger.info(`Resolving name for ${formatPath(file.path)}`)\n broadcast('file:resolve:name', { file: serializeFile(file) })\n })\n\n ctx.on('files:processing:start', async ({ files }) => {\n logger.start(`Processing ${pluralize('file', files.length)}`)\n broadcast('files:processing:start', {\n total: files.length,\n timestamp: Date.now(),\n })\n\n if (progressBar) {\n logger.pauseLogs()\n progressBar.start(files.length, 0, { message: 'Starting...' })\n }\n })\n\n ctx.on('file:processing:start', async ({ file, index, total }) => {\n logger.info(`Processing [${index + 1}/${total}] ${formatPath(file.path)}`)\n broadcast('file:processing:start', {\n index,\n total,\n file: serializeFile(file),\n })\n })\n\n ctx.on('file:processing:update', async ({ processed, total, percentage, file }) => {\n const formattedPercentage = Number.isFinite(percentage) ? percentage.toFixed(1) : '0.0'\n\n logger.info(`Progress ${formattedPercentage}% (${processed}/${total}) → ${formatPath(file.path)}`)\n broadcast('file:processing:update', {\n processed,\n total,\n percentage,\n file: serializeFile(file),\n })\n\n if (progressBar) {\n progressBar.increment(1, {\n message: `Writing ${formatPath(file.path)}`,\n })\n }\n })\n\n ctx.on('file:processing:end', async ({ file, index, total }) => {\n logger.success(`Finished [${index + 1}/${total}] ${formatPath(file.path)}`)\n broadcast('file:processing:end', {\n index,\n total,\n file: serializeFile(file),\n })\n })\n\n ctx.on('files:writing:start', async ({ files }) => {\n logger.start(`Writing ${pluralize('file', files.length)} to disk`)\n broadcast('files:writing:start', {\n files: files.map(serializeFile),\n })\n })\n\n ctx.on('files:writing:end', async ({ files }) => {\n logger.success(`Written ${pluralize('file', files.length)} to disk`)\n broadcast('files:writing:end', {\n files: files.map(serializeFile),\n })\n })\n\n ctx.on('files:processing:end', async ({ files }) => {\n logger.success(`Processed ${pluralize('file', files.length)}`)\n broadcast('files:processing:end', {\n total: files.length,\n timestamp: Date.now(),\n })\n\n if (progressBar) {\n progressBar.update(files.length, { message: 'Done ✅' })\n progressBar.stop()\n\n logger.resumeLogs()\n }\n })\n\n ctx.on('lifecycle:end', async () => {\n logger.success('Fabric run completed')\n broadcast('lifecycle:end', { timestamp: Date.now() })\n\n if (progressBar) {\n progressBar.stop()\n logger.resumeLogs()\n }\n\n const closures: Array<Promise<void>> = []\n\n if (wss) {\n const wsServer = wss\n\n closures.push(\n new Promise((resolve) => {\n for (const client of wsServer.clients) {\n client.close()\n }\n wsServer.close(() => resolve())\n }),\n )\n }\n\n if (server) {\n const httpServer = server\n\n closures.push(\n new Promise((resolve) => {\n httpServer.close(() => resolve())\n }),\n )\n }\n\n if (closures.length) {\n await Promise.allSettled(closures)\n logger.info('Logger websocket closed')\n }\n })\n },\n})\n"],"mappings":"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"}
package/dist/types.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as FabricOptions, i as FabricMode, m as KubbFile_d_exports, n as FabricConfig, r as FabricContext } from "./Fabric-BzIhBn8t.cjs";
1
+ import { a as FabricOptions, i as FabricMode, m as KubbFile_d_exports, n as FabricConfig, r as FabricContext } from "./Fabric-CVnHPMqM.cjs";
2
2
  export { type FabricConfig, type FabricContext, type FabricMode, type FabricOptions, KubbFile_d_exports as KubbFile };
package/dist/types.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as FabricOptions, i as FabricMode, m as KubbFile_d_exports, n as FabricConfig, r as FabricContext } from "./Fabric-igvWKffO.js";
1
+ import { a as FabricOptions, i as FabricMode, m as KubbFile_d_exports, n as FabricConfig, r as FabricContext } from "./Fabric-CEVrEuYU.js";
2
2
  export { type FabricConfig, type FabricContext, type FabricMode, type FabricOptions, KubbFile_d_exports as KubbFile };
@@ -1,4 +1,4 @@
1
- import { u as Parser } from "./Fabric-igvWKffO.js";
1
+ import { u as Parser } from "./Fabric-CEVrEuYU.js";
2
2
  import ts from "typescript";
3
3
 
4
4
  //#region src/parsers/typescriptParser.d.ts
@@ -36,4 +36,4 @@ declare function createExport({
36
36
  declare const typescriptParser: Parser<[], any>;
37
37
  //#endregion
38
38
  export { typescriptParser as i, createImport as n, print as r, createExport as t };
39
- //# sourceMappingURL=typescriptParser-BN1vEX-I.d.ts.map
39
+ //# sourceMappingURL=typescriptParser-9jJzfPj-.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import { t as trimExtName } from "./trimExtName-Dq2Z7SCT.js";
2
- import { t as createParser } from "./createParser-D_ANHZTa.js";
2
+ import { t as defineParser } from "./defineParser-Bxv4mb-N.js";
3
3
  import { t as getRelativePath } from "./getRelativePath-DayVrg5k.js";
4
4
  import path from "node:path";
5
5
  import ts from "typescript";
@@ -45,7 +45,7 @@ function createExport({ path: path$1, asAlias, isTypeOnly = false, name }) {
45
45
  return factory.createExportSpecifier(false, void 0, typeof propertyName === "string" ? factory.createIdentifier(propertyName) : propertyName);
46
46
  })), factory.createStringLiteral(path$1), void 0);
47
47
  }
48
- const typescriptParser = createParser({
48
+ const typescriptParser = defineParser({
49
49
  name: "typescript",
50
50
  extNames: [".ts", ".js"],
51
51
  install() {},
@@ -85,4 +85,4 @@ const typescriptParser = createParser({
85
85
 
86
86
  //#endregion
87
87
  export { typescriptParser as i, createImport as n, print as r, createExport as t };
88
- //# sourceMappingURL=typescriptParser-Cw2wm0gX.js.map
88
+ //# sourceMappingURL=typescriptParser-BLX7eX2k.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"typescriptParser-Cw2wm0gX.js","names":["path","sourceParts: Array<string>","importNodes: Array<ts.ImportDeclaration>","exportNodes: Array<ts.ExportDeclaration>"],"sources":["../src/parsers/typescriptParser.ts"],"sourcesContent":["import path from 'node:path'\nimport ts from 'typescript'\nimport { getRelativePath } from '../utils/getRelativePath.ts'\nimport { trimExtName } from '../utils/trimExtName.ts'\nimport { createParser } from './createParser.ts'\n\nconst { factory } = ts\n\n/**\n * Convert AST TypeScript/TSX nodes to a string based on the TypeScript printer.\n */\nexport function print(...elements: Array<ts.Node>): string {\n const sourceFile = ts.createSourceFile('print.tsx', '', ts.ScriptTarget.ES2022, true, ts.ScriptKind.TSX)\n\n const printer = ts.createPrinter({\n omitTrailingSemicolon: true,\n newLine: ts.NewLineKind.LineFeed,\n removeComments: false,\n noEmitHelpers: true,\n })\n\n for (const node of elements) {\n if (node.kind === ts.SyntaxKind.Unknown) {\n console.error('⚠️ Unknown node found:', node)\n }\n }\n\n const output = printer.printList(ts.ListFormat.MultiLine, factory.createNodeArray(elements.filter(Boolean)), sourceFile)\n\n return output.replace(/\\r\\n/g, '\\n')\n}\n\nexport function createImport({\n name,\n path,\n root,\n isTypeOnly = false,\n isNameSpace = false,\n}: {\n name: string | Array<string | { propertyName: string; name?: string }>\n path: string\n root?: string\n isTypeOnly?: boolean\n isNameSpace?: boolean\n}) {\n const resolvePath = root ? getRelativePath(root, path) : path\n\n // Namespace or default import\n if (!Array.isArray(name)) {\n if (isNameSpace) {\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, undefined, factory.createNamespaceImport(factory.createIdentifier(name))),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n }\n\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, factory.createIdentifier(name), undefined),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n }\n\n // Named imports\n const specifiers = name.map((item) => {\n if (typeof item === 'object') {\n const { propertyName, name: alias } = item\n return factory.createImportSpecifier(false, alias ? factory.createIdentifier(propertyName) : undefined, factory.createIdentifier(alias ?? propertyName))\n }\n\n return factory.createImportSpecifier(false, undefined, factory.createIdentifier(item))\n })\n\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, undefined, factory.createNamedImports(specifiers)),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n}\n\nexport function createExport({\n path,\n asAlias,\n isTypeOnly = false,\n name,\n}: {\n path: string\n asAlias?: boolean\n isTypeOnly?: boolean\n name?: string | Array<ts.Identifier | string>\n}) {\n if (name && !Array.isArray(name) && !asAlias) {\n console.warn(`When using name as string, asAlias should be true ${name}`)\n }\n\n if (!Array.isArray(name)) {\n const parsedName = name?.match(/^\\d/) ? `_${name?.slice(1)}` : name\n\n return factory.createExportDeclaration(\n undefined,\n isTypeOnly,\n asAlias && parsedName ? factory.createNamespaceExport(factory.createIdentifier(parsedName)) : undefined,\n factory.createStringLiteral(path),\n undefined,\n )\n }\n\n return factory.createExportDeclaration(\n undefined,\n isTypeOnly,\n factory.createNamedExports(\n name.map((propertyName) => {\n return factory.createExportSpecifier(false, undefined, typeof propertyName === 'string' ? factory.createIdentifier(propertyName) : propertyName)\n }),\n ),\n factory.createStringLiteral(path),\n undefined,\n )\n}\n\nexport const typescriptParser = createParser({\n name: 'typescript',\n extNames: ['.ts', '.js'],\n install() {},\n async parse(file, options = { extname: '.ts' }) {\n const sourceParts: Array<string> = []\n for (const item of file.sources) {\n if (item.value) {\n sourceParts.push(item.value)\n }\n }\n const source = sourceParts.join('\\n\\n')\n\n const importNodes: Array<ts.ImportDeclaration> = []\n for (const item of file.imports) {\n const importPath = item.root ? getRelativePath(item.root, item.path) : item.path\n const hasExtname = !!path.extname(importPath)\n\n importNodes.push(\n createImport({\n name: item.name,\n path: options.extname && hasExtname ? `${trimExtName(importPath)}${options.extname}` : item.root ? trimExtName(importPath) : importPath,\n isTypeOnly: item.isTypeOnly,\n }),\n )\n }\n\n const exportNodes: Array<ts.ExportDeclaration> = []\n for (const item of file.exports) {\n const exportPath = item.path\n const hasExtname = !!path.extname(exportPath)\n\n exportNodes.push(\n createExport({\n name: item.name,\n path: options.extname && hasExtname ? `${trimExtName(item.path)}${options.extname}` : trimExtName(item.path),\n isTypeOnly: item.isTypeOnly,\n asAlias: item.asAlias,\n }),\n )\n }\n\n const parts = [file.banner, print(...importNodes, ...exportNodes), source, file.footer].filter((segment): segment is string => segment != null)\n return parts.join('\\n')\n },\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"typescriptParser-BLX7eX2k.js","names":["path","sourceParts: Array<string>","importNodes: Array<ts.ImportDeclaration>","exportNodes: Array<ts.ExportDeclaration>"],"sources":["../src/parsers/typescriptParser.ts"],"sourcesContent":["import path from 'node:path'\nimport ts from 'typescript'\nimport { getRelativePath } from '../utils/getRelativePath.ts'\nimport { trimExtName } from '../utils/trimExtName.ts'\nimport { defineParser } from './defineParser.ts'\n\nconst { factory } = ts\n\n/**\n * Convert AST TypeScript/TSX nodes to a string based on the TypeScript printer.\n */\nexport function print(...elements: Array<ts.Node>): string {\n const sourceFile = ts.createSourceFile('print.tsx', '', ts.ScriptTarget.ES2022, true, ts.ScriptKind.TSX)\n\n const printer = ts.createPrinter({\n omitTrailingSemicolon: true,\n newLine: ts.NewLineKind.LineFeed,\n removeComments: false,\n noEmitHelpers: true,\n })\n\n for (const node of elements) {\n if (node.kind === ts.SyntaxKind.Unknown) {\n console.error('⚠️ Unknown node found:', node)\n }\n }\n\n const output = printer.printList(ts.ListFormat.MultiLine, factory.createNodeArray(elements.filter(Boolean)), sourceFile)\n\n return output.replace(/\\r\\n/g, '\\n')\n}\n\nexport function createImport({\n name,\n path,\n root,\n isTypeOnly = false,\n isNameSpace = false,\n}: {\n name: string | Array<string | { propertyName: string; name?: string }>\n path: string\n root?: string\n isTypeOnly?: boolean\n isNameSpace?: boolean\n}) {\n const resolvePath = root ? getRelativePath(root, path) : path\n\n // Namespace or default import\n if (!Array.isArray(name)) {\n if (isNameSpace) {\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, undefined, factory.createNamespaceImport(factory.createIdentifier(name))),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n }\n\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, factory.createIdentifier(name), undefined),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n }\n\n // Named imports\n const specifiers = name.map((item) => {\n if (typeof item === 'object') {\n const { propertyName, name: alias } = item\n return factory.createImportSpecifier(false, alias ? factory.createIdentifier(propertyName) : undefined, factory.createIdentifier(alias ?? propertyName))\n }\n\n return factory.createImportSpecifier(false, undefined, factory.createIdentifier(item))\n })\n\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, undefined, factory.createNamedImports(specifiers)),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n}\n\nexport function createExport({\n path,\n asAlias,\n isTypeOnly = false,\n name,\n}: {\n path: string\n asAlias?: boolean\n isTypeOnly?: boolean\n name?: string | Array<ts.Identifier | string>\n}) {\n if (name && !Array.isArray(name) && !asAlias) {\n console.warn(`When using name as string, asAlias should be true ${name}`)\n }\n\n if (!Array.isArray(name)) {\n const parsedName = name?.match(/^\\d/) ? `_${name?.slice(1)}` : name\n\n return factory.createExportDeclaration(\n undefined,\n isTypeOnly,\n asAlias && parsedName ? factory.createNamespaceExport(factory.createIdentifier(parsedName)) : undefined,\n factory.createStringLiteral(path),\n undefined,\n )\n }\n\n return factory.createExportDeclaration(\n undefined,\n isTypeOnly,\n factory.createNamedExports(\n name.map((propertyName) => {\n return factory.createExportSpecifier(false, undefined, typeof propertyName === 'string' ? factory.createIdentifier(propertyName) : propertyName)\n }),\n ),\n factory.createStringLiteral(path),\n undefined,\n )\n}\n\nexport const typescriptParser = defineParser({\n name: 'typescript',\n extNames: ['.ts', '.js'],\n install() {},\n async parse(file, options = { extname: '.ts' }) {\n const sourceParts: Array<string> = []\n for (const item of file.sources) {\n if (item.value) {\n sourceParts.push(item.value)\n }\n }\n const source = sourceParts.join('\\n\\n')\n\n const importNodes: Array<ts.ImportDeclaration> = []\n for (const item of file.imports) {\n const importPath = item.root ? getRelativePath(item.root, item.path) : item.path\n const hasExtname = !!path.extname(importPath)\n\n importNodes.push(\n createImport({\n name: item.name,\n path: options.extname && hasExtname ? `${trimExtName(importPath)}${options.extname}` : item.root ? trimExtName(importPath) : importPath,\n isTypeOnly: item.isTypeOnly,\n }),\n )\n }\n\n const exportNodes: Array<ts.ExportDeclaration> = []\n for (const item of file.exports) {\n const exportPath = item.path\n const hasExtname = !!path.extname(exportPath)\n\n exportNodes.push(\n createExport({\n name: item.name,\n path: options.extname && hasExtname ? `${trimExtName(item.path)}${options.extname}` : trimExtName(item.path),\n isTypeOnly: item.isTypeOnly,\n asAlias: item.asAlias,\n }),\n )\n }\n\n const parts = [file.banner, print(...importNodes, ...exportNodes), source, file.footer].filter((segment): segment is string => segment != null)\n return parts.join('\\n')\n },\n})\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { u as Parser } from "./Fabric-BzIhBn8t.cjs";
1
+ import { u as Parser } from "./Fabric-CVnHPMqM.cjs";
2
2
  import ts from "typescript";
3
3
 
4
4
  //#region src/parsers/typescriptParser.d.ts
@@ -36,4 +36,4 @@ declare function createExport({
36
36
  declare const typescriptParser: Parser<[], any>;
37
37
  //#endregion
38
38
  export { typescriptParser as i, createImport as n, print as r, createExport as t };
39
- //# sourceMappingURL=typescriptParser-BlRK18rx.d.cts.map
39
+ //# sourceMappingURL=typescriptParser-DCFNN4BL.d.cts.map
@@ -1,5 +1,5 @@
1
1
  const require_trimExtName = require('./trimExtName-DaBSwMN-.cjs');
2
- const require_createParser = require('./createParser-C4IkyTs5.cjs');
2
+ const require_defineParser = require('./defineParser-DODGK4rM.cjs');
3
3
  const require_getRelativePath = require('./getRelativePath-CLj7Ou6d.cjs');
4
4
  let node_path = require("node:path");
5
5
  node_path = require_trimExtName.__toESM(node_path);
@@ -47,7 +47,7 @@ function createExport({ path: path$1, asAlias, isTypeOnly = false, name }) {
47
47
  return factory.createExportSpecifier(false, void 0, typeof propertyName === "string" ? factory.createIdentifier(propertyName) : propertyName);
48
48
  })), factory.createStringLiteral(path$1), void 0);
49
49
  }
50
- const typescriptParser = require_createParser.createParser({
50
+ const typescriptParser = require_defineParser.defineParser({
51
51
  name: "typescript",
52
52
  extNames: [".ts", ".js"],
53
53
  install() {},
@@ -110,4 +110,4 @@ Object.defineProperty(exports, 'typescriptParser', {
110
110
  return typescriptParser;
111
111
  }
112
112
  });
113
- //# sourceMappingURL=typescriptParser-DRdx9q2o.cjs.map
113
+ //# sourceMappingURL=typescriptParser-OjFZ_DeI.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"typescriptParser-DRdx9q2o.cjs","names":["ts","getRelativePath","path","createParser","sourceParts: Array<string>","importNodes: Array<ts.ImportDeclaration>","trimExtName","exportNodes: Array<ts.ExportDeclaration>"],"sources":["../src/parsers/typescriptParser.ts"],"sourcesContent":["import path from 'node:path'\nimport ts from 'typescript'\nimport { getRelativePath } from '../utils/getRelativePath.ts'\nimport { trimExtName } from '../utils/trimExtName.ts'\nimport { createParser } from './createParser.ts'\n\nconst { factory } = ts\n\n/**\n * Convert AST TypeScript/TSX nodes to a string based on the TypeScript printer.\n */\nexport function print(...elements: Array<ts.Node>): string {\n const sourceFile = ts.createSourceFile('print.tsx', '', ts.ScriptTarget.ES2022, true, ts.ScriptKind.TSX)\n\n const printer = ts.createPrinter({\n omitTrailingSemicolon: true,\n newLine: ts.NewLineKind.LineFeed,\n removeComments: false,\n noEmitHelpers: true,\n })\n\n for (const node of elements) {\n if (node.kind === ts.SyntaxKind.Unknown) {\n console.error('⚠️ Unknown node found:', node)\n }\n }\n\n const output = printer.printList(ts.ListFormat.MultiLine, factory.createNodeArray(elements.filter(Boolean)), sourceFile)\n\n return output.replace(/\\r\\n/g, '\\n')\n}\n\nexport function createImport({\n name,\n path,\n root,\n isTypeOnly = false,\n isNameSpace = false,\n}: {\n name: string | Array<string | { propertyName: string; name?: string }>\n path: string\n root?: string\n isTypeOnly?: boolean\n isNameSpace?: boolean\n}) {\n const resolvePath = root ? getRelativePath(root, path) : path\n\n // Namespace or default import\n if (!Array.isArray(name)) {\n if (isNameSpace) {\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, undefined, factory.createNamespaceImport(factory.createIdentifier(name))),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n }\n\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, factory.createIdentifier(name), undefined),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n }\n\n // Named imports\n const specifiers = name.map((item) => {\n if (typeof item === 'object') {\n const { propertyName, name: alias } = item\n return factory.createImportSpecifier(false, alias ? factory.createIdentifier(propertyName) : undefined, factory.createIdentifier(alias ?? propertyName))\n }\n\n return factory.createImportSpecifier(false, undefined, factory.createIdentifier(item))\n })\n\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, undefined, factory.createNamedImports(specifiers)),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n}\n\nexport function createExport({\n path,\n asAlias,\n isTypeOnly = false,\n name,\n}: {\n path: string\n asAlias?: boolean\n isTypeOnly?: boolean\n name?: string | Array<ts.Identifier | string>\n}) {\n if (name && !Array.isArray(name) && !asAlias) {\n console.warn(`When using name as string, asAlias should be true ${name}`)\n }\n\n if (!Array.isArray(name)) {\n const parsedName = name?.match(/^\\d/) ? `_${name?.slice(1)}` : name\n\n return factory.createExportDeclaration(\n undefined,\n isTypeOnly,\n asAlias && parsedName ? factory.createNamespaceExport(factory.createIdentifier(parsedName)) : undefined,\n factory.createStringLiteral(path),\n undefined,\n )\n }\n\n return factory.createExportDeclaration(\n undefined,\n isTypeOnly,\n factory.createNamedExports(\n name.map((propertyName) => {\n return factory.createExportSpecifier(false, undefined, typeof propertyName === 'string' ? factory.createIdentifier(propertyName) : propertyName)\n }),\n ),\n factory.createStringLiteral(path),\n undefined,\n )\n}\n\nexport const typescriptParser = createParser({\n name: 'typescript',\n extNames: ['.ts', '.js'],\n install() {},\n async parse(file, options = { extname: '.ts' }) {\n const sourceParts: Array<string> = []\n for (const item of file.sources) {\n if (item.value) {\n sourceParts.push(item.value)\n }\n }\n const source = sourceParts.join('\\n\\n')\n\n const importNodes: Array<ts.ImportDeclaration> = []\n for (const item of file.imports) {\n const importPath = item.root ? getRelativePath(item.root, item.path) : item.path\n const hasExtname = !!path.extname(importPath)\n\n importNodes.push(\n createImport({\n name: item.name,\n path: options.extname && hasExtname ? `${trimExtName(importPath)}${options.extname}` : item.root ? trimExtName(importPath) : importPath,\n isTypeOnly: item.isTypeOnly,\n }),\n )\n }\n\n const exportNodes: Array<ts.ExportDeclaration> = []\n for (const item of file.exports) {\n const exportPath = item.path\n const hasExtname = !!path.extname(exportPath)\n\n exportNodes.push(\n createExport({\n name: item.name,\n path: options.extname && hasExtname ? `${trimExtName(item.path)}${options.extname}` : trimExtName(item.path),\n isTypeOnly: item.isTypeOnly,\n asAlias: item.asAlias,\n }),\n )\n }\n\n const parts = [file.banner, print(...importNodes, ...exportNodes), source, file.footer].filter((segment): segment is string => segment != null)\n return parts.join('\\n')\n },\n})\n"],"mappings":";;;;;;;;;AAMA,MAAM,EAAE,YAAYA;;;;AAKpB,SAAgB,MAAM,GAAG,UAAkC;CACzD,MAAM,aAAaA,mBAAG,iBAAiB,aAAa,IAAIA,mBAAG,aAAa,QAAQ,MAAMA,mBAAG,WAAW,IAAI;CAExG,MAAM,UAAUA,mBAAG,cAAc;EAC/B,uBAAuB;EACvB,SAASA,mBAAG,YAAY;EACxB,gBAAgB;EAChB,eAAe;EAChB,CAAC;AAEF,MAAK,MAAM,QAAQ,SACjB,KAAI,KAAK,SAASA,mBAAG,WAAW,QAC9B,SAAQ,MAAM,0BAA0B,KAAK;AAMjD,QAFe,QAAQ,UAAUA,mBAAG,WAAW,WAAW,QAAQ,gBAAgB,SAAS,OAAO,QAAQ,CAAC,EAAE,WAAW,CAE1G,QAAQ,SAAS,KAAK;;AAGtC,SAAgB,aAAa,EAC3B,MACA,cACA,MACA,aAAa,OACb,cAAc,SAOb;CACD,MAAM,cAAc,OAAOC,wCAAgB,MAAMC,OAAK,GAAGA;AAGzD,KAAI,CAAC,MAAM,QAAQ,KAAK,EAAE;AACxB,MAAI,YACF,QAAO,QAAQ,wBACb,QACA,QAAQ,mBAAmB,YAAY,QAAW,QAAQ,sBAAsB,QAAQ,iBAAiB,KAAK,CAAC,CAAC,EAChH,QAAQ,oBAAoB,YAAY,EACxC,OACD;AAGH,SAAO,QAAQ,wBACb,QACA,QAAQ,mBAAmB,YAAY,QAAQ,iBAAiB,KAAK,EAAE,OAAU,EACjF,QAAQ,oBAAoB,YAAY,EACxC,OACD;;CAIH,MAAM,aAAa,KAAK,KAAK,SAAS;AACpC,MAAI,OAAO,SAAS,UAAU;GAC5B,MAAM,EAAE,cAAc,MAAM,UAAU;AACtC,UAAO,QAAQ,sBAAsB,OAAO,QAAQ,QAAQ,iBAAiB,aAAa,GAAG,QAAW,QAAQ,iBAAiB,6CAAS,aAAa,CAAC;;AAG1J,SAAO,QAAQ,sBAAsB,OAAO,QAAW,QAAQ,iBAAiB,KAAK,CAAC;GACtF;AAEF,QAAO,QAAQ,wBACb,QACA,QAAQ,mBAAmB,YAAY,QAAW,QAAQ,mBAAmB,WAAW,CAAC,EACzF,QAAQ,oBAAoB,YAAY,EACxC,OACD;;AAGH,SAAgB,aAAa,EAC3B,cACA,SACA,aAAa,OACb,QAMC;AACD,KAAI,QAAQ,CAAC,MAAM,QAAQ,KAAK,IAAI,CAAC,QACnC,SAAQ,KAAK,qDAAqD,OAAO;AAG3E,KAAI,CAAC,MAAM,QAAQ,KAAK,EAAE;EACxB,MAAM,0DAAa,KAAM,MAAM,MAAM,IAAG,gDAAI,KAAM,MAAM,EAAE,KAAK;AAE/D,SAAO,QAAQ,wBACb,QACA,YACA,WAAW,aAAa,QAAQ,sBAAsB,QAAQ,iBAAiB,WAAW,CAAC,GAAG,QAC9F,QAAQ,oBAAoBA,OAAK,EACjC,OACD;;AAGH,QAAO,QAAQ,wBACb,QACA,YACA,QAAQ,mBACN,KAAK,KAAK,iBAAiB;AACzB,SAAO,QAAQ,sBAAsB,OAAO,QAAW,OAAO,iBAAiB,WAAW,QAAQ,iBAAiB,aAAa,GAAG,aAAa;GAChJ,CACH,EACD,QAAQ,oBAAoBA,OAAK,EACjC,OACD;;AAGH,MAAa,mBAAmBC,kCAAa;CAC3C,MAAM;CACN,UAAU,CAAC,OAAO,MAAM;CACxB,UAAU;CACV,MAAM,MAAM,MAAM,UAAU,EAAE,SAAS,OAAO,EAAE;EAC9C,MAAMC,cAA6B,EAAE;AACrC,OAAK,MAAM,QAAQ,KAAK,QACtB,KAAI,KAAK,MACP,aAAY,KAAK,KAAK,MAAM;EAGhC,MAAM,SAAS,YAAY,KAAK,OAAO;EAEvC,MAAMC,cAA2C,EAAE;AACnD,OAAK,MAAM,QAAQ,KAAK,SAAS;GAC/B,MAAM,aAAa,KAAK,OAAOJ,wCAAgB,KAAK,MAAM,KAAK,KAAK,GAAG,KAAK;GAC5E,MAAM,aAAa,CAAC,CAACC,kBAAK,QAAQ,WAAW;AAE7C,eAAY,KACV,aAAa;IACX,MAAM,KAAK;IACX,MAAM,QAAQ,WAAW,aAAa,GAAGI,gCAAY,WAAW,GAAG,QAAQ,YAAY,KAAK,OAAOA,gCAAY,WAAW,GAAG;IAC7H,YAAY,KAAK;IAClB,CAAC,CACH;;EAGH,MAAMC,cAA2C,EAAE;AACnD,OAAK,MAAM,QAAQ,KAAK,SAAS;GAC/B,MAAM,aAAa,KAAK;GACxB,MAAM,aAAa,CAAC,CAACL,kBAAK,QAAQ,WAAW;AAE7C,eAAY,KACV,aAAa;IACX,MAAM,KAAK;IACX,MAAM,QAAQ,WAAW,aAAa,GAAGI,gCAAY,KAAK,KAAK,GAAG,QAAQ,YAAYA,gCAAY,KAAK,KAAK;IAC5G,YAAY,KAAK;IACjB,SAAS,KAAK;IACf,CAAC,CACH;;AAIH,SADc;GAAC,KAAK;GAAQ,MAAM,GAAG,aAAa,GAAG,YAAY;GAAE;GAAQ,KAAK;GAAO,CAAC,QAAQ,YAA+B,WAAW,KAAK,CAClI,KAAK,KAAK;;CAE1B,CAAC"}
1
+ {"version":3,"file":"typescriptParser-OjFZ_DeI.cjs","names":["ts","getRelativePath","path","defineParser","sourceParts: Array<string>","importNodes: Array<ts.ImportDeclaration>","trimExtName","exportNodes: Array<ts.ExportDeclaration>"],"sources":["../src/parsers/typescriptParser.ts"],"sourcesContent":["import path from 'node:path'\nimport ts from 'typescript'\nimport { getRelativePath } from '../utils/getRelativePath.ts'\nimport { trimExtName } from '../utils/trimExtName.ts'\nimport { defineParser } from './defineParser.ts'\n\nconst { factory } = ts\n\n/**\n * Convert AST TypeScript/TSX nodes to a string based on the TypeScript printer.\n */\nexport function print(...elements: Array<ts.Node>): string {\n const sourceFile = ts.createSourceFile('print.tsx', '', ts.ScriptTarget.ES2022, true, ts.ScriptKind.TSX)\n\n const printer = ts.createPrinter({\n omitTrailingSemicolon: true,\n newLine: ts.NewLineKind.LineFeed,\n removeComments: false,\n noEmitHelpers: true,\n })\n\n for (const node of elements) {\n if (node.kind === ts.SyntaxKind.Unknown) {\n console.error('⚠️ Unknown node found:', node)\n }\n }\n\n const output = printer.printList(ts.ListFormat.MultiLine, factory.createNodeArray(elements.filter(Boolean)), sourceFile)\n\n return output.replace(/\\r\\n/g, '\\n')\n}\n\nexport function createImport({\n name,\n path,\n root,\n isTypeOnly = false,\n isNameSpace = false,\n}: {\n name: string | Array<string | { propertyName: string; name?: string }>\n path: string\n root?: string\n isTypeOnly?: boolean\n isNameSpace?: boolean\n}) {\n const resolvePath = root ? getRelativePath(root, path) : path\n\n // Namespace or default import\n if (!Array.isArray(name)) {\n if (isNameSpace) {\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, undefined, factory.createNamespaceImport(factory.createIdentifier(name))),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n }\n\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, factory.createIdentifier(name), undefined),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n }\n\n // Named imports\n const specifiers = name.map((item) => {\n if (typeof item === 'object') {\n const { propertyName, name: alias } = item\n return factory.createImportSpecifier(false, alias ? factory.createIdentifier(propertyName) : undefined, factory.createIdentifier(alias ?? propertyName))\n }\n\n return factory.createImportSpecifier(false, undefined, factory.createIdentifier(item))\n })\n\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, undefined, factory.createNamedImports(specifiers)),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n}\n\nexport function createExport({\n path,\n asAlias,\n isTypeOnly = false,\n name,\n}: {\n path: string\n asAlias?: boolean\n isTypeOnly?: boolean\n name?: string | Array<ts.Identifier | string>\n}) {\n if (name && !Array.isArray(name) && !asAlias) {\n console.warn(`When using name as string, asAlias should be true ${name}`)\n }\n\n if (!Array.isArray(name)) {\n const parsedName = name?.match(/^\\d/) ? `_${name?.slice(1)}` : name\n\n return factory.createExportDeclaration(\n undefined,\n isTypeOnly,\n asAlias && parsedName ? factory.createNamespaceExport(factory.createIdentifier(parsedName)) : undefined,\n factory.createStringLiteral(path),\n undefined,\n )\n }\n\n return factory.createExportDeclaration(\n undefined,\n isTypeOnly,\n factory.createNamedExports(\n name.map((propertyName) => {\n return factory.createExportSpecifier(false, undefined, typeof propertyName === 'string' ? factory.createIdentifier(propertyName) : propertyName)\n }),\n ),\n factory.createStringLiteral(path),\n undefined,\n )\n}\n\nexport const typescriptParser = defineParser({\n name: 'typescript',\n extNames: ['.ts', '.js'],\n install() {},\n async parse(file, options = { extname: '.ts' }) {\n const sourceParts: Array<string> = []\n for (const item of file.sources) {\n if (item.value) {\n sourceParts.push(item.value)\n }\n }\n const source = sourceParts.join('\\n\\n')\n\n const importNodes: Array<ts.ImportDeclaration> = []\n for (const item of file.imports) {\n const importPath = item.root ? getRelativePath(item.root, item.path) : item.path\n const hasExtname = !!path.extname(importPath)\n\n importNodes.push(\n createImport({\n name: item.name,\n path: options.extname && hasExtname ? `${trimExtName(importPath)}${options.extname}` : item.root ? trimExtName(importPath) : importPath,\n isTypeOnly: item.isTypeOnly,\n }),\n )\n }\n\n const exportNodes: Array<ts.ExportDeclaration> = []\n for (const item of file.exports) {\n const exportPath = item.path\n const hasExtname = !!path.extname(exportPath)\n\n exportNodes.push(\n createExport({\n name: item.name,\n path: options.extname && hasExtname ? `${trimExtName(item.path)}${options.extname}` : trimExtName(item.path),\n isTypeOnly: item.isTypeOnly,\n asAlias: item.asAlias,\n }),\n )\n }\n\n const parts = [file.banner, print(...importNodes, ...exportNodes), source, file.footer].filter((segment): segment is string => segment != null)\n return parts.join('\\n')\n },\n})\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/fabric-core",
3
- "version": "0.5.4",
3
+ "version": "0.6.0",
4
4
  "description": "Core functionality for Kubb's plugin-based code generation system, providing the foundation for transforming OpenAPI specifications.",
5
5
  "keywords": [
6
6
  "typescript",
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
  }