import { n as __name } from "./chunk-BVHe6Par.js";
import { _ as NodeTreeContext, a as renderIntrinsic, b as provide, c as TreeNode, f as AsyncEventEmitter, g as createFile, i as renderIndent, l as FileManager, n as createComponent, o as RenderContext, r as createIntrinsic, s as RootContext, t as Root, u as FileProcessor, v as createContext, x as unprovide, y as inject } from "./Root-BQX3eHqb.js";
import { t as getRelativePath } from "./getRelativePath-C4Au07ON.js";
import { createExport, createImport, print } from "./parsers/typescript.js";
import { isFunction } from "remeda";

//#region src/composables/useContext.ts
function useContext(key, defaultValue) {
	return inject(key, defaultValue);
}

//#endregion
//#region src/composables/useNodeTree.ts
/**
* Accesses the current node tree for tracking component hierarchy.
*
* Use this composable to inspect or manipulate the component tree structure.
* Returns null if not within a component that provides NodeTreeContext.
*
* @returns The current TreeNode or null
*
* @example
* ```ts
* const nodeTree = useNodeTree()
* if (nodeTree) {
*   const childTree = nodeTree.addChild({ type: 'MyComponent', props: {} })
* }
* ```
*/
function useNodeTree() {
	return useContext(NodeTreeContext);
}

//#endregion
//#region src/contexts/AppContext.ts
/**
* Provides app-level metadata and lifecycle hooks (like `exit`) to
* components and composables within a Fabric runtime.
*/
const AppContext = createContext({
	exit: () => {},
	meta: {}
});

//#endregion
//#region src/components/App.ts
/**
* Container component providing App context with metadata and lifecycle.
*
* Use this component to wrap your application and provide shared metadata
* that can be accessed by child components using the useApp composable.
*
* @example
* ```tsx
* <App meta={{ version: '1.0.0', author: 'John Doe' }}>
*   <File baseName="user.ts" path="./user.ts">
*     <File.Source>export type User = {}</File.Source>
*   </File>
* </App>
* ```
*/
const App = createComponent("App", ({ children, ...props }) => {
	const { meta = {} } = props;
	const { exit } = useContext(RootContext);
	const nodeTree = useNodeTree();
	if (nodeTree) provide(NodeTreeContext, nodeTree.addChild({
		type: "App",
		props
	}));
	provide(AppContext, {
		exit,
		meta
	});
	return children;
});
App.displayName = "App";

//#endregion
//#region src/components/Br.ts
/**
* Generates a line break in the output.
*
* Use this component to add newlines in generated code.
*
* @example
* ```tsx
* <>
*   const x = 1
*   <Br />
*   const y = 2
* </>
* ```
*/
const Br = createComponent("br", () => {
	return createIntrinsic("br");
});
Br.displayName = "Br";

