@kubb/fabric-core 0.2.11 → 0.2.13

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.
@@ -294,7 +294,7 @@ type FabricEvents = {
294
294
  }];
295
295
  };
296
296
  type FabricContext<TOptions extends FabricOptions> = {
297
- options?: TOptions;
297
+ config?: FabricConfig<TOptions>;
298
298
  events: AsyncEventEmitter<FabricEvents>;
299
299
  fileManager: FileManager;
300
300
  installedPlugins: Set<Plugin>;
@@ -302,6 +302,9 @@ type FabricContext<TOptions extends FabricOptions> = {
302
302
  };
303
303
  type FabricMode = 'sequential' | 'parallel';
304
304
  type AllOptional<T> = {} extends T ? true : false;
305
+ type FabricConfig<TOptions extends FabricOptions> = {
306
+ options: TOptions;
307
+ };
305
308
  type Install<TOptions = unknown> = TOptions extends any[] ? (app: Fabric, ...options: TOptions) => void | Promise<void> : AllOptional<TOptions> extends true ? (app: Fabric, options: TOptions | undefined) => void | Promise<void> : (app: Fabric, options: TOptions) => void | Promise<void>;
306
309
  type Inject<TOptions = unknown, TAppExtension extends Record<string, any> = {}> = TOptions extends any[] ? (app: Fabric, ...options: TOptions) => Partial<TAppExtension> : AllOptional<TOptions> extends true ? (app: Fabric, options: TOptions | undefined) => Partial<TAppExtension> : (app: Fabric, options: TOptions) => Partial<TAppExtension>;
307
310
  interface Fabric<TOptions extends FabricOptions = FabricOptions> extends Kubb.Fabric {
@@ -311,5 +314,5 @@ interface Fabric<TOptions extends FabricOptions = FabricOptions> extends Kubb.Fa
311
314
  addFile(...files: Array<File>): Promise<void>;
312
315
  }
313
316
  //#endregion
314
- export { FileManager as a, UserParser as c, Extname as d, File as f, FabricOptions as i, Plugin as l, ResolvedFile as m, FabricContext as n, FileProcessor as o, KubbFile_d_exports as p, FabricMode as r, Parser as s, Fabric as t, UserPlugin as u };
315
- //# sourceMappingURL=Fabric-Cu_YHe4S.d.ts.map
317
+ export { FabricOptions as a, Parser as c, UserPlugin as d, Extname as f, ResolvedFile as h, FabricMode as i, UserParser as l, KubbFile_d_exports as m, FabricConfig as n, FileManager as o, File as p, FabricContext as r, FileProcessor as s, Fabric as t, Plugin as u };
318
+ //# sourceMappingURL=Fabric-BfnUdEpq.d.cts.map
@@ -294,7 +294,7 @@ type FabricEvents = {
294
294
  }];
295
295
  };
