@kubb/fabric-core 0.5.0 → 0.5.2

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.
@@ -198,6 +198,7 @@ declare class FileManager {
198
198
  events
199
199
  }?: Options);
200
200
  add(...files: Array<File>): Promise<ResolvedFile<object>[]>;
201
+ upsert(...files: Array<File>): Promise<ResolvedFile<object>[]>;
201
202
  flush(): void;
202
203
  getByPath(path: Path): ResolvedFile | null;
203
204
  deleteByPath(path: Path): void;
@@ -360,9 +361,15 @@ interface Fabric<T extends FabricOptions = FabricOptions> extends Kubb.Fabric {
360
361
  * @returns A Fabric instance extended by the plugin (if applicable).
361
362
  */
362
363
  use<TPluginOptions = unknown, TMeta extends object = object, TExtension extends Record<string, any> = {}>(target: Plugin<TPluginOptions, TExtension> | Parser<TPluginOptions, TMeta>, ...options: TPluginOptions extends any[] ? NoInfer<TPluginOptions> : AllOptional<TPluginOptions> extends true ? [NoInfer<TPluginOptions>?] : [NoInfer<TPluginOptions>]): (this & TExtension) | Promise<this & TExtension>;
363
- /** Add one or more files to the Fabric file manager. */
364
+ /**
365
+ * Add one or more files to the Fabric file manager.
366
+ */
364
367
  addFile(...files: File[]): Promise<void>;
368
+ /**
369
+ * Add one or more files to the Fabric file manager and merge the source, imports, exports
370
+ */
371
+ upsertFile(...files: File[]): Promise<void>;
365
372
  }
366
373
  //#endregion
367
374
  export { FabricOptions as a, FileManager as c, UserParser as d, Extname as f, ResolvedFile as h, FabricMode as i, FileProcessor as l, KubbFile_d_exports as m, FabricConfig as n, Plugin as o, File as p, FabricContext as r, UserPlugin as s, Fabric as t, Parser as u };
368
- //# sourceMappingURL=Fabric-CkskSjFr.d.ts.map
375
+ //# sourceMappingURL=Fabric-BzIhBn8t.d.cts.map
@@ -198,6 +198,7 @@ declare class FileManager {
198
198
  events
199
199
  }?: Options);
200
200
  add(...files: Array<File>): Promise<ResolvedFile<object>[]>;
201
+ upsert(...files: Array<File>): Promise<ResolvedFile<object>[]>;
201
202
  flush(): void;
202
203
  getByPath(path: Path): ResolvedFile | null;
203
204
  deleteByPath(path: Path): void;
@@ -360,9 +361,15 @@ interface Fabric<T extends FabricOptions = FabricOptions> extends Kubb.Fabric {
360
361
  * @returns A Fabric instance extended by the plugin (if applicable).
361
362
  */
362
363
  use<TPluginOptions = unknown, TMeta extends object = object, TExtension extends Record<string, any> = {}>(target: Plugin<TPluginOptions, TExtension> | Parser<TPluginOptions, TMeta>, ...options: TPluginOptions extends any[] ? NoInfer<TPluginOptions> : AllOptional<TPluginOptions> extends true ? [NoInfer<TPluginOptions>?] : [NoInfer<TPluginOptions>]): (this & TExtension) | Promise<this & TExtension>;
363
- /** Add one or more files to the Fabric file manager. */
364
+ /**
365
+ * Add one or more files to the Fabric file manager.
366
+ */
364
367
  addFile(...files: File[]): Promise<void>;
368
+ /**
369
+ * Add one or more files to the Fabric file manager and merge the source, imports, exports
370
+ */
371
+ upsertFile(...files: File[]): Promise<void>;
365
372
  }
366
373
  //#endregion
367
374
  export { FabricOptions as a, FileManager as c, UserParser as d, Extname as f, ResolvedFile as h, FabricMode as i, FileProcessor as l, KubbFile_d_exports as m, FabricConfig as n, Plugin as o, File as p, FabricContext as r, UserPlugin as s, Fabric as t, Parser as u };
368
- //# sourceMappingURL=Fabric-BqMP-L92.d.cts.map
375
+ //# sourceMappingURL=Fabric-igvWKffO.d.ts.map
package/dist/index.cjs CHANGED
@@ -187,6 +187,25 @@ var FileManager = class {
187
187
  return this;
188
188
  }