//#endregion
//#region src/utils/createJSDoc.ts
/**
* Create JSDoc comment block from comments array
*/
function createJSDoc({ comments }) {
	if (!comments || comments.length === 0) return "";
	const lines = comments.flatMap((c) => String(c !== null && c !== void 0 ? c : "").split(/\r?\n/)).map((l) => l.replace(/\*\//g, "*\\/").replace(/\r/g, "")).filter((l) => l.trim().length > 0);
	if (lines.length === 0) return "";
	return [
		"/**",
		...lines.map((l) => ` * ${l}`),
		" */"
	].join("\n");
}

//#endregion
//#region src/components/Const.ts
/**
* Generates a TypeScript constant declaration.
*
* @example
* ```tsx
* <Const name="API_URL" export type="string">
*   'https://api.example.com'
* </Const>
* ```
*/
const Const = createComponent("Const", ({ children, ...props }) => {
	const { name, export: canExport, type, JSDoc, asConst } = props;
	const nodeTree = useNodeTree();
	if (nodeTree) provide(NodeTreeContext, nodeTree.addChild({
		type: "Const",
		props
	}));
	const value = renderIntrinsic(children);
	let result = "";
	if (JSDoc === null || JSDoc === void 0 ? void 0 : JSDoc.comments) {
		result += createJSDoc({ comments: JSDoc.comments });
		result += "\n";
	}
	if (canExport) result += "export ";
	result += `const ${name}`;
	if (type) result += `: ${type}`;
	result += ` = ${children ? value : ""}`;
	if (asConst) result += " as const";
	return result;
});
Const.displayName = "Const";

//#endregion
//#region src/components/Dedent.ts
/**
* Decreases indentation level in the output.
*
* Use this component to reduce indentation after an indented code block.
* Typically paired with Indent to control indentation levels.
*
* @example
* ```tsx
* <>
*   function example() {'{'}<Br />
*   <Indent />
*     return true<Br />
*   <Dedent />
*   {'}'}
* </>
* ```
*/
const Dedent = createComponent("dedent", () => {
	return createIntrinsic("dedent");
});
Dedent.displayName = "Dedent";

//#endregion
//#region src/contexts/FileContext.ts
/**
* Provides app-level metadata and lifecycle hooks (like `exit`) to
* components and composables within a Fabric runtime.
*/
const FileContext = createContext(null);

//#endregion
//#region src/composables/useFile.ts
/**
* Accesses the current File context.
*
* Use this composable to access or modify the current file's properties,
* sources, imports, or exports.
*
* @returns The current file object or null if not within a File component
*
* @example
* ```ts
* const file = useFile()
* if (file) {
*   console.log(file.path)
*   file.sources.push({ value: 'export const x = 1', isExportable: true })
* }
* ```
*/
function useFile() {
	return useContext(FileContext);
}

//#endregion
//#region src/composables/useFileManager.ts
/**
* Accesses the FileManager from the Root context.
*
* Use this composable to interact with the FileManager directly,
* such as adding, retrieving, or managing files.
*
* @returns The current FileManager instance
*
* @example
* ```ts
* const fileManager = useFileManager()
* fileManager.add({
*   baseName: 'user.ts',
*   path: './generated/user.ts',
*   sources: []
* })
* ```
*/
function useFileManager() {
	const { fileManager } = useContext(RootContext);
	return fileManager;
}

//#endregion
//#region src/components/File.ts
/**
* Component for generating files with sources, imports, and exports.
*
* Creates files in the FileManager that can be written to disk.
*
* @example
* ```tsx
* <File baseName="user.ts" path="./generated/user.ts">
*   <File.Source isExportable>
*     export type User = {{ '{' }} id: number {{ '}' }}
*   </File.Source>
* </File>
* ```
*/
const File = createComponent("File", ({ children, ...props }) => {
	const { baseName, path, meta = {}, footer, banner } = props;
	const fileManager = useFileManager();
	const nodeTree = useNodeTree();
	if (nodeTree) provide(NodeTreeContext, nodeTree.addChild({
		type: "File",
		props
	}));
	const file = {
		baseName,
		path,
		meta,
		banner,
		footer,
		sources: [],
		imports: [],
		exports: []
	};
	const [resolvedFile] = fileManager.add(file);
	provide(FileContext, resolvedFile);
	return children;
});
/**
* Adds source code to a file.
*
* Use this component inside a File component to add code blocks.
*
* @example
* ```tsx
* <File.Source isExportable name="User">
*   export type User = {{ '{' }} id: number {{ '}' }}
* </File.Source>
* ```
*/
const FileSource = createComponent("FileSource", ({ children, ...props }) => {
	const { name, isExportable, isIndexable, isTypeOnly } = props;
	const nodeTree = useNodeTree();
	const file = useFile();
	if (nodeTree) provide(NodeTreeContext, nodeTree.addChild({
		type: "FileSource",
		props
	}));
	const value = renderIntrinsic(children);
	if (file) file.sources.push({
		name,
		isExportable,
		isIndexable,
		isTypeOnly,
		value
	});
	return value;
});
/**
* Adds export statements to a file.
*
* Use this component to create re-exports from other files.
*
* @example
* ```tsx
* <File.Export name="User" path="./types/user" isTypeOnly />
* ```
*/
const FileExport = createComponent("FileExport", (props) => {
	const { name, path, isTypeOnly, asAlias } = props;
	const nodeTree = useNodeTree();
	const file = useFile();
	if (nodeTree) provide(NodeTreeContext, nodeTree.addChild({
		type: "FileExport",
		props
	}));
	if (file) file.exports.push({
		name,
		path,
		asAlias,
		isTypeOnly
	});
	return print(createExport({
		name,
		path,
		isTypeOnly,
		asAlias
	}));
});
/**
* Adds import statements to a file.
*
* Use this component to import types or values from other files.
*
* @example
* ```tsx
* <File.Import name="User" path="./types/user" isTypeOnly />
* ```
*/
const FileImport = createComponent("FileImport", (props) => {
	const { name, path, root, isNameSpace, isTypeOnly } = props;
	const nodeTree = useNodeTree();
	const file = useFile();
	if (nodeTree) provide(NodeTreeContext, nodeTree.addChild({
		type: "FileImport",
		props
	}));
	if (file) file.imports.push({
		name,
		path,
		root,
		isNameSpace,
		isTypeOnly
	});
	return print(createImport({
		name,
		path,
		root,
		isNameSpace,
		isTypeOnly
	}));
});
File.Source = FileSource;
File.Import = FileImport;
File.Export = FileExport;

//#endregion
//#region src/components/Indent.ts
/**
* Increases indentation level in the output.
*
* Use this component to add indentation for nested code blocks.
* Typically paired with Dedent to control indentation levels.
*
* @example
* ```tsx
* <>
*   function example() {'{'}<Br />
*   <Indent />
*     return true<Br />
*   <Dedent />
*   {'}'}
* </>
* ```
*/
const Indent = createComponent("indent", () => {
	return createIntrinsic("indent");
});
Indent.displayName = "Indent";

//#endregion
//#region src/components/Function.ts
/**
* Generates a TypeScript function declaration.
*
* @example
* ```tsx
* <Function
*   name="getUser"
*   export
*   async
*   params="id: number"
*   returnType="User"
* >
*   return fetch(`/users/${id}`).then(r => r.json())
* </Function>
* ```
*/
const Function = createComponent("Function", ({ children, ...props }) => {
	const { name, default: isDefault, export: canExport, async, generics, params, returnType, JSDoc } = props;
	const nodeTree = useNodeTree();
	if (nodeTree) provide(NodeTreeContext, nodeTree.addChild({
		type: "Function",
		props
	}));
	const parts = [];
	if (JSDoc === null || JSDoc === void 0 ? void 0 : JSDoc.comments) {
		parts.push(createJSDoc({ comments: JSDoc.comments }));
		parts.push("\n");
	}
	if (canExport) parts.push("export ");
	if (isDefault) parts.push("default ");
	if (async) parts.push("async ");
	parts.push(`function ${name}`);
	if (generics) {
		parts.push("<");
		parts.push(Array.isArray(generics) ? generics.join(", ").trim() : generics);
		parts.push(">");
	}
	parts.push(`(${params || ""})`);
	if (returnType && !async) parts.push(`: ${returnType}`);
	if (returnType && async) parts.push(`: Promise<${returnType}>`);
	parts.push(" {");
	if (children) return [
		parts.join(""),
		Br(),
		Indent(),
		children,
		Br(),
		Dedent(),
		"}"
	];
	return [parts.join(""), "}"];
});
Function.displayName = "Function";
/**
* ArrowFunction
*
* Builds an arrow function declaration string for the fsx renderer. Supports
* the same options as `Function`. Use `singleLine` to produce a one-line
* arrow expression.
*/
const ArrowFunction = createComponent("ArrowFunction", ({ children, ...props }) => {
	const { name, default: isDefault, export: canExport, async, generics, params, returnType, JSDoc, singleLine } = props;
	const nodeTree = useNodeTree();
	if (nodeTree) provide(NodeTreeContext, nodeTree.addChild({
		type: "ArrowFunction",
		props
	}));
	const parts = [];
	if (JSDoc === null || JSDoc === void 0 ? void 0 : JSDoc.comments) {
		parts.push(createJSDoc({ comments: JSDoc.comments }));
		parts.push("\n");
	}
	if (canExport) parts.push("export ");
	if (isDefault) parts.push("default ");
	parts.push(`const ${name} = `);
	if (async) parts.push("async ");
	if (generics) {
		parts.push("<");
		parts.push(Array.isArray(generics) ? generics.join(", ").trim() : generics);
		parts.push(">");
	}
	parts.push(`(${params || ""})`);
	if (returnType && !async) parts.push(`: ${returnType}`);
	if (returnType && async) parts.push(`: Promise<${returnType}>`);
	if (singleLine) {
		parts.push(` => ${children || ""}\n`);
		return parts.join("");
	}
	if (children) return [
		parts.join(""),
		" => {",
		Br(),
		Indent(),
		children,
		Br(),
		Dedent(),
		"}"
	];
	return [parts.join(""), " => {}"];
});
ArrowFunction.displayName = "ArrowFunction";
Function.Arrow = ArrowFunction;

//#endregion
//#region src/components/Type.ts
/**
* Generates a TypeScript type declaration.
*
* @example
* ```tsx
* <Type name="User" export>
*   {'{'} id: number; name: string {'}'}
* </Type>
* ```
*/
const Type = createComponent("Type", ({ children, ...props }) => {
	const { name, export: canExport, JSDoc } = props;
	const nodeTree = useNodeTree();
	if (nodeTree) provide(NodeTreeContext, nodeTree.addChild({
		type: "Type",
		props
	}));
	if (name.charAt(0).toUpperCase() !== name.charAt(0)) throw new Error("Name should start with a capital letter (see TypeScript types)");
	const value = renderIntrinsic(children);
	let result = "";
	if (JSDoc === null || JSDoc === void 0 ? void 0 : JSDoc.comments) {
		result += createJSDoc({ comments: JSDoc.comments });
		result += "\n";
	}
	if (canExport) result += "export ";
	result += `type ${name} = ${value || ""}`;
	return result;
});
Type.displayName = "Type";

//#endregion
//#region src/composables/useApp.ts
/**
* Accesses the App context with metadata and exit function.
*
* Use this composable to access metadata defined in the App component
* or to exit the rendering process early.
*
* @throws Error when no AppContext is available
*
* @example
* ```ts
* const { meta, exit } = useApp<{ version: string }>()
* console.log(meta.version)
* ```
*/
function useApp() {
	return useContext(AppContext);
}

//#endregion
//#region src/composables/useLifecycle.ts
/**
* Accesses lifecycle helpers for controlling generation flow.
*
* Use this composable to exit the rendering process early or perform
* cleanup operations.
*
* @returns Object with lifecycle methods (exit)
*
* @example
* ```ts
* const { exit } = useLifecycle()
*
* // Stop generation on error
* if (invalidData) {
*   exit(new Error('Invalid data'))
* }
* ```
*/
function useLifecycle() {
	const { exit } = useContext(RootContext);
	return { exit };
}

//#endregion
//#region src/createFabric.ts
/**
* Creates a new Fabric instance for file generation.
*
* The Fabric instance provides methods for registering plugins,
* adding files, and triggering file generation.
*
* @param config - Optional configuration object
* @returns A new Fabric instance
*
* @example
* ```ts
* import { createFabric } from '@kubb/fabric-core'
* import { fsPlugin } from '@kubb/fabric-core/plugins'
* import { typescriptParser } from '@kubb/fabric-core/parsers'
*
* const fabric = createFabric()
* fabric.use(fsPlugin)
* fabric.use(typescriptParser)
*
* await fabric.addFile({
*   baseName: 'user.ts',
*   path: './generated/user.ts',
*   sources: [{ value: 'export type User = {}', isExportable: true }],
*    imports: [],
*   exports: [],
* })
*
* await fabric.write({ extension: { '.ts': '.ts' } })
* ```
*/
function createFabric(config = { mode: "sequential" }) {
	const events = new AsyncEventEmitter();
	const installedPlugins = /* @__PURE__ */ new Set();
	const installedParsers = /* @__PURE__ */ new Map();
	const installedParserNames = /* @__PURE__ */ new Set();
	const fileManager = new FileManager({ events });
	const context = {
		get files() {
			return fileManager.files;
		},
		async addFile(...files) {
			await fileManager.add(...files);
		},
		config,
		fileManager,
		installedPlugins,
		installedParsers,
		on: events.on.bind(events),
		off: events.off.bind(events),
		onOnce: events.onOnce.bind(events),
		removeAll: events.removeAll.bind(events),
		emit: events.emit.bind(events)
	};
	const fabric = {
		context,
		get files() {
			return fileManager.files;
		},
		async addFile(...files) {
			await fileManager.add(...files);
		},
		async upsertFile(...files) {
			await fileManager.upsert(...files);
		},
		async use(pluginOrParser, ...options) {
			if (pluginOrParser.type === "plugin") {
				if (installedPlugins.has(pluginOrParser)) console.warn(`Plugin "${pluginOrParser.name}" already applied.`);
				else installedPlugins.add(pluginOrParser);
				if (isFunction(pluginOrParser.inject)) {
					const injecter = pluginOrParser.inject;
					const injected = injecter(context, ...options);
					Object.assign(fabric, injected);
				}
			}
			if (pluginOrParser.type === "parser") {
				if (installedParserNames.has(pluginOrParser.name)) console.warn(`Parser "${pluginOrParser.name}" already applied.`);
				else installedParserNames.add(pluginOrParser.name);
				if (pluginOrParser.extNames) for (const extName of pluginOrParser.extNames) {
					const existing = installedParsers.get(extName);
					if (existing && existing.name !== pluginOrParser.name) console.warn(`Parser "${pluginOrParser.name}" is overriding parser "${existing.name}" for extension "${extName}".`);
					installedParsers.set(extName, pluginOrParser);
				}
			}
			if (isFunction(pluginOrParser.install)) {
				const installer = pluginOrParser.install;
				await installer(context, ...options);
			}
			return fabric;
		}
	};
	return fabric;
}

//#endregion
export { App, AppContext, Br, Const, Dedent, File, FileContext, FileManager, FileProcessor, Function, Indent, NodeTreeContext, RenderContext, Root, RootContext, TreeNode, Type, createComponent, createContext, createFabric, createFile, createJSDoc, getRelativePath, inject, provide, renderIndent, renderIntrinsic, unprovide, useApp, useContext, useFile, useFileManager, useLifecycle, useNodeTree };
//# sourceMappingURL=index.js.map