296
296
  type FabricContext<TOptions extends FabricOptions> = {
297
- options?: TOptions;
297
+ config?: FabricConfig<TOptions>;
298
298
  events: AsyncEventEmitter<FabricEvents>;
299
299
  fileManager: FileManager;
300
300
  installedPlugins: Set<Plugin>;
@@ -302,6 +302,9 @@ type FabricContext<TOptions extends FabricOptions> = {
302
302
  };
303
303
  type FabricMode = 'sequential' | 'parallel';
304
304
  type AllOptional<T> = {} extends T ? true : false;
305
+ type FabricConfig<TOptions extends FabricOptions> = {
306
+ options: TOptions;
307
+ };
305
308
  type Install<TOptions = unknown> = TOptions extends any[] ? (app: Fabric, ...options: TOptions) => void | Promise<void> : AllOptional<TOptions> extends true ? (app: Fabric, options: TOptions | undefined) => void | Promise<void> : (app: Fabric, options: TOptions) => void | Promise<void>;
306
309
  type Inject<TOptions = unknown, TAppExtension extends Record<string, any> = {}> = TOptions extends any[] ? (app: Fabric, ...options: TOptions) => Partial<TAppExtension> : AllOptional<TOptions> extends true ? (app: Fabric, options: TOptions | undefined) => Partial<TAppExtension> : (app: Fabric, options: TOptions) => Partial<TAppExtension>;
307
310
  interface Fabric<TOptions extends FabricOptions = FabricOptions> extends Kubb.Fabric {
@@ -311,5 +314,5 @@ interface Fabric<TOptions extends FabricOptions = FabricOptions> extends Kubb.Fa
311
314
  addFile(...files: Array<File>): Promise<void>;
312
315
  }
313
316
  //#endregion
314
- export { FileManager as a, UserParser as c, Extname as d, File as f, FabricOptions as i, Plugin as l, ResolvedFile as m, FabricContext as n, FileProcessor as o, KubbFile_d_exports as p, FabricMode as r, Parser as s, Fabric as t, UserPlugin as u };
315
- //# sourceMappingURL=Fabric-CCPgegwe.d.cts.map
317
+ export { FabricOptions as a, Parser as c, UserPlugin as d, Extname as f, ResolvedFile as h, FabricMode as i, UserParser as l, KubbFile_d_exports as m, FabricConfig as n, FileManager as o, File as p, FabricContext as r, FileProcessor as s, Fabric as t, Plugin as u };
318
+ //# sourceMappingURL=Fabric-CxMkO4Rt.d.ts.map
@@ -0,0 +1,9 @@
1
+ import { a as FabricOptions, n as FabricConfig, t as Fabric } from "./Fabric-BfnUdEpq.cjs";
2
+
3
+ //#region src/defineFabric.d.ts
4
+ type RootRenderFunction<TOptions extends FabricOptions> = (fabric: Fabric<TOptions>) => void | Promise<void>;
5
+ type DefineFabric<TOptions extends FabricOptions> = (config?: FabricConfig<TOptions>) => Fabric;
6
+ declare function defineFabric<TOptions extends FabricOptions>(instance?: RootRenderFunction<TOptions>): DefineFabric<TOptions>;
7
+ //#endregion
8
+ export { defineFabric as n, DefineFabric as t };
9
+ //# sourceMappingURL=defineFabric-DApM1nNr.d.cts.map
@@ -0,0 +1,9 @@
1
+ import { a as FabricOptions, n as FabricConfig, t as Fabric } from "./Fabric-CxMkO4Rt.js";
2
+
3
+ //#region src/defineFabric.d.ts
4
+ type RootRenderFunction<TOptions extends FabricOptions> = (fabric: Fabric<TOptions>) => void | Promise<void>;
5
+ type DefineFabric<TOptions extends FabricOptions> = (config?: FabricConfig<TOptions>) => Fabric;
6
+ declare function defineFabric<TOptions extends FabricOptions>(instance?: RootRenderFunction<TOptions>): DefineFabric<TOptions>;
7
+ //#endregion
8
+ export { defineFabric as n, DefineFabric as t };
9
+ //# sourceMappingURL=defineFabric-Nf6eMaz7.d.ts.map
package/dist/index.cjs CHANGED
@@ -214,7 +214,7 @@ var FileManager = class {
214
214
  //#endregion
215
215
  //#region src/defineFabric.ts
216
216
  function defineFabric(instance) {
217
- function createFabric$1(options) {
217
+ function creator(config) {
218
218
  const events = new AsyncEventEmitter();
219
219
  const installedPlugins = /* @__PURE__ */ new Set();
220
220
  const installedParsers = /* @__PURE__ */ new Set();
@@ -222,7 +222,7 @@ function defineFabric(instance) {
222
222
  const fabric = {
223
223
  context: {
224
224
  events,
225
- options,
225
+ config,
226
226
  fileManager,
227
227
  installedPlugins,
228
228
  installedParsers
@@ -233,8 +233,8 @@ function defineFabric(instance) {
233
233
  async addFile(...newFiles) {
234
234
  await fileManager.add(...newFiles);
235
235
  },
236
- async use(pluginOrParser, ...options$1) {
237
- const args = options$1;
236
+ async use(pluginOrParser, ...options) {
237
+ const args = options;
238
238
  if (pluginOrParser.type === "plugin") {
239
239
  if (installedPlugins.has(pluginOrParser)) console.warn(`Plugin ${pluginOrParser.name} has already been applied to target fabric.`);
240
240
  else installedPlugins.add(pluginOrParser);
@@ -256,7 +256,7 @@ function defineFabric(instance) {
256
256
  if (instance) instance(fabric);
257
257
  return fabric;
258
258
  }
259
- return createFabric$1;
259
+ return creator;
260
260
  }
261
261
 
262
262
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["e","NodeEventEmitter","defaultParser","parser: Parser | undefined","resolvedFiles: Array<KubbFile.ResolvedFile>","createFile","trimExtName","createFabric","options","isFunction"],"sources":["../src/utils/Cache.ts","../../../node_modules/.pnpm/remeda@2.32.0/node_modules/remeda/dist/isFunction-BJjFuZR7.js","../src/utils/AsyncEventEmitter.ts","../src/FileProcessor.ts","../src/FileManager.ts","../src/defineFabric.ts","../src/createFabric.ts"],"sourcesContent":["export class Cache<T> {\n #buffer = new Map<string, T>()\n\n get(key: string): T | null {\n return this.#buffer.get(key) ?? null\n }\n\n set(key: string, value: T): void {\n this.#buffer.set(key, value)\n }\n\n delete(key: string): void {\n this.#buffer.delete(key)\n }\n\n clear(): void {\n this.#buffer.clear()\n }\n\n keys(): string[] {\n return [...this.#buffer.keys()]\n }\n\n values(): Array<T> {\n return [...this.#buffer.values()]\n }\n\n flush(): void {\n // No-op for base cache\n }\n}\n","const e=e=>typeof e==`function`;export{e as isFunction};\n//# sourceMappingURL=isFunction-BJjFuZR7.js.map","import { EventEmitter as NodeEventEmitter } from 'node:events'\n\nexport class AsyncEventEmitter<TEvents extends Record<string, any>> {\n constructor(maxListener = 100) {\n this.#emitter.setMaxListeners(maxListener)\n }\n #emitter = new NodeEventEmitter()\n\n async emit<TEventName extends keyof TEvents & string>(eventName: TEventName, ...eventArgs: TEvents[TEventName]): Promise<void> {\n const listeners = this.#emitter.listeners(eventName) as Array<(...args: TEvents[TEventName]) => any>\n\n if (listeners.length === 0) {\n return undefined\n }\n\n await Promise.all(\n listeners.map(async (listener) => {\n try {\n return await listener(...eventArgs)\n } catch (err) {\n console.error(`Error in async listener for \"${eventName}\":`, err)\n }\n }),\n )\n }\n\n on<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void): void {\n this.#emitter.on(eventName, handler as any)\n }\n\n onOnce<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArgs: TEvents[TEventName]) => void): void {\n const wrapper = (...args: TEvents[TEventName]) => {\n this.off(eventName, wrapper)\n handler(...args)\n }\n this.on(eventName, wrapper)\n }\n\n off<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void): void {\n this.#emitter.off(eventName, handler as any)\n }\n removeAll(): void {\n this.#emitter.removeAllListeners()\n }\n}\n","import type * as KubbFile from './KubbFile.ts'\nimport pLimit from 'p-limit'\n\nimport type { Parser } from './parsers/types.ts'\nimport { defaultParser } from './parsers/defaultParser.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\nimport type { FabricEvents, FabricMode } from './Fabric.ts'\n\nexport type ProcessFilesProps = {\n parsers?: Set<Parser>\n extension?: Record<KubbFile.Extname, KubbFile.Extname | ''>\n dryRun?: boolean\n /**\n * @default 'sequential'\n */\n mode?: FabricMode\n}\n\ntype GetParseOptions = {\n parsers?: Set<Parser>\n extension?: Record<KubbFile.Extname, KubbFile.Extname | ''>\n}\n\ntype Options = {\n events?: AsyncEventEmitter<FabricEvents>\n}\n\nexport class FileProcessor {\n #limit = pLimit(100)\n events: AsyncEventEmitter<FabricEvents>\n\n constructor({ events = new AsyncEventEmitter<FabricEvents>() }: Options = {}) {\n this.events = events\n\n return this\n }\n\n async parse(file: KubbFile.ResolvedFile, { parsers, extension }: GetParseOptions = {}): Promise<string> {\n const parseExtName = extension?.[file.extname] || undefined\n\n if (!parsers) {\n console.warn('No parsers provided, using default parser. If you want to use a specific parser, please provide it in the options.')\n\n return defaultParser.parse(file, { extname: parseExtName })\n }\n\n if (!file.extname) {\n return defaultParser.parse(file, { extname: parseExtName })\n }\n\n let parser: Parser | undefined\n for (const item of parsers) {\n if (item.extNames?.includes(file.extname)) {\n parser = item\n break\n }\n }\n\n if (!parser) {\n return defaultParser.parse(file, { extname: parseExtName })\n }\n\n return parser.parse(file, { extname: parseExtName })\n }\n\n async run(\n files: Array<KubbFile.ResolvedFile>,\n { parsers, mode = 'sequential', dryRun, extension }: ProcessFilesProps = {},\n ): Promise<KubbFile.ResolvedFile[]> {\n await this.events.emit('process:start', { files })\n\n let processed = 0\n const total = files.length\n\n const processOne = async (resolvedFile: KubbFile.ResolvedFile, index: number) => {\n const percentage = (processed / total) * 100\n\n await this.events.emit('file:start', { file: resolvedFile, index, total })\n\n const source = dryRun ? undefined : await this.parse(resolvedFile, { extension, parsers })\n\n await this.events.emit('process:progress', {\n file: resolvedFile,\n source,\n processed,\n percentage,\n total,\n })\n\n processed++\n\n await this.events.emit('file:end', { file: resolvedFile, index, total })\n }\n\n if (mode === 'sequential') {\n async function* asyncFiles() {\n for (let index = 0; index < files.length; index++) {\n yield [files[index], index] as const\n }\n }\n\n for await (const [file, index] of asyncFiles()) {\n if (file) {\n await processOne(file, index)\n }\n }\n } else {\n const promises = files.map((resolvedFile, index) => this.#limit(() => processOne(resolvedFile, index)))\n await Promise.all(promises)\n }\n\n await this.events.emit('process:end', { files })\n\n return files\n }\n}\n","import type * as KubbFile from './KubbFile.ts'\nimport { Cache } from './utils/Cache.ts'\nimport { trimExtName } from './utils/trimExtName.ts'\nimport { orderBy } from 'natural-orderby'\nimport { createFile } from './createFile.ts'\nimport { FileProcessor, type ProcessFilesProps } from './FileProcessor.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\nimport type { FabricEvents } from './Fabric.ts'\n\nfunction mergeFile<TMeta extends object = object>(a: KubbFile.File<TMeta>, b: KubbFile.File<TMeta>): KubbFile.File<TMeta> {\n return {\n ...a,\n sources: [...(a.sources || []), ...(b.sources || [])],\n imports: [...(a.imports || []), ...(b.imports || [])],\n exports: [...(a.exports || []), ...(b.exports || [])],\n }\n}\n\ntype Options = {\n events?: AsyncEventEmitter<FabricEvents>\n}\n\nexport class FileManager {\n #cache = new Cache<KubbFile.ResolvedFile>()\n events: AsyncEventEmitter<FabricEvents>\n processor: FileProcessor\n\n constructor({ events = new AsyncEventEmitter<FabricEvents>() }: Options = {}) {\n this.processor = new FileProcessor({ events })\n\n this.events = events\n return this\n }\n\n async add(...files: Array<KubbFile.File>) {\n const resolvedFiles: Array<KubbFile.ResolvedFile> = []\n\n const mergedFiles = new Map<string, KubbFile.File>()\n\n files.forEach((file) => {\n const existing = mergedFiles.get(file.path)\n if (existing) {\n mergedFiles.set(file.path, mergeFile(existing, file))\n } else {\n mergedFiles.set(file.path, file)\n }\n })\n\n for (const file of mergedFiles.values()) {\n const existing = this.#cache.get(file.path)\n\n const merged = existing ? mergeFile(existing, file) : file\n const resolvedFile = createFile(merged)\n\n this.#cache.set(resolvedFile.path, resolvedFile)\n this.flush()\n\n resolvedFiles.push(resolvedFile)\n }\n\n await this.events.emit('file:add', { files: resolvedFiles })\n\n return resolvedFiles\n }\n\n flush() {\n this.#cache.flush()\n }\n\n getByPath(path: KubbFile.Path): KubbFile.ResolvedFile | null {\n return this.#cache.get(path)\n }\n\n deleteByPath(path: KubbFile.Path): void {\n this.#cache.delete(path)\n }\n\n clear(): void {\n this.#cache.clear()\n }\n\n get files(): Array<KubbFile.ResolvedFile> {\n const cachedKeys = this.#cache.keys()\n\n // order by path length and if file is a barrel file\n const keys = orderBy(cachedKeys, [(v) => v.length, (v) => trimExtName(v).endsWith('index')])\n\n const files = keys.map((key) => this.#cache.get(key))\n\n return files.filter(Boolean)\n }\n\n //TODO add test and check if write of FileManager contains the newly added file\n async write(options: ProcessFilesProps): Promise<KubbFile.ResolvedFile[]> {\n await this.events.emit('write:start', { files: this.files })\n\n const resolvedFiles = await this.processor.run(this.files, options)\n\n this.clear()\n\n await this.events.emit('write:end', { files: resolvedFiles })\n\n return resolvedFiles\n }\n}\n","import { FileManager } from './FileManager.ts'\nimport { isFunction } from 'remeda'\nimport type { Plugin } from './plugins/types.ts'\nimport type { Parser } from './parsers/types.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\nimport type { FabricContext, FabricEvents, FabricOptions } from './Fabric.ts'\n\nimport type { Fabric } from './index.ts'\n\ntype RootRenderFunction<TOptions extends FabricOptions> = (fabric: Fabric<TOptions>) => void | Promise<void>\n\nexport type DefineFabric<TOptions> = (options?: TOptions) => Fabric\n\nexport function defineFabric<TOptions extends FabricOptions>(instance?: RootRenderFunction<TOptions>): DefineFabric<TOptions> {\n function createFabric(options?: TOptions): Fabric {\n const events = new AsyncEventEmitter<FabricEvents>()\n const installedPlugins = new Set<Plugin<any>>()\n const installedParsers = new Set<Parser<any>>()\n const fileManager = new FileManager({ events })\n const context = {\n events,\n options,\n fileManager,\n installedPlugins,\n installedParsers,\n } as FabricContext<TOptions>\n\n const fabric = {\n context,\n get files() {\n return fileManager.files\n },\n async addFile(...newFiles) {\n await fileManager.add(...newFiles)\n },\n async use(pluginOrParser, ...options) {\n const args = options\n\n if (pluginOrParser.type === 'plugin') {\n if (installedPlugins.has(pluginOrParser)) {\n console.warn(`Plugin ${pluginOrParser.name} has already been applied to target fabric.`)\n } else {\n installedPlugins.add(pluginOrParser)\n }\n\n if (pluginOrParser.inject && isFunction(pluginOrParser.inject)) {\n const injecter = pluginOrParser.inject\n\n const extraApp = (injecter as any)(fabric, ...args)\n Object.assign(fabric, extraApp)\n }\n }\n if (pluginOrParser.type === 'parser') {\n if (installedParsers.has(pluginOrParser)) {\n console.warn(`Parser ${pluginOrParser.name} has already been applied to target fabric.`)\n } else {\n installedParsers.add(pluginOrParser)\n }\n }\n\n if (pluginOrParser && isFunction(pluginOrParser.install)) {\n const installer = pluginOrParser.install\n\n await (installer as any)(fabric, ...args)\n }\n\n return fabric\n },\n } as Fabric<TOptions>\n\n if (instance) {\n instance(fabric)\n }\n\n return fabric\n }\n\n return createFabric\n}\n","import { defineFabric } from './defineFabric.ts'\n\nexport const createFabric = defineFabric()\n"],"x_google_ignoreList":[1],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["e","NodeEventEmitter","defaultParser","parser: Parser | undefined","resolvedFiles: Array<KubbFile.ResolvedFile>","createFile","trimExtName","isFunction"],"sources":["../src/utils/Cache.ts","../../../node_modules/.pnpm/remeda@2.32.0/node_modules/remeda/dist/isFunction-BJjFuZR7.js","../src/utils/AsyncEventEmitter.ts","../src/FileProcessor.ts","../src/FileManager.ts","../src/defineFabric.ts","../src/createFabric.ts"],"sourcesContent":["export class Cache<T> {\n #buffer = new Map<string, T>()\n\n get(key: string): T | null {\n return this.#buffer.get(key) ?? null\n }\n\n set(key: string, value: T): void {\n this.#buffer.set(key, value)\n }\n\n delete(key: string): void {\n this.#buffer.delete(key)\n }\n\n clear(): void {\n this.#buffer.clear()\n }\n\n keys(): string[] {\n return [...this.#buffer.keys()]\n }\n\n values(): Array<T> {\n return [...this.#buffer.values()]\n }\n\n flush(): void {\n // No-op for base cache\n }\n}\n","const e=e=>typeof e==`function`;export{e as isFunction};\n//# sourceMappingURL=isFunction-BJjFuZR7.js.map","import { EventEmitter as NodeEventEmitter } from 'node:events'\n\nexport class AsyncEventEmitter<TEvents extends Record<string, any>> {\n constructor(maxListener = 100) {\n this.#emitter.setMaxListeners(maxListener)\n }\n #emitter = new NodeEventEmitter()\n\n async emit<TEventName extends keyof TEvents & string>(eventName: TEventName, ...eventArgs: TEvents[TEventName]): Promise<void> {\n const listeners = this.#emitter.listeners(eventName) as Array<(...args: TEvents[TEventName]) => any>\n\n if (listeners.length === 0) {\n return undefined\n }\n\n await Promise.all(\n listeners.map(async (listener) => {\n try {\n return await listener(...eventArgs)\n } catch (err) {\n console.error(`Error in async listener for \"${eventName}\":`, err)\n }\n }),\n )\n }\n\n on<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void): void {\n this.#emitter.on(eventName, handler as any)\n }\n\n onOnce<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArgs: TEvents[TEventName]) => void): void {\n const wrapper = (...args: TEvents[TEventName]) => {\n this.off(eventName, wrapper)\n handler(...args)\n }\n this.on(eventName, wrapper)\n }\n\n off<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void): void {\n this.#emitter.off(eventName, handler as any)\n }\n removeAll(): void {\n this.#emitter.removeAllListeners()\n }\n}\n","import type * as KubbFile from './KubbFile.ts'\nimport pLimit from 'p-limit'\n\nimport type { Parser } from './parsers/types.ts'\nimport { defaultParser } from './parsers/defaultParser.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\nimport type { FabricEvents, FabricMode } from './Fabric.ts'\n\nexport type ProcessFilesProps = {\n parsers?: Set<Parser>\n extension?: Record<KubbFile.Extname, KubbFile.Extname | ''>\n dryRun?: boolean\n /**\n * @default 'sequential'\n */\n mode?: FabricMode\n}\n\ntype GetParseOptions = {\n parsers?: Set<Parser>\n extension?: Record<KubbFile.Extname, KubbFile.Extname | ''>\n}\n\ntype Options = {\n events?: AsyncEventEmitter<FabricEvents>\n}\n\nexport class FileProcessor {\n #limit = pLimit(100)\n events: AsyncEventEmitter<FabricEvents>\n\n constructor({ events = new AsyncEventEmitter<FabricEvents>() }: Options = {}) {\n this.events = events\n\n return this\n }\n\n async parse(file: KubbFile.ResolvedFile, { parsers, extension }: GetParseOptions = {}): Promise<string> {\n const parseExtName = extension?.[file.extname] || undefined\n\n if (!parsers) {\n console.warn('No parsers provided, using default parser. If you want to use a specific parser, please provide it in the options.')\n\n return defaultParser.parse(file, { extname: parseExtName })\n }\n\n if (!file.extname) {\n return defaultParser.parse(file, { extname: parseExtName })\n }\n\n let parser: Parser | undefined\n for (const item of parsers) {\n if (item.extNames?.includes(file.extname)) {\n parser = item\n break\n }\n }\n\n if (!parser) {\n return defaultParser.parse(file, { extname: parseExtName })\n }\n\n return parser.parse(file, { extname: parseExtName })\n }\n\n async run(\n files: Array<KubbFile.ResolvedFile>,\n { parsers, mode = 'sequential', dryRun, extension }: ProcessFilesProps = {},\n ): Promise<KubbFile.ResolvedFile[]> {\n await this.events.emit('process:start', { files })\n\n let processed = 0\n const total = files.length\n\n const processOne = async (resolvedFile: KubbFile.ResolvedFile, index: number) => {\n const percentage = (processed / total) * 100\n\n await this.events.emit('file:start', { file: resolvedFile, index, total })\n\n const source = dryRun ? undefined : await this.parse(resolvedFile, { extension, parsers })\n\n await this.events.emit('process:progress', {\n file: resolvedFile,\n source,\n processed,\n percentage,\n total,\n })\n\n processed++\n\n await this.events.emit('file:end', { file: resolvedFile, index, total })\n }\n\n if (mode === 'sequential') {\n async function* asyncFiles() {\n for (let index = 0; index < files.length; index++) {\n yield [files[index], index] as const\n }\n }\n\n for await (const [file, index] of asyncFiles()) {\n if (file) {\n await processOne(file, index)\n }\n }\n } else {\n const promises = files.map((resolvedFile, index) => this.#limit(() => processOne(resolvedFile, index)))\n await Promise.all(promises)\n }\n\n await this.events.emit('process:end', { files })\n\n return files\n }\n}\n","import type * as KubbFile from './KubbFile.ts'\nimport { Cache } from './utils/Cache.ts'\nimport { trimExtName } from './utils/trimExtName.ts'\nimport { orderBy } from 'natural-orderby'\nimport { createFile } from './createFile.ts'\nimport { FileProcessor, type ProcessFilesProps } from './FileProcessor.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\nimport type { FabricEvents } from './Fabric.ts'\n\nfunction mergeFile<TMeta extends object = object>(a: KubbFile.File<TMeta>, b: KubbFile.File<TMeta>): KubbFile.File<TMeta> {\n return {\n ...a,\n sources: [...(a.sources || []), ...(b.sources || [])],\n imports: [...(a.imports || []), ...(b.imports || [])],\n exports: [...(a.exports || []), ...(b.exports || [])],\n }\n}\n\ntype Options = {\n events?: AsyncEventEmitter<FabricEvents>\n}\n\nexport class FileManager {\n #cache = new Cache<KubbFile.ResolvedFile>()\n events: AsyncEventEmitter<FabricEvents>\n processor: FileProcessor\n\n constructor({ events = new AsyncEventEmitter<FabricEvents>() }: Options = {}) {\n this.processor = new FileProcessor({ events })\n\n this.events = events\n return this\n }\n\n async add(...files: Array<KubbFile.File>) {\n const resolvedFiles: Array<KubbFile.ResolvedFile> = []\n\n const mergedFiles = new Map<string, KubbFile.File>()\n\n files.forEach((file) => {\n const existing = mergedFiles.get(file.path)\n if (existing) {\n mergedFiles.set(file.path, mergeFile(existing, file))\n } else {\n mergedFiles.set(file.path, file)\n }\n })\n\n for (const file of mergedFiles.values()) {\n const existing = this.#cache.get(file.path)\n\n const merged = existing ? mergeFile(existing, file) : file\n const resolvedFile = createFile(merged)\n\n this.#cache.set(resolvedFile.path, resolvedFile)\n this.flush()\n\n resolvedFiles.push(resolvedFile)\n }\n\n await this.events.emit('file:add', { files: resolvedFiles })\n\n return resolvedFiles\n }\n\n flush() {\n this.#cache.flush()\n }\n\n getByPath(path: KubbFile.Path): KubbFile.ResolvedFile | null {\n return this.#cache.get(path)\n }\n\n deleteByPath(path: KubbFile.Path): void {\n this.#cache.delete(path)\n }\n\n clear(): void {\n this.#cache.clear()\n }\n\n get files(): Array<KubbFile.ResolvedFile> {\n const cachedKeys = this.#cache.keys()\n\n // order by path length and if file is a barrel file\n const keys = orderBy(cachedKeys, [(v) => v.length, (v) => trimExtName(v).endsWith('index')])\n\n const files = keys.map((key) => this.#cache.get(key))\n\n return files.filter(Boolean)\n }\n\n //TODO add test and check if write of FileManager contains the newly added file\n async write(options: ProcessFilesProps): Promise<KubbFile.ResolvedFile[]> {\n await this.events.emit('write:start', { files: this.files })\n\n const resolvedFiles = await this.processor.run(this.files, options)\n\n this.clear()\n\n await this.events.emit('write:end', { files: resolvedFiles })\n\n return resolvedFiles\n }\n}\n","import { FileManager } from './FileManager.ts'\nimport { isFunction } from 'remeda'\nimport type { Plugin } from './plugins/types.ts'\nimport type { Parser } from './parsers/types.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\nimport type { FabricConfig, FabricContext, FabricEvents, FabricOptions } from './Fabric.ts'\n\nimport type { Fabric } from './Fabric.ts'\n\ntype RootRenderFunction<TOptions extends FabricOptions> = (fabric: Fabric<TOptions>) => void | Promise<void>\n\nexport type DefineFabric<TOptions extends FabricOptions> = (config?: FabricConfig<TOptions>) => Fabric\n\nexport function defineFabric<TOptions extends FabricOptions>(instance?: RootRenderFunction<TOptions>): DefineFabric<TOptions> {\n function creator(config?: FabricConfig<TOptions>): Fabric {\n const events = new AsyncEventEmitter<FabricEvents>()\n const installedPlugins = new Set<Plugin<any>>()\n const installedParsers = new Set<Parser<any>>()\n const fileManager = new FileManager({ events })\n const context = {\n events,\n config,\n fileManager,\n installedPlugins,\n installedParsers,\n } as FabricContext<TOptions>\n\n const fabric = {\n context,\n get files() {\n return fileManager.files\n },\n async addFile(...newFiles) {\n await fileManager.add(...newFiles)\n },\n async use(pluginOrParser, ...options) {\n const args = options\n\n if (pluginOrParser.type === 'plugin') {\n if (installedPlugins.has(pluginOrParser)) {\n console.warn(`Plugin ${pluginOrParser.name} has already been applied to target fabric.`)\n } else {\n installedPlugins.add(pluginOrParser)\n }\n\n if (pluginOrParser.inject && isFunction(pluginOrParser.inject)) {\n const injecter = pluginOrParser.inject\n\n const extraApp = (injecter as any)(fabric, ...args)\n Object.assign(fabric, extraApp)\n }\n }\n if (pluginOrParser.type === 'parser') {\n if (installedParsers.has(pluginOrParser)) {\n console.warn(`Parser ${pluginOrParser.name} has already been applied to target fabric.`)\n } else {\n installedParsers.add(pluginOrParser)\n }\n }\n\n if (pluginOrParser && isFunction(pluginOrParser.install)) {\n const installer = pluginOrParser.install\n\n await (installer as any)(fabric, ...args)\n }\n\n return fabric\n },\n } as Fabric<TOptions>\n\n if (instance) {\n instance(fabric)\n }\n\n return fabric\n }\n\n return creator\n}\n","import { defineFabric } from './defineFabric.ts'\n\nexport const createFabric = defineFabric()\n"],"x_google_ignoreList":[1],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -1,3 +1,14 @@
1
- import { a as FileManager, o as FileProcessor, t as Fabric } from "./Fabric-CCPgegwe.cjs";
2
- import { i as defineFabric, n as createFabric, t as createFile } from "./index-BUculP1D.cjs";
3
- export { Fabric, FileManager, FileProcessor, createFabric, createFile, defineFabric };
1
+ import { a as FabricOptions, h as ResolvedFile, o as FileManager, p as File, s as FileProcessor, t as Fabric } from "./Fabric-BfnUdEpq.cjs";
2
+ import { n as defineFabric, t as DefineFabric } from "./defineFabric-DApM1nNr.cjs";
3
+
4
+ //#region src/createFabric.d.ts
5
+ declare const createFabric: DefineFabric<FabricOptions>;
6
+ //#endregion
7
+ //#region src/createFile.d.ts
8
+ /**
9
+ * Helper to create a file with name and id set
10
+ */
11
+ declare function createFile<TMeta extends object = object>(file: File<TMeta>): ResolvedFile<TMeta>;
12
+ //#endregion
13
+ export { type Fabric, FileManager, FileProcessor, createFabric, createFile, defineFabric };
14
+ //# sourceMappingURL=index.d.cts.map
package/dist/index.d.ts CHANGED
@@ -1,3 +1,14 @@
1
- import { a as FileManager, o as FileProcessor, t as Fabric } from "./Fabric-Cu_YHe4S.js";
2
- import { i as defineFabric, n as createFabric, t as createFile } from "./index-CvkyZHXK.js";
3
- export { Fabric, FileManager, FileProcessor, createFabric, createFile, defineFabric };
1
+ import { a as FabricOptions, h as ResolvedFile, o as FileManager, p as File, s as FileProcessor, t as Fabric } from "./Fabric-CxMkO4Rt.js";
2
+ import { n as defineFabric, t as DefineFabric } from "./defineFabric-Nf6eMaz7.js";
3
+
4
+ //#region src/createFabric.d.ts
5
+ declare const createFabric: DefineFabric<FabricOptions>;
6
+ //#endregion
7
+ //#region src/createFile.d.ts
8
+ /**
9
+ * Helper to create a file with name and id set
10
+ */
11
+ declare function createFile<TMeta extends object = object>(file: File<TMeta>): ResolvedFile<TMeta>;
12
+ //#endregion
13
+ export { type Fabric, FileManager, FileProcessor, createFabric, createFile, defineFabric };
14
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -211,7 +211,7 @@ var FileManager = class {
211
211
  //#endregion
212
212
  //#region src/defineFabric.ts
213
213
  function defineFabric(instance) {
214
- function createFabric$1(options) {
214
+ function creator(config) {
215
215
  const events = new AsyncEventEmitter();
216
216
  const installedPlugins = /* @__PURE__ */ new Set();
217
217
  const installedParsers = /* @__PURE__ */ new Set();
@@ -219,7 +219,7 @@ function defineFabric(instance) {
219
219
  const fabric = {
220
220
  context: {
221
221
  events,
222
- options,
222
+ config,
223
223
  fileManager,
224
224
  installedPlugins,
225
225
  installedParsers
@@ -230,8 +230,8 @@ function defineFabric(instance) {
230
230
  async addFile(...newFiles) {
231
231
  await fileManager.add(...newFiles);
232
232
  },
233
- async use(pluginOrParser, ...options$1) {
234
- const args = options$1;
233
+ async use(pluginOrParser, ...options) {
234
+ const args = options;
235
235
  if (pluginOrParser.type === "plugin") {
236
236
  if (installedPlugins.has(pluginOrParser)) console.warn(`Plugin ${pluginOrParser.name} has already been applied to target fabric.`);
237
237
  else installedPlugins.add(pluginOrParser);
@@ -253,7 +253,7 @@ function defineFabric(instance) {
253
253
  if (instance) instance(fabric);
254
254
  return fabric;
255
255
  }
256
- return createFabric$1;
256
+ return creator;
257
257
  }
258
258
 
259
259
  //#endregion
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["e","NodeEventEmitter","parser: Parser | undefined","resolvedFiles: Array<KubbFile.ResolvedFile>","createFabric","options","isFunction"],"sources":["../src/utils/Cache.ts","../../../node_modules/.pnpm/remeda@2.32.0/node_modules/remeda/dist/isFunction-BJjFuZR7.js","../src/utils/AsyncEventEmitter.ts","../src/FileProcessor.ts","../src/FileManager.ts","../src/defineFabric.ts","../src/createFabric.ts"],"sourcesContent":["export class Cache<T> {\n #buffer = new Map<string, T>()\n\n get(key: string): T | null {\n return this.#buffer.get(key) ?? null\n }\n\n set(key: string, value: T): void {\n this.#buffer.set(key, value)\n }\n\n delete(key: string): void {\n this.#buffer.delete(key)\n }\n\n clear(): void {\n this.#buffer.clear()\n }\n\n keys(): string[] {\n return [...this.#buffer.keys()]\n }\n\n values(): Array<T> {\n return [...this.#buffer.values()]\n }\n\n flush(): void {\n // No-op for base cache\n }\n}\n","const e=e=>typeof e==`function`;export{e as isFunction};\n//# sourceMappingURL=isFunction-BJjFuZR7.js.map","import { EventEmitter as NodeEventEmitter } from 'node:events'\n\nexport class AsyncEventEmitter<TEvents extends Record<string, any>> {\n constructor(maxListener = 100) {\n this.#emitter.setMaxListeners(maxListener)\n }\n #emitter = new NodeEventEmitter()\n\n async emit<TEventName extends keyof TEvents & string>(eventName: TEventName, ...eventArgs: TEvents[TEventName]): Promise<void> {\n const listeners = this.#emitter.listeners(eventName) as Array<(...args: TEvents[TEventName]) => any>\n\n if (listeners.length === 0) {\n return undefined\n }\n\n await Promise.all(\n listeners.map(async (listener) => {\n try {\n return await listener(...eventArgs)\n } catch (err) {\n console.error(`Error in async listener for \"${eventName}\":`, err)\n }\n }),\n )\n }\n\n on<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void): void {\n this.#emitter.on(eventName, handler as any)\n }\n\n onOnce<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArgs: TEvents[TEventName]) => void): void {\n const wrapper = (...args: TEvents[TEventName]) => {\n this.off(eventName, wrapper)\n handler(...args)\n }\n this.on(eventName, wrapper)\n }\n\n off<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void): void {\n this.#emitter.off(eventName, handler as any)\n }\n removeAll(): void {\n this.#emitter.removeAllListeners()\n }\n}\n","import type * as KubbFile from './KubbFile.ts'\nimport pLimit from 'p-limit'\n\nimport type { Parser } from './parsers/types.ts'\nimport { defaultParser } from './parsers/defaultParser.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\nimport type { FabricEvents, FabricMode } from './Fabric.ts'\n\nexport type ProcessFilesProps = {\n parsers?: Set<Parser>\n extension?: Record<KubbFile.Extname, KubbFile.Extname | ''>\n dryRun?: boolean\n /**\n * @default 'sequential'\n */\n mode?: FabricMode\n}\n\ntype GetParseOptions = {\n parsers?: Set<Parser>\n extension?: Record<KubbFile.Extname, KubbFile.Extname | ''>\n}\n\ntype Options = {\n events?: AsyncEventEmitter<FabricEvents>\n}\n\nexport class FileProcessor {\n #limit = pLimit(100)\n events: AsyncEventEmitter<FabricEvents>\n\n constructor({ events = new AsyncEventEmitter<FabricEvents>() }: Options = {}) {\n this.events = events\n\n return this\n }\n\n async parse(file: KubbFile.ResolvedFile, { parsers, extension }: GetParseOptions = {}): Promise<string> {\n const parseExtName = extension?.[file.extname] || undefined\n\n if (!parsers) {\n console.warn('No parsers provided, using default parser. If you want to use a specific parser, please provide it in the options.')\n\n return defaultParser.parse(file, { extname: parseExtName })\n }\n\n if (!file.extname) {\n return defaultParser.parse(file, { extname: parseExtName })\n }\n\n let parser: Parser | undefined\n for (const item of parsers) {\n if (item.extNames?.includes(file.extname)) {\n parser = item\n break\n }\n }\n\n if (!parser) {\n return defaultParser.parse(file, { extname: parseExtName })\n }\n\n return parser.parse(file, { extname: parseExtName })\n }\n\n async run(\n files: Array<KubbFile.ResolvedFile>,\n { parsers, mode = 'sequential', dryRun, extension }: ProcessFilesProps = {},\n ): Promise<KubbFile.ResolvedFile[]> {\n await this.events.emit('process:start', { files })\n\n let processed = 0\n const total = files.length\n\n const processOne = async (resolvedFile: KubbFile.ResolvedFile, index: number) => {\n const percentage = (processed / total) * 100\n\n await this.events.emit('file:start', { file: resolvedFile, index, total })\n\n const source = dryRun ? undefined : await this.parse(resolvedFile, { extension, parsers })\n\n await this.events.emit('process:progress', {\n file: resolvedFile,\n source,\n processed,\n percentage,\n total,\n })\n\n processed++\n\n await this.events.emit('file:end', { file: resolvedFile, index, total })\n }\n\n if (mode === 'sequential') {\n async function* asyncFiles() {\n for (let index = 0; index < files.length; index++) {\n yield [files[index], index] as const\n }\n }\n\n for await (const [file, index] of asyncFiles()) {\n if (file) {\n await processOne(file, index)\n }\n }\n } else {\n const promises = files.map((resolvedFile, index) => this.#limit(() => processOne(resolvedFile, index)))\n await Promise.all(promises)\n }\n\n await this.events.emit('process:end', { files })\n\n return files\n }\n}\n","import type * as KubbFile from './KubbFile.ts'\nimport { Cache } from './utils/Cache.ts'\nimport { trimExtName } from './utils/trimExtName.ts'\nimport { orderBy } from 'natural-orderby'\nimport { createFile } from './createFile.ts'\nimport { FileProcessor, type ProcessFilesProps } from './FileProcessor.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\nimport type { FabricEvents } from './Fabric.ts'\n\nfunction mergeFile<TMeta extends object = object>(a: KubbFile.File<TMeta>, b: KubbFile.File<TMeta>): KubbFile.File<TMeta> {\n return {\n ...a,\n sources: [...(a.sources || []), ...(b.sources || [])],\n imports: [...(a.imports || []), ...(b.imports || [])],\n exports: [...(a.exports || []), ...(b.exports || [])],\n }\n}\n\ntype Options = {\n events?: AsyncEventEmitter<FabricEvents>\n}\n\nexport class FileManager {\n #cache = new Cache<KubbFile.ResolvedFile>()\n events: AsyncEventEmitter<FabricEvents>\n processor: FileProcessor\n\n constructor({ events = new AsyncEventEmitter<FabricEvents>() }: Options = {}) {\n this.processor = new FileProcessor({ events })\n\n this.events = events\n return this\n }\n\n async add(...files: Array<KubbFile.File>) {\n const resolvedFiles: Array<KubbFile.ResolvedFile> = []\n\n const mergedFiles = new Map<string, KubbFile.File>()\n\n files.forEach((file) => {\n const existing = mergedFiles.get(file.path)\n if (existing) {\n mergedFiles.set(file.path, mergeFile(existing, file))\n } else {\n mergedFiles.set(file.path, file)\n }\n })\n\n for (const file of mergedFiles.values()) {\n const existing = this.#cache.get(file.path)\n\n const merged = existing ? mergeFile(existing, file) : file\n const resolvedFile = createFile(merged)\n\n this.#cache.set(resolvedFile.path, resolvedFile)\n this.flush()\n\n resolvedFiles.push(resolvedFile)\n }\n\n await this.events.emit('file:add', { files: resolvedFiles })\n\n return resolvedFiles\n }\n\n flush() {\n this.#cache.flush()\n }\n\n getByPath(path: KubbFile.Path): KubbFile.ResolvedFile | null {\n return this.#cache.get(path)\n }\n\n deleteByPath(path: KubbFile.Path): void {\n this.#cache.delete(path)\n }\n\n clear(): void {\n this.#cache.clear()\n }\n\n get files(): Array<KubbFile.ResolvedFile> {\n const cachedKeys = this.#cache.keys()\n\n // order by path length and if file is a barrel file\n const keys = orderBy(cachedKeys, [(v) => v.length, (v) => trimExtName(v).endsWith('index')])\n\n const files = keys.map((key) => this.#cache.get(key))\n\n return files.filter(Boolean)\n }\n\n //TODO add test and check if write of FileManager contains the newly added file\n async write(options: ProcessFilesProps): Promise<KubbFile.ResolvedFile[]> {\n await this.events.emit('write:start', { files: this.files })\n\n const resolvedFiles = await this.processor.run(this.files, options)\n\n this.clear()\n\n await this.events.emit('write:end', { files: resolvedFiles })\n\n return resolvedFiles\n }\n}\n","import { FileManager } from './FileManager.ts'\nimport { isFunction } from 'remeda'\nimport type { Plugin } from './plugins/types.ts'\nimport type { Parser } from './parsers/types.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\nimport type { FabricContext, FabricEvents, FabricOptions } from './Fabric.ts'\n\nimport type { Fabric } from './index.ts'\n\ntype RootRenderFunction<TOptions extends FabricOptions> = (fabric: Fabric<TOptions>) => void | Promise<void>\n\nexport type DefineFabric<TOptions> = (options?: TOptions) => Fabric\n\nexport function defineFabric<TOptions extends FabricOptions>(instance?: RootRenderFunction<TOptions>): DefineFabric<TOptions> {\n function createFabric(options?: TOptions): Fabric {\n const events = new AsyncEventEmitter<FabricEvents>()\n const installedPlugins = new Set<Plugin<any>>()\n const installedParsers = new Set<Parser<any>>()\n const fileManager = new FileManager({ events })\n const context = {\n events,\n options,\n fileManager,\n installedPlugins,\n installedParsers,\n } as FabricContext<TOptions>\n\n const fabric = {\n context,\n get files() {\n return fileManager.files\n },\n async addFile(...newFiles) {\n await fileManager.add(...newFiles)\n },\n async use(pluginOrParser, ...options) {\n const args = options\n\n if (pluginOrParser.type === 'plugin') {\n if (installedPlugins.has(pluginOrParser)) {\n console.warn(`Plugin ${pluginOrParser.name} has already been applied to target fabric.`)\n } else {\n installedPlugins.add(pluginOrParser)\n }\n\n if (pluginOrParser.inject && isFunction(pluginOrParser.inject)) {\n const injecter = pluginOrParser.inject\n\n const extraApp = (injecter as any)(fabric, ...args)\n Object.assign(fabric, extraApp)\n }\n }\n if (pluginOrParser.type === 'parser') {\n if (installedParsers.has(pluginOrParser)) {\n console.warn(`Parser ${pluginOrParser.name} has already been applied to target fabric.`)\n } else {\n installedParsers.add(pluginOrParser)\n }\n }\n\n if (pluginOrParser && isFunction(pluginOrParser.install)) {\n const installer = pluginOrParser.install\n\n await (installer as any)(fabric, ...args)\n }\n\n return fabric\n },\n } as Fabric<TOptions>\n\n if (instance) {\n instance(fabric)\n }\n\n return fabric\n }\n\n return createFabric\n}\n","import { defineFabric } from './defineFabric.ts'\n\nexport const createFabric = defineFabric()\n"],"x_google_ignoreList":[1],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["e","NodeEventEmitter","parser: Parser | undefined","resolvedFiles: Array<KubbFile.ResolvedFile>","isFunction"],"sources":["../src/utils/Cache.ts","../../../node_modules/.pnpm/remeda@2.32.0/node_modules/remeda/dist/isFunction-BJjFuZR7.js","../src/utils/AsyncEventEmitter.ts","../src/FileProcessor.ts","../src/FileManager.ts","../src/defineFabric.ts","../src/createFabric.ts"],"sourcesContent":["export class Cache<T> {\n #buffer = new Map<string, T>()\n\n get(key: string): T | null {\n return this.#buffer.get(key) ?? null\n }\n\n set(key: string, value: T): void {\n this.#buffer.set(key, value)\n }\n\n delete(key: string): void {\n this.#buffer.delete(key)\n }\n\n clear(): void {\n this.#buffer.clear()\n }\n\n keys(): string[] {\n return [...this.#buffer.keys()]\n }\n\n values(): Array<T> {\n return [...this.#buffer.values()]\n }\n\n flush(): void {\n // No-op for base cache\n }\n}\n","const e=e=>typeof e==`function`;export{e as isFunction};\n//# sourceMappingURL=isFunction-BJjFuZR7.js.map","import { EventEmitter as NodeEventEmitter } from 'node:events'\n\nexport class AsyncEventEmitter<TEvents extends Record<string, any>> {\n constructor(maxListener = 100) {\n this.#emitter.setMaxListeners(maxListener)\n }\n #emitter = new NodeEventEmitter()\n\n async emit<TEventName extends keyof TEvents & string>(eventName: TEventName, ...eventArgs: TEvents[TEventName]): Promise<void> {\n const listeners = this.#emitter.listeners(eventName) as Array<(...args: TEvents[TEventName]) => any>\n\n if (listeners.length === 0) {\n return undefined\n }\n\n await Promise.all(\n listeners.map(async (listener) => {\n try {\n return await listener(...eventArgs)\n } catch (err) {\n console.error(`Error in async listener for \"${eventName}\":`, err)\n }\n }),\n )\n }\n\n on<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void): void {\n this.#emitter.on(eventName, handler as any)\n }\n\n onOnce<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArgs: TEvents[TEventName]) => void): void {\n const wrapper = (...args: TEvents[TEventName]) => {\n this.off(eventName, wrapper)\n handler(...args)\n }\n this.on(eventName, wrapper)\n }\n\n off<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void): void {\n this.#emitter.off(eventName, handler as any)\n }\n removeAll(): void {\n this.#emitter.removeAllListeners()\n }\n}\n","import type * as KubbFile from './KubbFile.ts'\nimport pLimit from 'p-limit'\n\nimport type { Parser } from './parsers/types.ts'\nimport { defaultParser } from './parsers/defaultParser.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\nimport type { FabricEvents, FabricMode } from './Fabric.ts'\n\nexport type ProcessFilesProps = {\n parsers?: Set<Parser>\n extension?: Record<KubbFile.Extname, KubbFile.Extname | ''>\n dryRun?: boolean\n /**\n * @default 'sequential'\n */\n mode?: FabricMode\n}\n\ntype GetParseOptions = {\n parsers?: Set<Parser>\n extension?: Record<KubbFile.Extname, KubbFile.Extname | ''>\n}\n\ntype Options = {\n events?: AsyncEventEmitter<FabricEvents>\n}\n\nexport class FileProcessor {\n #limit = pLimit(100)\n events: AsyncEventEmitter<FabricEvents>\n\n constructor({ events = new AsyncEventEmitter<FabricEvents>() }: Options = {}) {\n this.events = events\n\n return this\n }\n\n async parse(file: KubbFile.ResolvedFile, { parsers, extension }: GetParseOptions = {}): Promise<string> {\n const parseExtName = extension?.[file.extname] || undefined\n\n if (!parsers) {\n console.warn('No parsers provided, using default parser. If you want to use a specific parser, please provide it in the options.')\n\n return defaultParser.parse(file, { extname: parseExtName })\n }\n\n if (!file.extname) {\n return defaultParser.parse(file, { extname: parseExtName })\n }\n\n let parser: Parser | undefined\n for (const item of parsers) {\n if (item.extNames?.includes(file.extname)) {\n parser = item\n break\n }\n }\n\n if (!parser) {\n return defaultParser.parse(file, { extname: parseExtName })\n }\n\n return parser.parse(file, { extname: parseExtName })\n }\n\n async run(\n files: Array<KubbFile.ResolvedFile>,\n { parsers, mode = 'sequential', dryRun, extension }: ProcessFilesProps = {},\n ): Promise<KubbFile.ResolvedFile[]> {\n await this.events.emit('process:start', { files })\n\n let processed = 0\n const total = files.length\n\n const processOne = async (resolvedFile: KubbFile.ResolvedFile, index: number) => {\n const percentage = (processed / total) * 100\n\n await this.events.emit('file:start', { file: resolvedFile, index, total })\n\n const source = dryRun ? undefined : await this.parse(resolvedFile, { extension, parsers })\n\n await this.events.emit('process:progress', {\n file: resolvedFile,\n source,\n processed,\n percentage,\n total,\n })\n\n processed++\n\n await this.events.emit('file:end', { file: resolvedFile, index, total })\n }\n\n if (mode === 'sequential') {\n async function* asyncFiles() {\n for (let index = 0; index < files.length; index++) {\n yield [files[index], index] as const\n }\n }\n\n for await (const [file, index] of asyncFiles()) {\n if (file) {\n await processOne(file, index)\n }\n }\n } else {\n const promises = files.map((resolvedFile, index) => this.#limit(() => processOne(resolvedFile, index)))\n await Promise.all(promises)\n }\n\n await this.events.emit('process:end', { files })\n\n return files\n }\n}\n","import type * as KubbFile from './KubbFile.ts'\nimport { Cache } from './utils/Cache.ts'\nimport { trimExtName } from './utils/trimExtName.ts'\nimport { orderBy } from 'natural-orderby'\nimport { createFile } from './createFile.ts'\nimport { FileProcessor, type ProcessFilesProps } from './FileProcessor.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\nimport type { FabricEvents } from './Fabric.ts'\n\nfunction mergeFile<TMeta extends object = object>(a: KubbFile.File<TMeta>, b: KubbFile.File<TMeta>): KubbFile.File<TMeta> {\n return {\n ...a,\n sources: [...(a.sources || []), ...(b.sources || [])],\n imports: [...(a.imports || []), ...(b.imports || [])],\n exports: [...(a.exports || []), ...(b.exports || [])],\n }\n}\n\ntype Options = {\n events?: AsyncEventEmitter<FabricEvents>\n}\n\nexport class FileManager {\n #cache = new Cache<KubbFile.ResolvedFile>()\n events: AsyncEventEmitter<FabricEvents>\n processor: FileProcessor\n\n constructor({ events = new AsyncEventEmitter<FabricEvents>() }: Options = {}) {\n this.processor = new FileProcessor({ events })\n\n this.events = events\n return this\n }\n\n async add(...files: Array<KubbFile.File>) {\n const resolvedFiles: Array<KubbFile.ResolvedFile> = []\n\n const mergedFiles = new Map<string, KubbFile.File>()\n\n files.forEach((file) => {\n const existing = mergedFiles.get(file.path)\n if (existing) {\n mergedFiles.set(file.path, mergeFile(existing, file))\n } else {\n mergedFiles.set(file.path, file)\n }\n })\n\n for (const file of mergedFiles.values()) {\n const existing = this.#cache.get(file.path)\n\n const merged = existing ? mergeFile(existing, file) : file\n const resolvedFile = createFile(merged)\n\n this.#cache.set(resolvedFile.path, resolvedFile)\n this.flush()\n\n resolvedFiles.push(resolvedFile)\n }\n\n await this.events.emit('file:add', { files: resolvedFiles })\n\n return resolvedFiles\n }\n\n flush() {\n this.#cache.flush()\n }\n\n getByPath(path: KubbFile.Path): KubbFile.ResolvedFile | null {\n return this.#cache.get(path)\n }\n\n deleteByPath(path: KubbFile.Path): void {\n this.#cache.delete(path)\n }\n\n clear(): void {\n this.#cache.clear()\n }\n\n get files(): Array<KubbFile.ResolvedFile> {\n const cachedKeys = this.#cache.keys()\n\n // order by path length and if file is a barrel file\n const keys = orderBy(cachedKeys, [(v) => v.length, (v) => trimExtName(v).endsWith('index')])\n\n const files = keys.map((key) => this.#cache.get(key))\n\n return files.filter(Boolean)\n }\n\n //TODO add test and check if write of FileManager contains the newly added file\n async write(options: ProcessFilesProps): Promise<KubbFile.ResolvedFile[]> {\n await this.events.emit('write:start', { files: this.files })\n\n const resolvedFiles = await this.processor.run(this.files, options)\n\n this.clear()\n\n await this.events.emit('write:end', { files: resolvedFiles })\n\n return resolvedFiles\n }\n}\n","import { FileManager } from './FileManager.ts'\nimport { isFunction } from 'remeda'\nimport type { Plugin } from './plugins/types.ts'\nimport type { Parser } from './parsers/types.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\nimport type { FabricConfig, FabricContext, FabricEvents, FabricOptions } from './Fabric.ts'\n\nimport type { Fabric } from './Fabric.ts'\n\ntype RootRenderFunction<TOptions extends FabricOptions> = (fabric: Fabric<TOptions>) => void | Promise<void>\n\nexport type DefineFabric<TOptions extends FabricOptions> = (config?: FabricConfig<TOptions>) => Fabric\n\nexport function defineFabric<TOptions extends FabricOptions>(instance?: RootRenderFunction<TOptions>): DefineFabric<TOptions> {\n function creator(config?: FabricConfig<TOptions>): Fabric {\n const events = new AsyncEventEmitter<FabricEvents>()\n const installedPlugins = new Set<Plugin<any>>()\n const installedParsers = new Set<Parser<any>>()\n const fileManager = new FileManager({ events })\n const context = {\n events,\n config,\n fileManager,\n installedPlugins,\n installedParsers,\n } as FabricContext<TOptions>\n\n const fabric = {\n context,\n get files() {\n return fileManager.files\n },\n async addFile(...newFiles) {\n await fileManager.add(...newFiles)\n },\n async use(pluginOrParser, ...options) {\n const args = options\n\n if (pluginOrParser.type === 'plugin') {\n if (installedPlugins.has(pluginOrParser)) {\n console.warn(`Plugin ${pluginOrParser.name} has already been applied to target fabric.`)\n } else {\n installedPlugins.add(pluginOrParser)\n }\n\n if (pluginOrParser.inject && isFunction(pluginOrParser.inject)) {\n const injecter = pluginOrParser.inject\n\n const extraApp = (injecter as any)(fabric, ...args)\n Object.assign(fabric, extraApp)\n }\n }\n if (pluginOrParser.type === 'parser') {\n if (installedParsers.has(pluginOrParser)) {\n console.warn(`Parser ${pluginOrParser.name} has already been applied to target fabric.`)\n } else {\n installedParsers.add(pluginOrParser)\n }\n }\n\n if (pluginOrParser && isFunction(pluginOrParser.install)) {\n const installer = pluginOrParser.install\n\n await (installer as any)(fabric, ...args)\n }\n\n return fabric\n },\n } as Fabric<TOptions>\n\n if (instance) {\n instance(fabric)\n }\n\n return fabric\n }\n\n return creator\n}\n","import { defineFabric } from './defineFabric.ts'\n\nexport const createFabric = defineFabric()\n"],"x_google_ignoreList":[1],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import "../Fabric-CCPgegwe.cjs";
2
- import { i as typescriptParser, n as createImport, r as print, t as createExport } from "../typescriptParser-CCbr9PD6.cjs";
1
+ import "../Fabric-BfnUdEpq.cjs";
2
+ import { i as typescriptParser, n as createImport, r as print, t as createExport } from "../typescriptParser-Dz9T1BQ1.cjs";
3
3
  export { createExport, createImport, print, typescriptParser };
@@ -1,3 +1,3 @@
1
- import "../Fabric-Cu_YHe4S.js";
2
- import { i as typescriptParser, n as createImport, r as print, t as createExport } from "../typescriptParser-DHu674Vq.js";
1
+ import "../Fabric-CxMkO4Rt.js";
2
+ import { i as typescriptParser, n as createImport, r as print, t as createExport } from "../typescriptParser-DypTa1AN.js";
3
3
  export { createExport, createImport, print, typescriptParser };
@@ -1,5 +1,5 @@
1
- import { c as UserParser, s as Parser } from "./Fabric-CCPgegwe.cjs";
2
- import { i as typescriptParser } from "./typescriptParser-CCbr9PD6.cjs";
1
+ import { c as Parser, l as UserParser } from "./Fabric-BfnUdEpq.cjs";
2
+ import { i as typescriptParser } from "./typescriptParser-Dz9T1BQ1.cjs";
3
3
 
4
4
  //#region src/parsers/createParser.d.ts
5
5
  declare function createParser<TOptions = unknown, TMeta extends object = any>(parser: UserParser<TOptions, TMeta>): Parser<TOptions, TMeta>;
package/dist/parsers.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { c as UserParser, s as Parser } from "./Fabric-Cu_YHe4S.js";
2
- import { i as typescriptParser } from "./typescriptParser-DHu674Vq.js";
1
+ import { c as Parser, l as UserParser } from "./Fabric-CxMkO4Rt.js";
2
+ import { i as typescriptParser } from "./typescriptParser-DypTa1AN.js";
3
3
 
4
4
  //#region src/parsers/createParser.d.ts
5
5
  declare function createParser<TOptions = unknown, TMeta extends object = any>(parser: UserParser<TOptions, TMeta>): Parser<TOptions, TMeta>;
package/dist/plugins.cjs CHANGED
@@ -61,9 +61,9 @@ const fsPlugin = createPlugin({
61
61
  },
62
62
  inject(app, { dryRun } = {}) {
63
63
  return { async write(options = { extension: { ".ts": ".ts" } }) {
64
- var _app$context$options;
64
+ var _app$context$config;
65
65
  await app.context.fileManager.write({
66
- mode: (_app$context$options = app.context.options) === null || _app$context$options === void 0 ? void 0 : _app$context$options.mode,
66
+ mode: (_app$context$config = app.context.config) === null || _app$context$config === void 0 || (_app$context$config = _app$context$config.options) === null || _app$context$config === void 0 ? void 0 : _app$context$config.mode,
67
67
  extension: options.extension,
68
68
  dryRun,
69
69
  parsers: app.context.installedParsers
@@ -252,7 +252,7 @@ const barrelPlugin = createPlugin({
252
252
  inject(app, options) {
253
253
  if (!options) throw new Error("Barrel plugin requires options.root and options.mode");
254
254
  return { async writeEntry({ root, mode }) {
255
- var _app$context$options;
255
+ var _app$context$config;
256
256
  if (!mode || mode === "propagate") return;
257
257
  const rootPath = node_path.default.resolve(root, "index.ts");
258
258
  const entryFile = require_defineProperty.createFile({
@@ -276,7 +276,7 @@ const barrelPlugin = createPlugin({
276
276
  });
277
277
  await app.context.fileManager.add(entryFile);
278
278
  await app.context.fileManager.write({
279
- mode: (_app$context$options = app.context.options) === null || _app$context$options === void 0 ? void 0 : _app$context$options.mode,
279
+ mode: (_app$context$config = app.context.config) === null || _app$context$config === void 0 || (_app$context$config = _app$context$config.options) === null || _app$context$config === void 0 ? void 0 : _app$context$config.mode,
280
280
  dryRun: options.dryRun,
281
281
  parsers: app.context.installedParsers
282
282
  });
@@ -1 +1 @@
1
- {"version":3,"file":"plugins.cjs","names":["path","fs","stack: Array<TreeNode<TData>>","result: Array<TreeNode<TData>>","nodes: Array<{ id: string; label: string }>","edges: Array<{ from: string; to: string }>","next: TreeNode<BarrelData> | undefined","path","createFile","getRelativePath","SingleBar","Presets","process","path","http","createFile","path"],"sources":["../src/plugins/createPlugin.ts","../src/plugins/fsPlugin.ts","../src/utils/TreeNode.ts","../src/plugins/barrelPlugin.ts","../src/plugins/progressPlugin.ts","../src/utils/open.ts","../src/plugins/graphPlugin.ts"],"sourcesContent":["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","import { createPlugin } from './createPlugin.ts'\nimport fs from 'fs-extra'\nimport { resolve } from 'node:path'\nimport type * as KubbFile from '../KubbFile.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\n// biome-ignore lint/suspicious/noTsIgnore: production ready\n// @ts-ignore\ndeclare module '@kubb/fabric-core' {\n interface Fabric {\n write(options?: WriteOptions): Promise<void>\n }\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(app, options = {}) {\n if (options.clean) {\n fs.removeSync(options.clean.path)\n }\n\n app.context.events.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(app, { dryRun } = {}) {\n return {\n async write(\n options = {\n extension: { '.ts': '.ts' },\n },\n ) {\n await app.context.fileManager.write({\n mode: app.context.options?.mode,\n extension: options.extension,\n dryRun,\n parsers: app.context.installedParsers,\n })\n },\n }\n },\n})\n","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 #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 this.#cachedLeaves = undefined // invalidate cached leaves\n return child\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 stack: Array<TreeNode<TData>> = [...this.children]\n const result: Array<TreeNode<TData>> = []\n\n for (const node of stack) {\n if (node.children.length) {\n for (const child of node.children) stack.push(child)\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 (const node of stack) {\n callback(node)\n if (node.children.length) {\n for (const child of node.children) stack.push(child)\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 root.forEach((node) => {\n nodes.push({\n id: node.data.path,\n label: node.data.name,\n })\n\n for (const child of node.children) {\n edges.push({\n from: node.data.path,\n to: child.data.path,\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 filteredFiles = files.filter((file) => {\n const filePath = normalizePath(file.path)\n\n return !filePath.endsWith('.json') && (!rootFolder || filePath.startsWith(rootPrefix))\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 relPath = normalizePath(file.path).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: TreeNode<BarrelData> | undefined\n for (const child of current.children) {\n if ((child.data as BarrelData).name === part) {\n next = child\n break\n }\n }\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","/** biome-ignore-all lint/suspicious/useIterableCallbackReturn: not needed */\n\nimport { createPlugin } from './createPlugin.ts'\nimport type * as KubbFile from '../KubbFile.ts'\nimport { TreeNode } from '../utils/TreeNode.ts'\nimport path from 'node:path'\nimport { getRelativePath } from '../utils/getRelativePath.ts'\nimport { createFile } from '../createFile.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 writeEntry(options: WriteEntryOptions): Promise<void>\n}\n\n// biome-ignore lint/suspicious/noTsIgnore: production ready\n// @ts-ignore\ndeclare module '@kubb/fabric-core' {\n interface Fabric {\n writeEntry(options: WriteEntryOptions): Promise<void>\n }\n}\n\ndeclare global {\n namespace Kubb {\n interface Fabric {\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 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 // Collect all leaves under the current directory node\n node.leaves.forEach((leaf) => {\n const file = leaf.data.file\n if (!file) {\n return\n }\n\n const sources = file.sources || []\n sources.forEach((source) => {\n if (!file.path || !source.isIndexable || !source.name) {\n return\n }\n\n const key = `${source.name}|${source.isTypeOnly ? '1' : '0'}`\n if (seen.has(key)) {\n return\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(app, 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 app.context.events.on('write:start', async ({ files }) => {\n const root = options.root\n const barrelFiles = getBarrelFiles({ files, root, mode: options.mode })\n\n await app.context.fileManager.add(...barrelFiles)\n })\n },\n inject(app, 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 = app.files.filter((file) => {\n return file.sources.some((source) => source.isIndexable)\n })\n\n const entryFile = createFile({\n path: rootPath,\n baseName: 'index.ts',\n exports: barrelFiles\n .flatMap((file) => {\n const containsOnlyTypes = file.sources.every((source) => source.isTypeOnly)\n\n return file.sources\n ?.map((source) => {\n if (!file.path || !source.isIndexable) {\n return undefined\n }\n\n return {\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 .filter(Boolean)\n })\n .filter(Boolean),\n sources: [],\n })\n\n await app.context.fileManager.add(entryFile)\n\n await app.context.fileManager.write({\n mode: app.context.options?.mode,\n dryRun: options.dryRun,\n parsers: app.context.installedParsers,\n })\n },\n }\n },\n})\n","import { Presets, SingleBar } from 'cli-progress'\nimport { createPlugin } from './createPlugin.ts'\nimport { relative } from 'node:path'\nimport process from 'node:process'\n\nexport const progressPlugin = createPlugin({\n name: 'progress',\n install(app) {\n const progressBar = 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\n app.context.events.on('process:start', async ({ files }) => {\n progressBar.start(files.length, 0, { message: 'Starting...' })\n })\n\n app.context.events.on('process:progress', async ({ file }) => {\n const message = `Writing ${relative(process.cwd(), file.path)}`\n progressBar.increment(1, { message })\n })\n\n app.context.events.on('process:end', async ({ files }) => {\n progressBar.update(files.length, { message: 'Done ✅' })\n progressBar.stop()\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 { createPlugin } from './createPlugin.ts'\nimport type * as KubbFile from '../KubbFile.ts'\nimport { type Graph, TreeNode } from '../utils/TreeNode.ts'\nimport path from 'node:path'\nimport http from 'node:http'\nimport type { AddressInfo } from 'node:net'\nimport handler from 'serve-handler'\nimport { open } from '../utils/open.ts'\n\nimport { createFile } from '../createFile.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(app, options) {\n if (!options) {\n throw new Error('Graph plugin requires options.root and options.mode')\n }\n\n app.context.events.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 app.context.fileManager.add(graphFile, graphHtmlFile)\n\n if (options.open) {\n await serve(root)\n }\n })\n },\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"plugins.cjs","names":["path","fs","stack: Array<TreeNode<TData>>","result: Array<TreeNode<TData>>","nodes: Array<{ id: string; label: string }>","edges: Array<{ from: string; to: string }>","next: TreeNode<BarrelData> | undefined","path","createFile","getRelativePath","SingleBar","Presets","process","path","http","createFile","path"],"sources":["../src/plugins/createPlugin.ts","../src/plugins/fsPlugin.ts","../src/utils/TreeNode.ts","../src/plugins/barrelPlugin.ts","../src/plugins/progressPlugin.ts","../src/utils/open.ts","../src/plugins/graphPlugin.ts"],"sourcesContent":["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","import { createPlugin } from './createPlugin.ts'\nimport fs from 'fs-extra'\nimport { resolve } from 'node:path'\nimport type * as KubbFile from '../KubbFile.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\n// biome-ignore lint/suspicious/noTsIgnore: production ready\n// @ts-ignore\ndeclare module '@kubb/fabric-core' {\n interface Fabric {\n write(options?: WriteOptions): Promise<void>\n }\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(app, options = {}) {\n if (options.clean) {\n fs.removeSync(options.clean.path)\n }\n\n app.context.events.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(app, { dryRun } = {}) {\n return {\n async write(\n options = {\n extension: { '.ts': '.ts' },\n },\n ) {\n await app.context.fileManager.write({\n mode: app.context.config?.options?.mode,\n extension: options.extension,\n dryRun,\n parsers: app.context.installedParsers,\n })\n },\n }\n },\n})\n","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 #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 this.#cachedLeaves = undefined // invalidate cached leaves\n return child\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 stack: Array<TreeNode<TData>> = [...this.children]\n const result: Array<TreeNode<TData>> = []\n\n for (const node of stack) {\n if (node.children.length) {\n for (const child of node.children) stack.push(child)\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 (const node of stack) {\n callback(node)\n if (node.children.length) {\n for (const child of node.children) stack.push(child)\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 root.forEach((node) => {\n nodes.push({\n id: node.data.path,\n label: node.data.name,\n })\n\n for (const child of node.children) {\n edges.push({\n from: node.data.path,\n to: child.data.path,\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 filteredFiles = files.filter((file) => {\n const filePath = normalizePath(file.path)\n\n return !filePath.endsWith('.json') && (!rootFolder || filePath.startsWith(rootPrefix))\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 relPath = normalizePath(file.path).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: TreeNode<BarrelData> | undefined\n for (const child of current.children) {\n if ((child.data as BarrelData).name === part) {\n next = child\n break\n }\n }\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","/** biome-ignore-all lint/suspicious/useIterableCallbackReturn: not needed */\n\nimport { createPlugin } from './createPlugin.ts'\nimport type * as KubbFile from '../KubbFile.ts'\nimport { TreeNode } from '../utils/TreeNode.ts'\nimport path from 'node:path'\nimport { getRelativePath } from '../utils/getRelativePath.ts'\nimport { createFile } from '../createFile.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 writeEntry(options: WriteEntryOptions): Promise<void>\n}\n\n// biome-ignore lint/suspicious/noTsIgnore: production ready\n// @ts-ignore\ndeclare module '@kubb/fabric-core' {\n interface Fabric {\n writeEntry(options: WriteEntryOptions): Promise<void>\n }\n}\n\ndeclare global {\n namespace Kubb {\n interface Fabric {\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 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 // Collect all leaves under the current directory node\n node.leaves.forEach((leaf) => {\n const file = leaf.data.file\n if (!file) {\n return\n }\n\n const sources = file.sources || []\n sources.forEach((source) => {\n if (!file.path || !source.isIndexable || !source.name) {\n return\n }\n\n const key = `${source.name}|${source.isTypeOnly ? '1' : '0'}`\n if (seen.has(key)) {\n return\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(app, 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 app.context.events.on('write:start', async ({ files }) => {\n const root = options.root\n const barrelFiles = getBarrelFiles({ files, root, mode: options.mode })\n\n await app.context.fileManager.add(...barrelFiles)\n })\n },\n inject(app, 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 = app.files.filter((file) => {\n return file.sources.some((source) => source.isIndexable)\n })\n\n const entryFile = createFile({\n path: rootPath,\n baseName: 'index.ts',\n exports: barrelFiles\n .flatMap((file) => {\n const containsOnlyTypes = file.sources.every((source) => source.isTypeOnly)\n\n return file.sources\n ?.map((source) => {\n if (!file.path || !source.isIndexable) {\n return undefined\n }\n\n return {\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 .filter(Boolean)\n })\n .filter(Boolean),\n sources: [],\n })\n\n await app.context.fileManager.add(entryFile)\n\n await app.context.fileManager.write({\n mode: app.context.config?.options?.mode,\n dryRun: options.dryRun,\n parsers: app.context.installedParsers,\n })\n },\n }\n },\n})\n","import { Presets, SingleBar } from 'cli-progress'\nimport { createPlugin } from './createPlugin.ts'\nimport { relative } from 'node:path'\nimport process from 'node:process'\n\nexport const progressPlugin = createPlugin({\n name: 'progress',\n install(app) {\n const progressBar = 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\n app.context.events.on('process:start', async ({ files }) => {\n progressBar.start(files.length, 0, { message: 'Starting...' })\n })\n\n app.context.events.on('process:progress', async ({ file }) => {\n const message = `Writing ${relative(process.cwd(), file.path)}`\n progressBar.increment(1, { message })\n })\n\n app.context.events.on('process:end', async ({ files }) => {\n progressBar.update(files.length, { message: 'Done ✅' })\n progressBar.stop()\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 { createPlugin } from './createPlugin.ts'\nimport type * as KubbFile from '../KubbFile.ts'\nimport { type Graph, TreeNode } from '../utils/TreeNode.ts'\nimport path from 'node:path'\nimport http from 'node:http'\nimport type { AddressInfo } from 'node:net'\nimport handler from 'serve-handler'\nimport { open } from '../utils/open.ts'\n\nimport { createFile } from '../createFile.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(app, options) {\n if (!options) {\n throw new Error('Graph plugin requires options.root and options.mode')\n }\n\n app.context.events.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 app.context.fileManager.add(graphFile, graphHtmlFile)\n\n if (options.open) {\n await serve(root)\n }\n })\n },\n})\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { d as Extname, l as Plugin, u as UserPlugin } from "./Fabric-CCPgegwe.cjs";
1
+ import { d as UserPlugin, f as Extname, u as Plugin } from "./Fabric-BfnUdEpq.cjs";
2
2
 
3
3
  //#region src/plugins/createPlugin.d.ts
4
4
  declare function createPlugin<Options$3 = unknown, TAppExtension extends Record<string, any> = {}>(plugin: UserPlugin<Options$3, TAppExtension>): Plugin<Options$3, TAppExtension>;
package/dist/plugins.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { d as Extname, l as Plugin, u as UserPlugin } from "./Fabric-Cu_YHe4S.js";
1
+ import { d as UserPlugin, f as Extname, u as Plugin } from "./Fabric-CxMkO4Rt.js";
2
2
 
3
3
  //#region src/plugins/createPlugin.d.ts
4
4
  declare function createPlugin<Options$3 = unknown, TAppExtension extends Record<string, any> = {}>(plugin: UserPlugin<Options$3, TAppExtension>): Plugin<Options$3, TAppExtension>;
package/dist/plugins.js CHANGED
@@ -54,9 +54,9 @@ const fsPlugin = createPlugin({
54
54
  },
55
55
  inject(app, { dryRun } = {}) {
56
56
  return { async write(options = { extension: { ".ts": ".ts" } }) {
57
- var _app$context$options;
57
+ var _app$context$config;
58
58
  await app.context.fileManager.write({
59
- mode: (_app$context$options = app.context.options) === null || _app$context$options === void 0 ? void 0 : _app$context$options.mode,
59
+ mode: (_app$context$config = app.context.config) === null || _app$context$config === void 0 || (_app$context$config = _app$context$config.options) === null || _app$context$config === void 0 ? void 0 : _app$context$config.mode,
60
60
  extension: options.extension,
61
61
  dryRun,
62
62
  parsers: app.context.installedParsers
@@ -245,7 +245,7 @@ const barrelPlugin = createPlugin({
245
245
  inject(app, options) {
246
246
  if (!options) throw new Error("Barrel plugin requires options.root and options.mode");
247
247
  return { async writeEntry({ root, mode }) {
248
- var _app$context$options;
248
+ var _app$context$config;
249
249
  if (!mode || mode === "propagate") return;
250
250
  const rootPath = path.resolve(root, "index.ts");
251
251
  const entryFile = createFile({
@@ -269,7 +269,7 @@ const barrelPlugin = createPlugin({
269
269
  });
270
270
  await app.context.fileManager.add(entryFile);
271
271
  await app.context.fileManager.write({
272
- mode: (_app$context$options = app.context.options) === null || _app$context$options === void 0 ? void 0 : _app$context$options.mode,
272
+ mode: (_app$context$config = app.context.config) === null || _app$context$config === void 0 || (_app$context$config = _app$context$config.options) === null || _app$context$config === void 0 ? void 0 : _app$context$config.mode,
273
273
  dryRun: options.dryRun,
274
274
  parsers: app.context.installedParsers
275
275
  });
@@ -1 +1 @@
1
- {"version":3,"file":"plugins.js","names":["path","stack: Array<TreeNode<TData>>","result: Array<TreeNode<TData>>","nodes: Array<{ id: string; label: string }>","edges: Array<{ from: string; to: string }>","next: TreeNode<BarrelData> | undefined","process","path"],"sources":["../src/plugins/createPlugin.ts","../src/plugins/fsPlugin.ts","../src/utils/TreeNode.ts","../src/plugins/barrelPlugin.ts","../src/plugins/progressPlugin.ts","../src/utils/open.ts","../src/plugins/graphPlugin.ts"],"sourcesContent":["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","import { createPlugin } from './createPlugin.ts'\nimport fs from 'fs-extra'\nimport { resolve } from 'node:path'\nimport type * as KubbFile from '../KubbFile.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\n// biome-ignore lint/suspicious/noTsIgnore: production ready\n// @ts-ignore\ndeclare module '@kubb/fabric-core' {\n interface Fabric {\n write(options?: WriteOptions): Promise<void>\n }\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(app, options = {}) {\n if (options.clean) {\n fs.removeSync(options.clean.path)\n }\n\n app.context.events.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(app, { dryRun } = {}) {\n return {\n async write(\n options = {\n extension: { '.ts': '.ts' },\n },\n ) {\n await app.context.fileManager.write({\n mode: app.context.options?.mode,\n extension: options.extension,\n dryRun,\n parsers: app.context.installedParsers,\n })\n },\n }\n },\n})\n","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 #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 this.#cachedLeaves = undefined // invalidate cached leaves\n return child\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 stack: Array<TreeNode<TData>> = [...this.children]\n const result: Array<TreeNode<TData>> = []\n\n for (const node of stack) {\n if (node.children.length) {\n for (const child of node.children) stack.push(child)\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 (const node of stack) {\n callback(node)\n if (node.children.length) {\n for (const child of node.children) stack.push(child)\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 root.forEach((node) => {\n nodes.push({\n id: node.data.path,\n label: node.data.name,\n })\n\n for (const child of node.children) {\n edges.push({\n from: node.data.path,\n to: child.data.path,\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 filteredFiles = files.filter((file) => {\n const filePath = normalizePath(file.path)\n\n return !filePath.endsWith('.json') && (!rootFolder || filePath.startsWith(rootPrefix))\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 relPath = normalizePath(file.path).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: TreeNode<BarrelData> | undefined\n for (const child of current.children) {\n if ((child.data as BarrelData).name === part) {\n next = child\n break\n }\n }\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","/** biome-ignore-all lint/suspicious/useIterableCallbackReturn: not needed */\n\nimport { createPlugin } from './createPlugin.ts'\nimport type * as KubbFile from '../KubbFile.ts'\nimport { TreeNode } from '../utils/TreeNode.ts'\nimport path from 'node:path'\nimport { getRelativePath } from '../utils/getRelativePath.ts'\nimport { createFile } from '../createFile.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 writeEntry(options: WriteEntryOptions): Promise<void>\n}\n\n// biome-ignore lint/suspicious/noTsIgnore: production ready\n// @ts-ignore\ndeclare module '@kubb/fabric-core' {\n interface Fabric {\n writeEntry(options: WriteEntryOptions): Promise<void>\n }\n}\n\ndeclare global {\n namespace Kubb {\n interface Fabric {\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 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 // Collect all leaves under the current directory node\n node.leaves.forEach((leaf) => {\n const file = leaf.data.file\n if (!file) {\n return\n }\n\n const sources = file.sources || []\n sources.forEach((source) => {\n if (!file.path || !source.isIndexable || !source.name) {\n return\n }\n\n const key = `${source.name}|${source.isTypeOnly ? '1' : '0'}`\n if (seen.has(key)) {\n return\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(app, 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 app.context.events.on('write:start', async ({ files }) => {\n const root = options.root\n const barrelFiles = getBarrelFiles({ files, root, mode: options.mode })\n\n await app.context.fileManager.add(...barrelFiles)\n })\n },\n inject(app, 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 = app.files.filter((file) => {\n return file.sources.some((source) => source.isIndexable)\n })\n\n const entryFile = createFile({\n path: rootPath,\n baseName: 'index.ts',\n exports: barrelFiles\n .flatMap((file) => {\n const containsOnlyTypes = file.sources.every((source) => source.isTypeOnly)\n\n return file.sources\n ?.map((source) => {\n if (!file.path || !source.isIndexable) {\n return undefined\n }\n\n return {\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 .filter(Boolean)\n })\n .filter(Boolean),\n sources: [],\n })\n\n await app.context.fileManager.add(entryFile)\n\n await app.context.fileManager.write({\n mode: app.context.options?.mode,\n dryRun: options.dryRun,\n parsers: app.context.installedParsers,\n })\n },\n }\n },\n})\n","import { Presets, SingleBar } from 'cli-progress'\nimport { createPlugin } from './createPlugin.ts'\nimport { relative } from 'node:path'\nimport process from 'node:process'\n\nexport const progressPlugin = createPlugin({\n name: 'progress',\n install(app) {\n const progressBar = 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\n app.context.events.on('process:start', async ({ files }) => {\n progressBar.start(files.length, 0, { message: 'Starting...' })\n })\n\n app.context.events.on('process:progress', async ({ file }) => {\n const message = `Writing ${relative(process.cwd(), file.path)}`\n progressBar.increment(1, { message })\n })\n\n app.context.events.on('process:end', async ({ files }) => {\n progressBar.update(files.length, { message: 'Done ✅' })\n progressBar.stop()\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 { createPlugin } from './createPlugin.ts'\nimport type * as KubbFile from '../KubbFile.ts'\nimport { type Graph, TreeNode } from '../utils/TreeNode.ts'\nimport path from 'node:path'\nimport http from 'node:http'\nimport type { AddressInfo } from 'node:net'\nimport handler from 'serve-handler'\nimport { open } from '../utils/open.ts'\n\nimport { createFile } from '../createFile.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(app, options) {\n if (!options) {\n throw new Error('Graph plugin requires options.root and options.mode')\n }\n\n app.context.events.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 app.context.fileManager.add(graphFile, graphHtmlFile)\n\n if (options.open) {\n await serve(root)\n }\n })\n },\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"plugins.js","names":["path","stack: Array<TreeNode<TData>>","result: Array<TreeNode<TData>>","nodes: Array<{ id: string; label: string }>","edges: Array<{ from: string; to: string }>","next: TreeNode<BarrelData> | undefined","process","path"],"sources":["../src/plugins/createPlugin.ts","../src/plugins/fsPlugin.ts","../src/utils/TreeNode.ts","../src/plugins/barrelPlugin.ts","../src/plugins/progressPlugin.ts","../src/utils/open.ts","../src/plugins/graphPlugin.ts"],"sourcesContent":["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","import { createPlugin } from './createPlugin.ts'\nimport fs from 'fs-extra'\nimport { resolve } from 'node:path'\nimport type * as KubbFile from '../KubbFile.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\n// biome-ignore lint/suspicious/noTsIgnore: production ready\n// @ts-ignore\ndeclare module '@kubb/fabric-core' {\n interface Fabric {\n write(options?: WriteOptions): Promise<void>\n }\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(app, options = {}) {\n if (options.clean) {\n fs.removeSync(options.clean.path)\n }\n\n app.context.events.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(app, { dryRun } = {}) {\n return {\n async write(\n options = {\n extension: { '.ts': '.ts' },\n },\n ) {\n await app.context.fileManager.write({\n mode: app.context.config?.options?.mode,\n extension: options.extension,\n dryRun,\n parsers: app.context.installedParsers,\n })\n },\n }\n },\n})\n","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 #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 this.#cachedLeaves = undefined // invalidate cached leaves\n return child\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 stack: Array<TreeNode<TData>> = [...this.children]\n const result: Array<TreeNode<TData>> = []\n\n for (const node of stack) {\n if (node.children.length) {\n for (const child of node.children) stack.push(child)\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 (const node of stack) {\n callback(node)\n if (node.children.length) {\n for (const child of node.children) stack.push(child)\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 root.forEach((node) => {\n nodes.push({\n id: node.data.path,\n label: node.data.name,\n })\n\n for (const child of node.children) {\n edges.push({\n from: node.data.path,\n to: child.data.path,\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 filteredFiles = files.filter((file) => {\n const filePath = normalizePath(file.path)\n\n return !filePath.endsWith('.json') && (!rootFolder || filePath.startsWith(rootPrefix))\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 relPath = normalizePath(file.path).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: TreeNode<BarrelData> | undefined\n for (const child of current.children) {\n if ((child.data as BarrelData).name === part) {\n next = child\n break\n }\n }\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","/** biome-ignore-all lint/suspicious/useIterableCallbackReturn: not needed */\n\nimport { createPlugin } from './createPlugin.ts'\nimport type * as KubbFile from '../KubbFile.ts'\nimport { TreeNode } from '../utils/TreeNode.ts'\nimport path from 'node:path'\nimport { getRelativePath } from '../utils/getRelativePath.ts'\nimport { createFile } from '../createFile.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 writeEntry(options: WriteEntryOptions): Promise<void>\n}\n\n// biome-ignore lint/suspicious/noTsIgnore: production ready\n// @ts-ignore\ndeclare module '@kubb/fabric-core' {\n interface Fabric {\n writeEntry(options: WriteEntryOptions): Promise<void>\n }\n}\n\ndeclare global {\n namespace Kubb {\n interface Fabric {\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 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 // Collect all leaves under the current directory node\n node.leaves.forEach((leaf) => {\n const file = leaf.data.file\n if (!file) {\n return\n }\n\n const sources = file.sources || []\n sources.forEach((source) => {\n if (!file.path || !source.isIndexable || !source.name) {\n return\n }\n\n const key = `${source.name}|${source.isTypeOnly ? '1' : '0'}`\n if (seen.has(key)) {\n return\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(app, 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 app.context.events.on('write:start', async ({ files }) => {\n const root = options.root\n const barrelFiles = getBarrelFiles({ files, root, mode: options.mode })\n\n await app.context.fileManager.add(...barrelFiles)\n })\n },\n inject(app, 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 = app.files.filter((file) => {\n return file.sources.some((source) => source.isIndexable)\n })\n\n const entryFile = createFile({\n path: rootPath,\n baseName: 'index.ts',\n exports: barrelFiles\n .flatMap((file) => {\n const containsOnlyTypes = file.sources.every((source) => source.isTypeOnly)\n\n return file.sources\n ?.map((source) => {\n if (!file.path || !source.isIndexable) {\n return undefined\n }\n\n return {\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 .filter(Boolean)\n })\n .filter(Boolean),\n sources: [],\n })\n\n await app.context.fileManager.add(entryFile)\n\n await app.context.fileManager.write({\n mode: app.context.config?.options?.mode,\n dryRun: options.dryRun,\n parsers: app.context.installedParsers,\n })\n },\n }\n },\n})\n","import { Presets, SingleBar } from 'cli-progress'\nimport { createPlugin } from './createPlugin.ts'\nimport { relative } from 'node:path'\nimport process from 'node:process'\n\nexport const progressPlugin = createPlugin({\n name: 'progress',\n install(app) {\n const progressBar = 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\n app.context.events.on('process:start', async ({ files }) => {\n progressBar.start(files.length, 0, { message: 'Starting...' })\n })\n\n app.context.events.on('process:progress', async ({ file }) => {\n const message = `Writing ${relative(process.cwd(), file.path)}`\n progressBar.increment(1, { message })\n })\n\n app.context.events.on('process:end', async ({ files }) => {\n progressBar.update(files.length, { message: 'Done ✅' })\n progressBar.stop()\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 { createPlugin } from './createPlugin.ts'\nimport type * as KubbFile from '../KubbFile.ts'\nimport { type Graph, TreeNode } from '../utils/TreeNode.ts'\nimport path from 'node:path'\nimport http from 'node:http'\nimport type { AddressInfo } from 'node:net'\nimport handler from 'serve-handler'\nimport { open } from '../utils/open.ts'\n\nimport { createFile } from '../createFile.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(app, options) {\n if (!options) {\n throw new Error('Graph plugin requires options.root and options.mode')\n }\n\n app.context.events.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 app.context.fileManager.add(graphFile, graphHtmlFile)\n\n if (options.open) {\n await serve(root)\n }\n })\n },\n})\n"],"mappings":"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"}
package/dist/types.d.cts CHANGED
@@ -1,3 +1,3 @@
1
- import { n as FabricContext, p as KubbFile_d_exports, r as FabricMode } from "./Fabric-CCPgegwe.cjs";
2
- import { r as DefineFabric } from "./index-BUculP1D.cjs";
3
- export { type DefineFabric, type FabricContext, type FabricMode, KubbFile_d_exports as KubbFile };
1
+ import { i as FabricMode, m as KubbFile_d_exports, n as FabricConfig, r as FabricContext } from "./Fabric-BfnUdEpq.cjs";
2
+ import { t as DefineFabric } from "./defineFabric-DApM1nNr.cjs";
3
+ export { type DefineFabric, type FabricConfig, type FabricContext, type FabricMode, KubbFile_d_exports as KubbFile };
package/dist/types.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { n as FabricContext, p as KubbFile_d_exports, r as FabricMode } from "./Fabric-Cu_YHe4S.js";
2
- import { r as DefineFabric } from "./index-CvkyZHXK.js";
3
- export { type DefineFabric, type FabricContext, type FabricMode, KubbFile_d_exports as KubbFile };
1
+ import { i as FabricMode, m as KubbFile_d_exports, n as FabricConfig, r as FabricContext } from "./Fabric-CxMkO4Rt.js";
2
+ import { t as DefineFabric } from "./defineFabric-Nf6eMaz7.js";
3
+ export { type DefineFabric, type FabricConfig, type FabricContext, type FabricMode, KubbFile_d_exports as KubbFile };
@@ -1,4 +1,4 @@
1
- import { s as Parser } from "./Fabric-Cu_YHe4S.js";
1
+ import { c as Parser } from "./Fabric-CxMkO4Rt.js";
2
2
  import ts from "typescript";
3
3
 
4
4
  //#region src/parsers/typescriptParser.d.ts
@@ -47,4 +47,4 @@ declare function createExport({
47
47
  declare const typescriptParser: Parser<[], any>;
48
48
  //#endregion
49
49
  export { typescriptParser as i, createImport as n, print as r, createExport as t };
50
- //# sourceMappingURL=typescriptParser-DHu674Vq.d.ts.map
50
+ //# sourceMappingURL=typescriptParser-DypTa1AN.d.ts.map
@@ -1,4 +1,4 @@
1
- import { s as Parser } from "./Fabric-CCPgegwe.cjs";
1
+ import { c as Parser } from "./Fabric-BfnUdEpq.cjs";
2
2
  import ts from "typescript";
3
3
 
4
4
  //#region src/parsers/typescriptParser.d.ts
@@ -47,4 +47,4 @@ declare function createExport({
47
47
  declare const typescriptParser: Parser<[], any>;
48
48
  //#endregion
49
49
  export { typescriptParser as i, createImport as n, print as r, createExport as t };
50
- //# sourceMappingURL=typescriptParser-CCbr9PD6.d.cts.map
50
+ //# sourceMappingURL=typescriptParser-Dz9T1BQ1.d.cts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/fabric-core",
3
- "version": "0.2.11",
3
+ "version": "0.2.13",
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
@@ -74,7 +74,7 @@ export type FabricEvents = {
74
74
  }
75
75
 
76
76
  export type FabricContext<TOptions extends FabricOptions> = {
77
- options?: TOptions
77
+ config?: FabricConfig<TOptions>
78
78
  events: AsyncEventEmitter<FabricEvents>
79
79
  fileManager: FileManager
80
80
  installedPlugins: Set<Plugin>
@@ -85,6 +85,10 @@ export type FabricMode = 'sequential' | 'parallel'
85
85
 
86
86
  type AllOptional<T> = {} extends T ? true : false
87
87
 
88
+ export type FabricConfig<TOptions extends FabricOptions> = {
89
+ options: TOptions
90
+ }
91
+
88
92
  export type Install<TOptions = unknown> = TOptions extends any[]
89
93
  ? (app: Fabric, ...options: TOptions) => void | Promise<void>
90
94
  : AllOptional<TOptions> extends true
@@ -3,23 +3,23 @@ import { isFunction } from 'remeda'
3
3
  import type { Plugin } from './plugins/types.ts'
4
4
  import type { Parser } from './parsers/types.ts'
5
5
  import { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'
6
- import type { FabricContext, FabricEvents, FabricOptions } from './Fabric.ts'
6
+ import type { FabricConfig, FabricContext, FabricEvents, FabricOptions } from './Fabric.ts'
7
7
 
8
- import type { Fabric } from './index.ts'
8
+ import type { Fabric } from './Fabric.ts'
9
9
 
10
10
  type RootRenderFunction<TOptions extends FabricOptions> = (fabric: Fabric<TOptions>) => void | Promise<void>
11
11
 
12
- export type DefineFabric<TOptions> = (options?: TOptions) => Fabric
12
+ export type DefineFabric<TOptions extends FabricOptions> = (config?: FabricConfig<TOptions>) => Fabric
13
13
 
14
14
  export function defineFabric<TOptions extends FabricOptions>(instance?: RootRenderFunction<TOptions>): DefineFabric<TOptions> {
15
- function createFabric(options?: TOptions): Fabric {
15
+ function creator(config?: FabricConfig<TOptions>): Fabric {
16
16
  const events = new AsyncEventEmitter<FabricEvents>()
17
17
  const installedPlugins = new Set<Plugin<any>>()
18
18
  const installedParsers = new Set<Parser<any>>()
19
19
  const fileManager = new FileManager({ events })
20
20
  const context = {
21
21
  events,
22
- options,
22
+ config,
23
23
  fileManager,
24
24
  installedPlugins,
25
25
  installedParsers,
@@ -75,5 +75,5 @@ export function defineFabric<TOptions extends FabricOptions>(instance?: RootRend
75
75
  return fabric
76
76
  }
77
77
 
78
- return createFabric
78
+ return creator
79
79
  }
@@ -196,7 +196,7 @@ export const barrelPlugin = createPlugin<Options, ExtendOptions>({
196
196
  await app.context.fileManager.add(entryFile)
197
197
 
198
198
  await app.context.fileManager.write({
199
- mode: app.context.options?.mode,
199
+ mode: app.context.config?.options?.mode,
200
200
  dryRun: options.dryRun,
201
201
  parsers: app.context.installedParsers,
202
202
  })
@@ -115,7 +115,7 @@ export const fsPlugin = createPlugin<Options, ExtendOptions>({
115
115
  },
116
116
  ) {
117
117
  await app.context.fileManager.write({
118
- mode: app.context.options?.mode,
118
+ mode: app.context.config?.options?.mode,
119
119
  extension: options.extension,
120
120
  dryRun,
121
121
  parsers: app.context.installedParsers,
package/src/types.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export * as KubbFile from './KubbFile.ts'
2
2
  export type { DefineFabric } from './defineFabric.ts'
3
- export type { FabricContext, FabricMode } from './Fabric.ts'
3
+ export type { FabricContext, FabricMode, FabricConfig } from './Fabric.ts'
@@ -1,18 +0,0 @@
1
- import { f as File, i as FabricOptions, m as ResolvedFile, t as Fabric } from "./Fabric-CCPgegwe.cjs";
2
-
3
- //#region src/defineFabric.d.ts
4
- type RootRenderFunction<TOptions extends FabricOptions> = (fabric: Fabric<TOptions>) => void | Promise<void>;
5
- type DefineFabric<TOptions> = (options?: TOptions) => Fabric;
6
- declare function defineFabric<TOptions extends FabricOptions>(instance?: RootRenderFunction<TOptions>): DefineFabric<TOptions>;
7
- //#endregion
8
- //#region src/createFabric.d.ts
9
- declare const createFabric: DefineFabric<FabricOptions>;
10
- //#endregion
11
- //#region src/createFile.d.ts
12
- /**
13
- * Helper to create a file with name and id set
14
- */
15
- declare function createFile<TMeta extends object = object>(file: File<TMeta>): ResolvedFile<TMeta>;
16
- //#endregion
17
- export { defineFabric as i, createFabric as n, DefineFabric as r, createFile as t };
18
- //# sourceMappingURL=index-BUculP1D.d.cts.map
@@ -1,18 +0,0 @@
1
- import { f as File, i as FabricOptions, m as ResolvedFile, t as Fabric } from "./Fabric-Cu_YHe4S.js";
2
-
3
- //#region src/defineFabric.d.ts
4
- type RootRenderFunction<TOptions extends FabricOptions> = (fabric: Fabric<TOptions>) => void | Promise<void>;
5
- type DefineFabric<TOptions> = (options?: TOptions) => Fabric;
6
- declare function defineFabric<TOptions extends FabricOptions>(instance?: RootRenderFunction<TOptions>): DefineFabric<TOptions>;
7
- //#endregion
8
- //#region src/createFabric.d.ts
9
- declare const createFabric: DefineFabric<FabricOptions>;
10
- //#endregion
11
- //#region src/createFile.d.ts
12
- /**
13
- * Helper to create a file with name and id set
14
- */
15
- declare function createFile<TMeta extends object = object>(file: File<TMeta>): ResolvedFile<TMeta>;
16
- //#endregion
17
- export { defineFabric as i, createFabric as n, DefineFabric as r, createFile as t };
18
- //# sourceMappingURL=index-CvkyZHXK.d.ts.map