189
189
  async add(...files) {
190
+ const resolvedFiles = [];
191
+ const mergedFiles = /* @__PURE__ */ new Map();
192
+ files.forEach((file) => {
193
+ const existing = mergedFiles.get(file.path);
194
+ if (existing) mergedFiles.set(file.path, mergeFile(existing, file));
195
+ else mergedFiles.set(file.path, file);
196
+ });
197
+ for (let file of mergedFiles.values()) {
198
+ file = require_defineProperty._assertClassBrand(_FileManager_brand, this, _resolveName).call(this, file);
199
+ file = require_defineProperty._assertClassBrand(_FileManager_brand, this, _resolvePath).call(this, file);
200
+ const resolvedFile = require_defineProperty.createFile(file);
201
+ require_defineProperty._classPrivateFieldGet2(_cache, this).set(resolvedFile.path, resolvedFile);
202
+ this.flush();
203
+ resolvedFiles.push(resolvedFile);
204
+ }
205
+ await this.events.emit("file:add", { files: resolvedFiles });
206
+ return resolvedFiles;
207
+ }
208
+ async upsert(...files) {
190
209
  const resolvedFiles = [];
191
210
  const mergedFiles = /* @__PURE__ */ new Map();
192
211
  files.forEach((file) => {
@@ -291,6 +310,9 @@ function defineFabric(init) {
291
310
  async addFile(...files) {
292
311
  await fileManager.add(...files);
293
312
  },
313
+ async upsertFile(...files) {
314
+ await fileManager.upsert(...files);
315
+ },
294
316
  async use(pluginOrParser, ...options) {
295
317
  if (pluginOrParser.type === "plugin") {
296
318
  if (installedPlugins.has(pluginOrParser)) console.warn(`Plugin "${pluginOrParser.name}" already applied.`);
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["e","NodeEventEmitter","errors: Error[]","defaultParser","resolvedFiles: Array<KubbFile.ResolvedFile>","createFile","trimExtName","files: Array<KubbFile.ResolvedFile>","context: FabricContext<T>","fabric: Fabric<T>","isFunction"],"sources":["../../../node_modules/.pnpm/remeda@2.32.0/node_modules/remeda/dist/isFunction-BJjFuZR7.js","../src/utils/AsyncEventEmitter.ts","../src/FileProcessor.ts","../src/utils/Cache.ts","../src/FileManager.ts","../src/defineFabric.ts","../src/createFabric.ts"],"sourcesContent":["const e=e=>typeof e==`function`;export{e as isFunction};\n//# sourceMappingURL=isFunction-BJjFuZR7.js.map","import { EventEmitter as NodeEventEmitter } from 'node:events'\nimport type { FabricMode } from '../Fabric.ts'\n\ntype Options = {\n mode?: FabricMode\n maxListener?: number\n}\n\nexport class AsyncEventEmitter<TEvents extends Record<string, any>> {\n constructor({ maxListener = 100, mode = 'sequential' }: Options = {}) {\n this.#emitter.setMaxListeners(maxListener)\n this.#mode = mode\n }\n\n #emitter = new NodeEventEmitter()\n #mode: FabricMode\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\n }\n\n const errors: Error[] = []\n\n if (this.#mode === 'sequential') {\n // Run listeners one by one, in order\n for (const listener of listeners) {\n try {\n await listener(...eventArgs)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n errors.push(error)\n }\n }\n } else {\n // Run all listeners concurrently\n const promises = listeners.map(async (listener) => {\n try {\n await listener(...eventArgs)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n errors.push(error)\n }\n })\n await Promise.all(promises)\n }\n\n if (errors.length === 1) {\n throw errors[0]\n }\n\n if (errors.length > 1) {\n throw new AggregateError(errors, `Errors in async listeners for \"${eventName}\"`)\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\n removeAll(): void {\n this.#emitter.removeAllListeners()\n }\n}\n","import pLimit from 'p-limit'\nimport type { FabricEvents, FabricMode } from './Fabric.ts'\nimport type * as KubbFile from './KubbFile.ts'\nimport { defaultParser } from './parsers/defaultParser.ts'\nimport type { Parser } from './parsers/types.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\n\nexport type ProcessFilesProps = {\n parsers?: Map<KubbFile.Extname, 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?: Map<KubbFile.Extname, 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 const parser = parsers.get(file.extname)\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 const total = files.length\n let processed = 0\n\n const processOne = async (resolvedFile: KubbFile.ResolvedFile, index: number) => {\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 const currentProcessed = ++processed\n const percentage = (currentProcessed / total) * 100\n\n await this.events.emit('process:progress', {\n file: resolvedFile,\n source,\n processed: currentProcessed,\n percentage,\n total,\n })\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","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","import { orderBy } from 'natural-orderby'\nimport { createFile } from './createFile.ts'\nimport type { FabricEvents } from './Fabric.ts'\nimport { FileProcessor, type ProcessFilesProps } from './FileProcessor.ts'\nimport type * as KubbFile from './KubbFile.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\nimport { Cache } from './utils/Cache.ts'\nimport { trimExtName } from './utils/trimExtName.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 #filesCache: Array<KubbFile.ResolvedFile> | null = null\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 #resolvePath(file: KubbFile.File): KubbFile.File {\n this.events.emit('file:resolve:path', { file })\n\n return file\n }\n\n #resolveName(file: KubbFile.File): KubbFile.File {\n this.events.emit('file:resolve:name', { file })\n\n return file\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 (let file of mergedFiles.values()) {\n const existing = this.#cache.get(file.path)\n\n file = this.#resolveName(file)\n file = this.#resolvePath(file)\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.#filesCache = null\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 this.#filesCache = null\n }\n\n clear(): void {\n this.#cache.clear()\n this.#filesCache = null\n }\n\n get files(): Array<KubbFile.ResolvedFile> {\n if (this.#filesCache) {\n return this.#filesCache\n }\n\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: Array<KubbFile.ResolvedFile> = []\n\n for (const key of keys) {\n const file = this.#cache.get(key)\n if (file) {\n files.push(file)\n }\n }\n\n this.#filesCache = files\n\n return files\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 { isFunction } from 'remeda'\nimport type { Fabric, FabricConfig, FabricContext, FabricEvents, FabricOptions } from './Fabric.ts'\nimport { FileManager } from './FileManager.ts'\nimport type * as KubbFile from './KubbFile.ts'\nimport type { Parser } from './parsers/types.ts'\nimport type { Plugin } from './plugins/types.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\n\n/**\n * Function that initializes the root Fabric instance.\n *\n * Used for setting up plugins, parsers, or performing side effects\n * once the Fabric context is ready.\n */\ntype FabricInitializer<T extends FabricOptions> = (fabric: Fabric<T>) => void | Promise<void>\n\n/**\n * A function returned by {@link defineFabric} that creates a Fabric instance.\n */\nexport type CreateFabric<T extends FabricOptions> = (config?: FabricConfig<T>) => Fabric<T>\n\n/**\n * Defines a new Fabric factory function.\n *\n * @example\n * export const createFabric = defineFabric((fabric) => {\n * fabric.use(myPlugin())\n * })\n */\nexport function defineFabric<T extends FabricOptions>(init?: FabricInitializer<T>): CreateFabric<T> {\n function create(config: FabricConfig<T> = { mode: 'sequential' } as FabricConfig<T>): Fabric<T> {\n const events = new AsyncEventEmitter<FabricEvents>()\n const installedPlugins = new Set<Plugin<any>>()\n const installedParsers = new Map<KubbFile.Extname, Parser<any>>()\n const installedParserNames = new Set<string>()\n const fileManager = new FileManager({ events })\n\n const context: FabricContext<T> = {\n get files() {\n return fileManager.files\n },\n async addFile(...files) {\n await fileManager.add(...files)\n },\n config,\n fileManager,\n installedPlugins,\n installedParsers,\n on: events.on.bind(events),\n off: events.off.bind(events),\n onOnce: events.onOnce.bind(events),\n removeAll: events.removeAll.bind(events),\n emit: events.emit.bind(events),\n } as FabricContext<T>\n\n const fabric: Fabric<T> = {\n context,\n get files() {\n return fileManager.files\n },\n async addFile(...files) {\n await fileManager.add(...files)\n },\n async use(pluginOrParser, ...options) {\n if (pluginOrParser.type === 'plugin') {\n if (installedPlugins.has(pluginOrParser)) {\n console.warn(`Plugin \"${pluginOrParser.name}\" already applied.`)\n } else {\n installedPlugins.add(pluginOrParser)\n }\n\n if (isFunction(pluginOrParser.inject)) {\n const injecter = pluginOrParser.inject\n\n const injected = (injecter as any)(context, ...options)\n Object.assign(fabric, injected)\n }\n }\n\n if (pluginOrParser.type === 'parser') {\n if (installedParserNames.has(pluginOrParser.name)) {\n console.warn(`Parser \"${pluginOrParser.name}\" already applied.`)\n } else {\n installedParserNames.add(pluginOrParser.name)\n }\n\n if (pluginOrParser.extNames) {\n for (const extName of pluginOrParser.extNames) {\n const existing = installedParsers.get(extName)\n if (existing && existing.name !== pluginOrParser.name) {\n console.warn(`Parser \"${pluginOrParser.name}\" is overriding parser \"${existing.name}\" for extension \"${extName}\".`)\n }\n installedParsers.set(extName, pluginOrParser)\n }\n }\n }\n\n if (isFunction(pluginOrParser.install)) {\n const installer = pluginOrParser.install\n\n await (installer as any)(context, ...options)\n }\n\n return fabric\n },\n } as Fabric<T>\n\n if (init) {\n init(fabric)\n }\n\n return fabric\n }\n\n return create\n}\n","import { defineFabric } from './defineFabric.ts'\n\nexport const createFabric = defineFabric()\n"],"x_google_ignoreList":[0],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["e","NodeEventEmitter","errors: Error[]","defaultParser","resolvedFiles: Array<KubbFile.ResolvedFile>","createFile","trimExtName","files: Array<KubbFile.ResolvedFile>","context: FabricContext<T>","fabric: Fabric<T>","isFunction"],"sources":["../../../node_modules/.pnpm/remeda@2.32.0/node_modules/remeda/dist/isFunction-BJjFuZR7.js","../src/utils/AsyncEventEmitter.ts","../src/FileProcessor.ts","../src/utils/Cache.ts","../src/FileManager.ts","../src/defineFabric.ts","../src/createFabric.ts"],"sourcesContent":["const e=e=>typeof e==`function`;export{e as isFunction};\n//# sourceMappingURL=isFunction-BJjFuZR7.js.map","import { EventEmitter as NodeEventEmitter } from 'node:events'\nimport type { FabricMode } from '../Fabric.ts'\n\ntype Options = {\n mode?: FabricMode\n maxListener?: number\n}\n\nexport class AsyncEventEmitter<TEvents extends Record<string, any>> {\n constructor({ maxListener = 100, mode = 'sequential' }: Options = {}) {\n this.#emitter.setMaxListeners(maxListener)\n this.#mode = mode\n }\n\n #emitter = new NodeEventEmitter()\n #mode: FabricMode\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\n }\n\n const errors: Error[] = []\n\n if (this.#mode === 'sequential') {\n // Run listeners one by one, in order\n for (const listener of listeners) {\n try {\n await listener(...eventArgs)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n errors.push(error)\n }\n }\n } else {\n // Run all listeners concurrently\n const promises = listeners.map(async (listener) => {\n try {\n await listener(...eventArgs)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n errors.push(error)\n }\n })\n await Promise.all(promises)\n }\n\n if (errors.length === 1) {\n throw errors[0]\n }\n\n if (errors.length > 1) {\n throw new AggregateError(errors, `Errors in async listeners for \"${eventName}\"`)\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\n removeAll(): void {\n this.#emitter.removeAllListeners()\n }\n}\n","import pLimit from 'p-limit'\nimport type { FabricEvents, FabricMode } from './Fabric.ts'\nimport type * as KubbFile from './KubbFile.ts'\nimport { defaultParser } from './parsers/defaultParser.ts'\nimport type { Parser } from './parsers/types.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\n\nexport type ProcessFilesProps = {\n parsers?: Map<KubbFile.Extname, 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?: Map<KubbFile.Extname, 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 const parser = parsers.get(file.extname)\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 const total = files.length\n let processed = 0\n\n const processOne = async (resolvedFile: KubbFile.ResolvedFile, index: number) => {\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 const currentProcessed = ++processed\n const percentage = (currentProcessed / total) * 100\n\n await this.events.emit('process:progress', {\n file: resolvedFile,\n source,\n processed: currentProcessed,\n percentage,\n total,\n })\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","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","import { orderBy } from 'natural-orderby'\nimport { createFile } from './createFile.ts'\nimport type { FabricEvents } from './Fabric.ts'\nimport { FileProcessor, type ProcessFilesProps } from './FileProcessor.ts'\nimport type * as KubbFile from './KubbFile.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\nimport { Cache } from './utils/Cache.ts'\nimport { trimExtName } from './utils/trimExtName.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 #filesCache: Array<KubbFile.ResolvedFile> | null = null\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 #resolvePath(file: KubbFile.File): KubbFile.File {\n this.events.emit('file:resolve:path', { file })\n\n return file\n }\n\n #resolveName(file: KubbFile.File): KubbFile.File {\n this.events.emit('file:resolve:name', { file })\n\n return file\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 (let file of mergedFiles.values()) {\n file = this.#resolveName(file)\n file = this.#resolvePath(file)\n\n const resolvedFile = createFile(file)\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 async upsert(...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 (let file of mergedFiles.values()) {\n const existing = this.#cache.get(file.path)\n\n file = this.#resolveName(file)\n file = this.#resolvePath(file)\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.#filesCache = null\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 this.#filesCache = null\n }\n\n clear(): void {\n this.#cache.clear()\n this.#filesCache = null\n }\n\n get files(): Array<KubbFile.ResolvedFile> {\n if (this.#filesCache) {\n return this.#filesCache\n }\n\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: Array<KubbFile.ResolvedFile> = []\n\n for (const key of keys) {\n const file = this.#cache.get(key)\n if (file) {\n files.push(file)\n }\n }\n\n this.#filesCache = files\n\n return files\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 { isFunction } from 'remeda'\nimport type { Fabric, FabricConfig, FabricContext, FabricEvents, FabricOptions } from './Fabric.ts'\nimport { FileManager } from './FileManager.ts'\nimport type * as KubbFile from './KubbFile.ts'\nimport type { Parser } from './parsers/types.ts'\nimport type { Plugin } from './plugins/types.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\n\n/**\n * Function that initializes the root Fabric instance.\n *\n * Used for setting up plugins, parsers, or performing side effects\n * once the Fabric context is ready.\n */\ntype FabricInitializer<T extends FabricOptions> = (fabric: Fabric<T>) => void | Promise<void>\n\n/**\n * A function returned by {@link defineFabric} that creates a Fabric instance.\n */\nexport type CreateFabric<T extends FabricOptions> = (config?: FabricConfig<T>) => Fabric<T>\n\n/**\n * Defines a new Fabric factory function.\n *\n * @example\n * export const createFabric = defineFabric((fabric) => {\n * fabric.use(myPlugin())\n * })\n */\nexport function defineFabric<T extends FabricOptions>(init?: FabricInitializer<T>): CreateFabric<T> {\n function create(config: FabricConfig<T> = { mode: 'sequential' } as FabricConfig<T>): Fabric<T> {\n const events = new AsyncEventEmitter<FabricEvents>()\n const installedPlugins = new Set<Plugin<any>>()\n const installedParsers = new Map<KubbFile.Extname, Parser<any>>()\n const installedParserNames = new Set<string>()\n const fileManager = new FileManager({ events })\n\n const context: FabricContext<T> = {\n get files() {\n return fileManager.files\n },\n async addFile(...files) {\n await fileManager.add(...files)\n },\n config,\n fileManager,\n installedPlugins,\n installedParsers,\n on: events.on.bind(events),\n off: events.off.bind(events),\n onOnce: events.onOnce.bind(events),\n removeAll: events.removeAll.bind(events),\n emit: events.emit.bind(events),\n } as FabricContext<T>\n\n const fabric: Fabric<T> = {\n context,\n get files() {\n return fileManager.files\n },\n async addFile(...files) {\n await fileManager.add(...files)\n },\n async upsertFile(...files) {\n await fileManager.upsert(...files)\n },\n async use(pluginOrParser, ...options) {\n if (pluginOrParser.type === 'plugin') {\n if (installedPlugins.has(pluginOrParser)) {\n console.warn(`Plugin \"${pluginOrParser.name}\" already applied.`)\n } else {\n installedPlugins.add(pluginOrParser)\n }\n\n if (isFunction(pluginOrParser.inject)) {\n const injecter = pluginOrParser.inject\n\n const injected = (injecter as any)(context, ...options)\n Object.assign(fabric, injected)\n }\n }\n\n if (pluginOrParser.type === 'parser') {\n if (installedParserNames.has(pluginOrParser.name)) {\n console.warn(`Parser \"${pluginOrParser.name}\" already applied.`)\n } else {\n installedParserNames.add(pluginOrParser.name)\n }\n\n if (pluginOrParser.extNames) {\n for (const extName of pluginOrParser.extNames) {\n const existing = installedParsers.get(extName)\n if (existing && existing.name !== pluginOrParser.name) {\n console.warn(`Parser \"${pluginOrParser.name}\" is overriding parser \"${existing.name}\" for extension \"${extName}\".`)\n }\n installedParsers.set(extName, pluginOrParser)\n }\n }\n }\n\n if (isFunction(pluginOrParser.install)) {\n const installer = pluginOrParser.install\n\n await (installer as any)(context, ...options)\n }\n\n return fabric\n },\n } as Fabric<T>\n\n if (init) {\n init(fabric)\n }\n\n return fabric\n }\n\n return create\n}\n","import { defineFabric } from './defineFabric.ts'\n\nexport const createFabric = defineFabric()\n"],"x_google_ignoreList":[0],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as FabricOptions, c as FileManager, h as ResolvedFile, l as FileProcessor, n as FabricConfig, p as File, t as Fabric } from "./Fabric-BqMP-L92.cjs";
1
+ import { a as FabricOptions, c as FileManager, h as ResolvedFile, l as FileProcessor, n as FabricConfig, p as File, t as Fabric } from "./Fabric-BzIhBn8t.cjs";
2
2
 
3
3
  //#region src/defineFabric.d.ts
4
4
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as FabricOptions, c as FileManager, h as ResolvedFile, l as FileProcessor, n as FabricConfig, p as File, t as Fabric } from "./Fabric-CkskSjFr.js";
1
+ import { a as FabricOptions, c as FileManager, h as ResolvedFile, l as FileProcessor, n as FabricConfig, p as File, t as Fabric } from "./Fabric-igvWKffO.js";
2
2
 
3
3
  //#region src/defineFabric.d.ts
4
4
 
package/dist/index.js CHANGED
@@ -186,6 +186,25 @@ var FileManager = class {
186
186
  return this;
187
187
  }
188
188
  async add(...files) {
189
+ const resolvedFiles = [];
190
+ const mergedFiles = /* @__PURE__ */ new Map();
191
+ files.forEach((file) => {
192
+ const existing = mergedFiles.get(file.path);
193
+ if (existing) mergedFiles.set(file.path, mergeFile(existing, file));
194
+ else mergedFiles.set(file.path, file);
195
+ });
196
+ for (let file of mergedFiles.values()) {
197
+ file = _assertClassBrand(_FileManager_brand, this, _resolveName).call(this, file);
198
+ file = _assertClassBrand(_FileManager_brand, this, _resolvePath).call(this, file);
199
+ const resolvedFile = createFile(file);
200
+ _classPrivateFieldGet2(_cache, this).set(resolvedFile.path, resolvedFile);
201
+ this.flush();
202
+ resolvedFiles.push(resolvedFile);
203
+ }
204
+ await this.events.emit("file:add", { files: resolvedFiles });
205
+ return resolvedFiles;
206
+ }
207
+ async upsert(...files) {
189
208
  const resolvedFiles = [];
190
209
  const mergedFiles = /* @__PURE__ */ new Map();
191
210
  files.forEach((file) => {
@@ -290,6 +309,9 @@ function defineFabric(init) {
290
309
  async addFile(...files) {
291
310
  await fileManager.add(...files);
292
311
  },
312
+ async upsertFile(...files) {
313
+ await fileManager.upsert(...files);
314
+ },
293
315
  async use(pluginOrParser, ...options) {
294
316
  if (pluginOrParser.type === "plugin") {
295
317
  if (installedPlugins.has(pluginOrParser)) console.warn(`Plugin "${pluginOrParser.name}" already applied.`);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["e","NodeEventEmitter","errors: Error[]","resolvedFiles: Array<KubbFile.ResolvedFile>","files: Array<KubbFile.ResolvedFile>","context: FabricContext<T>","fabric: Fabric<T>","isFunction"],"sources":["../../../node_modules/.pnpm/remeda@2.32.0/node_modules/remeda/dist/isFunction-BJjFuZR7.js","../src/utils/AsyncEventEmitter.ts","../src/FileProcessor.ts","../src/utils/Cache.ts","../src/FileManager.ts","../src/defineFabric.ts","../src/createFabric.ts"],"sourcesContent":["const e=e=>typeof e==`function`;export{e as isFunction};\n//# sourceMappingURL=isFunction-BJjFuZR7.js.map","import { EventEmitter as NodeEventEmitter } from 'node:events'\nimport type { FabricMode } from '../Fabric.ts'\n\ntype Options = {\n mode?: FabricMode\n maxListener?: number\n}\n\nexport class AsyncEventEmitter<TEvents extends Record<string, any>> {\n constructor({ maxListener = 100, mode = 'sequential' }: Options = {}) {\n this.#emitter.setMaxListeners(maxListener)\n this.#mode = mode\n }\n\n #emitter = new NodeEventEmitter()\n #mode: FabricMode\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\n }\n\n const errors: Error[] = []\n\n if (this.#mode === 'sequential') {\n // Run listeners one by one, in order\n for (const listener of listeners) {\n try {\n await listener(...eventArgs)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n errors.push(error)\n }\n }\n } else {\n // Run all listeners concurrently\n const promises = listeners.map(async (listener) => {\n try {\n await listener(...eventArgs)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n errors.push(error)\n }\n })\n await Promise.all(promises)\n }\n\n if (errors.length === 1) {\n throw errors[0]\n }\n\n if (errors.length > 1) {\n throw new AggregateError(errors, `Errors in async listeners for \"${eventName}\"`)\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\n removeAll(): void {\n this.#emitter.removeAllListeners()\n }\n}\n","import pLimit from 'p-limit'\nimport type { FabricEvents, FabricMode } from './Fabric.ts'\nimport type * as KubbFile from './KubbFile.ts'\nimport { defaultParser } from './parsers/defaultParser.ts'\nimport type { Parser } from './parsers/types.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\n\nexport type ProcessFilesProps = {\n parsers?: Map<KubbFile.Extname, 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?: Map<KubbFile.Extname, 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 const parser = parsers.get(file.extname)\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 const total = files.length\n let processed = 0\n\n const processOne = async (resolvedFile: KubbFile.ResolvedFile, index: number) => {\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 const currentProcessed = ++processed\n const percentage = (currentProcessed / total) * 100\n\n await this.events.emit('process:progress', {\n file: resolvedFile,\n source,\n processed: currentProcessed,\n percentage,\n total,\n })\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","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","import { orderBy } from 'natural-orderby'\nimport { createFile } from './createFile.ts'\nimport type { FabricEvents } from './Fabric.ts'\nimport { FileProcessor, type ProcessFilesProps } from './FileProcessor.ts'\nimport type * as KubbFile from './KubbFile.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\nimport { Cache } from './utils/Cache.ts'\nimport { trimExtName } from './utils/trimExtName.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 #filesCache: Array<KubbFile.ResolvedFile> | null = null\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 #resolvePath(file: KubbFile.File): KubbFile.File {\n this.events.emit('file:resolve:path', { file })\n\n return file\n }\n\n #resolveName(file: KubbFile.File): KubbFile.File {\n this.events.emit('file:resolve:name', { file })\n\n return file\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 (let file of mergedFiles.values()) {\n const existing = this.#cache.get(file.path)\n\n file = this.#resolveName(file)\n file = this.#resolvePath(file)\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.#filesCache = null\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 this.#filesCache = null\n }\n\n clear(): void {\n this.#cache.clear()\n this.#filesCache = null\n }\n\n get files(): Array<KubbFile.ResolvedFile> {\n if (this.#filesCache) {\n return this.#filesCache\n }\n\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: Array<KubbFile.ResolvedFile> = []\n\n for (const key of keys) {\n const file = this.#cache.get(key)\n if (file) {\n files.push(file)\n }\n }\n\n this.#filesCache = files\n\n return files\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 { isFunction } from 'remeda'\nimport type { Fabric, FabricConfig, FabricContext, FabricEvents, FabricOptions } from './Fabric.ts'\nimport { FileManager } from './FileManager.ts'\nimport type * as KubbFile from './KubbFile.ts'\nimport type { Parser } from './parsers/types.ts'\nimport type { Plugin } from './plugins/types.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\n\n/**\n * Function that initializes the root Fabric instance.\n *\n * Used for setting up plugins, parsers, or performing side effects\n * once the Fabric context is ready.\n */\ntype FabricInitializer<T extends FabricOptions> = (fabric: Fabric<T>) => void | Promise<void>\n\n/**\n * A function returned by {@link defineFabric} that creates a Fabric instance.\n */\nexport type CreateFabric<T extends FabricOptions> = (config?: FabricConfig<T>) => Fabric<T>\n\n/**\n * Defines a new Fabric factory function.\n *\n * @example\n * export const createFabric = defineFabric((fabric) => {\n * fabric.use(myPlugin())\n * })\n */\nexport function defineFabric<T extends FabricOptions>(init?: FabricInitializer<T>): CreateFabric<T> {\n function create(config: FabricConfig<T> = { mode: 'sequential' } as FabricConfig<T>): Fabric<T> {\n const events = new AsyncEventEmitter<FabricEvents>()\n const installedPlugins = new Set<Plugin<any>>()\n const installedParsers = new Map<KubbFile.Extname, Parser<any>>()\n const installedParserNames = new Set<string>()\n const fileManager = new FileManager({ events })\n\n const context: FabricContext<T> = {\n get files() {\n return fileManager.files\n },\n async addFile(...files) {\n await fileManager.add(...files)\n },\n config,\n fileManager,\n installedPlugins,\n installedParsers,\n on: events.on.bind(events),\n off: events.off.bind(events),\n onOnce: events.onOnce.bind(events),\n removeAll: events.removeAll.bind(events),\n emit: events.emit.bind(events),\n } as FabricContext<T>\n\n const fabric: Fabric<T> = {\n context,\n get files() {\n return fileManager.files\n },\n async addFile(...files) {\n await fileManager.add(...files)\n },\n async use(pluginOrParser, ...options) {\n if (pluginOrParser.type === 'plugin') {\n if (installedPlugins.has(pluginOrParser)) {\n console.warn(`Plugin \"${pluginOrParser.name}\" already applied.`)\n } else {\n installedPlugins.add(pluginOrParser)\n }\n\n if (isFunction(pluginOrParser.inject)) {\n const injecter = pluginOrParser.inject\n\n const injected = (injecter as any)(context, ...options)\n Object.assign(fabric, injected)\n }\n }\n\n if (pluginOrParser.type === 'parser') {\n if (installedParserNames.has(pluginOrParser.name)) {\n console.warn(`Parser \"${pluginOrParser.name}\" already applied.`)\n } else {\n installedParserNames.add(pluginOrParser.name)\n }\n\n if (pluginOrParser.extNames) {\n for (const extName of pluginOrParser.extNames) {\n const existing = installedParsers.get(extName)\n if (existing && existing.name !== pluginOrParser.name) {\n console.warn(`Parser \"${pluginOrParser.name}\" is overriding parser \"${existing.name}\" for extension \"${extName}\".`)\n }\n installedParsers.set(extName, pluginOrParser)\n }\n }\n }\n\n if (isFunction(pluginOrParser.install)) {\n const installer = pluginOrParser.install\n\n await (installer as any)(context, ...options)\n }\n\n return fabric\n },\n } as Fabric<T>\n\n if (init) {\n init(fabric)\n }\n\n return fabric\n }\n\n return create\n}\n","import { defineFabric } from './defineFabric.ts'\n\nexport const createFabric = defineFabric()\n"],"x_google_ignoreList":[0],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["e","NodeEventEmitter","errors: Error[]","resolvedFiles: Array<KubbFile.ResolvedFile>","files: Array<KubbFile.ResolvedFile>","context: FabricContext<T>","fabric: Fabric<T>","isFunction"],"sources":["../../../node_modules/.pnpm/remeda@2.32.0/node_modules/remeda/dist/isFunction-BJjFuZR7.js","../src/utils/AsyncEventEmitter.ts","../src/FileProcessor.ts","../src/utils/Cache.ts","../src/FileManager.ts","../src/defineFabric.ts","../src/createFabric.ts"],"sourcesContent":["const e=e=>typeof e==`function`;export{e as isFunction};\n//# sourceMappingURL=isFunction-BJjFuZR7.js.map","import { EventEmitter as NodeEventEmitter } from 'node:events'\nimport type { FabricMode } from '../Fabric.ts'\n\ntype Options = {\n mode?: FabricMode\n maxListener?: number\n}\n\nexport class AsyncEventEmitter<TEvents extends Record<string, any>> {\n constructor({ maxListener = 100, mode = 'sequential' }: Options = {}) {\n this.#emitter.setMaxListeners(maxListener)\n this.#mode = mode\n }\n\n #emitter = new NodeEventEmitter()\n #mode: FabricMode\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\n }\n\n const errors: Error[] = []\n\n if (this.#mode === 'sequential') {\n // Run listeners one by one, in order\n for (const listener of listeners) {\n try {\n await listener(...eventArgs)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n errors.push(error)\n }\n }\n } else {\n // Run all listeners concurrently\n const promises = listeners.map(async (listener) => {\n try {\n await listener(...eventArgs)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n errors.push(error)\n }\n })\n await Promise.all(promises)\n }\n\n if (errors.length === 1) {\n throw errors[0]\n }\n\n if (errors.length > 1) {\n throw new AggregateError(errors, `Errors in async listeners for \"${eventName}\"`)\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\n removeAll(): void {\n this.#emitter.removeAllListeners()\n }\n}\n","import pLimit from 'p-limit'\nimport type { FabricEvents, FabricMode } from './Fabric.ts'\nimport type * as KubbFile from './KubbFile.ts'\nimport { defaultParser } from './parsers/defaultParser.ts'\nimport type { Parser } from './parsers/types.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\n\nexport type ProcessFilesProps = {\n parsers?: Map<KubbFile.Extname, 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?: Map<KubbFile.Extname, 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 const parser = parsers.get(file.extname)\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 const total = files.length\n let processed = 0\n\n const processOne = async (resolvedFile: KubbFile.ResolvedFile, index: number) => {\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 const currentProcessed = ++processed\n const percentage = (currentProcessed / total) * 100\n\n await this.events.emit('process:progress', {\n file: resolvedFile,\n source,\n processed: currentProcessed,\n percentage,\n total,\n })\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","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","import { orderBy } from 'natural-orderby'\nimport { createFile } from './createFile.ts'\nimport type { FabricEvents } from './Fabric.ts'\nimport { FileProcessor, type ProcessFilesProps } from './FileProcessor.ts'\nimport type * as KubbFile from './KubbFile.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\nimport { Cache } from './utils/Cache.ts'\nimport { trimExtName } from './utils/trimExtName.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 #filesCache: Array<KubbFile.ResolvedFile> | null = null\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 #resolvePath(file: KubbFile.File): KubbFile.File {\n this.events.emit('file:resolve:path', { file })\n\n return file\n }\n\n #resolveName(file: KubbFile.File): KubbFile.File {\n this.events.emit('file:resolve:name', { file })\n\n return file\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 (let file of mergedFiles.values()) {\n file = this.#resolveName(file)\n file = this.#resolvePath(file)\n\n const resolvedFile = createFile(file)\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 async upsert(...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 (let file of mergedFiles.values()) {\n const existing = this.#cache.get(file.path)\n\n file = this.#resolveName(file)\n file = this.#resolvePath(file)\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.#filesCache = null\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 this.#filesCache = null\n }\n\n clear(): void {\n this.#cache.clear()\n this.#filesCache = null\n }\n\n get files(): Array<KubbFile.ResolvedFile> {\n if (this.#filesCache) {\n return this.#filesCache\n }\n\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: Array<KubbFile.ResolvedFile> = []\n\n for (const key of keys) {\n const file = this.#cache.get(key)\n if (file) {\n files.push(file)\n }\n }\n\n this.#filesCache = files\n\n return files\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 { isFunction } from 'remeda'\nimport type { Fabric, FabricConfig, FabricContext, FabricEvents, FabricOptions } from './Fabric.ts'\nimport { FileManager } from './FileManager.ts'\nimport type * as KubbFile from './KubbFile.ts'\nimport type { Parser } from './parsers/types.ts'\nimport type { Plugin } from './plugins/types.ts'\nimport { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'\n\n/**\n * Function that initializes the root Fabric instance.\n *\n * Used for setting up plugins, parsers, or performing side effects\n * once the Fabric context is ready.\n */\ntype FabricInitializer<T extends FabricOptions> = (fabric: Fabric<T>) => void | Promise<void>\n\n/**\n * A function returned by {@link defineFabric} that creates a Fabric instance.\n */\nexport type CreateFabric<T extends FabricOptions> = (config?: FabricConfig<T>) => Fabric<T>\n\n/**\n * Defines a new Fabric factory function.\n *\n * @example\n * export const createFabric = defineFabric((fabric) => {\n * fabric.use(myPlugin())\n * })\n */\nexport function defineFabric<T extends FabricOptions>(init?: FabricInitializer<T>): CreateFabric<T> {\n function create(config: FabricConfig<T> = { mode: 'sequential' } as FabricConfig<T>): Fabric<T> {\n const events = new AsyncEventEmitter<FabricEvents>()\n const installedPlugins = new Set<Plugin<any>>()\n const installedParsers = new Map<KubbFile.Extname, Parser<any>>()\n const installedParserNames = new Set<string>()\n const fileManager = new FileManager({ events })\n\n const context: FabricContext<T> = {\n get files() {\n return fileManager.files\n },\n async addFile(...files) {\n await fileManager.add(...files)\n },\n config,\n fileManager,\n installedPlugins,\n installedParsers,\n on: events.on.bind(events),\n off: events.off.bind(events),\n onOnce: events.onOnce.bind(events),\n removeAll: events.removeAll.bind(events),\n emit: events.emit.bind(events),\n } as FabricContext<T>\n\n const fabric: Fabric<T> = {\n context,\n get files() {\n return fileManager.files\n },\n async addFile(...files) {\n await fileManager.add(...files)\n },\n async upsertFile(...files) {\n await fileManager.upsert(...files)\n },\n async use(pluginOrParser, ...options) {\n if (pluginOrParser.type === 'plugin') {\n if (installedPlugins.has(pluginOrParser)) {\n console.warn(`Plugin \"${pluginOrParser.name}\" already applied.`)\n } else {\n installedPlugins.add(pluginOrParser)\n }\n\n if (isFunction(pluginOrParser.inject)) {\n const injecter = pluginOrParser.inject\n\n const injected = (injecter as any)(context, ...options)\n Object.assign(fabric, injected)\n }\n }\n\n if (pluginOrParser.type === 'parser') {\n if (installedParserNames.has(pluginOrParser.name)) {\n console.warn(`Parser \"${pluginOrParser.name}\" already applied.`)\n } else {\n installedParserNames.add(pluginOrParser.name)\n }\n\n if (pluginOrParser.extNames) {\n for (const extName of pluginOrParser.extNames) {\n const existing = installedParsers.get(extName)\n if (existing && existing.name !== pluginOrParser.name) {\n console.warn(`Parser \"${pluginOrParser.name}\" is overriding parser \"${existing.name}\" for extension \"${extName}\".`)\n }\n installedParsers.set(extName, pluginOrParser)\n }\n }\n }\n\n if (isFunction(pluginOrParser.install)) {\n const installer = pluginOrParser.install\n\n await (installer as any)(context, ...options)\n }\n\n return fabric\n },\n } as Fabric<T>\n\n if (init) {\n init(fabric)\n }\n\n return fabric\n }\n\n return create\n}\n","import { defineFabric } from './defineFabric.ts'\n\nexport const createFabric = defineFabric()\n"],"x_google_ignoreList":[0],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import "../Fabric-BqMP-L92.cjs";
2
- import { i as typescriptParser, n as createImport, r as print, t as createExport } from "../typescriptParser-Dw2j-g-3.cjs";
1
+ import "../Fabric-BzIhBn8t.cjs";
2
+ import { i as typescriptParser, n as createImport, r as print, t as createExport } from "../typescriptParser-BlRK18rx.cjs";
3
3
  export { createExport, createImport, print, typescriptParser };
@@ -1,3 +1,3 @@
1
- import "../Fabric-CkskSjFr.js";
2
- import { i as typescriptParser, n as createImport, r as print, t as createExport } from "../typescriptParser-4vB6Ej7d.js";
1
+ import "../Fabric-igvWKffO.js";
2
+ import { i as typescriptParser, n as createImport, r as print, t as createExport } from "../typescriptParser-BN1vEX-I.js";
3
3
  export { createExport, createImport, print, typescriptParser };
@@ -1,5 +1,5 @@
1
- import { d as UserParser, u as Parser } from "./Fabric-BqMP-L92.cjs";
2
- import { i as typescriptParser } from "./typescriptParser-Dw2j-g-3.cjs";
1
+ import { d as UserParser, u as Parser } from "./Fabric-BzIhBn8t.cjs";
2
+ import { i as typescriptParser } from "./typescriptParser-BlRK18rx.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 { d as UserParser, u as Parser } from "./Fabric-CkskSjFr.js";
2
- import { i as typescriptParser } from "./typescriptParser-4vB6Ej7d.js";
1
+ import { d as UserParser, u as Parser } from "./Fabric-igvWKffO.js";
2
+ import { i as typescriptParser } from "./typescriptParser-BN1vEX-I.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>;
@@ -1,4 +1,4 @@
1
- import { f as Extname, o as Plugin, s as UserPlugin } from "./Fabric-BqMP-L92.cjs";
1
+ import { f as Extname, o as Plugin, s as UserPlugin } from "./Fabric-BzIhBn8t.cjs";
2
2
  import { LogLevel } from "consola";
3
3
 
4
4
  //#region src/plugins/barrelPlugin.d.ts
package/dist/plugins.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { f as Extname, o as Plugin, s as UserPlugin } from "./Fabric-CkskSjFr.js";
1
+ import { f as Extname, o as Plugin, s as UserPlugin } from "./Fabric-igvWKffO.js";
2
2
  import { LogLevel } from "consola";
3
3
 
4
4
  //#region src/plugins/barrelPlugin.d.ts
package/dist/types.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as FabricOptions, i as FabricMode, m as KubbFile_d_exports, n as FabricConfig, r as FabricContext } from "./Fabric-BqMP-L92.cjs";
1
+ import { a as FabricOptions, i as FabricMode, m as KubbFile_d_exports, n as FabricConfig, r as FabricContext } from "./Fabric-BzIhBn8t.cjs";
2
2
  export { type FabricConfig, type FabricContext, type FabricMode, type FabricOptions, KubbFile_d_exports as KubbFile };
package/dist/types.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as FabricOptions, i as FabricMode, m as KubbFile_d_exports, n as FabricConfig, r as FabricContext } from "./Fabric-CkskSjFr.js";
1
+ import { a as FabricOptions, i as FabricMode, m as KubbFile_d_exports, n as FabricConfig, r as FabricContext } from "./Fabric-igvWKffO.js";
2
2
  export { type FabricConfig, type FabricContext, type FabricMode, type FabricOptions, KubbFile_d_exports as KubbFile };
@@ -1,4 +1,4 @@
1
- import { u as Parser } from "./Fabric-CkskSjFr.js";
1
+ import { u as Parser } from "./Fabric-igvWKffO.js";
2
2
  import ts from "typescript";
3
3
 
4
4
  //#region src/parsers/typescriptParser.d.ts
@@ -36,4 +36,4 @@ declare function createExport({
36
36
  declare const typescriptParser: Parser<[], any>;
37
37
  //#endregion
38
38
  export { typescriptParser as i, createImport as n, print as r, createExport as t };
39
- //# sourceMappingURL=typescriptParser-4vB6Ej7d.d.ts.map
39
+ //# sourceMappingURL=typescriptParser-BN1vEX-I.d.ts.map
@@ -1,4 +1,4 @@
1
- import { u as Parser } from "./Fabric-BqMP-L92.cjs";
1
+ import { u as Parser } from "./Fabric-BzIhBn8t.cjs";
2
2
  import ts from "typescript";
3
3
 
4
4
  //#region src/parsers/typescriptParser.d.ts
@@ -36,4 +36,4 @@ declare function createExport({
36
36
  declare const typescriptParser: Parser<[], any>;
37
37
  //#endregion
38
38
  export { typescriptParser as i, createImport as n, print as r, createExport as t };
39
- //# sourceMappingURL=typescriptParser-Dw2j-g-3.d.cts.map
39
+ //# sourceMappingURL=typescriptParser-BlRK18rx.d.cts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/fabric-core",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
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
@@ -160,6 +160,12 @@ export interface Fabric<T extends FabricOptions = FabricOptions> extends Kubb.Fa
160
160
  : [NoInfer<TPluginOptions>] // Required otherwise
161
161
  ): (this & TExtension) | Promise<this & TExtension>
162
162
 
163
- /** Add one or more files to the Fabric file manager. */
163
+ /**
164
+ * Add one or more files to the Fabric file manager.
165
+ */
164
166
  addFile(...files: KubbFile.File[]): Promise<void>
167
+ /**
168
+ * Add one or more files to the Fabric file manager and merge the source, imports, exports
169
+ */
170
+ upsertFile(...files: KubbFile.File[]): Promise<void>
165
171
  }
@@ -59,6 +59,37 @@ export class FileManager {
59
59
  }
60
60
  })
61
61
 
62
+ for (let file of mergedFiles.values()) {
63
+ file = this.#resolveName(file)
64
+ file = this.#resolvePath(file)
65
+
66
+ const resolvedFile = createFile(file)
67
+
68
+ this.#cache.set(resolvedFile.path, resolvedFile)
69
+ this.flush()
70
+
71
+ resolvedFiles.push(resolvedFile)
72
+ }
73
+
74
+ await this.events.emit('file:add', { files: resolvedFiles })
75
+
76
+ return resolvedFiles
77
+ }
78
+
79
+ async upsert(...files: Array<KubbFile.File>) {
80
+ const resolvedFiles: Array<KubbFile.ResolvedFile> = []
81
+
82
+ const mergedFiles = new Map<string, KubbFile.File>()
83
+
84
+ files.forEach((file) => {
85
+ const existing = mergedFiles.get(file.path)
86
+ if (existing) {
87
+ mergedFiles.set(file.path, mergeFile(existing, file))
88
+ } else {
89
+ mergedFiles.set(file.path, file)
90
+ }
91
+ })
92
+
62
93
  for (let file of mergedFiles.values()) {
63
94
  const existing = this.#cache.get(file.path)
64
95
 
@@ -61,6 +61,9 @@ export function defineFabric<T extends FabricOptions>(init?: FabricInitializer<T
61
61
  async addFile(...files) {
62
62
  await fileManager.add(...files)
63
63
  },
64
+ async upsertFile(...files) {
65
+ await fileManager.upsert(...files)
66
+ },
64
67
  async use(pluginOrParser, ...options) {
65
68
  if (pluginOrParser.type === 'plugin') {
66
69
  if (installedPlugins.has(pluginOrParser)) {