@remotex-labs/xbuild 3.0.1 → 3.0.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.
package/dist/bash.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["src/bash.ts","src/errors/uncaught.error.ts","src/providers/stack.provider.ts","src/models/files.model.ts","src/services/framework.service.ts","src/errors/base.error.ts","src/ui/screen.ui.ts","src/ui/interactive.ui.ts","src/ui/print.ui.ts","src/ui/banner.ui.ts","src/ui/color.ui.ts","src/constants/ui.constant.ts","src/services/configuration.service.ts","src/components/object.component.ts","src/constants/configuration.constant.ts","src/modules/typescript/services/typescript.service.ts","src/modules/typescript/models/declaration.model.ts","src/components/transformer.component.ts","src/modules/typescript/constants/typescript.constant.ts","src/modules/typescript/services/host.service.ts","src/components/glob.component.ts","src/constants/glob.constant.ts","src/modules/argv/argv.module.ts","src/modules/argv/constants/argv.constant.ts","src/modules/server/server.module.ts","src/modules/server/html/server.html","src/services/build.service.ts","src/errors/xbuild.error.ts","src/services/variant.service.ts","src/providers/log.provider.ts","src/directives/analyze.directive.ts","src/constants/macros.constant.ts","src/directives/define.directive.ts","src/directives/macros.directive.ts","src/directives/inline.directive.ts","src/services/vm.service.ts","src/services/transpiler.service.ts","src/constants/transpiler.constant.ts","src/components/entry-points.component.ts","src/constants/variant.constant.ts","src/providers/message.provider.ts","src/services/watch.service.ts","src/providers/config-file.provider.ts"],"sourceRoot":"https://github.com/remotex-labs/xBuild/tree/v3.0.1/","sourcesContent":["/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { ArgumentsInterface } from '@argv/interfaces/argv-module.interface';\nimport type { ConfigurationInterface } from '@interfaces/configuration.interface';\nimport type { ServerConfigurationInterface } from '@server/interfaces/server.interface';\nimport type { xBuildConfigInterface } from '@providers/interfaces/config-file-provider.interface';\n\n/**\n * Imports\n */\n\nimport { rmSync } from 'fs';\nimport '@errors/uncaught.error';\nimport { Screen } from '@ui/screen.ui';\nimport { bannerUi } from '@ui/banner.ui';\nimport { ArgvModule } from '@argv/argv.module';\nimport { inject } from '@remotex-labs/xinject';\nimport { FilesModel } from '@models/files.model';\nimport { ServerModule } from '@server/server.module';\nimport { startInteractive } from '@ui/interactive.ui';\nimport { BuildService } from '@services/build.service';\nimport { WatchService } from '@services/watch.service';\nimport { configFileProvider } from '@providers/config-file.provider';\n\n/**\n * Replaces the declared variants with one built from the entry points the command line named.\n *\n * @param config - Configuration read from the file, modified in place\n * @param args - Parsed command line the run was started with\n *\n * @remarks\n * Files named on the command line are a run of their own rather than an addition to what the file declares,\n * so the variants it declares are put aside, and a single variant named `argv` takes their place.\n * A command line naming no entry point leaves the configuration as the file wrote it.\n *\n * @example\n * ```ts\n * // xBuild src/index.ts\n * configureEntryPoints(config, args);\n * config.variants; // { argv: { esbuild: { entryPoints: [ 'src/index.ts' ] } } }\n * ```\n *\n * @since 3.0.0\n */\n\nexport function configureEntryPoints(config: xBuildConfigInterface, args: ArgumentsInterface): void {\n if (!args.entryPoints) return;\n\n config.variants = {\n argv: {\n esbuild: {\n entryPoints: args.entryPoints\n }\n }\n };\n}\n\n/**\n * Writes the flags the command line typed onto every variant.\n *\n * @param config - Configuration the overrides are written onto, modified in place\n * @param args - Parsed command line the run was started with\n *\n * @remarks\n * A flag left untyped is left alone rather than written as its default,\n * so what a configuration file states survives everything the command line did not say.\n * The overrides reach every variant, since a flag names what the run is for rather than which variant it is about.\n * Each output directory is also excluded from the watch as it is settled,\n * without which a build would write into the tree it is watching and set off the next one.\n *\n * @example\n * ```ts\n * // xBuild --outdir build --minify\n * applyCommandLineOverrides(config, args);\n * config.watch.filter; // [ '!build/**' ]\n * ```\n *\n * @since 3.0.0\n */\n\nexport function applyCommandLineOverrides(config: xBuildConfigInterface, args: ArgumentsInterface): void {\n const commonOutDir = config.common?.esbuild?.outdir ?? 'dist';\n const variants = Object.values(config.variants ?? {});\n if(commonOutDir) {\n config.watch?.filter?.push(`!${ commonOutDir }/**`);\n }\n\n for (const variant of variants) {\n if (args.types !== undefined) variant.types = args.types;\n if (args.outdir !== undefined) variant.esbuild.outdir = args.outdir;\n if (args.bundle !== undefined) variant.esbuild.minify = args.bundle;\n if (args.minify !== undefined) variant.esbuild.minify = args.minify;\n if (args.tsconfig !== undefined) variant.esbuild.tsconfig = args.tsconfig;\n if (args.platform !== undefined) variant.esbuild.platform = args.platform;\n if (args.declaration !== undefined) variant.declaration = args.declaration;\n if (args.failOnError !== undefined) {\n variant.types = { failOnError: args.failOnError };\n }\n\n if(variant.esbuild.outdir && variant.esbuild.outdir !== commonOutDir) {\n config.watch?.filter?.push(`!${ variant.esbuild.outdir }/**`);\n }\n }\n}\n\n/**\n * Clears the output of an earlier run where the command line asked for it, then builds.\n *\n * @param build - Service the variants are built through\n * @param args - Parsed command line the run was started with\n * @returns A promise settling once every variant asked for has finished\n *\n * @remarks\n * Bound to its two arguments and handed to the screen,\n * so a key or a watch starts the same build the command line asked for.\n * The directory cleared is `dist` rather than whatever the configuration writes to.\n * The `--build` flag decides which variants run, and naming none runs every variant the configuration declares.\n *\n * @since 3.0.0\n */\n\nasync function executeBuild(build: BuildService, args: ArgumentsInterface): Promise<void> {\n if (args.clean) rmSync('dist', { recursive: true, force: true });\n\n await build.build(args.build);\n}\n\n/**\n * Starts the development server where either the command line or the configuration asks for one.\n *\n * @param config - Configuration read for its `serve` block\n * @param args - Parsed command line the run was started with\n * @param screen - Screen the server reports through\n * @returns A promise settling once the server is listening, at once when none was asked for\n *\n * @remarks\n * `--serve` carries the directory to serve, so asking for a server and choosing what it serves are the one flag,\n * and a configuration that starts one of its own is honored even where the flag is absent.\n * The directory falls back to the configured one and then to `dist`, which is where a build writes by default.\n * The server reports through the screen rather than to the console,\n * so its address reaches the status line and its requests are held to the level the run reports at.\n *\n * @example\n * ```ts\n * // xBuild --serve dist\n * await startServer(config, args, screen);\n * // [xBuild] → serve http://localhost:3000\n * ```\n *\n * @see ServerModule\n * @since 3.0.0\n */\n\nexport async function startServer(config: xBuildConfigInterface, args: ArgumentsInterface, screen: Screen): Promise<void> {\n const shouldStartServer = (args.serve ?? false) !== false || config.serve?.start;\n if (!shouldStartServer) return;\n\n const serveDir = config.serve?.dir || args.serve || 'dist';\n const server = new ServerModule(<ServerConfigurationInterface> { ...config.serve }, serveDir);\n server.subscribe(screen.serverEvent.bind(screen));\n\n await server.start();\n}\n\n/**\n * Watches the project, rebuilds on a change, and takes the terminal for the shortcuts.\n *\n * @param buildService - Service the rebuilds run through\n * @param config - Configuration read for its `watch` block, and replaced when its file changes\n * @param args - Parsed command line the run was started with\n * @param screen - Screen the rebuilds are announced on\n * @returns A promise settling once the keys are listened for, at once when no watch was asked for\n *\n * @remarks\n * A run is watched where `--watch` asked for it, and also where a server is serving,\n * since output nobody rebuilds is not worth serving.\n * A change refreshes the file model before anything is rebuilt,\n * so the rebuild reads the files as they now are rather than as they were read the first time.\n * Reloading the TypeScript configuration belongs to the screen rather than to the watch,\n * which puts a rebuild started by a key on the same footing as one started by a change.\n * The configuration file is watched by its own version rather than by its path,\n * so an edit to it is reparsed and reapplied while every other change goes straight to a rebuild.\n * The shortcuts are listened for last, since they take the last row of the terminal,\n * and a run that never reaches here leaves the terminal as it found it.\n *\n * @example\n * ```ts\n * // xBuild --watch\n * await startWatchMode(build, config, args, screen);\n * // [xBuild] ↻ rebuild 2 files changed\n * ```\n *\n * @see WatchService\n * @see startInteractive\n *\n * @since 3.0.0\n */\n\nexport async function startWatchMode(\n buildService: BuildService, config: xBuildConfigInterface, args: ArgumentsInterface, screen: Screen\n): Promise<void> {\n const shouldWatch = args.watch || args.serve !== undefined || config.serve?.start;\n if (!shouldWatch) return;\n\n const files = inject(FilesModel);\n let configVersion = files.touch(args.config!).version;\n\n const watchService = new WatchService(process.cwd(), config.watch);\n watchService.subscribe(async (changedFiles) => {\n files.refreshAll();\n\n if(configVersion !== files.touch(args.config!).version) {\n configVersion = files.touch(args.config!).version;\n const config = await configFileProvider(args.config!);\n applyCommandLineOverrides(config, args);\n buildService.configuration = config;\n }\n\n const count = Object.keys(changedFiles).length;\n await screen.rebuild(`${ count } ${ count === 1 ? 'file' : 'files' } changed`);\n });\n\n await startInteractive(screen);\n}\n\n/**\n * Runs the command line from the banner to the last build.\n *\n * @returns A promise settling once the build has run, or never returning where a check ended the process\n *\n * @remarks\n * The configuration file is found before anything else is parsed, since it is what declares the rest of the flags,\n * and the full parse is written back onto the arguments the provider was handed.\n * The screen is built around the build itself, so a key pressed later starts the same run the command line asked for.\n * A run asking for a type check reports it and leaves from there, since nothing is built for one.\n * The server and the watch are started before the first build,\n * so a rebuild reaches a screen, and the output is served as soon as it is written.\n *\n * @since 3.0.0\n */\n\nasync function main(): Promise<void> {\n console.log(bannerUi());\n\n // Parse configuration\n const argvService = inject(ArgvModule);\n const preConfig = argvService.parseConfigFile(process.argv);\n\n const args = {} as ArgumentsInterface;\n const config = await configFileProvider(preConfig.config, args);\n\n // Configure build\n configureEntryPoints(config, args);\n applyCommandLineOverrides(config, args);\n\n const buildService = new BuildService(config as ConfigurationInterface, args);\n const screen = inject(Screen, executeBuild.bind({}, buildService, args));\n buildService.subscribe(screen.buildEvent.bind(screen));\n\n if (args.typeCheck) {\n screen.diagnostics(await buildService.typeChack(args.build));\n }\n\n // Execute build pipeline\n await startServer(config, args, screen);\n await startWatchMode(buildService, config, args, screen);\n await executeBuild(buildService, args);\n}\n\nawait main();\n","/**\n * Imports\n */\n\nimport process from 'node:process';\nimport { xBuildBaseError } from '@errors/base.error';\nimport { formatStack, getErrorMetadata } from '@providers/stack.provider';\n\n/**\n * Prints whatever reached a global handler the way the framework prints its own errors.\n *\n * @param reason - Error, aggregate error, or any other value that escaped\n *\n * @remarks\n * An {@link xBuildBaseError} already carries its resolved block, so it goes to the console untouched rather than\n * being resolved a second time.\n * Any other `Error` is resolved here with the framework and native frames kept,\n * since a value that got this far offers no other clue about where it came from.\n * An {@link AggregateError} is announced once and then unwrapped, each of its errors going through the same choice.\n * A value that is not an error is printed as it stands.\n *\n * @example\n * ```ts\n * formatErrors(new Error('connect ECONNREFUSED')); // heading, snippet and resolved trace\n * formatErrors(new xBuildError('bad config')); // the block the error already carries\n * formatErrors('not an error at all'); // 'not an error at all'\n * ```\n *\n * @see formatStack\n * @see xBuildBaseError\n * @see getErrorMetadata\n *\n * @since 2.0.0\n */\n\nexport function formatErrors(reason: unknown): void {\n if (reason instanceof AggregateError) {\n console.error('AggregateError:', reason.message);\n for (const err of reason.errors) {\n if (err instanceof Error && !(err instanceof xBuildBaseError)) {\n const metadata = getErrorMetadata(err, { withFrameworkFrames: true, withNativeFrames: true });\n console.error(formatStack(metadata, err.name, err.message));\n } else {\n console.error(err);\n }\n }\n\n return;\n }\n\n if (reason instanceof Error && !(reason instanceof xBuildBaseError)) {\n const metadata = getErrorMetadata(reason, { withFrameworkFrames: true, withNativeFrames: true });\n console.error(formatStack(metadata, reason.name, reason.message));\n } else {\n console.error(reason);\n }\n}\n\n/**\n * Prints an exception that escaped every `try` and leaves the process with exit code `2`.\n *\n * @remarks\n * Registered as a side effect of importing this file, which is why the CLI entry point imports it on its first line -\n * anything thrown while the later imports evaluate is already covered.\n * Node leaves the process in an undefined state once an exception gets this far, so the handler prints and exits\n * instead of letting the build carry on.\n *\n * @example\n * ```ts\n * import '@errors/uncaught.error';\n * throw new Error('unreachable state'); // the resolved block, then exit code 2\n * ```\n *\n * @see formatErrors\n * @see {@link https://nodejs.org/api/process.html#event-uncaughtexception | process 'uncaughtException'}\n *\n * @since 2.0.0\n */\n\nprocess.on('uncaughtException', (reason: unknown) => {\n formatErrors(reason);\n process.exit(2);\n});\n\n/**\n * Prints a rejection nobody awaited and leaves the process with exit code `2`.\n *\n * @remarks\n * Registered alongside the exception handler, since an unawaited rejection ends the build just as surely and would\n * otherwise print Node's own warning without any source resolution.\n * The exit code matches the one used for uncaught exceptions: both mean the build died on an unhandled failure, and\n * nothing downstream needs to tell them apart.\n *\n * @example\n * ```ts\n * import '@errors/uncaught.error';\n * Promise.reject(new Error('write after end')); // the resolved block, then exit code 2\n * ```\n *\n * @see formatErrors\n * @see {@link https://nodejs.org/api/process.html#event-unhandledrejection | process 'unhandledRejection'}\n *\n * @since 2.0.0\n */\n\nprocess.on('unhandledRejection', (reason: unknown) => {\n formatErrors(reason);\n process.exit(3);\n});\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { PartialMessage } from 'esbuild';\nimport type { SourceService } from '@remotex-labs/xmap';\nimport type { ParsedStackTraceInterface } from '@remotex-labs/xmap/parser.component';\nimport type { StackTraceInterface, ResolveMetadataInterface } from '@providers/interfaces/stack-provider.interface';\n\n/**\n * Imports\n */\n\nimport { inject } from '@remotex-labs/xinject';\nimport { FilesModel } from '@models/files.model';\nimport { resolveError } from '@remotex-labs/xmap';\nimport { xterm } from '@remotex-labs/xansi/xterm.component';\nimport { FrameworkService } from '@services/framework.service';\nimport { parseErrorStack } from '@remotex-labs/xmap/parser.component';\nimport { formatErrorCode } from '@remotex-labs/xmap/formatter.component';\nimport { highlightCode } from '@remotex-labs/xmap/highlighter.component';\n\n/**\n * Returns a source resolver for a file, from its source map when one is registered and from its cached text otherwise.\n *\n * @param fileName - Path of the file a stack frame points at, relative or absolute\n * @returns The resolver for that file, or `null` when the file has neither a map nor cached text\n *\n * @remarks\n * A registered map wins since it resolves back to the authored file rather than to the emitted one.\n * Without a map the cached text stands in through a minimal resolver that slices the surrounding lines as its\n * code window, so an unmapped file still prints a snippet.\n * That window spans three lines either side unless the caller asks for a different span and is clamped to the\n * bounds of the file.\n * `startLine` and `endLine` come back as 1-based line numbers rather than as indexes into the text,\n * which is how {@link formatErrorCode} reads them, so a printed number labels the line it belongs to.\n * The line passes through as it arrived, while the column comes back one higher than it was given.\n *\n * @example\n * ```ts\n * getSource('dist/index.js'); // SourceService - the registered map\n * getSource('src/index.ts')?.getPositionWithCode(10, 4); // line 10, column 5, lines 7-13 as code\n * getSource('missing.ts'); // null\n * ```\n *\n * @see SourceService\n * @see FilesModel.touch\n * @see FrameworkService.getSourceMap\n *\n * @since 2.0.0\n */\n\nexport function getSource(fileName: string = ''): SourceService | null {\n const framework = inject(FrameworkService);\n const mapped = framework.getSourceMap(fileName);\n if (mapped) return mapped;\n\n const snapshot = inject(FilesModel).touch(fileName);\n const code = snapshot.snapshot?.text;\n\n if (!snapshot || !code) return null;\n const lines = code.split('\\n');\n\n return {\n getPositionWithCode: (line, column, _bias, options) => {\n const after = options?.linesAfter ?? 3;\n const before = options?.linesBefore ?? 3;\n\n // both bounds are 1-based line numbers, so only the slice start converts to an index\n const startLine = Math.max(line - before, 1);\n const endLine = Math.min(line + after, lines.length);\n\n return {\n line,\n name: null,\n code: lines.slice(startLine - 1, endLine).join('\\n'),\n source: fileName,\n column: column,\n endLine,\n startLine,\n sourceRoot: null,\n sourceIndex: -1,\n generatedLine: -1,\n generatedColumn: -1\n };\n }\n } as SourceService;\n}\n\n/**\n * Brings an error and an esbuild message to the same shape - a name, a message, and a list of frames.\n *\n * @param raw - Thrown error, or the message esbuild reported for a failed build\n * @returns The parsed trace, with an empty frame list when there is nothing to point at\n *\n * @remarks\n * An `Error` is parsed from its own stack text, whether it arrives on its own or wrapped as the `detail` of an\n * esbuild message.\n * A plain esbuild message carries no stack, so its location becomes the single frame of the trace, flagged as\n * ordinary code: not eval, not async, not native, and not a constructor call.\n * A message without a location resolves to no frames at all, which leaves the caller with the text alone.\n *\n * @example\n * ```ts\n * getErrorStack(new Error('boom')).stack.length; // 12 - frames parsed from error.stack\n *\n * getErrorStack({ text: 'Unexpected token', location: { file: 'src/index.ts', line: 4, column: 2 } }).stack;\n * // [ { source: '@src/index.ts', fileName: 'src/index.ts', line: 4, column: 2, ... } ]\n *\n * getErrorStack({ text: 'Could not resolve module' }).stack; // []\n * ```\n *\n * @see parseErrorStack\n * @see ParsedStackTraceInterface\n *\n * @since 2.0.0\n */\n\nexport function getErrorStack(raw: Partial<PartialMessage> | Error): ParsedStackTraceInterface {\n if (raw instanceof Error) return parseErrorStack(raw);\n if (raw.detail instanceof Error) return parseErrorStack(raw.detail);\n\n if (!raw.location) {\n return { stack: [], name: 'esBuildMessage', message: raw.text ?? '', rawStack: '' };\n }\n\n return {\n name: 'esBuildMessage',\n message: raw.text ?? '',\n rawStack: '',\n stack: [\n {\n source: `@${ raw.location.file }`,\n line: raw.location.line,\n column: raw.location.column || 1,\n fileName: raw.location.file,\n eval: false,\n async: false,\n native: false,\n constructor: false\n }\n ]\n };\n}\n\n/**\n * Resolves an error back to its authored sources and picks the code window to print with it.\n *\n * @param raw - Thrown error, or the message esbuild reported for a failed build\n * @param options - Frame selection and code window size, as {@link resolveError} takes them\n * @param verbose - Whether native frames stay in the resolved stack\n * @returns The resolved trace, carrying `formatCode` when a frame supplied a code window\n *\n * @remarks\n * Every frame resolves through {@link getSource}, so a mapped frame points at the authored file and an unmapped\n * one falls back to the cached text of the emitted file.\n * `verbose` and `withFrameworkFrames` each admit native frames to the stack, while `withFrameworkFrames` alone\n * decides whether a framework frame may supply the code window.\n * The window is taken from the first frame that carries code, highlighted and marked at that position, and is\n * left unset when no frame carries any - a resolve against sources that are gone prints as a bare trace.\n *\n * @example\n * ```ts\n * const metadata = getErrorMetadata(error, { linesBefore: 2, linesAfter: 2 });\n * metadata.stack[0].format; // 'at run src/index.ts:12:8'\n * metadata.formatCode; // lines 10-14, highlighted, with column 8 marked in bright pink\n * ```\n *\n * @see resolveError\n * @see getErrorStack\n * @see StackTraceInterface\n * @see ResolveMetadataInterface\n *\n * @since 3.0.0\n */\n\nexport function getErrorMetadata(raw: PartialMessage | Error, options?: StackTraceInterface, verbose: boolean = false): ResolveMetadataInterface {\n const framework = inject(FrameworkService);\n const parsed = getErrorStack(raw);\n const resolved: ResolveMetadataInterface = resolveError(parsed, {\n ...options,\n withNativeFrames: verbose || (options?.withFrameworkFrames ?? false),\n getSource(path: string): SourceService | null {\n return getSource(path);\n }\n });\n\n resolved.stack.filter(frame => {\n if (!(options?.withFrameworkFrames ?? false) && framework.isFrameworkFile(frame)) return false;\n if(!resolved.formatCode && frame.code) {\n resolved.formatCode = formatErrorCode(\n {\n code: highlightCode(frame.code),\n line: frame.line ?? 1,\n column: frame.column ?? 1,\n startLine: frame.stratLine ?? 1\n },\n { color: xterm.brightPink }\n );\n }\n });\n\n return resolved;\n}\n\n/**\n * Renders resolved metadata as the block that gets printed to the terminal.\n *\n * @param metadata - Resolved trace, as {@link getErrorMetadata} returns it\n * @param name - Name to head the block with, such as `TypeError` or `esBuildMessage`\n * @param message - Message to head the block with\n * @param notes - Extra lines esbuild attached to the message, printed in gray under the heading\n * @returns The block, ready to write as-is\n *\n * @remarks\n * The heading is always written, the code window and the trace only when the metadata holds them, so an error\n * resolved against missing sources still prints as a single readable line.\n * Coloring of the window and of each frame is left as {@link getErrorMetadata} produced it - nothing here is\n * highlighted a second time.\n *\n * @example\n * ```ts\n * formatStack(metadata, 'TypeError', 'x is not a function');\n * //\n * // TypeError: x is not a function\n * //\n * // 11 | x();\n * // | ^\n * //\n * // Enhanced Stack Trace:\n * // at run src/index.ts:11:2\n * ```\n *\n * @see xterm\n * @see getErrorMetadata\n * @see ResolveMetadataInterface\n *\n * @since 2.0.0\n */\n\nexport function formatStack(metadata: ResolveMetadataInterface, name: string, message: string, notes: PartialMessage['notes'] = []): string {\n const parts = [ `\\n${ name }: ${ xterm.lightCoral(message) }` ];\n for (const note of notes ?? []) {\n if(note.text) parts.push('\\n ' + xterm.gray(note.text));\n }\n\n if (metadata.formatCode) parts.push(`\\n\\n${ metadata.formatCode }`);\n if (metadata.stack.length) {\n parts.push(`\\n\\nEnhanced Stack Trace:\\n ${ metadata.stack.map(stack => stack.format).join('\\n ') }\\n`);\n }\n\n return parts.join('');\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { Stats } from 'fs';\nimport type { TextChangeRange } from 'typescript';\nimport type { FileSnapshotInterface, ScriptSnapshotType } from './interfaces/files-model.interface';\n\n/**\n * Imports\n */\n\nimport { readFileSync, statSync } from 'fs';\nimport { resolve } from '@remotex-labs/xmap';\nimport { Injectable } from '@remotex-labs/xinject';\n\n/**\n * In-memory cache of file contents keyed by resolved absolute path.\n *\n * @remarks\n * Backs the TypeScript language service, which asks for a script version on every request and only reparses when\n * that version changes.\n * Content is read once and re-read only when the modification time moves,\n * so repeated lookups of an unchanged file cost a map read.\n * Reach for {@link touch} when any cached content will do,\n * {@link refresh} when the file may have changed on disk or when a watcher already carries its `Stats`,\n * and {@link refreshAll} to catch what the watcher failed to report.\n *\n * @example\n * ```ts\n * const model = inject(FilesModel);\n *\n * model.touch('src/index.ts').version; // 1 - read from disk\n * model.touch('src/index.ts').version; // 1 - served from the cache\n * model.refresh('src/index.ts').version; // 2 - the file changed on disk\n * model.clear(); // every entry dropped\n * ```\n *\n * @see FileSnapshotInterface\n * @since 2.0.0\n */\n\n@Injectable({\n scope: 'singleton'\n})\nexport class FilesModel {\n /**\n * Memoized mapping from an input path to its resolved absolute form.\n *\n * @remarks\n * Kept apart from {@link cache} because several input paths can resolve to the same absolute path,\n * and resolution is repeated far more often than content changes.\n *\n * @since 3.0.0\n */\n\n private readonly resolved = new Map<string, string>();\n\n /**\n * Entries keyed by resolved absolute path.\n *\n * @remarks\n * Holds one {@link FileSnapshotInterface} per tracked path, including paths that carry no readable file.\n *\n * @since 3.0.0\n */\n\n private readonly cache = new Map<string, FileSnapshotInterface>();\n\n /**\n * Drops every cached entry and every memoized path.\n *\n * @remarks\n * Leaves the model in its initial state, so the next request re-reads from disk and restarts versions at `1`.\n *\n * @example\n * ```ts\n * model.touch('src/index.ts');\n * model.clear();\n * model.getSnapshot('src/index.ts'); // undefined\n * ```\n *\n * @since 2.0.0\n */\n\n clear(): void {\n this.cache.clear();\n this.resolved.clear();\n }\n\n /**\n * Returns the cached entry for a path without touching the filesystem.\n *\n * @param path - Filesystem path, relative or absolute\n * @returns The cached entry, or `undefined` when the path was never tracked\n *\n * @remarks\n * A pure cache read: it never reads or stats the file, so an untracked path stays untracked.\n * Use {@link touch} to track the path instead.\n *\n * @example\n * ```ts\n * model.getSnapshot('src/index.ts'); // undefined - never tracked\n * model.touch('src/index.ts');\n * model.getSnapshot('src/index.ts'); // { mtimeMs: 1754000000000, version: 1, snapshot: { ... } }\n * ```\n *\n * @see touch\n * @since 2.0.0\n */\n\n getSnapshot(path: string): FileSnapshotInterface | undefined {\n return this.cache.get(this.resolve(path));\n }\n\n /**\n * Returns the entry for a path, reading the file when it is not tracked yet.\n *\n * @param path - Filesystem path, relative or absolute\n * @param encoding - Encoding used when the file is read, defaulting to `utf-8`\n * @returns The entry for the path, cached or newly created\n *\n * @remarks\n * A tracked path is returned as it stands, without a `stat` call, however stale it may be.\n * Use {@link refresh} when the file may have changed since it was cached.\n *\n * @example\n * ```ts\n * model.touch('src/index.ts').version; // 1 - read from disk\n * model.touch('src/index.ts').version; // 1 - served from the cache, no stat\n * ```\n *\n * @see refresh\n * @since 3.0.0\n */\n\n touch(path: string, encoding?: BufferEncoding): FileSnapshotInterface {\n const target = this.resolve(path);\n\n return this.cache.get(target) ?? this.sync(target, this.stat(target), encoding);\n }\n\n /**\n * Synchronizes a path with the filesystem and returns its entry.\n *\n * @param path - Filesystem path, relative or absolute\n * @param stats - Already obtained `Stats` for the path, sparing a `stat` call\n * @param encoding - Encoding used when the file is read, defaulting to `utf-8`\n * @returns The entry for the path, rebuilt only when the file actually changed\n *\n * @remarks\n * The content is re-read when the modification time differs from the cached one,\n * so calling this on an unchanged file leaves its version intact.\n * A path that is missing or is not a regular file yields an entry with an `undefined` snapshot.\n *\n * @example\n * ```ts\n * model.touch('src/index.ts').version; // 1\n * model.refresh('src/index.ts').version; // 1 - mtime unchanged\n * model.refresh('src/index.ts').version; // 2 - the file was written to\n * ```\n *\n * @see touch\n * @since 3.0.0\n */\n\n refresh(path: string, stats?: Stats, encoding?: BufferEncoding): FileSnapshotInterface {\n const target = this.resolve(path);\n\n return this.sync(target, stats ?? this.stat(target), encoding);\n }\n\n /**\n * Synchronizes a set of paths, or every path already tracked.\n *\n * @param paths - Paths to synchronize, defaulting to everything in the cache\n *\n * @remarks\n * The safety net under file watching: a change that goes unreported leaves an entry stale with nothing to\n * announce it - the version never moves,\n * so the language service is never told to reparse, and the build keeps compiling text that is no longer on disk.\n * Sweeping asks the filesystem rather than the watcher,\n * so a missed event costs a needless rebuild at worst rather than a wrong one.\n * Every path gets a `stat`, and only the ones whose time moved are read again.\n * The keys it walks are already resolved,\n * so re-synchronizing them writes back over the same keys and cannot extend the walk.\n * A tracked path that is still missing keeps the entry and the version it had,\n * so repeated sweeps do not inflate the versions of files that were deleted.\n *\n * @example\n * ```ts\n * model.refreshAll([ 'src/index.ts' ]); // that one path\n * model.refreshAll(); // every tracked path, re-read where it changed\n * ```\n *\n * @see refresh\n * @since 3.0.0\n */\n\n refreshAll(paths?: Array<string>): void {\n const pathList = paths ?? this.cache.keys();\n for (const path of pathList) {\n this.refresh(path);\n }\n }\n\n /**\n * Normalizes a path to its absolute form.\n *\n * @param path - Filesystem path, relative or absolute\n * @returns Absolute path with forward slashes\n *\n * @remarks\n * The result is memoized per input string, since the same paths are resolved on every cache lookup.\n *\n * @example\n * ```ts\n * model.resolve('src/index.ts'); // 'D:/project/src/index.ts'\n * ```\n *\n * @since 2.0.0\n */\n\n resolve(path: string): string {\n let target = this.resolved.get(path);\n if (target === undefined) this.resolved.set(path, target = resolve(path));\n\n return target;\n }\n\n /**\n * Brings the entry for a resolved path in line with the given filesystem state.\n *\n * @param target - Resolved absolute path\n * @param info - `Stats` for the path, or `undefined` when it does not exist\n * @param encoding - Encoding used when the file is read, defaulting to `utf-8`\n * @returns The entry for the path, reused when nothing changed\n *\n * @remarks\n * A path that is not a regular file keeps its already empty entry untouched,\n * so repeated events for a missing path do not inflate its version.\n * A file whose modification time matches the cached one is left as is, and the content is not read.\n *\n * @since 3.0.0\n */\n\n private sync(target: string, info: Stats | undefined, encoding: BufferEncoding = 'utf-8'): FileSnapshotInterface {\n const entry = this.cache.get(target);\n\n if (!info?.isFile()) {\n if (entry && !entry.snapshot) return entry;\n\n return this.store(target, { mtimeMs: 0, snapshot: undefined, version: (entry?.version ?? 0) + 1 });\n }\n\n if (entry?.mtimeMs === info.mtimeMs) return entry;\n\n return this.store(target, {\n mtimeMs: info.mtimeMs,\n version: (entry?.version ?? 0) + 1,\n snapshot: this.snapshot(readFileSync(target, encoding))\n });\n }\n\n /**\n * Computes the span that differs between two versions of a text.\n *\n * @param oldText - Text the language service last parsed\n * @param newText - Text that replaces it\n * @returns The replaced span in `oldText` together with the length of its replacement\n *\n * @remarks\n * Narrows the change by trimming the shared prefix and the shared suffix,\n * which lets the language service reuse the untouched parts of the syntax tree.\n * The suffix scan stops at the prefix boundary, so the two never overlap on a text that shrank.\n *\n * @since 3.0.0\n */\n\n private changeRange(oldText: string, newText: string): TextChangeRange {\n const oldLength = oldText.length;\n const newLength = newText.length;\n const max = Math.min(oldLength, newLength);\n\n let prefix = 0;\n while (prefix < max && oldText.charCodeAt(prefix) === newText.charCodeAt(prefix)) prefix++;\n\n let suffix = 0;\n while (suffix < max - prefix && oldText.charCodeAt(oldLength - 1 - suffix) === newText.charCodeAt(newLength - 1 - suffix)) suffix++;\n\n return {\n span: { start: prefix, length: oldLength - prefix - suffix },\n newLength: newLength - prefix - suffix\n };\n }\n\n /**\n * Wraps file content in a script snapshot.\n *\n * @param text - Content read from disk\n * @returns A snapshot exposing the content both as `text` and through the `IScriptSnapshot` methods\n *\n * @remarks\n * `getChangeRange` closes over this text as the new version and delegates to {@link changeRange},\n * so the language service can diff against any earlier snapshot it still holds.\n *\n * @since 3.0.0\n */\n\n private snapshot(text: string): ScriptSnapshotType {\n return {\n text,\n getText: (start, end): string => text.slice(start, end),\n getLength: (): number => text.length,\n getChangeRange: (previous):\n TextChangeRange => this.changeRange(previous.getText(0, previous.getLength()), text)\n };\n }\n\n /**\n * Writes an entry to the cache and hands it back.\n *\n * @param target - Resolved absolute path\n * @param entry - Entry to store under that path\n * @returns The stored entry\n *\n * @remarks\n * Exists so {@link sync} can store and return in a single expression.\n *\n * @since 3.0.0\n */\n\n private store(target: string, entry: FileSnapshotInterface): FileSnapshotInterface {\n this.cache.set(target, entry);\n\n return entry;\n }\n\n /**\n * Reads the filesystem state of a path.\n *\n * @param path - Resolved absolute path\n * @returns The `Stats` for the path, or `undefined` when it does not exist\n *\n * @remarks\n * A missing path is an ordinary outcome here rather than a failure, so the throwing form is disabled.\n *\n * @since 3.0.0\n */\n\n private stat(path: string): Stats | undefined {\n return statSync(path, { throwIfNoEntry: false });\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { PositionInterface, FormatStackFrameInterface } from '@remotex-labs/xmap';\n\n/**\n * Imports\n */\n\nimport { cwd } from 'process';\nimport { readFileSync } from 'fs';\nimport { FilesModel } from '@models/files.model';\nimport { inject, Injectable } from '@remotex-labs/xinject';\nimport { normalize, SourceService } from '@remotex-labs/xmap';\n\n/**\n * Matches a path that belongs to the framework rather than to the project being built.\n *\n * @remarks\n * Case-insensitive, since the same file surfaces as `xBuild` from a checkout and as `xbuild` from `node_modules`.\n * The lookahead spares a project's own `xbuild.config`, which names the framework without being part of it.\n *\n * @since 3.0.0\n */\n\nconst FRAMEWORK_PATH_REGEX = /xbuild(?!\\.config)/i;\n\n/**\n * Matches a source map whose `mappings` field is empty.\n *\n * @remarks\n * Such a map resolves nothing,\n * so keeping it would cost a lookup on every frame and answer with the generated position anyway.\n * Kept at module level so the pattern is compiled once rather than on every registration.\n *\n * @since 3.0.0\n */\n\nconst EMPTY_MAPPINGS_REGEX = /\"mappings\"\\s*:\\s*\"\"/;\n\n/**\n * Holds the framework's own paths and the source maps a stack trace is resolved through.\n *\n * @remarks\n * Two jobs in service of one thing - reporting an error against the source a reader recognizes.\n * It tells framework frames apart from a project's own,\n * and it hands out the {@link SourceService} that maps a generated position back to its source.\n * Maps arrive either as text through {@link addSourceMap} or read from a `.map` companion through\n * {@link loadSourceMap}, and both are keyed by resolved path, so the same file registered under a relative and an\n * absolute path is parsed once.\n * The framework's own map is loaded on construction, which is what lets an error thrown inside the build be reported\n * against its source.\n * Registered as a singleton, so every consumer shares one registry.\n *\n * @example\n * ```ts\n * const framework = inject(FrameworkService);\n *\n * framework.projectRoot; // 'D:/app' - where the build was started\n * framework.getSourceMap(framework.frameworkFile); // the framework's own SourceService\n * framework.isFrameworkFile({ source: 'D:/app/src/index.ts' }); // false - a project file\n * ```\n *\n * @see SourceService\n * @since 2.0.0\n */\n\n@Injectable({\n scope: 'singleton'\n})\nexport class FrameworkService {\n /**\n * Absolute path of the framework file this service was loaded from.\n *\n * @remarks\n * Normalized like {@link frameworkRoot} and {@link projectRoot},\n * so all three compare and join the same way whatever the platform.\n *\n * @example\n * ```ts\n * framework.frameworkFile; // 'D:/app/node_modules/@remotex-labs/xbuild/dist/index.js'\n * ```\n *\n * @since 3.0.0\n */\n\n readonly frameworkFile: string;\n\n /**\n * Absolute path of the directory the framework was distributed in.\n *\n * @remarks\n * Where anything shipped beside the build is found, the server's certificates among them.\n *\n * @example\n * ```ts\n * framework.frameworkRoot; // 'D:/app/node_modules/@remotex-labs/xbuild/dist'\n * ```\n *\n * @since 3.0.0\n */\n\n readonly frameworkRoot: string;\n\n /**\n * Absolute path of the directory the build was started from.\n *\n * @remarks\n * The user's project root rather than the framework's,\n * so it is what a path is made relative to when a frame is printed.\n *\n * @example\n * ```ts\n * framework.projectRoot; // 'D:/app'\n * ```\n *\n * @since 3.0.0\n */\n\n readonly projectRoot: string;\n\n /**\n * Shared file cache, held on the class so {@link resolve} needs no instance.\n *\n * @remarks\n * What is wanted here is the memo it keeps rather than the snapshots: resolving through it is what keeps this\n * registry, the file cache, and everything else keyed by path agreeing on what one path is.\n * Claimed by the first {@link resolve} rather than by a static initializer, since an initializer would run while\n * this module is being imported, and importing it must not reach the container.\n *\n * @see FilesModel\n * @since 3.0.0\n */\n\n private static files?: FilesModel;\n\n /**\n * Source maps keyed by the resolved path of the file each one describes.\n *\n * @since 2.0.0\n */\n\n private readonly sourceMaps = new Map<string, SourceService>();\n\n /**\n * Captures the framework's paths and loads its own source map.\n *\n * @throws Error - When the framework ships without a readable `.map` companion\n *\n * @remarks\n * A framework shipped without its map is a broken build rather than a supported one,\n * so the read failure surfaces here instead of being swallowed.\n *\n * @example\n * ```ts\n * const framework = new FrameworkService();\n * framework.getSourceMap(framework.frameworkFile); // SourceService\n * ```\n *\n * @see loadSourceMap\n * @since 2.0.0\n */\n\n constructor() {\n this.projectRoot = normalize(cwd());\n this.frameworkFile = normalize(import.meta.filename);\n this.frameworkRoot = normalize(import.meta.dirname);\n\n this.loadSourceMap(this.frameworkFile);\n }\n\n /**\n * Normalizes a path to the absolute form every cache here is keyed by.\n *\n * @param path - Filesystem path, relative or absolute\n * @returns Absolute path with forward slashes\n *\n * @remarks\n * Static so that a caller with no framework service in hand can still key a path the way this package does, which\n * is what keeps entry-point names, source-map keys, and file entries from disagreeing about one file.\n * The first call claims the file cache, and every later call finds it already claimed, so the container is reached\n * only once something asks for a path rather than when this module is imported.\n * Resolution is memoized by the cache behind it, so resolving the same path again costs a lookup.\n *\n * @example\n * ```ts\n * FrameworkService.resolve('src/index.ts'); // 'D:/app/src/index.ts'\n * ```\n *\n * @see FilesModel\n * @since 3.0.0\n */\n\n static resolve(path: string): string {\n return (FrameworkService.files ??= inject(FilesModel)).resolve(path);\n }\n\n /**\n * Reports whether a position belongs to the framework rather than to the project being built.\n *\n * @param position - Position or stack frame to judge, as the source map resolver reports it\n * @returns `true` when the position comes from framework code\n *\n * @remarks\n * The judgment is made on the path, matched case-insensitively, since the same file surfaces as `xBuild` from a\n * checkout and as `xbuild` from `node_modules`.\n * A project's own `xbuild.config` names the framework without being part of it, so it is excluded by name.\n * The source root is consulted only when the source itself does not settle the question.\n *\n * @example\n * ```ts\n * framework.isFrameworkFile({ source: 'D:/app/node_modules/xbuild/dist/index.js' }); // true\n * framework.isFrameworkFile({ source: 'D:/app/xbuild.config.ts' }); // false\n * framework.isFrameworkFile({ source: 'D:/app/src/index.ts' }); // false\n * ```\n *\n * @see PositionInterface\n * @see FormatStackFrameInterface\n *\n * @since 2.2.5\n */\n\n isFrameworkFile(position: PositionInterface | FormatStackFrameInterface): boolean {\n return FRAMEWORK_PATH_REGEX.test(position.source ?? '') || FRAMEWORK_PATH_REGEX.test(position.sourceRoot ?? '');\n }\n\n /**\n * Returns the source map registered for a file.\n *\n * @param path - Path of the file, relative or absolute\n * @returns The source map of that file, or `undefined` when none was registered\n *\n * @remarks\n * A pure registry read: a file that was never registered stays unregistered, since nothing here reaches the disk.\n * Use {@link loadSourceMap} to register one.\n *\n * @example\n * ```ts\n * framework.getSourceMap('dist/index.js'); // undefined - never registered\n * framework.loadSourceMap('dist/index.js');\n * framework.getSourceMap('dist/index.js'); // SourceService\n * ```\n *\n * @see SourceService\n * @since 2.0.0\n */\n\n getSourceMap(path: string): SourceService | undefined {\n return this.sourceMaps.get(FrameworkService.resolve(path));\n }\n\n /**\n * Registers a source map from its text.\n *\n * @param path - Path of the file the map describes, relative or absolute\n * @param source - Raw source map content\n * @param force - Whether a map the file already carries is replaced rather than kept\n *\n * @throws Error - When the content is not a source map the resolver can parse\n *\n * @remarks\n * A file that already carries a map keeps it, so the first registration wins, and a later call costs only a lookup.\n * A caller that knows the file was written again says so with `force`, which parses the map it was handed and puts\n * it in place of the one registered before: a watch rebuilding a file leaves the map registered for it describing\n * text that is no longer there, and a stale map resolves a frame to the wrong line rather than to none.\n * A map with empty mappings is dropped rather than registered, resolving through such a map being the same as not\n * resolving at all, and it leaves what was registered before it in place rather than clearing it.\n *\n * @example\n * ```ts\n * framework.addSourceMap('dist/index.js', readFileSync('dist/index.js.map', 'utf-8'));\n * framework.getSourceMap('dist/index.js'); // SourceService\n *\n * framework.addSourceMap('dist/index.js', rebuilt); // kept - the first registration wins\n * framework.addSourceMap('dist/index.js', rebuilt, true); // replaced - the file was written again\n * ```\n *\n * @see loadSourceMap\n * @since 3.0.0\n */\n\n addSourceMap(path: string, source: string, force: boolean = false): void {\n const key = FrameworkService.resolve(path);\n if (!force && this.sourceMaps.has(key)) return;\n\n this.register(key, source);\n }\n\n /**\n * Registers the source map a file's `.map` companion carries.\n *\n * @param path - Path of the generated file, relative or absolute\n *\n * @throws Error - When the companion cannot be read or does not parse\n *\n * @remarks\n * The companion is looked for beside the file, as `<path>.map`, which is where every file this toolchain emits\n * carries its map.\n * A file that already carries a map is left alone before the disk is touched,\n * so repeating the call on a tracked file costs only a lookup.\n * An empty path is ignored outright,\n * and a companion that parses but maps nothing registers no map and raises nothing.\n *\n * @example\n * ```ts\n * framework.loadSourceMap('dist/index.js'); // reads dist/index.js.map\n * framework.loadSourceMap('dist/index.js'); // cached - no read\n * ```\n *\n * @see addSourceMap\n * @since 3.0.0\n */\n\n loadSourceMap(path: string): void {\n if (!path) return;\n\n const key = FrameworkService.resolve(path);\n if (this.sourceMaps.has(key)) return;\n\n let source: string;\n try {\n source = readFileSync(`${ key }.map`, 'utf-8');\n } catch (error) {\n throw FrameworkService.failure(key, error);\n }\n\n this.register(key, source);\n }\n\n /**\n * Builds the error reported when a source map cannot be registered.\n *\n * @param key - Resolved path of the file the map describes\n * @param error - Failure raised while reading or parsing it\n * @returns The error to throw, naming the file and carrying the original reason\n *\n * @remarks\n * The reading and the parsing halves fail in the same way as far as a caller is concerned,\n * so both report the file first and the reason after it.\n *\n * @since 3.0.0\n */\n\n private static failure(key: string, error: unknown): Error {\n return new Error(\n `Failed to load source map for: ${ key }\\n${ error instanceof Error ? error.message : String(error) }`\n );\n }\n\n /**\n * Parses a source map and files it under a resolved path.\n *\n * @param key - Resolved path of the file the map describes\n * @param source - Raw source map content\n *\n * @throws Error - When the content is not a source map the resolver can parse\n *\n * @remarks\n * The single point where a map enters the registry,\n * so both entry points resolve their path once and skip an already registered file before reaching here.\n * A map with empty mappings is dropped rather than registered, since resolving through such a map answers with\n * the position it was given.\n *\n * @since 3.0.0\n */\n\n private register(key: string, source: string): void {\n if (EMPTY_MAPPINGS_REGEX.test(source)) return;\n\n try {\n this.sourceMaps.set(key, new SourceService(source, key));\n } catch (error) {\n throw FrameworkService.failure(key, error);\n }\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { StackTraceInterface, ResolveMetadataInterface } from '@providers/interfaces/stack-provider.interface';\n\n/**\n * Imports\n */\n\nimport { formatStack, getErrorMetadata } from '@providers/stack.provider';\n\n/**\n * Base class for errors that print as authored code rather than as the stack of the emitted bundle.\n *\n * @remarks\n * A subclass gets nothing extra until it calls {@link reformatStack}, which resolves the captured stack through the\n * source maps and keeps both the frames as data and the block to print.\n * Node writes that block whenever the error reaches the console, so a caught error names the original file and line\n * and carries a highlighted snippet of the surrounding code.\n * Extend this class when callers need an error type of their own to branch on.\n * Throw {@link xBuildError} when a general framework error will do.\n *\n * @example\n * ```ts\n * class ValidationError extends xBuildBaseError {\n * constructor(message: string) {\n * super(message, 'ValidationError');\n * this.reformatStack(this, { withFrameworkFrames: false });\n * }\n * }\n *\n * const error = new ValidationError('email is not an address');\n * error.metadata?.stack[0].format; // 'at validate src/validator.ts:15:3'\n * console.error(error); // the heading, the snippet, and the resolved trace\n * ```\n *\n * @see formatStack\n * @see xBuildError\n * @see getErrorMetadata\n * @see StackTraceInterface\n * @see ResolveMetadataInterface\n *\n * @since 2.0.0\n */\n\nexport abstract class xBuildBaseError extends Error {\n /**\n * Resolved stack metadata, as {@link getErrorMetadata} produced it.\n *\n * @remarks\n * Undefined until {@link reformatStack} runs, and replaced whole by every later call.\n * Reachable read-only through {@link metadata} for callers that want the frames as data rather than as text.\n *\n * @see ResolveMetadataInterface\n * @since 2.0.0\n */\n\n protected errorMetadata: ResolveMetadataInterface | undefined;\n\n /**\n * The block to print for this error, as {@link formatStack} produced it.\n *\n * @remarks\n * Undefined until {@link reformatStack} runs, which leaves the native stack as the only thing to print.\n * Coloring and highlighting are already applied, so the string is written out as it stands.\n *\n * @see formatStack\n * @since 2.0.0\n */\n\n protected formattedStack: string | undefined;\n\n /**\n * Creates the error and captures its raw stack, leaving the resolving to the subclass.\n *\n * @param message - Message describing what went wrong\n * @param name - Name the error reports itself under\n *\n * @remarks\n * The prototype is restored from `new.target`, so `instanceof` answers for the subclass and not only for `Error`,\n * which a transpiled subclass would otherwise lose.\n * The captured stack starts at the caller rather than inside this constructor, and stays the raw one until the\n * subclass calls {@link reformatStack} - passing a name here only heads the block, it resolves nothing.\n *\n * @since 2.0.0\n */\n\n protected constructor(message: string, name: string = 'xBuildBaseError') {\n super(message);\n\n // Ensure a correct prototype chain (important for `instanceof`)\n Object.setPrototypeOf(this, new.target.prototype);\n this.name = name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n /**\n * The resolved stack metadata of this error.\n *\n * @returns The metadata, or `undefined` when {@link reformatStack} has not run\n *\n * @remarks\n * The frames as data, for a logger or a reporting service that renders them itself instead of printing the block.\n *\n * @example\n * ```ts\n * error.metadata; // undefined - the subclass never reformatted\n * error.metadata?.stack.length; // 4 - after reformatStack\n * error.metadata?.formatCode; // the highlighted snippet, when a frame carried code\n * ```\n *\n * @see ResolveMetadataInterface\n * @since 2.0.0\n */\n\n get metadata(): ResolveMetadataInterface | undefined {\n return this.errorMetadata;\n }\n\n /**\n * Renders the error for `console.log`, `console.error` and `util.inspect`.\n *\n * @returns The resolved block when there is one, and the native stack otherwise\n *\n * @remarks\n * Node calls this in place of printing the error's own fields, which is what puts the resolved trace on the\n * terminal without the caller having to format anything.\n * An empty block counts as no block, so an error whose sources could not be resolved still prints its native\n * stack rather than nothing.\n *\n * @example\n * ```ts\n * console.error(error); // 'ValidationError: email is not an address', the snippet, and the resolved trace\n * ```\n *\n * @see {@link https://nodejs.org/api/util.html#custom-inspection-functions-on-objects | Custom inspection}\n * @since 2.0.0\n */\n\n [Symbol.for('nodejs.util.inspect.custom')](): string | undefined {\n return this.formattedStack || this.stack;\n }\n\n /**\n * Resolves an error's stack against its sources and keeps both the metadata and the block to print.\n *\n * @param error - Error to resolve, usually `this`\n * @param options - Frame selection and code window size\n *\n * @remarks\n * Call it from the subclass constructor, after the name and the message are in place, since both are read off\n * the error to head the block with.\n * The error need not be `this` - a wrapper passes the cause it carries to report the trace of the failure that\n * actually happened.\n * Calling it again replaces both fields, so resolving a second time under different options is safe.\n *\n * @see formatStack\n * @see getErrorMetadata\n * @see StackTraceInterface\n *\n * @since 2.0.0\n */\n\n protected reformatStack(error: Error, options?: StackTraceInterface): void {\n this.errorMetadata = getErrorMetadata(error, options);\n this.formattedStack = formatStack(this.errorMetadata, error.name, error.message);\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { ServerEventsType } from '@server/interfaces/server.interface';\nimport type { LogLevelType } from '@providers/interfaces/log-provider.interface';\nimport type { LifecycleEventsType, LifecycleLogsType } from '@interfaces/lifecycle.interface';\n\n/**\n * Imports\n */\n\nimport { exit } from 'process';\nimport { setActivity } from '@ui/interactive.ui';\nimport { Injectable, inject } from '@remotex-labs/xinject';\nimport { ConfigurationService } from '@services/configuration.service';\nimport { TypescriptService } from '@typescript/services/typescript.service';\nimport { clearScreen, createActionPrefix, printGroup, printOutputs } from '@ui/print.ui';\nimport { keywordColor, mutedColor, warnColor, errorColor, infoColor, okColor, pathColor } from '@ui/color.ui';\nimport { WarningSymbol, ErrorSymbol, DotSymbol, ArrowSymbol, ReloadSymbol, SuccessSymbol, Levels } from '@constants/ui.constant';\n\n/**\n * Turns what a run reports into what a terminal shows.\n *\n * @remarks\n * Every event of a run arrives here: a build starting and ending, a server answering, a check reporting.\n * Each one becomes a printed line, the groups of messages under it, and a word on the status line,\n * so the scrollback carries the whole run while the bar carries only what is happening now.\n * A singleton, since a run has one terminal and the level it reports at is read from every corner of it.\n *\n * @example\n * ```ts\n * const screen = inject(Screen, () => build.build());\n * build.subscribe(screen.buildEvent.bind(screen));\n *\n * screen.toggleVerbose(); // 'verbose' - and the bar says so\n * ```\n *\n * @see LifecycleEventsType\n * @since 3.0.0\n */\n\n@Injectable({\n scope: 'singleton'\n})\nexport class Screen {\n /**\n * The configuration service the reporting level is read and written through.\n *\n * @remarks\n * The injected instance rather than one of its own,\n * so a level a key changes here is the level every other reader of the configuration sees.\n *\n * @example\n * ```ts\n * screen.config$.getValue().logLevel; // 'info'\n * ```\n *\n * @see ConfigurationService\n * @since 3.0.0\n */\n\n readonly config$ = inject(ConfigurationService);\n\n /**\n * The address a running server answers on, absent while none is running.\n *\n * @remarks\n * Written as the server reports its start and cleared as it stops,\n * so the status line offers a URL only while there is one to open.\n *\n * @since 3.0.0\n */\n\n private serverUrl?: string;\n\n /**\n * The level to go back to once reporting is turned down again.\n *\n * @remarks\n * Held so that turning `verbose` off restores the level the run was started at rather than a default,\n * which is what makes the toggle reversible for a run started at `error`.\n *\n * @since 3.0.0\n */\n\n private restoreLevel: LogLevelType;\n\n /**\n * Takes the build a key or a watch asks for, and settles the level to fall back to.\n *\n * @param build - What to run when a rebuild is asked for\n *\n * @remarks\n * The build arrives as a callback rather than as a service,\n * so the screen starts a run without knowing what a run is made of.\n * A run already started at `verbose` has no quieter level to remember, so `info` stands in as the one to return to.\n *\n * @example\n * ```ts\n * const screen = inject(Screen, runBuild); // runBuild is what a key or a watch will call\n * ```\n *\n * @since 3.0.0\n */\n\n constructor(private readonly build: () => Promise<void>) {\n this.restoreLevel = this.logLevel !== 'verbose' ? this.logLevel : 'info';\n }\n\n /**\n * Sets the level the run reports at.\n *\n * @param value - Level to report at from now on\n *\n * @remarks\n * Written through the configuration rather than held here,\n * so a variant reading the level for its own messages and the screen reading it for its groups agree.\n *\n * @example\n * ```ts\n * screen.logLevel = 'warning'; // info and verbose stop printing\n * ```\n *\n * @see LogLevelType\n * @since 3.0.0\n */\n\n set logLevel(value: LogLevelType) {\n this.config$.patch({ logLevel: value });\n }\n\n /**\n * The level the run is reporting at.\n *\n * @returns The configured level, `info` where the configuration names none\n *\n * @example\n * ```ts\n * screen.logLevel; // 'info'\n * ```\n *\n * @see LogLevelType\n * @since 3.0.0\n */\n\n get logLevel(): LogLevelType {\n return this.config$.getValue().logLevel ?? 'info';\n }\n\n /**\n * The address the running server answers on.\n *\n * @returns The URL, empty while no server is running\n *\n * @remarks\n * Empty rather than absent, so a caller writing it into a line needs no guard of its own.\n *\n * @example\n * ```ts\n * screen.url; // 'http://localhost:3000'\n * ```\n *\n * @since 3.0.0\n */\n\n get url(): string {\n return this.serverUrl ?? '';\n }\n\n /**\n * Records the address a server has begun answering on.\n *\n * @param value - URL the server bound to\n *\n * @example\n * ```ts\n * screen.url = 'http://localhost:3000';\n * ```\n *\n * @since 3.0.0\n */\n\n set url(value: string) {\n this.serverUrl = value;\n }\n\n /**\n * Reports either end of a build: its start or its finish.\n *\n * @param event - What the variant reported, carrying its context and, at the end, its result\n *\n * @remarks\n * A start says which variant is building and no more, since nothing has been found out yet.\n * An end prints the messages first and the outcome last,\n * so a reader scrolling up meets the verdict before its reasons.\n * A build that wrote no output is the failing case, whether it threw or only reported errors,\n * and it sets the exit code, which is what lets a pipeline read the run without reading its output.\n * Reporting at `verbose` lists every output rather than the largest few.\n *\n * @example\n * ```ts\n * build.subscribe(screen.buildEvent.bind(screen));\n * // [xBuild] → build esm\n * // [xBuild] ✓ esm in 128 ms\n * ```\n *\n * @see LifecycleEventsType\n * @since 3.0.0\n */\n\n buildEvent(event: LifecycleEventsType): void {\n if (event.type === 'start')\n return this.say(`${ infoColor.dim(ArrowSymbol) } ${ mutedColor('building') } ${ keywordColor(event.context.variantName) }`,\n `${ createActionPrefix('build') } ${ keywordColor(event.context.variantName) }`);\n\n const { errors, warnings, info, verbose: notes, metafile } = event.buildResult;\n const failed = !metafile;\n if (failed) process.exitCode = 1;\n else process.exitCode = 0;\n\n this.groups({ error: errors, warning: warnings, info, verbose: notes });\n if (metafile) printOutputs(metafile, this.logLevel === 'verbose' ? Infinity : undefined);\n\n const symbol = failed ? errorColor(ErrorSymbol) : okColor(SuccessSymbol);\n const name = failed ? warnColor(event.context.variantName) : keywordColor(event.context.variantName);\n\n this.say(`${ symbol } ${ name } ${ mutedColor.dim(`in ${ event.duration } ms`) }`,\n `\\n${ createActionPrefix('build', symbol) } ${ name } ${ mutedColor.dim(`in ${ event.duration } ms`) }`);\n }\n\n /**\n * Reports what the development server is doing.\n *\n * @param event - What the server reported: its start, its stop, a request, or a failure\n *\n * @remarks\n * A start is where the address comes from, and a stop is what takes it away again,\n * so the status line offers the URL for exactly as long as something answers on it.\n * A stop is reported only where a server was running, since a stop is worth a line only where something was answering.\n * Requests are reported only at `verbose`, one line being worth little against a page that fetches thirty files.\n * A failed `favicon.ico` is dropped whatever the level, since browsers ask for one unprompted on every visit.\n *\n * @example\n * ```ts\n * server.subscribe(screen.serverEvent.bind(screen));\n * // [xBuild] → serve http://localhost:3000\n * ```\n *\n * @see ServerEventsType\n * @since 3.0.0\n */\n\n serverEvent(event: ServerEventsType): void {\n switch (event.type) {\n case 'start':\n this.url = event.url;\n\n return console.log(`${ createActionPrefix('serve') } ${ pathColor(event.url) }`);\n case 'stop':\n this.serverUrl = undefined;\n if (event.running) console.log(`${ createActionPrefix('serve') } ${ mutedColor('stopped') }`);\n\n return;\n case 'request':\n if (this.logLevel === 'verbose')\n console.log(`${ createActionPrefix('serve') } ${ mutedColor.dim(event.url) }`);\n\n return;\n case 'error':\n if (event.url?.includes('favicon')) return;\n console.log(\n `${ createActionPrefix('serve', errorColor(ErrorSymbol)) } ${ mutedColor(event.error.message) }`\n );\n }\n }\n\n /**\n * Reports a type check and ends the process on what it found.\n *\n * @param diagnostics - Messages each variant's check reported, keyed by the variant's name\n *\n * @remarks\n * Every variant gets a heading carrying what it found, followed by its groups,\n * so a clean variant is still reported rather than left out of a run that named it.\n * The count is of everything the check reported rather than of what the level prints,\n * which is what keeps a quiet run from reading as a clean one.\n * The process leaves from here, and an error anywhere leaves with `1`,\n * since a check is the whole of what a run asking for one wanted.\n *\n * @example\n * ```ts\n * screen.diagnostics(await build.typeChack());\n * // [xBuild] → type-check esm 2 to look at\n * ```\n *\n * @see LifecycleLogsType\n * @since 3.0.0\n */\n\n diagnostics(diagnostics: Record<string, LifecycleLogsType>): void {\n let failed = false;\n\n for (const [ name, logs ] of Object.entries(diagnostics)) {\n const total = logs.error.length + logs.warning.length + logs.info.length + logs.verbose.length;\n\n failed ||= logs.error.length > 0;\n console.log(`${ createActionPrefix('type-check') } ${ keywordColor(name) } ${ mutedColor.dim(`${ total } to look at`) }`);\n this.groups(logs);\n console.log('');\n }\n\n exit(failed ? 1 : 0);\n }\n\n /**\n * Clears what the last build left, takes up any configuration change, says what asked for this build, and runs it.\n *\n * @param reason - What asked for the build, such as the files that changed or the key that was pressed\n * @param force - Whether every TypeScript project reparses its configuration even where its file has not moved\n *\n * @remarks\n * Every rebuild of a watch goes through here, so the screen is cleared and the run announced the same way\n * whichever asked for it.\n * The build itself is the one the run handed over when the screen was made.\n * The TypeScript configurations are reloaded here rather than by the watch,\n * so a rebuild started by a key reads them as freshly as one started by a changed file.\n * A configuration that has stayed put costs a lookup and nothing more.\n * Forcing reparses every project regardless, which is what the reload key asks for\n * and what catches a change the configuration file's own version misses.\n *\n * @example\n * ```ts\n * await screen.rebuild('2 files changed'); // [xBuild] rebuild 2 files changed\n * await screen.rebuild('reloading', true); // the same, with every tsconfig reparsed first\n * ```\n *\n * @see TypescriptService.reload\n * @since 3.0.0\n */\n\n async rebuild(reason: string, force: boolean = false): Promise<void> {\n clearScreen();\n TypescriptService.reload(force);\n\n this.say(`${ infoColor.dim(ReloadSymbol) } ${ mutedColor(reason) }`,\n `${ createActionPrefix('rebuild', infoColor.dim(ReloadSymbol)) } ${ mutedColor(reason) }`);\n\n await this.build();\n }\n\n /**\n * Turns reporting all the way up, or back to what it was before it was turned up.\n *\n * @returns The level the run now reports at\n *\n * @remarks\n * The level the run was set to is remembered rather than assumed,\n * so a run started at `error` goes back to `error` rather than to the default.\n * The level is written back through the configuration, so everything reading it follows in the same breath.\n *\n * @example\n * ```ts\n * screen.toggleVerbose(); // 'verbose'\n * screen.toggleVerbose(); // 'info' - what it was before\n * ```\n *\n * @since 3.0.0\n */\n\n toggleVerbose(): LogLevelType {\n if (this.logLevel === 'verbose') this.logLevel = this.restoreLevel;\n else {\n this.restoreLevel = this.logLevel;\n this.logLevel = 'verbose';\n }\n\n return this.logLevel;\n }\n\n /**\n * Writes a line to the scrollback and says the same thing on the status line.\n *\n * @param activity - What is happening, as the bar says it\n * @param line - The line printed to the scrollback\n *\n * @remarks\n * The two are worded apart rather than shared, since the bar carries no prefix and has one row to say it in,\n * while the printed line stands on its own long after the run has moved past it.\n *\n * @see setActivity\n * @since 3.0.0\n */\n\n private say(activity: string, line: string): void {\n console.log(line);\n setActivity(activity);\n }\n\n /**\n * Prints the message groups the current level allows.\n *\n * @param logs - Messages to print, filed under the level each was reported at\n *\n * @remarks\n * The groups run loudest first, so what failed a build is read before what merely remarked on it.\n * Each group is compared against the level the run is set to,\n * which is what leaves a quiet run its errors and drops everything under them.\n * An error always carries its code window and its trace, since that is what an error is read for,\n * while the quieter groups carry theirs only at `verbose`.\n *\n * @see Levels\n * @see printGroup\n *\n * @since 3.0.0\n */\n\n private groups(logs: LifecycleLogsType): void {\n const lowest = Levels[this.logLevel];\n const code = this.logLevel === 'verbose';\n\n if (Levels.error >= lowest) printGroup(logs.error, 'Errors', errorColor, ErrorSymbol, true);\n if (Levels.warning >= lowest) printGroup(logs.warning, 'Warnings', warnColor, WarningSymbol, code);\n if (Levels.info >= lowest) printGroup(logs.info, 'Info', infoColor, ArrowSymbol, code);\n if (Levels.verbose >= lowest) printGroup(logs.verbose, 'Verbose', mutedColor, DotSymbol, code);\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { Key } from 'readline';\nimport type { Screen } from '@ui/screen.ui';\n\n/**\n * Imports\n */\n\nimport { exec } from 'child_process';\nimport * as readline from 'node:readline';\nimport { clearScreen, width } from '@ui/print.ui';\nimport { platform, stdin, stdout, exit } from 'process';\nimport { xterm } from '@remotex-labs/xansi/xterm.component';\nimport { ANSI, moveCursor, writeRaw } from '@remotex-labs/xansi';\nimport { ShadowRenderer } from '@remotex-labs/xansi/shadow.service';\nimport { infoColor, keywordColor, mutedColor, pathColor } from '@ui/color.ui';\nimport { DotSymbol, Indent, MinimumRows, RepaintInterval, ReloadSymbol, ReportTimeout } from '@constants/ui.constant';\n\n/**\n * The command each platform opens a URL with.\n *\n * @remarks\n * Anything the table does not name falls back to the freedesktop opener, which is what every other Unix carries.\n *\n * @since 3.0.0\n */\n\nconst OpenCommands: Record<string, string> = { darwin: 'open', win32: 'start' };\n\n/**\n * What each key does, paired with the line the menu describes it by.\n *\n * @remarks\n * One table drives both the menu and the dispatch, so a key cannot be listed without an action or the other way round.\n * The key that opens a browser is listed only while a server is running, which is what `server` marks it by.\n *\n * @since 3.0.0\n */\n\nconst Keys = [\n { key: 'h', describe: 'show this menu', server: false },\n { key: 'b', describe: 'run the build', server: false },\n { key: 'r', describe: 'reload and rebuild', server: false },\n { key: 'v', describe: 'toggle verbose', server: false },\n { key: 'c', describe: 'clear the screen', server: false },\n { key: 'o', describe: 'open it in a browser', server: true },\n { key: 'q', describe: 'quit', server: false }\n] as const;\n\n/**\n * The screen the keys act on and the bar reads, absent while no watch is listening.\n *\n * @remarks\n * The settings a run is under live on the screen rather than here,\n * so a key that changes one and a report that reads it are looking at the same value.\n *\n * @since 3.0.0\n */\n\nlet session: Screen | undefined;\n\n/**\n * What the run is doing, as the bar says it, empty while the watch rests between builds.\n *\n * @since 3.0.0\n */\n\nlet activity = '';\n\n/**\n * The row the bar draws through, absent while the terminal has none to spare.\n *\n * @remarks\n * A viewport one row tall pinned to the foot of the terminal.\n * Its rows count from one, so the row it is offset by is the one above the last,\n * which is what puts its only row on the last one rather than a line past the bottom of the screen.\n * It holds what it drew, so redrawing writes only the cells that moved, and a line too long for the terminal is cut\n * to fit rather than wrapping onto the row above and breaking the region the report scrolls in.\n *\n * @see ShadowRenderer\n * @since 3.0.0\n */\n\nlet row: ShadowRenderer | undefined;\n\n/**\n * The beat the bar is painted on, absent while no watch holds a row.\n *\n * @since 3.0.0\n */\n\nlet repaint: NodeJS.Timeout | undefined;\n\n/**\n * The row the cursor sits on, as the terminal itself reports it.\n *\n * @returns The row, or the last one where the terminal did not answer\n *\n * @remarks\n * Where a run has printed to is the one thing it cannot know for itself, and it decides everything the row rests on:\n * a watch started on a screen already full leaves the cursor on the last row, which is the row the line is about\n * to take, and every line printed afterward would land under the line and be painted over rather than scrolled.\n * The terminal is asked outright, and it answers on the input the shortcuts have yet to claim,\n * so the reply is read before the keys are listened for rather than swallowed by them.\n * A terminal that does not answer is taken to be full, which is the safe half of the guess.\n *\n * @since 3.0.0\n */\n\nfunction cursorRow(): Promise<number> {\n return new Promise(resolve => {\n const answer = (data: Buffer): void => {\n const reported = /\\[(\\d+);\\d+R/.exec(data.toString());\n if (!reported) return;\n\n stdin.off('data', answer);\n resolve(Number(reported[1]));\n };\n\n stdin.on('data', answer);\n writeRaw('\\u001B[6n');\n setTimeout(() => (stdin.off('data', answer), resolve(stdout.rows)), ReportTimeout).unref();\n });\n}\n\n/**\n * Opens a URL in whatever the platform treats as the browser.\n *\n * @param url - Address to open\n *\n * @remarks\n * The command is spawned and left to itself, so a browser that takes its time does not hold the watch up,\n * and a platform without an opener fails silently rather than taking down the run with it.\n *\n * @example\n * ```ts\n * openInBrowser('http://localhost:3000');\n * ```\n *\n * @since 3.0.0\n */\n\nexport function openInBrowser(url: string): void {\n exec(`${ OpenCommands[platform] ?? 'xdg-open' } ${ url }`);\n}\n\n/**\n * Renders the menu of what the keys do.\n *\n * @returns The menu, ready to write\n *\n * @remarks\n * The key that opens a browser is listed only while a server is running, there being nothing to open otherwise.\n *\n * @example\n * ```ts\n * console.log(helpMenu());\n * // Shortcuts\n * // press h to show this menu\n * ```\n *\n * @since 3.0.0\n */\n\nexport function helpMenu(): string {\n const lines = [ `\\n🚀 ${ keywordColor('Shortcuts') }` ];\n for (const { key, describe, server } of Keys) {\n if (!server || session?.url)\n lines.push(`${ Indent }${ mutedColor.dim('press') } ${ xterm.bold(key) } ${ mutedColor.dim(`to ${ describe }`) }`);\n }\n\n return `${ lines.join('\\n') }\\n`;\n}\n\n/**\n * Draws the status line on the row it holds, leaving the cursor where it found it.\n *\n * @param force - Whether to paint every cell rather than the ones that moved\n *\n * @remarks\n * Only what changed is written, unless the caller asks for the whole row,\n * which is what the repainting beat asks for: a terminal cleared behind the run's back is not what the row\n * remembers drawing, so nothing would be found to differ and nothing would be written.\n * What the run is doing leads, and the rest reads left to right:\n * where the server is, whether it is reporting everything, and how to see the keys.\n *\n * @example\n * ```ts\n * drawStatusBar();\n * // PASS main in 134 ms · http://localhost:3000 · verbose · press h for shortcuts\n * ```\n *\n * @since 3.0.0\n */\n\nexport function drawStatusBar(force = false): void {\n if (!row) return;\n\n const parts = [ activity || `${ infoColor.dim(ReloadSymbol) } ${ mutedColor('watching') }` ];\n if (session?.url) parts.push(pathColor(session.url));\n if (session?.logLevel === 'verbose') parts.push(keywordColor('verbose'));\n parts.push(mutedColor.dim('press h for shortcuts'));\n\n writeRaw(ANSI.SAVE_CURSOR);\n row.writeText(0, 0, ` ${ parts.join(mutedColor.dim(` ${ DotSymbol } `)) }`, true);\n row.render(force);\n writeRaw(ANSI.RESTORE_CURSOR);\n}\n\n/**\n * Says what the run is doing and redraws the bar.\n *\n * @param text - What is happening, already colored, empty to say the watch is resting\n *\n * @example\n * ```ts\n * setActivity(`${ infoColor(ArrowSymbol) } building index`);\n * ```\n *\n * @see drawStatusBar\n * @since 3.0.0\n */\n\nexport function setActivity(text: string): void {\n activity = text;\n drawStatusBar();\n}\n\n/**\n * Listens for the shortcuts and takes the last row of the terminal for the status line.\n *\n * @param screen - Screen the keys act on and the bar reads its settings from\n * @returns A promise settling once the row is held and the keys are listened for\n *\n * @remarks\n * A terminal that is not one - a pipe, a log file, a pipeline - is left alone,\n * since raw mode would take a run that nobody is watching and break its input.\n * Where the run has printed to is asked of the terminal before the keys are listened for, the answer coming back\n * on the same input: only a run that has reached the last row needs one scrolled free,\n * and one that has not keeps the blank line it would have cost.\n * The region is set so that everything printed afterward scrolls above the line rather than over it,\n * which keeps it out of the scrollback.\n * The row is painted again on a beat, so a terminal cleared from outside the run gets the line back at once,\n * and the beat is unreferenced, so it never holds the process open on its own.\n * The cursor is put away for as long as the line holds the row, and everything is given back as the run leaves.\n *\n * @example\n * ```ts\n * startInteractive(screen);\n * ```\n *\n * @see handleKey\n * @see drawStatusBar\n *\n * @since 3.0.0\n */\n\nexport async function startInteractive(screen: Screen): Promise<void> {\n if (!stdin.isTTY || !stdout.isTTY || repaint) return;\n session = screen;\n\n stdin.setRawMode(true);\n writeRaw(ANSI.HIDE_CURSOR);\n\n const printed = await cursorRow();\n if (printed >= stdout.rows) writeRaw('\\n');\n claimRow(Math.min(printed, stdout.rows - 1));\n\n readline.emitKeypressEvents(stdin);\n stdin.on('keypress', (_, key: Key) => handleKey(key));\n\n stdout.on('resize', () => claimRow());\n repaint = setInterval(() => drawStatusBar(true), RepaintInterval).unref();\n process.on('exit', stopInteractive);\n}\n\n/**\n * Gives the row back and clears what the status line left on it.\n *\n * @remarks\n * Run as the process leaves, so the terminal is handed back scrolling in the whole of itself, cursor and all.\n * A run that never took a row has none to give, and returns.\n *\n * @since 3.0.0\n */\n\nexport function stopInteractive(): void {\n if (!repaint) return;\n\n clearInterval(repaint);\n repaint = undefined;\n row = undefined;\n\n writeRaw(`\\u001B[r${ moveCursor(stdout.rows, 1) }${ ANSI.CLEAR_LINE }${ ANSI.SHOW_CURSOR }`);\n}\n\n/**\n * Cuts the region the output scrolls in out of the terminal as it now stands, and draws the line under it.\n *\n * @param anchor - Row the run had printed to, left out by a resize to put the cursor back where it was\n *\n * @remarks\n * Run on every resize as well as on the first claim, so the row is rebuilt for the size the terminal now is.\n * Setting a region homes the cursor, so it is put back where the caller says the run had printed to:\n * the next line printed belongs under the last one written, not at the foot of a screen it has yet to fill,\n * and never on the row the line holds, where it would be painted over rather than read.\n * A resize is given no row to go back to and restores what was saved, the run printing inside the region by then.\n * The row is cleared before it is drawn, since the line has no claim on what a resize reflowed onto it.\n * A terminal too short to spare a row keeps all of itself and goes without the line until it is resized larger.\n *\n * @since 3.0.0\n */\n\nfunction claimRow(anchor?: number): void {\n if (stdout.rows < MinimumRows) {\n row = undefined;\n\n return writeRaw(`\\u001B[r${ ANSI.CLEAR_LINE }`);\n }\n\n const last = stdout.rows - 1;\n const back = anchor === undefined ? ANSI.RESTORE_CURSOR : moveCursor(anchor, 1);\n\n row = new ShadowRenderer(1, width(), last, 1);\n writeRaw(\n `${ ANSI.SAVE_CURSOR }\\u001B[1;${ last }r`\n + `${ moveCursor(stdout.rows, 1) }${ ANSI.CLEAR_LINE }${ back }`\n );\n\n drawStatusBar(true);\n}\n\n/**\n * Runs what a key asks for.\n *\n * @param key - Key that was pressed, as the terminal reported it\n *\n * @remarks\n * Interrupts leave through the same door as `q`, so a watch stopped by a keystroke and one stopped by a signal\n * end the same way, and both hand the terminal back before they go.\n * The run leaves only once the line saying so has been written, since leaving outright would cut the terminal\n * off before what was written for it had reached it.\n * Building and reloading part on one flag: `b` builds again from the configurations as they were parsed,\n * while `r` has every TypeScript project reparse its own first.\n * That reparse is what catches a change their versions miss, such as an edit to a file one of them extends.\n * A key with nothing bound to it is passed over, since a watch is left running rather than surprised by a typo.\n *\n * @see helpMenu\n * @since 3.0.0\n */\n\nasync function handleKey(key: Key): Promise<void> {\n if (key.ctrl && (key.name === 'c' || key.name === 'd')) key.name = 'q';\n\n switch (key.name) {\n case 'q':\n stopInteractive();\n stdout.write(`${ mutedColor('Stopped.') }\\n`, () => exit(process.exitCode ? Number(process.exitCode) : 0));\n\n return;\n case 'c':\n clearScreen();\n\n return drawStatusBar(true);\n case 'h':\n return console.log(helpMenu());\n case 'v':\n session?.toggleVerbose();\n\n return drawStatusBar(true);\n case 'o':\n if (session?.url) openInBrowser(session.url);\n\n return;\n case 'b':\n return session?.rebuild('rebuilding');\n case 'r':\n return session?.rebuild('reloading', true);\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { errorColor } from '@ui/color.ui';\nimport type { Metafile, PartialMessage } from 'esbuild';\nimport type { MessageRowInterface } from '@ui/interfaces/print-ui.interface';\nimport type { ResolveMetadataInterface } from '@providers/interfaces/stack-provider.interface';\n\n/**\n * Imports\n */\n\nimport { resolve } from 'path';\nimport { stdout } from 'process';\nimport { prefix } from '@ui/banner.ui';\nimport { relative } from '@remotex-labs/xmap';\nimport { inject } from '@remotex-labs/xinject';\nimport { stripAnsi } from '@remotex-labs/xansi';\nimport { cursorTo, clearScreenDown } from 'readline';\nimport { xterm } from '@remotex-labs/xansi/xterm.component';\nimport { getErrorMetadata } from '@providers/stack.provider';\nimport { FrameworkService } from '@services/framework.service';\nimport { infoColor, mutedColor, okColor, pathColor, warnColor } from '@ui/color.ui';\nimport { ArrowSymbol, DefaultWidth, DotSymbol, Indent, Kilobyte, Megabyte, OutputLimit } from '@constants/ui.constant';\n\n/**\n * Opens a reported line with the package's mark, a symbol, and the action being reported.\n *\n * @param action - What the line reports, such as `build` or `serve`\n * @param symbol - Symbol between the mark and the action, a dimmed arrow by default\n * @returns The opening of the line, colored\n *\n * @remarks\n * Every line printed outside a message group opens this way,\n * so the mark, the symbol, and the action sit in the same three places whatever printed them.\n * The symbol is what a caller varies to say how the action went, since the action itself reads the same either way.\n *\n * @example\n * ```ts\n * createActionPrefix('build'); // '[xBuild] → build'\n * createActionPrefix('build', okColor(SuccessSymbol)); // '[xBuild] ✓ build'\n * ```\n *\n * @see prefix\n * @since 3.0.0\n */\n\nexport function createActionPrefix(action: string, symbol: string = infoColor.dim(ArrowSymbol)): string {\n return `${ prefix() } ${ symbol } ${ infoColor(action) }`;\n}\n\n/**\n * Counts the characters a text takes on screen.\n *\n * @param text - Text to measure, colored or not\n * @returns The number of characters that print\n *\n * @remarks\n * The escape sequences a color leaves behind take no width of their own,\n * so measuring the string itself would pad a colored column by however many bytes its color cost.\n *\n * @example\n * ```ts\n * visible(pathColor('src/index.ts')); // 12\n * ```\n *\n * @since 3.0.0\n */\n\nexport function visible(text: string): number {\n return stripAnsi(text).length;\n}\n\n/**\n * Pads a text with spaces up to a width.\n *\n * @param text - Text to pad, colored or not\n * @param size - Width to pad it to, counted in printed characters\n * @returns The text, followed by the spaces that carry it to the width\n *\n * @remarks\n * The width is measured through {@link visible}, so a colored text pads to what it prints rather than to what it holds.\n * A text already at or past the width comes back as it is rather than cut,\n * since a column that overflows reads better than one that loses the end of a name.\n *\n * @example\n * ```ts\n * pad('src', 6); // 'src '\n * pad('src/index', 6); // 'src/index' - already past the width\n * ```\n *\n * @see visible\n * @since 3.0.0\n */\n\nexport function pad(text: string, size: number): string {\n return text + ' '.repeat(Math.max(0, size - visible(text)));\n}\n\n/**\n * Brings the path a frame resolved to back to one the project can be read against.\n *\n * @param file - Path the frame named, as the source map spelled it\n * @returns The path relative to the directory the run was started in\n *\n * @remarks\n * A map spells its sources relative to what was written rather than to what is being read,\n * so a config compiled by this package resolves as a path reaching back out of the framework's own directory.\n * Such a path is resolved from there rather than from the project, which is the only place it means anything,\n * and every other path is resolved the way this package keys files everywhere else.\n * A source that names a URL rather than a path is left as it is, there being no root to read it against.\n *\n * @example\n * ```ts\n * sourcePath('../config.xbuild.ts'); // 'config.xbuild.ts'\n * sourcePath('src/index.ts'); // 'src/index.ts'\n * sourcePath('https://github.com/x/y.ts'); // 'https://github.com/x/y.ts'\n * ```\n *\n * @see FrameworkService\n * @since 3.0.0\n */\n\nexport function sourcePath(file: string): string {\n if (file.includes('://')) return file;\n const absolute = file.startsWith('.')\n ? resolve(inject(FrameworkService).frameworkRoot, file)\n : FrameworkService.resolve(file);\n\n return relative(process.cwd(), absolute);\n}\n\n/**\n * Renders where a message points.\n *\n * @param file - Path the message points at, absent when it points nowhere\n * @param line - Line within that file\n * @param column - Column within that line\n * @returns The location, colored, empty when there is no file to point at\n *\n * @example\n * ```ts\n * formatLocation('src/index.ts', 12, 8); // 'src/index.ts:12:8'\n * formatLocation(undefined); // ''\n * ```\n *\n * @see sourcePath\n * @since 3.0.0\n */\n\nexport function formatLocation(file?: string, line: number = 0, column: number = 0): string {\n if (!file) return '';\n const separator = mutedColor.dim(':');\n\n return `${ pathColor(sourcePath(file)) }${ separator }${ warnColor(String(line)) }${ separator }${ warnColor(String(column)) }`;\n}\n\n/**\n * Renders the code window and the trace printed under a message.\n *\n * @param metadata - Already resolved trace of the message, so nothing is resolved twice\n * @param indent - What every line is indented by\n * @returns The lines to print under the message, empty when it resolved to neither code nor a trace\n *\n * @remarks\n * A trace of a single frame says nothing the location line has not said already, so it is left out.\n * Paths are printed from the directory the run was started in, the absolute part being the same for every frame.\n *\n * @see getErrorMetadata\n * @since 3.0.0\n */\n\nexport function formatDetail(metadata: ResolveMetadataInterface, indent: string): Array<string> {\n const root = `${ process.cwd() }/`;\n const lines: Array<string> = [];\n\n if (metadata.formatCode)\n lines.push('', ...metadata.formatCode.split('\\n').map(line => `${ indent }${ xterm.dim(line) }`));\n\n if (metadata.stack.length > 1) lines.push('', ...metadata.stack.map(frame => {\n return `${ indent }${ mutedColor.dim(frame.format.replaceAll(root, '')) }`;\n }));\n\n return lines.length > 0 ? [ ...lines, '' ] : lines;\n}\n\n/**\n * Works a message out into the parts a report line is laid out from.\n *\n * @param message - Message to describe\n * @param code - Whether the code window and trace are wanted under the line\n * @returns The message worked out, ready to be measured and printed\n *\n * @remarks\n * A diagnostic filed under a TypeScript code - an id of `TS<code>` - already points at the file that was written,\n * so it is taken at its word.\n * Anything else points at what was built rather than at what was written - a plugin throwing from a config that was\n * compiled to run reports the offset it failed at in the compiled text - so it is resolved through the source map\n * and read off the first frame instead.\n * The resolve is done once and serves both the location and what is printed under it,\n * and is skipped entirely by a diagnostic that needs neither.\n *\n * @example\n * ```ts\n * describeMessage({ id: 'TS2304', location: { file: 'src/index.ts', line: 12, column: 8 } }, false);\n * // { id: 'TS2304', location: 'src/index.ts:12:8', detail: [] }\n * ```\n *\n * @see getErrorMetadata\n * @see MessageRowInterface\n *\n * @since 3.0.0\n */\n\nexport function describeMessage(message: PartialMessage, code: boolean): MessageRowInterface {\n const typescript = message.id?.startsWith('TS') ?? false;\n const metadata = typescript && !code\n ? undefined\n : getErrorMetadata(message, { linesAfter: 1, linesBefore: 1, withFrameworkFrames: true });\n\n const frame = typescript ? undefined : metadata?.stack[0];\n const point = frame ?? message.location;\n\n return {\n id: message.id ?? '',\n detail: code && metadata ? formatDetail(metadata, Indent.repeat(2)) : [],\n location: formatLocation(frame?.fileName ?? message.location?.file, point?.line, point?.column)\n };\n}\n\n/**\n * Prints a group of messages under a heading, in columns sized to what they hold.\n *\n * @param messages - Messages to print, the group being skipped when there are none\n * @param title - Heading the group is printed under\n * @param color - Color the heading, the symbol, and the ids are printed in\n * @param symbol - Symbol each message is marked with\n * @param code - Whether each message carries its code window and trace\n *\n * @remarks\n * Every message is worked out once, in the pass that measures the columns,\n * since neither the location column nor the id column can be sized until all of them have been seen.\n * An id column is left out entirely when nothing in the group carries one.\n *\n * @example\n * ```ts\n * printGroup(errors, 'Errors', errorColor, ErrorSymbol, true);\n * // Errors (1)\n * // x config.xbuild.ts:126:27 asdasd\n * ```\n *\n * @see describeMessage\n * @since 3.0.0\n */\n\nexport function printGroup(\n messages: Array<PartialMessage>, title: string, color: typeof errorColor, symbol: string, code = false\n): void {\n if (messages.length < 1) return;\n\n let left = 0;\n let middle = 0;\n const rows: Array<MessageRowInterface> = [];\n\n for (const message of messages) {\n const row = describeMessage(message, code);\n left = Math.max(left, visible(row.location));\n middle = Math.max(middle, row.id.length);\n rows.push(row);\n }\n\n const lines = [ `\\n ${ color(title) } ${ mutedColor.dim(`(${ rows.length })`) }` ];\n for (const [ index, { id, location, detail }] of rows.entries()) {\n const tag = middle > 0 ? `${ pad(color(id), middle) } ` : '';\n\n lines.push(`${ Indent }${ color(symbol) } ${ pad(location, left) } ${ tag }${ mutedColor(messages[index].text ?? '') }`);\n lines.push(...detail);\n }\n\n console.log(lines.join('\\n'));\n}\n\n/**\n * Clears the terminal and puts the cursor back at the top.\n *\n * @remarks\n * The screen is pushed out of view rather than wiped, so the scrollback survives a clear.\n *\n * @since 3.0.0\n */\n\nexport function clearScreen(): void {\n const rows = Math.max(0, stdout.rows - 2);\n if (rows > 0) console.log('\\n'.repeat(rows));\n\n cursorTo(stdout, 0, 0);\n clearScreenDown(stdout);\n}\n\n/**\n * The width of the terminal, or what stands in for one that does not report it.\n *\n * @returns Columns the report is laid out in\n *\n * @since 3.0.0\n */\n\nexport function width(): number {\n return stdout.columns || DefaultWidth;\n}\n\n/**\n * Renders a byte count in the largest unit that keeps it above one.\n *\n * @param bytes - Size to render\n * @returns The size with its unit\n *\n * @example\n * ```ts\n * formatSize(512); // '512 B'\n * formatSize(458520); // '447.77 KB'\n * ```\n *\n * @since 3.0.0\n */\n\nexport function formatSize(bytes: number): string {\n if (bytes < Kilobyte) return `${ bytes } B`;\n if (bytes < Megabyte) return `${ (bytes / Kilobyte).toFixed(2) } KB`;\n\n return `${ (bytes / Megabyte).toFixed(2) } MB`;\n}\n\n/**\n * Writes what a build wrote, largest first, with the sizes set against the right margin.\n *\n * @param metafile - Metafile of the finished build, read for its outputs\n * @param limit - How many outputs to name before the rest are counted rather than listed, `Infinity` for all of them\n *\n * @remarks\n * The sizes are set flush against the right margin, so their digits line up under one another,\n * and the heading carries the total, which is the number a reader is usually after.\n * A build of many entry points writes more than a reader wants to scroll,\n * so the largest few are named and the rest left as a count carrying what it comes to.\n *\n * @example\n * ```ts\n * printOutputs(metafile);\n * // Outputs (18) 1.24 MB\n * // dist/index.js.map 681 B\n * ```\n *\n * @since 3.0.0\n */\n\nexport function printOutputs(metafile: Metafile, limit: number = OutputLimit): void {\n const outputs = Object.entries(metafile.outputs).sort(\n ([ , a ], [ , b ]) => b.bytes - a.bytes\n );\n\n if (outputs.length < 1) return;\n const listed = outputs.slice(0, limit);\n const sizes = listed.map(([ , { bytes }]) => formatSize(bytes));\n const right = Math.max(...sizes.map(size => size.length));\n const total = outputs.reduce((sum, [ , { bytes }]) => sum + bytes, 0);\n\n const room = width() - Indent.length - right - 4;\n const header = ` ${ okColor('Outputs') } ${ mutedColor.dim(`(${ outputs.length })`) }`;\n const lines = [ `\\n${ pad(header, width() - right - 1) }${ warnColor.dim(formatSize(total)) }` ];\n\n for (const [ index, [ path ]] of listed.entries())\n lines.push(\n `${ Indent }${ infoColor.dim(ArrowSymbol) } ${ pad(pathColor(path), room + 1) }`\n + warnColor.dim(sizes[index].padStart(right))\n );\n\n if (outputs.length > limit) {\n const rest = outputs.slice(limit).reduce((sum, [ , { bytes }]) => sum + bytes, 0);\n const more = mutedColor.dim(`${ DotSymbol } ${ outputs.length - limit } more`);\n lines.push(`${ Indent } ${ pad(more, room + 1) }${ warnColor.dim(formatSize(rest).padStart(right)) }`);\n }\n\n console.log(lines.join('\\n'));\n}\n","/**\n * Imports\n */\n\nimport { xterm } from '@remotex-labs/xansi/xterm.component';\n\n/**\n * The xBuild wordmark drawn in ASCII art.\n *\n * @remarks\n * Opens and closes with a newline, so it stands on its own lines wherever it is printed.\n * The backslashes are escaped for the template literal,\n * so the string holds one backslash everywhere the source shows two.\n *\n * @example\n * ```ts\n * console.log(asciiLogo);\n * ```\n *\n * @see bannerUi\n * @since 1.0.0\n */\n\nexport const asciiLogo = `\n ______ _ _ _\n | ___ \\\\ (_) | | |\n__ _| |_/ /_ _ _| | __| |\n\\\\ \\\\/ / ___ \\\\ | | | | |/ _\\` |\n > <| |_/ / |_| | | | (_| |\n/_/\\\\_\\\\____/ \\\\__,_|_|_|\\\\__,_|\n`;\n\n/**\n * Renders the startup banner, the logo above the version.\n *\n * @returns The banner as one string, colored and ready to print\n *\n * @remarks\n * The logo is drawn in burnt orange and the version in bright pink.\n * Every line opens with a carriage return, so the text starts at column zero\n * whatever indentation the template literal carries.\n * The version reads `__VERSION`, which the build replaces with the `package.json` version at compile time.\n *\n * @example\n * ```ts\n * console.log(bannerComponent());\n * ```\n *\n * @see asciiLogo\n * @since 1.0.0\n */\n\nexport function bannerUi(): string {\n return `\n \\r${ xterm.burntOrange(asciiLogo) }\n \\rVersion: ${ xterm.brightPink(__VERSION) }\n \\r`;\n}\n\n/**\n * The `[xBuild]` tag that marks a line as coming from the build.\n *\n * @returns The tag in light coral\n *\n * @remarks\n * Prepended to log lines so xBuild output stays recognizable when several tools write to the same console.\n *\n * @example\n * ```ts\n * console.log(`${ prefix() } Starting build`); // [xBuild] Starting build\n * ```\n *\n * @since 1.0.0\n */\n\nexport function prefix(): string {\n return xterm.lightCoral('[xBuild]');\n}\n","/**\n * Imports\n */\n\nimport { xterm } from '@remotex-labs/xansi/xterm.component';\n\n/**\n * Style token for a step that finished as it should.\n *\n * @remarks\n * Green.\n * Reserved for an outcome the reader can stop reading at, so a step that merely progressed stays unstyled.\n *\n * @example\n * ```ts\n * console.log(okColor('build finished'));\n * ```\n *\n * @since 2.0.0\n */\n\nexport const okColor = xterm.hex('#a6da95');\n\n/**\n * Style token for ordinary body text.\n *\n * @remarks\n * Neutral light.\n * The default weight everything else is read against, so it carries no meaning of its own.\n *\n * @example\n * ```ts\n * console.log(textColor('4 entry points'));\n * ```\n *\n * @since 2.0.0\n */\n\nexport const textColor = xterm.hex('#cad3f5');\n\n/**\n * Style token for a notice the reader may act on but need not.\n *\n * @remarks\n * Blue.\n * Distinguished from {@link warnColor} by carrying no fault - it reports what happened rather than what went wrong.\n *\n * @example\n * ```ts\n * console.log(infoColor('watching for changes'));\n * ```\n *\n * @since 2.0.0\n */\n\nexport const infoColor = xterm.hex('#91d7e3');\n\n/**\n * Style token for something suspect that did not stop the build.\n *\n * @remarks\n * Yellow.\n * The middle ground between {@link infoColor} and {@link errorColor}, for output worth reading after the run.\n *\n * @example\n * ```ts\n * console.log(warnColor('3 files matched no entry point'));\n * ```\n *\n * @since 2.0.0\n */\n\nexport const warnColor = xterm.hex('#eed49f');\n\n/**\n * Style token for a file path, a URL, or a location.\n *\n * @remarks\n * Cyan.\n * Marks the part of a line the reader is most likely to copy, so it stays distinct inside an otherwise styled message.\n *\n * @example\n * ```ts\n * console.log(pathColor('src/index.ts'));\n * ```\n *\n * @since 2.0.0\n */\n\nexport const pathColor = xterm.hex('#f5a97f');\n\n/**\n * Style token for a failure.\n *\n * @remarks\n * Red.\n * For an outcome that stopped the work, which keeps it rare enough to still register when it appears.\n *\n * @example\n * ```ts\n * console.log(errorColor('Cannot resolve module'));\n * ```\n *\n * @since 2.0.0\n */\n\nexport const errorColor = xterm.hex('#ed8796');\n\n/**\n * Style token for a keyword or an identifier quoted inside a message.\n *\n * @remarks\n * Purple.\n * Picks a name out of surrounding prose the way {@link pathColor} picks out a location.\n *\n * @example\n * ```ts\n * console.log(keywordColor('bundleDeclaration'));\n * ```\n *\n * @since 2.0.0\n */\n\nexport const keywordColor = xterm.hex('#c6a0f6');\n\n/**\n * Style token for text that belongs on the line but not at the front of the reader's attention.\n *\n * @remarks\n * Muted gray.\n * For figures that qualify a message rather than carry it, such as a timing or a count.\n *\n * @example\n * ```ts\n * console.log(mutedColor('in 412ms'));\n * ```\n *\n * @since 2.0.0\n */\n\nexport const mutedColor = xterm.hex('#939ab7');\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { LogLevelType } from '@providers/interfaces/log-provider.interface';\n\n/**\n * The three spaces that indent one level of reported detail.\n *\n * @remarks\n * Wide enough to clear the symbol marking the line above,\n * so a message sits under the heading it belongs to rather than against the margin.\n * A code window and a trace are indented twice over, which sets them under the message they explain.\n *\n * @example\n * ```ts\n * `${ Indent }dist/index.js`; // ' dist/index.js'\n * ```\n *\n * @since 3.0.0\n */\n\nexport const Indent = ' ';\n\n/**\n * The width a report is laid out in where the terminal reports none.\n *\n * @remarks\n * A pipe and a log file have no column count to answer with,\n * so the sizes a report sets against the right margin would have nothing to measure from.\n *\n * @example\n * ```ts\n * width(); // 100 - piped, so the terminal reported nothing\n * ```\n *\n * @see width\n * @since 3.0.0\n */\n\nexport const DefaultWidth = 100;\n\n/**\n * How many outputs a build names before the rest are counted rather than listed.\n *\n * @remarks\n * A build of many entry points writes more than a reader wants to scroll,\n * so the largest few are named and what is left becomes one line carrying its count and its size.\n * Reporting at `verbose` lifts the limit rather than raising it.\n *\n * @example\n * ```ts\n * printOutputs(metafile); // the six largest, then '· 12 more'\n * printOutputs(metafile, Infinity); // all of them\n * ```\n *\n * @since 3.0.0\n */\n\nexport const OutputLimit = 6;\n\n/**\n * The fewest rows a terminal can have and still give one up to the status line.\n *\n * @remarks\n * Below this the scrolling region would be shorter than the report it carries,\n * so the line is given up and the terminal keeps all of itself until it is resized larger.\n *\n * @since 3.0.0\n */\n\nexport const MinimumRows = 4;\n\n/**\n * How long the status line waits between repaints, in milliseconds.\n *\n * @remarks\n * The beat is what brings the line back after a terminal is cleared from outside the run,\n * since the row remembers what it drew and would otherwise find nothing to redraw.\n * Short enough to read as immediate, long enough that a resting watch costs a repaint three times a second.\n *\n * @since 3.0.0\n */\n\nexport const RepaintInterval = 300;\n\n/**\n * How long the terminal is given to say where the cursor is, in milliseconds.\n *\n * @remarks\n * A terminal that answers does so at once, so the wait is only ever spent on one that never will,\n * and a run under a terminal like that is taken to have filled the screen.\n *\n * @since 3.0.0\n */\n\nexport const ReportTimeout = 100;\n\n/**\n * The number of bytes in one kilobyte.\n *\n * @remarks\n * Binary rather than decimal, `1024` rather than `1000`,\n * which is what makes a reported size agree with the one a file manager shows.\n *\n * @example\n * ```ts\n * 2048 / Kilobyte; // 2\n * ```\n *\n * @since 3.0.0\n */\n\nexport const Kilobyte = 1024;\n\n/**\n * The number of bytes in one megabyte.\n *\n * @remarks\n * Derived from {@link Kilobyte} rather than written out, so the two cannot drift apart,\n * and binary for the same reason it is.\n *\n * @example\n * ```ts\n * Megabyte / Kilobyte; // 1024\n * ```\n *\n * @see Kilobyte\n * @since 3.0.0\n */\n\nexport const Megabyte = Kilobyte * 1024;\n\n/**\n * The middle dot that separates one part of a line from the next.\n *\n * @remarks\n * A separator rather than a mark, so it stands between two values instead of opening a line,\n * which is what keeps it apart from {@link WarningSymbol}.\n * It also marks the quietest group of messages, where a bare dot is as much as a note deserves.\n *\n * @example\n * ```ts\n * `esm ${ DotSymbol } 12 ms`; // 'esm · 12 ms'\n * ```\n *\n * @since 3.0.0\n */\n\nexport const DotSymbol = '·';\n\n/**\n * The arrow that marks work under way.\n *\n * @remarks\n * Opens the line of a variant while it builds and the line of every output a build wrote,\n * so a reader follows what is happening down the same column.\n * One of {@link SuccessSymbol} or {@link ErrorSymbol} takes its place once the build ends.\n *\n * @example\n * ```ts\n * `${ ArrowSymbol } building esm`; // '→ building esm'\n * ```\n *\n * @since 3.0.0\n */\n\nexport const ArrowSymbol = '→';\n\n/**\n * The cross that marks a failure.\n *\n * @remarks\n * Closes the line of a variant that produced no output, and opens each of its errors,\n * so a run scanned from the left reads its failures without their text.\n *\n * @example\n * ```ts\n * `${ ErrorSymbol } esm`; // '× esm'\n * ```\n *\n * @see SuccessSymbol\n * @since 3.0.0\n */\n\nexport const ErrorSymbol = '×';\n\n/**\n * The circular arrow that marks a rebuild.\n *\n * @remarks\n * Written when a watch starts the build again, beside the reason it restarted,\n * and again on the status line while the watch rests between builds.\n *\n * @example\n * ```ts\n * `${ ReloadSymbol } 2 files changed`; // '↻ 2 files changed'\n * ```\n *\n * @since 3.0.0\n */\n\nexport const ReloadSymbol = '↻';\n\n/**\n * The bullet that marks a warning.\n *\n * @remarks\n * A filled dot rather than a cross, so a warning reads as quieter than a failure\n * and still stands out from a line carrying no mark at all.\n *\n * @example\n * ```ts\n * `${ WarningSymbol } unsupported require call`; // '• unsupported require call'\n * ```\n *\n * @see ErrorSymbol\n * @since 3.0.0\n */\n\nexport const WarningSymbol = '•';\n\n/**\n * The check mark that marks a build that finished clean.\n *\n * @remarks\n * Closes the line of a variant that wrote its output, opposite {@link ErrorSymbol},\n * so the two read as one column of outcomes down the left of a run.\n *\n * @example\n * ```ts\n * `${ SuccessSymbol } esm in 128 ms`; // '✓ esm in 128 ms'\n * ```\n *\n * @see ErrorSymbol\n * @since 3.0.0\n */\n\nexport const SuccessSymbol = '✓';\n\n/**\n * How loud each level is, as a number the levels can be compared by.\n *\n * @remarks\n * A report prints the groups that rank at or above the level the run is set to,\n * which needs an order that the level names do not carry on their own.\n * `silent` ranks above every group, so nothing reaches a run set to it.\n *\n * @example\n * ```ts\n * Levels.warning >= Levels.info; // true - warnings print at the info level\n * Levels.info >= Levels.error; // false - info is quiet at the error level\n * ```\n *\n * @see LogLevelType\n * @since 3.0.0\n */\n\nexport const Levels: Record<LogLevelType, number> = { verbose: 0, info: 1, warning: 2, error: 3, silent: 4 };\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { DeepPartialType } from '@interfaces/types.interface';\nimport type { UnsubscribeType, Observable } from '@remotex-labs/xobservable';\nimport type { ConfigurationInterface } from '@interfaces/configuration.interface';\nimport type { xBuildConfigInterface } from '@providers/interfaces/config-file-provider.interface';\n\n/**\n * Imports\n */\n\nimport { Injectable } from '@remotex-labs/xinject';\nimport { BehaviorSubject } from '@remotex-labs/xobservable';\nimport { deepMerge, equals } from '@components/object.component';\nimport { map, distinctUntilChanged } from '@remotex-labs/xobservable';\nimport { DefaultsCommonConfig } from '@constants/configuration.constant';\n\n/**\n * Holds the build configuration and lets the rest of the build watch it change.\n *\n * @typeParam T - Shape of the configuration, at least a {@link ConfigurationInterface}\n *\n * @remarks\n * The configuration is not settled once and read forever: a watch reloads the file behind it, so whatever depends on\n * a setting has to be told when it moves rather than reading it once at startup.\n * That is what {@link select} is for - it reports only when the value that a caller actually asked for has changed,\n * so a change elsewhere in the configuration wakes nobody.\n * Updates merge rather than replace, so an update says what changes and leaves the rest standing.\n * Registered as a singleton, so every consumer reads and watches the same configuration.\n *\n * @example\n * ```ts\n * const configuration = inject(ConfigurationService);\n *\n * configuration.getValue(config => config.logLevel); // info\n * configuration.select(config => config.variants)\n * .subscribe(variants => rebuild(variants)); // told whenever the variants change\n * configuration.patch({ verbose: true }); // the variant's watcher hears nothing\n * ```\n *\n * @see xBuildConfigInterface\n * @see ConfigurationInterface\n *\n * @since 2.0.0\n */\n\n@Injectable({\n scope: 'singleton'\n})\nexport class ConfigurationService<T extends ConfigurationInterface = Required<xBuildConfigInterface>> {\n /**\n * The configuration and everything watching it.\n *\n * @remarks\n * A behavior subject rather than a plain one, so a subscriber arriving late is handed the configuration as it\n * stands instead of waiting for the next change.\n *\n * @since 2.0.0\n */\n\n private readonly config$: BehaviorSubject<T>;\n\n /**\n * Creates the service around a starting configuration.\n *\n * @param initialConfig - Configuration to start from the built-in defaults when omitted\n *\n * @remarks\n * The configuration is copied on the way in, so the object handed over is never written to - which is what makes\n * the frozen defaults usable as a starting point.\n * It is also kept as it was passed, since {@link reload} needs something to return to.\n *\n * @example\n * ```ts\n * const configuration = new ConfigurationService({ variants: { esm: { esbuild: { format: 'esm' } } } });\n * configuration.getValue().variants.esm; // { esbuild: { format: 'esm' } }\n * ```\n *\n * @see DefaultsCommonConfig\n * @since 2.0.0\n */\n\n constructor(private initialConfig: T = DefaultsCommonConfig as T) {\n this.config$ = new BehaviorSubject<T>(deepMerge({}, initialConfig) as T);\n }\n\n /**\n * Reads the whole configuration as it stands.\n *\n * @returns The current configuration\n *\n * @example\n * ```ts\n * configuration.getValue().verbose; // false\n * ```\n *\n * @since 2.0.0\n */\n\n getValue(): T;\n\n /**\n * Reads one value out of the configuration as it stands.\n *\n * @typeParam R - What the selector returns\n * @param selector - Picks the value to read\n * @returns Whatever the selector returned\n *\n * @remarks\n * The one-off counterpart of {@link select}: it answers once and never again, which suits a decision taken at a\n * point in time rather than something that has to follow the configuration.\n *\n * @example\n * ```ts\n * configuration.getValue(config => Object.keys(config.variants)); // [ 'esm', 'cjs' ]\n * ```\n *\n * @since 2.0.0\n */\n\n getValue<R>(selector: (config: T) => R): R;\n\n /**\n * Serves both reading forms.\n *\n * @param selector - Picks a value, or reads the whole configuration when absent\n * @returns The configuration, or what the selector returned\n *\n * @since 2.0.0\n */\n\n getValue<R>(selector?: (config: T) => R): T | R {\n if (!selector)\n return this.config$.value;\n\n return selector(this.config$.value);\n }\n\n /**\n * Watches the whole configuration.\n *\n * @param observer - Called with the configuration, now and on every change\n * @returns A function that stops the watching\n *\n * @remarks\n * Called straight away with the configuration as it stands, so a subscriber needs no separate first read.\n * It hears every change, whatever moved, which is why {@link select} is the better choice for anything that cares\n * about one corner of the configuration.\n *\n * @example\n * ```ts\n * const stop = configuration.subscribe(config => console.log(config.verbose)); // logs at once\n * configuration.patch({ verbose: true }); // logs again\n * stop();\n * ```\n *\n * @see select\n * @since 1.0.0\n */\n\n subscribe(observer: (value: T) => void): UnsubscribeType {\n return this.config$.subscribe(observer);\n }\n\n /**\n * Watches one value in the configuration.\n *\n * @typeParam R - What the selector returns\n * @param selector - Picks the value to watch\n * @returns A stream of that value, reporting only when it has actually changed\n *\n * @remarks\n * The selector runs on every change, but its result is compared against the one before and only a real difference\n * is passed on - so a change elsewhere costs a comparison rather than the work behind a subscriber.\n * The comparison is structural, so a selector that builds an equal object each time still reports nothing.\n *\n * @example\n * ```ts\n * configuration.select(config => config.common?.esbuild?.minify)\n * .subscribe(minify => console.log(minify)); // true, then again only when it changes\n *\n * configuration.patch({ verbose: true }); // nothing reported - minify did not move\n * ```\n *\n * @see equals\n * @see subscribe\n *\n * @since 2.0.0\n */\n\n select<R>(selector: (config: T) => R): Observable<R> {\n return this.config$.pipe(\n map(selector),\n distinctUntilChanged((prev, curr) => equals(prev, curr))\n ) as Observable<R>;\n }\n\n /**\n * Merges changes into the configuration and reports them.\n *\n * @param partial - The parts to change, nested as deeply as needed\n *\n * @remarks\n * Merged over what is there now, so anything left out keeps its value and only the corners named are touched.\n * Arrays are concatenated rather than replaced, so patching a list adds to it - which is a reason to reach for\n * {@link reload} when a list has to be replaced rather than extended.\n * Every subscriber is told, while a {@link select} passes it on only if the value it picked actually moved.\n *\n * @example\n * ```ts\n * configuration.patch({ common: { esbuild: { minify: false } } });\n * configuration.getValue().common?.esbuild?.format; // 'cjs' - untouched\n * ```\n *\n * @see reload\n * @since 1.0.0\n */\n\n patch(partial: DeepPartialType<T>): void {\n const mergedConfig = deepMerge<T>(\n {} as T,\n this.config$.value,\n partial\n );\n\n this.config$.next(mergedConfig);\n }\n\n /**\n * Starts again from the initial configuration, with the given one merged over it.\n *\n * @param config - Configuration to apply over the initial one\n *\n * @remarks\n * Not a replacement: the result is the configuration this service was constructed with,\n * merged with what is passed here.\n * What the initial configuration carried therefore survives, and only what accumulated since is dropped.\n * That is what re-reading an edited file wants, since a patch has no way to take something back.\n * To be rid of the initial configuration too, construct another service.\n *\n * @example\n * ```ts\n * configuration.patch({ verbose: true });\n * configuration.reload({ common: { types: false } });\n * configuration.getValue().verbose; // false again - the patch is gone\n * ```\n *\n * @see patch\n * @since 2.0.0\n */\n\n reload(config: DeepPartialType<T>): void {\n this.config$.next(deepMerge({}, this.initialConfig, config) as T);\n }\n}\n","/**\n * Reports whether a value can be treated as a keyed object.\n *\n * @param item - Value to test\n * @returns `true` when the value is a non-null object that is not an array\n *\n * @remarks\n * Narrows to `Record<string, unknown>`, which is what lets the merge and comparison helpers index a value they were\n * handed as `unknown`.\n * Only arrays and `null` are ruled out, so a `Date`, a `RegExp`, and a class instance all pass - the callers that\n * care treat those specially before asking.\n *\n * @example\n * ```ts\n * isObject({ key: 'value' }); // true\n * isObject(new Date()); // true - an object, whatever else it is\n * isObject([]); // false\n * isObject(null); // false\n * ```\n *\n * @see deepMerge\n * @since 2.0.0\n */\n\nexport function isObject(item: unknown): item is Record<string, unknown> {\n return !!item && typeof item === 'object' && !Array.isArray(item);\n}\n\n/**\n * Reports whether a value is an ordinary keyed object rather than an instance of something.\n *\n * @param item - Value to test\n * @returns `true` when the value is an object literal, or one built with a null prototype\n *\n * @remarks\n * Where {@link isObject} asks whether a value can be indexed, this asks whether walking its keys describes it.\n * A `Date`, a `RegExp`, a `Map`, and a class instance carry their state somewhere other than their own enumerable\n * keys, so merging into a fresh object would leave nothing of them behind.\n * The test is that the prototype is a root of its chain rather than this realm's `Object.prototype`.\n * An object literal built inside a `vm` context therefore counts as plain,\n * which is what a configuration file executed in a sandbox hands back.\n *\n * @example\n * ```ts\n * isPlainObject({ key: 'value' }); // true\n * isPlainObject(Object.create(null)); // true\n * isPlainObject(runInNewContext('({ a: 1 })')); // true - plain, whatever realm built it\n * isPlainObject(/^_/); // false - a value, not a shape\n * isPlainObject(new Date()); // false\n * ```\n *\n * @see isObject\n * @see deepMerge\n *\n * @since 3.0.0\n */\n\nexport function isPlainObject(item: unknown): item is Record<string, unknown> {\n if (!isObject(item)) return false;\n const prototype = Object.getPrototypeOf(item);\n\n return prototype === null || Object.getPrototypeOf(prototype) === null;\n}\n\n/**\n * Merges objects into a target, recursing into nested objects.\n *\n * @typeParam T - Type of the object being merged into\n *\n * @param target - Object the sources are merged into, modified in place\n * @param sources - Objects to merge, applied left to right so a later one wins\n * @returns The target, for chaining\n *\n * @remarks\n * Three rules decide each key: two arrays concatenate, two plain objects merge, and anything else is overwritten.\n * A `Date`, a `RegExp`, a `Map`, and a class instance are values rather than shapes to walk,\n * so they are carried across as they stand.\n * Recursing into such a value would reduce it to a plain object holding whatever its own enumerable keys are.\n * Concatenation rather than replacement means merging the same configuration twice doubles its arrays,\n * so an accumulating merge wants a fresh target each time.\n * That is also the way to use this as a deep copy, by merging into `{}`.\n * The target is modified rather than copied, so pass a literal unless the caller means to have its object rewritten.\n *\n * @example\n * ```ts\n * deepMerge({ a: 1, b: { x: 10 } }, { b: { y: 20 }, c: 3 }); // { a: 1, b: { x: 10, y: 20 }, c: 3 }\n * deepMerge({ items: [ 1, 2 ] }, { items: [ 3 ] }); // { items: [ 1, 2, 3 ] } - concatenated\n * deepMerge({}, { pattern: /^_/ }); // { pattern: /^_/ } - the same regular expression\n * deepMerge({}, config); // a deep copy of config\n * ```\n *\n * @see isObject\n * @see isPlainObject\n *\n * @since 2.0.0\n */\n\nexport function deepMerge<T extends object>(target: T, ...sources: Array<object>): T {\n if (!sources.length) return target;\n const source = sources.shift();\n\n if (isObject(target) && isObject(source)) {\n for (const key in source) {\n const sourceValue = source[key];\n const targetValue = target[key];\n\n if (Array.isArray(sourceValue) && Array.isArray(targetValue)) {\n Object.assign(target, { [key]: [ ...targetValue, ...sourceValue ] });\n } else if (isPlainObject(sourceValue)) {\n Object.assign(target, {\n [key]: deepMerge(\n isPlainObject(targetValue) ? targetValue : {},\n sourceValue\n )\n });\n } else {\n Object.assign(target, { [key]: sourceValue });\n }\n }\n\n return deepMerge(target, ...sources);\n }\n\n return target;\n}\n\n/**\n * Compares two values by structure rather than by identity.\n *\n * @param a - First value\n * @param b - Second value\n * @param strictCheck - Whether both sides must have the same number of entries, `true` by default\n * @returns `true` when the two are equal by these rules\n *\n * @remarks\n * `Date`, `RegExp`, and `URL` are compared by what they mean - timestamp, pattern and flags, href - rather than by\n * walking their properties, which would find nothing.\n * `NaN` equals itself here, unlike under `===`.\n * `0` and `-0` compare equal, since strict equality settles them before the question of sign arises.\n * Relaxing `strictCheck` turns the comparison into a subset test: every entry of the first value must appear in the\n * second, and extra entries in the second are ignored.\n *\n * @example\n * ```ts\n * equals(NaN, NaN); // true\n * equals(new Date('2024-01-01'), new Date('2024-01-01')); // true\n * equals({ a: 1, b: { c: 2 } }, { a: 1, b: { c: 2 } }); // true\n * equals([ 1, 2 ], [ 1, 2, 3 ], false); // true - a subset\n * equals([ 1, 2 ], [ 1, 2, 3 ]); // false - lengths differ\n * ```\n *\n * @see hasKey\n * @since 2.0.0\n */\n\nexport function equals(a: unknown, b: unknown, strictCheck = true): boolean {\n if (a === b) return true;\n if (Object.is(a, b)) return true;\n if (a === null || b === null) return false;\n\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n\n if (a instanceof RegExp && b instanceof RegExp)\n return a.source === b.source && a.flags === b.flags;\n\n if (URL && a instanceof URL && b instanceof URL)\n return a.href === b.href;\n\n if (typeof a === 'object' && typeof b === 'object') {\n return deepEquals(a, b, strictCheck);\n }\n\n return false;\n}\n\n/**\n * Reports whether a key can be reached on a value.\n *\n * @param obj - Value to look in\n * @param key - Key to look for, a name or a symbol\n * @returns `true` when the key is reachable, own or inherited\n *\n * @remarks\n * Answers for objects and functions only: a primitive returns `false` even where the key would resolve, so\n * `'length'` on a string is not found here.\n * `null` and `undefined` answer `false` rather than throwing, which is the point of asking through this rather than\n * with `in` directly.\n *\n * @example\n * ```ts\n * hasKey({ name: 'test' }, 'name'); // true\n * hasKey({ name: 'test' }, 'age'); // false\n * hasKey(null, 'key'); // false\n * hasKey('string', 'length'); // false - a primitive, not an object\n * ```\n *\n * @since 2.0.0\n */\n\nexport function hasKey(obj: unknown, key: string | symbol): boolean {\n if (obj == null || (typeof obj !== 'object' && typeof obj !== 'function'))\n return false;\n\n return key in obj || Object.prototype.hasOwnProperty.call(obj, key);\n}\n\n/**\n * Compares two objects or arrays entry by entry.\n *\n * @param a - First value\n * @param b - Second value\n * @param strictCheck - Whether both sides must have the same number of entries\n * @returns `true` when every entry of the first matches the second\n *\n * @remarks\n * The recursive half of {@link equals}, which handles the special types before delegating here.\n * Position compares arrays, so the same items in another order are not equal.\n * Objects are walked by the first value's own enumerable keys, which is what makes the relaxed mode a subset test -\n * a key the second value has and the first does not is never looked at.\n *\n * @since 2.0.0\n */\n\nfunction deepEquals(a: object, b: object, strictCheck: boolean = true): boolean {\n if (Array.isArray(a) && Array.isArray(b)) {\n if(strictCheck && a.length !== b.length) return false;\n\n return a.every((val, i) => equals(val, b[i], strictCheck));\n }\n\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n if (strictCheck && aKeys.length !== bKeys.length) return false;\n\n for (const key of aKeys) {\n if (!hasKey(b, key)) return false;\n if (!equals((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key], strictCheck)) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Serializes a value to JSON, carrying a `bigint` across as a string.\n *\n * @param value - Value to serialize\n * @returns The JSON text\n *\n * @throws TypeError - Raised when the value holds a circular reference\n *\n * @remarks\n * `JSON.stringify` throws on a `bigint` rather than serializing it, so this converts each to its decimal digits on\n * the way out.\n * The digits are written as a JSON string, since JSON has no number wide enough to hold them,\n * which is what keeps a value past `Number.MAX_SAFE_INTEGER` exact.\n * A reader therefore gets a string back where a `bigint` went in.\n * Everything else behaves as `JSON.stringify` does: an `undefined` property is dropped, a `Map` and a `Set` come out\n * as `{}`, and a `Date` comes out as the string its own `toJSON` produced.\n * A top-level `undefined`, function, or symbol still yields `undefined` rather than text,\n * which the declared return type does not admit.\n *\n * @example\n * ```ts\n * stringify({ id: 9007199254740993n }); // '{\"id\":\"9007199254740993n\"}' - the digits kept exactly\n * stringify({ a: 1, b: [ 1, 2 ] }); // '{\"a\":1,\"b\":[1,2]}'\n * stringify({ a: undefined, b: 1 }); // '{\"b\":1}' - the undefined key dropped\n * stringify(undefined); // undefined - not text, despite the signature\n * ```\n *\n * @since 3.0.0\n */\n\nexport function stringify(value: unknown): string {\n return JSON.stringify(value, (_, entry) => typeof entry === 'bigint' ? entry.toString() + 'n' : entry);\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { PartialConfigurationType } from '@interfaces/configuration.interface';\n\n/**\n * The configuration that a build starts from, before a file or a flag says otherwise.\n *\n * @remarks\n * The object, its `common` block, and its `esbuild` block are each frozen,\n * so nothing can rewrite the defaults for every other consumer that reads them.\n * {@link ConfigurationService} copies it on the way in rather than holding it directly,\n * which is what keeps the freeze from turning an ordinary patch into a failure.\n * `absWorkingDir` is read when this module is first imported, so it records the directory the process started in\n * rather than wherever a later build happens to look.\n *\n * @example\n * ```ts\n * DefaultsCommonConfig.common?.esbuild?.format; // 'cjs'\n * DefaultsCommonConfig.common?.esbuild?.outdir; // 'dist'\n * ```\n *\n * @see ConfigurationService\n * @since 3.0.0\n */\n\nexport const DefaultsCommonConfig: PartialConfigurationType = Object.freeze({\n common: Object.freeze({\n types: true,\n logOverride: {},\n declaration: true,\n esbuild: Object.freeze({\n write: true,\n bundle: true,\n minify: true,\n format: 'cjs',\n outdir: 'dist',\n platform: 'browser',\n absWorkingDir: process.cwd(),\n legalComments: 'none'\n })\n })\n});\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { ModuleResolutionCache, SourceFile } from 'typescript';\nimport type { LanguageService, Diagnostic, Program } from 'typescript';\nimport type { EmitAndSemanticDiagnosticsBuilderProgram } from 'typescript';\nimport type { CacheEntryInterface } from './interfaces/typescript-service.interface';\nimport type { ParsedCommandLine, BuilderProgramHost, ReadBuildProgramHost } from 'typescript';\nimport type { DiagnosticInterface, ResolvedModuleInterface } from './interfaces/typescript-service.interface';\n\n/**\n * Imports\n */\n\nimport ts from 'typescript';\nimport { Injectable } from '@remotex-labs/xinject';\nimport { normalize, relative, dirname } from '@remotex-labs/xmap';\nimport { DeclarationModel } from '@typescript/models/declaration.model';\nimport { LanguageHostService } from '@typescript/services/host.service';\n\n/**\n * One TypeScript project, wrapping its language service, module resolution, and declaration emit.\n *\n * @remarks\n * Everything a build needs from TypeScript comes through here:\n *\n * - **Diagnostics** - {@link check}\n * - **Declaration files** - {@link emit} and {@link emitBundle}\n * - **Specifier resolution** - {@link resolve}\n *\n * Each configuration file gets one shared instance, reference counted,\n * so several consumers naming the same `tsconfig.json` share one language service,\n * and the last {@link dispose} tears it down.\n * The parse forces `emitDeclarationOnly` on,\n * since this asks the compiler for types alone while the bundler produces the JavaScript.\n *\n * @example\n * ```ts\n * const service = inject(TypescriptService, 'tsconfig.json');\n *\n * service.check(); // [] - the project type-checks\n * await service.emit({ index: 'src/index.ts' }); // [ 'D:/app/dist/index.d.ts' ]\n * service.dispose(); // released - torn down once nothing else holds it\n * ```\n *\n * @see DeclarationModel\n * @see LanguageHostService\n *\n * @since 2.0.0\n */\n\n@Injectable({\n factory(path?: string): TypescriptService {\n return TypescriptService.acquire(path);\n }\n})\nexport class TypescriptService {\n /**\n * The language service this project's queries run against.\n *\n * @remarks\n * Backed by {@link languageHostService} and a document registry,\n * so the syntax trees of shared files survive between requests.\n *\n * @example\n * ```ts\n * service.languageService.getProgram()?.getSourceFiles().length; // 214\n * ```\n *\n * @since 2.0.0\n */\n\n readonly languageService: LanguageService;\n\n /**\n * The host the language service reads files and versions through.\n *\n * @remarks\n * Exposed because it owns the tracked file set, which is what decides the program's file list.\n *\n * @example\n * ```ts\n * service.languageHostService.tracked.size; // grows as the language service resolves imports\n * ```\n *\n * @see LanguageHostService\n * @since 2.0.0\n */\n\n readonly languageHostService: LanguageHostService;\n\n /**\n * The live instances, keyed by their normalized configuration path.\n *\n * @remarks\n * Static, so sharing spans the whole process rather than one injector,\n * and each entry carries the reference count that decides when its language service is torn down.\n *\n * @see acquire\n * @since 3.0.0\n */\n\n private static readonly cache = new Map<string, CacheEntryInterface>();\n\n /**\n * The diagnostics of every file checked so far, keyed by the file name the compiler reported.\n *\n * @remarks\n * Only the affected files are recomputed on a {@link check},\n * so the untouched entries here are what makes the result whole-project rather than only-what-changed.\n * The key is the absolute path the compiler reported,\n * so a caller's own names are resolved before they are read back.\n *\n * @see reconcileDiagnostics\n * @since 3.0.0\n */\n\n private readonly diagnosticsCache = new Map<string, Array<DiagnosticInterface>>();\n\n /**\n * The host the builder program reads through.\n *\n * @remarks\n * Routes every read to {@link languageHostService},\n * so the builder sees the same cached content the language service does\n * rather than reaching the disk a second time and disagreeing with it.\n *\n * @since 3.0.0\n */\n\n private readonly builderHost: ReadBuildProgramHost & BuilderProgramHost = {\n createHash: ts.sys.createHash,\n readFile: (file: string, encoding?: BufferEncoding): string | undefined =>\n this.languageHostService.readFile(file, encoding),\n getCurrentDirectory: (): string => ts.sys.getCurrentDirectory(),\n useCaseSensitiveFileNames: (): boolean => ts.sys.useCaseSensitiveFileNames\n };\n\n /**\n * The declaration cache and emitter bound to this project.\n *\n * @remarks\n * Constructed with this service, whose {@link resolve} is what decides which specifiers name project files.\n *\n * @see DeclarationModel\n * @since 3.0.0\n */\n\n private readonly declaration: DeclarationModel;\n\n /**\n * The configuration currently in force, replaced whenever the file behind it is reparsed.\n *\n * @see parseConfig\n * @since 3.0.0\n */\n\n private parsedConfig: ParsedCommandLine;\n\n /**\n * The snapshot version of the configuration file behind the current parse.\n *\n * @remarks\n * Taken from the shared file model, which advances a version whenever the watcher re-reads a file that changed,\n * so comparing it against the version the model now holds tells {@link reload} whether anything needs reparsing.\n *\n * @see reload\n * @since 3.0.0\n */\n\n private configVersion: number;\n\n /**\n * The cache backing {@link resolve}, rebuilt whenever the compiler options change.\n *\n * @see createResolutionCache\n * @since 3.0.0\n */\n\n private resolutionCache: ModuleResolutionCache;\n\n /**\n * The builder program of the last {@link check}, carried forward, so the next check only revisits what changed.\n *\n * @remarks\n * Absent before the first check and after a {@link reload}, either of which makes the next check a full pass.\n *\n * @since 3.0.0\n */\n\n private builder?: EmitAndSemanticDiagnosticsBuilderProgram;\n\n /**\n * Creates a service for one configuration file.\n *\n * @param configPath - Path of the `tsconfig.json` to run against\n *\n * @remarks\n * Prefer injecting the service, which shares and reference counts instances per configuration path.\n * An instance built here stays outside the shared cache, so nothing else can reach it,\n * and {@link dispose} has no hold of its own to release.\n * A configuration that cannot be read does not throw - {@link parseConfig} falls back to a built-in default.\n *\n * @example\n * ```ts\n * const service = new TypescriptService('tsconfig.build.json');\n * service.config.options.emitDeclarationOnly; // true - forced on regardless of the file\n * ```\n *\n * @see acquire\n * @since 3.0.0\n */\n\n constructor(readonly configPath: string = 'tsconfig.json') {\n this.parsedConfig = this.parseConfig();\n this.languageHostService = new LanguageHostService(this.parsedConfig);\n this.configVersion = this.languageHostService.filesCache.touch(this.configPath).version;\n this.resolutionCache = this.createResolutionCache();\n this.languageService = ts.createLanguageService(\n this.languageHostService, ts.createDocumentRegistry(true)\n );\n\n this.declaration = new DeclarationModel(this);\n }\n\n /**\n * Reparses the configuration of every shared instance whose file has changed.\n *\n * @param force - Whether every instance reparses regardless of whether its configuration file has moved\n * @returns The configuration paths reparsed by this call, in the order their instances were acquired\n *\n * @remarks\n * This walks the whole shared cache rather than reaching one instance through a holder.\n * A single call after a watch event covers every project in the process,\n * and a configuration several consumers share is reparsed once rather than once per consumer.\n *\n * Each version comes from the shared file model as it stands rather than from disk,\n * since re-reading a changed file is the watcher's part,\n * so an instance whose configuration has not moved costs a map lookup and nothing more.\n *\n * Forcing skips that comparison and reparses every instance\n * that catches a change the configuration file's own version misses, such as an edit to a file it extends.\n * The cost is the state of every project in the process rather than the state of what moved.\n *\n * A change discards everything the old options fed:\n * the file set, the resolution cache, the cached declarations, the cached diagnostics, and the builder program,\n * so the next {@link check} runs as a full pass.\n * An instance the constructor built rather than the cache is never reached here.\n *\n * @example\n * ```ts\n * const service = inject(TypescriptService, 'tsconfig.json');\n *\n * TypescriptService.reload(); // [] - nothing has been written since the configuration was read\n * TypescriptService.reload(); // [ 'tsconfig.json' ] - reparsed, and service.config describes the edit\n * TypescriptService.reload(true); // [ 'tsconfig.json' ] - reparsed with nothing written since\n * ```\n *\n * @see check\n * @see acquire\n *\n * @since 3.0.0\n */\n\n static reload(force: boolean = false): Array<string> {\n const reloaded: Array<string> = [];\n for (const [ path, entry ] of TypescriptService.cache) {\n if (entry.instance.refresh(force)) reloaded.push(path);\n }\n\n return reloaded;\n }\n\n /**\n * The parsed configuration this service is running against.\n *\n * @returns The compiler options, file names, and raw configuration currently in force\n *\n * @remarks\n * {@link reload} replaces it wholesale,\n * so a reference taken from here describes the configuration as it stood when it was read.\n *\n * @example\n * ```ts\n * service.config.options.rootDir; // 'D:/app' - defaulted to the working directory when the file omits it\n * service.config.fileNames.length; // 42\n * ```\n *\n * @since 3.0.0\n */\n\n get config(): ParsedCommandLine {\n return this.parsedConfig;\n }\n\n /**\n * Type-checks the project and returns the diagnostics of the files named.\n *\n * @param reachable - Files to report on, as the build reaches them, reporting everything checked when omitted\n * @returns Diagnostics of those files, formatted for reporting\n *\n * @remarks\n * Only the files the builder reports as affected are rechecked,\n * their semantic, syntactic, and suggestion diagnostics replacing what was cached for them,\n * while untouched files keep the diagnostics they already had.\n * That is what makes the result whole-project without rechecking it whole.\n * A file matched by the configuration's `exclude` globs is skipped,\n * and a file that has left the program loses its cached diagnostics\n * rather than reporting them against a file that is no longer there.\n *\n * The check covers the program while the report covers `reachable`,\n * which is what lets several variants share one service:\n * the diagnostics are computed once for whatever changed,\n * and each variant reads back the files its own build reaches at the cost of a lookup per file.\n * Narrowing the check instead would consume a file for the variant that saw it first\n * and leave the next one with nothing to report.\n * Each name is resolved as it is read, so a build's own paths serve as they are, relative or absolute.\n *\n * @example\n * ```ts\n * service.check(); // [ { file: 'src/index.ts', line: 3, column: 7, code: 2322, category: 1, message: '...' } ]\n * service.check(); // [] once the file is fixed and the watcher has refreshed it\n *\n * service.check(context.stage.reachableFiles); // only what this variant's build reaches\n * ```\n *\n * @see DiagnosticInterface\n * @see reconcileDiagnostics\n *\n * @since 3.0.0\n */\n\n check(reachable?: Iterable<string>): Array<DiagnosticInterface> {\n const program = this.languageService.getProgram();\n if (!program) return [];\n\n const ignore = this.languageHostService.ignoreSourceFile;\n const skip = (file: SourceFile): boolean => {\n if(file.fileName.includes('node_modules')) return true;\n\n return ignore(file);\n };\n\n let affected;\n this.builder = ts.createEmitAndSemanticDiagnosticsBuilderProgram(program, this.builderHost, this.builder);\n while (affected = this.builder.getSemanticDiagnosticsOfNextAffectedFile(undefined, skip)) {\n if ('fileName' in affected.affected) {\n const file = affected.affected;\n this.diagnosticsCache.set(file.fileName, [\n ...affected.result,\n ...this.builder!.getSyntacticDiagnostics(file),\n ...this.languageService.getSuggestionDiagnostics(file.fileName)\n ].map(diagnostic => this.formatDiagnostic(diagnostic)));\n }\n }\n\n return this.reconcileDiagnostics(program, reachable ?? this.diagnosticsCache.keys());\n }\n\n /**\n * Writes one declaration file per project file the entry points reach.\n *\n * @param entryPoints - Entry files to walk, keyed by the output name each entry itself is written under\n * @param outdir - Directory to write into, defaulting to the configuration's `outDir` and then to `dist`\n * @returns The output paths written by this call, empty when everything was already current\n *\n * @remarks\n * This path always passes a directory on, so `declarationDir` is never consulted.\n * Name it explicitly to write somewhere other than `outDir`.\n * The keys name the entries alone, while the files reached through them keep the layout of the source tree.\n * Declarations come out of this project's program, so the checker writes the types the source leaves out,\n * and a type it cannot write surfaces through {@link check} rather than as a failure to write.\n *\n * @example\n * ```ts\n * await service.emit({ index: 'src/index.ts' }); // [ 'dist/index.d.ts', 'dist/builder.d.ts' ] - absolute\n * await service.emit({ index: 'src/index.ts' }); // [] - nothing changed since\n * await service.emit({ index: 'src/index.ts' }, 'types'); // the same files, written under ./types\n * ```\n *\n * @see emitBundle\n * @since 3.0.0\n */\n\n async emit(entryPoints: Record<string, string>, outdir?: string): Promise<Array<string>> {\n outdir ??= this.config.options.outDir ?? 'dist';\n\n return this.declaration.emit(entryPoints, outdir);\n }\n\n /**\n * Writes one bundled declaration file per entry point.\n *\n * @param entryPoints - Entry files to bundle, keyed by the output name each is written under\n * @param outdir - Directory to write into, defaulting to the configuration's `outDir` and then to `dist`\n * @returns The output paths written, in the order the entry points were given\n *\n * @remarks\n * Each entry becomes one file carrying the declarations of everything it reaches,\n * so a package ships a single `.d.ts` instead of a tree mirroring its source.\n * The keys name the outputs, with `.d.ts` appended to each,\n * which is the shape the bundler's own entry points take and what keeps two entries of one name apart.\n * Every call rebuilds its bundles rather than reading a cache, so unlike {@link emit} this always writes.\n *\n * @example\n * ```ts\n * await service.emitBundle({ index: 'src/index.ts' }, 'dist'); // [ 'D:/app/dist/index.d.ts' ]\n * ```\n *\n * @see emit\n * @since 3.0.0\n */\n\n async emitBundle(entryPoints: Record<string, string>, outdir?: string): Promise<Array<string>> {\n outdir ??= this.config.options.outDir ?? 'dist';\n\n return this.declaration.emitBundle(entryPoints, outdir);\n }\n\n /**\n * Re-reads a batch of files so the language service sees their current content.\n *\n * @param files - Paths to refresh, relative or absolute\n *\n * @remarks\n * Each path is tracked as it is refreshed,\n * so naming a file the program has not reached yet adds it rather than passing over it.\n *\n * @example\n * ```ts\n * service.touchFiles([ 'src/index.ts' ]);\n * service.check(); // now reflects what is on disk\n * ```\n *\n * @see LanguageHostService.refreshFiles\n * @since 2.0.0\n */\n\n touchFiles(files: Array<string>): void {\n this.languageHostService.refreshFiles(files);\n }\n\n /**\n * Resolves a specifier the way the type checker resolves it.\n *\n * @param specifier - Module specifier as written in the source\n * @param containingFile - File the specifier was written in, since resolution is relative to its directory\n * @returns The resolved module, or `undefined` when the specifier resolves to nothing\n *\n * @remarks\n * An alias or a `paths` mapping resolves the way the compiler sees it rather than the way Node would,\n * which is what lets the declarations rewrite an alias into a path that still resolves.\n * The result carries two fields beyond what the compiler returns:\n * the directory the specifier resolved against, and the path from that directory to the target.\n * The first resolution attaches both, and the cached entry serves them back.\n * With no containing file, the working directory stands in for it.\n *\n * @example\n * ```ts\n * const module = service.resolve('@components/builder', 'D:/app/src/index.ts');\n *\n * module?.resolvedFileName; // 'D:/app/src/components/builder.ts'\n * module?.relativeFileName; // './components/builder.ts'\n * module?.isExternalLibraryImport; // false - a project file, not a package\n * ```\n *\n * @see ResolvedModuleInterface\n * @since 3.0.0\n */\n\n resolve(specifier: string, containingFile?: string): ResolvedModuleInterface | undefined {\n const container = containingFile ? this.languageHostService.filesCache.resolve(dirname(containingFile)) : process.cwd();\n const dirCache = this.resolutionCache.getOrCreateCacheForDirectory(container);\n const cached = dirCache.get(specifier, undefined)?.resolvedModule;\n if(cached) return cached as ResolvedModuleInterface;\n\n const result = <ResolvedModuleInterface> ts.resolveModuleName(\n specifier, containingFile ?? '', this.parsedConfig.options, this.languageHostService, this.resolutionCache\n ).resolvedModule;\n\n if (result) {\n const path = relative(container, result.resolvedFileName);\n\n result.container = container;\n result.relativeFileName = path.startsWith('.') ? path : `./${ path }`;\n }\n\n return result;\n }\n\n /**\n * Releases this consumer's hold on the shared instance.\n *\n * @remarks\n * The language service is torn down and the instance dropped from the shared cache\n * only once the last holder has released it,\n * so a service several consumers share outlives any one of them.\n * The hold released is the one the shared cache keeps under this service's configuration path,\n * so a release takes effect only on an instance the shared cache holds.\n *\n * @example\n * ```ts\n * const service = inject(TypescriptService);\n *\n * service.dispose(); // released - torn down only if nothing else holds it\n * ```\n *\n * @see acquire\n * @since 3.0.0\n */\n\n dispose(): void {\n const entry = TypescriptService.cache.get(this.configPath);\n if (!entry) return;\n\n entry.refCount--;\n if (entry.refCount > 0) return;\n\n this.languageService.dispose();\n TypescriptService.cache.delete(this.configPath);\n }\n\n /**\n * Releases the service when it leaves a `using` scope.\n *\n * @remarks\n * Delegates to {@link dispose}, so scope-bound and explicit release share one reference count.\n *\n * @example\n * ```ts\n * {\n * using service = inject(TypescriptService);\n * service.check();\n * } // released here\n * ```\n *\n * @see dispose\n * @since 3.0.0\n */\n\n [Symbol.dispose ?? Symbol.for('Symbol.dispose')](): void {\n this.dispose();\n }\n\n /**\n * Returns the shared instance for a configuration path, creating it on the first request.\n *\n * @param path - Path of the `tsconfig.json` the instance runs against\n * @returns The instance for that path, with its reference count raised\n *\n * @remarks\n * The path is normalized before it serves as the key,\n * so the same configuration reached by two spellings is one instance.\n * The instance is constructed with that normalized key,\n * which is what lets a release find its own entry.\n * Reached through the injectable factory rather than called directly.\n *\n * @see dispose\n * @since 3.0.0\n */\n\n private static acquire(path: string = 'tsconfig.json'): TypescriptService {\n const key = normalize(path);\n const entry = TypescriptService.cache.get(key);\n\n if (entry) {\n entry.refCount++;\n\n return entry.instance;\n }\n\n const instance = new TypescriptService(key);\n TypescriptService.cache.set(key, { instance, refCount: 1 });\n\n return instance;\n }\n\n /**\n * Rebuilds everything this instance derives from its compiler options once its configuration file has moved.\n *\n * @param force - Whether the rebuild runs even though the configuration file's version has not moved\n * @returns Whether the configuration was reparsed\n *\n * @remarks\n * Split out of {@link reload}, so the shared cache decides which instance reloads,\n * while the state it rebuilds stays with the instance holding it.\n * The version is the one the shared file model already holds,\n * since re-reading a file that changed is the watcher's part,\n * so this observes a change rather than going looking for one.\n * Forcing drops that guard and rebuilds regardless,\n * which is the only way through for a change the version leaves out.\n * The version is taken and stored either way,\n * so a forced rebuild leaves nothing behind for the next call to mistake for a change.\n *\n * @see reload\n * @since 3.0.0\n */\n\n private refresh(force: boolean = false): boolean {\n const { version } = this.languageHostService.filesCache.touch(this.configPath);\n if (!force && version === this.configVersion) return false;\n\n this.configVersion = version;\n this.parsedConfig = this.parseConfig();\n this.languageHostService.options = this.parsedConfig;\n this.resolutionCache = this.createResolutionCache();\n this.declaration.clear();\n this.diagnosticsCache.clear();\n this.builder = undefined;\n\n return true;\n }\n\n /**\n * Builds the module resolution cache for the current options.\n *\n * @returns A cache keyed the way the language host normalizes paths\n *\n * @remarks\n * Real paths go through the host,\n * so a symlinked file is keyed the same here as in the file cache,\n * and the two cannot disagree about which file a specifier reached.\n *\n * @since 3.0.0\n */\n\n private createResolutionCache(): ModuleResolutionCache {\n return ts.createModuleResolutionCache(\n ts.sys.getCurrentDirectory(),\n path => this.languageHostService.realpath(path),\n this.parsedConfig.options\n );\n }\n\n /**\n * Reads the diagnostics of a set of files out of the cache, dropping whatever no longer belongs to the program.\n *\n * @param program - Program the files are looked up in\n * @param reachable - Files to read, named as the caller has them, relative or absolute\n * @returns The cached diagnostics of those files, in the order they were named\n *\n * @remarks\n * The walk covers the files asked for rather than the cache,\n * so reporting one variant's inputs costs what that variant reaches rather than what the project holds.\n * Each name is resolved before the lookup,\n * since the cache is keyed by the absolute path the compiler reported,\n * while a build names its inputs relative to its own working directory.\n * A file that leaves the program - deleted, excluded, or no longer reached -\n * would otherwise keep reporting the diagnostics it had when it left,\n * since nothing marks it affected once it is gone,\n * so a name the program no longer carries is dropped from the cache as it is read.\n *\n * @since 3.0.0\n */\n\n private reconcileDiagnostics(program: Program, reachable: Iterable<string>): Array<DiagnosticInterface> {\n const files = this.languageHostService.filesCache;\n const result: Array<DiagnosticInterface> = [];\n\n for (const name of reachable) {\n const path = files.resolve(name);\n const diagnostics = this.diagnosticsCache.get(path);\n\n if (!diagnostics) continue;\n if (program.getSourceFile(path)) result.push(...diagnostics);\n else this.diagnosticsCache.delete(path);\n }\n\n return result;\n }\n\n /**\n * Reduces a compiler diagnostic to the shape that reporting consumes.\n *\n * @param diagnostic - Diagnostic as the compiler produced it\n * @returns The message and category, with the position and code when the diagnostic has a location\n *\n * @remarks\n * Chained messages are flattened into one string, and line and column are counted from one rather than from zero,\n * since the compiler counts from zero while every editor and terminal reports from one.\n * A diagnostic with no file - a configuration error, say - carries the message and category alone.\n *\n * @see DiagnosticInterface\n * @since 2.0.0\n */\n\n private formatDiagnostic(diagnostic: Diagnostic): DiagnosticInterface {\n const result: DiagnosticInterface = {\n message: ts.flattenDiagnosticMessageText(diagnostic.messageText, '\\n'),\n category: diagnostic.category\n };\n\n if (diagnostic.file && diagnostic.start !== undefined) {\n const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);\n result.file = diagnostic.file.fileName;\n result.line = line + 1;\n result.column = character + 1;\n result.code = diagnostic.code;\n }\n\n return result;\n }\n\n /**\n * Reads the configuration file and forces the options this build depends on.\n *\n * @returns The parsed configuration, with the forced options applied\n *\n * @remarks\n * Declaration emit is forced on and source maps off,\n * since this asks the compiler for types alone while the bundler produces the JavaScript.\n * `stripInternal` and `skipLibCheck` follow from that.\n * A configuration that cannot be read yields a built-in default rather than an error,\n * so a project without a `tsconfig.json` still type-checks under sensible settings.\n * `rootDir` falls back to the working directory,\n * without which output paths would follow whichever directory the sources happen to share.\n *\n * @since 2.0.0\n */\n\n private parseConfig(): ParsedCommandLine {\n let config = ts.getParsedCommandLineOfConfigFile(\n this.configPath,\n {\n sourceMap: false,\n skipLibCheck: true,\n stripInternal: true,\n declarationMap: false,\n emitDeclarationOnly: true\n },\n {\n ...ts.sys,\n onUnRecoverableConfigFileDiagnostic: () => {}\n }\n );\n\n if (!config) {\n config = {\n options: {\n strict: true,\n target: ts.ScriptTarget.ESNext,\n module: ts.ModuleKind.NodeNext,\n sourceMap: false,\n skipLibCheck: true,\n stripInternal: true,\n declarationMap: false,\n emitDeclarationOnly: true,\n moduleResolution: ts.ModuleResolutionKind.NodeNext\n },\n errors: [],\n fileNames: [],\n projectReferences: undefined\n };\n }\n\n config.options = {\n ...config.options,\n noEmit: true,\n rootDir: config.options?.rootDir ?? process.cwd(),\n isolatedModules: false,\n useCaseSensitiveFileNames: true\n };\n\n return config;\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { TypescriptService } from '@typescript/services/typescript.service';\nimport type { DeclarationEntryInterface } from './interfaces/declaration-model.interface';\nimport type { NamedBindingInterface, ParseContextInterface } from './interfaces/declaration-model.interface';\nimport type { Declaration, Directive, ModuleExportName, Statement, StringLiteral } from '@oxc-project/types';\nimport type { BundleSurfaceInterface, MergedImportInterface } from './interfaces/declaration-model.interface';\nimport type { ExportNamedDeclaration, ImportDeclaration, TSImportEqualsDeclaration } from '@oxc-project/types';\nimport type { ExportAllDeclaration, ExportDefaultDeclaration, ExportDefaultDeclarationKind } from '@oxc-project/types';\n\n/**\n * Imports\n */\n\nimport { existsSync } from 'fs';\nimport { parseSync } from 'oxc-parser';\nimport { inject } from '@remotex-labs/xinject';\nimport { mkdir, writeFile } from 'fs/promises';\nimport { Char } from '@constants/char.constant';\nimport { FilesModel } from '@models/files.model';\nimport { join, dirname, relative } from '@remotex-labs/xmap';\nimport { applyEdits, removeNode } from '@components/transformer.component';\nimport { HeaderDeclarationBundle } from '@typescript/constants/typescript.constant';\n\n/**\n * Builds and caches the declaration of every file a build touches, in both the forms it needs.\n *\n * @remarks\n * Each file is reduced to a {@link DeclarationEntryInterface}: the standalone declaration with its project specifiers\n * resolved, the same text stripped down to inlinable declarations, and the dependency, import, and export records that\n * stripping produced.\n * Declarations are emitted by the project's own program, so the checker writes the types an annotation leaves out,\n * and an entry costs one declaration emit and one parse.\n * Both forms and every record come out of that single parse.\n * Entries are held against the snapshot version of their file,\n * so a file is rebuilt only once the file model has observed the change,\n * and {@link clear} drops the cache when the compiler options behind the entries move.\n * One instance owns one cache,\n * so a build that wants entries shared across its steps passes the model around rather than constructing a second one.\n *\n * @example\n * ```ts\n * const declarations = new DeclarationModel(inject(TypescriptService));\n * const entry = declarations.touch('src/index.ts');\n *\n * entry.content; // 'declare const version: string;\\n'\n * entry.declaration; // the same text, prefixed with its imports\n * entry.projectDependencies; // Set { 'D:/app/src/builder.ts' }\n * declarations.touch('src/index.ts') === entry; // true - unchanged file, cached entry\n * ```\n *\n * @see DeclarationEntryInterface\n * @since 3.0.0\n */\n\nexport class DeclarationModel {\n /**\n * Entries keyed by the resolved absolute path of the file they describe.\n *\n * @remarks\n * Exposed for consumers that walk an already-built graph.\n * Use {@link touch} to build or refresh an entry.\n *\n * @example\n * ```ts\n * declarations.touch('src/index.ts');\n * declarations.cache.size; // 1\n * ```\n *\n * @see DeclarationEntryInterface\n * @since 3.0.0\n */\n\n readonly cache = new Map<string, DeclarationEntryInterface>();\n\n /**\n * Shared file snapshot cache the entries are versioned against.\n *\n * @since 3.0.0\n */\n\n private readonly filesCache = inject(FilesModel);\n\n /**\n * Entry version last written to each output path.\n *\n * @remarks\n * Keyed by output path rather than source path,\n * so emitting into a different directory writes every file again instead of reporting them as already current.\n * What it records is what was written rather than what is on disk,\n * so {@link emit} checks the file is still there before it passes over one,\n * which is what makes an output that something else removed come back on the next run.\n *\n * @since 3.0.0\n */\n\n private readonly emitted = new Map<string, number>();\n\n /**\n * Creates a declaration cache bound to one TypeScript service.\n *\n * @param ts - Service whose module resolution decides which specifiers are project files\n *\n * @example\n * ```ts\n * const declarations = new DeclarationModel(inject(TypescriptService));\n * declarations.cache.size; // 0\n * ```\n *\n * @see TypescriptService\n * @since 3.0.0\n */\n\n constructor(private readonly ts: TypescriptService) {}\n\n /**\n * Drops every cached entry.\n *\n * @remarks\n * Needed when something the declarations depend on has changed without the snapshot versions reflecting it -\n * the compiler options, or the resolution cache behind them.\n * A file whose content changed does not need this, since its entry is rebuilt on the next {@link touch}.\n * The record of what already reached the disk goes with them,\n * so the next call to {@link emit} writes every file again,\n * which is also what a cleaned output directory calls for.\n *\n * @example\n * ```ts\n * declarations.touch('src/index.ts');\n * declarations.clear();\n * declarations.cache.size; // 0\n * ```\n *\n * @see touch\n * @since 3.0.0\n */\n\n clear(): void {\n this.cache.clear();\n this.emitted.clear();\n }\n\n /**\n * Returns the declaration entry of a file, building it only when the cached one is stale.\n *\n * @param path - Filesystem path of the file, relative or absolute\n * @returns The entry describing the file's declarations, dependencies, and exports\n *\n * @remarks\n * The file is tracked through the file model, so a path never seen before is read from the disk once,\n * and a tracked path costs a map lookup.\n * The cached entry is returned whenever its version still matches the file's snapshot version, which only advances\n * when the file model observes a change on disk.\n * A file that is missing or unreadable yields an entry built from empty content rather than throwing.\n *\n * @example\n * ```ts\n * const entry = declarations.touch('src/index.ts');\n * entry.version; // 1\n * declarations.touch('src/index.ts') === entry; // true\n * ```\n *\n * @see clear\n * @see DeclarationEntryInterface\n *\n * @since 3.0.0\n */\n\n touch(path: string): DeclarationEntryInterface {\n const target = this.filesCache.resolve(path);\n const file = this.filesCache.touch(target);\n const cached = this.cache.get(target);\n\n if (cached?.version === file.version) return cached;\n\n const entry = this.build(target, file.version);\n this.cache.set(target, entry);\n\n return entry;\n }\n\n /**\n * Writes one declaration file per project file the entry points reach, skipping what has not changed.\n *\n * @param entryPoints - Entry files to walk, keyed by the output name each entry itself is written under\n * @param outdir - Directory to write into, overriding the configuration's `declarationDir` and `outDir`\n * @returns The output paths written by this call, empty when everything was already current\n *\n * @remarks\n * The walk follows the dependency edges out of each entry, so a project whose `tsconfig.json` lists only its entry\n * points still emits every file those entries reach.\n * Nothing outside the project is emitted, since only project files are edges,\n * and a `.d.ts` input is skipped along with everything only it reaches - it is already a declaration.\n * A key names the output of the entry it is keyed to and of nothing else.\n * The files reached through it keep mirroring the source tree the way `tsc` lays them out:\n * `declarationDir` wins over `outDir`, and the per-file path is taken relative to `rootDir`.\n * A file whose entry was written unchanged since the last call is left alone, so a watch cycle rewrites only what\n * moved.\n *\n * @example\n * ```ts\n * await declarations.emit({ main: 'src/index.ts' }); // [ 'dist/main.d.ts', 'dist/builder.d.ts' ]\n * await declarations.emit({ main: 'src/index.ts' }); // [] - nothing changed\n * await declarations.emit({ main: 'src/index.ts' }, './types'); // the same files, written under ./types\n * ```\n *\n * @see clear\n * @see emitBundle\n *\n * @since 3.0.0\n */\n\n async emit(entryPoints: Record<string, string>, outdir?: string): Promise<Array<string>> {\n const outputs: Array<string> = [];\n const contents: Array<string> = [];\n const visited = new Set<string>();\n const names = new Map<string, string>();\n\n for (const [ name, entry ] of Object.entries(entryPoints))\n names.set(this.filesCache.resolve(entry), name);\n\n const pending = [ ...names.keys() ];\n while (pending.length > 0) {\n const target = pending.pop()!;\n if (visited.has(target) || target.endsWith('.d.ts')) continue;\n visited.add(target);\n\n const entry = this.touch(target);\n for (const dependency of entry.projectDependencies)\n if (!visited.has(dependency)) pending.push(dependency);\n\n const output = this.outputPath(target, outdir, names.get(target));\n if (this.emitted.get(output) === entry.version && existsSync(output)) continue;\n\n this.emitted.set(output, entry.version);\n outputs.push(output);\n contents.push(entry.declaration);\n }\n\n return this.write(outputs, contents);\n }\n\n /**\n * Bundles every entry point and writes each one to a declaration file of its own.\n *\n * @param entryPoints - Entry files to bundle, keyed by the output name each is written under\n * @param outdir - Directory to write into, overriding the configuration's `declarationDir` and `outDir`\n * @returns The output paths written, in the order the entry points were given\n *\n * @remarks\n * The key names the output rather than the source doing so, `.d.ts` being appended to it, so two entries both\n * called `index.ts` are told apart by the names they were keyed under.\n * A key carrying a directory writes into it, and the directory is created if it is not there.\n * Bundles are always rebuilt, since assembling one from cached entries costs little,\n * and they open with {@link HeaderDeclarationBundle} so a generated file is recognizable as one.\n * With no output directory configured or passed, they land in the working directory.\n *\n * @example\n * ```ts\n * await declarations.emitBundle({ index: 'src/index.ts', 'utils/index': 'src/utils/index.ts' }, 'dist/types');\n * // [ 'D:/app/dist/types/index.d.ts', 'D:/app/dist/types/utils/index.d.ts' ]\n * ```\n *\n * @see emit\n * @since 3.0.0\n */\n\n async emitBundle(entryPoints: Record<string, string>, outdir?: string): Promise<Array<string>> {\n const options = this.ts.config.options;\n const base = this.filesCache.resolve(outdir ?? options.declarationDir ?? options.outDir ?? '.');\n\n return this.write(\n Object.keys(entryPoints).map(name => join(base, `${ name }.d.ts`)),\n Object.values(entryPoints).map(entry => this.bundle(entry))\n );\n }\n\n /**\n * Builds the bundled declaration text of one entry point.\n *\n * @param entry - Filesystem path of the entry file, relative or absolute\n * @returns The complete declaration file content, header included\n *\n * @remarks\n * Nothing is written and nothing is cached beyond the entries themselves, so the same entry can be bundled\n * repeatedly, and each call reflects the files as the cache currently sees them.\n * Declarations are inlined once per file even when several files depend on it, and a dependency cycle is walked\n * once rather than followed around.\n *\n * @see render\n * @since 3.0.0\n */\n\n private bundle(entry: string): string {\n const target = this.filesCache.resolve(entry);\n const node = this.touch(target);\n\n return this.render(this.collectClosure(target, node), this.collectSurface(target, node));\n }\n\n /**\n * Creates the directories of a batch and writes its files concurrently.\n *\n * @param outputs - Absolute output paths to write\n * @param contents - Content of each output, in the same order\n * @returns The written paths, for direct return by callers\n *\n * @remarks\n * Each directory is created once for the whole batch rather than once per file, and an empty batch touches the disk\n * not at all.\n *\n * @since 3.0.0\n */\n\n private async write(outputs: Array<string>, contents: Array<string>): Promise<Array<string>> {\n if (outputs.length < 1) return outputs;\n\n const directories = new Set(outputs.map(output => dirname(output)));\n await Promise.all([ ...directories ].map(directory => mkdir(directory, { recursive: true })));\n await Promise.all(outputs.map((output, index) => writeFile(output, contents[index], 'utf-8')));\n\n return outputs;\n }\n\n /**\n * Maps a source path to the declaration path it is written to.\n *\n * @param source - Resolved absolute path of the source file\n * @param outdir - Directory overriding both configured output directories\n * @param name - Output name to use instead of the one the source implies, carrying no extension\n * @returns The absolute output path\n *\n * @remarks\n * The directory is the first of `outdir`, `declarationDir`, and `outDir` that is set,\n * and the source's own directory only when none of them is.\n * A name replaces everything the source would have decided, `.d.ts` being appended to it, and a name carrying a\n * directory nests the output inside the base.\n * Without one the path mirrors the source tree relative to `rootDir` - the source directory standing in when no\n * `rootDir` is set, which flattens the output the way `tsc` does - and the extension follows the input, so `.ts`\n * and `.tsx` become `.d.ts` while `.mts` and `.cts` keep their module flavor as `.d.mts` and `.d.cts`.\n *\n * @since 3.0.0\n */\n\n private outputPath(source: string, outdir?: string, name?: string): string {\n const { declarationDir, outDir, rootDir } = this.ts.config.options;\n const base = outdir ?? declarationDir ?? outDir;\n const target = base ? this.filesCache.resolve(base) : dirname(source);\n if (name) return join(target, `${ name }.d.ts`);\n\n const root = rootDir ? this.filesCache.resolve(rootDir) : dirname(source);\n\n return join(target, relative(root, source).replace(/\\.([cm]?)tsx?$/, '.d.$1ts'));\n }\n\n /**\n * Collects every project file the entry reaches, dependencies first.\n *\n * @param target - Resolved absolute path of the entry file\n * @param entry - Cache entry of the entry file\n * @returns The entries to inline, in the order their content is concatenated\n *\n * @remarks\n * A depth-first walk over the dependency edges with an explicit stack, so a deep dependency chain cannot overflow\n * the stack, and a visited set, so a cycle terminates, and a shared dependency is inlined once.\n * The entry counts as visited from the start, so a dependency cycling back to it does not inline it twice, and it\n * lands last regardless, which keeps the file the bundle describes at the bottom.\n *\n * @since 3.0.0\n */\n\n private collectClosure(target: string, entry: DeclarationEntryInterface): Array<DeclarationEntryInterface> {\n const visited = new Set<string>([ target ]);\n const closure: Array<DeclarationEntryInterface> = [];\n const pending = [ ...entry.projectDependencies ];\n\n while (pending.length > 0) {\n const dependency = pending.pop()!;\n if (visited.has(dependency)) continue;\n visited.add(dependency);\n\n const node = this.touch(dependency);\n closure.push(node);\n\n for (const nested of node.projectDependencies)\n if (!visited.has(nested)) pending.push(nested);\n }\n\n closure.push(entry);\n\n return closure;\n }\n\n /**\n * Collects the names and re-export statements the bundle exposes.\n *\n * @param target - Resolved absolute path of the entry file\n * @param entry - Cache entry of the entry file\n * @returns The entry's surface, merged with the surface of every project file it star re-exports\n *\n * @remarks\n * Star re-exports of project files are followed transitively, their names becoming the entry's own, while package\n * re-exports are kept as statements and passed straight through.\n * The entry counts as visited from the start, so a star re-export cycling back to it is not walked again.\n * Namespace re-exports of project files are left out: flattening one would mean synthesizing a `declare namespace`\n * around the target's exports, which the inlined fragments do not describe well enough.\n *\n * @see BundleSurfaceInterface\n * @since 3.0.0\n */\n\n private collectSurface(target: string, entry: DeclarationEntryInterface): BundleSurfaceInterface {\n const exports = new Set<string>();\n const statements = new Set<string>();\n const visited = new Set<string>([ target ]);\n const pending = [ entry ];\n\n while (pending.length > 0) {\n const node = pending.pop()!;\n for (const binding of node.projectExports.exports) exports.add(this.clause(binding));\n\n for (const [ module, bindings ] of Object.entries(node.packageExports)) {\n if (bindings.star) statements.add(`export * from '${ module }';`);\n if (bindings.named?.length)\n statements.add(`export { ${ bindings.named.map(binding => this.clause(binding)).join(', ') } } from '${ module }';`);\n\n for (const name of bindings.namespaces ?? []) statements.add(`export * as ${ name } from '${ module }';`);\n }\n\n for (const star of node.projectExports.star) {\n if (visited.has(star)) continue;\n visited.add(star);\n pending.push(this.touch(star));\n }\n }\n\n return { exports, statements };\n }\n\n /**\n * Merges the package imports of every inlined file into one record per module.\n *\n * @param closure - Entries whose content the bundle carries\n * @returns The merged bindings, keyed by module specifier in first-seen order\n *\n * @remarks\n * One pass over the files and their modules folds each module's side effect flag, default binding, namespaces,\n * and named bindings into a single record the bundle can write back as statements.\n *\n * @see MergedImportInterface\n * @since 3.0.0\n */\n\n private mergeImports(closure: Array<DeclarationEntryInterface>): Map<string, MergedImportInterface> {\n const merged = new Map<string, MergedImportInterface>();\n\n for (const node of closure) {\n for (const [ module, bindings ] of Object.entries(node.packageImports)) {\n let entry = merged.get(module);\n if (!entry) merged.set(module, entry = { side: false, named: new Set(), namespaces: new Set() });\n\n if (bindings.side) entry.side = true;\n entry.default ??= bindings.default;\n for (const name of bindings.namespaces ?? []) entry.namespaces.add(name);\n for (const binding of bindings.named ?? []) entry.named.add(this.clause(binding));\n }\n }\n\n return merged;\n }\n\n /**\n * Writes the merged imports back out as import statements.\n *\n * @param merged - Bindings collected per module\n * @returns One statement per import form a module was used with\n *\n * @remarks\n * A module can need several statements: a side effect import, one for each namespace binding,\n * and one carrying its default and named bindings together.\n * Named bindings are sorted, so the same set of files always produces the same bundle.\n *\n * @since 3.0.0\n */\n\n private renderImports(merged: Map<string, MergedImportInterface>): Array<string> {\n const statements: Array<string> = [];\n\n for (const [ module, entry ] of merged) {\n if (entry.side) statements.push(`import '${ module }';`);\n for (const name of entry.namespaces) statements.push(`import * as ${ name } from '${ module }';`);\n\n const clauses: Array<string> = [];\n if (entry.default) clauses.push(entry.default);\n if (entry.named.size > 0) clauses.push(`{ ${ [ ...entry.named ].sort().join(', ') } }`);\n if (clauses.length > 0) statements.push(`import ${ clauses.join(', ') } from '${ module }';`);\n }\n\n return statements;\n }\n\n /**\n * Assembles the finished bundle from its header, imports, inlined content, and exports.\n *\n * @param closure - Entries to inline, dependencies first\n * @param surface - Names and statements the bundle exposes\n * @returns The complete declaration file content\n *\n * @remarks\n * Imports are merged over the whole closure rather than the surface, since every inlined declaration is free to\n * reference them, while the exports come from the surface alone.\n * A bundle that exposes nothing still closes with an empty export clause, without which its declarations would be\n * read as globals rather than as a module.\n *\n * @see HeaderDeclarationBundle\n * @since 3.0.0\n */\n\n private render(closure: Array<DeclarationEntryInterface>, surface: BundleSurfaceInterface): string {\n const parts: Array<string> = [ HeaderDeclarationBundle ];\n const imports = this.renderImports(this.mergeImports(closure));\n if (imports.length > 0) parts.push(...imports, '');\n\n for (const node of closure) {\n const content = node.content.trim();\n if (content) parts.push(content, '');\n }\n\n if (surface.exports.size > 0) parts.push(`export {\\n\\t${ [ ...surface.exports ].sort().join(',\\n\\t') }\\n};`);\n parts.push(...surface.statements);\n if (surface.exports.size < 1 && surface.statements.size < 1) parts.push('export {};');\n\n return `${ parts.join('\\n') }\\n`;\n }\n\n /**\n * Writes a binding the way an import or export clause spells it.\n *\n * @param binding - Name and the alias it was renamed to, if any\n * @returns The bare name, or `name as alias` when the clause renamed it\n *\n * @see NamedBindingInterface\n * @since 3.0.0\n */\n\n private clause(binding: NamedBindingInterface): string {\n return binding.alias ? `${ binding.name } as ${ binding.alias }` : binding.name;\n }\n\n /**\n * Emits the declarations of one file through the project's program.\n *\n * @param target - Resolved absolute path of the file\n * @returns The emitted declaration text, empty when the program reaches the file not at all\n *\n * @remarks\n * The emit runs against the shared program, so the checker supplies whatever an annotation leaves out\n * rather than every exported symbol having to spell its own type.\n * `forceDtsEmit` is what returns the text at all, since the parsed configuration forces `noEmit` on\n * to keep the compiler off the disk the bundler writes to.\n * A path the program has not reached is tracked and the program asked once more,\n * which covers a file the build reaches while `tsconfig.json` neither lists nor includes it.\n * A path its `exclude` globs match stays out even then, and yields no declarations rather than an error.\n *\n * @since 3.0.0\n */\n\n private emitDeclaration(target: string): string {\n const service = this.ts.languageService;\n\n if (!service.getProgram()?.getSourceFile(target)) {\n this.ts.touchFiles([ target ]);\n if (!service.getProgram()?.getSourceFile(target)) return '';\n }\n\n return service.getEmitOutput(target, true, true)\n .outputFiles.find(file => file.name.endsWith('.d.ts'))?.text ?? '';\n }\n\n /**\n * Emits the declarations of one file and reduces them to a cache entry.\n *\n * @param target - Resolved absolute path of the file\n * @param version - Snapshot version the entry is recorded against\n * @returns The freshly built entry\n *\n * @remarks\n * The emitted text is parsed once, and that parse drives everything: the statement walk queues both edit lists and\n * records the graph, and the comment walk that follows it queues the doc comments the stripping orphaned.\n * Emit diagnostics are not surfaced here - a declaration the checker cannot write is reported against the source\n * file itself by {@link TypescriptService.check}.\n *\n * @see strip\n * @see emitDeclaration\n * @see pruneComments\n *\n * @since 3.0.0\n */\n\n private build(target: string, version: number): DeclarationEntryInterface {\n // const declaration = isolatedDeclarationSync(target, source, { stripInternal: true }).code;\n const declaration = this.emitDeclaration(target);\n const context: ParseContextInterface = {\n edits: [],\n target,\n parsed: parseSync(target, declaration, { sourceType: 'module' }),\n content: declaration,\n bundleEdits: [],\n packageImports: Object.create(null),\n packageExports: Object.create(null),\n projectExports: { star: new Set(), exports: [], namespace: Object.create(null) },\n projectDependencies: new Set()\n };\n\n const kept: Array<number> = [];\n const { body } = context.parsed.program;\n\n for (const statement of body)\n if (this.strip(statement, context)) kept.push(statement.start);\n\n this.pruneComments(context, body, kept);\n\n return {\n version,\n content: applyEdits(declaration, context.bundleEdits),\n declaration: applyEdits(declaration, context.edits),\n packageImports: context.packageImports,\n packageExports: context.packageExports,\n projectExports: context.projectExports,\n projectDependencies: context.projectDependencies\n };\n }\n\n /**\n * Dispatches one top-level statement to the handler for its module syntax.\n *\n * @param statement - Statement to strip\n * @param context - Pass the edits are queued against and the bindings recorded on\n * @returns Whether the statement survives in the stripped content\n *\n * @remarks\n * Only top-level statements are visited, since only those can carry module syntax.\n * `export =` and `export as namespace` are dropped without a record: both describe how a module is consumed whole,\n * which a fragment inlined into a bundle can no longer express.\n * Anything that is not module syntax is kept untouched.\n *\n * @since 3.0.0\n */\n\n private strip(statement: Directive | Statement, context: ParseContextInterface): boolean {\n switch (statement.type) {\n case 'ImportDeclaration':\n this.stripImport(statement, context);\n\n return false;\n\n case 'ExportAllDeclaration':\n this.stripStarExport(statement, context);\n\n return false;\n\n case 'ExportNamedDeclaration':\n return this.stripNamedExport(statement, context);\n\n case 'ExportDefaultDeclaration':\n return this.stripDefaultExport(statement, context);\n\n case 'TSImportEqualsDeclaration':\n return this.stripImportEquals(statement, context);\n\n case 'TSExportAssignment':\n case 'TSNamespaceExportDeclaration':\n removeNode(statement, context.content, context.bundleEdits);\n\n return false;\n\n default:\n return true;\n }\n }\n\n /**\n * Removes an `import` statement, recording either a dependency or the package bindings it pulled in.\n *\n * @param statement - Import statement to strip\n * @param context - Pass the deletion is queued against\n *\n * @remarks\n * An import of a project file only contributes an edge, since the target's declarations are inlined,\n * and its bindings are already in scope in the bundle.\n * Everything else is recorded per module, so the bundle can reissue one import statement for it.\n *\n * @see link\n * @since 3.0.0\n */\n\n private stripImport(statement: ImportDeclaration, context: ParseContextInterface): void {\n removeNode(statement, context.content, context.bundleEdits);\n if (this.link(statement.source, context)) return;\n\n const module = context.packageImports[statement.source.value] ??= {};\n if (statement.specifiers.length < 1) {\n module.side = true;\n\n return;\n }\n\n for (const entry of statement.specifiers) {\n switch (entry.type) {\n case 'ImportDefaultSpecifier':\n module.default ??= entry.local.name;\n break;\n\n case 'ImportNamespaceSpecifier':\n (module.namespaces ??= []).push(entry.local.name);\n break;\n\n default:\n (module.named ??= []).push(this.binding(this.nameOf(entry.imported), entry.local.name));\n }\n }\n }\n\n /**\n * Removes an `import x = require('module')` statement the way its ESM equivalent is removed.\n *\n * @param statement - Import-equals statement to strip\n * @param context - Pass the deletion is queued against\n * @returns Whether the statement survives in the stripped content\n *\n * @remarks\n * Only the external-module form names a module.\n * `import A = B.C` aliases a local name and is kept as it stands, since the namespace it reaches into is inlined\n * with the rest of the fragment.\n * A package binding is recorded as a namespace import, which is what `require` binds in type space.\n *\n * @see stripImport\n * @since 3.0.0\n */\n\n private stripImportEquals(statement: TSImportEqualsDeclaration, context: ParseContextInterface): boolean {\n const { moduleReference } = statement;\n if (moduleReference.type !== 'TSExternalModuleReference') return true;\n\n removeNode(statement, context.content, context.bundleEdits);\n const source = moduleReference.expression;\n\n if (!this.link(source, context))\n ((context.packageImports[source.value] ??= {}).namespaces ??= []).push(statement.id.name);\n\n return false;\n }\n\n /**\n * Strips an `export` that carries a declaration, a specifier list, or a re-export clause.\n *\n * @param statement - Named export statement to strip\n * @param context - Pass the edits are queued against\n * @returns Whether the statement survives in the stripped content\n *\n * @remarks\n * A declaration keeps its body and loses only the `export` keyword, so `export declare const x` becomes\n * `declare const x` and stays valid where the fragment lands.\n * A specifier list is removed outright: names re-exported from a project file, or from nothing at all, are recorded\n * as this file's own surface, since the declarations behind them are inlined.\n * Only a clause pointing at a package is recorded as a re-export the bundle has to emit again.\n *\n * @see collectDeclared\n * @since 3.0.0\n */\n\n private stripNamedExport(statement: ExportNamedDeclaration, context: ParseContextInterface): boolean {\n const { exports } = context.projectExports;\n\n if (statement.declaration) {\n this.collectDeclared(statement.declaration, exports);\n context.bundleEdits.push({ start: statement.start, end: statement.declaration.start });\n\n return true;\n }\n\n removeNode(statement, context.content, context.bundleEdits);\n const named = statement.source && !this.link(statement.source, context)\n ? (context.packageExports[statement.source.value] ??= {}).named ??= []\n : exports;\n\n for (const entry of statement.specifiers)\n named.push(this.binding(this.nameOf(entry.local), this.nameOf(entry.exported)));\n\n return false;\n }\n\n /**\n * Removes an `export *` statement, recording the module or project file behind it.\n *\n * @param statement - Star export statement to strip\n * @param context - Pass the deletion is queued against\n *\n * @remarks\n * A star export of a project file becomes an edge plus an entry the bundler follows to collect the names it\n * exposes, whereas a namespace form records the name it is exposed under instead.\n *\n * @see link\n * @since 3.0.0\n */\n\n private stripStarExport(statement: ExportAllDeclaration, context: ParseContextInterface): void {\n removeNode(statement, context.content, context.bundleEdits);\n\n const target = this.link(statement.source, context);\n const exposed = statement.exported ? this.nameOf(statement.exported) : null;\n\n if (target) {\n if (exposed) context.projectExports.namespace[exposed] = target;\n else context.projectExports.star.add(target);\n\n return;\n }\n\n const module = context.packageExports[statement.source.value] ??= {};\n if (exposed) (module.namespaces ??= []).push(exposed);\n else module.star = true;\n }\n\n /**\n * Strips an `export default`, keeping the declaration behind it whenever there is one to keep.\n *\n * @param statement - Default export statement to strip\n * @param context - Pass the edits are queued against\n * @returns Whether the statement survives in the stripped content\n *\n * @remarks\n * A named class, function, or interface keeps its body and is recorded as `Name as default`,\n * with `export default` rewritten to `declare` so the fragment stays a valid ambient declaration.\n * A default export of an identifier is dropped, since the declaration it names is a statement of its own that\n * the fragment already carries.\n * An anonymous default has no binding a bundle could re-export, so it is dropped without a record.\n *\n * @see defaultBinding\n * @since 3.0.0\n */\n\n private stripDefaultExport(statement: ExportDefaultDeclaration, context: ParseContextInterface): boolean {\n const { declaration } = statement;\n const local = this.defaultBinding(declaration);\n if (local) context.projectExports.exports.push({ name: local, alias: 'default' });\n\n if (local && declaration.type !== 'Identifier') {\n context.bundleEdits.push({ start: statement.start, end: declaration.start, text: 'declare ' });\n\n return true;\n }\n\n removeNode(statement, context.content, context.bundleEdits);\n\n return false;\n }\n\n /**\n * Queues the removal of every doc comment the stripping left attached to nothing.\n *\n * @param context - Pass the deletions are queued against\n * @param body - Top-level statements of the file, in source order\n * @param kept - Start offsets of the surviving statements, in source order\n *\n * @remarks\n * Only comments that sit between two top-level statements are judged, so the documentation a surviving declaration\n * carries on its own members is never touched.\n * Such a comment is kept when nothing but whitespace separates it from the next surviving statement.\n * Anything else - a stripped statement between the two, another comment, or a trailing position with no statement\n * after it at all - makes it an orphan.\n * Only `/**` comments are considered, so line comments and plain block comments stay put.\n * Comments and statements are both in source order, so all three are walked together in one pass,\n * and a file with many comments does not cost a scan per comment.\n *\n * @see build\n * @since 3.0.0\n */\n\n private pruneComments(context: ParseContextInterface, body: Array<Directive | Statement>, kept: Array<number>): void {\n const { content, bundleEdits } = context;\n let inner = 0;\n let index = 0;\n\n for (const comment of context.parsed.comments) {\n if (comment.type !== 'Block' || comment.value.charCodeAt(0) !== Char.Star) continue;\n\n while (inner < body.length && body[inner].end <= comment.start) inner++;\n if (inner < body.length && body[inner].start < comment.start) continue;\n\n while (index < kept.length && kept[index] < comment.end) index++;\n if (index < kept.length && this.blank(content, comment.end, kept[index])) continue;\n\n removeNode(comment, content, bundleEdits);\n }\n }\n\n /**\n * Resolves a specifier, recording it as a dependency and rewriting it when it names a project file.\n *\n * @param source - Specifier literal as written in the declaration\n * @param context - Pass the specifier was read from\n * @returns The resolved absolute path, or `null` when the specifier names a package or does not resolve\n *\n * @remarks\n * The one place a specifier is looked at, so the two outputs cannot disagree on which files are inlined.\n * An internal target leaves an edge behind for the bundle and a relative rewrite for the standalone declaration,\n * while a package leaves both untouched.\n * The rewrite names the declaration rather than the source, the resolved extension giving way to `.d.ts`, so an\n * emitted file points at the file emitted beside it rather than at a source that was never shipped.\n * Resolution goes through the TypeScript service, so aliases and `paths` mappings resolve the way the type checker\n * sees them rather than the way Node would, and the path it reports is normalized the way the file cache keys are.\n *\n * @since 3.0.0\n */\n\n private link(source: StringLiteral, context: ParseContextInterface): string | null {\n const resolved = this.ts.resolve(source.value, context.target);\n if (!resolved || resolved.isExternalLibraryImport) return null;\n\n const { extension, relativeFileName, resolvedFileName } = resolved;\n const target = this.filesCache.resolve(resolvedFileName);\n\n context.projectDependencies.add(target);\n context.edits.push({\n end: source.end,\n start: source.start,\n text: `'${ extension ? relativeFileName.slice(0, -extension.length) : relativeFileName }.d.ts'`\n });\n\n return target;\n }\n\n /**\n * Appends the names a declaration binds to the exported surface.\n *\n * @param declaration - Declaration carried by an `export` statement\n * @param names - Bindings the declared names are appended to\n *\n * @remarks\n * A variable statement can bind several names at once, while every other declaration binds at most one.\n * Bindings that are not plain identifiers - a destructured variable, or an ambient module declared by its quoted\n * path - contribute nothing, having no name a bundle could re-export.\n *\n * @since 3.0.0\n */\n\n private collectDeclared(declaration: Declaration, names: Array<NamedBindingInterface>): void {\n if (declaration.type === 'VariableDeclaration') {\n for (const entry of declaration.declarations)\n if (entry.id.type === 'Identifier') names.push({ name: entry.id.name });\n\n return;\n }\n\n if ('id' in declaration && declaration.id && 'name' in declaration.id) names.push({ name: declaration.id.name });\n }\n\n /**\n * Returns the local name a default export binds, when it binds one.\n *\n * @param declaration - Declaration or expression behind `export default`\n * @returns The bound name, or `undefined` for an anonymous or non-binding default\n *\n * @since 3.0.0\n */\n\n private defaultBinding(declaration: ExportDefaultDeclarationKind): string | undefined {\n if (declaration.type === 'Identifier') return declaration.name;\n\n return 'id' in declaration ? declaration.id?.name : undefined;\n }\n\n /**\n * Reads the name out of an import or export clause entry.\n *\n * @param name - Identifier or string literal naming a binding\n * @returns The identifier, or the literal re-quoted so it can be emitted back into a clause\n *\n * @since 3.0.0\n */\n\n private nameOf(name: ModuleExportName): string {\n return 'name' in name ? name.name : JSON.stringify(name.value);\n }\n\n /**\n * Pairs the name a binding carries on the module with its local name.\n *\n * @param name - Name the binding is known by on the other side of the clause\n * @param alias - Local name the clause binds it under\n * @returns The bare name when the two match, and the pair when the clause renamed it\n *\n * @see NamedBindingInterface\n * @since 3.0.0\n */\n\n private binding(name: string, alias: string): NamedBindingInterface {\n return name === alias ? { name } : { name, alias };\n }\n\n /**\n * Reports whether a range of the content holds nothing but whitespace.\n *\n * @param content - Text the range points into\n * @param start - Inclusive start offset of the range\n * @param end - Exclusive end offset of the range\n * @returns `true` when every character in the range is a space, tab, or line break\n *\n * @remarks\n * Scans in place and stops at the first other character, so it costs nothing on the long ranges left behind by\n * stripped statements and allocates no substring on the short ones.\n *\n * @since 3.0.0\n */\n\n private blank(content: string, start: number, end: number): boolean {\n for (let index = start; index < end; index++) {\n const code = content.charCodeAt(index);\n if (code !== Char.Space && code !== Char.Tab && code !== Char.Lf && code !== Char.Cr) return false;\n }\n\n return true;\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { ParseResult } from 'oxc-parser';\nimport type { Span, StringLiteral } from '@oxc-project/types';\nimport type { TypescriptService } from '@typescript/services/typescript.service';\nimport type { SourceEditInterface } from './interfaces/transformer-component.interface';\n\n/**\n * Imports\n */\n\nimport { Char } from '@constants/char.constant';\n\n/**\n * Records an edit that deletes a node along with the rest of its line.\n *\n * @param node - Span of the node to delete, as the parser reported it\n * @param content - Source text the span points into\n * @param edits - Collector the deletion is appended to\n *\n * @remarks\n * The deleted range runs from the start of the node through the spaces and tabs that follow it and one line terminator,\n * so a statement that sat alone on its line does not leave a blank line behind.\n * Anything before the node on that line is kept, since the scan only moves forward from the node's end.\n *\n * @example\n * ```ts\n * const content = \"import 'a';\\nconst x = 1;\";\n * const edits: Array<SourceEditInterface> = [];\n *\n * removeNode({ start: 0, end: 11 }, content, edits);\n * edits; // [ { start: 0, end: 12 } ]\n * applyEdits(content, edits); // 'const x = 1;'\n * ```\n *\n * @see applyEdits\n * @since 3.0.0\n */\n\nexport function removeNode(node: Span, content: string, edits: Array<SourceEditInterface>): void {\n let cursor = node.end;\n\n while (cursor < content.length) {\n const code = content.charCodeAt(cursor);\n if (code !== Char.Space && code !== Char.Tab) break;\n cursor++;\n }\n if (content.charCodeAt(cursor) === Char.Cr) cursor++;\n if (content.charCodeAt(cursor) === Char.Lf) cursor++;\n\n edits.push({ start: node.start, end: cursor });\n}\n\n/**\n * Rewrites the source text with a set of edits applied.\n *\n * @param content - Source text the edits point into\n * @param edits - Edits to apply, sorted in place by start offset\n * @returns The rewritten text, or `content` itself when there is nothing to apply\n *\n * @remarks\n * The edits are ordered by start offset and applied left to right,\n * so a transform can collect them in whatever order it walks the tree.\n * An edit starting inside a range an earlier edit already replaced is dropped rather than merged,\n * which keeps the output well-formed when two passes claim overlapping spans.\n * An edit carrying no `text` deletes its span.\n * The array is sorted in place, so a caller that depends on its original order should pass a copy.\n *\n * @example\n * ```ts\n * applyEdits('const a = 1;', [ { start: 0, end: 5, text: 'let' } ]); // 'let a = 1';\n * applyEdits('const a = 1;', [ { start: 0, end: 6 } ]); // 'a = 1;' - deleted\n * applyEdits('const a = 1;', []); // 'const a = 1;' - returned untouched\n * ```\n *\n * @see SourceEditInterface\n * @since 3.0.0\n */\n\nexport function applyEdits(content: string, edits: Array<SourceEditInterface>): string {\n if (edits.length < 1) return content;\n edits.sort((left, right) => left.start - right.start);\n\n const parts: Array<string> = new Array(edits.length * 2 + 1);\n let index = 0;\n let cursor = 0;\n\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i];\n if (edit.start < cursor) continue;\n parts[index++] = content.slice(cursor, edit.start);\n parts[index++] = edit.text ?? '';\n cursor = edit.end;\n }\n\n parts[index++] = content.slice(cursor);\n parts.length = index;\n\n return parts.join('');\n}\n\n/**\n * Queues an edit rewriting a specifier to the relative path of the project file it resolves to.\n *\n * @param source - Specifier literal to rewrite, or `null` when the statement carries none\n * @param target - Resolved absolute path of the file the specifier was written in\n * @param edits - Collector the rewrite is appended to\n * @param ts - Service whose module resolution decides what the specifier names\n *\n * @remarks\n * Only a project file is rewritten, so a specifier naming a package or resolving nowhere is left as it was written.\n * So is a statement with no specifier at all, which is what `export { a }` without a `from` clause looks like.\n * The replacement is measured from the importing file's own directory and carries no extension,\n * so an alias or a `paths` mapping becomes a specifier that still resolves once the file no longer sits in the source\n * tree.\n *\n * @example\n * ```ts\n * const edits: Array<SourceEditInterface> = [];\n *\n * rewrite(statement.source, 'D:/app/src/index.ts', edits, ts);\n * edits; // [ { start: 21, end: 43, text: \"'./components/builder.js'\" } ]\n * ```\n *\n * @see resolveSource\n * @since 3.0.0\n */\n\nexport function rewrite(source: StringLiteral | null, target: string, edits: Array<SourceEditInterface>, ts: TypescriptService): void {\n if (!source) return;\n\n const resolved = ts.resolve(source.value, target);\n if (!resolved || resolved.isExternalLibraryImport) return;\n const { extension, relativeFileName } = resolved;\n const path = extension ? relativeFileName.slice(0, -extension.length) : relativeFileName;\n\n edits.push({ end: source.end, start: source.start, text: `'${ path }.js'` });\n}\n\n/**\n * Rewrites every project specifier in a parsed file and returns the text with the rewrites applied.\n *\n * @param parse - Parse of the text, whose spans are offsets into `content`\n * @param target - Resolved absolute path of the file the text belongs to\n * @param content - The text the parse describes, handed back unchanged when it is empty\n * @param ts - Service whose module resolution decides which specifiers name project files\n * @returns The text with every project specifier rewritten, or `content` itself when none was\n *\n * @remarks\n * Only top-level statements are visited, since only those can carry module syntax.\n * An import, an `export *`, and a named export are read for their `from` clause,\n * while `import x = require('m')` is read for its module name.\n * `import A = B.C` names no module, so it is left alone, as is an `export { a }` that carries no `from` clause.\n * Every specifier found goes through {@link rewrite}, so a package stays as it was written,\n * and only a project file is rewritten.\n * The parse and the text have to come from the same source, since the spans are offsets into it - a parse of one text\n * applied to another lands its edits in the wrong places.\n *\n * @example\n * ```ts\n * const content = \"import { build } from '@components/builder';\\nexport const x = 1;\";\n * const parse = parseSync('src/index.ts', content, { sourceType: 'module' });\n *\n * resolveSource(parse, 'D:/app/src/index.ts', content, ts);\n * // \"import { build } from './components/builder';\\nexport const x = 1;\"\n * ```\n *\n * @see rewrite\n * @see applyEdits\n *\n * @since 3.0.0\n */\n\nexport function resolveSource(parse: ParseResult, target: string, content: string = '', ts: TypescriptService): string {\n if(!content) return content;\n const edits: Array<SourceEditInterface> = [];\n\n for (const statement of parse.program.body) {\n switch (statement.type) {\n case 'ImportDeclaration':\n case 'ExportAllDeclaration':\n case 'ExportNamedDeclaration':\n rewrite(statement.source, target, edits, ts);\n break;\n\n case 'TSImportEqualsDeclaration':\n if (statement.moduleReference.type === 'TSExternalModuleReference')\n rewrite(statement.moduleReference.expression, target, edits, ts);\n }\n }\n\n return applyEdits(content, edits);\n}\n\n","/**\n * Header text included at the top of generated declaration bundle files.\n *\n * @remarks\n * This constant provides a standardized header comment prepended to all\n * declaration bundle files generated by the TypeScript module. The header clearly\n * indicates that the file was automatically generated and should not be edited manually.\n *\n * The header serves as:\n * - A warning to developers not to manually modify generated files\n * - Documentation indicating the source of the file\n * - A consistent marker for identifying generated declaration files\n *\n * @example\n * ```ts\n * import { HeaderDeclarationBundle } from './typescript.constant';\n * import { writeFileSync } from 'fs';\n *\n * const bundledContent = `${HeaderDeclarationBundle}\\n${actualDeclarations}`;\n * writeFileSync('dist/index.d.ts', bundledContent);\n * ```\n *\n * @since 1.5.9\n */\n\nexport const HeaderDeclarationBundle = `/**\n * This file was automatically generated by xBuild.\n * DO NOT EDIT MANUALLY.\n */\n`;\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { FileSnapshotInterface } from '@models/interfaces/files-model.interface';\nimport type { IScriptSnapshot, SourceFile, ParsedCommandLine, CompilerOptions } from 'typescript';\n\n/**\n * Imports\n */\n\nimport ts from 'typescript';\nimport { relative } from '@remotex-labs/xmap';\nimport { inject } from '@remotex-labs/xinject';\nimport { FilesModel } from '@models/files.model';\nimport { createMatcher } from '@components/glob.component';\n\n/**\n * A TypeScript language service host backed by cached file snapshots and the set of files it has tracked.\n *\n * @remarks\n * Satisfies `ts.LanguageServiceHost`, giving the language service its filesystem access, script snapshots, and\n * compiler configuration.\n * Reads and versions are delegated to the shared {@link FilesModel}, while the file set handed over through\n * {@link getScriptFileNames} is maintained here.\n * A path enters the tracked set the first time it is refreshed or its version is queried,\n * so the set grows from the configured entry files to every dependency the language service resolves into them.\n * Paths matched by the configuration's `exclude` globs are skipped by {@link refreshFiles} and reported as ignored\n * to incremental checks through {@link ignoreSourceFile}.\n *\n * @example\n * ```ts\n * const host = new LanguageHostService(parsedConfig); // entry files tracked and read up front\n *\n * host.refresh('src/index.ts'); // re-read and track one file\n * host.getScriptSnapshot('src/index.ts'); // what the language service parses\n * host.options = nextParsedConfig; // swap configuration and re-track from scratch\n * ```\n *\n * @see FilesModel\n * @since 2.0.0\n */\n\nexport class LanguageHostService implements ts.LanguageServiceHost {\n /**\n * Shared model that reads files, caches their snapshots, and tracks their versions.\n *\n * @remarks\n * Registered as a singleton, so every host and build step works against one cache keyed by resolved absolute path.\n *\n * @example\n * ```ts\n * host.filesCache.touch('src/index.ts').version; // 1\n * ```\n *\n * @see FilesModel\n * @since 3.0.0\n */\n\n readonly filesCache = inject(FilesModel);\n\n /**\n * Resolved absolute paths of every file this host has tracked for the language service.\n *\n * @remarks\n * Returned verbatim from {@link getScriptFileNames}.\n * A path is added the first time it is refreshed or its version is queried, then kept even after the file is\n * deleted, so the language service observes the deletion through an empty snapshot rather than a vanishing file.\n *\n * @see track\n * @since 3.0.0\n */\n\n private readonly trackedFiles = new Set<string>();\n\n /**\n * Memoized exclusion verdict per path, keyed by the resolved absolute path.\n *\n * @remarks\n * Exclusion is asked for on every refresh and on every source file an incremental check walks,\n * while the answer only changes with the configuration, so {@link reload} clears this rather than recomputing it.\n *\n * @see isExcluded\n * @since 3.0.0\n */\n\n private readonly exclusions = new Map<string, boolean>();\n\n /**\n * A predicate compiled from the configuration's `exclude` globs, tested against working-directory-relative\n * paths.\n *\n * @remarks\n * Assigned by {@link reload} before any lookup can reach it, hence the definite assignment.\n * It takes a relative path, so {@link isExcluded} is what callers use.\n *\n * @see compileExclude\n * @since 3.0.0\n */\n\n private matches!: (path: string) => boolean;\n\n /**\n * Initializes a new {@link LanguageHostService} from a parsed configuration.\n *\n * @param config - Parsed TypeScript configuration carrying the compiler options, entry file names,\n * and the raw `exclude` globs\n *\n * @remarks\n * Runs {@link reload}, so the entry files are read into the cache and tracked before the host is handed out.\n *\n * @example\n * ```ts\n * const config = ts.getParsedCommandLineOfConfigFile('tsconfig.json', {}, ts.sys as never)!;\n * const host = new LanguageHostService(config);\n * host.getScriptFileNames(); // the configuration's entry files\n * ```\n *\n * @see reload\n * @since 3.0.0\n */\n\n constructor(private config: ParsedCommandLine) {\n this.reload();\n }\n\n /**\n * The live set of resolved paths currently tracked by this host.\n *\n * @returns The tracked set itself, mutated as files are refreshed and cleared\n *\n * @remarks\n * Exposes the same paths as {@link getScriptFileNames} without copying,\n * so a caller can iterate them or feed them straight back into {@link refreshFiles}.\n *\n * @example\n * ```ts\n * host.refresh('src/index.ts');\n * host.tracked.has(host.realpath('src/index.ts')); // true\n * ```\n *\n * @see getScriptFileNames\n * @since 3.0.0\n */\n\n get tracked(): Set<string> {\n return this.trackedFiles;\n }\n\n /**\n * A source-file predicate that incremental checks can use to skip excluded files.\n *\n * @returns A predicate reporting `true` for a source file whose path matches the exclude globs\n *\n * @remarks\n * Bridges the path-based {@link isExcluded} to TypeScript's `ignoreSourceFile` hook by reading the absolute\n * `fileName`, so it agrees with how {@link refreshFiles} filters paths.\n *\n * @example\n * ```ts\n * builder.getSemanticDiagnosticsOfNextAffectedFile(undefined, host.ignoreSourceFile);\n * ```\n *\n * @see refreshFiles\n * @since 3.0.0\n */\n\n get ignoreSourceFile(): (file: SourceFile) => boolean {\n return (file: SourceFile): boolean => this.isExcluded(file.fileName);\n }\n\n /**\n * Replaces the configuration and re-tracks the project from scratch.\n *\n * @param config - The new parsed configuration\n *\n * @remarks\n * Delegates to {@link reload}, so the exclude predicate is recompiled and the new `config.fileNames` replace the\n * tracked set entirely.\n *\n * @example\n * ```ts\n * host.options = ts.getParsedCommandLineOfConfigFile('tsconfig.json', {}, ts.sys as never)!;\n * host.getScriptFileNames(); // the new entry files, nothing carried over\n * ```\n *\n * @see reload\n * @since 3.0.0\n */\n\n set options(config: ParsedCommandLine) {\n this.config = config;\n this.reload();\n }\n\n /**\n * Drops the tracked set and repopulates it from the configured entry files.\n *\n * @remarks\n * The {@link filesCache} snapshots survive, so only membership is reset,\n * and the files are re-read on the way back in through {@link refreshFiles}.\n *\n * @example\n * ```ts\n * host.refresh('src/scratch.ts');\n * host.clearTracked();\n * host.getScriptFileNames(); // back to the configured entry files, scratch.ts dropped\n * ```\n *\n * @see refreshFiles\n * @since 3.0.0\n */\n\n clearTracked(): void {\n this.trackedFiles.clear();\n this.refreshFiles(this.config.fileNames);\n }\n\n /**\n * Rebuilds the exclude predicate and the tracked set from the current configuration.\n *\n * @remarks\n * The single initialization path shared by the constructor and the {@link options} setter:\n * - compiles the `exclude` globs into {@link matches},\n * - drops the memoized {@link exclusions}, whose verdicts belong to the previous globs,\n * - refreshes every entry file through {@link clearTracked}, which reads them into the cache and tracks them.\n *\n * Call it directly when the configuration object was edited in place rather than replaced.\n *\n * @example\n * ```ts\n * host.reload();\n * host.getScriptFileNames(); // what the configuration now selects\n * ```\n *\n * @see clearTracked\n * @since 3.0.0\n */\n\n reload(): void {\n this.matches = this.compileExclude(this.config.raw?.exclude);\n this.exclusions.clear();\n\n this.clearTracked();\n }\n\n /**\n * Re-reads a file from the disk, tracks it, and returns its entry.\n *\n * @param path - File path, relative or absolute\n * @returns The entry for the file, with `version` advanced when the content changed\n *\n * @remarks\n * The path is tracked before the read, so it stays listed even when the file turns out to be gone.\n * Exclusion is not consulted here - {@link refreshFiles} is the caller that filters.\n *\n * @example\n * ```ts\n * const state = host.refresh('src/index.ts');\n * state.version; // 1 at first sight, advanced on every later change\n * state.snapshot?.text; // the content just read\n * ```\n *\n * @see track\n * @since 3.0.0\n */\n\n refresh(path: string): FileSnapshotInterface {\n return this.filesCache.refresh(this.track(path));\n }\n\n /**\n * Refreshes and tracks a batch of files, skipping any path matched by the exclude globs.\n *\n * @param paths - Paths to refresh, defaulting to the currently tracked set\n *\n * @remarks\n * Each retained path goes through {@link refresh} and so becomes tracked.\n * Calling it with no argument brings the already tracked files current, which is what a watch cycle does.\n *\n * @example\n * ```ts\n * host.refreshFiles([ 'src/a.ts', 'src/a.spec.ts' ]); // a.spec.ts skipped when excluded\n * host.refreshFiles(); // re-read everything already tracked\n * ```\n *\n * @see refresh\n * @since 3.0.0\n */\n\n refreshFiles(paths: Array<string> | Set<string> = this.trackedFiles): void {\n for (const path of paths) {\n if (this.isExcluded(path)) continue;\n this.refresh(path);\n }\n }\n\n /**\n * Returns the compiler options currently in force.\n *\n * @returns The active TypeScript compiler options\n *\n * @example\n * ```ts\n * host.getCompilationSettings().target; // ts.ScriptTarget.ES2020\n * ```\n *\n * @since 2.0.0\n */\n\n getCompilationSettings(): CompilerOptions {\n return this.config.options;\n }\n\n /**\n * Reports whether a file exists on disk.\n *\n * @param path - Absolute path\n * @returns `true` when the file exists\n *\n * @remarks\n * Goes straight to `ts.sys`, bypassing the snapshot cache, so it reflects the filesystem as it stands now.\n *\n * @example\n * ```ts\n * host.fileExists('/project/src/index.ts'); // true\n * ```\n *\n * @since 2.0.0\n */\n\n fileExists(path: string): boolean {\n return ts.sys.fileExists(path);\n }\n\n /**\n * Reads file content through the snapshot cache.\n *\n * @param path - File path, relative or absolute\n * @param encoding - Encoding used when the file is read, defaulting to `utf-8`\n * @returns The file content, or `undefined` when the path holds no readable file\n *\n * @remarks\n * Served from the cache once the file has been read, so the encoding only takes effect on the first read of a path.\n *\n * @example\n * ```ts\n * host.readFile('src/index.ts'); // export const x = 10;\n * host.readFile('src/gone.ts'); // undefined\n * ```\n *\n * @see FilesModel.touch\n * @since 3.0.0\n */\n\n readFile(path: string, encoding?: BufferEncoding): string | undefined {\n return this.filesCache.touch(path, encoding).snapshot?.text;\n }\n\n /**\n * Lists the files under a directory that match the given criteria.\n *\n * @param path - Directory to start from\n * @param extensions - File extensions to accept\n * @param exclude - Glob patterns to skip\n * @param include - Glob patterns to keep\n * @param depth - Maximum recursion depth\n * @returns The matching file paths\n *\n * @example\n * ```ts\n * host.readDirectory('src', [ '.ts' ], [ 'node_modules' ], undefined, 2); // [ 'src/index.ts', ... ]\n * ```\n *\n * @since 2.0.0\n */\n\n readDirectory(path: string, extensions?: Array<string>, exclude?: Array<string>, include?: Array<string>, depth?: number): Array<string> {\n return ts.sys.readDirectory(path, extensions, exclude, include, depth);\n }\n\n /**\n * Returns the immediate subdirectories of a path.\n *\n * @param path - Directory to list\n * @returns The subdirectory names\n *\n * @example\n * ```ts\n * host.getDirectories('src'); // [ 'services', 'models' ]\n * ```\n *\n * @since 2.0.0\n */\n\n getDirectories(path: string): Array<string> {\n return ts.sys.getDirectories(path);\n }\n\n /**\n * Reports whether a directory exists.\n *\n * @param path - Absolute path\n * @returns `true` when the directory exists\n *\n * @example\n * ```ts\n * host.directoryExists('src/services'); // true\n * ```\n *\n * @since 2.0.0\n */\n\n directoryExists(path: string): boolean {\n return ts.sys.directoryExists(path);\n }\n\n /**\n * Returns the working directory that relative paths resolve against.\n *\n * @returns The absolute path of the current working directory\n *\n * @example\n * ```ts\n * host.getCurrentDirectory(); // '/project'\n * ```\n *\n * @since 2.0.0\n */\n\n getCurrentDirectory(): string {\n return ts.sys.getCurrentDirectory();\n }\n\n /**\n * Returns the resolved paths of every file tracked by this host.\n *\n * @returns A snapshot array of the tracked absolute paths\n *\n * @remarks\n * This is the program's file set as far as the language service is concerned.\n * A deleted file stays listed, so its removal surfaces as a diagnostic rather than as a silently shrinking program.\n *\n * @example\n * ```ts\n * host.getScriptFileNames(); // [ '/project/src/index.ts', '/project/src/utils.ts' ]\n * ```\n *\n * @see tracked\n * @since 2.0.0\n */\n\n getScriptFileNames(): Array<string> {\n return [ ...this.trackedFiles ];\n }\n\n /**\n * Returns the path of the default lib file matching the given options.\n *\n * @param options - Compiler options, of which `target` decides the lib\n * @returns Absolute path to the matching `lib.*.d.ts`\n *\n * @example\n * ```ts\n * host.getDefaultLibFileName({ target: ts.ScriptTarget.ES2020 }); // '.../lib.es2020.full.d.ts'\n * ```\n *\n * @since 2.0.0\n */\n\n getDefaultLibFileName(options: CompilerOptions): string {\n return ts.getDefaultLibFilePath(options);\n }\n\n /**\n * Returns the version identifier of a file and tracks it.\n *\n * @param path - File path, relative or absolute\n * @returns The version as a string, such as `'1'` or `'2'`\n *\n * @remarks\n * The language service reparses a file only when this string changes, so the value must stay stable while the file\n * does.\n * The read is served from the cache, and {@link refresh} is what moves the version forward.\n *\n * @example\n * ```ts\n * host.getScriptVersion('src/index.ts'); // '1'\n * host.refresh('src/index.ts'); // the file changed on disk\n * host.getScriptVersion('src/index.ts'); // '2' - the language service reparses it\n * ```\n *\n * @see track\n * @since 2.0.0\n */\n\n getScriptVersion(path: string): string {\n return this.filesCache.touch(this.track(path)).version.toString();\n }\n\n /**\n * Returns the script snapshot of a file.\n *\n * @param path - File path, relative or absolute\n * @returns The snapshot, or `undefined` when the path holds no readable file\n *\n * @remarks\n * Reads through the cache, loading from the disk at first sight only.\n * Unlike {@link getScriptVersion}, it leaves the tracked set alone - tracking is driven by version queries.\n *\n * @example\n * ```ts\n * const snapshot = host.getScriptSnapshot('src/index.ts');\n * snapshot?.getText(0, snapshot.getLength()); // export const x = 10;\n * ```\n *\n * @see getScriptVersion\n * @since 2.0.0\n */\n\n getScriptSnapshot(path: string): IScriptSnapshot | undefined {\n return this.filesCache.touch(path).snapshot;\n }\n\n /**\n * Resolves a path to the absolute form used as the tracking and cache key.\n *\n * @param path - File path, relative or absolute\n * @returns The resolved absolute path\n *\n * @remarks\n * Implements the optional `realpath` host hook with the same normalization {@link FilesModel} applies to its cache\n * keys, so the paths reported to TypeScript match the ones tracked here.\n *\n * @example\n * ```ts\n * host.realpath('src/index.ts'); // '/project/src/index.ts'\n * ```\n *\n * @see FilesModel.resolve\n * @since 3.0.0\n */\n\n realpath(path: string): string {\n return this.filesCache.resolve(path);\n }\n\n /**\n * Compiles exclude globs into a matcher over working-directory-relative paths.\n *\n * @param globs - Patterns whose matching paths are excluded, or `undefined` when the configuration has none\n * @returns A predicate reporting `true` for a matched relative path, or one that always reports `false`\n *\n * @remarks\n * The empty case is handled explicitly, since {@link createMatcher} reads an empty pattern list as matching\n * everything, which would exclude the whole project.\n *\n * @see createMatcher\n * @since 3.0.0\n */\n\n private compileExclude(globs?: Array<string>): (path: string) => boolean {\n return globs && globs.length > 0 ? createMatcher(globs) : (): boolean => false;\n }\n\n /**\n * Reports whether a path is excluded by the configuration, memorizing the verdict.\n *\n * @param path - File path as the caller holds it, relative or absolute\n * @returns `true` when the path matches the exclude globs\n *\n * @remarks\n * The path is resolved before the verdict is stored, so the same file reached by two spellings is matched once,\n * and every later lookup of either costs a map read.\n *\n * @see exclusions\n * @since 3.0.0\n */\n\n private isExcluded(path: string): boolean {\n const target = this.filesCache.resolve(path);\n let excluded = this.exclusions.get(target);\n if (excluded === undefined) this.exclusions.set(\n target, excluded = this.matches(relative(process.cwd(), target))\n );\n\n return excluded;\n }\n\n /**\n * Adds a path to the tracked set and returns its resolved key.\n *\n * @param path - File path, relative or absolute\n * @returns The resolved absolute path used as the tracking key\n *\n * @remarks\n * Centralizes the tracking shared by {@link refresh} and {@link getScriptVersion}.\n * A path is added the first time it is seen and never removed,\n * so a deletion leaves a still-listed entry that resolves to an empty snapshot.\n *\n * @see trackedFiles\n * @since 3.0.0\n */\n\n private track(path: string): string {\n const target = this.filesCache.resolve(path);\n this.trackedFiles.add(target);\n\n return target;\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { Dirent } from 'fs';\nimport type { GlobOptionsInterface } from './interfaces/glob-component.interface';\n\n/**\n * Imports\n */\n\nimport { readdirSync } from 'fs';\nimport { join } from '@remotex-labs/xmap';\nimport { Char } from '@constants/char.constant';\nimport { FrameworkService } from '@services/framework.service';\nimport { RegexElement, RegexCloser } from '@constants/glob.constant';\n\n/**\n * Escapes a single character for literal use inside a regular expression.\n *\n * @param char - The character to escape\n * @returns The character prefixed with a backslash when it carries special meaning in a regular expression,\n * or the character unchanged otherwise\n *\n * @remarks\n * A backslash is prepended when `char` is one of the regex metacharacters `.+^$()|\\{}[]*?`.\n * Any other character is returned as-is.\n * Intended for building patterns from user-supplied glob fragments where each source character must match itself.\n *\n * @example\n * ```ts\n * lit('.'); // '\\\\.'\n * lit('a'); // 'a'\n * ```\n *\n * @since 3.0.0\n */\n\nexport function lit(char: string): string {\n return '.+^$()|\\\\{}[]*?'.includes(char) ? '\\\\' + char : char;\n}\n\n/**\n * Returns the UTF-16 code unit of a glob string at a given index.\n *\n * @param glob - The glob string to read from\n * @param index - The zero-based position of the character to read\n * @returns The code unit at `index`, or `NaN` when `index` is out of range\n *\n * @remarks\n * A thin wrapper over {@link String.charCodeAt} used while scanning a glob pattern character by character.\n * Comparing code units avoids allocating single-character substrings on the hot path.\n *\n * @example\n * ```ts\n * at('a*b', 1); // 42 - Char.Star\n * at('a*b', 9); // NaN - past the end\n * ```\n *\n * @see Char\n * @since 3.0.0\n */\n\nexport function at(glob: string, index: number): number {\n return glob.charCodeAt(index);\n}\n\n/**\n * Determines whether the `**` at a given index forms a globstar segment.\n *\n * @param glob - The glob string being scanned\n * @param index - The zero-based position of the first `*` of the candidate `**`\n * @returns `true` when the `**` occupies a whole path segment, `false` otherwise\n *\n * @remarks\n * A globstar is a `**` that spans an entire path segment,\n * so it must be bounded on both sides by a slash or by the start or end of the string.\n * The character before `index` must be the start of the string or a slash,\n * and the character after the `**` must be the end of the string or a slash.\n * A `**` embedded within a segment, such as in `a**b`, matches as two consecutive single stars rather than a globstar.\n * The caller is responsible for confirming that both characters at `index` and `index + 1` are `*`.\n *\n * @example\n * ```ts\n * isGlobstar('**', 0); // true - the whole string\n * isGlobstar('a/**', 2); // true - preceded by a slash, ends the string\n * isGlobstar('a**b', 1); // false - embedded in a segment\n * ```\n *\n * @see Char\n * @since 3.0.0\n */\n\nexport function isGlobstar(glob: string, index: number): boolean {\n return (index === 0 || at(glob, index - 1) === Char.Slash)\n && (index + 2 === glob.length || at(glob, index + 2) === Char.Slash);\n}\n\n/**\n * Wraps a regex fragment in a non-capturing group.\n *\n * @param body - The regex source to enclose\n * @returns The body wrapped as `(?:body)`\n *\n * @remarks\n * Groups a fragment so a following quantifier or alternation applies to the whole fragment rather than its last token.\n *\n * @example\n * ```ts\n * group('a|b'); // '(?:a|b)'\n * group('a|b') + '?'; // '(?:a|b)?' - the quantifier covers both alternatives\n * ```\n *\n * @since 3.0.0\n */\n\nexport function group(body: string): string {\n return `(?:${ body })`;\n}\n\n/**\n * Finds the index of the `]` that closes a character class.\n *\n * @param glob - The glob string being scanned\n * @param openIndex - The index of the opening `[`\n * @returns The index of the closing `]`, or the length of the string when the class is unterminated\n *\n * @remarks\n * Applies POSIX-style character-class rules while scanning.\n * A leading `!` or `^` negates the class and is skipped, and a `]` immediately after the opening bracket\n * (or after the negation) is treated as a literal member rather than a close.\n * A backslash escapes the next character, so an escaped `]` does not close the class.\n *\n * @example\n * ```ts\n * classEnd('[abc]def', 0); // 4\n * classEnd('[]abc]', 0); // 5 - the leading ] is a member\n * classEnd('[abc', 0); // 4 - unterminated, so the length\n * ```\n *\n * @see compileClass\n * @since 3.0.0\n */\n\nexport function classEnd(glob: string, openIndex: number): number {\n let scan = openIndex + 1;\n const lead = at(glob, scan);\n\n if (lead === Char.Bang || lead === Char.Caret) scan++;\n if (at(glob, scan) === Char.RBracket) scan++; // leading ] is literal\n\n while (scan < glob.length && at(glob, scan) !== Char.RBracket)\n scan += at(glob, scan) === Char.Backslash ? 2 : 1;\n\n return scan;\n}\n\n/**\n * Finds the index of the `)` that closes an extglob group.\n *\n * @param glob - The glob string being scanned\n * @param openIndex - The index of the opening `(`\n * @returns The index of the matching `)`, or `-1` when the group is unterminated\n *\n * @remarks\n * Tracks nesting depth so an inner `( ... )` does not end the outer group.\n * A backslash escapes the next character, and a `[ ... ]` character class is skipped via {@link classEnd},\n * so parentheses inside it are not counted.\n *\n * @example\n * ```ts\n * findClose('@(a|b)c', 1); // 5\n * findClose('@(a|(b))', 1); // 7 - the inner group does not end it\n * findClose('@(a', 1); // -1 - unterminated\n * ```\n *\n * @see classEnd\n * @since 3.0.0\n */\n\nexport function findClose(glob: string, openIndex: number): number {\n for (let cursor = openIndex, depth = 0; cursor < glob.length; cursor++) {\n const char = at(glob, cursor);\n\n if (char === Char.Backslash) cursor++;\n else if (char === Char.LParen) depth++;\n else if (char === Char.RParen && --depth === 0) return cursor;\n else if (char === Char.LBracket) cursor = classEnd(glob, cursor);\n }\n\n return -1;\n}\n\n/**\n * Finds the index of the `}` that closes an expandable brace group.\n *\n * @param glob - The glob string being scanned\n * @param openIndex - The index of the opening `{`\n * @returns The index of the matching `}` when the group contains a top-level comma, `-1` otherwise\n *\n * @remarks\n * A brace group is expandable only when it holds at least one top-level comma, so `{a,b}` closes but `{a}` does not.\n * Tracks nesting depth so an inner `{ ... }` does not end the outer group,\n * skips a `[ ... ]` character class via {@link classEnd}, and treats a backslash as escaping the next character.\n * Returning `-1` signals the caller to emit the `{` as a literal.\n *\n * @example\n * ```ts\n * braceClose('{a,b}c', 0); // 4\n * braceClose('{a,{b,c}}', 0); // 8 - the inner group does not end it\n * braceClose('{abc}', 0); // -1 - no top-level comma, so a literal\n * ```\n *\n * @see classEnd\n * @since 3.0.0\n */\n\nexport function braceClose(glob: string, openIndex: number): number {\n let comma = false;\n\n for (let cursor = openIndex + 1, depth = 0; cursor < glob.length; cursor++) {\n const char = at(glob, cursor);\n\n if (char === Char.Backslash) cursor++;\n else if (char === Char.LBrace) depth++;\n else if (char === Char.RBrace) {\n if (depth === 0) return comma ? cursor : -1; // expandable only with a comma\n depth--;\n }\n else if (char === Char.Comma && depth === 0) comma = true;\n else if (char === Char.LBracket) cursor = classEnd(glob, cursor);\n }\n\n return -1;\n}\n\n/**\n * Compiles a glob character class into its regex equivalent.\n *\n * @param glob - The glob string being scanned\n * @param openIndex - The index of the opening `[`\n * @returns A tuple of the compiled regex source and the index just past the class\n *\n * @remarks\n * Translates glob character-class syntax into a regex class.\n * A leading `!` or `^` becomes a negation that also excludes the path separator, emitted as `[^/`.\n * A `]` immediately after the opening (or after the negation) is escaped as a literal member,\n * and a `^` inside the class is escaped so it is not read as a negation.\n * An unterminated class is not a class at all - the function returns the literal `\\[` and advances past the `[`.\n *\n * @example\n * ```ts\n * compileClass('[a-z]x', 0); // [ '[a-z]', 5 ]\n * compileClass('[!a]', 0); // [ '[^/a]', 4 ] - negated, and the separator excluded with it\n * compileClass('[abc', 0); // [ '\\\\[', 1 ] - unterminated, so a literal bracket\n * ```\n *\n * @see classEnd\n * @since 3.0.0\n */\n\nexport function compileClass(glob: string, openIndex: number): [string, number] {\n const end = classEnd(glob, openIndex);\n if (end >= glob.length) return [ '\\\\[', openIndex + 1 ]; // unterminated → literal\n\n let cursor = openIndex + 1, out = '[';\n const lead = at(glob, cursor);\n\n if (lead === Char.Bang || lead === Char.Caret) { out += '^/'; cursor++; }\n if (at(glob, cursor) === Char.RBracket) { out += '\\\\]'; cursor++; }\n\n for (; cursor < end; cursor++) {\n if (at(glob, cursor) === Char.Backslash) out += '\\\\' + glob[++cursor];\n else if (at(glob, cursor) === Char.Caret) out += '\\\\^';\n else out += glob[cursor];\n }\n\n return [ out + ']', end + 1 ];\n}\n\n/**\n * Finds the index of the next path separator at or after a position.\n *\n * @param glob - The glob string being scanned\n * @param from - The zero-based position to start scanning from\n * @returns The index of the next unescaped `/`, or the length of the string when none remains\n *\n * @remarks\n * Marks the end of the current path segment.\n * A backslash escapes the next character, so an escaped `/` does not end the segment.\n *\n * @example\n * ```ts\n * segmentEnd('src/index.ts', 0); // 3\n * segmentEnd('index.ts', 0); // 8 - no separator left, so the length\n * ```\n *\n * @since 3.0.0\n */\n\nexport function segmentEnd(glob: string, from: number): number {\n for (let cursor = from; cursor < glob.length; cursor++) {\n if (at(glob, cursor) === Char.Slash) return cursor;\n if (at(glob, cursor) === Char.Backslash) cursor++;\n }\n\n return glob.length;\n}\n\n/**\n * Compiles a glob fragment into a regular-expression source.\n *\n * @param glob - The glob fragment to compile\n * @param isSegmentStart - Whether the fragment begins at the start of a path segment\n * @param alt - The code unit that separates alternatives, or `0` when the fragment is not an alternation body\n * @param options - Compilation options, of which only {@link GlobOptionsInterface.dot} is read, defaulting to `false`\n * @returns The regex source for the fragment, without the anchoring `^` and `$`\n *\n * @remarks\n * The core of the compiler, invoked recursively for the bodies of extglob, brace, and negation groups.\n * It walks the fragment one character at a time and emits the matching regex, handling wildcards (`*`, `**`, `?`),\n * character classes, brace expansion, extglob prefixes (`?( )`, `*( )`, `+( )`, `@( )`, `!( )`), and escapes.\n *\n * Segment-start tracking drives the leading-dot guard: at the start of a segment a wildcard must not match a dotfile,\n * so a {@link RegexElement.NotDot} guard is emitted.\n * `isSegmentStart` seeds this state for the fragment, and it is re-armed after every `/` and at each alternative.\n * When `options.dot` is `true`, the guard is suppressed everywhere, so wildcards match dotfiles as ordinary names,\n * and `**` descends into dot directories.\n *\n * The `alt` parameter marks the fragment as the body of an alternation.\n * When set to {@link Char.Pipe} or {@link Char.Comma}, an unescaped separator of that kind becomes a regex `|`,\n * and `**` is treated as two single stars rather than a globstar.\n * Any other occurrence of `|` or `,` is emitted literally.\n *\n * @example\n * ```ts\n * compileFragment('*.ts', true); // (?!\\.)[^/]*\\.ts\n * compileFragment('a,b', false, Char.Comma); // a|b\n * compileFragment('*.ts', true, 0, { dot: true }); // [^/]*\\.ts\n * ```\n *\n * @see globToRegExp\n * @see GlobOptionsInterface\n *\n * @since 3.0.0\n */\n\nexport function compileFragment(glob: string, isSegmentStart: boolean = false, alt: number = 0, options: GlobOptionsInterface = {}): string {\n const { dot = false } = options;\n\n let out = '';\n let index = 0;\n let wasStart = isSegmentStart;\n\n const guard = dot ? '' : RegexElement.NotDot;\n const DS = guard + RegexElement.NotSlash + '+';\n const GLOBSTAR = group(DS + '(?:/' + DS + ')*') + '?';\n\n while (index < glob.length) {\n const char = at(glob, index);\n const nChar = at(glob, index + 1);\n\n if (nChar === Char.LParen && (char === Char.Bang || RegexCloser[char])) {\n const close = findClose(glob, index + 1);\n\n if (char !== Char.Bang) { // ?*+@( ... )\n const end = close === -1 ? glob.length : close; // unclosed → group runs to the end\n const inner = compileFragment(glob.slice(index + 2, end), wasStart, Char.Pipe, options);\n\n out += RegexElement.Open + inner + RegexCloser[char];\n index = end + 1;\n continue;\n }\n\n if (close !== -1) {\n const inner = compileFragment(glob.slice(index + 2, close), wasStart, Char.Pipe, options);\n const tailEnd = segmentEnd(glob, close + 1);\n const tail = compileFragment(glob.slice(close + 1, tailEnd), false, 0, options);\n\n out += group(\n (wasStart ? guard : '') +\n `(?!${ group(inner) + tail + RegexElement.SegBreak })` +\n RegexElement.NotSlashLazy + tail\n );\n\n index = tailEnd;\n continue;\n }\n }\n\n switch (char) {\n case Char.Slash:\n out += RegexElement.Slash;\n index++;\n wasStart = true;\n break;\n\n case Char.Backslash:\n out += index + 1 < glob.length ? lit(glob[index + 1]) : '\\\\\\\\';\n index += 2;\n break;\n\n case Char.Question:\n out += wasStart && !dot ? RegexElement.NotDotSlash : RegexElement.NotSlash;\n index++;\n break;\n\n case Char.Star:\n if (nChar === Char.Star && alt !== Char.Pipe && (index > 0 || isSegmentStart) && isGlobstar(glob, index)) {\n const root = index === 0 && alt === 0 ? RegexElement.AbsRoot : '';\n if (at(glob, index + 2) === Char.Slash) {\n out += root + group(DS + RegexElement.Slash) + '*'; index += 3; wasStart = true;\n } else {\n out += root + GLOBSTAR; index += 2;\n }\n } else {\n out += (wasStart ? guard : '') + RegexElement.NotSlashRun;\n index++;\n }\n break;\n\n case Char.LBrace: {\n const close = braceClose(glob, index);\n\n if (close === -1) {\n out += '\\\\{'; index++;\n } else {\n out += group(compileFragment(glob.slice(index + 1, close), wasStart, Char.Comma, options));\n index = close + 1;\n }\n break;\n }\n\n case Char.LBracket: {\n const [ src, next ] = compileClass(glob, index);\n out += (wasStart && !dot && src !== '\\\\[' ? RegexElement.NotDot : '') + src;\n index = next;\n break;\n }\n\n case Char.Pipe:\n case Char.Comma:\n if (alt === char) { out += RegexElement.Alt; wasStart = isSegmentStart; }\n else out += lit(glob[index]);\n index++;\n break;\n\n default:\n out += lit(glob[index]); index++;\n }\n }\n\n return out;\n}\n\n/**\n * Compiles a glob pattern into an anchored regular expression.\n *\n * @param glob - The glob pattern to compile\n * @param options - Compilation options carrying the regex flags and the dotfile setting\n * @returns A {@link RegExp} anchored with `^` and `$` that matches exactly the paths described by the glob\n *\n * @remarks\n * The entry point of the compiler.\n * It compiles the pattern with {@link compileFragment} starting at a segment boundary, then wraps the result\n * in `^ ... $` so the expression matches a whole path rather than a substring.\n *\n * Supported glob syntax:\n * - `*` - matches any run of characters within a single path segment, never crossing a `/`.\n * - `?` - matches exactly one character within a segment.\n * - `**` - globstar, matching across segment boundaries, spanning any number of intermediate segments.\n * - `[abc]`, `[a-z]`, `[a-zA-Z0-9]` - a character class matching exactly one listed character or range.\n * Multiple ranges combine, and it never matches more than one character.\n * - `[!abc]`, `[^abc]` - a negated character class matching exactly one character not listed.\n * - `{a,b}`, `{a,{b,c}}` - brace alternation, matching any one of the comma-separated alternatives.\n * A brace group with no top-level comma, such as `{abc}`, is treated as the literal text `{abc}`.\n * - `@( ... )` - extglob group matching its `|`-separated alternatives exactly once.\n * - `?( ... )` - extglob group matching zero or one of its alternatives.\n * - `*( ... )` - extglob group matching zero or more of its alternatives.\n * - `+( ... )` - extglob group matching one or more of its alternatives.\n * - `!( ... )` - extglob negation matching anything the alternatives do not.\n * - `\\` - escapes the next character so it is matched literally, so `\\*.js` matches the literal name `*.js`.\n * - `/` - the literal path separator, which segment-relative wildcards never cross.\n *\n * Character classes and `?` always consume exactly one character.\n * To constrain a run of characters, follow the class with `*` (`[ab]*c` allows any run before `c`)\n * or repeat it with an extglob (`+([ab])c` requires every character before `c` to be `a` or `b`).\n *\n * The `!( ... )` negation is single-segment: its body never crosses a `/`, and the guarantee holds when\n * the negation is the last thing in its segment or is followed by a literal tail such as `.ts`.\n * It is not whole-pattern negation - a leading `!` not followed by `(` is matched as a literal `!`.\n *\n * Leading dots are guarded: at the start of a segment,\n * `*`, `?`, `[ ... ]`, and `**` do not match a name that begins with `.` unless the pattern spells the dot out.\n * So `*` matches `env` but not `.env`.\n * To include dotfiles, name the dot explicitly:\n * - `.*` - matches only dotfiles, such as `.env`.\n * - `{.,}*` - matches every name, dotfiles included.\n *\n * Passing {@link GlobOptionsInterface.dot} as `true` lifts the guard for the whole pattern,\n * so plain wildcards match dotfiles, and `**` descends into dot directories - `**\\/*` then matches `.git/config`.\n *\n * @example\n * <caption>Common patterns and what they match</caption>\n * ```text\n * *.{ts,js} x.ts, x.js\n * @(a|b) a, b\n * +(ab) ab, abab (not: '')\n * !(a).js ab.js, x.js (not: a.js)\n * !(*.spec).ts app.ts, index.ts (not: app.spec.ts)\n * !(*.spec|*.test).ts app.ts (not: app.spec.ts, app.test.ts)\n * ```\n *\n * @example\n * <caption>Every file except a spec, recursively - the two most useful forms</caption>\n * ```ts\n * globToRegExp('**\\/!(*.spec).{ts,js}'); // any .ts or .js file whose name does not end in .spec\n * globToRegExp('**\\/!(*.spec.ts)'); // any file at all except those ending in .spec.ts\n * ```\n *\n * @see compileFragment\n * @see GlobOptionsInterface\n *\n * @since 3.0.0\n */\n\nexport function globToRegExp(glob: string, options: GlobOptionsInterface = {}): RegExp {\n return new RegExp('^' + compileFragment(glob, true, 0, options) + '$', options.flags);\n}\n\n/**\n * Builds a predicate that tests a path against a set of include and exclude globs.\n *\n * @param globs - The glob patterns to match against, where a leading `!` marks an exclusion\n * @param options - Compilation options applied to every compiled pattern\n * @returns A predicate returning `true` when `path` is included by the set and excluded by none of it\n *\n * @remarks\n * Each glob is compiled once with {@link globToRegExp} and sorted into an include or exclude list.\n * A leading `!` marks the pattern as an exclusion and is stripped before compilation.\n * A repeated `!` toggles, so `!!pattern` is an inclusion again.\n * A `!` immediately followed by `(` is left in place - it is the extglob negation {@link globToRegExp} handles,\n * not a whole-pattern exclusion.\n *\n * The predicate accepts a path when it is matched by at least one include pattern and by no exclude pattern.\n * When the set contains no include patterns, every path is considered included,\n * so a set of only exclusions matches everything except what it excludes.\n *\n * @example\n * ```ts\n * const isSource = createMatcher([ '**\\/*.ts', '!**\\/*.spec.ts' ]);\n * isSource('src/app.ts'); // true\n * isSource('src/app.spec.ts'); // false - excluded\n * isSource('src/app.js'); // false - not included\n * ```\n *\n * @see globToRegExp\n * @see GlobOptionsInterface\n *\n * @since 3.0.0\n */\n\nexport function createMatcher(globs: Array<string>, options: GlobOptionsInterface = {}): (path: string) => boolean {\n const include: Array<RegExp> = [];\n const exclude: Array<RegExp> = [];\n\n for (let glob of globs) {\n let neg = false;\n while (at(glob, 0) === Char.Bang && at(glob, 1) !== Char.LParen) {\n neg = !neg;\n glob = glob.slice(1);\n }\n\n (neg ? exclude : include).push(globToRegExp(glob, options));\n }\n\n return (path) =>\n (include.length === 0 || include.some(r => r.test(path))) &&\n !exclude.some(r => r.test(path));\n}\n\n/**\n * Walks a directory tree and collects every file the globs match.\n *\n * @param base - The directory the walk starts from and the patterns are matched against\n * @param globs - The glob patterns to match, where a leading `!` marks an exclusion\n * @param options - Compilation options applied to every compiled pattern\n * @returns The matched files as paths relative to `base`, with forward slashes, in the order the walk reaches them\n *\n * @remarks\n * The base is resolved through the shared path cache,\n * and every path below it is built by appending a name to its directory's path.\n * A file therefore costs one string and one {@link createMatcher} test rather than a resolve of its own.\n * The walk is iterative, so a deep tree cannot overflow the stack,\n * and a directory that cannot be read is skipped rather than thrown from.\n * Unless `dot` is set, a name beginning with `.` is skipped before it is tested, which prunes whole trees such as `.git`.\n * A pattern that spells a leading dot, as `.github/**` or `**\\/.cache/*` does, disarms this and lets the walk descend.\n * Symbolic links are not followed, since a link never reports itself as a directory, which is what keeps a link cycle\n * from being walked.\n *\n * @example\n * ```ts\n * collectFiles(cwd(), [ 'src/**\\/*.ts', '!**\\/*.spec.ts' ]);\n * // [ 'src/index.ts', 'src/models/files.model.ts' ]\n * ```\n *\n * @see createMatcher\n * @see GlobOptionsInterface\n *\n * @since 3.0.0\n */\n\nexport function collectFiles(base: string, globs: Array<string>, options: GlobOptionsInterface = {}): Array<string> {\n const root = FrameworkService.resolve(base);\n const matcher = createMatcher(globs, options);\n const dotted = options.dot || globs.some(glob => at(glob, 0) === Char.Dot || glob.includes('/.'));\n\n const files: Array<string> = [];\n const stack: Array<string> = [ '' ];\n\n while (stack.length > 0) {\n const directory = stack.pop()!;\n\n let entries: Array<Dirent>;\n try {\n entries = readdirSync(directory ? join(root, directory) : root, { withFileTypes: true });\n } catch {\n continue;\n }\n\n for (const entry of entries) {\n if (!dotted && at(entry.name, 0) === Char.Dot) continue;\n const path = directory ? `${ directory }/${ entry.name }` : entry.name;\n\n if (entry.isDirectory()) stack.push(path);\n else if (matcher(path)) files.push(path);\n }\n }\n\n return files;\n}\n","/**\n * Imports\n */\n\nimport { Char } from '@constants/char.constant';\n\n/**\n * Regular-expression fragments emitted while compiling a glob into a {@link RegExp} source.\n *\n * @remarks\n * Each member is a reusable snippet of regex syntax with a fixed meaning in the compiled output,\n * so the compiler can assemble a pattern by concatenating members rather than repeating string literals.\n * Declared as a `const enum` so references inline to their literal value at compile time.\n *\n * @example\n * ```ts\n * RegexElement.NotDot + RegexElement.NotSlashRun; // '(?!\\\\.)[^/]*' - the source for a leading `*`\n * ```\n *\n * @see RegexCloser\n * @since 3.0.0\n */\n\nexport const enum RegexElement {\n /**\n * The alternation separator `|`.\n *\n * @since 3.0.0\n */\n\n Alt = '|',\n\n /**\n * The opening of a non-capturing group `(?:`.\n *\n * @since 3.0.0\n */\n\n Open = '(?:',\n\n /**\n * The literal path separator `/`.\n *\n * @since 3.0.0\n */\n\n Slash = '/',\n\n /**\n * A zero-width guard `(?!\\.)` that forbids a leading dot at the start of a segment.\n *\n * @remarks\n * Prevents a wildcard from matching a dotfile unless the pattern names the dot explicitly.\n *\n * @since 3.0.0\n */\n\n NotDot = '(?!\\\\.)',\n\n /**\n * A single character class `[^/]` matching any one character except the path separator.\n *\n * @since 3.0.0\n */\n\n NotSlash = '[^/]',\n\n /**\n * A segment boundary `(?:$|/)` matching either the end of the string or a slash.\n *\n * @since 3.0.0\n */\n\n SegBreak = '(?:$|/)',\n\n /**\n * A greedy run `[^/]*` of characters that are not the path separator.\n *\n * @since 3.0.0\n */\n\n NotSlashRun = '[^/]*',\n\n /**\n * A single character class `[^./]` matching any one character except `.` or `/`.\n *\n * @remarks\n * Emitted for `?` at the start of a segment, where a leading dot must not match.\n *\n * @since 3.0.0\n */\n\n NotDotSlash = '[^./]',\n\n /**\n * A lazy run `[^/]*?` of characters that are not the path separator.\n *\n * @remarks\n * Used as the body of a negation so the negative lookahead governs how much the segment consumes.\n *\n * @since 3.0.0\n */\n\n NotSlashLazy = '[^/]*?',\n\n /**\n * An optional absolute-path root `(?:[A-Za-z]:)?/?` matching a Windows drive prefix and/or a leading slash.\n *\n * @remarks\n * Emitted before a leading globstar so a relative pattern such as `**\\/*.ts` also matches an absolute path\n * like `/a/b/c.ts` or `C:/a/b/c.ts`.\n * Both parts are optional, so a purely relative path still matches.\n * Path separators are assumed to be forward slashes, so normalize Windows backslashes before testing.\n *\n * @since 3.0.0\n */\n\n AbsRoot = '(?:[A-Za-z]:)?/?',\n}\n\n/**\n * Maps an extglob prefix character to the regex closer that ends its non-capturing group.\n *\n * @remarks\n * Keyed by the {@link Char} code unit that precedes a `(` in an extglob construct,\n * the value carries the group-closing parenthesis together with the quantifier that reproduces the prefix semantics.\n * - `@( ... )` matches the group exactly once.\n * - `+( ... )` matches the group one or more times.\n * - `*( ... )` matches the group zero or more times.\n * - `?( ... )` matches the group zero or one time.\n * The presence of a key also signals that the prefix opens an extglob group,\n * so the compiler tests membership before treating the character as extglob syntax.\n *\n * @example\n * ```ts\n * RegexCloser[Char.Plus]; // ')+' - so `+(ab)` compiles to `(?:ab)+`\n * RegexCloser[Char.Bang]; // undefined - `!(` is a negation, handled apart\n * ```\n *\n * @see Char\n * @see RegexElement\n *\n * @since 3.0.0\n */\n\nexport const RegexCloser: Record<number, string> = {\n [Char.At]: ')',\n [Char.Plus]: ')+',\n [Char.Star]: ')*',\n [Char.Question]: ')?'\n} as const;\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { Argv } from 'yargs';\nimport type { BaseArgumentsInterface } from '@argv/interfaces/argv-module.interface';\nimport type { UserExtensionInterface, ArgumentsInterface } from '@argv/interfaces/argv-module.interface';\n\n/**\n * Imports\n */\n\nimport yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport { Injectable } from '@remotex-labs/xinject';\nimport { ArgsDefaultOptions, ArgsUsageExamples } from '@argv/constants/argv.constant';\n\n/**\n * Parses the command line in the two passes startup needs.\n *\n * @remarks\n * A configuration file may add options of its own, so the full option set is not known when the process starts.\n * The passes resolve that: {@link parseConfigFile} reads the `--config` path alone, the file it names is loaded and\n * its options collected, and {@link enhancedParse} then parses the line again knowing everything.\n * The first pass leaves `--help` and `--version` switched off so a run cannot exit on a half-built option set,\n * showing help that omits the configuration's own flags.\n * Only the second turns them on, along with the strict mode that rejects what none of the options account for.\n * Registered as a singleton, so every stage parses against one instance.\n *\n * @example\n * ```ts\n * const argv = inject(ArgvModule);\n *\n * const { config } = argv.parseConfigFile(process.argv); // 'config.xbuild.ts'\n * const userOptions = (await loadConfig(config)).userArgv; // options the file adds\n * argv.enhancedParse(process.argv, userOptions).entryPoints; // [ 'src/index.ts' ]\n * ```\n *\n * @see ArgsDefaultOptions\n * @since 2.0.0\n */\n\n@Injectable({\n scope: 'singleton'\n})\nexport class ArgvModule {\n /**\n * Reads the configuration file path before the rest of the options are known.\n *\n * @param argv - Command-line arguments to read\n * @returns The parsed arguments, always carrying a `config` path\n *\n * @remarks\n * Only `config` is declared, so everything else on the line falls through into the positional list rather than\n * failing - strict mode belongs to {@link enhancedParse}, which is the pass that knows the whole option set.\n * The path is never missing, the option carrying its own default, so a caller has nothing to fall back to.\n * The arguments are passed to yargs as given rather than through `hideBin`,\n * so the executable and script land in the positions and are ignored here, `config` being the only thing read.\n *\n * @example\n * ```ts\n * argv.parseConfigFile(process.argv).config; // 'config.xbuild.ts' - the default\n *\n * // xBuild --config build/prod.xbuild.ts src/index.ts\n * argv.parseConfigFile(process.argv).config; // 'build/prod.xbuild.ts'\n * ```\n *\n * @see enhancedParse\n * @since 2.0.0\n */\n\n parseConfigFile(argv: Array<string>): BaseArgumentsInterface & { config: string } {\n return yargs(argv)\n .help(false)\n .version(false)\n .options({\n config: ArgsDefaultOptions.config\n }).parseSync() as BaseArgumentsInterface & { config: string };\n }\n\n /**\n * Parses the whole command line, xBuild's options, and the configuration together.\n *\n * @param argv - Command-line arguments to parse, executable and script included\n * @param userExtensions - Options the configuration file adds to xBuild's own\n * @returns Every option the line carried, validated against the complete set\n *\n * @throws Error - Thrown by yargs on an unknown flag, a missing value, or a value outside an option's choices\n *\n * @remarks\n * The pass that can afford to be strict, both option sets being known by now: a misspelled flag fails here rather\n * than being collected and silently ignored.\n * Files named without a flag are taken as `entryPoints` through the default command, so the usual invocation\n * needs no flag at all.\n * Help lists the two sets under headings of their own, which is done inside an overridden `showHelp` rather than\n * up front - grouping costs nothing on a run that never asks for help.\n * `hideBin` drops the executable and script here, unlike the first pass, so the positions hold only what\n * the user typed.\n *\n * @example\n * ```ts\n * // xBuild src/app.ts --bundle --minify --env prod\n * const args = argv.enhancedParse(process.argv, { env: { type: 'string' } });\n *\n * args.entryPoints; // [ 'src/app.ts' ]\n * args.bundle; // true\n * args.env; // 'prod' - the configuration's own option\n * ```\n *\n * @see ArgsUsageExamples\n * @since 2.0.0\n */\n\n enhancedParse(argv: Array<string>, userExtensions: UserExtensionInterface = {}): ArgumentsInterface {\n const parser = yargs(hideBin(argv)).locale('en');\n const originalShowHelp = parser.showHelp;\n parser.showHelp = function (consoleFunction?: string | ((s: string) => void)): Argv<unknown> {\n this.group(Object.keys(ArgsDefaultOptions), 'xBuild Options:');\n this.group(Object.keys(userExtensions), 'user Options:');\n\n return originalShowHelp.call(this, consoleFunction as (s: string) => void);\n };\n\n parser\n .usage('Usage: xBuild [files..] [options]')\n .command('* [entryPoints..]', 'Specific files to build (supports glob patterns)', (yargs) => {\n return yargs.positional('entryPoints', {\n describe: 'Specific files to build (supports glob patterns)',\n type: 'string',\n array: true\n });\n })\n .options(userExtensions)\n .options(ArgsDefaultOptions)\n .epilogue('For more information, check the documentation https://remotex-labs.github.io/xBuild/')\n .help()\n .alias('help', 'h')\n .strict()\n .version();\n\n ArgsUsageExamples.forEach(([ command, description ]) => {\n parser.example(command, description);\n });\n\n return parser.parseSync();\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { Options } from 'yargs';\n\n/**\n * Path the `--config` option falls back to.\n *\n * @remarks\n * Resolved against the working directory, so the file is picked up by name from wherever the build was started.\n * It is the default of the option itself rather than a fallback applied afterward,\n * which is what lets every parse pass report a path whether one was typed.\n *\n * @example\n * ```ts\n * ArgsConfigPath; // 'config.xbuild.ts'\n * ArgsDefaultOptions.config.default; // 'config.xbuild.ts' - the same value, reused\n * ```\n *\n * @since 3.0.0\n */\n\nexport const ArgsConfigPath = 'config.xbuild.ts' as const;\n\n/**\n * Every option xBuild itself accepts, in the form yargs declares them.\n *\n * @remarks\n * One table serving three purposes:\n * - it declares the options for the full parse,\n * - it supplies `config` on its own to the early pass that only needs the configuration path,\n * - and its keys name the flags help gathers under the xBuild heading.\n *\n * An option added here is therefore declared, parsed, and documented by that one edit.\n * Only `config` carries a default, so every other flag is absent from the parse result unless it was typed.\n * That is what lets configuration handling tell a flag that was left out from one that was passed as `false`.\n * `platform` and `format` restrict their values, so an unrecognized one fails during parsing rather than reaching the\n * build.\n *\n * @example\n * ```ts\n * ArgsDefaultOptions.minify.alias; // 'm'\n * ArgsDefaultOptions.format.choices; // [ 'cjs', 'esm', 'iife' ]\n * Object.keys(ArgsDefaultOptions); // the flags listed under 'xBuild Options:' in help\n * ```\n *\n * @see ArgsConfigPath\n * @since 3.0.0\n */\n\nexport const ArgsDefaultOptions: Record<string, Options> = {\n entryPoints: {\n describe: 'Source files to build (supports glob patterns)',\n type: 'string',\n array: true\n },\n typeCheck: {\n describe: 'Perform type checking without building output',\n alias: 'tc',\n type: 'boolean'\n },\n platform: {\n describe: 'Target platform for the build output',\n alias: 'p',\n type: 'string',\n choices: [ 'browser', 'node', 'neutral' ] as const\n },\n serve: {\n describe: 'Start server to the <folder>',\n alias: 's',\n type: 'string'\n },\n outdir: {\n describe: 'Directory for build output files',\n alias: 'o',\n type: 'string'\n },\n declaration: {\n describe: 'Generate TypeScript declaration files (.d.ts)',\n alias: 'de',\n type: 'boolean'\n },\n watch: {\n describe: 'Watch mode - rebuild on file changes',\n alias: 'w',\n type: 'boolean'\n },\n config: {\n describe: 'Path to build configuration file',\n alias: 'c',\n type: 'string',\n default: ArgsConfigPath\n },\n tsconfig: {\n describe: 'Path to TypeScript configuration file',\n alias: 'tsc',\n type: 'string'\n },\n minify: {\n describe: 'Minify the build output',\n alias: 'm',\n type: 'boolean'\n },\n bundle: {\n describe: 'Bundle dependencies into output files',\n alias: 'b',\n type: 'boolean'\n },\n types: {\n describe: 'Enable type checking during build process',\n alias: 'btc',\n type: 'boolean'\n },\n failOnError: {\n describe: 'Fail build when TypeScript errors are detected',\n alias: 'foe',\n type: 'boolean'\n },\n format: {\n describe: 'Output module format',\n alias: 'f',\n type: 'string',\n choices: [ 'cjs', 'esm', 'iife' ]\n },\n verbose: {\n describe: 'Verbose error stack traces',\n alias: 'v',\n type: 'boolean'\n },\n build: {\n describe: 'Select an build configuration variant by names (as defined in your config file)',\n alias: 'xb',\n type: 'string',\n array: true\n },\n clean: {\n describe: 'Clean build artifacts',\n type: 'boolean',\n default: false\n }\n} as const;\n\n/**\n * Command and description pairs shown in the examples section of the help output.\n *\n * @remarks\n * Registered one by one on the parser, so the order here is the order they are printed in.\n * They document the combinations worth reaching for rather than every flag,\n * the option list above already covers each flag on its own.\n *\n * @example\n * ```ts\n * ArgsUsageExamples[0]; // [ 'xBuild src/index.ts', 'Build a single file with default settings' ]\n * ```\n *\n * @see ArgsDefaultOptions\n * @since 3.0.0\n */\n\nexport const ArgsUsageExamples = [\n [ 'xBuild src/index.ts', 'Build a single file with default settings' ],\n [ 'xBuild src/**/*.ts --bundle --minify', 'Bundle and minify all TypeScript files' ],\n [ 'xBuild src/app.ts -s', 'Development mode with watch and dev server' ],\n [ 'xBuild src/app.ts -s dist', 'Development mode with watch and dev server from dist folder' ],\n [ 'xBuild src/lib.ts --format esm --declaration', 'Build ESM library with type definitions' ],\n [ 'xBuild src/server.ts --platform node --outdir dist', 'Build Node.js application to dist folder' ],\n [ 'xBuild --typeCheck', 'Type check only without generating output' ],\n [ 'xBuild --config custom.xbuild.ts', 'Use custom configuration file' ]\n] as const;\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { IncomingMessage, ServerResponse } from 'http';\nimport type { ServerAddressInterface, ServerConfigurationInterface, ServerEventsType } from '@server/interfaces/server.interface';\n\n/**\n * Imports\n */\n\nimport * as http from 'http';\nimport * as https from 'https';\nimport { extname } from 'path';\nimport { readFileSync } from 'fs';\nimport html from './html/server.html';\nimport { join } from '@remotex-labs/xmap';\nimport { inject } from '@remotex-labs/xinject';\nimport { Subject } from '@remotex-labs/xobservable';\nimport { readdir, stat, readFile } from 'fs/promises';\nimport { FrameworkService } from '@services/framework.service';\n\n/**\n * Serves one directory over HTTP or HTTPS, files and listings alike.\n *\n * @remarks\n * Meant for looking at build output while developing:\n * a request maps to a path under the root, a file is sent with a content type guessed from its extension,\n * and a directory is rendered as a browsable listing.\n * A configuration can take a request over before any of that happens,\n * which is the hook to reach for when the output needs an API beside it or a single-page fallback.\n * Nothing here writes to a terminal: what it does is reported on a stream, so a run decides what to say about it.\n * Constructed rather than injected, so a build can run several of them over different roots at once.\n *\n * @example\n * ```ts\n * const server = new ServerModule({ port: 0, verbose: true }, 'dist');\n *\n * await server.start(); // resolves once listening, after onStart has run\n * server.config.port; // 54321 - the port the system picked, written back\n * await server.stop();\n * ```\n *\n * @see ServerConfigurationInterface\n * @since 2.0.0\n */\n\nexport class ServerModule {\n /**\n * Node server currently listening, absent until {@link start} and again after {@link stop}.\n *\n * @remarks\n * Holds either an HTTP or an HTTPS server,\n * since the HTTPS type extends the HTTP one and the two are interchangeable here.\n * Its presence is what {@link stop} treats as whether anything is running.\n *\n * @since 2.0.0\n */\n\n private server?: http.Server;\n\n /**\n * The stream everything this server does is reported on.\n *\n * @remarks\n * The server says what happened and writes none of it,\n * so a run decides for itself what reaches a terminal, and one that wants none of it subscribes to nothing.\n * Kept private and reached through {@link pipe} and {@link subscribe},\n * which is what keeps a reader from reporting an event of its own.\n *\n * @see ServerEventsType\n * @since 3.0.0\n */\n\n private readonly events$ = new Subject<ServerEventsType>();\n\n /**\n * Absolute directory every request is resolved inside.\n *\n * @remarks\n * Resolved once in the constructor, so a later change to the working directory cannot move what is being served.\n *\n * @since 2.0.0\n */\n\n private readonly rootDir: string;\n\n /**\n * Framework service, consulted for the directory the bundled certificates ship in.\n *\n * @remarks\n * Only reached when HTTPS is started without a key and certificate of its own.\n *\n * @see FrameworkService\n * @since 2.0.0\n */\n\n private readonly framework = inject(FrameworkService);\n\n /**\n * Creates a server over one directory.\n *\n * @param config - How to listen and what to do with requests\n * @param dir - Directory to serve, resolved to an absolute path immediately\n *\n * @remarks\n * The configuration is kept by reference rather than copied: the host and port defaults land on it here,\n * and the port the system assigns lands on it once listening.\n * The object the caller passed is therefore also how the caller learns what was bound.\n * A port of `0`, which is also the default, leaves the choice to the operating system.\n *\n * @example\n * ```ts\n * const config = { port: 8080, https: true, onRequest: (req, res, next) => next() };\n * const server = new ServerModule(config, './public');\n *\n * config.host; // 'localhost' - defaulted here, on the caller's own object\n * ```\n *\n * @see ServerConfigurationInterface\n * @since 2.0.0\n */\n\n constructor(readonly config: ServerConfigurationInterface, dir: string) {\n this.rootDir = FrameworkService.resolve(dir);\n this.config.port ||= 0;\n this.config.host ||= 'localhost';\n }\n\n /**\n * The event stream's `pipe`, bound to the stream.\n *\n * @remarks\n * Hands out the operator chain without handing out the subject,\n * so a reader composes on what the server reports and cannot report anything itself.\n *\n * @example\n * ```ts\n * server.pipe(filter(event => event.type === 'request')).subscribe(report);\n * ```\n *\n * @see subscribe\n * @since 3.0.0\n */\n\n get pipe(): typeof this.events$.pipe {\n return this.events$.pipe.bind(this.events$);\n }\n\n /**\n * The event stream's `subscribe`, bound to the stream.\n *\n * @remarks\n * How a run learns what the server is doing, since the server itself writes nothing.\n * Answers with the handle that ends the subscription, as the stream's own `subscribe` does.\n *\n * @example\n * ```ts\n * const unsubscribe = server.subscribe(event => event.type); // 'start', then 'request'\n * unsubscribe();\n * ```\n *\n * @see pipe\n * @since 3.0.0\n */\n\n get subscribe(): typeof this.events$.subscribe {\n return this.events$.subscribe.bind(this.events$);\n }\n\n /**\n * Starts listening over HTTPS when the configuration asks for it and over HTTP otherwise.\n *\n * @returns A promise settling once the server is listening\n *\n * @remarks\n * The `onStart` hook runs from the listen callback,\n * so it has already been called - and the assigned port already written back - by the time this resolves.\n * Nothing guards against starting twice:\n * a second call replaces the reference and leaves the first server listening with no way left to close it,\n * so reach for {@link restart} rather than starting again.\n *\n * @example\n * ```ts\n * const server = new ServerModule({ port: 3000, onStart: ({ url }) => console.log(url) }, 'dist');\n * await server.start(); // logs 'http://localhost:3000'\n * ```\n *\n * @see stop\n * @see restart\n *\n * @since 2.0.0\n */\n\n async start(): Promise<void> {\n if (this.config.https)\n return await this.startHttpsServer();\n\n await this.startHttpServer();\n }\n\n /**\n * Closes the server and waits for it to finish.\n *\n * @returns A promise settling once every connection has ended\n *\n * @throws Error - Reported by Node when the server was already closed underneath\n *\n * @remarks\n * Closing refuses new connections and waits on the ones in flight,\n * so a request already in progress delays this rather than ending mid-flight.\n * Stopping when nothing is running is not an error - it reports as much and returns.\n *\n * @example\n * ```ts\n * await server.stop(); // 'Server stopped.'\n * await server.stop(); // 'No server is currently running.'\n * ```\n *\n * @see start\n * @since 2.0.0\n */\n\n async stop(): Promise<void> {\n if (!this.server) return this.events$.next({ type: 'stop', running: false });\n\n await new Promise<void>((resolve, reject) => {\n this.server!.close(err => {\n if (err) reject(err);\n else resolve();\n });\n });\n\n this.server = undefined;\n this.events$.next({ type: 'stop', running: true });\n }\n\n /**\n * Stops the server and starts it again.\n *\n * @returns A promise settling once the new server is listening\n *\n * @remarks\n * Reads the configuration afresh on the way back up, so an edit made while it was running takes effect.\n * A port left at `0` is no longer `0` by then, since the previous run wrote the assigned one back,\n * so a restart keeps the port it was given rather than asking for another.\n *\n * @example\n * ```ts\n * server.config.verbose = true;\n * await server.restart(); // 'Restarting server...' then listening again, now logging requests\n * ```\n *\n * @see stop\n * @see start\n *\n * @since 2.0.0\n */\n\n async restart(): Promise<void> {\n await this.stop();\n await this.start();\n }\n\n /**\n * Writes the port the system assigned back onto the configuration.\n *\n * @remarks\n * Only a configured `0` is replaced, since `0` is the value that leaves the choice to the operating system.\n * A port asked for by number is already what was bound.\n * Called from the listen callback, before `onStart`, so the hook and every later reader see the real port.\n *\n * @since 2.0.0\n */\n\n private setActualPort(): void {\n if (this.config.port === 0) {\n const address = this.server!.address();\n if(address && typeof address === 'object' && address.port)\n this.config.port = address.port;\n }\n }\n\n /**\n * Creates and starts the plain HTTP server.\n *\n * @returns A promise settling once the server is listening\n *\n * @remarks\n * Every request goes through {@link handleRequest},\n * which is handed the default handling as a callback,\n * so a configuration hook can decide whether to run it.\n *\n * @since 2.0.0\n */\n\n private startHttpServer(): Promise<void> {\n return new Promise<void>((resolve) => {\n this.server = http.createServer((req, res) => {\n this.handleRequest(req, res, () => this.defaultResponse(req, res));\n });\n\n this.server.listen(this.config.port, this.config.host, () => {\n this.setActualPort();\n const address: ServerAddressInterface = {\n host: this.config.host!,\n port: this.config.port!,\n url: `http://${ this.config.host }:${ this.config.port }`\n };\n\n this.config.onStart?.(address);\n this.events$.next({ ...address, type: 'start' });\n resolve();\n });\n });\n }\n\n /**\n * Creates and starts the HTTPS server.\n *\n * @returns A promise settling once the server is listening\n *\n * @throws Error - Raised when a key or certificate cannot be read\n *\n * @remarks\n * A configuration naming neither key nor certificate falls back to the pair shipped with the framework,\n * so HTTPS can be switched on without producing one first.\n * That pair is self-signed, so a browser will warn about it, which is what a development server can live with.\n * Both files are read synchronously, before anything is listening,\n * so a missing one fails the start rather than the first request.\n *\n * @since 2.0.0\n */\n\n private startHttpsServer(): Promise<void> {\n return new Promise((resolve) => {\n const options = {\n key: readFileSync(this.config.key ?? join(this.framework.frameworkRoot, '..', 'certs', 'server.key')),\n cert: readFileSync(this.config.cert ?? join(this.framework.frameworkRoot, '..', 'certs', 'server.crt'))\n };\n\n this.server = https.createServer(options, (req, res) => {\n this.handleRequest(req, res, () => this.defaultResponse(req, res));\n });\n\n this.server.listen(this.config.port, this.config.host, () => {\n this.setActualPort();\n const address: ServerAddressInterface = {\n host: this.config.host!,\n port: this.config.port!,\n url: `https://${ this.config.host }:${ this.config.port }`\n };\n\n this.config.onStart?.(address);\n this.events$.next({ ...address, type: 'start' });\n resolve();\n });\n });\n }\n\n /**\n * Passes a request to the configuration's hook or to the default handling when there is none.\n *\n * @param req - Request as it arrived\n * @param res - Response to write to\n * @param defaultHandler - The static-file handling, for the hook to call or to skip\n *\n * @remarks\n * A hook that never calls the handler owns the response entirely,\n * which is what makes an API route or a single-page fallback possible.\n * Only what throws synchronously reaches the error response here:\n * the default handling is asynchronous and catches its own failures,\n * and a hook that rejects a promise of its own is beyond this.\n *\n * @see sendError\n * @since 2.0.0\n */\n\n private handleRequest(req: IncomingMessage, res: ServerResponse, defaultHandler: () => void): void {\n try {\n this.events$.next({ type: 'request', url: req.url ?? '' });\n\n if (this.config.onRequest) {\n this.config.onRequest(req, res, defaultHandler);\n } else {\n defaultHandler();\n }\n } catch (error) {\n this.sendError(res, <Error> error);\n }\n }\n\n /**\n * Maps a file extension to the content type it is served as.\n *\n * @param ext - Extension without its dot\n * @returns The matching content type, or the binary fallback for an extension not listed\n *\n * @remarks\n * Covers what a build emits rather than the web at large.\n * TypeScript is served as plain text, so a browser shows a source file instead of downloading it,\n * and an unlisted extension downloads under the binary fallback rather than under a guess.\n *\n * @since 2.0.0\n */\n\n private getContentType(ext: string): string {\n const contentTypes: Record<string, string> = {\n html: 'text/html',\n css: 'text/css',\n js: 'application/javascript',\n cjs: 'application/javascript',\n mjs: 'application/javascript',\n ts: 'text/plain',\n map: 'application/json',\n json: 'application/json',\n png: 'image/png',\n jpg: 'image/jpeg',\n gif: 'image/gif',\n txt: 'text/plain'\n };\n\n return contentTypes[ext] || 'application/octet-stream';\n }\n\n /**\n * Resolves a request to a path under the root and serves whatever is there.\n *\n * @param req - Request as it arrived\n * @param res - Response to write to\n *\n * @remarks\n * The request path is joined onto the root and the result checked for the root prefix,\n * so a path climbing out with `..` is refused with a 403.\n * The check is by prefix rather than true containment,\n * so a sibling directory whose name starts with the root's own would pass it.\n * A directory is listed and a file is sent.\n * Anything else on disk - a socket or a device - matches neither, and the request ends unanswered.\n * A path that cannot be reached at all is reported as missing,\n * and a failed `favicon.ico` is passed over in the log, since browsers ask for one unprompted on every visit.\n *\n * @see handleFile\n * @see handleDirectory\n *\n * @since 2.0.0\n */\n\n private async defaultResponse(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const requestPath = req.url === '/' ? '' : req.url?.replace(/^\\/+/, '') || '';\n const fullPath = join(this.rootDir, requestPath);\n\n if (!fullPath.startsWith(this.rootDir)) {\n res.statusCode = 403;\n res.end();\n\n return;\n }\n\n try {\n const stats = await stat(fullPath);\n\n if (stats.isDirectory()) {\n await this.handleDirectory(fullPath, requestPath, res);\n } else if (stats.isFile()) {\n await this.handleFile(fullPath, res);\n }\n } catch (error) {\n this.events$.next({ type: 'error', error: <Error> error, url: req.url });\n this.sendNotFound(res);\n }\n }\n\n /**\n * Renders a directory as a browsable listing.\n *\n * @param fullPath - Absolute path of the directory to list\n * @param requestPath - The same directory as the request spelled it, relative to the root\n * @param res - Response to write to\n *\n * @remarks\n * Entries are told apart by whether they have an extension,\n * so a directory carrying a dot in its name is drawn as a file,\n * since a listing is navigation rather than a report.\n * The request path is also split into a trail of links, one per directory it names,\n * which is what lets a visitor climb back out.\n * Names are put into the template as they are, so a filename containing markup reaches the page intact.\n *\n * @since 2.0.0\n */\n\n private async handleDirectory(fullPath: string, requestPath: string, res: ServerResponse): Promise<void> {\n const files = await readdir(fullPath);\n let fileList = files.map(file => {\n const fullPath = join(requestPath, file);\n const ext = extname(file).slice(1) || 'folder';\n\n if(ext === 'folder') {\n return `\n <a href=\"/${ fullPath }\" class=\"folder-row\">\n <div class=\"icon\"><i class=\"fa-solid fa-folder\"></i></div>\n <div class=\"meta\"><div class=\"name\">${ file }</div><div class=\"sub\">Folder</div></div>\n </a>\n `;\n }\n\n return `\n <a href=\"/${ fullPath }\" class=\"file-row\">\n <div class=\"icon\"><i class=\"fa-solid fa-file-code\"></i></div>\n <div class=\"meta\"><div class=\"name\">${ file }</div><div class=\"sub\">${ ext }</div></div>\n </a>\n `;\n }).join('');\n\n if(!fileList) {\n fileList = '<div class=\"empty\">No files or folders here.</div>';\n } else {\n fileList = `<div class=\"list\">${ fileList }</div>`;\n }\n\n let activePath = '/';\n const segments = requestPath.split('/').map(path => {\n activePath += `${ path }/`;\n\n return `<li><a href=\"${ activePath }\">${ path }</a></li>`;\n }).join('');\n\n const htmlResult = html.replace('${ fileList }', fileList)\n .replace('${ paths }', '<li><a href=\"/\">root</a></li>' + segments)\n .replace('${ up }', '/' + requestPath.split('/').slice(0, -1).join('/'));\n\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(htmlResult);\n }\n\n /**\n * Sends one file.\n *\n * @param fullPath - Absolute path of the file to send\n * @param res - Response to write to\n *\n * @remarks\n * Read whole before anything is written,\n * so the response carries no length and a large file is held in memory rather than streamed,\n * which a development server over its own build output can afford.\n * A file with no extension is treated as text.\n *\n * @see getContentType\n * @since 2.0.0\n */\n\n private async handleFile(fullPath: string, res: ServerResponse): Promise<void> {\n const ext = extname(fullPath).slice(1) || 'txt';\n const contentType = this.getContentType(ext);\n\n const data = await readFile(fullPath);\n res.writeHead(200, { 'Content-Type': contentType });\n res.end(data);\n }\n\n /**\n * Answers a request that reached nothing.\n *\n * @param res - Response to write to\n *\n * @remarks\n * Plain text rather than the listing template, since the answer is for whatever asked rather than for a reader.\n *\n * @since 2.0.0\n */\n\n private sendNotFound(res: ServerResponse): void {\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('Not Found');\n }\n\n /**\n * Answers a request that failed and reports why.\n *\n * @param res - Response to write to\n * @param error - The failure to report\n *\n * @remarks\n * The reason is logged rather than sent,\n * so a stack trace reaches the developer running the server and not whoever is connected to it.\n *\n * @since 2.0.0\n */\n\n private sendError(res: ServerResponse, error: Error): void {\n this.events$.next({ type: 'error', error });\n res.writeHead(500, { 'Content-Type': 'text/plain' });\n res.end('Internal Server Error');\n }\n}\n","<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"/><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"/><title>Dark File Browser — FTP-like</title><link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/css/all.min.css\" integrity=\"sha512-2SwdPD6INVrV/lHTZbO2nodKhrnDdJK9/kg2XD1r9uGqPo1cUbujc+IYdlYdEErWNu69gVcYgdxlmVmzTWnetw==\" crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\" /><style>:root{--bg:#0b0f14;--panel:#0f1720;--muted:#9aa4b2;--accent:#E5C07B;--glass:rgba(255,255,255,0.03);--card:#0c1116;--radius:12px;--gap:12px;--shadow:0 6px 18px rgba(0,0,0,0.4);--file-icon-size:40px;font-family:Inter,ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,'Helvetica Neue',Arial}*{box-sizing:border-box;font-style:normal !important}html,body{height:100%;margin:0;font-size:14px;color:#dce7ef;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:radial-gradient(1200px 600px at 10% 10%,rgba(110,231,183,0.04),transparent 8%),linear-gradient(180deg,rgba(255,255,255,0.01),transparent 20%),var(--bg);padding:28px;display:flex;gap:20px;align-items:flex-start;justify-content:center}.app{width:1100px;max-width:98vw;display:flex;gap:18px;padding:18px;border-radius:16px;box-shadow:var(--shadow);border:1px solid rgba(255,255,255,0.03);background:linear-gradient(180deg,rgba(255,255,255,0.02),rgba(255,255,255,0));overflow:hidden}.sidebar{width:260px;background:linear-gradient(180deg,rgba(255,255,255,0.01),transparent);border-radius:var(--radius);padding:14px}.brand{display:flex;gap:12px;align-items:center;margin-bottom:10px}.logo{width:46px;height:46px;border-radius:10px;background:linear-gradient(135deg,#b65b9f 0%,#804b8f 100%);display:flex;align-items:center;justify-content:center;font-weight:700}.brand h1{font-size:16px;margin:0}.muted{color:var(--muted);font-size:13px}.search{margin:12px 0}.search input{width:100%;padding:10px 12px;border-radius:10px;border:1px solid rgba(255,255,255,0.03);background:var(--glass);color:inherit}.quick-list{margin-top:12px}.quick-list a{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;background:transparent;color:var(--muted);text-decoration:none;cursor:pointer;transition:color 0.15s ease}.quick-list a:hover{color:var(--accent)}.main{flex:1;display:flex;flex-direction:column}.topbar{display:flex;align-items:center;gap:12px;padding-bottom:12px}.breadcrumbs{list-style:none;display:flex;gap:8px;align-items:center;background:var(--glass);padding:8px 12px;border-radius:var(--radius);margin:0}.breadcrumbs li{display:flex;align-items:center}.breadcrumbs li:not(:last-child)::after{content:'>';margin-left:8px;color:var(--muted)}.breadcrumbs a{color:var(--muted);text-decoration:none;transition:color 0.15s ease}.breadcrumbs a:hover{color:var(--accent)}.list{margin-top:14px;display:grid;grid-template-columns:1fr;gap:10px}.list a{display:flex;text-decoration:none;color:inherit}.folder-row,.file-row{display:flex;gap:12px;align-items:center;padding:10px;border-radius:10px;background:linear-gradient(180deg,rgba(255,255,255,0.01),transparent);border:1px solid rgba(255,255,255,0.02);transition:color 0.25s ease}.icon{width:var(--file-icon-size);height:var(--file-icon-size);border-radius:10px;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,0.02);flex-shrink:0;transition:background 0.25s ease,color 0.25s ease}.folder-row:hover,.file-row:hover{color:var(--accent)}.folder-row:hover .icon{background:rgba(152,195,121,0.2)}.file-row:hover .icon{background:rgba(224,108,117,0.2)}.folder-row:hover .icon i{color:#98C379}.file-row:hover .icon i{color:#e09c6c}.meta{display:flex;flex-direction:column}.name{font-weight:600}.sub{color:var(--muted);font-size:13px}.empty{padding:40px;text-align:center;color:var(--muted)}@media (max-width:880px){.app{flex-direction:column;padding:12px}.sidebar,.main{width:100%}}</style></head><body><div class=\"app\"><aside class=\"sidebar\"><div class=\"brand\"><div class=\"logo\">F</div><div><h1>xBuildFTP</h1><div class=\"muted\">Browse & serve files</div></div></div><div class=\"search\"><input placeholder=\"Search files & folders...\"/></div><div class=\"quick-list\"><a href=\"/\">🏠 Home</a><a href=\"${ up }\">⬆️ Up</a></div></aside><main class=\"main\"><div class=\"topbar\"><div class=\"topbar\"><ul class=\"breadcrumbs\"> ${ paths } </ul></div></div> ${ fileList } </main></div></body><script> const searchInput = document.querySelector('.search input'); const listItems = document.querySelectorAll('.list > .folder-row, .list > .file-row'); const emptyMessage = document.querySelector('.empty'); searchInput.addEventListener('input', () => { const query = searchInput.value.toLowerCase(); let anyVisible = false; listItems.forEach(item => { const name = item.querySelector('.name').textContent.toLowerCase(); if (name.includes(query)) { item.style.display = 'flex'; anyVisible = true; } else { item.style.display = 'none'; } }); emptyMessage.style.display = anyVisible ? 'none' : 'block'; }); </script></html>","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { Message } from 'esbuild';\nimport type { DeepPartialType } from '@interfaces/types.interface';\nimport type { ConfigurationInterface } from '@interfaces/configuration.interface';\nimport type { BuildResultInterface, LifecycleEventsType, LifecycleLogsType } from '@interfaces/lifecycle.interface';\n\n/**\n * Imports\n */\n\nimport { inject } from '@remotex-labs/xinject';\nimport { xBuildError } from '@errors/xbuild.error';\nimport { Subject } from '@remotex-labs/xobservable';\nimport { VariantService } from '@services/variant.service';\nimport { ConfigurationService } from '@services/configuration.service';\nimport { TypescriptService } from '@typescript/services/typescript.service';\n\n/**\n * Runs a whole configuration - every variant it declares, in the order their dependencies allow.\n *\n * @remarks\n * Owns the configuration for a run and the event stream the variants report on,\n * while each variant owns the build it runs.\n * A variant is constructed for every entry the configuration declares and reused from then on,\n * so re-reading an edited configuration adds what it gained and leaves the rest running.\n *\n * @example\n * ```ts\n * const build = new BuildService(config, { watch: true });\n * build.subscribe(event => event.type); // 'start', then 'end'\n *\n * const results = await build.build();\n * results.length; // 2 - one per variant\n * ```\n *\n * @see VariantService\n * @see ConfigurationInterface\n *\n * @since 3.0.0\n */\n\nexport class BuildService {\n /**\n * The stream every variant reports its start and end on.\n *\n * @remarks\n * Handed to each variant as it is constructed, so one stream carries the whole run\n * rather than a reader subscribing to each variant in turn.\n * Kept private and reached through `pipe` and `subscribe`,\n * which is what keeps a reader from pushing an event of its own onto it.\n *\n * @see LifecycleEventsType\n * @since 3.0.0\n */\n\n private readonly events$ = new Subject<LifecycleEventsType>();\n\n /**\n * The configuration service this run reads and writes through.\n *\n * @remarks\n * The injected instance rather than one of its own, and the same instance every variant selects from,\n * so a change written here reaches the variants without being handed to them.\n *\n * @see ConfigurationService\n * @since 3.0.0\n */\n\n private readonly config$ = inject(ConfigurationService);\n\n /**\n * Applies a configuration and constructs a variant for every entry it declares.\n *\n * @param config - Configuration to run, merged over whatever the service already holds\n * @param argv - Parsed command line the build was started with, empty when the caller passes none\n *\n * @remarks\n * The configuration is patched rather than put in place of what is there,\n * so the built-in defaults survive underneath what a configuration file states.\n * The subscription that follows is called at once with the merged configuration,\n * which is what constructs the variants before the constructor returns,\n * and it keeps them current with every later change.\n *\n * @example\n * ```ts\n * const build = new BuildService({ logLevel: 'warning', variants: { esm } }, { watch: true });\n * ```\n *\n * @see ConfigurationService.patch\n * @since 3.0.0\n */\n\n constructor(config: ConfigurationInterface, private argv: Record<string, unknown> = {}) {\n this.config$.patch(config);\n this.config$.subscribe(this.parseVariants.bind(this));\n }\n\n /**\n * The event stream's `pipe`, bound to the stream.\n *\n * @remarks\n * Hands out the operator chain without handing out the subject,\n * so a reader composes on the run's events and cannot report one of its own.\n *\n * @example\n * ```ts\n * const ended = build.pipe(filter(event => event.type === 'end'));\n * ended.subscribe(report);\n * ```\n *\n * @see BuildService.subscribe\n * @since 3.0.0\n */\n\n get pipe(): typeof this.events$.pipe {\n return this.events$.pipe.bind(this.events$);\n }\n\n /**\n * The event stream's `subscribe`, bound to the stream.\n *\n * @remarks\n * The plain way to watch a run, for a reader wanting every event rather than a filtered view.\n * Answers with the handle that ends the subscription, as the stream's own `subscribe` does.\n *\n * @example\n * ```ts\n * const unsubscribe = build.subscribe(event => event.type); // 'start', then 'end'\n * unsubscribe();\n * ```\n *\n * @see BuildService.pipe\n * @since 3.0.0\n */\n\n get subscribe(): typeof this.events$.subscribe {\n return this.events$.subscribe.bind(this.events$);\n }\n\n /**\n * Starts the configuration again from the one this service was constructed with.\n *\n * @param config - Configuration to apply over the initial one\n *\n * @remarks\n * Reloads rather than patches, so whatever accumulated since construction is dropped,\n * and only the initial configuration survives underneath.\n * That is what re-reading an edited file wants, since patching a list would extend it rather than replace it.\n * Assigning is also what ends a variant,\n * since one the new configuration no longer declares disposes of itself as the change reaches it.\n *\n * @example\n * ```ts\n * build.configuration = { common: { esbuild: { minify: false } } };\n * ```\n *\n * @see ConfigurationService.reload\n * @since 3.0.0\n */\n\n set configuration(config: DeepPartialType<ConfigurationInterface>) {\n this.config$.reload(config);\n }\n\n /**\n * Builds the variants named, or every variant the configuration declares, in the order `dependOn` asks for.\n *\n * @param names - Variants to build, building every variant the configuration declares when omitted\n * @returns One result per variant asked for, in the order they were named\n * @throws xBuildError - When a `dependOn` chain closes on itself, or names a variant that does not exist\n *\n * @remarks\n * Naming variants builds those and whatever they wait for, leaving everything else alone.\n * A name no variant answers to is passed over rather than reported as an error,\n * so a list naming nothing this configuration declares builds nothing at all.\n * A dependency built along the way reports on the event stream like any other build\n * while staying out of the results, which carry the variants that were asked for.\n * The whole graph is wired before any variant runs, and every variant waits on the same gate,\n * so a chain that turns out to be broken builds nothing at all rather than part of the output.\n * A variant that several others depend on is built once and its result shared,\n * since the graph is walked through a cache keyed by name.\n * A build that fails does not reject here - its errors arrive on its own result.\n * A dependency counts as failed where it produced no output, whether it threw or only reported errors.\n * The variant waiting on it is skipped rather than built,\n * and the result {@link skipped} shapes carries no output either, so its own dependents skip in turn.\n *\n * @example\n * ```ts\n * const results = await build.build();\n * results.length; // 2 - the types variant first, then the bundle that depends on it\n *\n * const [ app ] = await build.build([ 'app' ]); // types builds too, since app waits for it\n * await build.build([ 'umd' ]); // [] - no variant answers to the name\n * ```\n *\n * @see BuildResultInterface\n * @since 3.0.0\n */\n\n async build(names?: Array<string>): Promise<Array<BuildResultInterface>> {\n const variants = new Map(Array.from(VariantService.get(), variant => [ variant.name, variant ] as const));\n const cache = new Map<string, Promise<BuildResultInterface>>();\n const start = Promise.withResolvers<void>();\n\n const run = (name: string, path: Array<string> = []): Promise<BuildResultInterface> => {\n if (path.includes(name))\n throw new xBuildError(`Circular dependency detected: ${ [ ...path, name ].join(' → ') }`);\n if (!variants.has(name))\n throw new xBuildError(`Variant \"${ path.at(-1) }\" depends on \"${ name }\", which is not a variant`);\n\n if (!cache.has(name)) {\n const dependOn = this.getDependOn(name);\n\n cache.set(name, Promise\n .all([ start.promise, ...dependOn.map(dependency => run(dependency, [ ...path, name ])) ])\n .then(([ , ...results ]) => {\n const failed = dependOn.filter((_, index) => Object.keys(results[index]?.metafile?.outputs ?? {}).length < 1);\n if (failed.length) return this.skipped(name, failed);\n\n return variants.get(name)!.build();\n })\n );\n }\n\n return cache.get(name)!;\n };\n\n const results = Array.from(names?.filter(name => variants.has(name)) ?? variants.keys(), name => run(name));\n start.resolve();\n\n return Promise.all(results);\n }\n\n /**\n * Type-checks the variants named, or every variant the configuration declares, without building any of them.\n *\n * @param names - Variants to check, checking every variant the configuration declares when omitted\n * @returns The messages each variant's check reported, keyed by the variant's name\n *\n * @remarks\n * The variants are checked one at a time rather than together,\n * since every variant carries a TypeScript program of its own.\n * Each variant answers with the buckets a build would file its messages under,\n * so a diagnostic reads at the level the configuration gives it rather than in the compiler's own shape.\n * A variant that checks clean is present with its buckets empty rather than left out,\n * so a reader tells a clean variant from one that was never checked.\n * Only the variants named are checked, dependencies among them or not,\n * since a variant is checked against the files its own build reaches,\n * and what another variant reaches is that variant's own to report.\n * A name is matched against the variants rather than looked up,\n * so one no variant answers to is passed over,\n * and a list naming nothing this configuration declares checks nothing at all.\n *\n * @example\n * ```ts\n * const { esm } = await build.typeChack();\n * esm.error.length; // 0 - nothing to report\n *\n * await build.typeChack([ 'esm' ]); // { esm: { ... } } - cjs is left alone\n * await build.typeChack([ 'umd' ]); // {} - no variant answers to the name\n * ```\n *\n * @see LifecycleLogsType\n * @since 3.0.0\n */\n\n async typeChack(names?: Array<string>): Promise<Record<string, LifecycleLogsType>> {\n const result: Record<string, LifecycleLogsType> = {};\n\n for (const variant of VariantService.get()) {\n if (!names || names.includes(variant.name)) result[variant.name] = await variant.check();\n }\n\n return result;\n }\n\n /**\n * Re-reads the TypeScript configuration from disk.\n *\n * @remarks\n * Reparses the configuration so a later check or build reads it as it now stands,\n * which is what a watch cycle needs after an edit to `tsconfig.json`.\n * The list of files reparsed is dropped rather than passed on, so a caller learns only that the reparse ran.\n * Nothing here waits on anything, so the promise settles at once.\n *\n * @example\n * ```ts\n * await build.reload(); // the TypeScript configuration is read again\n * ```\n *\n * @see TypescriptService.reload\n * @since 3.0.0\n */\n\n async reload(): Promise<void> {\n TypescriptService.reload();\n }\n\n /**\n * Constructs a variant for every entry the configuration declares.\n *\n * @param config - Configuration as it now stands\n * @throws xBuildError - When there is no configuration to read variants from\n *\n * @remarks\n * A name that already has a variant is passed over,\n * so re-reading a configuration adds what it gained\n * and leaves the variants it kept running rather than replacing them.\n * Nothing is removed here,\n * since a variant the configuration stopped declaring watches its own entry and disposes of itself.\n *\n * @see VariantService\n * @since 3.0.0\n */\n\n private parseVariants(config: ConfigurationInterface): void {\n if (!config)\n throw new xBuildError('Variants are not defined in the configuration');\n\n for (const name of Object.keys(config.variants ?? [])) {\n if (VariantService.has(name)) continue;\n new VariantService(name, this.events$, this.argv);\n }\n }\n\n /**\n * Shapes the result of a variant that was skipped rather than run and reports it as an end.\n *\n * @param name - Variant that was not built\n * @param dependencies - Names of the dependencies that failed, in the order the variant declared them\n * @returns A result carrying one error naming them, and nothing at any other level\n *\n * @remarks\n * Shaped as a build result rather than as a thrown error,\n * so a skipped variant reads like a failed one to whatever reports the run.\n * It carries no metafile, which is what makes its own dependents skip in turn,\n * since a dependency that produced no output is what the graph reads as a failure.\n * Nothing was compiled, so every bucket but `errors` comes back empty.\n * The result is built from the buckets the context carries rather than from a second literal,\n * so a level cannot be named in one and missing from the other,\n * and a reader of the event and a reader of the result are looking at the same messages.\n * The same result goes out on the event stream as an end,\n * since a variant that never ran reports no end of its own.\n * A reader would otherwise see the run finish, with one variant missing from the count.\n * The context is assembled here rather than taken from a build,\n * so its options are the ones the configuration states, and its duration is zero.\n *\n * @example\n * ```ts\n * const { errors } = this.skipped('app', [ 'types' ]);\n * errors[0].text; // 'Variant \"app\" was not built, because \"types\" failed'\n * ```\n *\n * @see BuildResultInterface\n * @since 3.0.0\n */\n\n private skipped(name: string, dependencies: Array<string>): BuildResultInterface {\n const failed = dependencies.map(dependency => `\"${ dependency }\"`).join(', ');\n const errors: Array<Message> = [\n {\n id: 'dependency-failed',\n text: `Variant \"${ name }\" was not built, because ${ failed } failed`,\n notes: [],\n detail: undefined,\n location: null,\n pluginName: name\n }\n ];\n\n const variant = this.config$.getValue().variants?.[name];\n const logs: LifecycleLogsType = { info: [], verbose: [], error: errors, warning: [] };\n const buildResult = <BuildResultInterface> <unknown> {\n info: logs.info, verbose: logs.verbose, errors: logs.error, warnings: logs.warning\n };\n\n this.events$.next({\n type: 'end',\n duration: 0,\n context: {\n argv: this.argv,\n logs,\n options: variant?.esbuild ?? {},\n overrides: variant?.logOverride ?? {},\n variantName: name,\n stage: {\n startTime: new Date(),\n dropped: new Set<string>(),\n reachableFiles: new Set<string>()\n }\n },\n buildResult\n });\n\n return buildResult;\n }\n\n /**\n * Returns the variants one variant waits for.\n *\n * @param name - Variant whose dependencies are wanted\n * @returns The names it depends on, empty when it depends on none\n *\n * @remarks\n * Read from the configuration as it stands rather than from a copy taken when the run began.\n * A single name is flattened into a list, so both forms `dependOn` accepts read the same way here.\n *\n * @see VariantConfigurationInterface\n * @since 3.0.0\n */\n\n private getDependOn(name: string): Array<string> {\n return [ this.config$.getValue().variants?.[name]?.dependOn ?? [] ].flat();\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { StackTraceInterface } from '@providers/interfaces/stack-provider.interface';\n\n/**\n * Imports\n */\n\nimport { xBuildBaseError } from '@errors/base.error';\n\n/**\n * A general framework error, resolved against its sources as it is constructed.\n *\n * @remarks\n * Throw this when the failure needs no error type of its own.\n * Extend {@link xBuildBaseError} instead when callers have to branch on the type,\n * or when the error has to carry extra fields.\n * Framework frames stay eligible for the code window by default, since a failure raised here is usually raised\n * inside the build itself and the snippet would otherwise be dropped.\n *\n * @example\n * ```ts\n * throw new xBuildError('tsconfig.json was not found');\n * // xBuildBaseError: tsconfig.json was not found\n * //\n * // Enhanced Stack Trace:\n * // at run src/bash.ts:41:11\n * ```\n *\n * @see xBuildBaseError\n * @see StackTraceInterface\n *\n * @since 1.0.0\n */\n\nexport class xBuildError extends xBuildBaseError {\n\n /**\n * Creates the error and resolves its stack right away.\n *\n * @param message - Message describing what went wrong\n * @param options - Frame selection and code window size, keeping framework frames by default\n *\n * @remarks\n * Resolution happens here rather than on first print, so the frames describe the throw site even when the error\n * travels before anything renders it.\n *\n * @example\n * ```ts\n * new xBuildError('entry point missing').metadata?.formatCode; // the highlighted throw site\n * new xBuildError('entry point missing', { linesBefore: 1, linesAfter: 1 }); // a tighter code window\n * ```\n *\n * @see StackTraceInterface\n * @see xBuildBaseError.reformatStack\n *\n * @since 1.0.0\n */\n\n constructor(message: string, options: StackTraceInterface = { withFrameworkFrames: true }) {\n super(message);\n this.reformatStack(this, options);\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { PartialMessage, Loader } from 'esbuild';\nimport type { OnResolveArgs, OnResolveResult } from 'esbuild';\nimport type { OnStartResult, OnLoadArgs, OnLoadResult } from 'esbuild';\nimport type { DiagnosticInterface } from '@typescript/typescript.module';\nimport type { Subject, UnsubscribeType } from '@remotex-labs/xobservable';\nimport type { BuildOptions, Plugin, PluginBuild, BuildResult } from 'esbuild';\nimport type { LifecycleContextInterface } from '@interfaces/lifecycle.interface';\nimport type { LogLevelType } from '@providers/interfaces/log-provider.interface';\nimport type { VariantConfigurationInterface } from '@interfaces/configuration.interface';\nimport type { BuildResultType } from '@services/interfaces/transpiler-service.interface';\nimport type { CallType, HandleType } from '@services/interfaces/variant-service.interface';\nimport type { LifecycleEventsType, BuildResultInterface } from '@interfaces/lifecycle.interface';\nimport type { LifecyclePluginInterface, LifecycleLogsType } from '@interfaces/lifecycle.interface';\nimport type { VariantSubscriptionInterface } from '@services/interfaces/variant-service.interface';\n\n/**\n * Imports\n */\n\nimport { parseSync } from 'oxc-parser';\nimport { relative } from '@remotex-labs/xmap';\nimport { inject } from '@remotex-labs/xinject';\nimport { FilesModel } from '@models/files.model';\nimport { xBuildError } from '@errors/xbuild.error';\nimport { collectLogs } from '@providers/log.provider';\nimport { Typescript } from '@typescript/typescript.module';\nimport { analyzeMacros } from '@directives/analyze.directive';\nimport { transformMacros } from '@directives/macros.directive';\nimport { resolveSource } from '@components/transformer.component';\nimport { deepMerge, stringify } from '@components/object.component';\nimport { ConfigurationService } from '@services/configuration.service';\nimport { extractEntryPoints } from '@components/entry-points.component';\nimport { TextBlocks, DiagnosticLevels } from '@constants/variant.constant';\nimport { errorToMessage, isEsbuildError } from '@providers/message.provider';\nimport { buildFiles, analyzeDependencies } from '@services/transpiler.service';\n\n/**\n * Runs one named variant of a build, from the configuration it watches to the result it reports.\n *\n * @remarks\n * One instance per entry in `variants`, kept in a static registry under that name and reused by every build,\n * so a watch cycle rebuilds through the same variant rather than replacing it each time.\n * The instance follows the configuration it was named in:\n * it re-reads its settings whenever they change and disposes of itself once the configuration drops its entry.\n * A build runs as a single esbuild plugin, which is what gives the configured hooks their place in the run.\n *\n * @example\n * ```ts\n * const variant = new VariantService('esm', events$, { watch: true });\n * const result = await variant.build();\n *\n * result.errors.length; // 0\n * variant.dispose();\n * ```\n *\n * @see LifecyclePluginInterface\n * @see VariantConfigurationInterface\n *\n * @since 3.0.0\n */\n\nexport class VariantService {\n /**\n * The file model every variant reads its sources through.\n *\n * @remarks\n * Held on the class rather than the instance, so one cache of snapshots serves every variant,\n * which is what keeps two variants of the same project from reading the same file twice.\n *\n * @since 3.0.0\n */\n\n private static readonly filesModel: FilesModel = inject(FilesModel);\n\n /**\n * The live variants, keyed by the name each was constructed under.\n *\n * @remarks\n * What {@link VariantService.has} and {@link VariantService.get} read,\n * and what {@link VariantService.dispose} removes an entry from,\n * so a name a disposed variant held is free for a later configuration to claim.\n *\n * @since 3.0.0\n */\n\n private static readonly instances = new Map<string, VariantService>();\n\n /**\n * The handle that ends this variant's configuration subscription.\n *\n * @remarks\n * Called as the variant is disposed,\n * so one the configuration has dropped stops reacting to a configuration it no longer belongs to.\n *\n * @since 3.0.0\n */\n\n private readonly configUnsubscribe: UnsubscribeType;\n\n /**\n * The hook sets these variant dispatches to, in the order they run.\n *\n * @remarks\n * Rebuilt on every configuration change as the declared plugins followed by the variant's own `lifecycle` set,\n * so a shared plugin runs ahead of the hooks a variant adds for itself.\n * The `lifecycle` set is given the variant's name, which is what lets its messages be credited as a plugin's.\n *\n * @since 3.0.0\n */\n\n private hooks: Array<LifecyclePluginInterface> = [];\n\n /**\n * Whether this variant has been torn down.\n *\n * @remarks\n * Guards {@link VariantService.build},\n * so a variant the configuration dropped reports rather than building against settings that are gone.\n *\n * @since 3.0.0\n */\n\n private isDisposed = false;\n\n /**\n * The TypeScript module this variant checks and emits through.\n *\n * @remarks\n * Replaced whenever the configuration changes, since a different `tsconfig` needs a program of its own,\n * and the one it replaces is disposed of only after the swap.\n * Populated by the subscription the constructor opens rather than by the constructor itself.\n *\n * @since 3.0.0\n */\n\n private typescriptModule!: Typescript;\n\n /**\n * The merged settings this variant builds under.\n *\n * @remarks\n * The common block with the variant merged over it, so a read here needs no further merging.\n * Populated by the subscription the constructor opens rather than by the constructor itself.\n *\n * @see VariantConfigurationInterface\n * @since 3.0.0\n */\n\n private buildConfig!: VariantConfigurationInterface;\n\n /**\n * Registers a variant under its name and starts following the configuration.\n *\n * @param name - Name the configuration declares this variant under, readable afterward\n * @param events$ - Subject the variant reports its start and end on\n * @param argv - Parsed command line the build was started with, empty when the caller passes none\n *\n * @remarks\n * The variant is usable as soon as it is constructed, since the subscription it opens delivers the settings\n * before the constructor returns.\n * An error in the subscription reports is rethrown rather than collected\n * because a variant that cannot read its configuration has nothing to build.\n *\n * @example\n * ```ts\n * const variant = new VariantService('esm', events$, { watch: true });\n * variant.name; // 'esm'\n * ```\n *\n * @since 3.0.0\n */\n\n constructor(readonly name: string, private events$: Subject<LifecycleEventsType>, private argv: Record<string, unknown> = {}) {\n VariantService.instances.set(name, this);\n this.configUnsubscribe = inject(ConfigurationService).select(config => ({\n common: config.common,\n variant: config.variants?.[this.name]\n })).subscribe(this.handleConfigChange.bind(this), error => {\n throw error;\n });\n }\n\n /**\n * Reports whether a variant is already registered under a name.\n *\n * @param name - Name to look for\n * @returns `true` when a live variant holds that name\n *\n * @remarks\n * What keeps a second variant from being constructed for a name that already has one,\n * so re-reading a configuration adds the entries it gained without disturbing the ones it kept.\n *\n * @example\n * ```ts\n * VariantService.has('esm'); // true\n * VariantService.has('umd'); // false - never constructed, or disposed since\n * ```\n *\n * @since 3.0.0\n */\n\n static has(name: string): boolean {\n return VariantService.instances.has(name);\n }\n\n /**\n * Returns every variant currently registered.\n *\n * @returns An iterator over the live variants, in the order they were constructed\n *\n * @remarks\n * Walks the registry itself rather than a copy of it,\n * so a variant that disposes of itself part way through a walk is not visited afterward.\n *\n * @example\n * ```ts\n * for (const variant of VariantService.get()) variant.name; // 'esm', then 'cjs'\n * ```\n *\n * @since 3.0.0\n */\n\n static get(): MapIterator<VariantService> {\n return VariantService.instances.values();\n }\n\n /**\n * Type-checks the variant's sources without building them.\n *\n * @returns The diagnostics as build messages, filed under the level each was reported at\n *\n * @remarks\n * A dependency scan of the variant's entry points settles which files the check covers,\n * so it reports against what this variant builds rather than against every file the project holds.\n * The scan runs with the plugins stripped, which keeps it out of the variant's own hooks.\n * The diagnostics come back as messages rather than in the compiler's own shape,\n * so the override table a build reads decides the level each one is filed under.\n * An error stays an error whatever `types.failOnError` says, since nothing is being emitted for it to stop.\n * Nothing is built here, so the messages belong to no result and a run wanting them on one build instead.\n *\n * @example\n * ```ts\n * const logs = await variant.check();\n * logs.error.length; // 2\n * logs.warning.length; // 0\n * ```\n *\n * @see LifecycleLogsType\n * @since 3.0.0\n */\n\n async check(): Promise<LifecycleLogsType> {\n const { metafile } = await analyzeDependencies({ ...this.buildConfig.esbuild, plugins: undefined });\n\n const logs: LifecycleLogsType = { info: [], verbose: [], error: [], warning: [] };\n this.diagnostics(this.typescriptModule.check(new Set(Object.keys(metafile.inputs))), logs);\n\n return logs;\n }\n\n /**\n * Runs one build of this variant.\n *\n * @returns The finished build, carrying every message the run reported at every level\n * @throws xBuildError - When the variant has already been disposed\n *\n * @remarks\n * esbuild runs at `silent` with no log limit, so every message reaches the result through the plugin\n * instead of the console, and nothing is dropped for being the hundredth of its kind.\n * A build that fails resolves to an empty esbuild result rather than rejecting,\n * since what went wrong is already in the logs the plugin collected.\n *\n * @example\n * ```ts\n * const result = await variant.build();\n * result.errors.length; // 0\n * result.warnings.length; // 2\n * ```\n *\n * @see BuildResultInterface\n * @since 3.0.0\n */\n\n async build(): Promise<BuildResultInterface> {\n if (this.isDisposed) throw new xBuildError(`Variant ${ this.name } is disposed`);\n\n const logs: LifecycleLogsType = { info: [], verbose: [], error: [], warning: [] };\n const result = await buildFiles({\n ...this.buildConfig.esbuild,\n plugins: [ this.lifecycle(logs) ],\n logLimit: 0,\n logLevel: 'silent'\n }).catch(() => <BuildResult> {});\n\n return this.toResult(result, logs);\n }\n\n /**\n * Tears the variant down and frees its name.\n *\n * @remarks\n * Ends the configuration subscription, disposes the TypeScript module, and drops the variant from the registry,\n * so the name is free for a later configuration to claim.\n * The instance stays marked as disposed, which is what makes a later build report rather than run.\n *\n * @example\n * ```ts\n * variant.dispose();\n * VariantService.has('esm'); // false\n * await variant.build(); // throws - the variant is disposed\n * ```\n *\n * @since 3.0.0\n */\n\n dispose(): void {\n this.isDisposed = true;\n this.configUnsubscribe?.();\n this.typescriptModule?.dispose?.();\n VariantService.instances.delete(this.name);\n }\n\n /**\n * Disposes the variant at the end of a `using` block.\n *\n * @remarks\n * Defers to {@link VariantService.dispose}, so a variant held by a `using` declaration is torn down\n * when the block ends rather than waiting for a caller to remember.\n *\n * @example\n * ```ts\n * using variant = new VariantService('esm', events$);\n * await variant.build(); // disposed as the block ends\n * ```\n *\n * @see VariantService.dispose\n * @since 3.0.0\n */\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n /**\n * Files a batch of messages under a level, credited to a plugin.\n *\n * @param logs - Buckets the messages are appended to\n * @param messages - Messages to file, absent where the stage produced none\n * @param level - Level a message takes when no override claims it\n * @param name - Plugin to credit the messages to, left as reported when omitted\n *\n * @remarks\n * An absent or empty batch is skipped, so nothing walks a list with nothing in it.\n * The variant's own override table is what decides each message's level,\n * which is how a configuration re-levels or silences one without the stage knowing.\n *\n * @since 3.0.0\n */\n\n private collect(logs: LifecycleLogsType, messages: Array<PartialMessage> | undefined, level: LogLevelType, name?: string): void {\n if (messages?.length) collectLogs(logs, this.buildConfig.logOverride!, messages, level, name);\n }\n\n /**\n * Records a thrown value as an error on the build.\n *\n * @param logs - Buckets the error is appended to\n * @param error - Value that was thrown, of any shape\n * @param name - Plugin to credit the error to, the variant itself by default\n *\n * @remarks\n * A value that is not an `Error` is wrapped in one first, so the message carries a text either way.\n * The error goes straight to the bucket rather than through the override table,\n * since a failure a stage could not handle is not something a configuration silences.\n *\n * @since 3.0.0\n */\n\n private fail(logs: LifecycleLogsType, error: unknown, name: string = this.name): void {\n logs.error.push(errorToMessage(error instanceof Error ? error : new Error(String(error)), '', name));\n }\n\n /**\n * Widens an esbuild result with the levels esbuild does not report on one.\n *\n * @param result - Result esbuild returned, empty when the build threw\n * @param logs - Messages the run collected, at every level\n * @returns The same result, carrying the quieter levels beside the two esbuild reports\n *\n * @remarks\n * Assigns onto the result rather than copying it, so the returned object is the one esbuild produced.\n * The error and warning buckets replace esbuild's own instead of joining them,\n * because the logs already hold those messages along with whatever the hooks added.\n *\n * @see BuildResultInterface\n * @since 3.0.0\n */\n\n private toResult(result: BuildResult, logs: LifecycleLogsType): BuildResultInterface {\n return Object.assign(<BuildResultType> result, {\n info: logs.info,\n errors: logs.error,\n verbose: logs.verbose,\n warnings: logs.warning\n }) as BuildResultInterface;\n }\n\n /**\n * Runs one call against every hook in order and collects what each reports.\n *\n * @typeParam T - Result the call produces for a hook that answers\n *\n * @param logs - Buckets each hook's messages are filed under\n * @param call - Invocation to run against a hook, returning its result or nothing\n * @param handle - Decides whether a result ends the walk, never ending it by default\n * @returns The result that ended the walk, or `undefined` when no result ended it\n *\n * @remarks\n * Each hook's errors and warnings are filed under that hook's own name,\n * so a message reads as the plugin that raised it rather than as the variant.\n * A hook that throws is recorded against its name, and the walk carries on,\n * which keeps one broken plugin from taking the rest of the stage with it.\n * A hook returning nothing is passed over without its result being inspected.\n *\n * @see LifecyclePluginInterface\n * @since 3.0.0\n */\n\n private async dispatch<T>(logs: LifecycleLogsType, call: CallType, handle: HandleType<T> = () => false): Promise<T | undefined> {\n for (const hook of this.hooks) {\n try {\n const result = <T & OnStartResult | undefined> await call(hook);\n if (!result) continue;\n\n this.collect(logs, result.errors, 'error', hook.name);\n this.collect(logs, result.warnings, 'warning', hook.name);\n if (handle(result)) return result;\n } catch (error) {\n this.fail(logs, error, hook.name);\n }\n }\n }\n\n /**\n * Emits the declaration files for this build.\n *\n * @param context - Context of the build being emitted for, read for its resolved options\n *\n * @remarks\n * Written to the directory `declaration` names, falling back to the build's own `outdir` when it names none.\n * A bundled build emits through `emitBundle` so each entry point becomes one declaration,\n * while an unbundled one emits file by file.\n *\n * @see DeclarationOptionsInterface\n * @since 3.0.0\n */\n\n private async declarations(context: LifecycleContextInterface): Promise<void> {\n const { declaration } = this.buildConfig;\n const entryPoints = <Record<string, string>> context.options.entryPoints;\n const outdir = (typeof declaration === 'object' ? declaration.outDir : undefined) ?? context.options.outdir;\n\n if (context.options.bundle) await this.typescriptModule.emitBundle(entryPoints, outdir);\n else await this.typescriptModule.emit(entryPoints, outdir);\n }\n\n /**\n * Re-reads the variant's settings whenever the configuration changes.\n *\n * @param change - The common block and this variant's entry, as the configuration now stands\n *\n * @remarks\n * A change carrying no entry for this variant means the configuration dropped it,\n * so the variant disposes of itself instead of rebuilding its settings.\n * The common block is merged under the variant, entry points are resolved,\n * and the TypeScript module is swapped before the one it replaces is disposed of,\n * so a failure part-way through does not leave the variant without a module.\n * The hook list is rebuilt with the declared plugins ahead of the variant's own `lifecycle` set.\n *\n * @see VariantSubscriptionInterface\n * @since 3.0.0\n */\n\n private handleConfigChange({ common, variant }: VariantSubscriptionInterface): void {\n if (!variant) return this.dispose();\n\n const previous = this.typescriptModule;\n const config = deepMerge(<VariantConfigurationInterface> {}, common ?? {}, variant);\n\n this.typescriptModule = inject(Typescript, config.esbuild.tsconfig);\n config.esbuild.entryPoints = extractEntryPoints(config.esbuild.entryPoints);\n config.logOverride ??= {};\n previous?.dispose();\n\n this.buildConfig = config;\n this.hooks = [ ...config.plugins ?? [], { name: this.name, ...config.lifecycle }];\n }\n\n /**\n * Writes one text block into the esbuild options.\n *\n * @param options - Options the block is written onto, modified in place\n * @param type - Block to write, one of `banner`, `footer`, or `define`\n *\n * @remarks\n * A value written as a function is called with the variant's name and the arguments the build was started with,\n * so an injected value can carry something the configuration file cannot know.\n * A value resolving to `null` or `undefined` is left out rather than written as text,\n * which is how a definition can decline to apply to a given variant.\n *\n * @see TextBlocks\n * @since 3.0.0\n */\n\n private injectTextBlock(options: BuildOptions, type: 'banner' | 'footer' | 'define'): void {\n const source = this.buildConfig[type];\n if (!source) return;\n\n const target = options[type] ??= {};\n for (const [ key, value ] of Object.entries(source)) {\n const content = typeof value === 'function' ? value(this.name, this.argv) : value;\n if (content !== undefined && content !== null) target[key] = stringify(content);\n }\n }\n\n /**\n * Files a batch of TypeScript diagnostics as messages.\n *\n * @param diagnostics - Diagnostics to file, as the TypeScript module reported them\n * @param logs - Buckets the messages are filed under\n * @param failOnError - Whether an error keeps its level, filed as a warning instead when `false`\n *\n * @remarks\n * Each diagnostic carries its code as `TS<code>`, so an override claims one by that id,\n * spelled the way the compiler itself spells it rather than in a shape of this package's own.\n * The code, category, and text also travel whole on the message's `detail`,\n * so a reporter reads the diagnostic itself rather than parsing it back out of the message text.\n * The level comes from the diagnostic's category, and a category the table does not reach is filed as `verbose`.\n * A build passes `types.failOnError` in, while a check leaves it alone,\n * since nothing is being emitted there for an error to stop.\n * Nothing here runs the check, so which files it covered is the caller's to decide.\n *\n * @see DiagnosticLevels\n * @see DiagnosticInterface\n * @see TypeCheckOptionsInterface\n *\n * @since 3.0.0\n */\n\n private diagnostics(diagnostics: Array<DiagnosticInterface>, logs: LifecycleLogsType, failOnError: boolean = true): void {\n for (const { category, code, message: text, file, line, column } of diagnostics) {\n const message: PartialMessage = { text };\n if (code !== undefined) message.id = `TS${ code }`;\n if (file) message.location = { file, line, column };\n\n const level = <LogLevelType> (DiagnosticLevels[category] ?? 'verbose');\n message.detail = { code, category, message: text };\n\n this.collect(logs, [ message ], level === 'error' && !failOnError ? 'warning' : level, 'typescript');\n }\n }\n\n /**\n * Runs the start stage of a build.\n *\n * @param context - Context shared by every hook of this build\n * @param esbuild - The esbuild module driving the build, handed to each start hook\n * @returns The errors collected so far, which is what fails the build when any were\n *\n * @remarks\n * The start hooks run first, and the sources are type-checked only where nothing has failed yet,\n * since diagnostics against a build that already broke report noise rather than a cause.\n * The check covers the files the setup stage recorded on the stage,\n * so a build reports against its own inputs without scanning for them a second time.\n * `types.failOnError` decides whether a type error fails the build or is filed as a warning beside it.\n * The error bucket comes back rather than the hooks' own results,\n * so esbuild stops on anything the stage collected, whichever hook raised it.\n *\n * @see StartContextInterface\n * @since 3.0.0\n */\n\n private async start(context: LifecycleContextInterface, esbuild: PluginBuild['esbuild']): Promise<OnStartResult> {\n const { logs } = context;\n await this.dispatch(logs, hook => hook.onStart?.({ context, esbuild }));\n if (this.buildConfig.types && logs.error.length < 1) {\n const types = this.buildConfig.types;\n const failOnError = typeof types === 'object' ? types.failOnError : true;\n this.diagnostics(this.typescriptModule.check(context.stage.reachableFiles), context.logs, failOnError);\n }\n\n return { errors: logs.error };\n }\n\n /**\n * Resolves one import through the hooks.\n *\n * @param context - Context shared by every hook of this build\n * @param args - The import being resolved, as esbuild described it\n * @returns The first result a hook returned, or the errors collected so far when none claimed the path\n *\n * @remarks\n * The first hook to return anything settles the path, and the rest are not consulted,\n * which is how esbuild itself behaves across plugins.\n * Where no hook claims the import, esbuild is left to resolve it.\n *\n * @see ResolveContextInterface\n * @since 3.0.0\n */\n\n private async resolve(context: LifecycleContextInterface, args: OnResolveArgs): Promise<OnResolveResult | undefined | null> {\n const result = await this.dispatch<OnResolveResult>(\n context.logs, hook => hook.onResolve?.({ context, args }), () => true\n );\n\n return result ?? { errors: context.logs.error };\n }\n\n /**\n * Loads one file and runs it through the hooks.\n *\n * @param context - Context shared by every hook of this build\n * @param args - The file esbuild is loading, as it described it\n * @returns The contents and loader the chain settled on, with the messages left to the variant's own logs\n *\n * @remarks\n * The file is read from the shared model, then rewritten so its imports resolve where the build is unbundled,\n * and its macros are transformed either way.\n * A failure in any of that is recorded, and the file still goes on to the hooks.\n * Each hook is handed what the one before it returned, so the list reads as a chain rather than a race,\n * and every hook is consulted rather than the first that answers.\n * The result carries no messages of its own, since the stage filed them under the variant's levels already.\n *\n * @see LoadContextInterface\n * @since 3.0.0\n */\n\n private async load(context: LifecycleContextInterface, args: OnLoadArgs): Promise<OnLoadResult | undefined | null> {\n const path = VariantService.filesModel.resolve(args.path);\n\n let loader: Loader = 'default';\n let contents = VariantService.filesModel.touch(path).snapshot?.text ?? '';\n\n try {\n const parsed = parseSync(path, contents, { sourceType: 'module' });\n contents = await transformMacros(parsed, path, contents, context);\n\n if (!context.options.bundle) {\n const parsed = parseSync(path, contents, { sourceType: 'module' });\n contents = resolveSource(parsed, path, contents, this.typescriptModule);\n }\n } catch (error) {\n this.fail(context.logs, error);\n }\n\n let merged: OnLoadResult = {};\n await this.dispatch<OnLoadResult>(context.logs,\n hook => hook.onLoad?.({ context, contents, loader, args }),\n result => {\n merged = { ...merged, ...result };\n loader = result.loader ?? loader;\n\n if (result.contents !== undefined)\n contents = typeof result.contents === 'string' ? result.contents : Buffer.from(result.contents).toString();\n\n return false;\n }\n );\n\n return { ...merged, contents, loader, errors: [], warnings: [] };\n }\n\n /**\n * Closes a build out and reports it.\n *\n * @param context - Context shared by every hook of this build\n * @param buildResult - The result esbuild produced for the run\n *\n * @remarks\n * Only the messages esbuild raised itself are collected here,\n * since one carrying a plugin name was already filed when its hook returned it.\n * Declarations are emitted only where nothing failed, so a broken build does not leave stale types behind.\n * `onSuccess` runs ahead of `onEnd` and only on a result with no errors,\n * after which the end event is reported whatever the outcome.\n *\n * @see EndContextInterface\n * @since 3.0.0\n */\n\n private async end(context: LifecycleContextInterface, buildResult: BuildResult): Promise<void> {\n this.collect(context.logs, buildResult.errors.filter(message => !message.pluginName), 'error');\n this.collect(context.logs, buildResult.warnings.filter(message => !message.pluginName), 'warning');\n\n const event = {\n context,\n duration: Date.now() - context.stage.startTime.getTime(),\n buildResult: this.toResult(buildResult, context.logs)\n };\n\n if (context.logs.error.length < 1) {\n try {\n if (this.buildConfig.declaration) await this.declarations(context);\n } catch (error) {\n errorToMessage(error as Error, '', this.name);\n }\n }\n\n await this.dispatch(context.logs, async hook => {\n if (event.buildResult.errors.length < 1) await hook.onSuccess?.(event);\n await hook.onEnd?.(event);\n });\n\n this.events$.next({ ...event, type: 'end' });\n }\n\n /**\n * Prepares the build's options before esbuild reads them.\n *\n * @param context - Context shared by every hook of this build\n * @param build - The esbuild plugin build whose initial options are being shaped\n *\n * @remarks\n * Injects the text blocks, records the files the build reaches on the stage,\n * and replaces the entry points with the dependency map where the build is unbundled.\n * The macro scan reads that same set,\n * so the bindings the run is to drop come from every input the build reaches rather than from the entry points.\n * A failure anywhere in that is recorded against the variant rather than thrown,\n * so a scan that cannot run reports itself and leaves the build to fail on the errors it filed.\n * The setup hooks run last, so a plugin changing an option overrides what this stage settled.\n *\n * @see analyzeMacros\n * @since 3.0.0\n */\n\n private async setup(context: LifecycleContextInterface, build: PluginBuild): Promise<void> {\n const options = build.initialOptions;\n\n try {\n for (const block of TextBlocks) this.injectTextBlock(options, block);\n\n const files = await this.buildDependencyMap();\n context.stage.reachableFiles = new Set(Object.values(files));\n if (!options.bundle) options.entryPoints = files;\n context.stage.dropped = analyzeMacros(context.stage.reachableFiles, options.define ?? {});\n } catch (error) {\n if(isEsbuildError(error) && error.errors) {\n context.logs.error.push(...error.errors);\n } else {\n this.fail(context.logs, error, '');\n }\n }\n\n await this.dispatch(context.logs, hook => hook.onSetup?.(context));\n }\n\n /**\n * Maps every input the build reaches to the output name it takes.\n *\n * @returns The inputs, keyed by their path below the root directory with the extension dropped\n *\n * @remarks\n * The scan runs with the plugins stripped, so it does not re-enter this variant's own hooks\n * and cannot recurse into the build it is preparing.\n * Each path is made relative to the root directory and loses its extension,\n * which is what gives an unbundled build one output per input rather than one bundle.\n *\n * @since 3.0.0\n */\n\n private async buildDependencyMap(): Promise<Record<string, string>> {\n const rootDir = this.typescriptModule.config.options.rootDir!;\n const { metafile } = await analyzeDependencies({ ...this.buildConfig.esbuild, plugins: undefined });\n\n return Object.fromEntries(Object.keys(metafile.inputs).map(file => {\n const path = relative(rootDir, VariantService.filesModel.resolve(file));\n const dot = path.lastIndexOf('.');\n\n return [ dot > 0 ? path.slice(0, dot) : path, file ];\n }));\n }\n\n /**\n * Builds the esbuild plugin this variant runs as.\n *\n * @param logs - Buckets every stage of the run files its messages under\n * @returns The plugin, named after the variant\n *\n * @remarks\n * The context is created once per build and handed to every stage,\n * which is what makes `stage` a place one hook leaves a value for a later one.\n * Its two sets start empty, and setup fills them before the first hook reads one.\n * The four esbuild callbacks are registered before setup runs,\n * so a hook changing an option during setup is still ahead of the first file being read.\n * The plugin carries the variant's name, so message esbuild attributes to it read as the variant.\n *\n * @see LifecycleContextInterface\n * @since 3.0.0\n */\n\n private lifecycle(logs: LifecycleLogsType): Plugin {\n return {\n name: this.name,\n setup: async (build: PluginBuild): Promise<void> => {\n const context: LifecycleContextInterface = {\n logs,\n argv: this.argv,\n options: build.initialOptions,\n overrides: this.buildConfig.logOverride!,\n variantName: this.name,\n stage: {\n startTime: new Date(),\n dropped: new Set<string>(),\n reachableFiles: new Set<string>()\n }\n };\n\n build.onEnd(this.end.bind(this, context));\n build.onStart(this.start.bind(this, context, build.esbuild));\n build.onLoad({ filter: /.*/ }, this.load.bind(this, context));\n build.onResolve({ filter: /.*/ }, this.resolve.bind(this, context));\n await this.setup(context, build);\n\n this.events$.next({ context, esbuild: build.esbuild, type: 'start' });\n }\n };\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { Message, PartialMessage } from 'esbuild';\nimport type { LifecycleLogsType } from '@interfaces/lifecycle.interface';\nimport type { LogLevelType, LogOverridesType } from '@providers/interfaces/log-provider.interface';\n\n/**\n * Resolves the level a message is reported under.\n *\n * @param overrides - The configured levels, keyed by message id or by a pattern matching one\n * @param id - ID the message was reported with, absent on a message that carries none\n * @param level - Level the message takes when no override claims it\n * @returns The level the message is reported under\n *\n * @remarks\n * An id is looked up as a key first and read against the pattern keys only when that misses,\n * so a table naming its ids outright is answered without a match being run at all.\n * A pattern is anchored with `^(?:...)$` to make it match a whole id rather than a part of one,\n * which is what lets a set of ids be written as a single alternation, and the first the table declared wins.\n * A key whose syntax does not parse is passed over rather than thrown on.\n *\n * @example\n * ```ts\n * const overrides: LogOverridesType = { 'direct-eval': 'silent', 'TS-2\\\\d{3}': 'warning' };\n *\n * resolveLevel(overrides, 'direct-eval', 'warning'); // 'silent' - claimed by name\n * resolveLevel(overrides, 'TS-2304', 'error'); // 'warning' - claimed by pattern\n * resolveLevel(overrides, 'empty-glob', 'warning'); // 'warning' - claimed by neither\n * ```\n *\n * @see collectLog\n * @see LogOverridesType\n *\n * @since 3.0.0\n */\n\nexport function resolveLevel(overrides: LogOverridesType, id: string | undefined, level: LogLevelType): LogLevelType {\n if (id === undefined) return level;\n if (Object.hasOwn(overrides, id)) return overrides[id];\n\n for (const key in overrides) {\n try {\n if (new RegExp(`^(?:${ key })$`).test(id)) return overrides[key];\n } catch {\n if(id === key) return overrides[key];\n }\n }\n\n return level;\n}\n\n/**\n * Files a message under the level it resolves to.\n *\n * @param logs - Buckets the message is appended to, keyed by level\n * @param overrides - The configured levels, consulted for the message id\n * @param message - Message to file\n * @param level - Level the message takes when no override claims it\n *\n * @remarks\n * A message that resolves to `silent` is dropped rather than filed,\n * which is what keeps the log record free of a bucket for it.\n *\n * @example\n * ```ts\n * const logs = { debug: [], info: [], warning: [], error: [] };\n *\n * collectLog(logs, { 'direct-eval': 'silent' }, { id: 'direct-eval', text: 'Using eval' }, 'warning');\n * logs.warning; // [] - the override silenced it\n * ```\n *\n * @see collectLogs\n * @see resolveLevel\n *\n * @since 3.0.0\n */\n\nexport function collectLog(\n logs: LifecycleLogsType, overrides: LogOverridesType, message: PartialMessage, level: LogLevelType\n): void {\n const resolved = resolveLevel(overrides, message.id, level);\n if (resolved !== 'silent') logs[resolved].push(<Message> message);\n}\n\n/**\n * Files a batch of messages, each under the level it resolves to.\n *\n * @param logs - Buckets the messages are appended to, keyed by level\n * @param overrides - The configured levels, consulted for each message id\n * @param messages - Messages to file, in the order they were reported\n * @param level - Level a message takes when no override claims it\n * @param name - Plugin to credit each message to, left as reported when omitted or empty\n *\n * @remarks\n * Every message is resolved on its own, so one batch can end up spread across several buckets.\n * A name replaces whatever `pluginName` a message already carried,\n * so a batch coming out of one plugin reads as that plugin's even where esbuild credited another.\n * It writes onto the messages themselves rather than onto copies,\n * so a caller holding the same objects sees the credit as well.\n * The credit lands before the level resolves, so a message an override silences still carries it.\n *\n * @example\n * ```ts\n * const logs = { debug: [], info: [], warning: [], error: [] };\n *\n * collectLogs(logs, {}, [ { text: 'first' } ], 'error');\n * logs.error; // [ { text: 'first' } ] - left uncredited\n *\n * collectLogs(logs, {}, [ { text: 'second' } ], 'error', 'timing');\n * logs.error; // [ { text: 'first' }, { text: 'second', pluginName: 'timing' } ]\n * ```\n *\n * @see collectLog\n * @since 3.0.0\n */\n\nexport function collectLogs(\n logs: LifecycleLogsType, overrides: LogOverridesType, messages: Array<PartialMessage>, level: LogLevelType, name?: string\n): void {\n for (const message of messages) {\n if(name) message.pluginName = name;\n collectLog(logs, overrides, message, level);\n }\n}\n","/**\n * Imports\n */\n\nimport { parseSync } from 'oxc-parser';\nimport { inject } from '@remotex-labs/xinject';\nimport { FilesModel } from '@models/files.model';\nimport { isDefined } from '@directives/define.directive';\nimport { Macros, MacroScanHint } from '@constants/macros.constant';\n\n/**\n * Collects the names of the macro declarations a build is to drop.\n *\n * @param files - Paths to scan, relative or absolute\n * @param defines - The definition table the build substitutes, holding the source text each flag stands for\n * @returns The names bound to a conditional macro whose condition does not hold\n *\n * @remarks\n * Each file is read through {@link FilesModel}, so a path already tracked is served from the cache rather than\n * from the disk, and a path that is missing is skipped.\n * A file is parsed only once it contains {@link MacroScanHint}, which spares the parse where no conditional\n * macro can be.\n *\n * - **What is looked at** - an exported top-level binding alone, `export const NAME = $$ifdef('FLAG')` or its\n * `$$ifndef` counterpart. A macro nested in a block, or bound without an export, is not seen.\n * - **What counts as defined** - a definition holds source text rather than a value, so the text is what decides.\n * Anything in {@link MacroFalsyDefines} leaves the flag unset, as does a flag that the table does not name.\n * Every other text sets the flag, `'0'` and the empty string among them.\n * - **What ends up in the set** - an `$$ifdef` name whose flag is absent, and an `$$ifndef` name whose flag is\n * present. {@link Macros.inline} is not read here.\n *\n * @example\n * ```ts\n * // src/feature.ts\n * export const $$dev = $$ifdef('DEV');\n * export const $$release = $$ifndef('DEV');\n *\n * analyzeMacros([ 'src/feature.ts' ], { DEV: 'true' }); // Set { '$$release' }\n * analyzeMacros([ 'src/feature.ts' ], { DEV: 'false' }); // Set { '$$dev' }\n * ```\n *\n * @see Macros\n * @see isDefined\n * @see MacroScanHint\n *\n * @since 3.0.0\n */\n\nexport function analyzeMacros(files: Iterable<string>, defines: Record<string, string>): Set<string> {\n const dropped = new Set<string>();\n const filesModel = inject(FilesModel);\n\n for (const file of files) {\n const content = filesModel.touch(file).snapshot?.text;\n\n if (!content?.includes(MacroScanHint)) continue;\n const { program } = parseSync(file, content, { sourceType: 'module' });\n\n for (const node of program.body) {\n if (node.type !== 'ExportNamedDeclaration') continue;\n if (node.declaration?.type !== 'VariableDeclaration') continue;\n\n for (const declarator of node.declaration.declarations) {\n const call = declarator.init;\n if (call?.type !== 'CallExpression' || call.callee.type !== 'Identifier') continue;\n\n const directive = call.callee.name;\n if (directive !== Macros.ifdef && directive !== Macros.ifndef) continue;\n\n const arg = call.arguments[0];\n if (arg?.type !== 'Literal' || typeof arg.value !== 'string') continue;\n if (declarator.id.type !== 'Identifier') continue;\n\n if ((directive === Macros.ifdef) !== isDefined(defines, arg.value)) {\n dropped.add(declarator.id.name);\n }\n }\n }\n }\n\n return dropped;\n}\n","/**\n * The prefix every macro name is expected to open with.\n *\n * @remarks\n * Keeps a macro apart from an ordinary binding and doubles as the cheapest test that a source holds one at all,\n * since a file without it carries nothing to expand.\n * A declared macro named without it still expands and draws a `macro-prefix` warning.\n *\n * @example\n * ```ts\n * '$$ifdef'.startsWith(MacroPrefix); // true\n * ```\n *\n * @see Macros\n * @see MacroScanHint\n *\n * @since 3.0.0\n */\n\nexport const MacroPrefix = '$$';\n\n/**\n * The prefix the two conditional macros share.\n *\n * @remarks\n * What `$$ifdef` and `$$ifndef` both open with, so a source without it declares neither of them,\n * and the walk looking for one is skipped.\n * {@link Macros.inline} does not carry it and is reached through {@link MacroPrefix} instead.\n *\n * @example\n * ```ts\n * MacroScanHint; // '$$if'\n * 'const $$dev = $$ifdef(\"DEV\", 1);'.includes(MacroScanHint); // true\n * ```\n *\n * @see Macros\n * @see MacroPrefix\n *\n * @since 3.0.0\n */\n\nexport const MacroScanHint = `${ MacroPrefix }if`;\n\n/**\n * The three names that mark a call as a macro.\n *\n * @remarks\n * The callee of the call names the macro, and the shape of the call has to match the name:\n * the two conditional macros take a flag as a string literal and the value that flag guards,\n * while `inline` takes the value alone.\n * A call that matches neither shape is left as it stands rather than reported.\n *\n * @example\n * ```ts\n * export const $$dev = $$ifdef('DEV', () => console.log('dev')); // kept while DEV is set\n * export const $$prod = $$ifndef('DEV', () => 0); // kept while DEV is not set\n * export const $$stamp = $$inline(() => 2 + 2); // becomes 4 in the output\n * ```\n *\n * @see MacroPrefix\n * @see transformMacros\n *\n * @since 3.0.0\n */\n\nexport const enum Macros {\n /**\n * Keeps its value while the flag is set.\n *\n * @remarks\n * The flag is read from the definition table, and the declaration is dropped when the flag is not set,\n * along with every reference to the name that it bound.\n *\n * @example\n * ```ts\n * export const $$dev = $$ifdef('DEV', () => log()); // dropped while DEV is 'false'\n * ```\n *\n * @since 3.0.0\n */\n\n ifdef = `${ MacroPrefix }ifdef`,\n\n /**\n * Keeps its value while the flag is not set.\n *\n * @remarks\n * The counterpart of `ifdef`, reading the same definitions and dropped on the opposite answer,\n * which is what a fallback for an absent flag is written as.\n *\n * @example\n * ```ts\n * export const $$prod = $$ifndef('DEV', () => 0); // dropped while DEV is set\n * ```\n *\n * @since 3.0.0\n */\n\n ifndef = `${ MacroPrefix }ifndef`,\n\n /**\n * Replaces the call with what its value evaluates to.\n *\n * @remarks\n * Evaluated while the build runs, so the output carries the result rather than the call.\n * A failure is reported as a `macro-inline` error and leaves `undefined` behind.\n *\n * @example\n * ```ts\n * export const $$stamp = $$inline(() => 2 + 2); // export const $$stamp = 4;\n * ```\n *\n * @since 3.0.0\n */\n\n inline = `${ MacroPrefix }inline`\n}\n\n/**\n * The definition values that leave a flag unset.\n *\n * @remarks\n * A definition holds source text rather than a value, so `false` reaches the build as the string `'false'`.\n * These three leave the flag unset, and every other text sets it, `'0'` and the empty string among them.\n * A flag that the definition table does not name is not set either, which {@link isDefined} tests on its own.\n * The text is trimmed before the lookup.\n *\n * @example\n * ```ts\n * MacroFalsyDefines.has('false'); // true\n * MacroFalsyDefines.has('0'); // false - '0' sets the flag\n * ```\n *\n * @see Macros\n * @see isDefined\n *\n * @since 3.0.0\n */\n\nexport const MacroFalsyDefines = new Set([ 'false', 'null', 'undefined' ]);\n\n/**\n * The parent properties under which an identifier names something rather than reads it.\n *\n * @remarks\n * A dropped macro's identifier becomes `undefined` wherever it is read, and is left alone where it is only a name -\n * the `id` of a declaration, a label, an import or export binding, or a parameter.\n * An object key and a member property are decided by the parent's `computed` flag instead of by this set.\n *\n * @example\n * ```ts\n * MacroNameKeys.has('id'); // true - `const $$dev = ...` keeps the name it declares\n * MacroNameKeys.has('object'); // false - `$$dev.run()` has the reference replaced\n * ```\n *\n * @see transformMacros\n * @since 3.0.0\n */\n\nexport const MacroNameKeys = new Set([ 'id', 'label', 'local', 'params', 'exported', 'imported' ]);\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { MacroTargetInterface } from '@directives/interfaces/macros-directive.interface';\n\n/**\n * Imports\n */\n\nimport { MacroFalsyDefines } from '@constants/macros.constant';\n\n/**\n * Whether the definition table sets a flag.\n *\n * @param defines - The definition table the build substitutes, holding the source text each flag stands for\n * @param name - Name of the flag to test\n * @returns `true` when the table names the flag and holds something other than a falsy text for it\n *\n * @remarks\n * A definition holds source text rather than a value, so the text is what decides.\n * A flag that the table does not name is not set, and neither is one whose text is in {@link MacroFalsyDefines}.\n * The text is trimmed before the lookup, so padding around it does not change the answer.\n * Every other text sets the flag, `'0'` and the empty string among them.\n *\n * @example\n * ```ts\n * isDefined({ DEV: 'true' }, 'DEV'); // true\n * isDefined({ DEV: ' false ' }, 'DEV'); // false - trimmed before the lookup\n * isDefined({}, 'DEV'); // false - the table does not name it\n * ```\n *\n * @see MacroFalsyDefines\n * @since 3.0.0\n */\n\nexport function isDefined(defines: Record<string, string>, name: string): boolean {\n const value = defines[name];\n\n return value !== undefined && !MacroFalsyDefines.has(value.trim());\n}\n\n/**\n * Builds the replacement source for a declaration that a macro initializes.\n *\n * @param code - Source text the target's spans point into\n * @param name - Name the declaration binds\n * @param target - The macro call and whatever call text followed it\n * @param prefix - Text placed in front of the result, `'export '` for an exported declaration\n * @returns The source that replaces the whole declaration\n *\n * @remarks\n * The value the macro guards is its second argument, and the way that argument is written decides the form:\n *\n * - **A function the source already invokes** - parenthesized and left invoked, so the binding holds the result.\n * - **A function the source does not invoke** - rewritten as a function declaration under the same name, carrying\n * its parameters, its return type, and its `async` keyword. An expression body becomes a `return` statement, and\n * a function without a body becomes an empty one.\n * - **Anything else** - substituted as written, with the trailing call kept.\n *\n * @example\n * ```ts\n * // source: export const $$log = $$ifdef('DEV', (m: string) => console.log(m));\n * defineDeclaration(code, '$$log', target, 'export ');\n * // result: export function $$log(m: string) { return console.log(m); }\n *\n * // source: const $$now = $$ifdef('DEV', () => Date.now())();\n * defineDeclaration(code, '$$now', target, '');\n * // result: const $$now = (() => Date.now())();\n * ```\n *\n * @see defineExpression\n * @see MacroTargetInterface\n *\n * @since 3.0.0\n */\n\nexport function defineDeclaration(code: string, name: string, target: MacroTargetInterface, prefix: string): string {\n const { call, suffix } = target;\n const callback = call.arguments[1];\n const text = code.slice(callback.start, callback.end);\n\n if (callback.type !== 'ArrowFunctionExpression' && callback.type !== 'FunctionExpression')\n return `${ prefix }const ${ name } = ${ text }${ suffix };`;\n\n if (suffix) return `${ prefix }const ${ name } = (${ text })${ suffix };`;\n\n const { body } = callback;\n const params = callback.params.map(param => code.slice(param.start, param.end)).join(', ');\n const returns = callback.returnType ? code.slice(callback.returnType.start, callback.returnType.end) : '';\n const head = `${ prefix }${ callback.async ? 'async ' : '' }function ${ name }(${ params })${ returns }`;\n\n if (!body) return `${ head } {}`;\n if (body.type === 'BlockStatement') return `${ head } ${ code.slice(body.start, body.end) }`;\n\n return `${ head } { return ${ code.slice(body.start, body.end) }; }`;\n}\n\n/**\n * Builds the replacement source for a macro standing in an expression.\n *\n * @param code - Source text the target's spans point into\n * @param target - The macro call and whatever call text followed it\n * @param statement - Whether the macro stands as a statement of its own\n * @returns The source that replaces the macro call\n *\n * @remarks\n * The value the macro guards is its second argument, and the way that argument is written decides the form:\n *\n * - **A function inside an expression** - parenthesized and invoked, so the expression evaluates to what the\n * function returns. The call the source wrote is used where there is one, and `()` where there is not.\n * - **A function standing as a statement** - its body is inlined where the call stood, with no wrapper around it.\n * An expression body becomes that expression, and a function without a body leaves nothing behind.\n * - **Anything else** - substituted as written, with the trailing call kept.\n *\n * @example\n * ```ts\n * // source: $$ifdef('DEV', () => console.log('on'));\n * defineExpression(code, target, true);\n * // result: console.log('on');\n *\n * // source: const x = $$ifdef('DEV', () => 1);\n * defineExpression(code, target, false);\n * // result: (() => 1)()\n * ```\n *\n * @see defineDeclaration\n * @since 3.0.0\n */\n\nexport function defineExpression(code: string, target: MacroTargetInterface, statement: boolean): string {\n const { call, suffix } = target;\n const callback = call.arguments[1];\n const text = code.slice(callback.start, callback.end);\n const tail = statement ? ';' : '';\n\n if (callback.type !== 'ArrowFunctionExpression' && callback.type !== 'FunctionExpression')\n return `${ text }${ suffix }${ tail }`;\n\n if (suffix || !statement) return `(${ text })${ suffix || '()' }${ tail }`;\n\n const { body } = callback;\n if (!body) return '';\n if (body.type !== 'BlockStatement') return `${ code.slice(body.start, body.end) };`;\n\n return code.slice(body.start + 1, body.end - 1).trim();\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { PartialMessage } from 'esbuild';\nimport type { ParseResult } from 'oxc-parser';\nimport type { LifecycleContextInterface } from '@interfaces/lifecycle.interface';\nimport type { LogLevelType } from '@providers/interfaces/log-provider.interface';\nimport type { NodeVisitorType } from '@directives/interfaces/macros-directive.interface';\nimport type { ExportNamedDeclaration, ImportDeclaration, Node, Span } from '@oxc-project/types';\nimport type { SourceEditInterface } from '@components/interfaces/transformer-component.interface';\nimport type { DeclaredMacroType, MacroCallType } from '@directives/interfaces/macros-directive.interface';\nimport type { MacroStateInterface, MacroTargetInterface } from '@directives/interfaces/macros-directive.interface';\n\n/**\n * Imports\n */\n\nimport { visitorKeys } from 'oxc-parser';\nimport { collectLog } from '@providers/log.provider';\nimport { evaluate } from '@directives/inline.directive';\nimport { applyEdits } from '@components/transformer.component';\nimport { defineDeclaration, defineExpression, isDefined } from '@directives/define.directive';\nimport { MacroNameKeys, MacroPrefix, Macros, MacroScanHint } from '@constants/macros.constant';\n\n/**\n * Whether a value read out of a node is itself a node.\n *\n * @param value - Value read out of a parent node's property\n * @returns `true` when the value is an object carrying a string `type`\n *\n * @remarks\n * The test the walk applies before it steps into a property,\n * since a visitor key can hold a node, an array of them, or a plain value such as a name or a flag.\n *\n * @since 3.0.0\n */\n\nexport function isNode(value: unknown): value is Node {\n return typeof value === 'object' && value !== null && typeof (<Node> value).type === 'string';\n}\n\n/**\n * Visits a node and everything under it, depth-first.\n *\n * @param node - Node the walk starts from\n * @param visit - Called for each node, returning `true` to leave the subtree unvisited\n * @param parent - Node the current one hangs from, `null` at the root\n * @param key - Property of the parent the current node sits under, empty at the root\n *\n * @remarks\n * Child properties come from oxc's `visitorKeys`, so a node type that the table does not name is treated as a leaf.\n * A visitor returning `true` prunes the subtree,\n * so a rule further down never rewrites a node that an earlier one already replaced.\n *\n * @see NodeVisitorType\n * @since 3.0.0\n */\n\nexport function walk(node: Node, visit: NodeVisitorType, parent: Node | null = null, key = ''): void {\n if (visit(node, parent, key)) return;\n\n const keys: Array<string> | undefined = visitorKeys[node.type];\n\n for (const childKey of keys ?? []) {\n const value = (<Record<string, unknown>> <unknown> node)[childKey];\n\n if (Array.isArray(value)) {\n for (const item of value) if (isNode(item)) walk(item, visit, node, childKey);\n } else if (isNode(value)) walk(value, visit, node, childKey);\n }\n}\n\n/**\n * Files a message against a position in the file being transformed.\n *\n * @param state - Transform state, read for the source text and the file name\n * @param offset - Offset in the source the message points at\n * @param level - Level the message is filed under, before any override applies\n * @param message - Message to file, whose `location` this fills in\n *\n * @remarks\n * The line and the column are counted by scanning the source up to the offset,\n * since the parser reports spans rather than positions.\n * The message is filled in where it stands rather than copied, and it reaches the log through {@link collectLog},\n * so the overrides the build declared still decide the level it lands at.\n *\n * @see collectLog\n * @since 3.0.0\n */\n\nexport function report(state: MacroStateInterface, offset: number, level: LogLevelType, message: PartialMessage): void {\n const { code } = state;\n let line = 1;\n let start = 0;\n\n for (let index = code.indexOf('\\n'); index !== -1 && index < offset; index = code.indexOf('\\n', index + 1)) {\n line++;\n start = index + 1;\n }\n\n message.location = { file: state.target, line, column: offset - start };\n collectLog(state.logs, state.overrides, message, level);\n}\n\n/**\n * Queues an edit that replaces a span with text.\n *\n * @param state - Transform state the edit is collected on\n * @param span - Span of the source the edit replaces\n * @param text - Replacement text, empty to delete the span\n * @returns `true`, so a caller can hand it straight back to the walk\n *\n * @remarks\n * Returning `true` is what tells the walk that this node is dealt with and that it should not descend into it.\n * The edit is applied later along with the rest, so the offsets it carries stay valid for the whole walk.\n *\n * @see applyEdits\n * @since 3.0.0\n */\n\nexport function record(state: MacroStateInterface, span: Span, text: string): boolean {\n state.edits.push({ start: span.start, end: span.end, text });\n\n return true;\n}\n\n/**\n * Queues an edit whose text is known only once an inline call has run.\n *\n * @param state - Transform state the edit and the promise are collected on\n * @param span - Span of the source the edit replaces\n * @param call - The `$$inline` call to evaluate\n * @param wrap - Turns the value that comes back into the text that replaces the span\n * @returns `true`, so a caller can hand it straight back to the walk\n *\n * @remarks\n * The edit is queued empty and filled in when the call finishes, so the walk carries on while it runs.\n * The promise is collected on `state.pending` for the caller to await before the edits are applied.\n * A failure fills the edit with `wrap('undefined')` and reports a `macro-inline` error,\n * so a macro that cannot be evaluated still leaves the file parsable.\n *\n * @see evaluate\n * @since 3.0.0\n */\n\nexport function defer(state: MacroStateInterface, span: Span, call: MacroCallType, wrap: (value: string) => string): boolean {\n const edit: SourceEditInterface = { start: span.start, end: span.end, text: '' };\n\n state.edits.push(edit);\n state.pending.push(evaluate(state, call).then(value => {\n edit.text = wrap(value);\n }, (error: unknown) => {\n edit.text = wrap('undefined');\n report(state, call.start, 'error', {\n detail: error,\n id: 'macro-inline',\n text: `${ Macros.inline } failed: ${ (<Error> error)?.message ?? String(error) }`\n });\n }));\n\n return true;\n}\n\n/**\n * Whether a node is a macro call this transform handles.\n *\n * @param value - Node to test\n * @returns `true` when the callee names a macro and the arguments match that name\n *\n * @remarks\n * The callee has to be a plain identifier naming one of {@link Macros}, and the arguments have to match the name:\n * one for `inline`, and two for the conditional pair, the first of which is a string literal naming the flag.\n * Anything else is an ordinary call and is left alone.\n *\n * @see MacroCallType\n * @since 3.0.0\n */\n\nexport function isMacroCall(value: Node): value is MacroCallType {\n if (value.type !== 'CallExpression' || value.callee.type !== 'Identifier') return false;\n\n const { name } = value.callee;\n if (name === Macros.inline) return value.arguments.length === 1;\n if (name !== Macros.ifdef && name !== Macros.ifndef || value.arguments.length !== 2) return false;\n\n const flag = value.arguments[0];\n\n return flag.type === 'Literal' && typeof flag.value === 'string';\n}\n\n/**\n * Whether a conditional macro keeps its value.\n *\n * @param state - Transform state, read for the definition table\n * @param call - The `$$ifdef` or `$$ifndef` call to weigh\n * @returns `true` when the macro's condition holds\n *\n * @remarks\n * `$$ifdef` holds while its flag is set and `$$ifndef` while it is not, which {@link isDefined} answers.\n * A flag that is not a string literal is read as the empty name, which no table sets.\n *\n * @see isDefined\n * @since 3.0.0\n */\n\nexport function isActive(state: MacroStateInterface, call: MacroCallType): boolean {\n const flag = call.arguments[0];\n const name = flag.type === 'Literal' ? String(flag.value) : '';\n\n return (call.callee.name === Macros.ifdef) === isDefined(state.defines, name);\n}\n\n/**\n * Whether a node calls a macro that the build dropped.\n *\n * @param state - Transform state, read for the dropped names\n * @param node - Node to test\n * @returns `true` when the node calls an identifier that the build dropped\n *\n * @remarks\n * How a use of a disabled macro is recognized once its own declaration is gone,\n * which is what lets the transform replace the call rather than leave it to fail while the output runs.\n *\n * @since 3.0.0\n */\n\nexport function isDropped(state: MacroStateInterface, node: Node): boolean {\n return node.type === 'CallExpression' && node.callee.type === 'Identifier' && state.dropped.has(node.callee.name);\n}\n\n/**\n * The macro call a node holds, with whatever call followed it.\n *\n * @param state - Transform state, read for the source text\n * @param node - Node to look in, which may be absent\n * @returns The macro call and its trailing text, or `undefined` where the node holds none\n *\n * @remarks\n * Three shapes reach here.\n * A macro call on its own yields an empty suffix, a call whose callee is the macro yields the text of the outer\n * call as the suffix, and a TypeScript `as` expression is unwrapped and retried.\n *\n * @see MacroTargetInterface\n * @since 3.0.0\n */\n\nexport function macroTarget(state: MacroStateInterface, node?: Node | null): MacroTargetInterface | undefined {\n if (!node) return;\n if (isMacroCall(node)) return { call: node, suffix: '' };\n if (node.type === 'TSAsExpression') return macroTarget(state, node.expression);\n if (node.type !== 'CallExpression' || !isMacroCall(node.callee)) return;\n\n return { call: node.callee, suffix: state.code.slice(node.callee.end, node.end) };\n}\n\n/**\n * The name a declaration binds, together with the macro that initializes it.\n *\n * @param state - Transform state, read for the source text\n * @param node - Declaration to look at, exported or bare\n * @returns The declared name and its macro target, or `undefined` where the node declares no macro\n *\n * @remarks\n * An `export` wrapper is stepped through first, so one test serves the exported form and the bare one alike.\n * A single declarator alone qualifies, which leaves `const a = $$ifdef('DEV', 1), b = 2` untouched.\n *\n * @see DeclaredMacroType\n * @since 3.0.0\n */\n\nexport function declaredMacro(state: MacroStateInterface, node: Node): DeclaredMacroType | undefined {\n const declaration = node.type === 'ExportNamedDeclaration' ? node.declaration : node;\n if (declaration?.type !== 'VariableDeclaration' || declaration.declarations.length !== 1) return;\n\n const { id, init } = declaration.declarations[0];\n if (id.type !== 'Identifier') return;\n\n const target = macroTarget(state, init);\n\n return target && [ id, target ];\n}\n\n/**\n * Rewrites an import that names a dropped macro.\n *\n * @param state - Transform state the edit is collected on\n * @param node - Import declaration to prune\n * @returns `true` when the statement was rewritten\n *\n * @remarks\n * A named specifier bound to a dropped macro is removed, while a default or a namespace import is kept as written.\n * An import left with no specifiers at all becomes a bare `import 'source';`,\n * so a module imported for its side effect still runs.\n *\n * @since 3.0.0\n */\n\nexport function pruneImport(state: MacroStateInterface, node: ImportDeclaration): boolean {\n const named: Array<string> = [];\n const parts: Array<string> = [];\n let dropped = false;\n\n for (const specifier of node.specifiers) {\n const text = state.code.slice(specifier.start, specifier.end);\n\n if (specifier.type !== 'ImportSpecifier') parts.push(text);\n else if (state.dropped.has(specifier.local.name)) dropped = true;\n else named.push(text);\n }\n\n if (!dropped) return false;\n const source = state.code.slice(node.source.start, node.source.end);\n if (named.length > 0) parts.push(`{ ${ named.join(', ') } }`);\n\n if (parts.length < 1) return record(state, node, `import ${ source };`);\n\n return record(state, node, `import ${ parts.join(', ') } from ${ source };`);\n}\n\n/**\n * Rewrites an export list that names a dropped macro.\n *\n * @param state - Transform state the edit is collected on\n * @param node - Export declaration to prune\n * @returns `true` when the statement was rewritten\n *\n * @remarks\n * The specifiers that survive are re-emitted as they were written, and a list left with none is deleted outright.\n * A list that names nothing dropped is reported untouched, so the walk descends into it as usual.\n *\n * @since 3.0.0\n */\n\nexport function pruneExport(state: MacroStateInterface, node: ExportNamedDeclaration): boolean {\n const { specifiers } = node;\n const kept = specifiers.filter(\n ({ local }) => !state.dropped.has(local.type === 'Literal' ? local.value : local.name)\n );\n\n if (kept.length === specifiers.length) return false;\n if (kept.length < 1) return record(state, node, '');\n\n return record(state, node, `export { ${ kept.map(item => state.code.slice(item.start, item.end)).join(', ') } };`);\n}\n\n/**\n * Replaces a declaration whose value comes from a macro.\n *\n * @param state - Transform state the edit is collected on\n * @param node - Declaration to expand, exported or bare\n * @returns `true` when the declaration was rewritten\n *\n * @remarks\n * A name that does not open with {@link MacroPrefix} draws a `macro-prefix` warning and expands either way.\n * An `inline` declaration is deferred until its value has run.\n * A conditional declaration becomes what {@link defineDeclaration} builds while it is active\n * and is deleted where it is not.\n *\n * @since 3.0.0\n */\n\nexport function expandDeclaration(state: MacroStateInterface, node: Node): boolean {\n const declared = declaredMacro(state, node);\n if (!declared) return false;\n\n const [ id, target ] = declared;\n const { call, suffix } = target;\n const prefix = node.type === 'ExportNamedDeclaration' ? 'export ' : '';\n\n if (!id.name.startsWith(MacroPrefix)) report(state, id.start, 'warning', {\n id: 'macro-prefix',\n text: `Macro '${ id.name }' does not start with the '${ MacroPrefix }' prefix to avoid conflicts`\n });\n\n if (call.callee.name === Macros.inline)\n return defer(state, node, call, value => `${ prefix }const ${ id.name } = ${ value }${ suffix };`);\n\n return record(state, node, isActive(state, call) ? defineDeclaration(state.code, id.name, target, prefix) : '');\n}\n\n/**\n * Replaces a macro used as a value.\n *\n * @param state - Transform state the edit is collected on\n * @param node - Node the replacement stands in for\n * @param target - The macro call and whatever call followed it\n * @param statement - Whether the macro stands as a statement of its own\n * @returns `true`, since every call that reaches here rewrites something\n *\n * @remarks\n * An `inline` call is deferred until its value has run.\n * A conditional call becomes what {@link defineExpression} builds while it is active.\n * An inactive one leaves nothing behind as a statement, and `undefined` where a value is expected.\n *\n * @since 3.0.0\n */\n\nexport function expand(state: MacroStateInterface, node: Node, target: MacroTargetInterface, statement: boolean): boolean {\n const { call, suffix } = target;\n\n if (call.callee.name === Macros.inline)\n return defer(state, node, call, value => statement ? '' : `${ value }${ suffix }`);\n\n if (!isActive(state, call)) return record(state, node, statement ? '' : 'undefined');\n\n return record(state, node, defineExpression(state.code, target, statement));\n}\n\n/**\n * Rewrites one node and reports whether the walk should stop there.\n *\n * @param state - Transform state the edits are collected on\n * @param node - Node the walk arrived at\n * @param parent - Node it hangs from, `null` at the root\n * @param key - Property of the parent it sits under\n * @returns `true` when the node was rewritten and the walk should not descend into it\n *\n * @remarks\n * The visitor the rewriting walk runs, dispatching on the type of the node:\n *\n * - **An identifier** - a dropped name becomes `undefined` where it is read, and is left alone where it only names\n * something, which {@link MacroNameKeys} and the parent's `computed` flag decide between.\n * - **An import or an export list** - pruned of the names the build dropped.\n * - **A declaration** - expanded, or pruned where it re-exports rather than declares.\n * - **An expression statement or a call** - expanded, or replaced where it calls something dropped.\n *\n * Any other node is reported untouched, so the walk descends into it.\n *\n * @since 3.0.0\n */\n\nexport function expandNode(state: MacroStateInterface, node: Node, parent: Node | null, key: string): boolean {\n switch (node.type) {\n case 'Identifier': {\n if (!state.dropped.has(node.name) || !parent) return false;\n\n const keyed = key === 'key' || key === 'property';\n const named = keyed ? !('computed' in parent) || !parent.computed : MacroNameKeys.has(key);\n\n return !named && record(state, node, 'undefined');\n }\n\n case 'ImportDeclaration':\n return pruneImport(state, node);\n\n case 'ExportNamedDeclaration':\n if (expandDeclaration(state, node)) return true;\n if (node.source || node.specifiers.length < 1) return false;\n\n return pruneExport(state, node);\n\n case 'VariableDeclaration':\n return expandDeclaration(state, node);\n\n case 'ExpressionStatement': {\n if (isDropped(state, node.expression)) return record(state, node, '');\n const target = macroTarget(state, node.expression);\n\n return target !== undefined && expand(state, node, target, true);\n }\n\n case 'CallExpression':\n case 'TSAsExpression': {\n if (isDropped(state, node)) return record(state, node, 'undefined');\n const target = macroTarget(state, node);\n\n return target !== undefined && expand(state, node, target, false);\n }\n }\n\n return false;\n}\n\n/**\n * Expands every macro in a file and returns the rewritten source.\n *\n * @param parse - The file's parse result, walked rather than parsed again\n * @param target - Absolute path of the file, named in messages and used to resolve an inline value's packages\n * @param content - Source text of the file\n * @param context - Lifecycle context, read for the logs, the flags, and the names the build has dropped\n * @returns The rewritten source, or `content` itself where there was nothing to expand\n *\n * @remarks\n * An empty file comes back untouched, and so does any file under `node_modules`.\n * So does a file that carries no {@link MacroPrefix}, unless an earlier file dropped a name this one may still use.\n * A first walk over a file carrying {@link MacroScanHint} collects the conditional macros that are not active and\n * adds their names to the set the build shares, so dropping a name where it was declared.\n * also drops it where it is imported.\n * The rewriting walk follows, and any deferred `inline` value is awaited before the edits are applied.\n *\n * @example\n * ```ts\n * // source: export const $$dev = $$ifdef('DEV', () => log());\n * await transformMacros(parse, '/src/a.ts', content, context);\n * // result: export function $$dev() { return log(); } - while DEV is set\n * ```\n *\n * @see analyzeMacros\n * @see MacroStateInterface\n *\n * @since 3.0.0\n */\n\nexport async function transformMacros(\n parse: ParseResult, target: string, content: string, context: LifecycleContextInterface\n): Promise<string> {\n if (content.length < 1 || target.includes('node_modules')) return content;\n\n const { dropped } = context.stage;\n if (dropped.size < 1 && !content.includes(MacroPrefix)) return content;\n\n const state: MacroStateInterface = {\n target,\n dropped,\n code: content,\n logs: context.logs,\n edits: [],\n pending: [],\n defines: context.options.define ?? {},\n overrides: context.overrides\n };\n\n if (content.includes(MacroScanHint)) walk(parse.program, node => {\n const declared = declaredMacro(state, node);\n if (!declared) return false;\n\n const [ id, { call }] = declared;\n if (call.callee.name !== Macros.inline && !isActive(state, call)) dropped.add(id.name);\n\n return false;\n });\n\n walk(parse.program, expandNode.bind(null, state));\n if (state.pending.length > 0) await Promise.all(state.pending);\n\n return applyEdits(content, state.edits);\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { MacroCallType, MacroStateInterface } from '@directives/interfaces/macros-directive.interface';\n\n/**\n * Imports\n */\n\nimport { createRequire } from 'module';\nimport { inject } from '@remotex-labs/xinject';\nimport { sandboxExecute } from '@services/vm.service';\nimport { stringify } from '@components/object.component';\nimport { FrameworkService } from '@services/framework.service';\nimport { buildFromString } from '@services/transpiler.service';\n\n/**\n * Renders an evaluated value as the source text that stands in for the call.\n *\n * @param value - Value the callback produced\n * @returns Source text for the value, or `'undefined'` where there is nothing to render\n *\n * @remarks\n * `undefined` and `null` both come out as `undefined`, since the call has to leave an expression behind.\n * A function comes out as its own source, and a number or a boolean through `String`.\n * Everything else goes through {@link stringify}, which is JSON,\n * so a `Map` or a `Set` arrives as `{}` and a `bigint` as a quoted string.\n *\n * @since 3.0.0\n */\n\nexport function serialize(value: unknown): string {\n if (value === undefined || value === null) return 'undefined';\n if (typeof value === 'function') return value.toString();\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n\n return stringify(value) ?? 'undefined';\n}\n\n/**\n * Runs the callback of an `$$inline` call and renders what it produced.\n *\n * @param state - Transform state, read for the source text and for the file the call sits in\n * @param call - The `$$inline` call whose only argument is the callback to run\n * @returns Source text standing for the value the callback produced\n *\n * @throws BuildFailure - Rejected by esbuild when the callback does not build\n * @throws Error - Whatever the callback itself threw while it ran\n *\n * @remarks\n * The callback is taken from the source as written, wrapped in a CommonJS module that calls it,\n * and built through {@link buildFromString}.\n * A relative specifier inside it therefore resolves against the working directory rather than against the file that\n * the call sits in.\n * A package stays external and is required through a `require` bound to that file as the callback runs.\n * The built code runs through {@link sandboxExecute}, and the value is read from what the run returned,\n * falling back to `module.exports`.\n * What comes back is source text rather than a value, since {@link serialize} renders it.\n *\n * @example\n * ```ts\n * // $$inline(() => 2 + 2)\n * await evaluate(state, call); // '4'\n *\n * // $$inline(() => ({ region: 'eu' }))\n * await evaluate(state, call); // '{\"region\":\"eu\"}'\n * ```\n *\n * @see serialize\n * @see sandboxExecute\n * @see buildFromString\n *\n * @since 3.0.0\n */\n\nexport async function evaluate(state: MacroStateInterface, call: MacroCallType): Promise<string> {\n const target = state.target + '.inline';\n const thunk = state.code.slice(call.arguments[0].start, call.arguments[0].end);\n const [ map, output ] = (await buildFromString(`module.exports = (${ thunk })();`, target, {\n format: 'cjs',\n platform: 'node',\n packages: 'external'\n })).outputFiles!;\n\n const module = { exports: undefined };\n inject(FrameworkService).addSourceMap(target, map.text, true);\n const value = await sandboxExecute(output.text, { module, require: createRequire(state.target) }, {\n filename: target\n });\n\n return serialize(value ?? module.exports);\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { Context, ScriptOptions } from 'vm';\n\n/**\n * Imports\n */\n\nimport { Script, createContext } from 'vm';\n\n/**\n * Runs code in a VM context that shares the host's globals.\n *\n * @param code - Source to compile and run\n * @param sandbox - Values to expose as globals, each shadowing the host value of the same name\n * @param options - Compile-time options, such as the filename errors are reported against\n * @param isolateLogs - Whether to keep the code's console output from reaching the host\n * @returns The completion value of the last expression, awaited when it is a promise\n *\n * @throws SyntaxError - Thrown when the code does not compile\n * @throws Error - Whatever the code itself throws, propagated unchanged\n *\n * @remarks\n * The host's own globals are copied into the context before the sandbox is applied,\n * so the code inside sees the same intrinsics the caller does.\n * A value the code builds crosses back out intact - a `RegExp` made inside satisfies `instanceof RegExp` outside,\n * which a fresh context's own intrinsics would not.\n * This isolates the global scope, not the process.\n * `process` and the timers are reachable from the code being run,\n * so it is a scoping tool for code you trust rather than a boundary against code you do not.\n * Only compilation is configurable - the run is fixed to break on `SIGINT` and to leave errors undecorated.\n * It carries no timeout, so code that never finishes blocks the caller.\n *\n * `isolateLogs` drops the host `console` rather than replacing it,\n * so the code falls back to the console a fresh context is given and its output reaches nothing the caller sees.\n * A call still succeeds, since `console.log` is a function either way,\n * so quieting the output does not break code that logs.\n * The drop happens after the sandbox is applied, so it takes a `console` the caller injected as well.\n * It covers the console alone - code writing to `process.stdout` reaches the host whatever this is set to.\n *\n * @example\n * ```ts\n * await sandboxExecute('2 + 2'); // 4\n * (await sandboxExecute('new RegExp(\"a\")')) instanceof RegExp; // true - the host's RegExp\n *\n * const module = { exports: {} };\n * await sandboxExecute('module.exports = process.cwd();', { module });\n * module.exports; // 'D:/app' - read back through the injected object\n *\n * await sandboxExecute('console.log(\"noisy\"); 1', {}, {}, true); // 1 - nothing printed\n * ```\n *\n * @see Context\n * @see ScriptOptions\n *\n * @since 3.0.0\n */\n\nexport async function sandboxExecute(code: string, sandbox: Context = {}, options: ScriptOptions = {}, isolateLogs = false): Promise<unknown> {\n const base: Record<string, unknown> = {};\n const descriptors: { [x: string]: PropertyDescriptor; } = Object.getOwnPropertyDescriptors(globalThis);\n delete descriptors.globalThis;\n if(isolateLogs) delete descriptors.console;\n\n Object.defineProperties(base, descriptors);\n Object.assign(base, sandbox);\n\n const context = createContext(base);\n const script = new Script(code, options);\n\n return await script.runInContext(context, { breakOnSigint: true, displayErrors: false });\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { BuildOptions, BuildResult, Metafile } from 'esbuild';\nimport type { BuildResultType } from '@services/interfaces/transpiler-service.interface';\n\n/**\n * Imports\n */\n\nimport { cwd } from 'process';\nimport { build } from 'esbuild';\nimport { dirname, basename } from '@remotex-labs/xmap';\nimport { DefaultBuildOptions } from '@constants/transpiler.constant';\n\n/**\n * Builds whatever the options describe and returns the result in memory.\n *\n * @typeParam T - Extra fields to widen the result with, for a caller that attaches its own\n *\n * @param buildOptions - esbuild options, the entry points among them, overriding {@link DefaultBuildOptions}\n * @returns The build result, carrying a metafile the type still marks optional\n *\n * @throws BuildFailure - Rejected by esbuild when the build fails, carrying its errors and warnings\n *\n * @remarks\n * Options are layered in four steps: the working directory, then {@link DefaultBuildOptions},\n * then the caller's own, and last the metafile.\n * Only the metafile is applied after the caller's, so it is the single option that cannot be turned off.\n * Everything else is the caller's to change, including the working directory and whether output is written at all.\n * Entry points travel in the options like any other setting,\n * so a build is described by a single object rather than by an argument and an object that have to agree.\n *\n * @example\n * ```ts\n * const result = await buildFiles({ entryPoints: [ 'src/index.ts' ] });\n *\n * result.outputFiles?.length; // 2 - the source map and the code\n * Object.keys(result.metafile!.inputs); // [ 'src/index.ts', 'src/builder.ts' ]\n * ```\n *\n * @see DefaultBuildOptions\n * @since 3.0.0\n */\n\nexport async function buildFiles<T = object>(buildOptions: BuildOptions = {}): Promise<BuildResultType & T> {\n return await build({\n absWorkingDir: cwd(),\n ...DefaultBuildOptions,\n ...buildOptions,\n metafile: true\n }) as BuildResultType & T;\n}\n\n/**\n * Builds source text that has no file behind it.\n *\n * @typeParam T - Extra fields to widen the result with, for a caller that attaches its own\n *\n * @param source - TypeScript source to build\n * @param path - Name the source is reported under in its map and in errors, which need not exist on the disk\n * @param buildOptions - Options overriding {@link DefaultBuildOptions}\n * @returns The build result, carrying the code and its map in `outputFiles`\n *\n * @throws BuildFailure - Rejected by esbuild when the build fails, carrying its errors and warnings\n *\n * @remarks\n * The text is fed in through esbuild's `stdin` rather than read from a file,\n * which is what lets a macro body or a generated snippet be built before any file exists.\n * It is loaded as TypeScript, and its relative imports resolve against the working directory rather than against\n * `path`, which names the source in the map and in errors without pointing at a real location.\n * Four options are fixed after the caller's and cannot be overridden: the stdin input, in-memory output, the metafile,\n * and an external source map.\n * Logging is not among them: it arrives silent from {@link DefaultBuildOptions} and stays the caller's to raise.\n *\n * @example\n * ```ts\n * const result = await buildFromString('export const x: number = 42;', 'virtual.ts');\n *\n * result.outputFiles?.length; // 2 - the source map and the code\n * Object.keys(result.metafile!.inputs); // [ 'virtual.ts' ] - keyed by the name that was passed\n * ```\n *\n * @see DefaultBuildOptions\n * @since 3.0.0\n */\n\nexport async function buildFromString<T = object>(source: string, path: string, buildOptions: BuildOptions = {}): Promise<BuildResultType & T> {\n return await build({\n absWorkingDir: cwd(),\n ...DefaultBuildOptions,\n ...buildOptions,\n stdin: {\n loader: 'ts',\n contents: source,\n resolveDir: dirname(path),\n sourcefile: basename(path)\n },\n write: false,\n metafile: true,\n sourcemap: 'external'\n }) as BuildResultType & T;\n}\n\n/**\n * Walks the imports of the entry points named in the options and returns the dependency graph, building no output.\n *\n * @param buildOptions - esbuild options, the entry points to walk among them, applied under the ones it fixes\n * @returns The result, its `metafile` describing every input reached and the imports between them\n *\n * @throws BuildFailure - Rejected by esbuild when a specifier does not resolve\n *\n * @remarks\n * Bundling is what does the walking,\n * so the graph matches what a bundler would resolve rather than a reading of the import statements.\n * An unresolvable specifier therefore fails the call instead of being reported as a missing edge.\n * Packages are marked external, so the walk stops at the project's edge rather than descending into `node_modules`.\n * Nothing reaches the disk: output is kept in memory,\n * and the output directory is nominal, named only because esbuild insists on one.\n * {@link DefaultBuildOptions} is not applied here, unlike {@link buildFiles}, so the caller's options and the seven\n * fixed after them are the whole of the configuration.\n *\n * @example\n * ```ts\n * const result = await analyzeDependencies({ entryPoints: [ 'src/index.ts' ] });\n *\n * Object.keys(result.metafile.inputs); // [ 'src/index.ts', 'src/builder.ts' ]\n * result.metafile.inputs['src/index.ts'].imports; // [ { path: 'src/builder.ts', kind: 'import-statement' } ]\n * ```\n *\n * @see Metafile\n * @since 3.0.0\n */\n\nexport async function analyzeDependencies(buildOptions: BuildOptions = {}): Promise<\n BuildResult & { metafile: Metafile }\n> {\n return await build({\n ...buildOptions,\n write: false,\n bundle: true,\n outdir: 'tmp',\n outfile: undefined,\n metafile: true,\n packages: 'external',\n logLevel: 'silent'\n });\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { BuildOptions } from 'esbuild';\n\n/**\n * Base esbuild options every build in this package starts from.\n *\n * @remarks\n * Output is kept in memory rather than written,\n * so a caller reads `outputFiles` and decides for itself what reaches the disk.\n * The source map is emitted as its own output file rather than inlined,\n * which keeps the code readable and lets a consumer attach the map only when it wants it.\n * An output directory is set even though nothing is written,\n * since esbuild insists on one as soon as a build has more than a single entry point.\n * Spread before the caller's options wherever it is used,\n * so any of these can be overridden - unlike the options each build helper fixes after them.\n *\n * @example\n * ```ts\n * defaultBuildOptions.write; // false - the result is returned, not written\n * await buildFiles({ entryPoints: [ 'src/index.ts' ], minify: false }); // overrides one, keeps the rest\n * ```\n *\n * @see BuildOptions\n * @since 2.0.0\n */\n\nexport const DefaultBuildOptions: BuildOptions = {\n write: false,\n bundle: true,\n minify: true,\n outdir: 'dist',\n format: 'cjs',\n target: 'esnext',\n logLimit: 0,\n logLevel: 'silent',\n platform: 'browser',\n sourcemap: 'external'\n};\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { BuildOptions } from 'esbuild';\n\n/**\n * Imports\n */\n\nimport { cwd } from 'process';\nimport { relative } from '@remotex-labs/xmap';\nimport { collectFiles } from '@components/glob.component';\nimport { FrameworkService } from '@services/framework.service';\n\n/**\n * Normalizes entry points of any esbuild form into an output name to input path record.\n *\n * @param entryPoints - Entry points in any form esbuild accepts, or `undefined`\n * @param root - Directory the output names are shortened against, defaulting to the working directory\n * @returns The entry points keyed by the output each one produces, or `undefined` when none were given\n *\n * @throws Error - When the entry points are neither an array, an object, nor `undefined`\n *\n * @remarks\n * The three forms differ only in where the output name comes from:\n * - A list of globs is matched from the working directory, and each file is keyed by its path with `root` stripped\n * off the front and the extension dropped, so `src` as the root turns `src/components/interactive.component.ts`\n * into `components/interactive.component`.\n * - A list of `in` and `out` pairs is keyed by `out`, both paths passing through untouched.\n * - A record is already in the target shape and is returned as it stands, without a copy.\n *\n * Globs are always matched from the working directory, whatever `root` says: `root` shortens the output names and\n * does nothing else, matching no files itself and excluding none.\n * A file the globs reach from outside `root` is therefore kept rather than dropped,\n * and is named by its whole path from the working directory instead.\n * One call can therefore carry files from either side of `root`:\n * an outside file lands in a directory of its own in the output, while an inside file lands at the top.\n * The values are the paths the walk produced, relative to the working directory,\n * so nothing is resolved a second time, and a key costs one slice.\n * An empty list yields an empty record rather than every file under the working directory, which a pattern set with\n * no includes would otherwise match.\n *\n * @example\n * ```ts\n * extractEntryPoints([ 'src/**' ]);\n * // { 'src/index': 'src/index.ts', 'src/components/glob.component': 'src/components/glob.component.ts' }\n *\n * extractEntryPoints([ 'src/**' ], 'src/components');\n * // {\n * // 'glob.component': 'src/components/glob.component.ts', // under the root, shortened to its own name\n * // 'src/services/vm.service': 'src/services/vm.service.ts' // outside it, named by its whole path\n * // }\n *\n * extractEntryPoints([ { in: 'src/index.ts', out: 'bundle' } ]);\n * // { bundle: 'src/index.ts' }\n * ```\n *\n * @see collectFiles\n * @see {@link https://esbuild.github.io/api/#entry-points | esbuild entry points}\n *\n * @since 3.0.0\n */\n\nexport function extractEntryPoints(entryPoints: BuildOptions['entryPoints'], root: string = cwd()): Record<string, string> | undefined {\n if (entryPoints === undefined) return undefined;\n if (!Array.isArray(entryPoints)) {\n if (typeof entryPoints !== 'object' || entryPoints === null) throw new Error('Unsupported entry points format');\n\n return entryPoints;\n }\n\n const result: Record<string, string> = {};\n if (entryPoints.length < 1) return result;\n\n if (typeof entryPoints[0] === 'object') {\n for (const entry of <Array<{ in: string, out: string }>> entryPoints) result[entry.out] = entry.in;\n\n return result;\n }\n\n const prefix = relative(cwd(), FrameworkService.resolve(root));\n const scope = prefix && prefix !== '.' ? `${ prefix }/` : '';\n\n for (const file of collectFiles(cwd(), <Array<string>> entryPoints)) {\n const name = scope && file.startsWith(scope) ? file.slice(scope.length) : file;\n const dot = name.lastIndexOf('.');\n result[dot > name.lastIndexOf('/') + 1 ? name.slice(0, dot) : name] = file;\n }\n\n return result;\n}\n","/**\n * The configuration blocks a build injects into its esbuild options as text.\n *\n * @remarks\n * The three settings a configuration states as a table of names to code rather than as a plain option,\n * so one pass over this list injects all of them instead of naming each at its own call site.\n * A value written as a function is called for the variant being built and its result injected,\n * which is what makes the three interchangeable here.\n *\n * @example\n * ```ts\n * for (const block of TextBlocks) injectTextBlock(options, block); // banner, then footer, then define\n * ```\n *\n * @see VariantService\n * @since 3.0.0\n */\n\nexport const TextBlocks = [ 'banner', 'footer', 'define' ] as const;\n\n/**\n * The reporting level each TypeScript diagnostic category maps to.\n *\n * @remarks\n * Indexed by `ts.DiagnosticCategory`, which counts `Warning` as `0`, `Error` as `1`, and `Suggestion` as `2`,\n * so the order of the entries is the mapping itself rather than a preference.\n * `Message` counts as `3` and falls off the end,\n * so whatever reads the table settles that one for itself.\n *\n * @example\n * ```ts\n * DiagnosticLevels[1]; // 'error' - ts.DiagnosticCategory.Error\n * DiagnosticLevels[3]; // undefined - a plain message, left to the reader\n * ```\n *\n * @see LogLevelType\n * @see VariantService\n *\n * @since 3.0.0\n */\n\nexport const DiagnosticLevels = [ 'warning', 'error', 'info' ];\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { PartialMessage, Message, OnStartResult } from 'esbuild';\n\n/**\n * Imports\n */\n\nimport { parseErrorStack } from '@remotex-labs/xmap/parser.component';\n\n/**\n * Reports whether a caught value carries esbuild's own messages rather than being an ordinary error.\n *\n * @param error - Value caught from a build, of unknown shape\n * @returns `true` when the value holds esbuild messages, which narrows it to {@link OnStartResult}\n *\n * @remarks\n * The test is a non-null object whose `errors` array holds at least one entry,\n * and whose first entry is an object carrying a `detail` key.\n * esbuild puts `detail` on every message it produces, so the key is there even where it holds nothing,\n * and the guard reads whether the key is present rather than what it holds.\n * That is what separates a nested build that failed from an error a hook threw:\n * the first already carries messages a reporter files as they stand,\n * while the second reaches {@link errorToMessage} to become one.\n * A result assembled by hand goes unrecognized, since a message written as `{ text }` carries no `detail` key.\n *\n * @example\n * ```ts\n * isEsbuildError(buildFailure); // true - errors[0] came from esbuild\n * isEsbuildError(new Error('boom')); // false - no errors\n * isEsbuildError({ errors: [] }); // false - nothing to report\n * isEsbuildError({ errors: [ { text: 'oops' } ] }); // false - no detail key\n * ```\n *\n * @see errorToMessage\n * @since 3.0.0\n */\n\nexport function isEsbuildError(error: unknown): error is OnStartResult {\n if (error === null || typeof error !== 'object') return false;\n\n const errors = (error as { errors?: unknown }).errors;\n if (!Array.isArray(errors) || errors.length === 0) return false;\n const first = errors[0];\n\n return first !== null && typeof first === 'object' && 'detail' in first;\n}\n\n/**\n * Converts a thrown error into an esbuild message.\n *\n * @param error - Error to convert, kept whole on the message's `detail`\n * @param id - Message id to file the diagnostic under, empty when the caller names none\n * @param name - Plugin name to credit the message to, empty when the caller names none\n * @returns The message, carrying a location when the error's first frame named one\n *\n * @remarks\n * The error travels on `detail` rather than flattened into the text,\n * so {@link getErrorStack} unwraps it later and resolves the whole trace instead of the summary line alone.\n * `text` is the message the stack parsed out, and `location` comes from the first frame,\n * set only when that frame names a file, a line, and a column.\n * A frame of the three leaves the message without a location,\n * which leaves a reader with the text alone.\n * The location is filed under the `file` namespace, since a parsed frame points at a path on disk\n * rather than at something a plugin serves itself.\n *\n * @example\n * ```ts\n * const message = errorToMessage(new Error('boom'), 'macro-failed', 'xbuild');\n * message.text; // 'boom'\n * message.id; // 'macro-failed'\n * message.location?.line; // 19 - the line the first frame points at\n * ```\n *\n * @see getErrorStack\n * @see parseErrorStack\n *\n * @since 3.0.0\n */\n\nexport function errorToMessage(error: Error, id: string = '', name: string = ''): Message {\n const message = { detail: error, id, pluginName: name } as PartialMessage;\n\n const parsedStack = parseErrorStack(error);\n const frame = parsedStack.stack[0];\n\n message.text = parsedStack.message;\n if (frame?.fileName && frame.line && frame.column) {\n message.location = {\n line: frame.line,\n file: frame.fileName,\n column: frame.column,\n namespace: 'file'\n };\n }\n\n return message as Message;\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { FSWatcher, Dirent } from 'fs';\nimport type { ErrorType, CompleteType, UnsubscribeType } from '@remotex-labs/xobservable';\nimport type { WatchEventType, ChangeType, ObserverType } from './interfaces/watch-service.interface';\nimport type { WatchChangeInterface, WatchOptionsInterface } from './interfaces/watch-service.interface';\n\n/**\n * Imports\n */\n\nimport { Injectable } from '@remotex-labs/xinject';\nimport { Subject } from '@remotex-labs/xobservable';\nimport { ChangeCode } from '@constants/watch.constant';\nimport { createMatcher } from '@components/glob.component';\nimport { resolve, join, relative } from '@remotex-labs/xmap';\nimport { watch, realpathSync, readdirSync, lstatSync, statSync } from 'fs';\n\n/**\n * A filesystem watcher that multicasts debounced batches of path changes to every subscriber.\n *\n * @remarks\n * Extends a multicast {@link Subject}: the underlying `fs.watch` handles are opened on the **first** subscription and\n * torn down only when the **last** subscription ends, while every active subscriber receives each emitted batch.\n * Events are filtered by a glob matcher, coalesced within a debounced window, and delivered as a single\n * {@link WatchEventType} keyed by path relative to the base.\n * Because `fs.watch` never follows symbolic links,\n * {@link WatchOptionsInterface.followSymlinks} places explicit watchers on the links it finds.\n * As a {@link Subject}, the emitted stream can be reshaped with `pipe` and operators before subscribing.\n *\n * @example\n * <caption>Multiple independent subscribers - each receives every batch</caption>\n * ```ts\n * const watcher = new WatchService('src', { recursive: true, filter: [ '**\\/*.{ts,js}' ], debounce: 100 });\n *\n * const stopA = watcher.subscribe((changes) => rebuild(changes)); // opens the fs watchers\n * const stopB = watcher.subscribe((changes) => reloadTypes(changes)); // reuses them\n *\n * stopB(); // watchers stay open - `stopA` is still subscribed\n * stopA(); // last subscriber leaves - every handle is closed\n * ```\n *\n * @example\n * <caption>Scoped teardown - the subscription disposes automatically at the end of the block</caption>\n * ```ts\n * const watcher = new WatchService(cwd(), { followSymlinks: true, filter: [ '**\\/*.{ts,js}' ] });\n * using sub = watcher.subscribe((changes) => console.log(Object.keys(changes)));\n * ```\n *\n * @see Subject.pipe\n * @see WatchEventType\n * @see WatchOptionsInterface\n *\n * @since 3.0.0\n */\n\n@Injectable({\n scope: 'singleton'\n})\nexport class WatchService extends Subject<WatchEventType> {\n /**\n * The absolute root path being watched.\n *\n * @since 3.0.0\n */\n\n private readonly base: string;\n\n /**\n * Predicate deciding whether a path passes the configured filter.\n *\n * @since 3.0.0\n */\n\n private readonly matcher: ReturnType<typeof createMatcher>;\n\n /**\n * Active `fs.watch` handles, keyed by the path each was opened on.\n *\n * @since 3.0.0\n */\n\n private readonly watchers = new Map<string, FSWatcher>();\n\n /**\n * Changes accumulated in the current debounced window, keyed by path relative to the base.\n *\n * @since 3.0.0\n */\n\n private readonly pending = new Map<string, WatchChangeInterface>();\n\n /**\n * Count of currently active subscriptions, used to start watchers on the first and stop them on the last.\n *\n * @since 3.0.0\n */\n\n private subscriptions = 0;\n\n /**\n * Handle for the scheduled debounced flush, or `undefined` while idle.\n *\n * @since 3.0.0\n */\n\n private timer?: ReturnType<typeof setTimeout>;\n\n /**\n * Creates a watcher rooted at a base path.\n *\n * @param base - Directory to watch, resolved to an absolute path\n * @param options - Filtering, debounce, recursion, and symlink behavior\n *\n * @remarks\n * No watcher is opened until the first subscriber attaches, so constructing one costs a resolve and a matcher.\n *\n * @example\n * ```ts\n * const watcher = new WatchService('src', { filter: [ '**\\/*.ts' ] }); // nothing is watched yet\n * ```\n *\n * @see WatchOptionsInterface\n * @since 3.0.0\n */\n\n constructor(base: string, private options?: WatchOptionsInterface) {\n super();\n\n this.base = resolve(base);\n this.matcher = createMatcher(this.options?.filter ?? [], {\n dot: this.options?.dot ?? false\n });\n }\n\n /**\n * Subscribes to the debounced change stream, starting the watchers on the first subscriber.\n *\n * @param observerOrNext - A full observer object, or a `next` callback\n * @param error - Error handler, used when the first argument is a `next` callback\n * @param complete - Completion handler, used when the first argument is a `next` callback\n * @returns Idempotent, disposable unsubscribe function that detaches this subscriber and,\n * once it is the last one, closes every open watcher\n *\n * @remarks\n * The first subscription opens the `fs.watch` handles, and each later subscription reuses them.\n * Unsubscribing runs at most once.\n * The handles, the pending batch, and the flush timer are released only when the final subscriber leaves,\n * so a watcher shared by several consumers stays alive until all of them detach.\n *\n * @example\n * ```ts\n * const stop = watcher.subscribe((changes) => rebuild(changes));\n * stop(); // detaches, and closes the handles when no other subscriber is left\n * ```\n *\n * @see ObserverType\n * @see Subject.subscribe\n *\n * @since 3.0.0\n */\n\n override subscribe(observerOrNext?: ObserverType, error?: ErrorType, complete?: CompleteType): UnsubscribeType {\n const unsubscribe = super.subscribe(observerOrNext, error, complete);\n if (++this.subscriptions === 1) this.start();\n\n return this.toUnsubscribe(() => {\n unsubscribe();\n if (--this.subscriptions === 0) this.stop();\n });\n }\n\n /**\n * The debounced window in milliseconds, defaulting to 150.\n *\n * @since 3.0.0\n */\n\n private get debounce(): number {\n return this.options?.debounce ?? 150;\n }\n\n /**\n * Opens the base watcher and the symlink watchers when configured.\n *\n * @remarks\n * Invoked once when the subscriber count rises from zero to one.\n *\n * @since 3.0.0\n */\n\n private start(): void {\n this.watch(this.base, this.ignored.bind(this), this.options?.recursive);\n if (this.options?.followSymlinks) this.watchSymlinks(this.base);\n }\n\n /**\n * Clears the pending timer and closes every open watcher.\n *\n * @remarks\n * Invoked once when the subscriber count falls back to zero, returning the service to its pre-subscription state so\n * a later subscription can start clean.\n *\n * @since 3.0.0\n */\n\n private stop(): void {\n if (this.timer) clearTimeout(this.timer);\n for (const watcher of this.watchers.values()) watcher.close();\n\n this.timer = undefined;\n this.pending.clear();\n this.watchers.clear();\n }\n\n /**\n * Emits the accumulated batch to every subscriber and clears the window.\n *\n * @remarks\n * A no-op when nothing is pending, so an expired timer with no changes emits nothing.\n * A `next` that throws is reported to that subscriber's own `error` handler by the {@link Subject},\n * which then rethrows the failures as one aggregate.\n * That aggregate is swallowed here, so one faulty consumer cannot stop the watcher for the others.\n *\n * @since 3.0.0\n */\n\n private flush(): void {\n this.timer = undefined;\n if (this.pending.size === 0) return;\n\n const batch = Object.fromEntries(this.pending) as WatchEventType;\n this.pending.clear();\n\n try {\n this.next(batch);\n } catch {\n /* handled per-observer by the Subject */\n }\n }\n\n /**\n * Closes and forgets the watcher registered on a path, if any.\n *\n * @param path - Path whose watcher should be released\n *\n * @since 3.0.0\n */\n\n private watcherClose(path: string): void {\n const watcher = this.watchers.get(path);\n if (!watcher) return;\n\n watcher.close();\n this.watchers.delete(path);\n }\n\n /**\n * Classifies a raw watch event and queues it for the next flush.\n *\n * @param event - The `fs.watch` event name, either `rename` or `change`\n * @param path - Absolute path the event refers to\n *\n * @remarks\n * A symlink is stat-followed: when it resolves to a matching file, it is watched directly,\n * and when it resolves to a directory under a recursive watch, it is watched recursively.\n * A broken link is dropped.\n * The change type is read from that followed `stat` - a missing entry is {@link ChangeCode.Deleted} and closes its\n * watcher, an entry whose `birthtime` equals its `mtime` is {@link ChangeCode.Added},\n * and anything else is {@link ChangeCode.Change}.\n * Only paths that pass the filter arm the debounced timer and enter the pending batch.\n *\n * @since 3.0.0\n */\n\n private watcherEvent(event: string, path: string): void {\n const relativePath = relative(this.base, path);\n const link = lstatSync(path, { throwIfNoEntry: false });\n const stats = link?.isSymbolicLink() ? statSync(path, { throwIfNoEntry: false }) : link;\n\n if (link?.isSymbolicLink()) {\n if (!stats) return;\n if (event === 'rename') this.watcherClose(path);\n\n if (stats.isFile() && this.matcher(path)) this.watch(path);\n else if (stats.isDirectory() && this.options?.recursive)\n this.watch(path, this.ignored.bind(this), true);\n }\n\n if (!this.matcher(relativePath)) return;\n if (this.timer) this.timer.refresh();\n else this.timer = setTimeout(this.flush.bind(this), this.debounce);\n\n let type: ChangeType;\n if (!stats) {\n this.watcherClose(path);\n type = ChangeCode.Deleted;\n } else {\n type = stats.birthtimeMs === stats.mtimeMs ? ChangeCode.Added : ChangeCode.Change;\n }\n\n this.pending.set(relativePath, { type, stats });\n }\n\n /**\n * Opens an `fs.watch` on a path and registers its change and error handlers.\n *\n * @param path - Path to watch, ignored if already watched or filtered out by {@link ignored}\n * @param ignore - Optional per-entry ignore predicate forwarded to `fs.watch`\n * @param recursive - Whether the watch should cover nested entries\n *\n * @remarks\n * The watch is opened on the real (symlink-resolved) path, while events are reported against the original `path`.\n * A watcher error closes the watcher and forwards the error to every subscriber.\n *\n * @since 3.0.0\n */\n\n private watch(path: string, ignore?: (filename: string) => boolean, recursive: boolean = false): void {\n if (this.watchers.has(path) || this.ignored(path)) return;\n const watcher = watch(realpathSync(path), { recursive, ignore }, (event, filename) => {\n if (!filename) return;\n const target = path.includes(filename) ? path : join(path, filename);\n this.watcherEvent(event, target);\n });\n\n watcher.on('error', (error: Error) => {\n this.watcherClose(path);\n this.error(error);\n });\n\n this.watchers.set(path, watcher);\n }\n\n /**\n * Whether a path should be skipped by the watcher.\n *\n * @param target - Path to test\n * @returns `true` for an empty path, a `~` backup file, or - unless `dot` is set - any dot-prefixed segment\n *\n * @since 3.0.0\n */\n\n private ignored(target: string): boolean {\n if (!target || target.endsWith('~')) return true;\n if (!this.options?.dot) {\n if (target && target.split(/[/\\\\]/).some(\n seg => seg.startsWith('.'))\n ) return true;\n }\n\n return false;\n }\n\n /**\n * Walks the tree under a root and watches every symbolic link found.\n *\n * @param root - Directory to scan for links\n *\n * @remarks\n * Iterative and single-level per read, so ignored directories are pruned before entry and never fully materialized.\n * Descends into real subdirectories only when recursion is enabled.\n * Unreadable directories are skipped silently.\n *\n * @since 3.0.0\n */\n\n private watchSymlinks(root: string): void {\n const stack: Array<string> = [ root ];\n\n while (stack.length) {\n const dir = stack.pop()!;\n\n let entries: Array<Dirent>;\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n continue;\n }\n\n for (const entry of entries) {\n const full = join(entry.parentPath ?? dir, entry.name);\n if (this.ignored(full)) continue;\n\n if (entry.isSymbolicLink()) {\n this.watch(full, this.ignored.bind(this), this.options?.recursive);\n } else if (this.options?.recursive && entry.isDirectory()) {\n stack.push(full);\n }\n }\n }\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { xBuildConfigInterface } from '@providers/interfaces/config-file-provider.interface';\n\n/**\n * Imports\n */\n\nimport { resolve } from 'path';\nimport process from 'node:process';\nimport { createRequire } from 'module';\nimport { dirname } from '@remotex-labs/xmap';\nimport { ArgvModule } from '@argv/argv.module';\nimport { inject } from '@remotex-labs/xinject';\nimport { FilesModel } from '@models/files.model';\nimport { sandboxExecute } from '@services/vm.service';\nimport { deepMerge } from '@components/object.component';\nimport { FrameworkService } from '@services/framework.service';\nimport { buildFromString } from '@services/transpiler.service';\n\n/**\n * Runs a compiled configuration file and returns what it exported.\n *\n * @typeParam T - Shape the export is cast to, which the caller states rather than this function checks\n *\n * @param code - The file, already compiled to CommonJS\n * @param path - Path the file came from, which binds its `require` and names it in a stack\n * @param $argv - Arguments to expose to the file as a global, empty where none have been parsed yet\n * @param isolation - Whether to keep the file's console output from reaching the host\n * @returns The named `config` export, the default export where there is none, or an empty object for neither\n *\n * @throws Error - Whatever the file itself threw while it ran\n *\n * @remarks\n * The `require` handed in is bound to the file's own path rather than to this module,\n * so a configuration file resolves a package the way a file in its own directory would.\n * A named `config` export wins over a default export, and a file exporting neither comes back empty.\n * Compiled CommonJS replaces `module.exports` outright,\n * which is what leaves the two exports to be told apart rather than read off the object this function seeded.\n * Reach for `isolation` on a run whose output would only be repeated, since a file may be run more than once.\n *\n * @example\n * ```ts\n * // the file: export const config = { serve: { dir: 'dist' } };\n * const config = await execConfigFile(code, 'xbuild.config.ts', { watch: true });\n * config.serve; // { dir: 'dist' }\n * ```\n *\n * @see sandboxExecute\n * @see configFileProvider\n *\n * @since 3.0.0\n */\n\nexport async function execConfigFile<T>(code: string, path: string, $argv = {}, isolation = false): Promise<T> {\n const module = { exports: { config: {}, default: {} } };\n await sandboxExecute(code, { require: createRequire(resolve(path)), module, $argv }, { filename: path }, isolation);\n const config = module.exports.config ?? module.exports.default;\n\n return (config ?? {}) as T;\n}\n\n/**\n * Loads a configuration file and returns what it exported.\n *\n * @typeParam T - Shape the result is cast to, which the caller states rather than this provider checks\n * @param path - Path of the configuration file, relative or absolute\n * @param argv - Object the parsed arguments are written onto, left untouched where the file is missing\n * @returns What the file exported over the default watch settings, or an empty object where it exported nothing\n *\n * @throws BuildFailure - Rejected by esbuild when the file does not compile\n * @throws Error - Whatever the file itself threw while it ran\n *\n * @remarks\n * A configuration file is built as CommonJS and runs through {@link sandboxExecute},\n * with its `require` bound to its own path,\n * so it may import a package the project already depends on rather than only what this build bundles.\n * Its identifiers survive the build, and its source map is registered with {@link FrameworkService},\n * so an error thrown while it runs is reported against the source that was written.\n *\n * The file runs twice, since the options it declares through `userArgv` are known only once it has been read.\n * The first run is a throwaway: it sees an empty `$argv`, and its output is isolated,\n * so a file that logs does not report the same lines on both passes.\n * The command line is then parsed knowing those options, and the second run sees the whole option set on `$argv`.\n * The caller's `argv` object receives those arguments too, which is how a caller reads them back.\n * Anything the file does on its way to an export therefore happens twice.\n *\n * {@link execConfigFile} settles which of the two exports is read,\n * and what comes back here is that export merged over a default watch filter and recursive watching, key by key,\n * so a file naming one watch setting keeps the others.\n * A `filter` the file names joins the default list rather than replacing it,\n * since {@link deepMerge} concatenates two arrays.\n * A file that exports nothing still picks up those defaults,\n * while one that is missing or holds no text returns before the merge and comes back as a bare empty object.\n * The result is cast rather than validated, so a file exporting something else entirely reaches the caller unchanged.\n *\n * @example\n * ```ts\n * // the configuration file\n * export const config = { serve: { dir: 'dist', start: true }, watch: { debounce: 50 } };\n *\n * const loaded = await configFileProvider('xbuild.config.ts');\n * loaded.serve; // { dir: 'dist', start: true }\n * loaded.watch; // { filter: [ ... ], recursive: true, debounce: 50 } - the defaults kept\n * ```\n *\n * @see deepMerge\n * @see execConfigFile\n * @see buildFromString\n * @see xBuildConfigInterface\n *\n * @since 3.0.0\n */\n\nexport async function configFileProvider<T extends xBuildConfigInterface>(path: string, argv: Record<string, unknown> = {}): Promise<T> {\n const fileObject = inject(FilesModel).touch(path);\n const text = fileObject.snapshot?.text;\n if (!text) return <T> {};\n\n const [ map, code ] = (await buildFromString(text, path, {\n minify: false,\n format: 'cjs',\n outdir: dirname(path),\n platform: 'node',\n logLevel: 'silent',\n packages: 'external',\n minifySyntax: true,\n minifyWhitespace: true,\n minifyIdentifiers: false\n })).outputFiles!;\n\n const argvService = inject(ArgvModule);\n inject(FrameworkService).addSourceMap(path, map.text, true);\n\n const preConfig = await execConfigFile<T>(code.text, path, {}, true);\n const args = argvService.enhancedParse(process.argv, preConfig.userArgv ?? {});\n\n Object.assign(argv, args);\n const config = await execConfigFile<T>(code.text, path, args);\n\n return deepMerge({} as T, {\n watch: {\n filter: [ '**/*.{js,ts,json}', '!**/*.d.ts' ],\n recursive: true\n }\n }, config as T);\n}\n"],"mappings":"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","names":["rmSync","process","inject","readFileSync","statSync","resolve","Injectable","FilesModel","path","encoding","target","stats","paths","pathList","resolve","info","entry","readFileSync","oldText","newText","oldLength","newLength","max","prefix","suffix","text","start","end","previous","statSync","__decorateClass","Injectable","resolveError","xterm","cwd","readFileSync","inject","Injectable","normalize","SourceService","FRAMEWORK_PATH_REGEX","EMPTY_MAPPINGS_REGEX","FrameworkService","normalize","cwd","path","inject","FilesModel","position","source","force","key","readFileSync","error","SourceService","__publicField","__decorateClass","Injectable","parseErrorStack","formatErrorCode","highlightCode","getSource","fileName","mapped","inject","FrameworkService","snapshot","FilesModel","code","lines","line","column","_bias","options","after","before","startLine","endLine","getErrorStack","raw","getErrorMetadata","verbose","framework","parsed","resolved","resolveError","path","frame","xterm","formatStack","metadata","name","message","notes","parts","note","stack","xBuildBaseError","message","name","error","options","getErrorMetadata","formatStack","formatErrors","reason","err","xBuildBaseError","metadata","getErrorMetadata","formatStack","process","exit","exec","readline","resolve","stdout","xterm","asciiLogo","bannerUi","prefix","relative","inject","stripAnsi","cursorTo","clearScreenDown","xterm","xterm","okColor","textColor","infoColor","warnColor","pathColor","errorColor","keywordColor","mutedColor","Levels","createActionPrefix","action","symbol","infoColor","prefix","visible","text","stripAnsi","pad","size","sourcePath","file","absolute","resolve","inject","FrameworkService","relative","formatLocation","line","column","separator","mutedColor","pathColor","warnColor","formatDetail","metadata","indent","root","lines","xterm","frame","describeMessage","message","code","typescript","getErrorMetadata","point","printGroup","messages","title","color","left","middle","rows","row","index","id","location","detail","tag","clearScreen","stdout","cursorTo","clearScreenDown","width","formatSize","bytes","printOutputs","metafile","limit","outputs","a","b","listed","sizes","right","total","sum","room","header","okColor","path","rest","more","platform","stdin","stdout","exit","xterm","ANSI","moveCursor","writeRaw","ShadowRenderer","OpenCommands","Keys","session","activity","row","repaint","cursorRow","resolve","answer","data","reported","stdin","writeRaw","stdout","openInBrowser","url","exec","platform","helpMenu","lines","keywordColor","key","describe","server","mutedColor","xterm","drawStatusBar","force","parts","infoColor","pathColor","ANSI","setActivity","text","startInteractive","screen","printed","claimRow","_","handleKey","stopInteractive","moveCursor","anchor","last","back","ShadowRenderer","width","exit","clearScreen","Injectable","inject","Injectable","BehaviorSubject","isObject","item","isPlainObject","prototype","deepMerge","target","sources","source","key","sourceValue","targetValue","equals","a","b","strictCheck","deepEquals","hasKey","obj","val","i","aKeys","bKeys","stringify","value","_","entry","map","distinctUntilChanged","DefaultsCommonConfig","ConfigurationService","initialConfig","DefaultsCommonConfig","BehaviorSubject","deepMerge","selector","observer","map","distinctUntilChanged","prev","curr","equals","partial","mergedConfig","config","__decorateClass","Injectable","ts","Injectable","normalize","relative","dirname","existsSync","parseSync","inject","mkdir","writeFile","join","dirname","relative","removeNode","node","content","edits","cursor","code","applyEdits","left","right","parts","index","i","edit","rewrite","source","target","ts","resolved","extension","relativeFileName","path","resolveSource","parse","statement","HeaderDeclarationBundle","DeclarationModel","ts","inject","FilesModel","path","target","file","cached","entry","entryPoints","outdir","outputs","contents","visited","names","name","pending","dependency","output","existsSync","options","base","join","node","directories","dirname","directory","mkdir","index","writeFile","source","declarationDir","outDir","rootDir","root","relative","closure","nested","exports","statements","binding","module","bindings","star","merged","clauses","surface","parts","HeaderDeclarationBundle","imports","content","service","version","declaration","context","parseSync","kept","body","statement","applyEdits","removeNode","moduleReference","named","exposed","local","bundleEdits","inner","comment","resolved","extension","relativeFileName","resolvedFileName","alias","start","end","code","ts","relative","inject","readdirSync","join","RegexCloser","lit","char","at","glob","index","isGlobstar","group","body","classEnd","openIndex","scan","lead","findClose","cursor","depth","braceClose","comma","compileClass","end","out","segmentEnd","from","compileFragment","isSegmentStart","alt","options","dot","wasStart","guard","DS","GLOBSTAR","nChar","RegexCloser","close","inner","tailEnd","tail","root","src","next","globToRegExp","createMatcher","globs","include","exclude","neg","path","r","collectFiles","base","FrameworkService","matcher","dotted","files","stack","directory","entries","readdirSync","join","entry","LanguageHostService","config","inject","FilesModel","file","path","paths","ts","encoding","extensions","exclude","include","depth","options","globs","createMatcher","target","excluded","relative","TypescriptService","configPath","LanguageHostService","ts","DeclarationModel","file","encoding","force","reloaded","path","entry","reachable","program","ignore","skip","affected","diagnostic","entryPoints","outdir","files","specifier","containingFile","container","dirname","cached","result","relative","key","normalize","instance","version","name","diagnostics","line","character","config","__publicField","__decorateClass","Injectable","Screen","build","inject","ConfigurationService","value","event","infoColor","mutedColor","keywordColor","createActionPrefix","errors","warnings","info","notes","metafile","failed","printOutputs","symbol","errorColor","okColor","name","warnColor","pathColor","diagnostics","logs","total","exit","reason","force","clearScreen","TypescriptService","activity","line","setActivity","lowest","Levels","code","printGroup","__decorateClass","Injectable","yargs","hideBin","Injectable","ArgsConfigPath","ArgsDefaultOptions","ArgsUsageExamples","ArgvModule","argv","yargs","ArgsDefaultOptions","userExtensions","parser","hideBin","originalShowHelp","consoleFunction","ArgsUsageExamples","command","description","__decorateClass","Injectable","inject","http","https","extname","readFileSync","server_default","join","inject","Subject","readdir","stat","readFile","ServerModule","config","dir","FrameworkService","Subject","inject","resolve","reject","err","address","req","res","options","readFileSync","join","defaultHandler","error","ext","requestPath","fullPath","stats","stat","fileList","readdir","file","extname","activePath","segments","path","htmlResult","server_default","contentType","data","readFile","inject","xBuildError","xBuildBaseError","message","options","Subject","parseSync","relative","inject","resolveLevel","overrides","id","level","key","collectLog","logs","message","resolved","collectLogs","messages","name","parseSync","inject","MacroPrefix","MacroScanHint","Macros","MacroFalsyDefines","MacroNameKeys","isDefined","defines","name","value","MacroFalsyDefines","defineDeclaration","code","target","prefix","call","suffix","callback","text","body","params","param","returns","head","defineExpression","statement","tail","analyzeMacros","files","defines","dropped","filesModel","inject","FilesModel","file","content","MacroScanHint","program","parseSync","node","declarator","call","directive","Macros","arg","isDefined","visitorKeys","createRequire","inject","Script","createContext","sandboxExecute","code","sandbox","options","isolateLogs","base","descriptors","context","cwd","build","dirname","basename","DefaultBuildOptions","buildFiles","buildOptions","build","cwd","DefaultBuildOptions","buildFromString","source","path","dirname","basename","analyzeDependencies","serialize","value","stringify","evaluate","state","call","target","thunk","map","output","buildFromString","module","inject","FrameworkService","sandboxExecute","createRequire","isNode","value","walk","node","visit","parent","key","keys","visitorKeys","childKey","item","report","state","offset","level","message","code","line","start","index","collectLog","record","span","text","defer","call","wrap","edit","evaluate","error","Macros","isMacroCall","name","flag","isActive","isDefined","isDropped","macroTarget","declaredMacro","declaration","id","init","target","pruneImport","named","parts","dropped","specifier","source","pruneExport","specifiers","kept","local","expandDeclaration","declared","suffix","prefix","defineDeclaration","expand","statement","defineExpression","expandNode","MacroNameKeys","transformMacros","parse","content","context","MacroScanHint","applyEdits","cwd","relative","extractEntryPoints","entryPoints","root","cwd","result","entry","prefix","relative","FrameworkService","scope","file","collectFiles","name","dot","TextBlocks","DiagnosticLevels","parseErrorStack","isEsbuildError","error","errors","first","errorToMessage","id","name","message","parsedStack","frame","VariantService","_VariantService","name","events$","argv","inject","ConfigurationService","config","error","FilesModel","metafile","analyzeDependencies","logs","xBuildError","result","buildFiles","messages","level","collectLogs","errorToMessage","call","handle","hook","context","declaration","entryPoints","outdir","common","variant","previous","deepMerge","TypescriptService","extractEntryPoints","options","type","source","target","key","value","content","stringify","diagnostics","failOnError","category","code","text","file","line","column","message","DiagnosticLevels","esbuild","types","args","path","loader","contents","parsed","parseSync","transformMacros","resolveSource","merged","buildResult","event","build","block","TextBlocks","files","analyzeMacros","isEsbuildError","rootDir","relative","dot","BuildService","config","argv","Subject","inject","ConfigurationService","names","variants","VariantService","variant","cache","start","run","name","path","xBuildError","dependOn","dependency","results","failed","_","index","result","TypescriptService","dependencies","errors","logs","buildResult","Injectable","Subject","resolve","join","relative","watch","realpathSync","readdirSync","lstatSync","statSync","WatchService","Subject","base","options","resolve","createMatcher","observerOrNext","error","complete","unsubscribe","watcher","batch","path","event","relativePath","relative","link","lstatSync","stats","statSync","type","ignore","recursive","watch","realpathSync","filename","target","join","seg","root","stack","dir","entries","readdirSync","entry","full","__decorateClass","Injectable","resolve","process","createRequire","dirname","inject","execConfigFile","code","path","$argv","isolation","module","sandboxExecute","createRequire","resolve","configFileProvider","argv","text","inject","FilesModel","map","buildFromString","dirname","argvService","ArgvModule","FrameworkService","preConfig","args","process","config","deepMerge","configureEntryPoints","config","args","applyCommandLineOverrides","commonOutDir","variants","variant","executeBuild","build","rmSync","startServer","screen","serveDir","server","ServerModule","startWatchMode","buildService","files","inject","FilesModel","configVersion","WatchService","changedFiles","configFileProvider","count","startInteractive","main","bannerUi","preConfig","ArgvModule","BuildService","Screen"]}
1
+ {"version":3,"sources":["src/bash.ts","src/errors/uncaught.error.ts","src/providers/stack.provider.ts","src/models/files.model.ts","src/services/framework.service.ts","src/errors/base.error.ts","src/ui/screen.ui.ts","src/ui/interactive.ui.ts","src/ui/print.ui.ts","src/ui/banner.ui.ts","src/ui/color.ui.ts","src/constants/ui.constant.ts","src/services/configuration.service.ts","src/components/object.component.ts","src/constants/configuration.constant.ts","src/modules/typescript/services/typescript.service.ts","src/modules/typescript/models/declaration.model.ts","src/components/transformer.component.ts","src/modules/typescript/constants/typescript.constant.ts","src/modules/typescript/services/host.service.ts","src/components/glob.component.ts","src/constants/glob.constant.ts","src/modules/argv/argv.module.ts","src/modules/argv/constants/argv.constant.ts","src/modules/server/server.module.ts","src/modules/server/html/server.html","src/services/build.service.ts","src/errors/xbuild.error.ts","src/services/variant.service.ts","src/providers/log.provider.ts","src/directives/analyze.directive.ts","src/constants/macros.constant.ts","src/directives/define.directive.ts","src/directives/macros.directive.ts","src/directives/inline.directive.ts","src/services/vm.service.ts","src/services/transpiler.service.ts","src/constants/transpiler.constant.ts","src/components/entry-points.component.ts","src/constants/variant.constant.ts","src/providers/message.provider.ts","src/services/watch.service.ts","src/providers/config-file.provider.ts"],"sourceRoot":"https://github.com/remotex-labs/xBuild/tree/v3.0.2/","sourcesContent":["/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { ArgumentsInterface } from '@argv/interfaces/argv-module.interface';\nimport type { ConfigurationInterface } from '@interfaces/configuration.interface';\nimport type { ServerConfigurationInterface } from '@server/interfaces/server.interface';\nimport type { xBuildConfigInterface } from '@providers/interfaces/config-file-provider.interface';\n\n/**\n * Imports\n */\n\nimport { rmSync } from 'fs';\nimport '@errors/uncaught.error';\nimport { Screen } from '@ui/screen.ui';\nimport { bannerUi } from '@ui/banner.ui';\nimport { ArgvModule } from '@argv/argv.module';\nimport { inject } from '@remotex-labs/xinject';\nimport { FilesModel } from '@models/files.model';\nimport { ServerModule } from '@server/server.module';\nimport { startInteractive } from '@ui/interactive.ui';\nimport { BuildService } from '@services/build.service';\nimport { WatchService } from '@services/watch.service';\nimport { configFileProvider } from '@providers/config-file.provider';\n\n/**\n * Replaces the declared variants with one built from the entry points the command line named.\n *\n * @param config - Configuration read from the file, modified in place\n * @param args - Parsed command line the run was started with\n *\n * @remarks\n * Files named on the command line are a run of their own rather than an addition to what the file declares,\n * so the variants it declares are put aside, and a single variant named `argv` takes their place.\n * A command line naming no entry point leaves the configuration as the file wrote it.\n *\n * @example\n * ```ts\n * // xBuild src/index.ts\n * configureEntryPoints(config, args);\n * config.variants; // { argv: { esbuild: { entryPoints: [ 'src/index.ts' ] } } }\n * ```\n *\n * @since 3.0.0\n */\n\nexport function configureEntryPoints(config: xBuildConfigInterface, args: ArgumentsInterface): void {\n if (!args.entryPoints) return;\n\n config.variants = {\n argv: {\n esbuild: {\n entryPoints: args.entryPoints\n }\n }\n };\n}\n\n/**\n * Writes the flags the command line typed onto every variant.\n *\n * @param config - Configuration the overrides are written onto, modified in place\n * @param args - Parsed command line the run was started with\n *\n * @remarks\n * A flag left untyped is left alone rather than written as its default,\n * so what a configuration file states survives everything the command line did not say.\n * The overrides reach every variant, since a flag names what the run is for rather than which variant it is about.\n * Each output directory is also excluded from the watch as it is settled,\n * without which a build would write into the tree it is watching and set off the next one.\n *\n * @example\n * ```ts\n * // xBuild --outdir build --minify\n * applyCommandLineOverrides(config, args);\n * config.watch.filter; // [ '!build/**' ]\n * ```\n *\n * @since 3.0.0\n */\n\nexport function applyCommandLineOverrides(config: xBuildConfigInterface, args: ArgumentsInterface): void {\n const commonOutDir = config.common?.esbuild?.outdir ?? 'dist';\n const variants = Object.values(config.variants ?? {});\n if(commonOutDir) {\n config.watch?.filter?.push(`!${ commonOutDir }/**`);\n }\n\n for (const variant of variants) {\n if (args.types !== undefined) variant.types = args.types;\n if (args.outdir !== undefined) variant.esbuild.outdir = args.outdir;\n if (args.bundle !== undefined) variant.esbuild.minify = args.bundle;\n if (args.minify !== undefined) variant.esbuild.minify = args.minify;\n if (args.tsconfig !== undefined) variant.esbuild.tsconfig = args.tsconfig;\n if (args.platform !== undefined) variant.esbuild.platform = args.platform;\n if (args.declaration !== undefined) variant.declaration = args.declaration;\n if (args.failOnError !== undefined) {\n variant.types = { failOnError: args.failOnError };\n }\n\n if(variant.esbuild.outdir && variant.esbuild.outdir !== commonOutDir) {\n config.watch?.filter?.push(`!${ variant.esbuild.outdir }/**`);\n }\n }\n}\n\n/**\n * Clears the output of an earlier run where the command line asked for it, then builds.\n *\n * @param build - Service the variants are built through\n * @param args - Parsed command line the run was started with\n * @returns A promise settling once every variant asked for has finished\n *\n * @remarks\n * Bound to its two arguments and handed to the screen,\n * so a key or a watch starts the same build the command line asked for.\n * The directory cleared is `dist` rather than whatever the configuration writes to.\n * The `--build` flag decides which variants run, and naming none runs every variant the configuration declares.\n *\n * @since 3.0.0\n */\n\nasync function executeBuild(build: BuildService, args: ArgumentsInterface): Promise<void> {\n if (args.clean) rmSync('dist', { recursive: true, force: true });\n\n await build.build(args.build);\n}\n\n/**\n * Starts the development server where either the command line or the configuration asks for one.\n *\n * @param config - Configuration read for its `serve` block\n * @param args - Parsed command line the run was started with\n * @param screen - Screen the server reports through\n * @returns A promise settling once the server is listening, at once when none was asked for\n *\n * @remarks\n * `--serve` carries the directory to serve, so asking for a server and choosing what it serves are the one flag,\n * and a configuration that starts one of its own is honored even where the flag is absent.\n * The directory falls back to the configured one and then to `dist`, which is where a build writes by default.\n * The server reports through the screen rather than to the console,\n * so its address reaches the status line and its requests are held to the level the run reports at.\n *\n * @example\n * ```ts\n * // xBuild --serve dist\n * await startServer(config, args, screen);\n * // [xBuild] → serve http://localhost:3000\n * ```\n *\n * @see ServerModule\n * @since 3.0.0\n */\n\nexport async function startServer(config: xBuildConfigInterface, args: ArgumentsInterface, screen: Screen): Promise<void> {\n const shouldStartServer = (args.serve ?? false) !== false || config.serve?.start;\n if (!shouldStartServer) return;\n\n const serveDir = config.serve?.dir || args.serve || 'dist';\n const server = new ServerModule(<ServerConfigurationInterface> { ...config.serve }, serveDir);\n server.subscribe(screen.serverEvent.bind(screen));\n\n await server.start();\n}\n\n/**\n * Watches the project, rebuilds on a change, and takes the terminal for the shortcuts.\n *\n * @param buildService - Service the rebuilds run through\n * @param config - Configuration read for its `watch` block, and replaced when its file changes\n * @param args - Parsed command line the run was started with\n * @param screen - Screen the rebuilds are announced on\n * @returns A promise settling once the keys are listened for, at once when no watch was asked for\n *\n * @remarks\n * A run is watched where `--watch` asked for it, and also where a server is serving,\n * since output nobody rebuilds is not worth serving.\n * A change refreshes the file model before anything is rebuilt,\n * so the rebuild reads the files as they now are rather than as they were read the first time.\n * Reloading the TypeScript configuration belongs to the screen rather than to the watch,\n * which puts a rebuild started by a key on the same footing as one started by a change.\n * The configuration file is watched by its own version rather than by its path,\n * so an edit to it is reparsed and reapplied while every other change goes straight to a rebuild.\n * The shortcuts are listened for last, since they take the last row of the terminal,\n * and a run that never reaches here leaves the terminal as it found it.\n *\n * @example\n * ```ts\n * // xBuild --watch\n * await startWatchMode(build, config, args, screen);\n * // [xBuild] ↻ rebuild 2 files changed\n * ```\n *\n * @see WatchService\n * @see startInteractive\n *\n * @since 3.0.0\n */\n\nexport async function startWatchMode(\n buildService: BuildService, config: xBuildConfigInterface, args: ArgumentsInterface, screen: Screen\n): Promise<void> {\n const shouldWatch = args.watch || args.serve !== undefined || config.serve?.start;\n if (!shouldWatch) return;\n\n const files = inject(FilesModel);\n let configVersion = files.touch(args.config!).version;\n\n const watchService = new WatchService(process.cwd(), config.watch);\n watchService.subscribe(async (changedFiles) => {\n files.refreshAll();\n\n if(configVersion !== files.touch(args.config!).version) {\n configVersion = files.touch(args.config!).version;\n const config = await configFileProvider(args.config!);\n applyCommandLineOverrides(config, args);\n buildService.configuration = config;\n }\n\n const count = Object.keys(changedFiles).length;\n await screen.rebuild(`${ count } ${ count === 1 ? 'file' : 'files' } changed`);\n });\n\n await startInteractive(screen);\n}\n\n/**\n * Runs the command line from the banner to the last build.\n *\n * @returns A promise settling once the build has run, or never returning where a check ended the process\n *\n * @remarks\n * The configuration file is found before anything else is parsed, since it is what declares the rest of the flags,\n * and the full parse is written back onto the arguments the provider was handed.\n * The screen is built around the build itself, so a key pressed later starts the same run the command line asked for.\n * A run asking for a type check reports it and leaves from there, since nothing is built for one.\n * The server and the watch are started before the first build,\n * so a rebuild reaches a screen, and the output is served as soon as it is written.\n *\n * @since 3.0.0\n */\n\nasync function main(): Promise<void> {\n console.log(bannerUi());\n\n // Parse configuration\n const argvService = inject(ArgvModule);\n const preConfig = argvService.parseConfigFile(process.argv);\n\n const args = {} as ArgumentsInterface;\n const config = await configFileProvider(preConfig.config, args);\n\n // Configure build\n configureEntryPoints(config, args);\n applyCommandLineOverrides(config, args);\n\n const buildService = new BuildService(config as ConfigurationInterface, args);\n const screen = inject(Screen, executeBuild.bind({}, buildService, args));\n buildService.subscribe(screen.buildEvent.bind(screen));\n\n if (args.typeCheck) {\n screen.diagnostics(await buildService.typeChack(args.build));\n }\n\n // Execute build pipeline\n await startServer(config, args, screen);\n await startWatchMode(buildService, config, args, screen);\n await executeBuild(buildService, args);\n}\n\nawait main();\n","/**\n * Imports\n */\n\nimport process from 'node:process';\nimport { xBuildBaseError } from '@errors/base.error';\nimport { formatStack, getErrorMetadata } from '@providers/stack.provider';\n\n/**\n * Prints whatever reached a global handler the way the framework prints its own errors.\n *\n * @param reason - Error, aggregate error, or any other value that escaped\n *\n * @remarks\n * An {@link xBuildBaseError} already carries its resolved block, so it goes to the console untouched rather than\n * being resolved a second time.\n * Any other `Error` is resolved here with the framework and native frames kept,\n * since a value that got this far offers no other clue about where it came from.\n * An {@link AggregateError} is announced once and then unwrapped, each of its errors going through the same choice.\n * A value that is not an error is printed as it stands.\n *\n * @example\n * ```ts\n * formatErrors(new Error('connect ECONNREFUSED')); // heading, snippet and resolved trace\n * formatErrors(new xBuildError('bad config')); // the block the error already carries\n * formatErrors('not an error at all'); // 'not an error at all'\n * ```\n *\n * @see formatStack\n * @see xBuildBaseError\n * @see getErrorMetadata\n *\n * @since 2.0.0\n */\n\nexport function formatErrors(reason: unknown): void {\n if (reason instanceof AggregateError) {\n console.error('AggregateError:', reason.message);\n for (const err of reason.errors) {\n if (err instanceof Error && !(err instanceof xBuildBaseError)) {\n const metadata = getErrorMetadata(err, { withFrameworkFrames: true, withNativeFrames: true });\n console.error(formatStack(metadata, err.name, err.message));\n } else {\n console.error(err);\n }\n }\n\n return;\n }\n\n if (reason instanceof Error && !(reason instanceof xBuildBaseError)) {\n const metadata = getErrorMetadata(reason, { withFrameworkFrames: true, withNativeFrames: true });\n console.error(formatStack(metadata, reason.name, reason.message));\n } else {\n console.error(reason);\n }\n}\n\n/**\n * Prints an exception that escaped every `try` and leaves the process with exit code `2`.\n *\n * @remarks\n * Registered as a side effect of importing this file, which is why the CLI entry point imports it on its first line -\n * anything thrown while the later imports evaluate is already covered.\n * Node leaves the process in an undefined state once an exception gets this far, so the handler prints and exits\n * instead of letting the build carry on.\n *\n * @example\n * ```ts\n * import '@errors/uncaught.error';\n * throw new Error('unreachable state'); // the resolved block, then exit code 2\n * ```\n *\n * @see formatErrors\n * @see {@link https://nodejs.org/api/process.html#event-uncaughtexception | process 'uncaughtException'}\n *\n * @since 2.0.0\n */\n\nprocess.on('uncaughtException', (reason: unknown) => {\n formatErrors(reason);\n process.exit(2);\n});\n\n/**\n * Prints a rejection nobody awaited and leaves the process with exit code `2`.\n *\n * @remarks\n * Registered alongside the exception handler, since an unawaited rejection ends the build just as surely and would\n * otherwise print Node's own warning without any source resolution.\n * The exit code matches the one used for uncaught exceptions: both mean the build died on an unhandled failure, and\n * nothing downstream needs to tell them apart.\n *\n * @example\n * ```ts\n * import '@errors/uncaught.error';\n * Promise.reject(new Error('write after end')); // the resolved block, then exit code 2\n * ```\n *\n * @see formatErrors\n * @see {@link https://nodejs.org/api/process.html#event-unhandledrejection | process 'unhandledRejection'}\n *\n * @since 2.0.0\n */\n\nprocess.on('unhandledRejection', (reason: unknown) => {\n formatErrors(reason);\n process.exit(3);\n});\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { PartialMessage } from 'esbuild';\nimport type { SourceService } from '@remotex-labs/xmap';\nimport type { ParsedStackTraceInterface } from '@remotex-labs/xmap/parser.component';\nimport type { StackTraceInterface, ResolveMetadataInterface } from '@providers/interfaces/stack-provider.interface';\n\n/**\n * Imports\n */\n\nimport { inject } from '@remotex-labs/xinject';\nimport { FilesModel } from '@models/files.model';\nimport { resolveError } from '@remotex-labs/xmap';\nimport { xterm } from '@remotex-labs/xansi/xterm.component';\nimport { FrameworkService } from '@services/framework.service';\nimport { parseErrorStack } from '@remotex-labs/xmap/parser.component';\nimport { formatErrorCode } from '@remotex-labs/xmap/formatter.component';\nimport { highlightCode } from '@remotex-labs/xmap/highlighter.component';\n\n/**\n * Returns a source resolver for a file, from its source map when one is registered and from its cached text otherwise.\n *\n * @param fileName - Path of the file a stack frame points at, relative or absolute\n * @returns The resolver for that file, or `null` when the file has neither a map nor cached text\n *\n * @remarks\n * A registered map wins since it resolves back to the authored file rather than to the emitted one.\n * Without a map the cached text stands in through a minimal resolver that slices the surrounding lines as its\n * code window, so an unmapped file still prints a snippet.\n * That window spans three lines either side unless the caller asks for a different span and is clamped to the\n * bounds of the file.\n * `startLine` and `endLine` come back as 1-based line numbers rather than as indexes into the text,\n * which is how {@link formatErrorCode} reads them, so a printed number labels the line it belongs to.\n * The line passes through as it arrived, while the column comes back one higher than it was given.\n *\n * @example\n * ```ts\n * getSource('dist/index.js'); // SourceService - the registered map\n * getSource('src/index.ts')?.getPositionWithCode(10, 4); // line 10, column 5, lines 7-13 as code\n * getSource('missing.ts'); // null\n * ```\n *\n * @see SourceService\n * @see FilesModel.touch\n * @see FrameworkService.getSourceMap\n *\n * @since 2.0.0\n */\n\nexport function getSource(fileName: string = ''): SourceService | null {\n const framework = inject(FrameworkService);\n const mapped = framework.getSourceMap(fileName);\n if (mapped) return mapped;\n\n const snapshot = inject(FilesModel).touch(fileName);\n const code = snapshot.snapshot?.text;\n\n if (!snapshot || !code) return null;\n const lines = code.split('\\n');\n\n return {\n getPositionWithCode: (line, column, _bias, options) => {\n const after = options?.linesAfter ?? 3;\n const before = options?.linesBefore ?? 3;\n\n // both bounds are 1-based line numbers, so only the slice start converts to an index\n const startLine = Math.max(line - before, 1);\n const endLine = Math.min(line + after, lines.length);\n\n return {\n line,\n name: null,\n code: lines.slice(startLine - 1, endLine).join('\\n'),\n source: fileName,\n column: column,\n endLine,\n startLine,\n sourceRoot: null,\n sourceIndex: -1,\n generatedLine: -1,\n generatedColumn: -1\n };\n }\n } as SourceService;\n}\n\n/**\n * Brings an error and an esbuild message to the same shape - a name, a message, and a list of frames.\n *\n * @param raw - Thrown error, or the message esbuild reported for a failed build\n * @returns The parsed trace, with an empty frame list when there is nothing to point at\n *\n * @remarks\n * An `Error` is parsed from its own stack text, whether it arrives on its own or wrapped as the `detail` of an\n * esbuild message.\n * A plain esbuild message carries no stack, so its location becomes the single frame of the trace, flagged as\n * ordinary code: not eval, not async, not native, and not a constructor call.\n * A message without a location resolves to no frames at all, which leaves the caller with the text alone.\n *\n * @example\n * ```ts\n * getErrorStack(new Error('boom')).stack.length; // 12 - frames parsed from error.stack\n *\n * getErrorStack({ text: 'Unexpected token', location: { file: 'src/index.ts', line: 4, column: 2 } }).stack;\n * // [ { source: '@src/index.ts', fileName: 'src/index.ts', line: 4, column: 2, ... } ]\n *\n * getErrorStack({ text: 'Could not resolve module' }).stack; // []\n * ```\n *\n * @see parseErrorStack\n * @see ParsedStackTraceInterface\n *\n * @since 2.0.0\n */\n\nexport function getErrorStack(raw: Partial<PartialMessage> | Error): ParsedStackTraceInterface {\n if (raw instanceof Error) return parseErrorStack(raw);\n if (raw.detail instanceof Error) return parseErrorStack(raw.detail);\n\n if (!raw.location) {\n return { stack: [], name: 'esBuildMessage', message: raw.text ?? '', rawStack: '' };\n }\n\n return {\n name: 'esBuildMessage',\n message: raw.text ?? '',\n rawStack: '',\n stack: [\n {\n source: `@${ raw.location.file }`,\n line: raw.location.line,\n column: raw.location.column || 1,\n fileName: raw.location.file,\n eval: false,\n async: false,\n native: false,\n constructor: false\n }\n ]\n };\n}\n\n/**\n * Resolves an error back to its authored sources and picks the code window to print with it.\n *\n * @param raw - Thrown error, or the message esbuild reported for a failed build\n * @param options - Frame selection and code window size, as {@link resolveError} takes them\n * @param verbose - Whether native frames stay in the resolved stack\n * @returns The resolved trace, carrying `formatCode` when a frame supplied a code window\n *\n * @remarks\n * Every frame resolves through {@link getSource}, so a mapped frame points at the authored file and an unmapped\n * one falls back to the cached text of the emitted file.\n * `verbose` and `withFrameworkFrames` each admit native frames to the stack, while `withFrameworkFrames` alone\n * decides whether a framework frame may supply the code window.\n * The window is taken from the first frame that carries code, highlighted and marked at that position, and is\n * left unset when no frame carries any - a resolve against sources that are gone prints as a bare trace.\n *\n * @example\n * ```ts\n * const metadata = getErrorMetadata(error, { linesBefore: 2, linesAfter: 2 });\n * metadata.stack[0].format; // 'at run src/index.ts:12:8'\n * metadata.formatCode; // lines 10-14, highlighted, with column 8 marked in bright pink\n * ```\n *\n * @see resolveError\n * @see getErrorStack\n * @see StackTraceInterface\n * @see ResolveMetadataInterface\n *\n * @since 3.0.0\n */\n\nexport function getErrorMetadata(raw: PartialMessage | Error, options?: StackTraceInterface, verbose: boolean = false): ResolveMetadataInterface {\n const framework = inject(FrameworkService);\n const parsed = getErrorStack(raw);\n const resolved: ResolveMetadataInterface = resolveError(parsed, {\n ...options,\n withNativeFrames: verbose || (options?.withFrameworkFrames ?? false),\n getSource(path: string): SourceService | null {\n return getSource(path);\n }\n });\n\n resolved.stack.filter(frame => {\n if (!(options?.withFrameworkFrames ?? false) && framework.isFrameworkFile(frame)) return false;\n if(!resolved.formatCode && frame.code) {\n resolved.formatCode = formatErrorCode(\n {\n code: highlightCode(frame.code),\n line: frame.line ?? 1,\n column: frame.column ?? 1,\n startLine: frame.stratLine ?? 1\n },\n { color: xterm.brightPink }\n );\n }\n });\n\n return resolved;\n}\n\n/**\n * Renders resolved metadata as the block that gets printed to the terminal.\n *\n * @param metadata - Resolved trace, as {@link getErrorMetadata} returns it\n * @param name - Name to head the block with, such as `TypeError` or `esBuildMessage`\n * @param message - Message to head the block with\n * @param notes - Extra lines esbuild attached to the message, printed in gray under the heading\n * @returns The block, ready to write as-is\n *\n * @remarks\n * The heading is always written, the code window and the trace only when the metadata holds them, so an error\n * resolved against missing sources still prints as a single readable line.\n * Coloring of the window and of each frame is left as {@link getErrorMetadata} produced it - nothing here is\n * highlighted a second time.\n *\n * @example\n * ```ts\n * formatStack(metadata, 'TypeError', 'x is not a function');\n * //\n * // TypeError: x is not a function\n * //\n * // 11 | x();\n * // | ^\n * //\n * // Enhanced Stack Trace:\n * // at run src/index.ts:11:2\n * ```\n *\n * @see xterm\n * @see getErrorMetadata\n * @see ResolveMetadataInterface\n *\n * @since 2.0.0\n */\n\nexport function formatStack(metadata: ResolveMetadataInterface, name: string, message: string, notes: PartialMessage['notes'] = []): string {\n const parts = [ `\\n${ name }: ${ xterm.lightCoral(message) }` ];\n for (const note of notes ?? []) {\n if(note.text) parts.push('\\n ' + xterm.gray(note.text));\n }\n\n if (metadata.formatCode) parts.push(`\\n\\n${ metadata.formatCode }`);\n if (metadata.stack.length) {\n parts.push(`\\n\\nEnhanced Stack Trace:\\n ${ metadata.stack.map(stack => stack.format).join('\\n ') }\\n`);\n }\n\n return parts.join('');\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { Stats } from 'fs';\nimport type { TextChangeRange } from 'typescript';\nimport type { FileSnapshotInterface, ScriptSnapshotType } from './interfaces/files-model.interface';\n\n/**\n * Imports\n */\n\nimport { readFileSync, statSync } from 'fs';\nimport { resolve } from '@remotex-labs/xmap';\nimport { Injectable } from '@remotex-labs/xinject';\n\n/**\n * In-memory cache of file contents keyed by resolved absolute path.\n *\n * @remarks\n * Backs the TypeScript language service, which asks for a script version on every request and only reparses when\n * that version changes.\n * Content is read once and re-read only when the modification time moves,\n * so repeated lookups of an unchanged file cost a map read.\n * Reach for {@link touch} when any cached content will do,\n * {@link refresh} when the file may have changed on disk or when a watcher already carries its `Stats`,\n * and {@link refreshAll} to catch what the watcher failed to report.\n *\n * @example\n * ```ts\n * const model = inject(FilesModel);\n *\n * model.touch('src/index.ts').version; // 1 - read from disk\n * model.touch('src/index.ts').version; // 1 - served from the cache\n * model.refresh('src/index.ts').version; // 2 - the file changed on disk\n * model.clear(); // every entry dropped\n * ```\n *\n * @see FileSnapshotInterface\n * @since 2.0.0\n */\n\n@Injectable({\n scope: 'singleton'\n})\nexport class FilesModel {\n /**\n * Memoized mapping from an input path to its resolved absolute form.\n *\n * @remarks\n * Kept apart from {@link cache} because several input paths can resolve to the same absolute path,\n * and resolution is repeated far more often than content changes.\n *\n * @since 3.0.0\n */\n\n private readonly resolved = new Map<string, string>();\n\n /**\n * Entries keyed by resolved absolute path.\n *\n * @remarks\n * Holds one {@link FileSnapshotInterface} per tracked path, including paths that carry no readable file.\n *\n * @since 3.0.0\n */\n\n private readonly cache = new Map<string, FileSnapshotInterface>();\n\n /**\n * Drops every cached entry and every memoized path.\n *\n * @remarks\n * Leaves the model in its initial state, so the next request re-reads from disk and restarts versions at `1`.\n *\n * @example\n * ```ts\n * model.touch('src/index.ts');\n * model.clear();\n * model.getSnapshot('src/index.ts'); // undefined\n * ```\n *\n * @since 2.0.0\n */\n\n clear(): void {\n this.cache.clear();\n this.resolved.clear();\n }\n\n /**\n * Returns the cached entry for a path without touching the filesystem.\n *\n * @param path - Filesystem path, relative or absolute\n * @returns The cached entry, or `undefined` when the path was never tracked\n *\n * @remarks\n * A pure cache read: it never reads or stats the file, so an untracked path stays untracked.\n * Use {@link touch} to track the path instead.\n *\n * @example\n * ```ts\n * model.getSnapshot('src/index.ts'); // undefined - never tracked\n * model.touch('src/index.ts');\n * model.getSnapshot('src/index.ts'); // { mtimeMs: 1754000000000, version: 1, snapshot: { ... } }\n * ```\n *\n * @see touch\n * @since 2.0.0\n */\n\n getSnapshot(path: string): FileSnapshotInterface | undefined {\n return this.cache.get(this.resolve(path));\n }\n\n /**\n * Returns the entry for a path, reading the file when it is not tracked yet.\n *\n * @param path - Filesystem path, relative or absolute\n * @param encoding - Encoding used when the file is read, defaulting to `utf-8`\n * @returns The entry for the path, cached or newly created\n *\n * @remarks\n * A tracked path is returned as it stands, without a `stat` call, however stale it may be.\n * Use {@link refresh} when the file may have changed since it was cached.\n *\n * @example\n * ```ts\n * model.touch('src/index.ts').version; // 1 - read from disk\n * model.touch('src/index.ts').version; // 1 - served from the cache, no stat\n * ```\n *\n * @see refresh\n * @since 3.0.0\n */\n\n touch(path: string, encoding?: BufferEncoding): FileSnapshotInterface {\n const target = this.resolve(path);\n\n return this.cache.get(target) ?? this.sync(target, this.stat(target), encoding);\n }\n\n /**\n * Synchronizes a path with the filesystem and returns its entry.\n *\n * @param path - Filesystem path, relative or absolute\n * @param stats - Already obtained `Stats` for the path, sparing a `stat` call\n * @param encoding - Encoding used when the file is read, defaulting to `utf-8`\n * @returns The entry for the path, rebuilt only when the file actually changed\n *\n * @remarks\n * The content is re-read when the modification time differs from the cached one,\n * so calling this on an unchanged file leaves its version intact.\n * A path that is missing or is not a regular file yields an entry with an `undefined` snapshot.\n *\n * @example\n * ```ts\n * model.touch('src/index.ts').version; // 1\n * model.refresh('src/index.ts').version; // 1 - mtime unchanged\n * model.refresh('src/index.ts').version; // 2 - the file was written to\n * ```\n *\n * @see touch\n * @since 3.0.0\n */\n\n refresh(path: string, stats?: Stats, encoding?: BufferEncoding): FileSnapshotInterface {\n const target = this.resolve(path);\n\n return this.sync(target, stats ?? this.stat(target), encoding);\n }\n\n /**\n * Synchronizes a set of paths, or every path already tracked.\n *\n * @param paths - Paths to synchronize, defaulting to everything in the cache\n *\n * @remarks\n * The safety net under file watching: a change that goes unreported leaves an entry stale with nothing to\n * announce it - the version never moves,\n * so the language service is never told to reparse, and the build keeps compiling text that is no longer on disk.\n * Sweeping asks the filesystem rather than the watcher,\n * so a missed event costs a needless rebuild at worst rather than a wrong one.\n * Every path gets a `stat`, and only the ones whose time moved are read again.\n * The keys it walks are already resolved,\n * so re-synchronizing them writes back over the same keys and cannot extend the walk.\n * A tracked path that is still missing keeps the entry and the version it had,\n * so repeated sweeps do not inflate the versions of files that were deleted.\n *\n * @example\n * ```ts\n * model.refreshAll([ 'src/index.ts' ]); // that one path\n * model.refreshAll(); // every tracked path, re-read where it changed\n * ```\n *\n * @see refresh\n * @since 3.0.0\n */\n\n refreshAll(paths?: Array<string>): void {\n const pathList = paths ?? this.cache.keys();\n for (const path of pathList) {\n this.refresh(path);\n }\n }\n\n /**\n * Normalizes a path to its absolute form.\n *\n * @param path - Filesystem path, relative or absolute\n * @returns Absolute path with forward slashes\n *\n * @remarks\n * The result is memoized per input string, since the same paths are resolved on every cache lookup.\n *\n * @example\n * ```ts\n * model.resolve('src/index.ts'); // 'D:/project/src/index.ts'\n * ```\n *\n * @since 2.0.0\n */\n\n resolve(path: string): string {\n let target = this.resolved.get(path);\n if (target === undefined) this.resolved.set(path, target = resolve(path));\n\n return target;\n }\n\n /**\n * Brings the entry for a resolved path in line with the given filesystem state.\n *\n * @param target - Resolved absolute path\n * @param info - `Stats` for the path, or `undefined` when it does not exist\n * @param encoding - Encoding used when the file is read, defaulting to `utf-8`\n * @returns The entry for the path, reused when nothing changed\n *\n * @remarks\n * A path that is not a regular file keeps its already empty entry untouched,\n * so repeated events for a missing path do not inflate its version.\n * A file whose modification time matches the cached one is left as is, and the content is not read.\n *\n * @since 3.0.0\n */\n\n private sync(target: string, info: Stats | undefined, encoding: BufferEncoding = 'utf-8'): FileSnapshotInterface {\n const entry = this.cache.get(target);\n\n if (!info?.isFile()) {\n if (entry && !entry.snapshot) return entry;\n\n return this.store(target, { mtimeMs: 0, snapshot: undefined, version: (entry?.version ?? 0) + 1 });\n }\n\n if (entry?.mtimeMs === info.mtimeMs) return entry;\n\n return this.store(target, {\n mtimeMs: info.mtimeMs,\n version: (entry?.version ?? 0) + 1,\n snapshot: this.snapshot(readFileSync(target, encoding))\n });\n }\n\n /**\n * Computes the span that differs between two versions of a text.\n *\n * @param oldText - Text the language service last parsed\n * @param newText - Text that replaces it\n * @returns The replaced span in `oldText` together with the length of its replacement\n *\n * @remarks\n * Narrows the change by trimming the shared prefix and the shared suffix,\n * which lets the language service reuse the untouched parts of the syntax tree.\n * The suffix scan stops at the prefix boundary, so the two never overlap on a text that shrank.\n *\n * @since 3.0.0\n */\n\n private changeRange(oldText: string, newText: string): TextChangeRange {\n const oldLength = oldText.length;\n const newLength = newText.length;\n const max = Math.min(oldLength, newLength);\n\n let prefix = 0;\n while (prefix < max && oldText.charCodeAt(prefix) === newText.charCodeAt(prefix)) prefix++;\n\n let suffix = 0;\n while (suffix < max - prefix && oldText.charCodeAt(oldLength - 1 - suffix) === newText.charCodeAt(newLength - 1 - suffix)) suffix++;\n\n return {\n span: { start: prefix, length: oldLength - prefix - suffix },\n newLength: newLength - prefix - suffix\n };\n }\n\n /**\n * Wraps file content in a script snapshot.\n *\n * @param text - Content read from disk\n * @returns A snapshot exposing the content both as `text` and through the `IScriptSnapshot` methods\n *\n * @remarks\n * `getChangeRange` closes over this text as the new version and delegates to {@link changeRange},\n * so the language service can diff against any earlier snapshot it still holds.\n *\n * @since 3.0.0\n */\n\n private snapshot(text: string): ScriptSnapshotType {\n return {\n text,\n getText: (start, end): string => text.slice(start, end),\n getLength: (): number => text.length,\n getChangeRange: (previous):\n TextChangeRange => this.changeRange(previous.getText(0, previous.getLength()), text)\n };\n }\n\n /**\n * Writes an entry to the cache and hands it back.\n *\n * @param target - Resolved absolute path\n * @param entry - Entry to store under that path\n * @returns The stored entry\n *\n * @remarks\n * Exists so {@link sync} can store and return in a single expression.\n *\n * @since 3.0.0\n */\n\n private store(target: string, entry: FileSnapshotInterface): FileSnapshotInterface {\n this.cache.set(target, entry);\n\n return entry;\n }\n\n /**\n * Reads the filesystem state of a path.\n *\n * @param path - Resolved absolute path\n * @returns The `Stats` for the path, or `undefined` when it does not exist\n *\n * @remarks\n * A missing path is an ordinary outcome here rather than a failure, so the throwing form is disabled.\n *\n * @since 3.0.0\n */\n\n private stat(path: string): Stats | undefined {\n return statSync(path, { throwIfNoEntry: false });\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { PositionInterface, FormatStackFrameInterface } from '@remotex-labs/xmap';\n\n/**\n * Imports\n */\n\nimport { cwd } from 'process';\nimport { readFileSync } from 'fs';\nimport { FilesModel } from '@models/files.model';\nimport { inject, Injectable } from '@remotex-labs/xinject';\nimport { normalize, SourceService } from '@remotex-labs/xmap';\n\n/**\n * Matches a path that belongs to the framework rather than to the project being built.\n *\n * @remarks\n * Case-insensitive, since the same file surfaces as `xBuild` from a checkout and as `xbuild` from `node_modules`.\n * The lookahead spares a project's own `xbuild.config`, which names the framework without being part of it.\n *\n * @since 3.0.0\n */\n\nconst FRAMEWORK_PATH_REGEX = /xbuild(?!\\.config)/i;\n\n/**\n * Matches a source map whose `mappings` field is empty.\n *\n * @remarks\n * Such a map resolves nothing,\n * so keeping it would cost a lookup on every frame and answer with the generated position anyway.\n * Kept at module level so the pattern is compiled once rather than on every registration.\n *\n * @since 3.0.0\n */\n\nconst EMPTY_MAPPINGS_REGEX = /\"mappings\"\\s*:\\s*\"\"/;\n\n/**\n * Holds the framework's own paths and the source maps a stack trace is resolved through.\n *\n * @remarks\n * Two jobs in service of one thing - reporting an error against the source a reader recognizes.\n * It tells framework frames apart from a project's own,\n * and it hands out the {@link SourceService} that maps a generated position back to its source.\n * Maps arrive either as text through {@link addSourceMap} or read from a `.map` companion through\n * {@link loadSourceMap}, and both are keyed by resolved path, so the same file registered under a relative and an\n * absolute path is parsed once.\n * The framework's own map is loaded on construction, which is what lets an error thrown inside the build be reported\n * against its source.\n * Registered as a singleton, so every consumer shares one registry.\n *\n * @example\n * ```ts\n * const framework = inject(FrameworkService);\n *\n * framework.projectRoot; // 'D:/app' - where the build was started\n * framework.getSourceMap(framework.frameworkFile); // the framework's own SourceService\n * framework.isFrameworkFile({ source: 'D:/app/src/index.ts' }); // false - a project file\n * ```\n *\n * @see SourceService\n * @since 2.0.0\n */\n\n@Injectable({\n scope: 'singleton'\n})\nexport class FrameworkService {\n /**\n * Absolute path of the framework file this service was loaded from.\n *\n * @remarks\n * Normalized like {@link frameworkRoot} and {@link projectRoot},\n * so all three compare and join the same way whatever the platform.\n *\n * @example\n * ```ts\n * framework.frameworkFile; // 'D:/app/node_modules/@remotex-labs/xbuild/dist/index.js'\n * ```\n *\n * @since 3.0.0\n */\n\n readonly frameworkFile: string;\n\n /**\n * Absolute path of the directory the framework was distributed in.\n *\n * @remarks\n * Where anything shipped beside the build is found, the server's certificates among them.\n *\n * @example\n * ```ts\n * framework.frameworkRoot; // 'D:/app/node_modules/@remotex-labs/xbuild/dist'\n * ```\n *\n * @since 3.0.0\n */\n\n readonly frameworkRoot: string;\n\n /**\n * Absolute path of the directory the build was started from.\n *\n * @remarks\n * The user's project root rather than the framework's,\n * so it is what a path is made relative to when a frame is printed.\n *\n * @example\n * ```ts\n * framework.projectRoot; // 'D:/app'\n * ```\n *\n * @since 3.0.0\n */\n\n readonly projectRoot: string;\n\n /**\n * Shared file cache, held on the class so {@link resolve} needs no instance.\n *\n * @remarks\n * What is wanted here is the memo it keeps rather than the snapshots: resolving through it is what keeps this\n * registry, the file cache, and everything else keyed by path agreeing on what one path is.\n * Claimed by the first {@link resolve} rather than by a static initializer, since an initializer would run while\n * this module is being imported, and importing it must not reach the container.\n *\n * @see FilesModel\n * @since 3.0.0\n */\n\n private static files?: FilesModel;\n\n /**\n * Source maps keyed by the resolved path of the file each one describes.\n *\n * @since 2.0.0\n */\n\n private readonly sourceMaps = new Map<string, SourceService>();\n\n /**\n * Captures the framework's paths and loads its own source map.\n *\n * @throws Error - When the framework ships without a readable `.map` companion\n *\n * @remarks\n * A framework shipped without its map is a broken build rather than a supported one,\n * so the read failure surfaces here instead of being swallowed.\n *\n * @example\n * ```ts\n * const framework = new FrameworkService();\n * framework.getSourceMap(framework.frameworkFile); // SourceService\n * ```\n *\n * @see loadSourceMap\n * @since 2.0.0\n */\n\n constructor() {\n this.projectRoot = normalize(cwd());\n this.frameworkFile = normalize(import.meta.filename);\n this.frameworkRoot = normalize(import.meta.dirname);\n\n this.loadSourceMap(this.frameworkFile);\n }\n\n /**\n * Normalizes a path to the absolute form every cache here is keyed by.\n *\n * @param path - Filesystem path, relative or absolute\n * @returns Absolute path with forward slashes\n *\n * @remarks\n * Static so that a caller with no framework service in hand can still key a path the way this package does, which\n * is what keeps entry-point names, source-map keys, and file entries from disagreeing about one file.\n * The first call claims the file cache, and every later call finds it already claimed, so the container is reached\n * only once something asks for a path rather than when this module is imported.\n * Resolution is memoized by the cache behind it, so resolving the same path again costs a lookup.\n *\n * @example\n * ```ts\n * FrameworkService.resolve('src/index.ts'); // 'D:/app/src/index.ts'\n * ```\n *\n * @see FilesModel\n * @since 3.0.0\n */\n\n static resolve(path: string): string {\n return (FrameworkService.files ??= inject(FilesModel)).resolve(path);\n }\n\n /**\n * Reports whether a position belongs to the framework rather than to the project being built.\n *\n * @param position - Position or stack frame to judge, as the source map resolver reports it\n * @returns `true` when the position comes from framework code\n *\n * @remarks\n * The judgment is made on the path, matched case-insensitively, since the same file surfaces as `xBuild` from a\n * checkout and as `xbuild` from `node_modules`.\n * A project's own `xbuild.config` names the framework without being part of it, so it is excluded by name.\n * The source root is consulted only when the source itself does not settle the question.\n *\n * @example\n * ```ts\n * framework.isFrameworkFile({ source: 'D:/app/node_modules/xbuild/dist/index.js' }); // true\n * framework.isFrameworkFile({ source: 'D:/app/xbuild.config.ts' }); // false\n * framework.isFrameworkFile({ source: 'D:/app/src/index.ts' }); // false\n * ```\n *\n * @see PositionInterface\n * @see FormatStackFrameInterface\n *\n * @since 2.2.5\n */\n\n isFrameworkFile(position: PositionInterface | FormatStackFrameInterface): boolean {\n return FRAMEWORK_PATH_REGEX.test(position.source ?? '') || FRAMEWORK_PATH_REGEX.test(position.sourceRoot ?? '');\n }\n\n /**\n * Returns the source map registered for a file.\n *\n * @param path - Path of the file, relative or absolute\n * @returns The source map of that file, or `undefined` when none was registered\n *\n * @remarks\n * A pure registry read: a file that was never registered stays unregistered, since nothing here reaches the disk.\n * Use {@link loadSourceMap} to register one.\n *\n * @example\n * ```ts\n * framework.getSourceMap('dist/index.js'); // undefined - never registered\n * framework.loadSourceMap('dist/index.js');\n * framework.getSourceMap('dist/index.js'); // SourceService\n * ```\n *\n * @see SourceService\n * @since 2.0.0\n */\n\n getSourceMap(path: string): SourceService | undefined {\n return this.sourceMaps.get(FrameworkService.resolve(path));\n }\n\n /**\n * Registers a source map from its text.\n *\n * @param path - Path of the file the map describes, relative or absolute\n * @param source - Raw source map content\n * @param force - Whether a map the file already carries is replaced rather than kept\n *\n * @throws Error - When the content is not a source map the resolver can parse\n *\n * @remarks\n * A file that already carries a map keeps it, so the first registration wins, and a later call costs only a lookup.\n * A caller that knows the file was written again says so with `force`, which parses the map it was handed and puts\n * it in place of the one registered before: a watch rebuilding a file leaves the map registered for it describing\n * text that is no longer there, and a stale map resolves a frame to the wrong line rather than to none.\n * A map with empty mappings is dropped rather than registered, resolving through such a map being the same as not\n * resolving at all, and it leaves what was registered before it in place rather than clearing it.\n *\n * @example\n * ```ts\n * framework.addSourceMap('dist/index.js', readFileSync('dist/index.js.map', 'utf-8'));\n * framework.getSourceMap('dist/index.js'); // SourceService\n *\n * framework.addSourceMap('dist/index.js', rebuilt); // kept - the first registration wins\n * framework.addSourceMap('dist/index.js', rebuilt, true); // replaced - the file was written again\n * ```\n *\n * @see loadSourceMap\n * @since 3.0.0\n */\n\n addSourceMap(path: string, source: string, force: boolean = false): void {\n const key = FrameworkService.resolve(path);\n if (!force && this.sourceMaps.has(key)) return;\n\n this.register(key, source);\n }\n\n /**\n * Registers the source map a file's `.map` companion carries.\n *\n * @param path - Path of the generated file, relative or absolute\n *\n * @throws Error - When the companion cannot be read or does not parse\n *\n * @remarks\n * The companion is looked for beside the file, as `<path>.map`, which is where every file this toolchain emits\n * carries its map.\n * A file that already carries a map is left alone before the disk is touched,\n * so repeating the call on a tracked file costs only a lookup.\n * An empty path is ignored outright,\n * and a companion that parses but maps nothing registers no map and raises nothing.\n *\n * @example\n * ```ts\n * framework.loadSourceMap('dist/index.js'); // reads dist/index.js.map\n * framework.loadSourceMap('dist/index.js'); // cached - no read\n * ```\n *\n * @see addSourceMap\n * @since 3.0.0\n */\n\n loadSourceMap(path: string): void {\n if (!path) return;\n\n const key = FrameworkService.resolve(path);\n if (this.sourceMaps.has(key)) return;\n\n let source: string;\n try {\n source = readFileSync(`${ key }.map`, 'utf-8');\n } catch (error) {\n throw FrameworkService.failure(key, error);\n }\n\n this.register(key, source);\n }\n\n /**\n * Builds the error reported when a source map cannot be registered.\n *\n * @param key - Resolved path of the file the map describes\n * @param error - Failure raised while reading or parsing it\n * @returns The error to throw, naming the file and carrying the original reason\n *\n * @remarks\n * The reading and the parsing halves fail in the same way as far as a caller is concerned,\n * so both report the file first and the reason after it.\n *\n * @since 3.0.0\n */\n\n private static failure(key: string, error: unknown): Error {\n return new Error(\n `Failed to load source map for: ${ key }\\n${ error instanceof Error ? error.message : String(error) }`\n );\n }\n\n /**\n * Parses a source map and files it under a resolved path.\n *\n * @param key - Resolved path of the file the map describes\n * @param source - Raw source map content\n *\n * @throws Error - When the content is not a source map the resolver can parse\n *\n * @remarks\n * The single point where a map enters the registry,\n * so both entry points resolve their path once and skip an already registered file before reaching here.\n * A map with empty mappings is dropped rather than registered, since resolving through such a map answers with\n * the position it was given.\n *\n * @since 3.0.0\n */\n\n private register(key: string, source: string): void {\n if (EMPTY_MAPPINGS_REGEX.test(source)) return;\n\n try {\n this.sourceMaps.set(key, new SourceService(source, key));\n } catch (error) {\n throw FrameworkService.failure(key, error);\n }\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { StackTraceInterface, ResolveMetadataInterface } from '@providers/interfaces/stack-provider.interface';\n\n/**\n * Imports\n */\n\nimport { formatStack, getErrorMetadata } from '@providers/stack.provider';\n\n/**\n * Base class for errors that print as authored code rather than as the stack of the emitted bundle.\n *\n * @remarks\n * A subclass gets nothing extra until it calls {@link reformatStack}, which resolves the captured stack through the\n * source maps and keeps both the frames as data and the block to print.\n * Node writes that block whenever the error reaches the console, so a caught error names the original file and line\n * and carries a highlighted snippet of the surrounding code.\n * Extend this class when callers need an error type of their own to branch on.\n * Throw {@link xBuildError} when a general framework error will do.\n *\n * @example\n * ```ts\n * class ValidationError extends xBuildBaseError {\n * constructor(message: string) {\n * super(message, 'ValidationError');\n * this.reformatStack(this, { withFrameworkFrames: false });\n * }\n * }\n *\n * const error = new ValidationError('email is not an address');\n * error.metadata?.stack[0].format; // 'at validate src/validator.ts:15:3'\n * console.error(error); // the heading, the snippet, and the resolved trace\n * ```\n *\n * @see formatStack\n * @see xBuildError\n * @see getErrorMetadata\n * @see StackTraceInterface\n * @see ResolveMetadataInterface\n *\n * @since 2.0.0\n */\n\nexport abstract class xBuildBaseError extends Error {\n /**\n * Resolved stack metadata, as {@link getErrorMetadata} produced it.\n *\n * @remarks\n * Undefined until {@link reformatStack} runs, and replaced whole by every later call.\n * Reachable read-only through {@link metadata} for callers that want the frames as data rather than as text.\n *\n * @see ResolveMetadataInterface\n * @since 2.0.0\n */\n\n protected errorMetadata: ResolveMetadataInterface | undefined;\n\n /**\n * The block to print for this error, as {@link formatStack} produced it.\n *\n * @remarks\n * Undefined until {@link reformatStack} runs, which leaves the native stack as the only thing to print.\n * Coloring and highlighting are already applied, so the string is written out as it stands.\n *\n * @see formatStack\n * @since 2.0.0\n */\n\n protected formattedStack: string | undefined;\n\n /**\n * Creates the error and captures its raw stack, leaving the resolving to the subclass.\n *\n * @param message - Message describing what went wrong\n * @param name - Name the error reports itself under\n *\n * @remarks\n * The prototype is restored from `new.target`, so `instanceof` answers for the subclass and not only for `Error`,\n * which a transpiled subclass would otherwise lose.\n * The captured stack starts at the caller rather than inside this constructor, and stays the raw one until the\n * subclass calls {@link reformatStack} - passing a name here only heads the block, it resolves nothing.\n *\n * @since 2.0.0\n */\n\n protected constructor(message: string, name: string = 'xBuildBaseError') {\n super(message);\n\n // Ensure a correct prototype chain (important for `instanceof`)\n Object.setPrototypeOf(this, new.target.prototype);\n this.name = name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n /**\n * The resolved stack metadata of this error.\n *\n * @returns The metadata, or `undefined` when {@link reformatStack} has not run\n *\n * @remarks\n * The frames as data, for a logger or a reporting service that renders them itself instead of printing the block.\n *\n * @example\n * ```ts\n * error.metadata; // undefined - the subclass never reformatted\n * error.metadata?.stack.length; // 4 - after reformatStack\n * error.metadata?.formatCode; // the highlighted snippet, when a frame carried code\n * ```\n *\n * @see ResolveMetadataInterface\n * @since 2.0.0\n */\n\n get metadata(): ResolveMetadataInterface | undefined {\n return this.errorMetadata;\n }\n\n /**\n * Renders the error for `console.log`, `console.error` and `util.inspect`.\n *\n * @returns The resolved block when there is one, and the native stack otherwise\n *\n * @remarks\n * Node calls this in place of printing the error's own fields, which is what puts the resolved trace on the\n * terminal without the caller having to format anything.\n * An empty block counts as no block, so an error whose sources could not be resolved still prints its native\n * stack rather than nothing.\n *\n * @example\n * ```ts\n * console.error(error); // 'ValidationError: email is not an address', the snippet, and the resolved trace\n * ```\n *\n * @see {@link https://nodejs.org/api/util.html#custom-inspection-functions-on-objects | Custom inspection}\n * @since 2.0.0\n */\n\n [Symbol.for('nodejs.util.inspect.custom')](): string | undefined {\n return this.formattedStack || this.stack;\n }\n\n /**\n * Resolves an error's stack against its sources and keeps both the metadata and the block to print.\n *\n * @param error - Error to resolve, usually `this`\n * @param options - Frame selection and code window size\n *\n * @remarks\n * Call it from the subclass constructor, after the name and the message are in place, since both are read off\n * the error to head the block with.\n * The error need not be `this` - a wrapper passes the cause it carries to report the trace of the failure that\n * actually happened.\n * Calling it again replaces both fields, so resolving a second time under different options is safe.\n *\n * @see formatStack\n * @see getErrorMetadata\n * @see StackTraceInterface\n *\n * @since 2.0.0\n */\n\n protected reformatStack(error: Error, options?: StackTraceInterface): void {\n this.errorMetadata = getErrorMetadata(error, options);\n this.formattedStack = formatStack(this.errorMetadata, error.name, error.message);\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { ServerEventsType } from '@server/interfaces/server.interface';\nimport type { LogLevelType } from '@providers/interfaces/log-provider.interface';\nimport type { LifecycleEventsType, LifecycleLogsType } from '@interfaces/lifecycle.interface';\n\n/**\n * Imports\n */\n\nimport { exit } from 'process';\nimport { setActivity } from '@ui/interactive.ui';\nimport { Injectable, inject } from '@remotex-labs/xinject';\nimport { ConfigurationService } from '@services/configuration.service';\nimport { TypescriptService } from '@typescript/services/typescript.service';\nimport { clearScreen, createActionPrefix, printGroup, printOutputs } from '@ui/print.ui';\nimport { keywordColor, mutedColor, warnColor, errorColor, infoColor, okColor, pathColor } from '@ui/color.ui';\nimport { WarningSymbol, ErrorSymbol, DotSymbol, ArrowSymbol, ReloadSymbol, SuccessSymbol, Levels } from '@constants/ui.constant';\n\n/**\n * Turns what a run reports into what a terminal shows.\n *\n * @remarks\n * Every event of a run arrives here: a build starting and ending, a server answering, a check reporting.\n * Each one becomes a printed line, the groups of messages under it, and a word on the status line,\n * so the scrollback carries the whole run while the bar carries only what is happening now.\n * A singleton, since a run has one terminal and the level it reports at is read from every corner of it.\n *\n * @example\n * ```ts\n * const screen = inject(Screen, () => build.build());\n * build.subscribe(screen.buildEvent.bind(screen));\n *\n * screen.toggleVerbose(); // 'verbose' - and the bar says so\n * ```\n *\n * @see LifecycleEventsType\n * @since 3.0.0\n */\n\n@Injectable({\n scope: 'singleton'\n})\nexport class Screen {\n /**\n * The configuration service the reporting level is read and written through.\n *\n * @remarks\n * The injected instance rather than one of its own,\n * so a level a key changes here is the level every other reader of the configuration sees.\n *\n * @example\n * ```ts\n * screen.config$.getValue().logLevel; // 'info'\n * ```\n *\n * @see ConfigurationService\n * @since 3.0.0\n */\n\n readonly config$ = inject(ConfigurationService);\n\n /**\n * The address a running server answers on, absent while none is running.\n *\n * @remarks\n * Written as the server reports its start and cleared as it stops,\n * so the status line offers a URL only while there is one to open.\n *\n * @since 3.0.0\n */\n\n private serverUrl?: string;\n\n /**\n * The level to go back to once reporting is turned down again.\n *\n * @remarks\n * Held so that turning `verbose` off restores the level the run was started at rather than a default,\n * which is what makes the toggle reversible for a run started at `error`.\n *\n * @since 3.0.0\n */\n\n private restoreLevel: LogLevelType;\n\n /**\n * Takes the build a key or a watch asks for, and settles the level to fall back to.\n *\n * @param build - What to run when a rebuild is asked for\n *\n * @remarks\n * The build arrives as a callback rather than as a service,\n * so the screen starts a run without knowing what a run is made of.\n * A run already started at `verbose` has no quieter level to remember, so `info` stands in as the one to return to.\n *\n * @example\n * ```ts\n * const screen = inject(Screen, runBuild); // runBuild is what a key or a watch will call\n * ```\n *\n * @since 3.0.0\n */\n\n constructor(private readonly build: () => Promise<void>) {\n this.restoreLevel = this.logLevel !== 'verbose' ? this.logLevel : 'info';\n }\n\n /**\n * Sets the level the run reports at.\n *\n * @param value - Level to report at from now on\n *\n * @remarks\n * Written through the configuration rather than held here,\n * so a variant reading the level for its own messages and the screen reading it for its groups agree.\n *\n * @example\n * ```ts\n * screen.logLevel = 'warning'; // info and verbose stop printing\n * ```\n *\n * @see LogLevelType\n * @since 3.0.0\n */\n\n set logLevel(value: LogLevelType) {\n this.config$.patch({ logLevel: value });\n }\n\n /**\n * The level the run is reporting at.\n *\n * @returns The configured level, `info` where the configuration names none\n *\n * @example\n * ```ts\n * screen.logLevel; // 'info'\n * ```\n *\n * @see LogLevelType\n * @since 3.0.0\n */\n\n get logLevel(): LogLevelType {\n return this.config$.getValue().logLevel ?? 'info';\n }\n\n /**\n * The address the running server answers on.\n *\n * @returns The URL, empty while no server is running\n *\n * @remarks\n * Empty rather than absent, so a caller writing it into a line needs no guard of its own.\n *\n * @example\n * ```ts\n * screen.url; // 'http://localhost:3000'\n * ```\n *\n * @since 3.0.0\n */\n\n get url(): string {\n return this.serverUrl ?? '';\n }\n\n /**\n * Records the address a server has begun answering on.\n *\n * @param value - URL the server bound to\n *\n * @example\n * ```ts\n * screen.url = 'http://localhost:3000';\n * ```\n *\n * @since 3.0.0\n */\n\n set url(value: string) {\n this.serverUrl = value;\n }\n\n /**\n * Reports either end of a build: its start or its finish.\n *\n * @param event - What the variant reported, carrying its context and, at the end, its result\n *\n * @remarks\n * A start says which variant is building and no more, since nothing has been found out yet.\n * An end prints the messages first and the outcome last,\n * so a reader scrolling up meets the verdict before its reasons.\n * A build that wrote no output is the failing case, whether it threw or only reported errors,\n * and it sets the exit code, which is what lets a pipeline read the run without reading its output.\n * Reporting at `verbose` lists every output rather than the largest few.\n *\n * @example\n * ```ts\n * build.subscribe(screen.buildEvent.bind(screen));\n * // [xBuild] → build esm\n * // [xBuild] ✓ esm in 128 ms\n * ```\n *\n * @see LifecycleEventsType\n * @since 3.0.0\n */\n\n buildEvent(event: LifecycleEventsType): void {\n if (event.type === 'start')\n return this.say(`${ infoColor.dim(ArrowSymbol) } ${ mutedColor('building') } ${ keywordColor(event.context.variantName) }`,\n `${ createActionPrefix('build') } ${ keywordColor(event.context.variantName) }`);\n\n const { errors, warnings, info, verbose: notes, metafile } = event.buildResult;\n const failed = !metafile;\n if (failed) process.exitCode = 1;\n else process.exitCode = 0;\n\n this.groups({ error: errors, warning: warnings, info, verbose: notes });\n if (metafile) printOutputs(metafile, this.logLevel === 'verbose' ? Infinity : undefined);\n\n const symbol = failed ? errorColor(ErrorSymbol) : okColor(SuccessSymbol);\n const name = failed ? warnColor(event.context.variantName) : keywordColor(event.context.variantName);\n\n this.say(`${ symbol } ${ name } ${ mutedColor.dim(`in ${ event.duration } ms`) }`,\n `\\n${ createActionPrefix('build', symbol) } ${ name } ${ mutedColor.dim(`in ${ event.duration } ms`) }`);\n }\n\n /**\n * Reports what the development server is doing.\n *\n * @param event - What the server reported: its start, its stop, a request, or a failure\n *\n * @remarks\n * A start is where the address comes from, and a stop is what takes it away again,\n * so the status line offers the URL for exactly as long as something answers on it.\n * A stop is reported only where a server was running, since a stop is worth a line only where something was answering.\n * Requests are reported only at `verbose`, one line being worth little against a page that fetches thirty files.\n * A failed `favicon.ico` is dropped whatever the level, since browsers ask for one unprompted on every visit.\n *\n * @example\n * ```ts\n * server.subscribe(screen.serverEvent.bind(screen));\n * // [xBuild] → serve http://localhost:3000\n * ```\n *\n * @see ServerEventsType\n * @since 3.0.0\n */\n\n serverEvent(event: ServerEventsType): void {\n switch (event.type) {\n case 'start':\n this.url = event.url;\n\n return console.log(`${ createActionPrefix('serve') } ${ pathColor(event.url) }`);\n case 'stop':\n this.serverUrl = undefined;\n if (event.running) console.log(`${ createActionPrefix('serve') } ${ mutedColor('stopped') }`);\n\n return;\n case 'request':\n if (this.logLevel === 'verbose')\n console.log(`${ createActionPrefix('serve') } ${ mutedColor.dim(event.url) }`);\n\n return;\n case 'error':\n if (event.url?.includes('favicon')) return;\n console.log(\n `${ createActionPrefix('serve', errorColor(ErrorSymbol)) } ${ mutedColor(event.error.message) }`\n );\n }\n }\n\n /**\n * Reports a type check and ends the process on what it found.\n *\n * @param diagnostics - Messages each variant's check reported, keyed by the variant's name\n *\n * @remarks\n * Every variant gets a heading carrying what it found, followed by its groups,\n * so a clean variant is still reported rather than left out of a run that named it.\n * The count is of everything the check reported rather than of what the level prints,\n * which is what keeps a quiet run from reading as a clean one.\n * The process leaves from here, and an error anywhere leaves with `1`,\n * since a check is the whole of what a run asking for one wanted.\n *\n * @example\n * ```ts\n * screen.diagnostics(await build.typeChack());\n * // [xBuild] → type-check esm 2 to look at\n * ```\n *\n * @see LifecycleLogsType\n * @since 3.0.0\n */\n\n diagnostics(diagnostics: Record<string, LifecycleLogsType>): void {\n let failed = false;\n\n for (const [ name, logs ] of Object.entries(diagnostics)) {\n const total = logs.error.length + logs.warning.length + logs.info.length + logs.verbose.length;\n\n failed ||= logs.error.length > 0;\n console.log(`${ createActionPrefix('type-check') } ${ keywordColor(name) } ${ mutedColor.dim(`${ total } to look at`) }`);\n this.groups(logs);\n console.log('');\n }\n\n exit(failed ? 1 : 0);\n }\n\n /**\n * Clears what the last build left, takes up any configuration change, says what asked for this build, and runs it.\n *\n * @param reason - What asked for the build, such as the files that changed or the key that was pressed\n * @param force - Whether every TypeScript project reparses its configuration even where its file has not moved\n *\n * @remarks\n * Every rebuild of a watch goes through here, so the screen is cleared and the run announced the same way\n * whichever asked for it.\n * The build itself is the one the run handed over when the screen was made.\n * The TypeScript configurations are reloaded here rather than by the watch,\n * so a rebuild started by a key reads them as freshly as one started by a changed file.\n * A configuration that has stayed put costs a lookup and nothing more.\n * Forcing reparses every project regardless, which is what the reload key asks for\n * and what catches a change the configuration file's own version misses.\n *\n * @example\n * ```ts\n * await screen.rebuild('2 files changed'); // [xBuild] rebuild 2 files changed\n * await screen.rebuild('reloading', true); // the same, with every tsconfig reparsed first\n * ```\n *\n * @see TypescriptService.reload\n * @since 3.0.0\n */\n\n async rebuild(reason: string, force: boolean = false): Promise<void> {\n clearScreen();\n TypescriptService.reload(force);\n\n this.say(`${ infoColor.dim(ReloadSymbol) } ${ mutedColor(reason) }`,\n `${ createActionPrefix('rebuild', infoColor.dim(ReloadSymbol)) } ${ mutedColor(reason) }`);\n\n await this.build();\n }\n\n /**\n * Turns reporting all the way up, or back to what it was before it was turned up.\n *\n * @returns The level the run now reports at\n *\n * @remarks\n * The level the run was set to is remembered rather than assumed,\n * so a run started at `error` goes back to `error` rather than to the default.\n * The level is written back through the configuration, so everything reading it follows in the same breath.\n *\n * @example\n * ```ts\n * screen.toggleVerbose(); // 'verbose'\n * screen.toggleVerbose(); // 'info' - what it was before\n * ```\n *\n * @since 3.0.0\n */\n\n toggleVerbose(): LogLevelType {\n if (this.logLevel === 'verbose') this.logLevel = this.restoreLevel;\n else {\n this.restoreLevel = this.logLevel;\n this.logLevel = 'verbose';\n }\n\n return this.logLevel;\n }\n\n /**\n * Writes a line to the scrollback and says the same thing on the status line.\n *\n * @param activity - What is happening, as the bar says it\n * @param line - The line printed to the scrollback\n *\n * @remarks\n * The two are worded apart rather than shared, since the bar carries no prefix and has one row to say it in,\n * while the printed line stands on its own long after the run has moved past it.\n *\n * @see setActivity\n * @since 3.0.0\n */\n\n private say(activity: string, line: string): void {\n console.log(line);\n setActivity(activity);\n }\n\n /**\n * Prints the message groups the current level allows.\n *\n * @param logs - Messages to print, filed under the level each was reported at\n *\n * @remarks\n * The groups run loudest first, so what failed a build is read before what merely remarked on it.\n * Each group is compared against the level the run is set to,\n * which is what leaves a quiet run its errors and drops everything under them.\n * An error always carries its code window and its trace, since that is what an error is read for,\n * while the quieter groups carry theirs only at `verbose`.\n *\n * @see Levels\n * @see printGroup\n *\n * @since 3.0.0\n */\n\n private groups(logs: LifecycleLogsType): void {\n const lowest = Levels[this.logLevel];\n const code = this.logLevel === 'verbose';\n\n if (Levels.error >= lowest) printGroup(logs.error, 'Errors', errorColor, ErrorSymbol, true);\n if (Levels.warning >= lowest) printGroup(logs.warning, 'Warnings', warnColor, WarningSymbol, code);\n if (Levels.info >= lowest) printGroup(logs.info, 'Info', infoColor, ArrowSymbol, code);\n if (Levels.verbose >= lowest) printGroup(logs.verbose, 'Verbose', mutedColor, DotSymbol, code);\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { Key } from 'readline';\nimport type { Screen } from '@ui/screen.ui';\n\n/**\n * Imports\n */\n\nimport { exec } from 'child_process';\nimport * as readline from 'node:readline';\nimport { clearScreen, width } from '@ui/print.ui';\nimport { platform, stdin, stdout, exit } from 'process';\nimport { xterm } from '@remotex-labs/xansi/xterm.component';\nimport { ANSI, moveCursor, writeRaw } from '@remotex-labs/xansi';\nimport { ShadowRenderer } from '@remotex-labs/xansi/shadow.service';\nimport { infoColor, keywordColor, mutedColor, pathColor } from '@ui/color.ui';\nimport { DotSymbol, Indent, MinimumRows, RepaintInterval, ReloadSymbol, ReportTimeout } from '@constants/ui.constant';\n\n/**\n * The command each platform opens a URL with.\n *\n * @remarks\n * Anything the table does not name falls back to the freedesktop opener, which is what every other Unix carries.\n *\n * @since 3.0.0\n */\n\nconst OpenCommands: Record<string, string> = { darwin: 'open', win32: 'start' };\n\n/**\n * What each key does, paired with the line the menu describes it by.\n *\n * @remarks\n * One table drives both the menu and the dispatch, so a key cannot be listed without an action or the other way round.\n * The key that opens a browser is listed only while a server is running, which is what `server` marks it by.\n *\n * @since 3.0.0\n */\n\nconst Keys = [\n { key: 'h', describe: 'show this menu', server: false },\n { key: 'b', describe: 'run the build', server: false },\n { key: 'r', describe: 'reload and rebuild', server: false },\n { key: 'v', describe: 'toggle verbose', server: false },\n { key: 'c', describe: 'clear the screen', server: false },\n { key: 'o', describe: 'open it in a browser', server: true },\n { key: 'q', describe: 'quit', server: false }\n] as const;\n\n/**\n * The screen the keys act on and the bar reads, absent while no watch is listening.\n *\n * @remarks\n * The settings a run is under live on the screen rather than here,\n * so a key that changes one and a report that reads it are looking at the same value.\n *\n * @since 3.0.0\n */\n\nlet session: Screen | undefined;\n\n/**\n * What the run is doing, as the bar says it, empty while the watch rests between builds.\n *\n * @since 3.0.0\n */\n\nlet activity = '';\n\n/**\n * The row the bar draws through, absent while the terminal has none to spare.\n *\n * @remarks\n * A viewport one row tall pinned to the foot of the terminal.\n * Its rows count from one, so the row it is offset by is the one above the last,\n * which is what puts its only row on the last one rather than a line past the bottom of the screen.\n * It holds what it drew, so redrawing writes only the cells that moved, and a line too long for the terminal is cut\n * to fit rather than wrapping onto the row above and breaking the region the report scrolls in.\n *\n * @see ShadowRenderer\n * @since 3.0.0\n */\n\nlet row: ShadowRenderer | undefined;\n\n/**\n * The beat the bar is painted on, absent while no watch holds a row.\n *\n * @since 3.0.0\n */\n\nlet repaint: NodeJS.Timeout | undefined;\n\n/**\n * The row the cursor sits on, as the terminal itself reports it.\n *\n * @returns The row, or the last one where the terminal did not answer\n *\n * @remarks\n * Where a run has printed to is the one thing it cannot know for itself, and it decides everything the row rests on:\n * a watch started on a screen already full leaves the cursor on the last row, which is the row the line is about\n * to take, and every line printed afterward would land under the line and be painted over rather than scrolled.\n * The terminal is asked outright, and it answers on the input the shortcuts have yet to claim,\n * so the reply is read before the keys are listened for rather than swallowed by them.\n * A terminal that does not answer is taken to be full, which is the safe half of the guess.\n *\n * @since 3.0.0\n */\n\nfunction cursorRow(): Promise<number> {\n return new Promise(resolve => {\n const answer = (data: Buffer): void => {\n const reported = /\\[(\\d+);\\d+R/.exec(data.toString());\n if (!reported) return;\n\n stdin.off('data', answer);\n resolve(Number(reported[1]));\n };\n\n stdin.on('data', answer);\n writeRaw('\\u001B[6n');\n setTimeout(() => (stdin.off('data', answer), resolve(stdout.rows)), ReportTimeout).unref();\n });\n}\n\n/**\n * Opens a URL in whatever the platform treats as the browser.\n *\n * @param url - Address to open\n *\n * @remarks\n * The command is spawned and left to itself, so a browser that takes its time does not hold the watch up,\n * and a platform without an opener fails silently rather than taking down the run with it.\n *\n * @example\n * ```ts\n * openInBrowser('http://localhost:3000');\n * ```\n *\n * @since 3.0.0\n */\n\nexport function openInBrowser(url: string): void {\n exec(`${ OpenCommands[platform] ?? 'xdg-open' } ${ url }`);\n}\n\n/**\n * Renders the menu of what the keys do.\n *\n * @returns The menu, ready to write\n *\n * @remarks\n * The key that opens a browser is listed only while a server is running, there being nothing to open otherwise.\n *\n * @example\n * ```ts\n * console.log(helpMenu());\n * // Shortcuts\n * // press h to show this menu\n * ```\n *\n * @since 3.0.0\n */\n\nexport function helpMenu(): string {\n const lines = [ `\\n🚀 ${ keywordColor('Shortcuts') }` ];\n for (const { key, describe, server } of Keys) {\n if (!server || session?.url)\n lines.push(`${ Indent }${ mutedColor.dim('press') } ${ xterm.bold(key) } ${ mutedColor.dim(`to ${ describe }`) }`);\n }\n\n return `${ lines.join('\\n') }\\n`;\n}\n\n/**\n * Draws the status line on the row it holds, leaving the cursor where it found it.\n *\n * @param force - Whether to paint every cell rather than the ones that moved\n *\n * @remarks\n * Only what changed is written, unless the caller asks for the whole row,\n * which is what the repainting beat asks for: a terminal cleared behind the run's back is not what the row\n * remembers drawing, so nothing would be found to differ and nothing would be written.\n * What the run is doing leads, and the rest reads left to right:\n * where the server is, whether it is reporting everything, and how to see the keys.\n *\n * @example\n * ```ts\n * drawStatusBar();\n * // PASS main in 134 ms · http://localhost:3000 · verbose · press h for shortcuts\n * ```\n *\n * @since 3.0.0\n */\n\nexport function drawStatusBar(force = false): void {\n if (!row) return;\n\n const parts = [ activity || `${ infoColor.dim(ReloadSymbol) } ${ mutedColor('watching') }` ];\n if (session?.url) parts.push(pathColor(session.url));\n if (session?.logLevel === 'verbose') parts.push(keywordColor('verbose'));\n parts.push(mutedColor.dim('press h for shortcuts'));\n\n writeRaw(ANSI.SAVE_CURSOR);\n row.writeText(0, 0, ` ${ parts.join(mutedColor.dim(` ${ DotSymbol } `)) }`, true);\n row.render(force);\n writeRaw(ANSI.RESTORE_CURSOR);\n}\n\n/**\n * Says what the run is doing and redraws the bar.\n *\n * @param text - What is happening, already colored, empty to say the watch is resting\n *\n * @example\n * ```ts\n * setActivity(`${ infoColor(ArrowSymbol) } building index`);\n * ```\n *\n * @see drawStatusBar\n * @since 3.0.0\n */\n\nexport function setActivity(text: string): void {\n activity = text;\n drawStatusBar();\n}\n\n/**\n * Listens for the shortcuts and takes the last row of the terminal for the status line.\n *\n * @param screen - Screen the keys act on and the bar reads its settings from\n * @returns A promise settling once the row is held and the keys are listened for\n *\n * @remarks\n * A terminal that is not one - a pipe, a log file, a pipeline - is left alone,\n * since raw mode would take a run that nobody is watching and break its input.\n * Where the run has printed to is asked of the terminal before the keys are listened for, the answer coming back\n * on the same input: only a run that has reached the last row needs one scrolled free,\n * and one that has not keeps the blank line it would have cost.\n * The region is set so that everything printed afterward scrolls above the line rather than over it,\n * which keeps it out of the scrollback.\n * The row is painted again on a beat, so a terminal cleared from outside the run gets the line back at once,\n * and the beat is unreferenced, so it never holds the process open on its own.\n * The cursor is put away for as long as the line holds the row, and everything is given back as the run leaves.\n *\n * @example\n * ```ts\n * startInteractive(screen);\n * ```\n *\n * @see handleKey\n * @see drawStatusBar\n *\n * @since 3.0.0\n */\n\nexport async function startInteractive(screen: Screen): Promise<void> {\n if (!stdin.isTTY || !stdout.isTTY || repaint) return;\n session = screen;\n\n stdin.setRawMode(true);\n writeRaw(ANSI.HIDE_CURSOR);\n\n const printed = await cursorRow();\n if (printed >= stdout.rows) writeRaw('\\n');\n claimRow(Math.min(printed, stdout.rows - 1));\n\n readline.emitKeypressEvents(stdin);\n stdin.on('keypress', (_, key: Key) => handleKey(key));\n\n stdout.on('resize', () => claimRow());\n repaint = setInterval(() => drawStatusBar(true), RepaintInterval).unref();\n process.on('exit', stopInteractive);\n}\n\n/**\n * Gives the row back and clears what the status line left on it.\n *\n * @remarks\n * Run as the process leaves, so the terminal is handed back scrolling in the whole of itself, cursor and all.\n * A run that never took a row has none to give, and returns.\n *\n * @since 3.0.0\n */\n\nexport function stopInteractive(): void {\n if (!repaint) return;\n\n clearInterval(repaint);\n repaint = undefined;\n row = undefined;\n\n writeRaw(`\\u001B[r${ moveCursor(stdout.rows, 1) }${ ANSI.CLEAR_LINE }${ ANSI.SHOW_CURSOR }`);\n}\n\n/**\n * Cuts the region the output scrolls in out of the terminal as it now stands, and draws the line under it.\n *\n * @param anchor - Row the run had printed to, left out by a resize to put the cursor back where it was\n *\n * @remarks\n * Run on every resize as well as on the first claim, so the row is rebuilt for the size the terminal now is.\n * Setting a region homes the cursor, so it is put back where the caller says the run had printed to:\n * the next line printed belongs under the last one written, not at the foot of a screen it has yet to fill,\n * and never on the row the line holds, where it would be painted over rather than read.\n * A resize is given no row to go back to and restores what was saved, the run printing inside the region by then.\n * The row is cleared before it is drawn, since the line has no claim on what a resize reflowed onto it.\n * A terminal too short to spare a row keeps all of itself and goes without the line until it is resized larger.\n *\n * @since 3.0.0\n */\n\nfunction claimRow(anchor?: number): void {\n if (stdout.rows < MinimumRows) {\n row = undefined;\n\n return writeRaw(`\\u001B[r${ ANSI.CLEAR_LINE }`);\n }\n\n const last = stdout.rows - 1;\n const back = anchor === undefined ? ANSI.RESTORE_CURSOR : moveCursor(anchor, 1);\n\n row = new ShadowRenderer(1, width(), last, 1);\n writeRaw(\n `${ ANSI.SAVE_CURSOR }\\u001B[1;${ last }r`\n + `${ moveCursor(stdout.rows, 1) }${ ANSI.CLEAR_LINE }${ back }`\n );\n\n drawStatusBar(true);\n}\n\n/**\n * Runs what a key asks for.\n *\n * @param key - Key that was pressed, as the terminal reported it\n *\n * @remarks\n * Interrupts leave through the same door as `q`, so a watch stopped by a keystroke and one stopped by a signal\n * end the same way, and both hand the terminal back before they go.\n * The run leaves only once the line saying so has been written, since leaving outright would cut the terminal\n * off before what was written for it had reached it.\n * Building and reloading part on one flag: `b` builds again from the configurations as they were parsed,\n * while `r` has every TypeScript project reparse its own first.\n * That reparse is what catches a change their versions miss, such as an edit to a file one of them extends.\n * A key with nothing bound to it is passed over, since a watch is left running rather than surprised by a typo.\n *\n * @see helpMenu\n * @since 3.0.0\n */\n\nasync function handleKey(key: Key): Promise<void> {\n if (key.ctrl && (key.name === 'c' || key.name === 'd')) key.name = 'q';\n\n switch (key.name) {\n case 'q':\n stopInteractive();\n stdout.write(`${ mutedColor('Stopped.') }\\n`, () => exit(process.exitCode ? Number(process.exitCode) : 0));\n\n return;\n case 'c':\n clearScreen();\n\n return drawStatusBar(true);\n case 'h':\n return console.log(helpMenu());\n case 'v':\n session?.toggleVerbose();\n\n return drawStatusBar(true);\n case 'o':\n if (session?.url) openInBrowser(session.url);\n\n return;\n case 'b':\n return session?.rebuild('rebuilding');\n case 'r':\n return session?.rebuild('reloading', true);\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { errorColor } from '@ui/color.ui';\nimport type { Metafile, PartialMessage } from 'esbuild';\nimport type { MessageRowInterface } from '@ui/interfaces/print-ui.interface';\nimport type { ResolveMetadataInterface } from '@providers/interfaces/stack-provider.interface';\n\n/**\n * Imports\n */\n\nimport { resolve } from 'path';\nimport { stdout } from 'process';\nimport { prefix } from '@ui/banner.ui';\nimport { inject } from '@remotex-labs/xinject';\nimport { stripAnsi } from '@remotex-labs/xansi';\nimport { cursorTo, clearScreenDown } from 'readline';\nimport { dirname, relative } from '@remotex-labs/xmap';\nimport { xterm } from '@remotex-labs/xansi/xterm.component';\nimport { getErrorMetadata } from '@providers/stack.provider';\nimport { FrameworkService } from '@services/framework.service';\nimport { infoColor, mutedColor, okColor, pathColor, warnColor } from '@ui/color.ui';\nimport { ArrowSymbol, DefaultWidth, DotSymbol, Indent, Kilobyte, Megabyte, OutputLimit } from '@constants/ui.constant';\n\n/**\n * Opens a reported line with the package's mark, a symbol, and the action being reported.\n *\n * @param action - What the line reports, such as `build` or `serve`\n * @param symbol - Symbol between the mark and the action, a dimmed arrow by default\n * @returns The opening of the line, colored\n *\n * @remarks\n * Every line printed outside a message group opens this way,\n * so the mark, the symbol, and the action sit in the same three places whatever printed them.\n * The symbol is what a caller varies to say how the action went, since the action itself reads the same either way.\n *\n * @example\n * ```ts\n * createActionPrefix('build'); // '[xBuild] → build'\n * createActionPrefix('build', okColor(SuccessSymbol)); // '[xBuild] ✓ build'\n * ```\n *\n * @see prefix\n * @since 3.0.0\n */\n\nexport function createActionPrefix(action: string, symbol: string = infoColor.dim(ArrowSymbol)): string {\n return `${ prefix() } ${ symbol } ${ infoColor(action) }`;\n}\n\n/**\n * Counts the characters a text takes on screen.\n *\n * @param text - Text to measure, colored or not\n * @returns The number of characters that print\n *\n * @remarks\n * The escape sequences a color leaves behind take no width of their own,\n * so measuring the string itself would pad a colored column by however many bytes its color cost.\n *\n * @example\n * ```ts\n * visible(pathColor('src/index.ts')); // 12\n * ```\n *\n * @since 3.0.0\n */\n\nexport function visible(text: string): number {\n return stripAnsi(text).length;\n}\n\n/**\n * Pads a text with spaces up to a width.\n *\n * @param text - Text to pad, colored or not\n * @param size - Width to pad it to, counted in printed characters\n * @returns The text, followed by the spaces that carry it to the width\n *\n * @remarks\n * The width is measured through {@link visible}, so a colored text pads to what it prints rather than to what it holds.\n * A text already at or past the width comes back as it is rather than cut,\n * since a column that overflows reads better than one that loses the end of a name.\n *\n * @example\n * ```ts\n * pad('src', 6); // 'src '\n * pad('src/index', 6); // 'src/index' - already past the width\n * ```\n *\n * @see visible\n * @since 3.0.0\n */\n\nexport function pad(text: string, size: number): string {\n return text + ' '.repeat(Math.max(0, size - visible(text)));\n}\n\n/**\n * Brings the path a frame resolved to back to one the project can be read against.\n *\n * @param file - Path the frame named, as the source map spelled it\n * @returns The path relative to the directory the run was started in\n *\n * @remarks\n * A map spells its sources relative to what was written rather than to what is being read,\n * so a config compiled by this package resolves as a path reaching back out of the framework's own directory.\n * Such a path is resolved from there rather than from the project, which is the only place it means anything,\n * and every other path is resolved the way this package keys files everywhere else.\n * A source that names a URL rather than a path is left as it is, there being no root to read it against.\n *\n * @example\n * ```ts\n * sourcePath('../config.xbuild.ts'); // 'config.xbuild.ts'\n * sourcePath('src/index.ts'); // 'src/index.ts'\n * sourcePath('https://github.com/x/y.ts'); // 'https://github.com/x/y.ts'\n * ```\n *\n * @see FrameworkService\n * @since 3.0.0\n */\n\nexport function sourcePath(file: string): string {\n if (file.includes('://')) return file;\n\n const frameworkRoot = inject(FrameworkService).frameworkRoot;\n if (file.includes(dirname(frameworkRoot))) return file;\n\n const absolute = file.startsWith('.') ? resolve(frameworkRoot, file) : FrameworkService.resolve(file);\n\n return relative(process.cwd(), absolute);\n}\n\n/**\n * Renders where a message points.\n *\n * @param file - Path the message points at, absent when it points nowhere\n * @param line - Line within that file\n * @param column - Column within that line\n * @returns The location, colored, empty when there is no file to point at\n *\n * @example\n * ```ts\n * formatLocation('src/index.ts', 12, 8); // 'src/index.ts:12:8'\n * formatLocation(undefined); // ''\n * ```\n *\n * @see sourcePath\n * @since 3.0.0\n */\n\nexport function formatLocation(file?: string, line: number = 0, column: number = 0): string {\n if (!file) return '';\n const separator = mutedColor.dim(':');\n\n return `${ pathColor(sourcePath(file)) }${ separator }${ warnColor(String(line)) }${ separator }${ warnColor(String(column)) }`;\n}\n\n/**\n * Renders the code window and the trace printed under a message.\n *\n * @param metadata - Already resolved trace of the message, so nothing is resolved twice\n * @param indent - What every line is indented by\n * @returns The lines to print under the message, empty when it resolved to neither code nor a trace\n *\n * @remarks\n * A trace of a single frame says nothing the location line has not said already, so it is left out.\n * Paths are printed from the directory the run was started in, the absolute part being the same for every frame.\n *\n * @see getErrorMetadata\n * @since 3.0.0\n */\n\nexport function formatDetail(metadata: ResolveMetadataInterface, indent: string): Array<string> {\n const root = `${ process.cwd() }/`;\n const lines: Array<string> = [];\n\n if (metadata.formatCode)\n lines.push('', ...metadata.formatCode.split('\\n').map(line => `${ indent }${ xterm.dim(line) }`));\n\n if (metadata.stack.length > 1) lines.push('', ...metadata.stack.map(frame => {\n return `${ indent }${ mutedColor.dim(frame.format.replaceAll(root, '')) }`;\n }));\n\n return lines.length > 0 ? [ ...lines, '' ] : lines;\n}\n\n/**\n * Works a message out into the parts a report line is laid out from.\n *\n * @param message - Message to describe\n * @param code - Whether the code window and trace are wanted under the line\n * @returns The message worked out, ready to be measured and printed\n *\n * @remarks\n * A diagnostic filed under a TypeScript code - an id of `TS<code>` - already points at the file that was written,\n * so it is taken at its word.\n * Anything else points at what was built rather than at what was written - a plugin throwing from a config that was\n * compiled to run reports the offset it failed at in the compiled text - so it is resolved through the source map\n * and read off the first frame instead.\n * The resolve is done once and serves both the location and what is printed under it,\n * and is skipped entirely by a diagnostic that needs neither.\n *\n * @example\n * ```ts\n * describeMessage({ id: 'TS2304', location: { file: 'src/index.ts', line: 12, column: 8 } }, false);\n * // { id: 'TS2304', location: 'src/index.ts:12:8', detail: [] }\n * ```\n *\n * @see getErrorMetadata\n * @see MessageRowInterface\n *\n * @since 3.0.0\n */\n\nexport function describeMessage(message: PartialMessage, code: boolean): MessageRowInterface {\n const typescript = message.id?.startsWith('TS') ?? false;\n const metadata = typescript && !code\n ? undefined\n : getErrorMetadata(message, { linesAfter: 1, linesBefore: 1, withFrameworkFrames: true });\n\n const frame = typescript ? undefined : metadata?.stack[0];\n const point = frame ?? message.location;\n\n return {\n id: message.id ?? '',\n detail: code && metadata ? formatDetail(metadata, Indent.repeat(2)) : [],\n location: formatLocation(frame?.fileName ?? message.location?.file, point?.line, point?.column)\n };\n}\n\n/**\n * Prints a group of messages under a heading, in columns sized to what they hold.\n *\n * @param messages - Messages to print, the group being skipped when there are none\n * @param title - Heading the group is printed under\n * @param color - Color the heading, the symbol, and the ids are printed in\n * @param symbol - Symbol each message is marked with\n * @param code - Whether each message carries its code window and trace\n *\n * @remarks\n * Every message is worked out once, in the pass that measures the columns,\n * since neither the location column nor the id column can be sized until all of them have been seen.\n * An id column is left out entirely when nothing in the group carries one.\n *\n * @example\n * ```ts\n * printGroup(errors, 'Errors', errorColor, ErrorSymbol, true);\n * // Errors (1)\n * // x config.xbuild.ts:126:27 asdasd\n * ```\n *\n * @see describeMessage\n * @since 3.0.0\n */\n\nexport function printGroup(\n messages: Array<PartialMessage>, title: string, color: typeof errorColor, symbol: string, code = false\n): void {\n if (messages.length < 1) return;\n\n let left = 0;\n let middle = 0;\n const rows: Array<MessageRowInterface> = [];\n\n for (const message of messages) {\n const row = describeMessage(message, code);\n left = Math.max(left, visible(row.location));\n middle = Math.max(middle, row.id.length);\n rows.push(row);\n }\n\n const lines = [ `\\n ${ color(title) } ${ mutedColor.dim(`(${ rows.length })`) }` ];\n for (const [ index, { id, location, detail }] of rows.entries()) {\n const tag = middle > 0 ? `${ pad(color(id), middle) } ` : '';\n\n lines.push(`${ Indent }${ color(symbol) } ${ pad(location, left) } ${ tag }${ mutedColor(messages[index].text ?? '') }`);\n lines.push(...detail);\n }\n\n console.log(lines.join('\\n'));\n}\n\n/**\n * Clears the terminal and puts the cursor back at the top.\n *\n * @remarks\n * The screen is pushed out of view rather than wiped, so the scrollback survives a clear.\n *\n * @since 3.0.0\n */\n\nexport function clearScreen(): void {\n const rows = Math.max(0, stdout.rows - 2);\n if (rows > 0) console.log('\\n'.repeat(rows));\n\n cursorTo(stdout, 0, 0);\n clearScreenDown(stdout);\n}\n\n/**\n * The width of the terminal, or what stands in for one that does not report it.\n *\n * @returns Columns the report is laid out in\n *\n * @since 3.0.0\n */\n\nexport function width(): number {\n return stdout.columns || DefaultWidth;\n}\n\n/**\n * Renders a byte count in the largest unit that keeps it above one.\n *\n * @param bytes - Size to render\n * @returns The size with its unit\n *\n * @example\n * ```ts\n * formatSize(512); // '512 B'\n * formatSize(458520); // '447.77 KB'\n * ```\n *\n * @since 3.0.0\n */\n\nexport function formatSize(bytes: number): string {\n if (bytes < Kilobyte) return `${ bytes } B`;\n if (bytes < Megabyte) return `${ (bytes / Kilobyte).toFixed(2) } KB`;\n\n return `${ (bytes / Megabyte).toFixed(2) } MB`;\n}\n\n/**\n * Writes what a build wrote, largest first, with the sizes set against the right margin.\n *\n * @param metafile - Metafile of the finished build, read for its outputs\n * @param limit - How many outputs to name before the rest are counted rather than listed, `Infinity` for all of them\n *\n * @remarks\n * The sizes are set flush against the right margin, so their digits line up under one another,\n * and the heading carries the total, which is the number a reader is usually after.\n * A build of many entry points writes more than a reader wants to scroll,\n * so the largest few are named and the rest left as a count carrying what it comes to.\n *\n * @example\n * ```ts\n * printOutputs(metafile);\n * // Outputs (18) 1.24 MB\n * // dist/index.js.map 681 B\n * ```\n *\n * @since 3.0.0\n */\n\nexport function printOutputs(metafile: Metafile, limit: number = OutputLimit): void {\n const outputs = Object.entries(metafile.outputs).sort(\n ([ , a ], [ , b ]) => b.bytes - a.bytes\n );\n\n if (outputs.length < 1) return;\n const listed = outputs.slice(0, limit);\n const sizes = listed.map(([ , { bytes }]) => formatSize(bytes));\n const right = Math.max(...sizes.map(size => size.length));\n const total = outputs.reduce((sum, [ , { bytes }]) => sum + bytes, 0);\n\n const room = width() - Indent.length - right - 4;\n const header = ` ${ okColor('Outputs') } ${ mutedColor.dim(`(${ outputs.length })`) }`;\n const lines = [ `\\n${ pad(header, width() - right - 1) }${ warnColor.dim(formatSize(total)) }` ];\n\n for (const [ index, [ path ]] of listed.entries())\n lines.push(\n `${ Indent }${ infoColor.dim(ArrowSymbol) } ${ pad(pathColor(path), room + 1) }`\n + warnColor.dim(sizes[index].padStart(right))\n );\n\n if (outputs.length > limit) {\n const rest = outputs.slice(limit).reduce((sum, [ , { bytes }]) => sum + bytes, 0);\n const more = mutedColor.dim(`${ DotSymbol } ${ outputs.length - limit } more`);\n lines.push(`${ Indent } ${ pad(more, room + 1) }${ warnColor.dim(formatSize(rest).padStart(right)) }`);\n }\n\n console.log(lines.join('\\n'));\n}\n","/**\n * Imports\n */\n\nimport { xterm } from '@remotex-labs/xansi/xterm.component';\n\n/**\n * The xBuild wordmark drawn in ASCII art.\n *\n * @remarks\n * Opens and closes with a newline, so it stands on its own lines wherever it is printed.\n * The backslashes are escaped for the template literal,\n * so the string holds one backslash everywhere the source shows two.\n *\n * @example\n * ```ts\n * console.log(asciiLogo);\n * ```\n *\n * @see bannerUi\n * @since 1.0.0\n */\n\nexport const asciiLogo = `\n ______ _ _ _\n | ___ \\\\ (_) | | |\n__ _| |_/ /_ _ _| | __| |\n\\\\ \\\\/ / ___ \\\\ | | | | |/ _\\` |\n > <| |_/ / |_| | | | (_| |\n/_/\\\\_\\\\____/ \\\\__,_|_|_|\\\\__,_|\n`;\n\n/**\n * Renders the startup banner, the logo above the version.\n *\n * @returns The banner as one string, colored and ready to print\n *\n * @remarks\n * The logo is drawn in burnt orange and the version in bright pink.\n * Every line opens with a carriage return, so the text starts at column zero\n * whatever indentation the template literal carries.\n * The version reads `__VERSION`, which the build replaces with the `package.json` version at compile time.\n *\n * @example\n * ```ts\n * console.log(bannerComponent());\n * ```\n *\n * @see asciiLogo\n * @since 1.0.0\n */\n\nexport function bannerUi(): string {\n return `\n \\r${ xterm.burntOrange(asciiLogo) }\n \\rVersion: ${ xterm.brightPink(__VERSION) }\n \\r`;\n}\n\n/**\n * The `[xBuild]` tag that marks a line as coming from the build.\n *\n * @returns The tag in light coral\n *\n * @remarks\n * Prepended to log lines so xBuild output stays recognizable when several tools write to the same console.\n *\n * @example\n * ```ts\n * console.log(`${ prefix() } Starting build`); // [xBuild] Starting build\n * ```\n *\n * @since 1.0.0\n */\n\nexport function prefix(): string {\n return xterm.lightCoral('[xBuild]');\n}\n","/**\n * Imports\n */\n\nimport { xterm } from '@remotex-labs/xansi/xterm.component';\n\n/**\n * Style token for a step that finished as it should.\n *\n * @remarks\n * Green.\n * Reserved for an outcome the reader can stop reading at, so a step that merely progressed stays unstyled.\n *\n * @example\n * ```ts\n * console.log(okColor('build finished'));\n * ```\n *\n * @since 2.0.0\n */\n\nexport const okColor = xterm.hex('#a6da95');\n\n/**\n * Style token for ordinary body text.\n *\n * @remarks\n * Neutral light.\n * The default weight everything else is read against, so it carries no meaning of its own.\n *\n * @example\n * ```ts\n * console.log(textColor('4 entry points'));\n * ```\n *\n * @since 2.0.0\n */\n\nexport const textColor = xterm.hex('#cad3f5');\n\n/**\n * Style token for a notice the reader may act on but need not.\n *\n * @remarks\n * Blue.\n * Distinguished from {@link warnColor} by carrying no fault - it reports what happened rather than what went wrong.\n *\n * @example\n * ```ts\n * console.log(infoColor('watching for changes'));\n * ```\n *\n * @since 2.0.0\n */\n\nexport const infoColor = xterm.hex('#91d7e3');\n\n/**\n * Style token for something suspect that did not stop the build.\n *\n * @remarks\n * Yellow.\n * The middle ground between {@link infoColor} and {@link errorColor}, for output worth reading after the run.\n *\n * @example\n * ```ts\n * console.log(warnColor('3 files matched no entry point'));\n * ```\n *\n * @since 2.0.0\n */\n\nexport const warnColor = xterm.hex('#eed49f');\n\n/**\n * Style token for a file path, a URL, or a location.\n *\n * @remarks\n * Cyan.\n * Marks the part of a line the reader is most likely to copy, so it stays distinct inside an otherwise styled message.\n *\n * @example\n * ```ts\n * console.log(pathColor('src/index.ts'));\n * ```\n *\n * @since 2.0.0\n */\n\nexport const pathColor = xterm.hex('#f5a97f');\n\n/**\n * Style token for a failure.\n *\n * @remarks\n * Red.\n * For an outcome that stopped the work, which keeps it rare enough to still register when it appears.\n *\n * @example\n * ```ts\n * console.log(errorColor('Cannot resolve module'));\n * ```\n *\n * @since 2.0.0\n */\n\nexport const errorColor = xterm.hex('#ed8796');\n\n/**\n * Style token for a keyword or an identifier quoted inside a message.\n *\n * @remarks\n * Purple.\n * Picks a name out of surrounding prose the way {@link pathColor} picks out a location.\n *\n * @example\n * ```ts\n * console.log(keywordColor('bundleDeclaration'));\n * ```\n *\n * @since 2.0.0\n */\n\nexport const keywordColor = xterm.hex('#c6a0f6');\n\n/**\n * Style token for text that belongs on the line but not at the front of the reader's attention.\n *\n * @remarks\n * Muted gray.\n * For figures that qualify a message rather than carry it, such as a timing or a count.\n *\n * @example\n * ```ts\n * console.log(mutedColor('in 412ms'));\n * ```\n *\n * @since 2.0.0\n */\n\nexport const mutedColor = xterm.hex('#939ab7');\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { LogLevelType } from '@providers/interfaces/log-provider.interface';\n\n/**\n * The three spaces that indent one level of reported detail.\n *\n * @remarks\n * Wide enough to clear the symbol marking the line above,\n * so a message sits under the heading it belongs to rather than against the margin.\n * A code window and a trace are indented twice over, which sets them under the message they explain.\n *\n * @example\n * ```ts\n * `${ Indent }dist/index.js`; // ' dist/index.js'\n * ```\n *\n * @since 3.0.0\n */\n\nexport const Indent = ' ';\n\n/**\n * The width a report is laid out in where the terminal reports none.\n *\n * @remarks\n * A pipe and a log file have no column count to answer with,\n * so the sizes a report sets against the right margin would have nothing to measure from.\n *\n * @example\n * ```ts\n * width(); // 100 - piped, so the terminal reported nothing\n * ```\n *\n * @see width\n * @since 3.0.0\n */\n\nexport const DefaultWidth = 100;\n\n/**\n * How many outputs a build names before the rest are counted rather than listed.\n *\n * @remarks\n * A build of many entry points writes more than a reader wants to scroll,\n * so the largest few are named and what is left becomes one line carrying its count and its size.\n * Reporting at `verbose` lifts the limit rather than raising it.\n *\n * @example\n * ```ts\n * printOutputs(metafile); // the six largest, then '· 12 more'\n * printOutputs(metafile, Infinity); // all of them\n * ```\n *\n * @since 3.0.0\n */\n\nexport const OutputLimit = 6;\n\n/**\n * The fewest rows a terminal can have and still give one up to the status line.\n *\n * @remarks\n * Below this the scrolling region would be shorter than the report it carries,\n * so the line is given up and the terminal keeps all of itself until it is resized larger.\n *\n * @since 3.0.0\n */\n\nexport const MinimumRows = 4;\n\n/**\n * How long the status line waits between repaints, in milliseconds.\n *\n * @remarks\n * The beat is what brings the line back after a terminal is cleared from outside the run,\n * since the row remembers what it drew and would otherwise find nothing to redraw.\n * Short enough to read as immediate, long enough that a resting watch costs a repaint three times a second.\n *\n * @since 3.0.0\n */\n\nexport const RepaintInterval = 300;\n\n/**\n * How long the terminal is given to say where the cursor is, in milliseconds.\n *\n * @remarks\n * A terminal that answers does so at once, so the wait is only ever spent on one that never will,\n * and a run under a terminal like that is taken to have filled the screen.\n *\n * @since 3.0.0\n */\n\nexport const ReportTimeout = 100;\n\n/**\n * The number of bytes in one kilobyte.\n *\n * @remarks\n * Binary rather than decimal, `1024` rather than `1000`,\n * which is what makes a reported size agree with the one a file manager shows.\n *\n * @example\n * ```ts\n * 2048 / Kilobyte; // 2\n * ```\n *\n * @since 3.0.0\n */\n\nexport const Kilobyte = 1024;\n\n/**\n * The number of bytes in one megabyte.\n *\n * @remarks\n * Derived from {@link Kilobyte} rather than written out, so the two cannot drift apart,\n * and binary for the same reason it is.\n *\n * @example\n * ```ts\n * Megabyte / Kilobyte; // 1024\n * ```\n *\n * @see Kilobyte\n * @since 3.0.0\n */\n\nexport const Megabyte = Kilobyte * 1024;\n\n/**\n * The middle dot that separates one part of a line from the next.\n *\n * @remarks\n * A separator rather than a mark, so it stands between two values instead of opening a line,\n * which is what keeps it apart from {@link WarningSymbol}.\n * It also marks the quietest group of messages, where a bare dot is as much as a note deserves.\n *\n * @example\n * ```ts\n * `esm ${ DotSymbol } 12 ms`; // 'esm · 12 ms'\n * ```\n *\n * @since 3.0.0\n */\n\nexport const DotSymbol = '·';\n\n/**\n * The arrow that marks work under way.\n *\n * @remarks\n * Opens the line of a variant while it builds and the line of every output a build wrote,\n * so a reader follows what is happening down the same column.\n * One of {@link SuccessSymbol} or {@link ErrorSymbol} takes its place once the build ends.\n *\n * @example\n * ```ts\n * `${ ArrowSymbol } building esm`; // '→ building esm'\n * ```\n *\n * @since 3.0.0\n */\n\nexport const ArrowSymbol = '→';\n\n/**\n * The cross that marks a failure.\n *\n * @remarks\n * Closes the line of a variant that produced no output, and opens each of its errors,\n * so a run scanned from the left reads its failures without their text.\n *\n * @example\n * ```ts\n * `${ ErrorSymbol } esm`; // '× esm'\n * ```\n *\n * @see SuccessSymbol\n * @since 3.0.0\n */\n\nexport const ErrorSymbol = '×';\n\n/**\n * The circular arrow that marks a rebuild.\n *\n * @remarks\n * Written when a watch starts the build again, beside the reason it restarted,\n * and again on the status line while the watch rests between builds.\n *\n * @example\n * ```ts\n * `${ ReloadSymbol } 2 files changed`; // '↻ 2 files changed'\n * ```\n *\n * @since 3.0.0\n */\n\nexport const ReloadSymbol = '↻';\n\n/**\n * The bullet that marks a warning.\n *\n * @remarks\n * A filled dot rather than a cross, so a warning reads as quieter than a failure\n * and still stands out from a line carrying no mark at all.\n *\n * @example\n * ```ts\n * `${ WarningSymbol } unsupported require call`; // '• unsupported require call'\n * ```\n *\n * @see ErrorSymbol\n * @since 3.0.0\n */\n\nexport const WarningSymbol = '•';\n\n/**\n * The check mark that marks a build that finished clean.\n *\n * @remarks\n * Closes the line of a variant that wrote its output, opposite {@link ErrorSymbol},\n * so the two read as one column of outcomes down the left of a run.\n *\n * @example\n * ```ts\n * `${ SuccessSymbol } esm in 128 ms`; // '✓ esm in 128 ms'\n * ```\n *\n * @see ErrorSymbol\n * @since 3.0.0\n */\n\nexport const SuccessSymbol = '✓';\n\n/**\n * How loud each level is, as a number the levels can be compared by.\n *\n * @remarks\n * A report prints the groups that rank at or above the level the run is set to,\n * which needs an order that the level names do not carry on their own.\n * `silent` ranks above every group, so nothing reaches a run set to it.\n *\n * @example\n * ```ts\n * Levels.warning >= Levels.info; // true - warnings print at the info level\n * Levels.info >= Levels.error; // false - info is quiet at the error level\n * ```\n *\n * @see LogLevelType\n * @since 3.0.0\n */\n\nexport const Levels: Record<LogLevelType, number> = { verbose: 0, info: 1, warning: 2, error: 3, silent: 4 };\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { DeepPartialType } from '@interfaces/types.interface';\nimport type { UnsubscribeType, Observable } from '@remotex-labs/xobservable';\nimport type { ConfigurationInterface } from '@interfaces/configuration.interface';\nimport type { xBuildConfigInterface } from '@providers/interfaces/config-file-provider.interface';\n\n/**\n * Imports\n */\n\nimport { Injectable } from '@remotex-labs/xinject';\nimport { BehaviorSubject } from '@remotex-labs/xobservable';\nimport { deepMerge, equals } from '@components/object.component';\nimport { map, distinctUntilChanged } from '@remotex-labs/xobservable';\nimport { DefaultsCommonConfig } from '@constants/configuration.constant';\n\n/**\n * Holds the build configuration and lets the rest of the build watch it change.\n *\n * @typeParam T - Shape of the configuration, at least a {@link ConfigurationInterface}\n *\n * @remarks\n * The configuration is not settled once and read forever: a watch reloads the file behind it, so whatever depends on\n * a setting has to be told when it moves rather than reading it once at startup.\n * That is what {@link select} is for - it reports only when the value that a caller actually asked for has changed,\n * so a change elsewhere in the configuration wakes nobody.\n * Updates merge rather than replace, so an update says what changes and leaves the rest standing.\n * Registered as a singleton, so every consumer reads and watches the same configuration.\n *\n * @example\n * ```ts\n * const configuration = inject(ConfigurationService);\n *\n * configuration.getValue(config => config.logLevel); // info\n * configuration.select(config => config.variants)\n * .subscribe(variants => rebuild(variants)); // told whenever the variants change\n * configuration.patch({ verbose: true }); // the variant's watcher hears nothing\n * ```\n *\n * @see xBuildConfigInterface\n * @see ConfigurationInterface\n *\n * @since 2.0.0\n */\n\n@Injectable({\n scope: 'singleton'\n})\nexport class ConfigurationService<T extends ConfigurationInterface = Required<xBuildConfigInterface>> {\n /**\n * The configuration and everything watching it.\n *\n * @remarks\n * A behavior subject rather than a plain one, so a subscriber arriving late is handed the configuration as it\n * stands instead of waiting for the next change.\n *\n * @since 2.0.0\n */\n\n private readonly config$: BehaviorSubject<T>;\n\n /**\n * Creates the service around a starting configuration.\n *\n * @param initialConfig - Configuration to start from the built-in defaults when omitted\n *\n * @remarks\n * The configuration is copied on the way in, so the object handed over is never written to - which is what makes\n * the frozen defaults usable as a starting point.\n * It is also kept as it was passed, since {@link reload} needs something to return to.\n *\n * @example\n * ```ts\n * const configuration = new ConfigurationService({ variants: { esm: { esbuild: { format: 'esm' } } } });\n * configuration.getValue().variants.esm; // { esbuild: { format: 'esm' } }\n * ```\n *\n * @see DefaultsCommonConfig\n * @since 2.0.0\n */\n\n constructor(private initialConfig: T = DefaultsCommonConfig as T) {\n this.config$ = new BehaviorSubject<T>(deepMerge({}, initialConfig) as T);\n }\n\n /**\n * Reads the whole configuration as it stands.\n *\n * @returns The current configuration\n *\n * @example\n * ```ts\n * configuration.getValue().verbose; // false\n * ```\n *\n * @since 2.0.0\n */\n\n getValue(): T;\n\n /**\n * Reads one value out of the configuration as it stands.\n *\n * @typeParam R - What the selector returns\n * @param selector - Picks the value to read\n * @returns Whatever the selector returned\n *\n * @remarks\n * The one-off counterpart of {@link select}: it answers once and never again, which suits a decision taken at a\n * point in time rather than something that has to follow the configuration.\n *\n * @example\n * ```ts\n * configuration.getValue(config => Object.keys(config.variants)); // [ 'esm', 'cjs' ]\n * ```\n *\n * @since 2.0.0\n */\n\n getValue<R>(selector: (config: T) => R): R;\n\n /**\n * Serves both reading forms.\n *\n * @param selector - Picks a value, or reads the whole configuration when absent\n * @returns The configuration, or what the selector returned\n *\n * @since 2.0.0\n */\n\n getValue<R>(selector?: (config: T) => R): T | R {\n if (!selector)\n return this.config$.value;\n\n return selector(this.config$.value);\n }\n\n /**\n * Watches the whole configuration.\n *\n * @param observer - Called with the configuration, now and on every change\n * @returns A function that stops the watching\n *\n * @remarks\n * Called straight away with the configuration as it stands, so a subscriber needs no separate first read.\n * It hears every change, whatever moved, which is why {@link select} is the better choice for anything that cares\n * about one corner of the configuration.\n *\n * @example\n * ```ts\n * const stop = configuration.subscribe(config => console.log(config.verbose)); // logs at once\n * configuration.patch({ verbose: true }); // logs again\n * stop();\n * ```\n *\n * @see select\n * @since 1.0.0\n */\n\n subscribe(observer: (value: T) => void): UnsubscribeType {\n return this.config$.subscribe(observer);\n }\n\n /**\n * Watches one value in the configuration.\n *\n * @typeParam R - What the selector returns\n * @param selector - Picks the value to watch\n * @returns A stream of that value, reporting only when it has actually changed\n *\n * @remarks\n * The selector runs on every change, but its result is compared against the one before and only a real difference\n * is passed on - so a change elsewhere costs a comparison rather than the work behind a subscriber.\n * The comparison is structural, so a selector that builds an equal object each time still reports nothing.\n *\n * @example\n * ```ts\n * configuration.select(config => config.common?.esbuild?.minify)\n * .subscribe(minify => console.log(minify)); // true, then again only when it changes\n *\n * configuration.patch({ verbose: true }); // nothing reported - minify did not move\n * ```\n *\n * @see equals\n * @see subscribe\n *\n * @since 2.0.0\n */\n\n select<R>(selector: (config: T) => R): Observable<R> {\n return this.config$.pipe(\n map(selector),\n distinctUntilChanged((prev, curr) => equals(prev, curr))\n ) as Observable<R>;\n }\n\n /**\n * Merges changes into the configuration and reports them.\n *\n * @param partial - The parts to change, nested as deeply as needed\n *\n * @remarks\n * Merged over what is there now, so anything left out keeps its value and only the corners named are touched.\n * Arrays are concatenated rather than replaced, so patching a list adds to it - which is a reason to reach for\n * {@link reload} when a list has to be replaced rather than extended.\n * Every subscriber is told, while a {@link select} passes it on only if the value it picked actually moved.\n *\n * @example\n * ```ts\n * configuration.patch({ common: { esbuild: { minify: false } } });\n * configuration.getValue().common?.esbuild?.format; // 'cjs' - untouched\n * ```\n *\n * @see reload\n * @since 1.0.0\n */\n\n patch(partial: DeepPartialType<T>): void {\n const mergedConfig = deepMerge<T>(\n {} as T,\n this.config$.value,\n partial\n );\n\n this.config$.next(mergedConfig);\n }\n\n /**\n * Starts again from the initial configuration, with the given one merged over it.\n *\n * @param config - Configuration to apply over the initial one\n *\n * @remarks\n * Not a replacement: the result is the configuration this service was constructed with,\n * merged with what is passed here.\n * What the initial configuration carried therefore survives, and only what accumulated since is dropped.\n * That is what re-reading an edited file wants, since a patch has no way to take something back.\n * To be rid of the initial configuration too, construct another service.\n *\n * @example\n * ```ts\n * configuration.patch({ verbose: true });\n * configuration.reload({ common: { types: false } });\n * configuration.getValue().verbose; // false again - the patch is gone\n * ```\n *\n * @see patch\n * @since 2.0.0\n */\n\n reload(config: DeepPartialType<T>): void {\n this.config$.next(deepMerge({}, this.initialConfig, config) as T);\n }\n}\n","/**\n * Reports whether a value can be treated as a keyed object.\n *\n * @param item - Value to test\n * @returns `true` when the value is a non-null object that is not an array\n *\n * @remarks\n * Narrows to `Record<string, unknown>`, which is what lets the merge and comparison helpers index a value they were\n * handed as `unknown`.\n * Only arrays and `null` are ruled out, so a `Date`, a `RegExp`, and a class instance all pass - the callers that\n * care treat those specially before asking.\n *\n * @example\n * ```ts\n * isObject({ key: 'value' }); // true\n * isObject(new Date()); // true - an object, whatever else it is\n * isObject([]); // false\n * isObject(null); // false\n * ```\n *\n * @see deepMerge\n * @since 2.0.0\n */\n\nexport function isObject(item: unknown): item is Record<string, unknown> {\n return !!item && typeof item === 'object' && !Array.isArray(item);\n}\n\n/**\n * Reports whether a value is an ordinary keyed object rather than an instance of something.\n *\n * @param item - Value to test\n * @returns `true` when the value is an object literal, or one built with a null prototype\n *\n * @remarks\n * Where {@link isObject} asks whether a value can be indexed, this asks whether walking its keys describes it.\n * A `Date`, a `RegExp`, a `Map`, and a class instance carry their state somewhere other than their own enumerable\n * keys, so merging into a fresh object would leave nothing of them behind.\n * The test is that the prototype is a root of its chain rather than this realm's `Object.prototype`.\n * An object literal built inside a `vm` context therefore counts as plain,\n * which is what a configuration file executed in a sandbox hands back.\n *\n * @example\n * ```ts\n * isPlainObject({ key: 'value' }); // true\n * isPlainObject(Object.create(null)); // true\n * isPlainObject(runInNewContext('({ a: 1 })')); // true - plain, whatever realm built it\n * isPlainObject(/^_/); // false - a value, not a shape\n * isPlainObject(new Date()); // false\n * ```\n *\n * @see isObject\n * @see deepMerge\n *\n * @since 3.0.0\n */\n\nexport function isPlainObject(item: unknown): item is Record<string, unknown> {\n if (!isObject(item)) return false;\n const prototype = Object.getPrototypeOf(item);\n\n return prototype === null || Object.getPrototypeOf(prototype) === null;\n}\n\n/**\n * Merges objects into a target, recursing into nested objects.\n *\n * @typeParam T - Type of the object being merged into\n *\n * @param target - Object the sources are merged into, modified in place\n * @param sources - Objects to merge, applied left to right so a later one wins\n * @returns The target, for chaining\n *\n * @remarks\n * Three rules decide each key: two arrays concatenate, two plain objects merge, and anything else is overwritten.\n * A `Date`, a `RegExp`, a `Map`, and a class instance are values rather than shapes to walk,\n * so they are carried across as they stand.\n * Recursing into such a value would reduce it to a plain object holding whatever its own enumerable keys are.\n * Concatenation rather than replacement means merging the same configuration twice doubles its arrays,\n * so an accumulating merge wants a fresh target each time.\n * That is also the way to use this as a deep copy, by merging into `{}`.\n * The target is modified rather than copied, so pass a literal unless the caller means to have its object rewritten.\n *\n * @example\n * ```ts\n * deepMerge({ a: 1, b: { x: 10 } }, { b: { y: 20 }, c: 3 }); // { a: 1, b: { x: 10, y: 20 }, c: 3 }\n * deepMerge({ items: [ 1, 2 ] }, { items: [ 3 ] }); // { items: [ 1, 2, 3 ] } - concatenated\n * deepMerge({}, { pattern: /^_/ }); // { pattern: /^_/ } - the same regular expression\n * deepMerge({}, config); // a deep copy of config\n * ```\n *\n * @see isObject\n * @see isPlainObject\n *\n * @since 2.0.0\n */\n\nexport function deepMerge<T extends object>(target: T, ...sources: Array<object>): T {\n if (!sources.length) return target;\n const source = sources.shift();\n\n if (isObject(target) && isObject(source)) {\n for (const key in source) {\n const sourceValue = source[key];\n const targetValue = target[key];\n\n if (Array.isArray(sourceValue) && Array.isArray(targetValue)) {\n Object.assign(target, { [key]: [ ...targetValue, ...sourceValue ] });\n } else if (isPlainObject(sourceValue)) {\n Object.assign(target, {\n [key]: deepMerge(\n isPlainObject(targetValue) ? targetValue : {},\n sourceValue\n )\n });\n } else {\n Object.assign(target, { [key]: sourceValue });\n }\n }\n\n return deepMerge(target, ...sources);\n }\n\n return target;\n}\n\n/**\n * Compares two values by structure rather than by identity.\n *\n * @param a - First value\n * @param b - Second value\n * @param strictCheck - Whether both sides must have the same number of entries, `true` by default\n * @returns `true` when the two are equal by these rules\n *\n * @remarks\n * `Date`, `RegExp`, and `URL` are compared by what they mean - timestamp, pattern and flags, href - rather than by\n * walking their properties, which would find nothing.\n * `NaN` equals itself here, unlike under `===`.\n * `0` and `-0` compare equal, since strict equality settles them before the question of sign arises.\n * Relaxing `strictCheck` turns the comparison into a subset test: every entry of the first value must appear in the\n * second, and extra entries in the second are ignored.\n *\n * @example\n * ```ts\n * equals(NaN, NaN); // true\n * equals(new Date('2024-01-01'), new Date('2024-01-01')); // true\n * equals({ a: 1, b: { c: 2 } }, { a: 1, b: { c: 2 } }); // true\n * equals([ 1, 2 ], [ 1, 2, 3 ], false); // true - a subset\n * equals([ 1, 2 ], [ 1, 2, 3 ]); // false - lengths differ\n * ```\n *\n * @see hasKey\n * @since 2.0.0\n */\n\nexport function equals(a: unknown, b: unknown, strictCheck = true): boolean {\n if (a === b) return true;\n if (Object.is(a, b)) return true;\n if (a === null || b === null) return false;\n\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n\n if (a instanceof RegExp && b instanceof RegExp)\n return a.source === b.source && a.flags === b.flags;\n\n if (URL && a instanceof URL && b instanceof URL)\n return a.href === b.href;\n\n if (typeof a === 'object' && typeof b === 'object') {\n return deepEquals(a, b, strictCheck);\n }\n\n return false;\n}\n\n/**\n * Reports whether a key can be reached on a value.\n *\n * @param obj - Value to look in\n * @param key - Key to look for, a name or a symbol\n * @returns `true` when the key is reachable, own or inherited\n *\n * @remarks\n * Answers for objects and functions only: a primitive returns `false` even where the key would resolve, so\n * `'length'` on a string is not found here.\n * `null` and `undefined` answer `false` rather than throwing, which is the point of asking through this rather than\n * with `in` directly.\n *\n * @example\n * ```ts\n * hasKey({ name: 'test' }, 'name'); // true\n * hasKey({ name: 'test' }, 'age'); // false\n * hasKey(null, 'key'); // false\n * hasKey('string', 'length'); // false - a primitive, not an object\n * ```\n *\n * @since 2.0.0\n */\n\nexport function hasKey(obj: unknown, key: string | symbol): boolean {\n if (obj == null || (typeof obj !== 'object' && typeof obj !== 'function'))\n return false;\n\n return key in obj || Object.prototype.hasOwnProperty.call(obj, key);\n}\n\n/**\n * Compares two objects or arrays entry by entry.\n *\n * @param a - First value\n * @param b - Second value\n * @param strictCheck - Whether both sides must have the same number of entries\n * @returns `true` when every entry of the first matches the second\n *\n * @remarks\n * The recursive half of {@link equals}, which handles the special types before delegating here.\n * Position compares arrays, so the same items in another order are not equal.\n * Objects are walked by the first value's own enumerable keys, which is what makes the relaxed mode a subset test -\n * a key the second value has and the first does not is never looked at.\n *\n * @since 2.0.0\n */\n\nfunction deepEquals(a: object, b: object, strictCheck: boolean = true): boolean {\n if (Array.isArray(a) && Array.isArray(b)) {\n if(strictCheck && a.length !== b.length) return false;\n\n return a.every((val, i) => equals(val, b[i], strictCheck));\n }\n\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n if (strictCheck && aKeys.length !== bKeys.length) return false;\n\n for (const key of aKeys) {\n if (!hasKey(b, key)) return false;\n if (!equals((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key], strictCheck)) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Serializes a value to JSON, carrying a `bigint` across as a string.\n *\n * @param value - Value to serialize\n * @returns The JSON text\n *\n * @throws TypeError - Raised when the value holds a circular reference\n *\n * @remarks\n * `JSON.stringify` throws on a `bigint` rather than serializing it, so this converts each to its decimal digits on\n * the way out.\n * The digits are written as a JSON string, since JSON has no number wide enough to hold them,\n * which is what keeps a value past `Number.MAX_SAFE_INTEGER` exact.\n * A reader therefore gets a string back where a `bigint` went in.\n * Everything else behaves as `JSON.stringify` does: an `undefined` property is dropped, a `Map` and a `Set` come out\n * as `{}`, and a `Date` comes out as the string its own `toJSON` produced.\n * A top-level `undefined`, function, or symbol still yields `undefined` rather than text,\n * which the declared return type does not admit.\n *\n * @example\n * ```ts\n * stringify({ id: 9007199254740993n }); // '{\"id\":\"9007199254740993n\"}' - the digits kept exactly\n * stringify({ a: 1, b: [ 1, 2 ] }); // '{\"a\":1,\"b\":[1,2]}'\n * stringify({ a: undefined, b: 1 }); // '{\"b\":1}' - the undefined key dropped\n * stringify(undefined); // undefined - not text, despite the signature\n * ```\n *\n * @since 3.0.0\n */\n\nexport function stringify(value: unknown): string {\n return JSON.stringify(value, (_, entry) => typeof entry === 'bigint' ? entry.toString() + 'n' : entry);\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { PartialConfigurationType } from '@interfaces/configuration.interface';\n\n/**\n * The configuration that a build starts from, before a file or a flag says otherwise.\n *\n * @remarks\n * The object, its `common` block, and its `esbuild` block are each frozen,\n * so nothing can rewrite the defaults for every other consumer that reads them.\n * {@link ConfigurationService} copies it on the way in rather than holding it directly,\n * which is what keeps the freeze from turning an ordinary patch into a failure.\n * `absWorkingDir` is read when this module is first imported, so it records the directory the process started in\n * rather than wherever a later build happens to look.\n *\n * @example\n * ```ts\n * DefaultsCommonConfig.common?.esbuild?.format; // 'cjs'\n * DefaultsCommonConfig.common?.esbuild?.outdir; // 'dist'\n * ```\n *\n * @see ConfigurationService\n * @since 3.0.0\n */\n\nexport const DefaultsCommonConfig: PartialConfigurationType = Object.freeze({\n common: Object.freeze({\n types: true,\n logOverride: {},\n declaration: true,\n esbuild: Object.freeze({\n write: true,\n bundle: true,\n minify: true,\n format: 'cjs',\n outdir: 'dist',\n platform: 'browser',\n absWorkingDir: process.cwd(),\n legalComments: 'none'\n })\n })\n});\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { ModuleResolutionCache, SourceFile } from 'typescript';\nimport type { LanguageService, Diagnostic, Program } from 'typescript';\nimport type { EmitAndSemanticDiagnosticsBuilderProgram } from 'typescript';\nimport type { CacheEntryInterface } from './interfaces/typescript-service.interface';\nimport type { ParsedCommandLine, BuilderProgramHost, ReadBuildProgramHost } from 'typescript';\nimport type { DiagnosticInterface, ResolvedModuleInterface } from './interfaces/typescript-service.interface';\n\n/**\n * Imports\n */\n\nimport ts from 'typescript';\nimport { Injectable } from '@remotex-labs/xinject';\nimport { normalize, relative, dirname } from '@remotex-labs/xmap';\nimport { DeclarationModel } from '@typescript/models/declaration.model';\nimport { LanguageHostService } from '@typescript/services/host.service';\n\n/**\n * One TypeScript project, wrapping its language service, module resolution, and declaration emit.\n *\n * @remarks\n * Everything a build needs from TypeScript comes through here:\n *\n * - **Diagnostics** - {@link check}\n * - **Declaration files** - {@link emit} and {@link emitBundle}\n * - **Specifier resolution** - {@link resolve}\n *\n * Each configuration file gets one shared instance, reference counted,\n * so several consumers naming the same `tsconfig.json` share one language service,\n * and the last {@link dispose} tears it down.\n * The parse forces `emitDeclarationOnly` on,\n * since this asks the compiler for types alone while the bundler produces the JavaScript.\n *\n * @example\n * ```ts\n * const service = inject(TypescriptService, 'tsconfig.json');\n *\n * service.check(); // [] - the project type-checks\n * await service.emit({ index: 'src/index.ts' }); // [ 'D:/app/dist/index.d.ts' ]\n * service.dispose(); // released - torn down once nothing else holds it\n * ```\n *\n * @see DeclarationModel\n * @see LanguageHostService\n *\n * @since 2.0.0\n */\n\n@Injectable({\n factory(path?: string): TypescriptService {\n return TypescriptService.acquire(path);\n }\n})\nexport class TypescriptService {\n /**\n * The language service this project's queries run against.\n *\n * @remarks\n * Backed by {@link languageHostService} and a document registry,\n * so the syntax trees of shared files survive between requests.\n *\n * @example\n * ```ts\n * service.languageService.getProgram()?.getSourceFiles().length; // 214\n * ```\n *\n * @since 2.0.0\n */\n\n readonly languageService: LanguageService;\n\n /**\n * The host the language service reads files and versions through.\n *\n * @remarks\n * Exposed because it owns the tracked file set, which is what decides the program's file list.\n *\n * @example\n * ```ts\n * service.languageHostService.tracked.size; // grows as the language service resolves imports\n * ```\n *\n * @see LanguageHostService\n * @since 2.0.0\n */\n\n readonly languageHostService: LanguageHostService;\n\n /**\n * The live instances, keyed by their normalized configuration path.\n *\n * @remarks\n * Static, so sharing spans the whole process rather than one injector,\n * and each entry carries the reference count that decides when its language service is torn down.\n *\n * @see acquire\n * @since 3.0.0\n */\n\n private static readonly cache = new Map<string, CacheEntryInterface>();\n\n /**\n * The diagnostics of every file checked so far, keyed by the file name the compiler reported.\n *\n * @remarks\n * Only the affected files are recomputed on a {@link check},\n * so the untouched entries here are what makes the result whole-project rather than only-what-changed.\n * The key is the absolute path the compiler reported,\n * so a caller's own names are resolved before they are read back.\n *\n * @see reconcileDiagnostics\n * @since 3.0.0\n */\n\n private readonly diagnosticsCache = new Map<string, Array<DiagnosticInterface>>();\n\n /**\n * The host the builder program reads through.\n *\n * @remarks\n * Routes every read to {@link languageHostService},\n * so the builder sees the same cached content the language service does\n * rather than reaching the disk a second time and disagreeing with it.\n *\n * @since 3.0.0\n */\n\n private readonly builderHost: ReadBuildProgramHost & BuilderProgramHost = {\n createHash: ts.sys.createHash,\n readFile: (file: string, encoding?: BufferEncoding): string | undefined =>\n this.languageHostService.readFile(file, encoding),\n getCurrentDirectory: (): string => ts.sys.getCurrentDirectory(),\n useCaseSensitiveFileNames: (): boolean => ts.sys.useCaseSensitiveFileNames\n };\n\n /**\n * The declaration cache and emitter bound to this project.\n *\n * @remarks\n * Constructed with this service, whose {@link resolve} is what decides which specifiers name project files.\n *\n * @see DeclarationModel\n * @since 3.0.0\n */\n\n private readonly declaration: DeclarationModel;\n\n /**\n * The configuration currently in force, replaced whenever the file behind it is reparsed.\n *\n * @see parseConfig\n * @since 3.0.0\n */\n\n private parsedConfig: ParsedCommandLine;\n\n /**\n * The snapshot version of the configuration file behind the current parse.\n *\n * @remarks\n * Taken from the shared file model, which advances a version whenever the watcher re-reads a file that changed,\n * so comparing it against the version the model now holds tells {@link reload} whether anything needs reparsing.\n *\n * @see reload\n * @since 3.0.0\n */\n\n private configVersion: number;\n\n /**\n * The cache backing {@link resolve}, rebuilt whenever the compiler options change.\n *\n * @see createResolutionCache\n * @since 3.0.0\n */\n\n private resolutionCache: ModuleResolutionCache;\n\n /**\n * The builder program of the last {@link check}, carried forward, so the next check only revisits what changed.\n *\n * @remarks\n * Absent before the first check and after a {@link reload}, either of which makes the next check a full pass.\n *\n * @since 3.0.0\n */\n\n private builder?: EmitAndSemanticDiagnosticsBuilderProgram;\n\n /**\n * Creates a service for one configuration file.\n *\n * @param configPath - Path of the `tsconfig.json` to run against\n *\n * @remarks\n * Prefer injecting the service, which shares and reference counts instances per configuration path.\n * An instance built here stays outside the shared cache, so nothing else can reach it,\n * and {@link dispose} has no hold of its own to release.\n * A configuration that cannot be read does not throw - {@link parseConfig} falls back to a built-in default.\n *\n * @example\n * ```ts\n * const service = new TypescriptService('tsconfig.build.json');\n * service.config.options.emitDeclarationOnly; // true - forced on regardless of the file\n * ```\n *\n * @see acquire\n * @since 3.0.0\n */\n\n constructor(readonly configPath: string = 'tsconfig.json') {\n this.parsedConfig = this.parseConfig();\n this.languageHostService = new LanguageHostService(this.parsedConfig);\n this.configVersion = this.languageHostService.filesCache.touch(this.configPath).version;\n this.resolutionCache = this.createResolutionCache();\n this.languageService = ts.createLanguageService(\n this.languageHostService, ts.createDocumentRegistry(true)\n );\n\n this.declaration = new DeclarationModel(this);\n }\n\n /**\n * Reparses the configuration of every shared instance whose file has changed.\n *\n * @param force - Whether every instance reparses regardless of whether its configuration file has moved\n * @returns The configuration paths reparsed by this call, in the order their instances were acquired\n *\n * @remarks\n * This walks the whole shared cache rather than reaching one instance through a holder.\n * A single call after a watch event covers every project in the process,\n * and a configuration several consumers share is reparsed once rather than once per consumer.\n *\n * Each version comes from the shared file model as it stands rather than from disk,\n * since re-reading a changed file is the watcher's part,\n * so an instance whose configuration has not moved costs a map lookup and nothing more.\n *\n * Forcing skips that comparison and reparses every instance\n * that catches a change the configuration file's own version misses, such as an edit to a file it extends.\n * The cost is the state of every project in the process rather than the state of what moved.\n *\n * A change discards everything the old options fed:\n * the file set, the resolution cache, the cached declarations, the cached diagnostics, and the builder program,\n * so the next {@link check} runs as a full pass.\n * An instance the constructor built rather than the cache is never reached here.\n *\n * @example\n * ```ts\n * const service = inject(TypescriptService, 'tsconfig.json');\n *\n * TypescriptService.reload(); // [] - nothing has been written since the configuration was read\n * TypescriptService.reload(); // [ 'tsconfig.json' ] - reparsed, and service.config describes the edit\n * TypescriptService.reload(true); // [ 'tsconfig.json' ] - reparsed with nothing written since\n * ```\n *\n * @see check\n * @see acquire\n *\n * @since 3.0.0\n */\n\n static reload(force: boolean = false): Array<string> {\n const reloaded: Array<string> = [];\n for (const [ path, entry ] of TypescriptService.cache) {\n if (entry.instance.refresh(force)) reloaded.push(path);\n }\n\n return reloaded;\n }\n\n /**\n * The parsed configuration this service is running against.\n *\n * @returns The compiler options, file names, and raw configuration currently in force\n *\n * @remarks\n * {@link reload} replaces it wholesale,\n * so a reference taken from here describes the configuration as it stood when it was read.\n *\n * @example\n * ```ts\n * service.config.options.rootDir; // 'D:/app' - defaulted to the working directory when the file omits it\n * service.config.fileNames.length; // 42\n * ```\n *\n * @since 3.0.0\n */\n\n get config(): ParsedCommandLine {\n return this.parsedConfig;\n }\n\n /**\n * Type-checks the project and returns the diagnostics of the files named.\n *\n * @param reachable - Files to report on, as the build reaches them, reporting everything checked when omitted\n * @returns Diagnostics of those files, formatted for reporting\n *\n * @remarks\n * Only the files the builder reports as affected are rechecked,\n * their semantic, syntactic, and suggestion diagnostics replacing what was cached for them,\n * while untouched files keep the diagnostics they already had.\n * That is what makes the result whole-project without rechecking it whole.\n * A file matched by the configuration's `exclude` globs is skipped,\n * and a file that has left the program loses its cached diagnostics\n * rather than reporting them against a file that is no longer there.\n *\n * The check covers the program while the report covers `reachable`,\n * which is what lets several variants share one service:\n * the diagnostics are computed once for whatever changed,\n * and each variant reads back the files its own build reaches at the cost of a lookup per file.\n * Narrowing the check instead would consume a file for the variant that saw it first\n * and leave the next one with nothing to report.\n * Each name is resolved as it is read, so a build's own paths serve as they are, relative or absolute.\n *\n * @example\n * ```ts\n * service.check(); // [ { file: 'src/index.ts', line: 3, column: 7, code: 2322, category: 1, message: '...' } ]\n * service.check(); // [] once the file is fixed and the watcher has refreshed it\n *\n * service.check(context.stage.reachableFiles); // only what this variant's build reaches\n * ```\n *\n * @see DiagnosticInterface\n * @see reconcileDiagnostics\n *\n * @since 3.0.0\n */\n\n check(reachable?: Iterable<string>): Array<DiagnosticInterface> {\n const program = this.languageService.getProgram();\n if (!program) return [];\n\n const ignore = this.languageHostService.ignoreSourceFile;\n const skip = (file: SourceFile): boolean => {\n if(file.fileName.includes('node_modules')) return true;\n\n return ignore(file);\n };\n\n let affected;\n this.builder = ts.createEmitAndSemanticDiagnosticsBuilderProgram(program, this.builderHost, this.builder);\n while (affected = this.builder.getSemanticDiagnosticsOfNextAffectedFile(undefined, skip)) {\n if ('fileName' in affected.affected) {\n const file = affected.affected;\n this.diagnosticsCache.set(file.fileName, [\n ...affected.result,\n ...this.builder!.getSyntacticDiagnostics(file),\n ...this.languageService.getSuggestionDiagnostics(file.fileName)\n ].map(diagnostic => this.formatDiagnostic(diagnostic)));\n }\n }\n\n return this.reconcileDiagnostics(program, reachable ?? this.diagnosticsCache.keys());\n }\n\n /**\n * Writes one declaration file per project file the entry points reach.\n *\n * @param entryPoints - Entry files to walk, keyed by the output name each entry itself is written under\n * @param outdir - Directory to write into, defaulting to the configuration's `outDir` and then to `dist`\n * @returns The output paths written by this call, empty when everything was already current\n *\n * @remarks\n * This path always passes a directory on, so `declarationDir` is never consulted.\n * Name it explicitly to write somewhere other than `outDir`.\n * The keys name the entries alone, while the files reached through them keep the layout of the source tree.\n * Declarations come out of this project's program, so the checker writes the types the source leaves out,\n * and a type it cannot write surfaces through {@link check} rather than as a failure to write.\n *\n * @example\n * ```ts\n * await service.emit({ index: 'src/index.ts' }); // [ 'dist/index.d.ts', 'dist/builder.d.ts' ] - absolute\n * await service.emit({ index: 'src/index.ts' }); // [] - nothing changed since\n * await service.emit({ index: 'src/index.ts' }, 'types'); // the same files, written under ./types\n * ```\n *\n * @see emitBundle\n * @since 3.0.0\n */\n\n async emit(entryPoints: Record<string, string>, outdir?: string): Promise<Array<string>> {\n outdir ??= this.config.options.outDir ?? 'dist';\n\n return this.declaration.emit(entryPoints, outdir);\n }\n\n /**\n * Writes one bundled declaration file per entry point.\n *\n * @param entryPoints - Entry files to bundle, keyed by the output name each is written under\n * @param outdir - Directory to write into, defaulting to the configuration's `outDir` and then to `dist`\n * @returns The output paths written, in the order the entry points were given\n *\n * @remarks\n * Each entry becomes one file carrying the declarations of everything it reaches,\n * so a package ships a single `.d.ts` instead of a tree mirroring its source.\n * The keys name the outputs, with `.d.ts` appended to each,\n * which is the shape the bundler's own entry points take and what keeps two entries of one name apart.\n * Every call rebuilds its bundles rather than reading a cache, so unlike {@link emit} this always writes.\n *\n * @example\n * ```ts\n * await service.emitBundle({ index: 'src/index.ts' }, 'dist'); // [ 'D:/app/dist/index.d.ts' ]\n * ```\n *\n * @see emit\n * @since 3.0.0\n */\n\n async emitBundle(entryPoints: Record<string, string>, outdir?: string): Promise<Array<string>> {\n outdir ??= this.config.options.outDir ?? 'dist';\n\n return this.declaration.emitBundle(entryPoints, outdir);\n }\n\n /**\n * Re-reads a batch of files so the language service sees their current content.\n *\n * @param files - Paths to refresh, relative or absolute\n *\n * @remarks\n * Each path is tracked as it is refreshed,\n * so naming a file the program has not reached yet adds it rather than passing over it.\n *\n * @example\n * ```ts\n * service.touchFiles([ 'src/index.ts' ]);\n * service.check(); // now reflects what is on disk\n * ```\n *\n * @see LanguageHostService.refreshFiles\n * @since 2.0.0\n */\n\n touchFiles(files: Array<string>): void {\n this.languageHostService.refreshFiles(files);\n }\n\n /**\n * Resolves a specifier the way the type checker resolves it.\n *\n * @param specifier - Module specifier as written in the source\n * @param containingFile - File the specifier was written in, since resolution is relative to its directory\n * @returns The resolved module, or `undefined` when the specifier resolves to nothing\n *\n * @remarks\n * An alias or a `paths` mapping resolves the way the compiler sees it rather than the way Node would,\n * which is what lets the declarations rewrite an alias into a path that still resolves.\n * The result carries two fields beyond what the compiler returns:\n * the directory the specifier resolved against, and the path from that directory to the target.\n * The first resolution attaches both, and the cached entry serves them back.\n * With no containing file, the working directory stands in for it.\n *\n * @example\n * ```ts\n * const module = service.resolve('@components/builder', 'D:/app/src/index.ts');\n *\n * module?.resolvedFileName; // 'D:/app/src/components/builder.ts'\n * module?.relativeFileName; // './components/builder.ts'\n * module?.isExternalLibraryImport; // false - a project file, not a package\n * ```\n *\n * @see ResolvedModuleInterface\n * @since 3.0.0\n */\n\n resolve(specifier: string, containingFile?: string): ResolvedModuleInterface | undefined {\n const container = containingFile ? this.languageHostService.filesCache.resolve(dirname(containingFile)) : process.cwd();\n const dirCache = this.resolutionCache.getOrCreateCacheForDirectory(container);\n const cached = dirCache.get(specifier, undefined)?.resolvedModule;\n if(cached) return cached as ResolvedModuleInterface;\n\n const result = <ResolvedModuleInterface> ts.resolveModuleName(\n specifier, containingFile ?? '', this.parsedConfig.options, this.languageHostService, this.resolutionCache\n ).resolvedModule;\n\n if (result) {\n const path = relative(container, result.resolvedFileName);\n\n result.container = container;\n result.relativeFileName = path.startsWith('.') ? path : `./${ path }`;\n }\n\n return result;\n }\n\n /**\n * Releases this consumer's hold on the shared instance.\n *\n * @remarks\n * The language service is torn down and the instance dropped from the shared cache\n * only once the last holder has released it,\n * so a service several consumers share outlives any one of them.\n * The hold released is the one the shared cache keeps under this service's configuration path,\n * so a release takes effect only on an instance the shared cache holds.\n *\n * @example\n * ```ts\n * const service = inject(TypescriptService);\n *\n * service.dispose(); // released - torn down only if nothing else holds it\n * ```\n *\n * @see acquire\n * @since 3.0.0\n */\n\n dispose(): void {\n const entry = TypescriptService.cache.get(this.configPath);\n if (!entry) return;\n\n entry.refCount--;\n if (entry.refCount > 0) return;\n\n this.languageService.dispose();\n TypescriptService.cache.delete(this.configPath);\n }\n\n /**\n * Releases the service when it leaves a `using` scope.\n *\n * @remarks\n * Delegates to {@link dispose}, so scope-bound and explicit release share one reference count.\n *\n * @example\n * ```ts\n * {\n * using service = inject(TypescriptService);\n * service.check();\n * } // released here\n * ```\n *\n * @see dispose\n * @since 3.0.0\n */\n\n [Symbol.dispose ?? Symbol.for('Symbol.dispose')](): void {\n this.dispose();\n }\n\n /**\n * Returns the shared instance for a configuration path, creating it on the first request.\n *\n * @param path - Path of the `tsconfig.json` the instance runs against\n * @returns The instance for that path, with its reference count raised\n *\n * @remarks\n * The path is normalized before it serves as the key,\n * so the same configuration reached by two spellings is one instance.\n * The instance is constructed with that normalized key,\n * which is what lets a release find its own entry.\n * Reached through the injectable factory rather than called directly.\n *\n * @see dispose\n * @since 3.0.0\n */\n\n private static acquire(path: string = 'tsconfig.json'): TypescriptService {\n const key = normalize(path);\n const entry = TypescriptService.cache.get(key);\n\n if (entry) {\n entry.refCount++;\n\n return entry.instance;\n }\n\n const instance = new TypescriptService(key);\n TypescriptService.cache.set(key, { instance, refCount: 1 });\n\n return instance;\n }\n\n /**\n * Rebuilds everything this instance derives from its compiler options once its configuration file has moved.\n *\n * @param force - Whether the rebuild runs even though the configuration file's version has not moved\n * @returns Whether the configuration was reparsed\n *\n * @remarks\n * Split out of {@link reload}, so the shared cache decides which instance reloads,\n * while the state it rebuilds stays with the instance holding it.\n * The version is the one the shared file model already holds,\n * since re-reading a file that changed is the watcher's part,\n * so this observes a change rather than going looking for one.\n * Forcing drops that guard and rebuilds regardless,\n * which is the only way through for a change the version leaves out.\n * The version is taken and stored either way,\n * so a forced rebuild leaves nothing behind for the next call to mistake for a change.\n *\n * @see reload\n * @since 3.0.0\n */\n\n private refresh(force: boolean = false): boolean {\n const { version } = this.languageHostService.filesCache.touch(this.configPath);\n if (!force && version === this.configVersion) return false;\n\n this.configVersion = version;\n this.parsedConfig = this.parseConfig();\n this.languageHostService.options = this.parsedConfig;\n this.resolutionCache = this.createResolutionCache();\n this.declaration.clear();\n this.diagnosticsCache.clear();\n this.builder = undefined;\n\n return true;\n }\n\n /**\n * Builds the module resolution cache for the current options.\n *\n * @returns A cache keyed the way the language host normalizes paths\n *\n * @remarks\n * Real paths go through the host,\n * so a symlinked file is keyed the same here as in the file cache,\n * and the two cannot disagree about which file a specifier reached.\n *\n * @since 3.0.0\n */\n\n private createResolutionCache(): ModuleResolutionCache {\n return ts.createModuleResolutionCache(\n ts.sys.getCurrentDirectory(),\n path => this.languageHostService.realpath(path),\n this.parsedConfig.options\n );\n }\n\n /**\n * Reads the diagnostics of a set of files out of the cache, dropping whatever no longer belongs to the program.\n *\n * @param program - Program the files are looked up in\n * @param reachable - Files to read, named as the caller has them, relative or absolute\n * @returns The cached diagnostics of those files, in the order they were named\n *\n * @remarks\n * The walk covers the files asked for rather than the cache,\n * so reporting one variant's inputs costs what that variant reaches rather than what the project holds.\n * Each name is resolved before the lookup,\n * since the cache is keyed by the absolute path the compiler reported,\n * while a build names its inputs relative to its own working directory.\n * A file that leaves the program - deleted, excluded, or no longer reached -\n * would otherwise keep reporting the diagnostics it had when it left,\n * since nothing marks it affected once it is gone,\n * so a name the program no longer carries is dropped from the cache as it is read.\n *\n * @since 3.0.0\n */\n\n private reconcileDiagnostics(program: Program, reachable: Iterable<string>): Array<DiagnosticInterface> {\n const files = this.languageHostService.filesCache;\n const result: Array<DiagnosticInterface> = [];\n\n for (const name of reachable) {\n const path = files.resolve(name);\n const diagnostics = this.diagnosticsCache.get(path);\n\n if (!diagnostics) continue;\n if (program.getSourceFile(path)) result.push(...diagnostics);\n else this.diagnosticsCache.delete(path);\n }\n\n return result;\n }\n\n /**\n * Reduces a compiler diagnostic to the shape that reporting consumes.\n *\n * @param diagnostic - Diagnostic as the compiler produced it\n * @returns The message and category, with the position and code when the diagnostic has a location\n *\n * @remarks\n * Chained messages are flattened into one string, and line and column are counted from one rather than from zero,\n * since the compiler counts from zero while every editor and terminal reports from one.\n * A diagnostic with no file - a configuration error, say - carries the message and category alone.\n *\n * @see DiagnosticInterface\n * @since 2.0.0\n */\n\n private formatDiagnostic(diagnostic: Diagnostic): DiagnosticInterface {\n const result: DiagnosticInterface = {\n message: ts.flattenDiagnosticMessageText(diagnostic.messageText, '\\n'),\n category: diagnostic.category\n };\n\n if (diagnostic.file && diagnostic.start !== undefined) {\n const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);\n result.file = diagnostic.file.fileName;\n result.line = line + 1;\n result.column = character + 1;\n result.code = diagnostic.code;\n }\n\n return result;\n }\n\n /**\n * Reads the configuration file and forces the options this build depends on.\n *\n * @returns The parsed configuration, with the forced options applied\n *\n * @remarks\n * Declaration emit is forced on and source maps off,\n * since this asks the compiler for types alone while the bundler produces the JavaScript.\n * `stripInternal` and `skipLibCheck` follow from that.\n * A configuration that cannot be read yields a built-in default rather than an error,\n * so a project without a `tsconfig.json` still type-checks under sensible settings.\n * `rootDir` falls back to the working directory,\n * without which output paths would follow whichever directory the sources happen to share.\n *\n * @since 2.0.0\n */\n\n private parseConfig(): ParsedCommandLine {\n let config = ts.getParsedCommandLineOfConfigFile(\n this.configPath,\n {\n sourceMap: false,\n skipLibCheck: true,\n stripInternal: true,\n declarationMap: false,\n emitDeclarationOnly: true\n },\n {\n ...ts.sys,\n onUnRecoverableConfigFileDiagnostic: () => {}\n }\n );\n\n if (!config) {\n config = {\n options: {\n strict: true,\n target: ts.ScriptTarget.ESNext,\n module: ts.ModuleKind.NodeNext,\n sourceMap: false,\n skipLibCheck: true,\n stripInternal: true,\n declarationMap: false,\n emitDeclarationOnly: true,\n moduleResolution: ts.ModuleResolutionKind.NodeNext\n },\n errors: [],\n fileNames: [],\n projectReferences: undefined\n };\n }\n\n config.options = {\n ...config.options,\n noEmit: true,\n rootDir: config.options?.rootDir ?? process.cwd(),\n isolatedModules: false,\n useCaseSensitiveFileNames: true\n };\n\n return config;\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { TypescriptService } from '@typescript/services/typescript.service';\nimport type { DeclarationEntryInterface } from './interfaces/declaration-model.interface';\nimport type { NamedBindingInterface, ParseContextInterface } from './interfaces/declaration-model.interface';\nimport type { Declaration, Directive, ModuleExportName, Statement, StringLiteral } from '@oxc-project/types';\nimport type { BundleSurfaceInterface, MergedImportInterface } from './interfaces/declaration-model.interface';\nimport type { ExportNamedDeclaration, ImportDeclaration, TSImportEqualsDeclaration } from '@oxc-project/types';\nimport type { ExportAllDeclaration, ExportDefaultDeclaration, ExportDefaultDeclarationKind } from '@oxc-project/types';\n\n/**\n * Imports\n */\n\nimport { existsSync } from 'fs';\nimport { parseSync } from 'oxc-parser';\nimport { inject } from '@remotex-labs/xinject';\nimport { mkdir, writeFile } from 'fs/promises';\nimport { Char } from '@constants/char.constant';\nimport { FilesModel } from '@models/files.model';\nimport { join, dirname, relative } from '@remotex-labs/xmap';\nimport { applyEdits, removeNode } from '@components/transformer.component';\nimport { HeaderDeclarationBundle } from '@typescript/constants/typescript.constant';\n\n/**\n * Builds and caches the declaration of every file a build touches, in both the forms it needs.\n *\n * @remarks\n * Each file is reduced to a {@link DeclarationEntryInterface}: the standalone declaration with its project specifiers\n * resolved, the same text stripped down to inlinable declarations, and the dependency, import, and export records that\n * stripping produced.\n * Declarations are emitted by the project's own program, so the checker writes the types an annotation leaves out,\n * and an entry costs one declaration emit and one parse.\n * Both forms and every record come out of that single parse.\n * Entries are held against the snapshot version of their file,\n * so a file is rebuilt only once the file model has observed the change,\n * and {@link clear} drops the cache when the compiler options behind the entries move.\n * One instance owns one cache,\n * so a build that wants entries shared across its steps passes the model around rather than constructing a second one.\n *\n * @example\n * ```ts\n * const declarations = new DeclarationModel(inject(TypescriptService));\n * const entry = declarations.touch('src/index.ts');\n *\n * entry.content; // 'declare const version: string;\\n'\n * entry.declaration; // the same text, prefixed with its imports\n * entry.projectDependencies; // Set { 'D:/app/src/builder.ts' }\n * declarations.touch('src/index.ts') === entry; // true - unchanged file, cached entry\n * ```\n *\n * @see DeclarationEntryInterface\n * @since 3.0.0\n */\n\nexport class DeclarationModel {\n /**\n * Entries keyed by the resolved absolute path of the file they describe.\n *\n * @remarks\n * Exposed for consumers that walk an already-built graph.\n * Use {@link touch} to build or refresh an entry.\n *\n * @example\n * ```ts\n * declarations.touch('src/index.ts');\n * declarations.cache.size; // 1\n * ```\n *\n * @see DeclarationEntryInterface\n * @since 3.0.0\n */\n\n readonly cache = new Map<string, DeclarationEntryInterface>();\n\n /**\n * Shared file snapshot cache the entries are versioned against.\n *\n * @since 3.0.0\n */\n\n private readonly filesCache = inject(FilesModel);\n\n /**\n * Entry version last written to each output path.\n *\n * @remarks\n * Keyed by output path rather than source path,\n * so emitting into a different directory writes every file again instead of reporting them as already current.\n * What it records is what was written rather than what is on disk,\n * so {@link emit} checks the file is still there before it passes over one,\n * which is what makes an output that something else removed come back on the next run.\n *\n * @since 3.0.0\n */\n\n private readonly emitted = new Map<string, number>();\n\n /**\n * Creates a declaration cache bound to one TypeScript service.\n *\n * @param ts - Service whose module resolution decides which specifiers are project files\n *\n * @example\n * ```ts\n * const declarations = new DeclarationModel(inject(TypescriptService));\n * declarations.cache.size; // 0\n * ```\n *\n * @see TypescriptService\n * @since 3.0.0\n */\n\n constructor(private readonly ts: TypescriptService) {}\n\n /**\n * Drops every cached entry.\n *\n * @remarks\n * Needed when something the declarations depend on has changed without the snapshot versions reflecting it -\n * the compiler options, or the resolution cache behind them.\n * A file whose content changed does not need this, since its entry is rebuilt on the next {@link touch}.\n * The record of what already reached the disk goes with them,\n * so the next call to {@link emit} writes every file again,\n * which is also what a cleaned output directory calls for.\n *\n * @example\n * ```ts\n * declarations.touch('src/index.ts');\n * declarations.clear();\n * declarations.cache.size; // 0\n * ```\n *\n * @see touch\n * @since 3.0.0\n */\n\n clear(): void {\n this.cache.clear();\n this.emitted.clear();\n }\n\n /**\n * Returns the declaration entry of a file, building it only when the cached one is stale.\n *\n * @param path - Filesystem path of the file, relative or absolute\n * @returns The entry describing the file's declarations, dependencies, and exports\n *\n * @remarks\n * The file is tracked through the file model, so a path never seen before is read from the disk once,\n * and a tracked path costs a map lookup.\n * The cached entry is returned whenever its version still matches the file's snapshot version, which only advances\n * when the file model observes a change on disk.\n * A file that is missing or unreadable yields an entry built from empty content rather than throwing.\n *\n * @example\n * ```ts\n * const entry = declarations.touch('src/index.ts');\n * entry.version; // 1\n * declarations.touch('src/index.ts') === entry; // true\n * ```\n *\n * @see clear\n * @see DeclarationEntryInterface\n *\n * @since 3.0.0\n */\n\n touch(path: string): DeclarationEntryInterface {\n const target = this.filesCache.resolve(path);\n const file = this.filesCache.touch(target);\n const cached = this.cache.get(target);\n\n if (cached?.version === file.version) return cached;\n\n const entry = this.build(target, file.version);\n this.cache.set(target, entry);\n\n return entry;\n }\n\n /**\n * Writes one declaration file per project file the entry points reach, skipping what has not changed.\n *\n * @param entryPoints - Entry files to walk, keyed by the output name each entry itself is written under\n * @param outdir - Directory to write into, overriding the configuration's `declarationDir` and `outDir`\n * @returns The output paths written by this call, empty when everything was already current\n *\n * @remarks\n * The walk follows the dependency edges out of each entry, so a project whose `tsconfig.json` lists only its entry\n * points still emits every file those entries reach.\n * Nothing outside the project is emitted, since only project files are edges,\n * and a `.d.ts` input is skipped along with everything only it reaches - it is already a declaration.\n * A key names the output of the entry it is keyed to and of nothing else.\n * The files reached through it keep mirroring the source tree the way `tsc` lays them out:\n * `declarationDir` wins over `outDir`, and the per-file path is taken relative to `rootDir`.\n * A file whose entry was written unchanged since the last call is left alone, so a watch cycle rewrites only what\n * moved.\n *\n * @example\n * ```ts\n * await declarations.emit({ main: 'src/index.ts' }); // [ 'dist/main.d.ts', 'dist/builder.d.ts' ]\n * await declarations.emit({ main: 'src/index.ts' }); // [] - nothing changed\n * await declarations.emit({ main: 'src/index.ts' }, './types'); // the same files, written under ./types\n * ```\n *\n * @see clear\n * @see emitBundle\n *\n * @since 3.0.0\n */\n\n async emit(entryPoints: Record<string, string>, outdir?: string): Promise<Array<string>> {\n const outputs: Array<string> = [];\n const contents: Array<string> = [];\n const visited = new Set<string>();\n const names = new Map<string, string>();\n\n for (const [ name, entry ] of Object.entries(entryPoints))\n names.set(this.filesCache.resolve(entry), name);\n\n const pending = [ ...names.keys() ];\n while (pending.length > 0) {\n const target = pending.pop()!;\n if (visited.has(target) || target.endsWith('.d.ts')) continue;\n visited.add(target);\n\n const entry = this.touch(target);\n for (const dependency of entry.projectDependencies)\n if (!visited.has(dependency)) pending.push(dependency);\n\n const output = this.outputPath(target, outdir, names.get(target));\n if (this.emitted.get(output) === entry.version && existsSync(output)) continue;\n\n this.emitted.set(output, entry.version);\n outputs.push(output);\n contents.push(entry.declaration);\n }\n\n return this.write(outputs, contents);\n }\n\n /**\n * Bundles every entry point and writes each one to a declaration file of its own.\n *\n * @param entryPoints - Entry files to bundle, keyed by the output name each is written under\n * @param outdir - Directory to write into, overriding the configuration's `declarationDir` and `outDir`\n * @returns The output paths written, in the order the entry points were given\n *\n * @remarks\n * The key names the output rather than the source doing so, `.d.ts` being appended to it, so two entries both\n * called `index.ts` are told apart by the names they were keyed under.\n * A key carrying a directory writes into it, and the directory is created if it is not there.\n * Bundles are always rebuilt, since assembling one from cached entries costs little,\n * and they open with {@link HeaderDeclarationBundle} so a generated file is recognizable as one.\n * With no output directory configured or passed, they land in the working directory.\n *\n * @example\n * ```ts\n * await declarations.emitBundle({ index: 'src/index.ts', 'utils/index': 'src/utils/index.ts' }, 'dist/types');\n * // [ 'D:/app/dist/types/index.d.ts', 'D:/app/dist/types/utils/index.d.ts' ]\n * ```\n *\n * @see emit\n * @since 3.0.0\n */\n\n async emitBundle(entryPoints: Record<string, string>, outdir?: string): Promise<Array<string>> {\n const options = this.ts.config.options;\n const base = this.filesCache.resolve(outdir ?? options.declarationDir ?? options.outDir ?? '.');\n\n return this.write(\n Object.keys(entryPoints).map(name => join(base, `${ name }.d.ts`)),\n Object.values(entryPoints).map(entry => this.bundle(entry))\n );\n }\n\n /**\n * Builds the bundled declaration text of one entry point.\n *\n * @param entry - Filesystem path of the entry file, relative or absolute\n * @returns The complete declaration file content, header included\n *\n * @remarks\n * Nothing is written and nothing is cached beyond the entries themselves, so the same entry can be bundled\n * repeatedly, and each call reflects the files as the cache currently sees them.\n * Declarations are inlined once per file even when several files depend on it, and a dependency cycle is walked\n * once rather than followed around.\n *\n * @see render\n * @since 3.0.0\n */\n\n private bundle(entry: string): string {\n const target = this.filesCache.resolve(entry);\n const node = this.touch(target);\n\n return this.render(this.collectClosure(target, node), this.collectSurface(target, node));\n }\n\n /**\n * Creates the directories of a batch and writes its files concurrently.\n *\n * @param outputs - Absolute output paths to write\n * @param contents - Content of each output, in the same order\n * @returns The written paths, for direct return by callers\n *\n * @remarks\n * Each directory is created once for the whole batch rather than once per file, and an empty batch touches the disk\n * not at all.\n *\n * @since 3.0.0\n */\n\n private async write(outputs: Array<string>, contents: Array<string>): Promise<Array<string>> {\n if (outputs.length < 1) return outputs;\n\n const directories = new Set(outputs.map(output => dirname(output)));\n await Promise.all([ ...directories ].map(directory => mkdir(directory, { recursive: true })));\n await Promise.all(outputs.map((output, index) => writeFile(output, contents[index], 'utf-8')));\n\n return outputs;\n }\n\n /**\n * Maps a source path to the declaration path it is written to.\n *\n * @param source - Resolved absolute path of the source file\n * @param outdir - Directory overriding both configured output directories\n * @param name - Output name to use instead of the one the source implies, carrying no extension\n * @returns The absolute output path\n *\n * @remarks\n * The directory is the first of `outdir`, `declarationDir`, and `outDir` that is set,\n * and the source's own directory only when none of them is.\n * A name replaces everything the source would have decided, `.d.ts` being appended to it, and a name carrying a\n * directory nests the output inside the base.\n * Without one the path mirrors the source tree relative to `rootDir` - the source directory standing in when no\n * `rootDir` is set, which flattens the output the way `tsc` does - and the extension follows the input, so `.ts`\n * and `.tsx` become `.d.ts` while `.mts` and `.cts` keep their module flavor as `.d.mts` and `.d.cts`.\n *\n * @since 3.0.0\n */\n\n private outputPath(source: string, outdir?: string, name?: string): string {\n const { declarationDir, outDir, rootDir } = this.ts.config.options;\n const base = outdir ?? declarationDir ?? outDir;\n const target = base ? this.filesCache.resolve(base) : dirname(source);\n if (name) return join(target, `${ name }.d.ts`);\n\n const root = rootDir ? this.filesCache.resolve(rootDir) : dirname(source);\n\n return join(target, relative(root, source).replace(/\\.([cm]?)tsx?$/, '.d.$1ts'));\n }\n\n /**\n * Collects every project file the entry reaches, dependencies first.\n *\n * @param target - Resolved absolute path of the entry file\n * @param entry - Cache entry of the entry file\n * @returns The entries to inline, in the order their content is concatenated\n *\n * @remarks\n * A depth-first walk over the dependency edges with an explicit stack, so a deep dependency chain cannot overflow\n * the stack, and a visited set, so a cycle terminates, and a shared dependency is inlined once.\n * The entry counts as visited from the start, so a dependency cycling back to it does not inline it twice, and it\n * lands last regardless, which keeps the file the bundle describes at the bottom.\n *\n * @since 3.0.0\n */\n\n private collectClosure(target: string, entry: DeclarationEntryInterface): Array<DeclarationEntryInterface> {\n const visited = new Set<string>([ target ]);\n const closure: Array<DeclarationEntryInterface> = [];\n const pending = [ ...entry.projectDependencies ];\n\n while (pending.length > 0) {\n const dependency = pending.pop()!;\n if (visited.has(dependency)) continue;\n visited.add(dependency);\n\n const node = this.touch(dependency);\n closure.push(node);\n\n for (const nested of node.projectDependencies)\n if (!visited.has(nested)) pending.push(nested);\n }\n\n closure.push(entry);\n\n return closure;\n }\n\n /**\n * Collects the names and re-export statements the bundle exposes.\n *\n * @param target - Resolved absolute path of the entry file\n * @param entry - Cache entry of the entry file\n * @returns The entry's surface, merged with the surface of every project file it star re-exports\n *\n * @remarks\n * Star re-exports of project files are followed transitively, their names becoming the entry's own, while package\n * re-exports are kept as statements and passed straight through.\n * The entry counts as visited from the start, so a star re-export cycling back to it is not walked again.\n * Namespace re-exports of project files are left out: flattening one would mean synthesizing a `declare namespace`\n * around the target's exports, which the inlined fragments do not describe well enough.\n *\n * @see BundleSurfaceInterface\n * @since 3.0.0\n */\n\n private collectSurface(target: string, entry: DeclarationEntryInterface): BundleSurfaceInterface {\n const exports = new Set<string>();\n const statements = new Set<string>();\n const visited = new Set<string>([ target ]);\n const pending = [ entry ];\n\n while (pending.length > 0) {\n const node = pending.pop()!;\n for (const binding of node.projectExports.exports) exports.add(this.clause(binding));\n\n for (const [ module, bindings ] of Object.entries(node.packageExports)) {\n if (bindings.star) statements.add(`export * from '${ module }';`);\n if (bindings.named?.length)\n statements.add(`export { ${ bindings.named.map(binding => this.clause(binding)).join(', ') } } from '${ module }';`);\n\n for (const name of bindings.namespaces ?? []) statements.add(`export * as ${ name } from '${ module }';`);\n }\n\n for (const star of node.projectExports.star) {\n if (visited.has(star)) continue;\n visited.add(star);\n pending.push(this.touch(star));\n }\n }\n\n return { exports, statements };\n }\n\n /**\n * Merges the package imports of every inlined file into one record per module.\n *\n * @param closure - Entries whose content the bundle carries\n * @returns The merged bindings, keyed by module specifier in first-seen order\n *\n * @remarks\n * One pass over the files and their modules folds each module's side effect flag, default binding, namespaces,\n * and named bindings into a single record the bundle can write back as statements.\n *\n * @see MergedImportInterface\n * @since 3.0.0\n */\n\n private mergeImports(closure: Array<DeclarationEntryInterface>): Map<string, MergedImportInterface> {\n const merged = new Map<string, MergedImportInterface>();\n\n for (const node of closure) {\n for (const [ module, bindings ] of Object.entries(node.packageImports)) {\n let entry = merged.get(module);\n if (!entry) merged.set(module, entry = { side: false, named: new Set(), namespaces: new Set() });\n\n if (bindings.side) entry.side = true;\n entry.default ??= bindings.default;\n for (const name of bindings.namespaces ?? []) entry.namespaces.add(name);\n for (const binding of bindings.named ?? []) entry.named.add(this.clause(binding));\n }\n }\n\n return merged;\n }\n\n /**\n * Writes the merged imports back out as import statements.\n *\n * @param merged - Bindings collected per module\n * @returns One statement per import form a module was used with\n *\n * @remarks\n * A module can need several statements: a side effect import, one for each namespace binding,\n * and one carrying its default and named bindings together.\n * Named bindings are sorted, so the same set of files always produces the same bundle.\n *\n * @since 3.0.0\n */\n\n private renderImports(merged: Map<string, MergedImportInterface>): Array<string> {\n const statements: Array<string> = [];\n\n for (const [ module, entry ] of merged) {\n if (entry.side) statements.push(`import '${ module }';`);\n for (const name of entry.namespaces) statements.push(`import * as ${ name } from '${ module }';`);\n\n const clauses: Array<string> = [];\n if (entry.default) clauses.push(entry.default);\n if (entry.named.size > 0) clauses.push(`{ ${ [ ...entry.named ].sort().join(', ') } }`);\n if (clauses.length > 0) statements.push(`import ${ clauses.join(', ') } from '${ module }';`);\n }\n\n return statements;\n }\n\n /**\n * Assembles the finished bundle from its header, imports, inlined content, and exports.\n *\n * @param closure - Entries to inline, dependencies first\n * @param surface - Names and statements the bundle exposes\n * @returns The complete declaration file content\n *\n * @remarks\n * Imports are merged over the whole closure rather than the surface, since every inlined declaration is free to\n * reference them, while the exports come from the surface alone.\n * A bundle that exposes nothing still closes with an empty export clause, without which its declarations would be\n * read as globals rather than as a module.\n *\n * @see HeaderDeclarationBundle\n * @since 3.0.0\n */\n\n private render(closure: Array<DeclarationEntryInterface>, surface: BundleSurfaceInterface): string {\n const parts: Array<string> = [ HeaderDeclarationBundle ];\n const imports = this.renderImports(this.mergeImports(closure));\n if (imports.length > 0) parts.push(...imports, '');\n\n for (const node of closure) {\n const content = node.content.trim();\n if (content) parts.push(content, '');\n }\n\n if (surface.exports.size > 0) parts.push(`export {\\n\\t${ [ ...surface.exports ].sort().join(',\\n\\t') }\\n};`);\n parts.push(...surface.statements);\n if (surface.exports.size < 1 && surface.statements.size < 1) parts.push('export {};');\n\n return `${ parts.join('\\n') }\\n`;\n }\n\n /**\n * Writes a binding the way an import or export clause spells it.\n *\n * @param binding - Name and the alias it was renamed to, if any\n * @returns The bare name, or `name as alias` when the clause renamed it\n *\n * @see NamedBindingInterface\n * @since 3.0.0\n */\n\n private clause(binding: NamedBindingInterface): string {\n return binding.alias ? `${ binding.name } as ${ binding.alias }` : binding.name;\n }\n\n /**\n * Emits the declarations of one file through the project's program.\n *\n * @param target - Resolved absolute path of the file\n * @returns The emitted declaration text, empty when the program reaches the file not at all\n *\n * @remarks\n * The emit runs against the shared program, so the checker supplies whatever an annotation leaves out\n * rather than every exported symbol having to spell its own type.\n * `forceDtsEmit` is what returns the text at all, since the parsed configuration forces `noEmit` on\n * to keep the compiler off the disk the bundler writes to.\n * A path the program has not reached is tracked and the program asked once more,\n * which covers a file the build reaches while `tsconfig.json` neither lists nor includes it.\n * A path its `exclude` globs match stays out even then, and yields no declarations rather than an error.\n *\n * @since 3.0.0\n */\n\n private emitDeclaration(target: string): string {\n const service = this.ts.languageService;\n\n if (!service.getProgram()?.getSourceFile(target)) {\n this.ts.touchFiles([ target ]);\n if (!service.getProgram()?.getSourceFile(target)) return '';\n }\n\n return service.getEmitOutput(target, true, true)\n .outputFiles.find(file => file.name.endsWith('.d.ts'))?.text ?? '';\n }\n\n /**\n * Emits the declarations of one file and reduces them to a cache entry.\n *\n * @param target - Resolved absolute path of the file\n * @param version - Snapshot version the entry is recorded against\n * @returns The freshly built entry\n *\n * @remarks\n * The emitted text is parsed once, and that parse drives everything: the statement walk queues both edit lists and\n * records the graph, and the comment walk that follows it queues the doc comments the stripping orphaned.\n * Emit diagnostics are not surfaced here - a declaration the checker cannot write is reported against the source\n * file itself by {@link TypescriptService.check}.\n *\n * @see strip\n * @see emitDeclaration\n * @see pruneComments\n *\n * @since 3.0.0\n */\n\n private build(target: string, version: number): DeclarationEntryInterface {\n // const declaration = isolatedDeclarationSync(target, source, { stripInternal: true }).code;\n const declaration = this.emitDeclaration(target);\n const context: ParseContextInterface = {\n edits: [],\n target,\n parsed: parseSync(target, declaration, { sourceType: 'module' }),\n content: declaration,\n bundleEdits: [],\n packageImports: Object.create(null),\n packageExports: Object.create(null),\n projectExports: { star: new Set(), exports: [], namespace: Object.create(null) },\n projectDependencies: new Set()\n };\n\n const kept: Array<number> = [];\n const { body } = context.parsed.program;\n\n for (const statement of body)\n if (this.strip(statement, context)) kept.push(statement.start);\n\n this.pruneComments(context, body, kept);\n\n return {\n version,\n content: applyEdits(declaration, context.bundleEdits),\n declaration: applyEdits(declaration, context.edits),\n packageImports: context.packageImports,\n packageExports: context.packageExports,\n projectExports: context.projectExports,\n projectDependencies: context.projectDependencies\n };\n }\n\n /**\n * Dispatches one top-level statement to the handler for its module syntax.\n *\n * @param statement - Statement to strip\n * @param context - Pass the edits are queued against and the bindings recorded on\n * @returns Whether the statement survives in the stripped content\n *\n * @remarks\n * Only top-level statements are visited, since only those can carry module syntax.\n * `export =` and `export as namespace` are dropped without a record: both describe how a module is consumed whole,\n * which a fragment inlined into a bundle can no longer express.\n * Anything that is not module syntax is kept untouched.\n *\n * @since 3.0.0\n */\n\n private strip(statement: Directive | Statement, context: ParseContextInterface): boolean {\n switch (statement.type) {\n case 'ImportDeclaration':\n this.stripImport(statement, context);\n\n return false;\n\n case 'ExportAllDeclaration':\n this.stripStarExport(statement, context);\n\n return false;\n\n case 'ExportNamedDeclaration':\n return this.stripNamedExport(statement, context);\n\n case 'ExportDefaultDeclaration':\n return this.stripDefaultExport(statement, context);\n\n case 'TSImportEqualsDeclaration':\n return this.stripImportEquals(statement, context);\n\n case 'TSExportAssignment':\n case 'TSNamespaceExportDeclaration':\n removeNode(statement, context.content, context.bundleEdits);\n\n return false;\n\n default:\n return true;\n }\n }\n\n /**\n * Removes an `import` statement, recording either a dependency or the package bindings it pulled in.\n *\n * @param statement - Import statement to strip\n * @param context - Pass the deletion is queued against\n *\n * @remarks\n * An import of a project file only contributes an edge, since the target's declarations are inlined,\n * and its bindings are already in scope in the bundle.\n * Everything else is recorded per module, so the bundle can reissue one import statement for it.\n *\n * @see link\n * @since 3.0.0\n */\n\n private stripImport(statement: ImportDeclaration, context: ParseContextInterface): void {\n removeNode(statement, context.content, context.bundleEdits);\n if (this.link(statement.source, context)) return;\n\n const module = context.packageImports[statement.source.value] ??= {};\n if (statement.specifiers.length < 1) {\n module.side = true;\n\n return;\n }\n\n for (const entry of statement.specifiers) {\n switch (entry.type) {\n case 'ImportDefaultSpecifier':\n module.default ??= entry.local.name;\n break;\n\n case 'ImportNamespaceSpecifier':\n (module.namespaces ??= []).push(entry.local.name);\n break;\n\n default:\n (module.named ??= []).push(this.binding(this.nameOf(entry.imported), entry.local.name));\n }\n }\n }\n\n /**\n * Removes an `import x = require('module')` statement the way its ESM equivalent is removed.\n *\n * @param statement - Import-equals statement to strip\n * @param context - Pass the deletion is queued against\n * @returns Whether the statement survives in the stripped content\n *\n * @remarks\n * Only the external-module form names a module.\n * `import A = B.C` aliases a local name and is kept as it stands, since the namespace it reaches into is inlined\n * with the rest of the fragment.\n * A package binding is recorded as a namespace import, which is what `require` binds in type space.\n *\n * @see stripImport\n * @since 3.0.0\n */\n\n private stripImportEquals(statement: TSImportEqualsDeclaration, context: ParseContextInterface): boolean {\n const { moduleReference } = statement;\n if (moduleReference.type !== 'TSExternalModuleReference') return true;\n\n removeNode(statement, context.content, context.bundleEdits);\n const source = moduleReference.expression;\n\n if (!this.link(source, context))\n ((context.packageImports[source.value] ??= {}).namespaces ??= []).push(statement.id.name);\n\n return false;\n }\n\n /**\n * Strips an `export` that carries a declaration, a specifier list, or a re-export clause.\n *\n * @param statement - Named export statement to strip\n * @param context - Pass the edits are queued against\n * @returns Whether the statement survives in the stripped content\n *\n * @remarks\n * A declaration keeps its body and loses only the `export` keyword, so `export declare const x` becomes\n * `declare const x` and stays valid where the fragment lands.\n * A specifier list is removed outright: names re-exported from a project file, or from nothing at all, are recorded\n * as this file's own surface, since the declarations behind them are inlined.\n * Only a clause pointing at a package is recorded as a re-export the bundle has to emit again.\n *\n * @see collectDeclared\n * @since 3.0.0\n */\n\n private stripNamedExport(statement: ExportNamedDeclaration, context: ParseContextInterface): boolean {\n const { exports } = context.projectExports;\n\n if (statement.declaration) {\n this.collectDeclared(statement.declaration, exports);\n context.bundleEdits.push({ start: statement.start, end: statement.declaration.start });\n\n return true;\n }\n\n removeNode(statement, context.content, context.bundleEdits);\n const named = statement.source && !this.link(statement.source, context)\n ? (context.packageExports[statement.source.value] ??= {}).named ??= []\n : exports;\n\n for (const entry of statement.specifiers)\n named.push(this.binding(this.nameOf(entry.local), this.nameOf(entry.exported)));\n\n return false;\n }\n\n /**\n * Removes an `export *` statement, recording the module or project file behind it.\n *\n * @param statement - Star export statement to strip\n * @param context - Pass the deletion is queued against\n *\n * @remarks\n * A star export of a project file becomes an edge plus an entry the bundler follows to collect the names it\n * exposes, whereas a namespace form records the name it is exposed under instead.\n *\n * @see link\n * @since 3.0.0\n */\n\n private stripStarExport(statement: ExportAllDeclaration, context: ParseContextInterface): void {\n removeNode(statement, context.content, context.bundleEdits);\n\n const target = this.link(statement.source, context);\n const exposed = statement.exported ? this.nameOf(statement.exported) : null;\n\n if (target) {\n if (exposed) context.projectExports.namespace[exposed] = target;\n else context.projectExports.star.add(target);\n\n return;\n }\n\n const module = context.packageExports[statement.source.value] ??= {};\n if (exposed) (module.namespaces ??= []).push(exposed);\n else module.star = true;\n }\n\n /**\n * Strips an `export default`, keeping the declaration behind it whenever there is one to keep.\n *\n * @param statement - Default export statement to strip\n * @param context - Pass the edits are queued against\n * @returns Whether the statement survives in the stripped content\n *\n * @remarks\n * A named class, function, or interface keeps its body and is recorded as `Name as default`,\n * with `export default` rewritten to `declare` so the fragment stays a valid ambient declaration.\n * A default export of an identifier is dropped, since the declaration it names is a statement of its own that\n * the fragment already carries.\n * An anonymous default has no binding a bundle could re-export, so it is dropped without a record.\n *\n * @see defaultBinding\n * @since 3.0.0\n */\n\n private stripDefaultExport(statement: ExportDefaultDeclaration, context: ParseContextInterface): boolean {\n const { declaration } = statement;\n const local = this.defaultBinding(declaration);\n if (local) context.projectExports.exports.push({ name: local, alias: 'default' });\n\n if (local && declaration.type !== 'Identifier') {\n context.bundleEdits.push({ start: statement.start, end: declaration.start, text: 'declare ' });\n\n return true;\n }\n\n removeNode(statement, context.content, context.bundleEdits);\n\n return false;\n }\n\n /**\n * Queues the removal of every doc comment the stripping left attached to nothing.\n *\n * @param context - Pass the deletions are queued against\n * @param body - Top-level statements of the file, in source order\n * @param kept - Start offsets of the surviving statements, in source order\n *\n * @remarks\n * Only comments that sit between two top-level statements are judged, so the documentation a surviving declaration\n * carries on its own members is never touched.\n * Such a comment is kept when nothing but whitespace separates it from the next surviving statement.\n * Anything else - a stripped statement between the two, another comment, or a trailing position with no statement\n * after it at all - makes it an orphan.\n * Only `/**` comments are considered, so line comments and plain block comments stay put.\n * Comments and statements are both in source order, so all three are walked together in one pass,\n * and a file with many comments does not cost a scan per comment.\n *\n * @see build\n * @since 3.0.0\n */\n\n private pruneComments(context: ParseContextInterface, body: Array<Directive | Statement>, kept: Array<number>): void {\n const { content, bundleEdits } = context;\n let inner = 0;\n let index = 0;\n\n for (const comment of context.parsed.comments) {\n if (comment.type !== 'Block' || comment.value.charCodeAt(0) !== Char.Star) continue;\n\n while (inner < body.length && body[inner].end <= comment.start) inner++;\n if (inner < body.length && body[inner].start < comment.start) continue;\n\n while (index < kept.length && kept[index] < comment.end) index++;\n if (index < kept.length && this.blank(content, comment.end, kept[index])) continue;\n\n removeNode(comment, content, bundleEdits);\n }\n }\n\n /**\n * Resolves a specifier, recording it as a dependency and rewriting it when it names a project file.\n *\n * @param source - Specifier literal as written in the declaration\n * @param context - Pass the specifier was read from\n * @returns The resolved absolute path, or `null` when the specifier names a package or does not resolve\n *\n * @remarks\n * The one place a specifier is looked at, so the two outputs cannot disagree on which files are inlined.\n * An internal target leaves an edge behind for the bundle and a relative rewrite for the standalone declaration,\n * while a package leaves both untouched.\n * The rewrite names the declaration rather than the source, the resolved extension giving way to `.d.ts`, so an\n * emitted file points at the file emitted beside it rather than at a source that was never shipped.\n * Resolution goes through the TypeScript service, so aliases and `paths` mappings resolve the way the type checker\n * sees them rather than the way Node would, and the path it reports is normalized the way the file cache keys are.\n *\n * @since 3.0.0\n */\n\n private link(source: StringLiteral, context: ParseContextInterface): string | null {\n const resolved = this.ts.resolve(source.value, context.target);\n if (!resolved || resolved.isExternalLibraryImport) return null;\n\n const { extension, relativeFileName, resolvedFileName } = resolved;\n const target = this.filesCache.resolve(resolvedFileName);\n\n context.projectDependencies.add(target);\n context.edits.push({\n end: source.end,\n start: source.start,\n text: `'${ extension ? relativeFileName.slice(0, -extension.length) : relativeFileName }.d.ts'`\n });\n\n return target;\n }\n\n /**\n * Appends the names a declaration binds to the exported surface.\n *\n * @param declaration - Declaration carried by an `export` statement\n * @param names - Bindings the declared names are appended to\n *\n * @remarks\n * A variable statement can bind several names at once, while every other declaration binds at most one.\n * Bindings that are not plain identifiers - a destructured variable, or an ambient module declared by its quoted\n * path - contribute nothing, having no name a bundle could re-export.\n *\n * @since 3.0.0\n */\n\n private collectDeclared(declaration: Declaration, names: Array<NamedBindingInterface>): void {\n if (declaration.type === 'VariableDeclaration') {\n for (const entry of declaration.declarations)\n if (entry.id.type === 'Identifier') names.push({ name: entry.id.name });\n\n return;\n }\n\n if ('id' in declaration && declaration.id && 'name' in declaration.id) names.push({ name: declaration.id.name });\n }\n\n /**\n * Returns the local name a default export binds, when it binds one.\n *\n * @param declaration - Declaration or expression behind `export default`\n * @returns The bound name, or `undefined` for an anonymous or non-binding default\n *\n * @since 3.0.0\n */\n\n private defaultBinding(declaration: ExportDefaultDeclarationKind): string | undefined {\n if (declaration.type === 'Identifier') return declaration.name;\n\n return 'id' in declaration ? declaration.id?.name : undefined;\n }\n\n /**\n * Reads the name out of an import or export clause entry.\n *\n * @param name - Identifier or string literal naming a binding\n * @returns The identifier, or the literal re-quoted so it can be emitted back into a clause\n *\n * @since 3.0.0\n */\n\n private nameOf(name: ModuleExportName): string {\n return 'name' in name ? name.name : JSON.stringify(name.value);\n }\n\n /**\n * Pairs the name a binding carries on the module with its local name.\n *\n * @param name - Name the binding is known by on the other side of the clause\n * @param alias - Local name the clause binds it under\n * @returns The bare name when the two match, and the pair when the clause renamed it\n *\n * @see NamedBindingInterface\n * @since 3.0.0\n */\n\n private binding(name: string, alias: string): NamedBindingInterface {\n return name === alias ? { name } : { name, alias };\n }\n\n /**\n * Reports whether a range of the content holds nothing but whitespace.\n *\n * @param content - Text the range points into\n * @param start - Inclusive start offset of the range\n * @param end - Exclusive end offset of the range\n * @returns `true` when every character in the range is a space, tab, or line break\n *\n * @remarks\n * Scans in place and stops at the first other character, so it costs nothing on the long ranges left behind by\n * stripped statements and allocates no substring on the short ones.\n *\n * @since 3.0.0\n */\n\n private blank(content: string, start: number, end: number): boolean {\n for (let index = start; index < end; index++) {\n const code = content.charCodeAt(index);\n if (code !== Char.Space && code !== Char.Tab && code !== Char.Lf && code !== Char.Cr) return false;\n }\n\n return true;\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { ParseResult } from 'oxc-parser';\nimport type { Span, StringLiteral } from '@oxc-project/types';\nimport type { TypescriptService } from '@typescript/services/typescript.service';\nimport type { SourceEditInterface } from './interfaces/transformer-component.interface';\n\n/**\n * Imports\n */\n\nimport { Char } from '@constants/char.constant';\n\n/**\n * Records an edit that deletes a node along with the rest of its line.\n *\n * @param node - Span of the node to delete, as the parser reported it\n * @param content - Source text the span points into\n * @param edits - Collector the deletion is appended to\n *\n * @remarks\n * The deleted range runs from the start of the node through the spaces and tabs that follow it and one line terminator,\n * so a statement that sat alone on its line does not leave a blank line behind.\n * Anything before the node on that line is kept, since the scan only moves forward from the node's end.\n *\n * @example\n * ```ts\n * const content = \"import 'a';\\nconst x = 1;\";\n * const edits: Array<SourceEditInterface> = [];\n *\n * removeNode({ start: 0, end: 11 }, content, edits);\n * edits; // [ { start: 0, end: 12 } ]\n * applyEdits(content, edits); // 'const x = 1;'\n * ```\n *\n * @see applyEdits\n * @since 3.0.0\n */\n\nexport function removeNode(node: Span, content: string, edits: Array<SourceEditInterface>): void {\n let cursor = node.end;\n\n while (cursor < content.length) {\n const code = content.charCodeAt(cursor);\n if (code !== Char.Space && code !== Char.Tab) break;\n cursor++;\n }\n if (content.charCodeAt(cursor) === Char.Cr) cursor++;\n if (content.charCodeAt(cursor) === Char.Lf) cursor++;\n\n edits.push({ start: node.start, end: cursor });\n}\n\n/**\n * Rewrites the source text with a set of edits applied.\n *\n * @param content - Source text the edits point into\n * @param edits - Edits to apply, sorted in place by start offset\n * @returns The rewritten text, or `content` itself when there is nothing to apply\n *\n * @remarks\n * The edits are ordered by start offset and applied left to right,\n * so a transform can collect them in whatever order it walks the tree.\n * An edit starting inside a range an earlier edit already replaced is dropped rather than merged,\n * which keeps the output well-formed when two passes claim overlapping spans.\n * An edit carrying no `text` deletes its span.\n * The array is sorted in place, so a caller that depends on its original order should pass a copy.\n *\n * @example\n * ```ts\n * applyEdits('const a = 1;', [ { start: 0, end: 5, text: 'let' } ]); // 'let a = 1';\n * applyEdits('const a = 1;', [ { start: 0, end: 6 } ]); // 'a = 1;' - deleted\n * applyEdits('const a = 1;', []); // 'const a = 1;' - returned untouched\n * ```\n *\n * @see SourceEditInterface\n * @since 3.0.0\n */\n\nexport function applyEdits(content: string, edits: Array<SourceEditInterface>): string {\n if (edits.length < 1) return content;\n edits.sort((left, right) => left.start - right.start);\n\n const parts: Array<string> = new Array(edits.length * 2 + 1);\n let index = 0;\n let cursor = 0;\n\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i];\n if (edit.start < cursor) continue;\n parts[index++] = content.slice(cursor, edit.start);\n parts[index++] = edit.text ?? '';\n cursor = edit.end;\n }\n\n parts[index++] = content.slice(cursor);\n parts.length = index;\n\n return parts.join('');\n}\n\n/**\n * Queues an edit rewriting a specifier to the relative path of the project file it resolves to.\n *\n * @param source - Specifier literal to rewrite, or `null` when the statement carries none\n * @param target - Resolved absolute path of the file the specifier was written in\n * @param edits - Collector the rewrite is appended to\n * @param ts - Service whose module resolution decides what the specifier names\n *\n * @remarks\n * Only a project file is rewritten, so a specifier naming a package or resolving nowhere is left as it was written.\n * So is a statement with no specifier at all, which is what `export { a }` without a `from` clause looks like.\n * The replacement is measured from the importing file's own directory and carries no extension,\n * so an alias or a `paths` mapping becomes a specifier that still resolves once the file no longer sits in the source\n * tree.\n *\n * @example\n * ```ts\n * const edits: Array<SourceEditInterface> = [];\n *\n * rewrite(statement.source, 'D:/app/src/index.ts', edits, ts);\n * edits; // [ { start: 21, end: 43, text: \"'./components/builder.js'\" } ]\n * ```\n *\n * @see resolveSource\n * @since 3.0.0\n */\n\nexport function rewrite(source: StringLiteral | null, target: string, edits: Array<SourceEditInterface>, ts: TypescriptService): void {\n if (!source) return;\n\n const resolved = ts.resolve(source.value, target);\n if (!resolved || resolved.isExternalLibraryImport) return;\n const { extension, relativeFileName } = resolved;\n const path = extension ? relativeFileName.slice(0, -extension.length) : relativeFileName;\n\n edits.push({ end: source.end, start: source.start, text: `'${ path }.js'` });\n}\n\n/**\n * Rewrites every project specifier in a parsed file and returns the text with the rewrites applied.\n *\n * @param parse - Parse of the text, whose spans are offsets into `content`\n * @param target - Resolved absolute path of the file the text belongs to\n * @param content - The text the parse describes, handed back unchanged when it is empty\n * @param ts - Service whose module resolution decides which specifiers name project files\n * @returns The text with every project specifier rewritten, or `content` itself when none was\n *\n * @remarks\n * Only top-level statements are visited, since only those can carry module syntax.\n * An import, an `export *`, and a named export are read for their `from` clause,\n * while `import x = require('m')` is read for its module name.\n * `import A = B.C` names no module, so it is left alone, as is an `export { a }` that carries no `from` clause.\n * Every specifier found goes through {@link rewrite}, so a package stays as it was written,\n * and only a project file is rewritten.\n * The parse and the text have to come from the same source, since the spans are offsets into it - a parse of one text\n * applied to another lands its edits in the wrong places.\n *\n * @example\n * ```ts\n * const content = \"import { build } from '@components/builder';\\nexport const x = 1;\";\n * const parse = parseSync('src/index.ts', content, { sourceType: 'module' });\n *\n * resolveSource(parse, 'D:/app/src/index.ts', content, ts);\n * // \"import { build } from './components/builder';\\nexport const x = 1;\"\n * ```\n *\n * @see rewrite\n * @see applyEdits\n *\n * @since 3.0.0\n */\n\nexport function resolveSource(parse: ParseResult, target: string, content: string = '', ts: TypescriptService): string {\n if(!content) return content;\n const edits: Array<SourceEditInterface> = [];\n\n for (const statement of parse.program.body) {\n switch (statement.type) {\n case 'ImportDeclaration':\n case 'ExportAllDeclaration':\n case 'ExportNamedDeclaration':\n rewrite(statement.source, target, edits, ts);\n break;\n\n case 'TSImportEqualsDeclaration':\n if (statement.moduleReference.type === 'TSExternalModuleReference')\n rewrite(statement.moduleReference.expression, target, edits, ts);\n }\n }\n\n return applyEdits(content, edits);\n}\n\n","/**\n * Header text included at the top of generated declaration bundle files.\n *\n * @remarks\n * This constant provides a standardized header comment prepended to all\n * declaration bundle files generated by the TypeScript module. The header clearly\n * indicates that the file was automatically generated and should not be edited manually.\n *\n * The header serves as:\n * - A warning to developers not to manually modify generated files\n * - Documentation indicating the source of the file\n * - A consistent marker for identifying generated declaration files\n *\n * @example\n * ```ts\n * import { HeaderDeclarationBundle } from './typescript.constant';\n * import { writeFileSync } from 'fs';\n *\n * const bundledContent = `${HeaderDeclarationBundle}\\n${actualDeclarations}`;\n * writeFileSync('dist/index.d.ts', bundledContent);\n * ```\n *\n * @since 1.5.9\n */\n\nexport const HeaderDeclarationBundle = `/**\n * This file was automatically generated by xBuild.\n * DO NOT EDIT MANUALLY.\n */\n`;\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { FileSnapshotInterface } from '@models/interfaces/files-model.interface';\nimport type { IScriptSnapshot, SourceFile, ParsedCommandLine, CompilerOptions } from 'typescript';\n\n/**\n * Imports\n */\n\nimport ts from 'typescript';\nimport { relative } from '@remotex-labs/xmap';\nimport { inject } from '@remotex-labs/xinject';\nimport { FilesModel } from '@models/files.model';\nimport { createMatcher } from '@components/glob.component';\n\n/**\n * A TypeScript language service host backed by cached file snapshots and the set of files it has tracked.\n *\n * @remarks\n * Satisfies `ts.LanguageServiceHost`, giving the language service its filesystem access, script snapshots, and\n * compiler configuration.\n * Reads and versions are delegated to the shared {@link FilesModel}, while the file set handed over through\n * {@link getScriptFileNames} is maintained here.\n * A path enters the tracked set the first time it is refreshed or its version is queried,\n * so the set grows from the configured entry files to every dependency the language service resolves into them.\n * Paths matched by the configuration's `exclude` globs are skipped by {@link refreshFiles} and reported as ignored\n * to incremental checks through {@link ignoreSourceFile}.\n *\n * @example\n * ```ts\n * const host = new LanguageHostService(parsedConfig); // entry files tracked and read up front\n *\n * host.refresh('src/index.ts'); // re-read and track one file\n * host.getScriptSnapshot('src/index.ts'); // what the language service parses\n * host.options = nextParsedConfig; // swap configuration and re-track from scratch\n * ```\n *\n * @see FilesModel\n * @since 2.0.0\n */\n\nexport class LanguageHostService implements ts.LanguageServiceHost {\n /**\n * Shared model that reads files, caches their snapshots, and tracks their versions.\n *\n * @remarks\n * Registered as a singleton, so every host and build step works against one cache keyed by resolved absolute path.\n *\n * @example\n * ```ts\n * host.filesCache.touch('src/index.ts').version; // 1\n * ```\n *\n * @see FilesModel\n * @since 3.0.0\n */\n\n readonly filesCache = inject(FilesModel);\n\n /**\n * Resolved absolute paths of every file this host has tracked for the language service.\n *\n * @remarks\n * Returned verbatim from {@link getScriptFileNames}.\n * A path is added the first time it is refreshed or its version is queried, then kept even after the file is\n * deleted, so the language service observes the deletion through an empty snapshot rather than a vanishing file.\n *\n * @see track\n * @since 3.0.0\n */\n\n private readonly trackedFiles = new Set<string>();\n\n /**\n * Memoized exclusion verdict per path, keyed by the resolved absolute path.\n *\n * @remarks\n * Exclusion is asked for on every refresh and on every source file an incremental check walks,\n * while the answer only changes with the configuration, so {@link reload} clears this rather than recomputing it.\n *\n * @see isExcluded\n * @since 3.0.0\n */\n\n private readonly exclusions = new Map<string, boolean>();\n\n /**\n * A predicate compiled from the configuration's `exclude` globs, tested against working-directory-relative\n * paths.\n *\n * @remarks\n * Assigned by {@link reload} before any lookup can reach it, hence the definite assignment.\n * It takes a relative path, so {@link isExcluded} is what callers use.\n *\n * @see compileExclude\n * @since 3.0.0\n */\n\n private matches!: (path: string) => boolean;\n\n /**\n * Initializes a new {@link LanguageHostService} from a parsed configuration.\n *\n * @param config - Parsed TypeScript configuration carrying the compiler options, entry file names,\n * and the raw `exclude` globs\n *\n * @remarks\n * Runs {@link reload}, so the entry files are read into the cache and tracked before the host is handed out.\n *\n * @example\n * ```ts\n * const config = ts.getParsedCommandLineOfConfigFile('tsconfig.json', {}, ts.sys as never)!;\n * const host = new LanguageHostService(config);\n * host.getScriptFileNames(); // the configuration's entry files\n * ```\n *\n * @see reload\n * @since 3.0.0\n */\n\n constructor(private config: ParsedCommandLine) {\n this.reload();\n }\n\n /**\n * The live set of resolved paths currently tracked by this host.\n *\n * @returns The tracked set itself, mutated as files are refreshed and cleared\n *\n * @remarks\n * Exposes the same paths as {@link getScriptFileNames} without copying,\n * so a caller can iterate them or feed them straight back into {@link refreshFiles}.\n *\n * @example\n * ```ts\n * host.refresh('src/index.ts');\n * host.tracked.has(host.realpath('src/index.ts')); // true\n * ```\n *\n * @see getScriptFileNames\n * @since 3.0.0\n */\n\n get tracked(): Set<string> {\n return this.trackedFiles;\n }\n\n /**\n * A source-file predicate that incremental checks can use to skip excluded files.\n *\n * @returns A predicate reporting `true` for a source file whose path matches the exclude globs\n *\n * @remarks\n * Bridges the path-based {@link isExcluded} to TypeScript's `ignoreSourceFile` hook by reading the absolute\n * `fileName`, so it agrees with how {@link refreshFiles} filters paths.\n *\n * @example\n * ```ts\n * builder.getSemanticDiagnosticsOfNextAffectedFile(undefined, host.ignoreSourceFile);\n * ```\n *\n * @see refreshFiles\n * @since 3.0.0\n */\n\n get ignoreSourceFile(): (file: SourceFile) => boolean {\n return (file: SourceFile): boolean => this.isExcluded(file.fileName);\n }\n\n /**\n * Replaces the configuration and re-tracks the project from scratch.\n *\n * @param config - The new parsed configuration\n *\n * @remarks\n * Delegates to {@link reload}, so the exclude predicate is recompiled and the new `config.fileNames` replace the\n * tracked set entirely.\n *\n * @example\n * ```ts\n * host.options = ts.getParsedCommandLineOfConfigFile('tsconfig.json', {}, ts.sys as never)!;\n * host.getScriptFileNames(); // the new entry files, nothing carried over\n * ```\n *\n * @see reload\n * @since 3.0.0\n */\n\n set options(config: ParsedCommandLine) {\n this.config = config;\n this.reload();\n }\n\n /**\n * Drops the tracked set and repopulates it from the configured entry files.\n *\n * @remarks\n * The {@link filesCache} snapshots survive, so only membership is reset,\n * and the files are re-read on the way back in through {@link refreshFiles}.\n *\n * @example\n * ```ts\n * host.refresh('src/scratch.ts');\n * host.clearTracked();\n * host.getScriptFileNames(); // back to the configured entry files, scratch.ts dropped\n * ```\n *\n * @see refreshFiles\n * @since 3.0.0\n */\n\n clearTracked(): void {\n this.trackedFiles.clear();\n this.refreshFiles(this.config.fileNames);\n }\n\n /**\n * Rebuilds the exclude predicate and the tracked set from the current configuration.\n *\n * @remarks\n * The single initialization path shared by the constructor and the {@link options} setter:\n * - compiles the `exclude` globs into {@link matches},\n * - drops the memoized {@link exclusions}, whose verdicts belong to the previous globs,\n * - refreshes every entry file through {@link clearTracked}, which reads them into the cache and tracks them.\n *\n * Call it directly when the configuration object was edited in place rather than replaced.\n *\n * @example\n * ```ts\n * host.reload();\n * host.getScriptFileNames(); // what the configuration now selects\n * ```\n *\n * @see clearTracked\n * @since 3.0.0\n */\n\n reload(): void {\n this.matches = this.compileExclude(this.config.raw?.exclude);\n this.exclusions.clear();\n\n this.clearTracked();\n }\n\n /**\n * Re-reads a file from the disk, tracks it, and returns its entry.\n *\n * @param path - File path, relative or absolute\n * @returns The entry for the file, with `version` advanced when the content changed\n *\n * @remarks\n * The path is tracked before the read, so it stays listed even when the file turns out to be gone.\n * Exclusion is not consulted here - {@link refreshFiles} is the caller that filters.\n *\n * @example\n * ```ts\n * const state = host.refresh('src/index.ts');\n * state.version; // 1 at first sight, advanced on every later change\n * state.snapshot?.text; // the content just read\n * ```\n *\n * @see track\n * @since 3.0.0\n */\n\n refresh(path: string): FileSnapshotInterface {\n return this.filesCache.refresh(this.track(path));\n }\n\n /**\n * Refreshes and tracks a batch of files, skipping any path matched by the exclude globs.\n *\n * @param paths - Paths to refresh, defaulting to the currently tracked set\n *\n * @remarks\n * Each retained path goes through {@link refresh} and so becomes tracked.\n * Calling it with no argument brings the already tracked files current, which is what a watch cycle does.\n *\n * @example\n * ```ts\n * host.refreshFiles([ 'src/a.ts', 'src/a.spec.ts' ]); // a.spec.ts skipped when excluded\n * host.refreshFiles(); // re-read everything already tracked\n * ```\n *\n * @see refresh\n * @since 3.0.0\n */\n\n refreshFiles(paths: Array<string> | Set<string> = this.trackedFiles): void {\n for (const path of paths) {\n if (this.isExcluded(path)) continue;\n this.refresh(path);\n }\n }\n\n /**\n * Returns the compiler options currently in force.\n *\n * @returns The active TypeScript compiler options\n *\n * @example\n * ```ts\n * host.getCompilationSettings().target; // ts.ScriptTarget.ES2020\n * ```\n *\n * @since 2.0.0\n */\n\n getCompilationSettings(): CompilerOptions {\n return this.config.options;\n }\n\n /**\n * Reports whether a file exists on disk.\n *\n * @param path - Absolute path\n * @returns `true` when the file exists\n *\n * @remarks\n * Goes straight to `ts.sys`, bypassing the snapshot cache, so it reflects the filesystem as it stands now.\n *\n * @example\n * ```ts\n * host.fileExists('/project/src/index.ts'); // true\n * ```\n *\n * @since 2.0.0\n */\n\n fileExists(path: string): boolean {\n return ts.sys.fileExists(path);\n }\n\n /**\n * Reads file content through the snapshot cache.\n *\n * @param path - File path, relative or absolute\n * @param encoding - Encoding used when the file is read, defaulting to `utf-8`\n * @returns The file content, or `undefined` when the path holds no readable file\n *\n * @remarks\n * Served from the cache once the file has been read, so the encoding only takes effect on the first read of a path.\n *\n * @example\n * ```ts\n * host.readFile('src/index.ts'); // export const x = 10;\n * host.readFile('src/gone.ts'); // undefined\n * ```\n *\n * @see FilesModel.touch\n * @since 3.0.0\n */\n\n readFile(path: string, encoding?: BufferEncoding): string | undefined {\n return this.filesCache.touch(path, encoding).snapshot?.text;\n }\n\n /**\n * Lists the files under a directory that match the given criteria.\n *\n * @param path - Directory to start from\n * @param extensions - File extensions to accept\n * @param exclude - Glob patterns to skip\n * @param include - Glob patterns to keep\n * @param depth - Maximum recursion depth\n * @returns The matching file paths\n *\n * @example\n * ```ts\n * host.readDirectory('src', [ '.ts' ], [ 'node_modules' ], undefined, 2); // [ 'src/index.ts', ... ]\n * ```\n *\n * @since 2.0.0\n */\n\n readDirectory(path: string, extensions?: Array<string>, exclude?: Array<string>, include?: Array<string>, depth?: number): Array<string> {\n return ts.sys.readDirectory(path, extensions, exclude, include, depth);\n }\n\n /**\n * Returns the immediate subdirectories of a path.\n *\n * @param path - Directory to list\n * @returns The subdirectory names\n *\n * @example\n * ```ts\n * host.getDirectories('src'); // [ 'services', 'models' ]\n * ```\n *\n * @since 2.0.0\n */\n\n getDirectories(path: string): Array<string> {\n return ts.sys.getDirectories(path);\n }\n\n /**\n * Reports whether a directory exists.\n *\n * @param path - Absolute path\n * @returns `true` when the directory exists\n *\n * @example\n * ```ts\n * host.directoryExists('src/services'); // true\n * ```\n *\n * @since 2.0.0\n */\n\n directoryExists(path: string): boolean {\n return ts.sys.directoryExists(path);\n }\n\n /**\n * Returns the working directory that relative paths resolve against.\n *\n * @returns The absolute path of the current working directory\n *\n * @example\n * ```ts\n * host.getCurrentDirectory(); // '/project'\n * ```\n *\n * @since 2.0.0\n */\n\n getCurrentDirectory(): string {\n return ts.sys.getCurrentDirectory();\n }\n\n /**\n * Returns the resolved paths of every file tracked by this host.\n *\n * @returns A snapshot array of the tracked absolute paths\n *\n * @remarks\n * This is the program's file set as far as the language service is concerned.\n * A deleted file stays listed, so its removal surfaces as a diagnostic rather than as a silently shrinking program.\n *\n * @example\n * ```ts\n * host.getScriptFileNames(); // [ '/project/src/index.ts', '/project/src/utils.ts' ]\n * ```\n *\n * @see tracked\n * @since 2.0.0\n */\n\n getScriptFileNames(): Array<string> {\n return [ ...this.trackedFiles ];\n }\n\n /**\n * Returns the path of the default lib file matching the given options.\n *\n * @param options - Compiler options, of which `target` decides the lib\n * @returns Absolute path to the matching `lib.*.d.ts`\n *\n * @example\n * ```ts\n * host.getDefaultLibFileName({ target: ts.ScriptTarget.ES2020 }); // '.../lib.es2020.full.d.ts'\n * ```\n *\n * @since 2.0.0\n */\n\n getDefaultLibFileName(options: CompilerOptions): string {\n return ts.getDefaultLibFilePath(options);\n }\n\n /**\n * Returns the version identifier of a file and tracks it.\n *\n * @param path - File path, relative or absolute\n * @returns The version as a string, such as `'1'` or `'2'`\n *\n * @remarks\n * The language service reparses a file only when this string changes, so the value must stay stable while the file\n * does.\n * The read is served from the cache, and {@link refresh} is what moves the version forward.\n *\n * @example\n * ```ts\n * host.getScriptVersion('src/index.ts'); // '1'\n * host.refresh('src/index.ts'); // the file changed on disk\n * host.getScriptVersion('src/index.ts'); // '2' - the language service reparses it\n * ```\n *\n * @see track\n * @since 2.0.0\n */\n\n getScriptVersion(path: string): string {\n return this.filesCache.touch(this.track(path)).version.toString();\n }\n\n /**\n * Returns the script snapshot of a file.\n *\n * @param path - File path, relative or absolute\n * @returns The snapshot, or `undefined` when the path holds no readable file\n *\n * @remarks\n * Reads through the cache, loading from the disk at first sight only.\n * Unlike {@link getScriptVersion}, it leaves the tracked set alone - tracking is driven by version queries.\n *\n * @example\n * ```ts\n * const snapshot = host.getScriptSnapshot('src/index.ts');\n * snapshot?.getText(0, snapshot.getLength()); // export const x = 10;\n * ```\n *\n * @see getScriptVersion\n * @since 2.0.0\n */\n\n getScriptSnapshot(path: string): IScriptSnapshot | undefined {\n return this.filesCache.touch(path).snapshot;\n }\n\n /**\n * Resolves a path to the absolute form used as the tracking and cache key.\n *\n * @param path - File path, relative or absolute\n * @returns The resolved absolute path\n *\n * @remarks\n * Implements the optional `realpath` host hook with the same normalization {@link FilesModel} applies to its cache\n * keys, so the paths reported to TypeScript match the ones tracked here.\n *\n * @example\n * ```ts\n * host.realpath('src/index.ts'); // '/project/src/index.ts'\n * ```\n *\n * @see FilesModel.resolve\n * @since 3.0.0\n */\n\n realpath(path: string): string {\n return this.filesCache.resolve(path);\n }\n\n /**\n * Compiles exclude globs into a matcher over working-directory-relative paths.\n *\n * @param globs - Patterns whose matching paths are excluded, or `undefined` when the configuration has none\n * @returns A predicate reporting `true` for a matched relative path, or one that always reports `false`\n *\n * @remarks\n * The empty case is handled explicitly, since {@link createMatcher} reads an empty pattern list as matching\n * everything, which would exclude the whole project.\n *\n * @see createMatcher\n * @since 3.0.0\n */\n\n private compileExclude(globs?: Array<string>): (path: string) => boolean {\n return globs && globs.length > 0 ? createMatcher(globs) : (): boolean => false;\n }\n\n /**\n * Reports whether a path is excluded by the configuration, memorizing the verdict.\n *\n * @param path - File path as the caller holds it, relative or absolute\n * @returns `true` when the path matches the exclude globs\n *\n * @remarks\n * The path is resolved before the verdict is stored, so the same file reached by two spellings is matched once,\n * and every later lookup of either costs a map read.\n *\n * @see exclusions\n * @since 3.0.0\n */\n\n private isExcluded(path: string): boolean {\n const target = this.filesCache.resolve(path);\n let excluded = this.exclusions.get(target);\n if (excluded === undefined) this.exclusions.set(\n target, excluded = this.matches(relative(process.cwd(), target))\n );\n\n return excluded;\n }\n\n /**\n * Adds a path to the tracked set and returns its resolved key.\n *\n * @param path - File path, relative or absolute\n * @returns The resolved absolute path used as the tracking key\n *\n * @remarks\n * Centralizes the tracking shared by {@link refresh} and {@link getScriptVersion}.\n * A path is added the first time it is seen and never removed,\n * so a deletion leaves a still-listed entry that resolves to an empty snapshot.\n *\n * @see trackedFiles\n * @since 3.0.0\n */\n\n private track(path: string): string {\n const target = this.filesCache.resolve(path);\n this.trackedFiles.add(target);\n\n return target;\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { Dirent } from 'fs';\nimport type { GlobOptionsInterface } from './interfaces/glob-component.interface';\n\n/**\n * Imports\n */\n\nimport { readdirSync } from 'fs';\nimport { join } from '@remotex-labs/xmap';\nimport { Char } from '@constants/char.constant';\nimport { FrameworkService } from '@services/framework.service';\nimport { RegexElement, RegexCloser } from '@constants/glob.constant';\n\n/**\n * Escapes a single character for literal use inside a regular expression.\n *\n * @param char - The character to escape\n * @returns The character prefixed with a backslash when it carries special meaning in a regular expression,\n * or the character unchanged otherwise\n *\n * @remarks\n * A backslash is prepended when `char` is one of the regex metacharacters `.+^$()|\\{}[]*?`.\n * Any other character is returned as-is.\n * Intended for building patterns from user-supplied glob fragments where each source character must match itself.\n *\n * @example\n * ```ts\n * lit('.'); // '\\\\.'\n * lit('a'); // 'a'\n * ```\n *\n * @since 3.0.0\n */\n\nexport function lit(char: string): string {\n return '.+^$()|\\\\{}[]*?'.includes(char) ? '\\\\' + char : char;\n}\n\n/**\n * Returns the UTF-16 code unit of a glob string at a given index.\n *\n * @param glob - The glob string to read from\n * @param index - The zero-based position of the character to read\n * @returns The code unit at `index`, or `NaN` when `index` is out of range\n *\n * @remarks\n * A thin wrapper over {@link String.charCodeAt} used while scanning a glob pattern character by character.\n * Comparing code units avoids allocating single-character substrings on the hot path.\n *\n * @example\n * ```ts\n * at('a*b', 1); // 42 - Char.Star\n * at('a*b', 9); // NaN - past the end\n * ```\n *\n * @see Char\n * @since 3.0.0\n */\n\nexport function at(glob: string, index: number): number {\n return glob.charCodeAt(index);\n}\n\n/**\n * Determines whether the `**` at a given index forms a globstar segment.\n *\n * @param glob - The glob string being scanned\n * @param index - The zero-based position of the first `*` of the candidate `**`\n * @returns `true` when the `**` occupies a whole path segment, `false` otherwise\n *\n * @remarks\n * A globstar is a `**` that spans an entire path segment,\n * so it must be bounded on both sides by a slash or by the start or end of the string.\n * The character before `index` must be the start of the string or a slash,\n * and the character after the `**` must be the end of the string or a slash.\n * A `**` embedded within a segment, such as in `a**b`, matches as two consecutive single stars rather than a globstar.\n * The caller is responsible for confirming that both characters at `index` and `index + 1` are `*`.\n *\n * @example\n * ```ts\n * isGlobstar('**', 0); // true - the whole string\n * isGlobstar('a/**', 2); // true - preceded by a slash, ends the string\n * isGlobstar('a**b', 1); // false - embedded in a segment\n * ```\n *\n * @see Char\n * @since 3.0.0\n */\n\nexport function isGlobstar(glob: string, index: number): boolean {\n return (index === 0 || at(glob, index - 1) === Char.Slash)\n && (index + 2 === glob.length || at(glob, index + 2) === Char.Slash);\n}\n\n/**\n * Wraps a regex fragment in a non-capturing group.\n *\n * @param body - The regex source to enclose\n * @returns The body wrapped as `(?:body)`\n *\n * @remarks\n * Groups a fragment so a following quantifier or alternation applies to the whole fragment rather than its last token.\n *\n * @example\n * ```ts\n * group('a|b'); // '(?:a|b)'\n * group('a|b') + '?'; // '(?:a|b)?' - the quantifier covers both alternatives\n * ```\n *\n * @since 3.0.0\n */\n\nexport function group(body: string): string {\n return `(?:${ body })`;\n}\n\n/**\n * Finds the index of the `]` that closes a character class.\n *\n * @param glob - The glob string being scanned\n * @param openIndex - The index of the opening `[`\n * @returns The index of the closing `]`, or the length of the string when the class is unterminated\n *\n * @remarks\n * Applies POSIX-style character-class rules while scanning.\n * A leading `!` or `^` negates the class and is skipped, and a `]` immediately after the opening bracket\n * (or after the negation) is treated as a literal member rather than a close.\n * A backslash escapes the next character, so an escaped `]` does not close the class.\n *\n * @example\n * ```ts\n * classEnd('[abc]def', 0); // 4\n * classEnd('[]abc]', 0); // 5 - the leading ] is a member\n * classEnd('[abc', 0); // 4 - unterminated, so the length\n * ```\n *\n * @see compileClass\n * @since 3.0.0\n */\n\nexport function classEnd(glob: string, openIndex: number): number {\n let scan = openIndex + 1;\n const lead = at(glob, scan);\n\n if (lead === Char.Bang || lead === Char.Caret) scan++;\n if (at(glob, scan) === Char.RBracket) scan++; // leading ] is literal\n\n while (scan < glob.length && at(glob, scan) !== Char.RBracket)\n scan += at(glob, scan) === Char.Backslash ? 2 : 1;\n\n return scan;\n}\n\n/**\n * Finds the index of the `)` that closes an extglob group.\n *\n * @param glob - The glob string being scanned\n * @param openIndex - The index of the opening `(`\n * @returns The index of the matching `)`, or `-1` when the group is unterminated\n *\n * @remarks\n * Tracks nesting depth so an inner `( ... )` does not end the outer group.\n * A backslash escapes the next character, and a `[ ... ]` character class is skipped via {@link classEnd},\n * so parentheses inside it are not counted.\n *\n * @example\n * ```ts\n * findClose('@(a|b)c', 1); // 5\n * findClose('@(a|(b))', 1); // 7 - the inner group does not end it\n * findClose('@(a', 1); // -1 - unterminated\n * ```\n *\n * @see classEnd\n * @since 3.0.0\n */\n\nexport function findClose(glob: string, openIndex: number): number {\n for (let cursor = openIndex, depth = 0; cursor < glob.length; cursor++) {\n const char = at(glob, cursor);\n\n if (char === Char.Backslash) cursor++;\n else if (char === Char.LParen) depth++;\n else if (char === Char.RParen && --depth === 0) return cursor;\n else if (char === Char.LBracket) cursor = classEnd(glob, cursor);\n }\n\n return -1;\n}\n\n/**\n * Finds the index of the `}` that closes an expandable brace group.\n *\n * @param glob - The glob string being scanned\n * @param openIndex - The index of the opening `{`\n * @returns The index of the matching `}` when the group contains a top-level comma, `-1` otherwise\n *\n * @remarks\n * A brace group is expandable only when it holds at least one top-level comma, so `{a,b}` closes but `{a}` does not.\n * Tracks nesting depth so an inner `{ ... }` does not end the outer group,\n * skips a `[ ... ]` character class via {@link classEnd}, and treats a backslash as escaping the next character.\n * Returning `-1` signals the caller to emit the `{` as a literal.\n *\n * @example\n * ```ts\n * braceClose('{a,b}c', 0); // 4\n * braceClose('{a,{b,c}}', 0); // 8 - the inner group does not end it\n * braceClose('{abc}', 0); // -1 - no top-level comma, so a literal\n * ```\n *\n * @see classEnd\n * @since 3.0.0\n */\n\nexport function braceClose(glob: string, openIndex: number): number {\n let comma = false;\n\n for (let cursor = openIndex + 1, depth = 0; cursor < glob.length; cursor++) {\n const char = at(glob, cursor);\n\n if (char === Char.Backslash) cursor++;\n else if (char === Char.LBrace) depth++;\n else if (char === Char.RBrace) {\n if (depth === 0) return comma ? cursor : -1; // expandable only with a comma\n depth--;\n }\n else if (char === Char.Comma && depth === 0) comma = true;\n else if (char === Char.LBracket) cursor = classEnd(glob, cursor);\n }\n\n return -1;\n}\n\n/**\n * Compiles a glob character class into its regex equivalent.\n *\n * @param glob - The glob string being scanned\n * @param openIndex - The index of the opening `[`\n * @returns A tuple of the compiled regex source and the index just past the class\n *\n * @remarks\n * Translates glob character-class syntax into a regex class.\n * A leading `!` or `^` becomes a negation that also excludes the path separator, emitted as `[^/`.\n * A `]` immediately after the opening (or after the negation) is escaped as a literal member,\n * and a `^` inside the class is escaped so it is not read as a negation.\n * An unterminated class is not a class at all - the function returns the literal `\\[` and advances past the `[`.\n *\n * @example\n * ```ts\n * compileClass('[a-z]x', 0); // [ '[a-z]', 5 ]\n * compileClass('[!a]', 0); // [ '[^/a]', 4 ] - negated, and the separator excluded with it\n * compileClass('[abc', 0); // [ '\\\\[', 1 ] - unterminated, so a literal bracket\n * ```\n *\n * @see classEnd\n * @since 3.0.0\n */\n\nexport function compileClass(glob: string, openIndex: number): [string, number] {\n const end = classEnd(glob, openIndex);\n if (end >= glob.length) return [ '\\\\[', openIndex + 1 ]; // unterminated → literal\n\n let cursor = openIndex + 1, out = '[';\n const lead = at(glob, cursor);\n\n if (lead === Char.Bang || lead === Char.Caret) { out += '^/'; cursor++; }\n if (at(glob, cursor) === Char.RBracket) { out += '\\\\]'; cursor++; }\n\n for (; cursor < end; cursor++) {\n if (at(glob, cursor) === Char.Backslash) out += '\\\\' + glob[++cursor];\n else if (at(glob, cursor) === Char.Caret) out += '\\\\^';\n else out += glob[cursor];\n }\n\n return [ out + ']', end + 1 ];\n}\n\n/**\n * Finds the index of the next path separator at or after a position.\n *\n * @param glob - The glob string being scanned\n * @param from - The zero-based position to start scanning from\n * @returns The index of the next unescaped `/`, or the length of the string when none remains\n *\n * @remarks\n * Marks the end of the current path segment.\n * A backslash escapes the next character, so an escaped `/` does not end the segment.\n *\n * @example\n * ```ts\n * segmentEnd('src/index.ts', 0); // 3\n * segmentEnd('index.ts', 0); // 8 - no separator left, so the length\n * ```\n *\n * @since 3.0.0\n */\n\nexport function segmentEnd(glob: string, from: number): number {\n for (let cursor = from; cursor < glob.length; cursor++) {\n if (at(glob, cursor) === Char.Slash) return cursor;\n if (at(glob, cursor) === Char.Backslash) cursor++;\n }\n\n return glob.length;\n}\n\n/**\n * Compiles a glob fragment into a regular-expression source.\n *\n * @param glob - The glob fragment to compile\n * @param isSegmentStart - Whether the fragment begins at the start of a path segment\n * @param alt - The code unit that separates alternatives, or `0` when the fragment is not an alternation body\n * @param options - Compilation options, of which only {@link GlobOptionsInterface.dot} is read, defaulting to `false`\n * @returns The regex source for the fragment, without the anchoring `^` and `$`\n *\n * @remarks\n * The core of the compiler, invoked recursively for the bodies of extglob, brace, and negation groups.\n * It walks the fragment one character at a time and emits the matching regex, handling wildcards (`*`, `**`, `?`),\n * character classes, brace expansion, extglob prefixes (`?( )`, `*( )`, `+( )`, `@( )`, `!( )`), and escapes.\n *\n * Segment-start tracking drives the leading-dot guard: at the start of a segment a wildcard must not match a dotfile,\n * so a {@link RegexElement.NotDot} guard is emitted.\n * `isSegmentStart` seeds this state for the fragment, and it is re-armed after every `/` and at each alternative.\n * When `options.dot` is `true`, the guard is suppressed everywhere, so wildcards match dotfiles as ordinary names,\n * and `**` descends into dot directories.\n *\n * The `alt` parameter marks the fragment as the body of an alternation.\n * When set to {@link Char.Pipe} or {@link Char.Comma}, an unescaped separator of that kind becomes a regex `|`,\n * and `**` is treated as two single stars rather than a globstar.\n * Any other occurrence of `|` or `,` is emitted literally.\n *\n * @example\n * ```ts\n * compileFragment('*.ts', true); // (?!\\.)[^/]*\\.ts\n * compileFragment('a,b', false, Char.Comma); // a|b\n * compileFragment('*.ts', true, 0, { dot: true }); // [^/]*\\.ts\n * ```\n *\n * @see globToRegExp\n * @see GlobOptionsInterface\n *\n * @since 3.0.0\n */\n\nexport function compileFragment(glob: string, isSegmentStart: boolean = false, alt: number = 0, options: GlobOptionsInterface = {}): string {\n const { dot = false } = options;\n\n let out = '';\n let index = 0;\n let wasStart = isSegmentStart;\n\n const guard = dot ? '' : RegexElement.NotDot;\n const DS = guard + RegexElement.NotSlash + '+';\n const GLOBSTAR = group(DS + '(?:/' + DS + ')*') + '?';\n\n while (index < glob.length) {\n const char = at(glob, index);\n const nChar = at(glob, index + 1);\n\n if (nChar === Char.LParen && (char === Char.Bang || RegexCloser[char])) {\n const close = findClose(glob, index + 1);\n\n if (char !== Char.Bang) { // ?*+@( ... )\n const end = close === -1 ? glob.length : close; // unclosed → group runs to the end\n const inner = compileFragment(glob.slice(index + 2, end), wasStart, Char.Pipe, options);\n\n out += RegexElement.Open + inner + RegexCloser[char];\n index = end + 1;\n continue;\n }\n\n if (close !== -1) {\n const inner = compileFragment(glob.slice(index + 2, close), wasStart, Char.Pipe, options);\n const tailEnd = segmentEnd(glob, close + 1);\n const tail = compileFragment(glob.slice(close + 1, tailEnd), false, 0, options);\n\n out += group(\n (wasStart ? guard : '') +\n `(?!${ group(inner) + tail + RegexElement.SegBreak })` +\n RegexElement.NotSlashLazy + tail\n );\n\n index = tailEnd;\n continue;\n }\n }\n\n switch (char) {\n case Char.Slash:\n out += RegexElement.Slash;\n index++;\n wasStart = true;\n break;\n\n case Char.Backslash:\n out += index + 1 < glob.length ? lit(glob[index + 1]) : '\\\\\\\\';\n index += 2;\n break;\n\n case Char.Question:\n out += wasStart && !dot ? RegexElement.NotDotSlash : RegexElement.NotSlash;\n index++;\n break;\n\n case Char.Star:\n if (nChar === Char.Star && alt !== Char.Pipe && (index > 0 || isSegmentStart) && isGlobstar(glob, index)) {\n const root = index === 0 && alt === 0 ? RegexElement.AbsRoot : '';\n if (at(glob, index + 2) === Char.Slash) {\n out += root + group(DS + RegexElement.Slash) + '*'; index += 3; wasStart = true;\n } else {\n out += root + GLOBSTAR; index += 2;\n }\n } else {\n out += (wasStart ? guard : '') + RegexElement.NotSlashRun;\n index++;\n }\n break;\n\n case Char.LBrace: {\n const close = braceClose(glob, index);\n\n if (close === -1) {\n out += '\\\\{'; index++;\n } else {\n out += group(compileFragment(glob.slice(index + 1, close), wasStart, Char.Comma, options));\n index = close + 1;\n }\n break;\n }\n\n case Char.LBracket: {\n const [ src, next ] = compileClass(glob, index);\n out += (wasStart && !dot && src !== '\\\\[' ? RegexElement.NotDot : '') + src;\n index = next;\n break;\n }\n\n case Char.Pipe:\n case Char.Comma:\n if (alt === char) { out += RegexElement.Alt; wasStart = isSegmentStart; }\n else out += lit(glob[index]);\n index++;\n break;\n\n default:\n out += lit(glob[index]); index++;\n }\n }\n\n return out;\n}\n\n/**\n * Compiles a glob pattern into an anchored regular expression.\n *\n * @param glob - The glob pattern to compile\n * @param options - Compilation options carrying the regex flags and the dotfile setting\n * @returns A {@link RegExp} anchored with `^` and `$` that matches exactly the paths described by the glob\n *\n * @remarks\n * The entry point of the compiler.\n * It compiles the pattern with {@link compileFragment} starting at a segment boundary, then wraps the result\n * in `^ ... $` so the expression matches a whole path rather than a substring.\n *\n * Supported glob syntax:\n * - `*` - matches any run of characters within a single path segment, never crossing a `/`.\n * - `?` - matches exactly one character within a segment.\n * - `**` - globstar, matching across segment boundaries, spanning any number of intermediate segments.\n * - `[abc]`, `[a-z]`, `[a-zA-Z0-9]` - a character class matching exactly one listed character or range.\n * Multiple ranges combine, and it never matches more than one character.\n * - `[!abc]`, `[^abc]` - a negated character class matching exactly one character not listed.\n * - `{a,b}`, `{a,{b,c}}` - brace alternation, matching any one of the comma-separated alternatives.\n * A brace group with no top-level comma, such as `{abc}`, is treated as the literal text `{abc}`.\n * - `@( ... )` - extglob group matching its `|`-separated alternatives exactly once.\n * - `?( ... )` - extglob group matching zero or one of its alternatives.\n * - `*( ... )` - extglob group matching zero or more of its alternatives.\n * - `+( ... )` - extglob group matching one or more of its alternatives.\n * - `!( ... )` - extglob negation matching anything the alternatives do not.\n * - `\\` - escapes the next character so it is matched literally, so `\\*.js` matches the literal name `*.js`.\n * - `/` - the literal path separator, which segment-relative wildcards never cross.\n *\n * Character classes and `?` always consume exactly one character.\n * To constrain a run of characters, follow the class with `*` (`[ab]*c` allows any run before `c`)\n * or repeat it with an extglob (`+([ab])c` requires every character before `c` to be `a` or `b`).\n *\n * The `!( ... )` negation is single-segment: its body never crosses a `/`, and the guarantee holds when\n * the negation is the last thing in its segment or is followed by a literal tail such as `.ts`.\n * It is not whole-pattern negation - a leading `!` not followed by `(` is matched as a literal `!`.\n *\n * Leading dots are guarded: at the start of a segment,\n * `*`, `?`, `[ ... ]`, and `**` do not match a name that begins with `.` unless the pattern spells the dot out.\n * So `*` matches `env` but not `.env`.\n * To include dotfiles, name the dot explicitly:\n * - `.*` - matches only dotfiles, such as `.env`.\n * - `{.,}*` - matches every name, dotfiles included.\n *\n * Passing {@link GlobOptionsInterface.dot} as `true` lifts the guard for the whole pattern,\n * so plain wildcards match dotfiles, and `**` descends into dot directories - `**\\/*` then matches `.git/config`.\n *\n * @example\n * <caption>Common patterns and what they match</caption>\n * ```text\n * *.{ts,js} x.ts, x.js\n * @(a|b) a, b\n * +(ab) ab, abab (not: '')\n * !(a).js ab.js, x.js (not: a.js)\n * !(*.spec).ts app.ts, index.ts (not: app.spec.ts)\n * !(*.spec|*.test).ts app.ts (not: app.spec.ts, app.test.ts)\n * ```\n *\n * @example\n * <caption>Every file except a spec, recursively - the two most useful forms</caption>\n * ```ts\n * globToRegExp('**\\/!(*.spec).{ts,js}'); // any .ts or .js file whose name does not end in .spec\n * globToRegExp('**\\/!(*.spec.ts)'); // any file at all except those ending in .spec.ts\n * ```\n *\n * @see compileFragment\n * @see GlobOptionsInterface\n *\n * @since 3.0.0\n */\n\nexport function globToRegExp(glob: string, options: GlobOptionsInterface = {}): RegExp {\n return new RegExp('^' + compileFragment(glob, true, 0, options) + '$', options.flags);\n}\n\n/**\n * Builds a predicate that tests a path against a set of include and exclude globs.\n *\n * @param globs - The glob patterns to match against, where a leading `!` marks an exclusion\n * @param options - Compilation options applied to every compiled pattern\n * @returns A predicate returning `true` when `path` is included by the set and excluded by none of it\n *\n * @remarks\n * Each glob is compiled once with {@link globToRegExp} and sorted into an include or exclude list.\n * A leading `!` marks the pattern as an exclusion and is stripped before compilation.\n * A repeated `!` toggles, so `!!pattern` is an inclusion again.\n * A `!` immediately followed by `(` is left in place - it is the extglob negation {@link globToRegExp} handles,\n * not a whole-pattern exclusion.\n *\n * The predicate accepts a path when it is matched by at least one include pattern and by no exclude pattern.\n * When the set contains no include patterns, every path is considered included,\n * so a set of only exclusions matches everything except what it excludes.\n *\n * @example\n * ```ts\n * const isSource = createMatcher([ '**\\/*.ts', '!**\\/*.spec.ts' ]);\n * isSource('src/app.ts'); // true\n * isSource('src/app.spec.ts'); // false - excluded\n * isSource('src/app.js'); // false - not included\n * ```\n *\n * @see globToRegExp\n * @see GlobOptionsInterface\n *\n * @since 3.0.0\n */\n\nexport function createMatcher(globs: Array<string>, options: GlobOptionsInterface = {}): (path: string) => boolean {\n const include: Array<RegExp> = [];\n const exclude: Array<RegExp> = [];\n\n for (let glob of globs) {\n let neg = false;\n while (at(glob, 0) === Char.Bang && at(glob, 1) !== Char.LParen) {\n neg = !neg;\n glob = glob.slice(1);\n }\n\n (neg ? exclude : include).push(globToRegExp(glob, options));\n }\n\n return (path) =>\n (include.length === 0 || include.some(r => r.test(path))) &&\n !exclude.some(r => r.test(path));\n}\n\n/**\n * Walks a directory tree and collects every file the globs match.\n *\n * @param base - The directory the walk starts from and the patterns are matched against\n * @param globs - The glob patterns to match, where a leading `!` marks an exclusion\n * @param options - Compilation options applied to every compiled pattern\n * @returns The matched files as paths relative to `base`, with forward slashes, in the order the walk reaches them\n *\n * @remarks\n * The base is resolved through the shared path cache,\n * and every path below it is built by appending a name to its directory's path.\n * A file therefore costs one string and one {@link createMatcher} test rather than a resolve of its own.\n * The walk is iterative, so a deep tree cannot overflow the stack,\n * and a directory that cannot be read is skipped rather than thrown from.\n * Unless `dot` is set, a name beginning with `.` is skipped before it is tested, which prunes whole trees such as `.git`.\n * A pattern that spells a leading dot, as `.github/**` or `**\\/.cache/*` does, disarms this and lets the walk descend.\n * Symbolic links are not followed, since a link never reports itself as a directory, which is what keeps a link cycle\n * from being walked.\n *\n * @example\n * ```ts\n * collectFiles(cwd(), [ 'src/**\\/*.ts', '!**\\/*.spec.ts' ]);\n * // [ 'src/index.ts', 'src/models/files.model.ts' ]\n * ```\n *\n * @see createMatcher\n * @see GlobOptionsInterface\n *\n * @since 3.0.0\n */\n\nexport function collectFiles(base: string, globs: Array<string>, options: GlobOptionsInterface = {}): Array<string> {\n const root = FrameworkService.resolve(base);\n const matcher = createMatcher(globs, options);\n const dotted = options.dot || globs.some(glob => at(glob, 0) === Char.Dot || glob.includes('/.'));\n\n const files: Array<string> = [];\n const stack: Array<string> = [ '' ];\n\n while (stack.length > 0) {\n const directory = stack.pop()!;\n\n let entries: Array<Dirent>;\n try {\n entries = readdirSync(directory ? join(root, directory) : root, { withFileTypes: true });\n } catch {\n continue;\n }\n\n for (const entry of entries) {\n if (!dotted && at(entry.name, 0) === Char.Dot) continue;\n const path = directory ? `${ directory }/${ entry.name }` : entry.name;\n\n if (entry.isDirectory()) stack.push(path);\n else if (matcher(path)) files.push(path);\n }\n }\n\n return files;\n}\n","/**\n * Imports\n */\n\nimport { Char } from '@constants/char.constant';\n\n/**\n * Regular-expression fragments emitted while compiling a glob into a {@link RegExp} source.\n *\n * @remarks\n * Each member is a reusable snippet of regex syntax with a fixed meaning in the compiled output,\n * so the compiler can assemble a pattern by concatenating members rather than repeating string literals.\n * Declared as a `const enum` so references inline to their literal value at compile time.\n *\n * @example\n * ```ts\n * RegexElement.NotDot + RegexElement.NotSlashRun; // '(?!\\\\.)[^/]*' - the source for a leading `*`\n * ```\n *\n * @see RegexCloser\n * @since 3.0.0\n */\n\nexport const enum RegexElement {\n /**\n * The alternation separator `|`.\n *\n * @since 3.0.0\n */\n\n Alt = '|',\n\n /**\n * The opening of a non-capturing group `(?:`.\n *\n * @since 3.0.0\n */\n\n Open = '(?:',\n\n /**\n * The literal path separator `/`.\n *\n * @since 3.0.0\n */\n\n Slash = '/',\n\n /**\n * A zero-width guard `(?!\\.)` that forbids a leading dot at the start of a segment.\n *\n * @remarks\n * Prevents a wildcard from matching a dotfile unless the pattern names the dot explicitly.\n *\n * @since 3.0.0\n */\n\n NotDot = '(?!\\\\.)',\n\n /**\n * A single character class `[^/]` matching any one character except the path separator.\n *\n * @since 3.0.0\n */\n\n NotSlash = '[^/]',\n\n /**\n * A segment boundary `(?:$|/)` matching either the end of the string or a slash.\n *\n * @since 3.0.0\n */\n\n SegBreak = '(?:$|/)',\n\n /**\n * A greedy run `[^/]*` of characters that are not the path separator.\n *\n * @since 3.0.0\n */\n\n NotSlashRun = '[^/]*',\n\n /**\n * A single character class `[^./]` matching any one character except `.` or `/`.\n *\n * @remarks\n * Emitted for `?` at the start of a segment, where a leading dot must not match.\n *\n * @since 3.0.0\n */\n\n NotDotSlash = '[^./]',\n\n /**\n * A lazy run `[^/]*?` of characters that are not the path separator.\n *\n * @remarks\n * Used as the body of a negation so the negative lookahead governs how much the segment consumes.\n *\n * @since 3.0.0\n */\n\n NotSlashLazy = '[^/]*?',\n\n /**\n * An optional absolute-path root `(?:[A-Za-z]:)?/?` matching a Windows drive prefix and/or a leading slash.\n *\n * @remarks\n * Emitted before a leading globstar so a relative pattern such as `**\\/*.ts` also matches an absolute path\n * like `/a/b/c.ts` or `C:/a/b/c.ts`.\n * Both parts are optional, so a purely relative path still matches.\n * Path separators are assumed to be forward slashes, so normalize Windows backslashes before testing.\n *\n * @since 3.0.0\n */\n\n AbsRoot = '(?:[A-Za-z]:)?/?',\n}\n\n/**\n * Maps an extglob prefix character to the regex closer that ends its non-capturing group.\n *\n * @remarks\n * Keyed by the {@link Char} code unit that precedes a `(` in an extglob construct,\n * the value carries the group-closing parenthesis together with the quantifier that reproduces the prefix semantics.\n * - `@( ... )` matches the group exactly once.\n * - `+( ... )` matches the group one or more times.\n * - `*( ... )` matches the group zero or more times.\n * - `?( ... )` matches the group zero or one time.\n * The presence of a key also signals that the prefix opens an extglob group,\n * so the compiler tests membership before treating the character as extglob syntax.\n *\n * @example\n * ```ts\n * RegexCloser[Char.Plus]; // ')+' - so `+(ab)` compiles to `(?:ab)+`\n * RegexCloser[Char.Bang]; // undefined - `!(` is a negation, handled apart\n * ```\n *\n * @see Char\n * @see RegexElement\n *\n * @since 3.0.0\n */\n\nexport const RegexCloser: Record<number, string> = {\n [Char.At]: ')',\n [Char.Plus]: ')+',\n [Char.Star]: ')*',\n [Char.Question]: ')?'\n} as const;\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { Argv } from 'yargs';\nimport type { BaseArgumentsInterface } from '@argv/interfaces/argv-module.interface';\nimport type { UserExtensionInterface, ArgumentsInterface } from '@argv/interfaces/argv-module.interface';\n\n/**\n * Imports\n */\n\nimport yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport { Injectable } from '@remotex-labs/xinject';\nimport { ArgsDefaultOptions, ArgsUsageExamples } from '@argv/constants/argv.constant';\n\n/**\n * Parses the command line in the two passes startup needs.\n *\n * @remarks\n * A configuration file may add options of its own, so the full option set is not known when the process starts.\n * The passes resolve that: {@link parseConfigFile} reads the `--config` path alone, the file it names is loaded and\n * its options collected, and {@link enhancedParse} then parses the line again knowing everything.\n * The first pass leaves `--help` and `--version` switched off so a run cannot exit on a half-built option set,\n * showing help that omits the configuration's own flags.\n * Only the second turns them on, along with the strict mode that rejects what none of the options account for.\n * Registered as a singleton, so every stage parses against one instance.\n *\n * @example\n * ```ts\n * const argv = inject(ArgvModule);\n *\n * const { config } = argv.parseConfigFile(process.argv); // 'config.xbuild.ts'\n * const userOptions = (await loadConfig(config)).userArgv; // options the file adds\n * argv.enhancedParse(process.argv, userOptions).entryPoints; // [ 'src/index.ts' ]\n * ```\n *\n * @see ArgsDefaultOptions\n * @since 2.0.0\n */\n\n@Injectable({\n scope: 'singleton'\n})\nexport class ArgvModule {\n /**\n * Reads the configuration file path before the rest of the options are known.\n *\n * @param argv - Command-line arguments to read\n * @returns The parsed arguments, always carrying a `config` path\n *\n * @remarks\n * Only `config` is declared, so everything else on the line falls through into the positional list rather than\n * failing - strict mode belongs to {@link enhancedParse}, which is the pass that knows the whole option set.\n * The path is never missing, the option carrying its own default, so a caller has nothing to fall back to.\n * The arguments are passed to yargs as given rather than through `hideBin`,\n * so the executable and script land in the positions and are ignored here, `config` being the only thing read.\n *\n * @example\n * ```ts\n * argv.parseConfigFile(process.argv).config; // 'config.xbuild.ts' - the default\n *\n * // xBuild --config build/prod.xbuild.ts src/index.ts\n * argv.parseConfigFile(process.argv).config; // 'build/prod.xbuild.ts'\n * ```\n *\n * @see enhancedParse\n * @since 2.0.0\n */\n\n parseConfigFile(argv: Array<string>): BaseArgumentsInterface & { config: string } {\n return yargs(argv)\n .help(false)\n .version(false)\n .options({\n config: ArgsDefaultOptions.config\n }).parseSync() as BaseArgumentsInterface & { config: string };\n }\n\n /**\n * Parses the whole command line, xBuild's options, and the configuration together.\n *\n * @param argv - Command-line arguments to parse, executable and script included\n * @param userExtensions - Options the configuration file adds to xBuild's own\n * @returns Every option the line carried, validated against the complete set\n *\n * @throws Error - Thrown by yargs on an unknown flag, a missing value, or a value outside an option's choices\n *\n * @remarks\n * The pass that can afford to be strict, both option sets being known by now: a misspelled flag fails here rather\n * than being collected and silently ignored.\n * Files named without a flag are taken as `entryPoints` through the default command, so the usual invocation\n * needs no flag at all.\n * Help lists the two sets under headings of their own, which is done inside an overridden `showHelp` rather than\n * up front - grouping costs nothing on a run that never asks for help.\n * `hideBin` drops the executable and script here, unlike the first pass, so the positions hold only what\n * the user typed.\n *\n * @example\n * ```ts\n * // xBuild src/app.ts --bundle --minify --env prod\n * const args = argv.enhancedParse(process.argv, { env: { type: 'string' } });\n *\n * args.entryPoints; // [ 'src/app.ts' ]\n * args.bundle; // true\n * args.env; // 'prod' - the configuration's own option\n * ```\n *\n * @see ArgsUsageExamples\n * @since 2.0.0\n */\n\n enhancedParse(argv: Array<string>, userExtensions: UserExtensionInterface = {}): ArgumentsInterface {\n const parser = yargs(hideBin(argv)).locale('en');\n const originalShowHelp = parser.showHelp;\n parser.showHelp = function (consoleFunction?: string | ((s: string) => void)): Argv<unknown> {\n this.group(Object.keys(ArgsDefaultOptions), 'xBuild Options:');\n this.group(Object.keys(userExtensions), 'user Options:');\n\n return originalShowHelp.call(this, consoleFunction as (s: string) => void);\n };\n\n parser\n .usage('Usage: xBuild [files..] [options]')\n .command('* [entryPoints..]', 'Specific files to build (supports glob patterns)', (yargs) => {\n return yargs.positional('entryPoints', {\n describe: 'Specific files to build (supports glob patterns)',\n type: 'string',\n array: true\n });\n })\n .options(userExtensions)\n .options(ArgsDefaultOptions)\n .epilogue('For more information, check the documentation https://remotex-labs.github.io/xBuild/')\n .help()\n .alias('help', 'h')\n .strict()\n .version();\n\n ArgsUsageExamples.forEach(([ command, description ]) => {\n parser.example(command, description);\n });\n\n return parser.parseSync();\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { Options } from 'yargs';\n\n/**\n * Path the `--config` option falls back to.\n *\n * @remarks\n * Resolved against the working directory, so the file is picked up by name from wherever the build was started.\n * It is the default of the option itself rather than a fallback applied afterward,\n * which is what lets every parse pass report a path whether one was typed.\n *\n * @example\n * ```ts\n * ArgsConfigPath; // 'config.xbuild.ts'\n * ArgsDefaultOptions.config.default; // 'config.xbuild.ts' - the same value, reused\n * ```\n *\n * @since 3.0.0\n */\n\nexport const ArgsConfigPath = 'config.xbuild.ts' as const;\n\n/**\n * Every option xBuild itself accepts, in the form yargs declares them.\n *\n * @remarks\n * One table serving three purposes:\n * - it declares the options for the full parse,\n * - it supplies `config` on its own to the early pass that only needs the configuration path,\n * - and its keys name the flags help gathers under the xBuild heading.\n *\n * An option added here is therefore declared, parsed, and documented by that one edit.\n * Only `config` carries a default, so every other flag is absent from the parse result unless it was typed.\n * That is what lets configuration handling tell a flag that was left out from one that was passed as `false`.\n * `platform` and `format` restrict their values, so an unrecognized one fails during parsing rather than reaching the\n * build.\n *\n * @example\n * ```ts\n * ArgsDefaultOptions.minify.alias; // 'm'\n * ArgsDefaultOptions.format.choices; // [ 'cjs', 'esm', 'iife' ]\n * Object.keys(ArgsDefaultOptions); // the flags listed under 'xBuild Options:' in help\n * ```\n *\n * @see ArgsConfigPath\n * @since 3.0.0\n */\n\nexport const ArgsDefaultOptions: Record<string, Options> = {\n entryPoints: {\n describe: 'Source files to build (supports glob patterns)',\n type: 'string',\n array: true\n },\n typeCheck: {\n describe: 'Perform type checking without building output',\n alias: 'tc',\n type: 'boolean'\n },\n platform: {\n describe: 'Target platform for the build output',\n alias: 'p',\n type: 'string',\n choices: [ 'browser', 'node', 'neutral' ] as const\n },\n serve: {\n describe: 'Start server to the <folder>',\n alias: 's',\n type: 'string'\n },\n outdir: {\n describe: 'Directory for build output files',\n alias: 'o',\n type: 'string'\n },\n declaration: {\n describe: 'Generate TypeScript declaration files (.d.ts)',\n alias: 'de',\n type: 'boolean'\n },\n watch: {\n describe: 'Watch mode - rebuild on file changes',\n alias: 'w',\n type: 'boolean'\n },\n config: {\n describe: 'Path to build configuration file',\n alias: 'c',\n type: 'string',\n default: ArgsConfigPath\n },\n tsconfig: {\n describe: 'Path to TypeScript configuration file',\n alias: 'tsc',\n type: 'string'\n },\n minify: {\n describe: 'Minify the build output',\n alias: 'm',\n type: 'boolean'\n },\n bundle: {\n describe: 'Bundle dependencies into output files',\n alias: 'b',\n type: 'boolean'\n },\n types: {\n describe: 'Enable type checking during build process',\n alias: 'btc',\n type: 'boolean'\n },\n failOnError: {\n describe: 'Fail build when TypeScript errors are detected',\n alias: 'foe',\n type: 'boolean'\n },\n format: {\n describe: 'Output module format',\n alias: 'f',\n type: 'string',\n choices: [ 'cjs', 'esm', 'iife' ]\n },\n verbose: {\n describe: 'Verbose error stack traces',\n alias: 'v',\n type: 'boolean'\n },\n build: {\n describe: 'Select an build configuration variant by names (as defined in your config file)',\n alias: 'xb',\n type: 'string',\n array: true\n },\n clean: {\n describe: 'Clean build artifacts',\n type: 'boolean',\n default: false\n }\n} as const;\n\n/**\n * Command and description pairs shown in the examples section of the help output.\n *\n * @remarks\n * Registered one by one on the parser, so the order here is the order they are printed in.\n * They document the combinations worth reaching for rather than every flag,\n * the option list above already covers each flag on its own.\n *\n * @example\n * ```ts\n * ArgsUsageExamples[0]; // [ 'xBuild src/index.ts', 'Build a single file with default settings' ]\n * ```\n *\n * @see ArgsDefaultOptions\n * @since 3.0.0\n */\n\nexport const ArgsUsageExamples = [\n [ 'xBuild src/index.ts', 'Build a single file with default settings' ],\n [ 'xBuild src/**/*.ts --bundle --minify', 'Bundle and minify all TypeScript files' ],\n [ 'xBuild src/app.ts -s', 'Development mode with watch and dev server' ],\n [ 'xBuild src/app.ts -s dist', 'Development mode with watch and dev server from dist folder' ],\n [ 'xBuild src/lib.ts --format esm --declaration', 'Build ESM library with type definitions' ],\n [ 'xBuild src/server.ts --platform node --outdir dist', 'Build Node.js application to dist folder' ],\n [ 'xBuild --typeCheck', 'Type check only without generating output' ],\n [ 'xBuild --config custom.xbuild.ts', 'Use custom configuration file' ]\n] as const;\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { IncomingMessage, ServerResponse } from 'http';\nimport type { ServerAddressInterface, ServerConfigurationInterface, ServerEventsType } from '@server/interfaces/server.interface';\n\n/**\n * Imports\n */\n\nimport * as http from 'http';\nimport * as https from 'https';\nimport { extname } from 'path';\nimport { readFileSync } from 'fs';\nimport html from './html/server.html';\nimport { join } from '@remotex-labs/xmap';\nimport { inject } from '@remotex-labs/xinject';\nimport { Subject } from '@remotex-labs/xobservable';\nimport { readdir, stat, readFile } from 'fs/promises';\nimport { FrameworkService } from '@services/framework.service';\n\n/**\n * Serves one directory over HTTP or HTTPS, files and listings alike.\n *\n * @remarks\n * Meant for looking at build output while developing:\n * a request maps to a path under the root, a file is sent with a content type guessed from its extension,\n * and a directory is rendered as a browsable listing.\n * A configuration can take a request over before any of that happens,\n * which is the hook to reach for when the output needs an API beside it or a single-page fallback.\n * Nothing here writes to a terminal: what it does is reported on a stream, so a run decides what to say about it.\n * Constructed rather than injected, so a build can run several of them over different roots at once.\n *\n * @example\n * ```ts\n * const server = new ServerModule({ port: 0, verbose: true }, 'dist');\n *\n * await server.start(); // resolves once listening, after onStart has run\n * server.config.port; // 54321 - the port the system picked, written back\n * await server.stop();\n * ```\n *\n * @see ServerConfigurationInterface\n * @since 2.0.0\n */\n\nexport class ServerModule {\n /**\n * Node server currently listening, absent until {@link start} and again after {@link stop}.\n *\n * @remarks\n * Holds either an HTTP or an HTTPS server,\n * since the HTTPS type extends the HTTP one and the two are interchangeable here.\n * Its presence is what {@link stop} treats as whether anything is running.\n *\n * @since 2.0.0\n */\n\n private server?: http.Server;\n\n /**\n * The stream everything this server does is reported on.\n *\n * @remarks\n * The server says what happened and writes none of it,\n * so a run decides for itself what reaches a terminal, and one that wants none of it subscribes to nothing.\n * Kept private and reached through {@link pipe} and {@link subscribe},\n * which is what keeps a reader from reporting an event of its own.\n *\n * @see ServerEventsType\n * @since 3.0.0\n */\n\n private readonly events$ = new Subject<ServerEventsType>();\n\n /**\n * Absolute directory every request is resolved inside.\n *\n * @remarks\n * Resolved once in the constructor, so a later change to the working directory cannot move what is being served.\n *\n * @since 2.0.0\n */\n\n private readonly rootDir: string;\n\n /**\n * Framework service, consulted for the directory the bundled certificates ship in.\n *\n * @remarks\n * Only reached when HTTPS is started without a key and certificate of its own.\n *\n * @see FrameworkService\n * @since 2.0.0\n */\n\n private readonly framework = inject(FrameworkService);\n\n /**\n * Creates a server over one directory.\n *\n * @param config - How to listen and what to do with requests\n * @param dir - Directory to serve, resolved to an absolute path immediately\n *\n * @remarks\n * The configuration is kept by reference rather than copied: the host and port defaults land on it here,\n * and the port the system assigns lands on it once listening.\n * The object the caller passed is therefore also how the caller learns what was bound.\n * A port of `0`, which is also the default, leaves the choice to the operating system.\n *\n * @example\n * ```ts\n * const config = { port: 8080, https: true, onRequest: (req, res, next) => next() };\n * const server = new ServerModule(config, './public');\n *\n * config.host; // 'localhost' - defaulted here, on the caller's own object\n * ```\n *\n * @see ServerConfigurationInterface\n * @since 2.0.0\n */\n\n constructor(readonly config: ServerConfigurationInterface, dir: string) {\n this.rootDir = FrameworkService.resolve(dir);\n this.config.port ||= 0;\n this.config.host ||= 'localhost';\n }\n\n /**\n * The event stream's `pipe`, bound to the stream.\n *\n * @remarks\n * Hands out the operator chain without handing out the subject,\n * so a reader composes on what the server reports and cannot report anything itself.\n *\n * @example\n * ```ts\n * server.pipe(filter(event => event.type === 'request')).subscribe(report);\n * ```\n *\n * @see subscribe\n * @since 3.0.0\n */\n\n get pipe(): typeof this.events$.pipe {\n return this.events$.pipe.bind(this.events$);\n }\n\n /**\n * The event stream's `subscribe`, bound to the stream.\n *\n * @remarks\n * How a run learns what the server is doing, since the server itself writes nothing.\n * Answers with the handle that ends the subscription, as the stream's own `subscribe` does.\n *\n * @example\n * ```ts\n * const unsubscribe = server.subscribe(event => event.type); // 'start', then 'request'\n * unsubscribe();\n * ```\n *\n * @see pipe\n * @since 3.0.0\n */\n\n get subscribe(): typeof this.events$.subscribe {\n return this.events$.subscribe.bind(this.events$);\n }\n\n /**\n * Starts listening over HTTPS when the configuration asks for it and over HTTP otherwise.\n *\n * @returns A promise settling once the server is listening\n *\n * @remarks\n * The `onStart` hook runs from the listen callback,\n * so it has already been called - and the assigned port already written back - by the time this resolves.\n * Nothing guards against starting twice:\n * a second call replaces the reference and leaves the first server listening with no way left to close it,\n * so reach for {@link restart} rather than starting again.\n *\n * @example\n * ```ts\n * const server = new ServerModule({ port: 3000, onStart: ({ url }) => console.log(url) }, 'dist');\n * await server.start(); // logs 'http://localhost:3000'\n * ```\n *\n * @see stop\n * @see restart\n *\n * @since 2.0.0\n */\n\n async start(): Promise<void> {\n if (this.config.https)\n return await this.startHttpsServer();\n\n await this.startHttpServer();\n }\n\n /**\n * Closes the server and waits for it to finish.\n *\n * @returns A promise settling once every connection has ended\n *\n * @throws Error - Reported by Node when the server was already closed underneath\n *\n * @remarks\n * Closing refuses new connections and waits on the ones in flight,\n * so a request already in progress delays this rather than ending mid-flight.\n * Stopping when nothing is running is not an error - it reports as much and returns.\n *\n * @example\n * ```ts\n * await server.stop(); // 'Server stopped.'\n * await server.stop(); // 'No server is currently running.'\n * ```\n *\n * @see start\n * @since 2.0.0\n */\n\n async stop(): Promise<void> {\n if (!this.server) return this.events$.next({ type: 'stop', running: false });\n\n await new Promise<void>((resolve, reject) => {\n this.server!.close(err => {\n if (err) reject(err);\n else resolve();\n });\n });\n\n this.server = undefined;\n this.events$.next({ type: 'stop', running: true });\n }\n\n /**\n * Stops the server and starts it again.\n *\n * @returns A promise settling once the new server is listening\n *\n * @remarks\n * Reads the configuration afresh on the way back up, so an edit made while it was running takes effect.\n * A port left at `0` is no longer `0` by then, since the previous run wrote the assigned one back,\n * so a restart keeps the port it was given rather than asking for another.\n *\n * @example\n * ```ts\n * server.config.verbose = true;\n * await server.restart(); // 'Restarting server...' then listening again, now logging requests\n * ```\n *\n * @see stop\n * @see start\n *\n * @since 2.0.0\n */\n\n async restart(): Promise<void> {\n await this.stop();\n await this.start();\n }\n\n /**\n * Writes the port the system assigned back onto the configuration.\n *\n * @remarks\n * Only a configured `0` is replaced, since `0` is the value that leaves the choice to the operating system.\n * A port asked for by number is already what was bound.\n * Called from the listen callback, before `onStart`, so the hook and every later reader see the real port.\n *\n * @since 2.0.0\n */\n\n private setActualPort(): void {\n if (this.config.port === 0) {\n const address = this.server!.address();\n if(address && typeof address === 'object' && address.port)\n this.config.port = address.port;\n }\n }\n\n /**\n * Creates and starts the plain HTTP server.\n *\n * @returns A promise settling once the server is listening\n *\n * @remarks\n * Every request goes through {@link handleRequest},\n * which is handed the default handling as a callback,\n * so a configuration hook can decide whether to run it.\n *\n * @since 2.0.0\n */\n\n private startHttpServer(): Promise<void> {\n return new Promise<void>((resolve) => {\n this.server = http.createServer((req, res) => {\n this.handleRequest(req, res, () => this.defaultResponse(req, res));\n });\n\n this.server.listen(this.config.port, this.config.host, () => {\n this.setActualPort();\n const address: ServerAddressInterface = {\n host: this.config.host!,\n port: this.config.port!,\n url: `http://${ this.config.host }:${ this.config.port }`\n };\n\n this.config.onStart?.(address);\n this.events$.next({ ...address, type: 'start' });\n resolve();\n });\n });\n }\n\n /**\n * Creates and starts the HTTPS server.\n *\n * @returns A promise settling once the server is listening\n *\n * @throws Error - Raised when a key or certificate cannot be read\n *\n * @remarks\n * A configuration naming neither key nor certificate falls back to the pair shipped with the framework,\n * so HTTPS can be switched on without producing one first.\n * That pair is self-signed, so a browser will warn about it, which is what a development server can live with.\n * Both files are read synchronously, before anything is listening,\n * so a missing one fails the start rather than the first request.\n *\n * @since 2.0.0\n */\n\n private startHttpsServer(): Promise<void> {\n return new Promise((resolve) => {\n const options = {\n key: readFileSync(this.config.key ?? join(this.framework.frameworkRoot, '..', 'certs', 'server.key')),\n cert: readFileSync(this.config.cert ?? join(this.framework.frameworkRoot, '..', 'certs', 'server.crt'))\n };\n\n this.server = https.createServer(options, (req, res) => {\n this.handleRequest(req, res, () => this.defaultResponse(req, res));\n });\n\n this.server.listen(this.config.port, this.config.host, () => {\n this.setActualPort();\n const address: ServerAddressInterface = {\n host: this.config.host!,\n port: this.config.port!,\n url: `https://${ this.config.host }:${ this.config.port }`\n };\n\n this.config.onStart?.(address);\n this.events$.next({ ...address, type: 'start' });\n resolve();\n });\n });\n }\n\n /**\n * Passes a request to the configuration's hook or to the default handling when there is none.\n *\n * @param req - Request as it arrived\n * @param res - Response to write to\n * @param defaultHandler - The static-file handling, for the hook to call or to skip\n *\n * @remarks\n * A hook that never calls the handler owns the response entirely,\n * which is what makes an API route or a single-page fallback possible.\n * Only what throws synchronously reaches the error response here:\n * the default handling is asynchronous and catches its own failures,\n * and a hook that rejects a promise of its own is beyond this.\n *\n * @see sendError\n * @since 2.0.0\n */\n\n private handleRequest(req: IncomingMessage, res: ServerResponse, defaultHandler: () => void): void {\n try {\n this.events$.next({ type: 'request', url: req.url ?? '' });\n\n if (this.config.onRequest) {\n this.config.onRequest(req, res, defaultHandler);\n } else {\n defaultHandler();\n }\n } catch (error) {\n this.sendError(res, <Error> error);\n }\n }\n\n /**\n * Maps a file extension to the content type it is served as.\n *\n * @param ext - Extension without its dot\n * @returns The matching content type, or the binary fallback for an extension not listed\n *\n * @remarks\n * Covers what a build emits rather than the web at large.\n * TypeScript is served as plain text, so a browser shows a source file instead of downloading it,\n * and an unlisted extension downloads under the binary fallback rather than under a guess.\n *\n * @since 2.0.0\n */\n\n private getContentType(ext: string): string {\n const contentTypes: Record<string, string> = {\n html: 'text/html',\n css: 'text/css',\n js: 'application/javascript',\n cjs: 'application/javascript',\n mjs: 'application/javascript',\n ts: 'text/plain',\n map: 'application/json',\n json: 'application/json',\n png: 'image/png',\n jpg: 'image/jpeg',\n gif: 'image/gif',\n txt: 'text/plain'\n };\n\n return contentTypes[ext] || 'application/octet-stream';\n }\n\n /**\n * Resolves a request to a path under the root and serves whatever is there.\n *\n * @param req - Request as it arrived\n * @param res - Response to write to\n *\n * @remarks\n * The request path is joined onto the root and the result checked for the root prefix,\n * so a path climbing out with `..` is refused with a 403.\n * The check is by prefix rather than true containment,\n * so a sibling directory whose name starts with the root's own would pass it.\n * A directory is listed and a file is sent.\n * Anything else on disk - a socket or a device - matches neither, and the request ends unanswered.\n * A path that cannot be reached at all is reported as missing,\n * and a failed `favicon.ico` is passed over in the log, since browsers ask for one unprompted on every visit.\n *\n * @see handleFile\n * @see handleDirectory\n *\n * @since 2.0.0\n */\n\n private async defaultResponse(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const requestPath = req.url === '/' ? '' : req.url?.replace(/^\\/+/, '') || '';\n const fullPath = join(this.rootDir, requestPath);\n\n if (!fullPath.startsWith(this.rootDir)) {\n res.statusCode = 403;\n res.end();\n\n return;\n }\n\n try {\n const stats = await stat(fullPath);\n\n if (stats.isDirectory()) {\n await this.handleDirectory(fullPath, requestPath, res);\n } else if (stats.isFile()) {\n await this.handleFile(fullPath, res);\n }\n } catch (error) {\n this.events$.next({ type: 'error', error: <Error> error, url: req.url });\n this.sendNotFound(res);\n }\n }\n\n /**\n * Renders a directory as a browsable listing.\n *\n * @param fullPath - Absolute path of the directory to list\n * @param requestPath - The same directory as the request spelled it, relative to the root\n * @param res - Response to write to\n *\n * @remarks\n * Entries are told apart by whether they have an extension,\n * so a directory carrying a dot in its name is drawn as a file,\n * since a listing is navigation rather than a report.\n * The request path is also split into a trail of links, one per directory it names,\n * which is what lets a visitor climb back out.\n * Names are put into the template as they are, so a filename containing markup reaches the page intact.\n *\n * @since 2.0.0\n */\n\n private async handleDirectory(fullPath: string, requestPath: string, res: ServerResponse): Promise<void> {\n const files = await readdir(fullPath);\n let fileList = files.map(file => {\n const fullPath = join(requestPath, file);\n const ext = extname(file).slice(1) || 'folder';\n\n if(ext === 'folder') {\n return `\n <a href=\"/${ fullPath }\" class=\"folder-row\">\n <div class=\"icon\"><i class=\"fa-solid fa-folder\"></i></div>\n <div class=\"meta\"><div class=\"name\">${ file }</div><div class=\"sub\">Folder</div></div>\n </a>\n `;\n }\n\n return `\n <a href=\"/${ fullPath }\" class=\"file-row\">\n <div class=\"icon\"><i class=\"fa-solid fa-file-code\"></i></div>\n <div class=\"meta\"><div class=\"name\">${ file }</div><div class=\"sub\">${ ext }</div></div>\n </a>\n `;\n }).join('');\n\n if(!fileList) {\n fileList = '<div class=\"empty\">No files or folders here.</div>';\n } else {\n fileList = `<div class=\"list\">${ fileList }</div>`;\n }\n\n let activePath = '/';\n const segments = requestPath.split('/').map(path => {\n activePath += `${ path }/`;\n\n return `<li><a href=\"${ activePath }\">${ path }</a></li>`;\n }).join('');\n\n const htmlResult = html.replace('${ fileList }', fileList)\n .replace('${ paths }', '<li><a href=\"/\">root</a></li>' + segments)\n .replace('${ up }', '/' + requestPath.split('/').slice(0, -1).join('/'));\n\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(htmlResult);\n }\n\n /**\n * Sends one file.\n *\n * @param fullPath - Absolute path of the file to send\n * @param res - Response to write to\n *\n * @remarks\n * Read whole before anything is written,\n * so the response carries no length and a large file is held in memory rather than streamed,\n * which a development server over its own build output can afford.\n * A file with no extension is treated as text.\n *\n * @see getContentType\n * @since 2.0.0\n */\n\n private async handleFile(fullPath: string, res: ServerResponse): Promise<void> {\n const ext = extname(fullPath).slice(1) || 'txt';\n const contentType = this.getContentType(ext);\n\n const data = await readFile(fullPath);\n res.writeHead(200, { 'Content-Type': contentType });\n res.end(data);\n }\n\n /**\n * Answers a request that reached nothing.\n *\n * @param res - Response to write to\n *\n * @remarks\n * Plain text rather than the listing template, since the answer is for whatever asked rather than for a reader.\n *\n * @since 2.0.0\n */\n\n private sendNotFound(res: ServerResponse): void {\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('Not Found');\n }\n\n /**\n * Answers a request that failed and reports why.\n *\n * @param res - Response to write to\n * @param error - The failure to report\n *\n * @remarks\n * The reason is logged rather than sent,\n * so a stack trace reaches the developer running the server and not whoever is connected to it.\n *\n * @since 2.0.0\n */\n\n private sendError(res: ServerResponse, error: Error): void {\n this.events$.next({ type: 'error', error });\n res.writeHead(500, { 'Content-Type': 'text/plain' });\n res.end('Internal Server Error');\n }\n}\n","<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"/><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"/><title>Dark File Browser — FTP-like</title><link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/css/all.min.css\" integrity=\"sha512-2SwdPD6INVrV/lHTZbO2nodKhrnDdJK9/kg2XD1r9uGqPo1cUbujc+IYdlYdEErWNu69gVcYgdxlmVmzTWnetw==\" crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\" /><style>:root{--bg:#0b0f14;--panel:#0f1720;--muted:#9aa4b2;--accent:#E5C07B;--glass:rgba(255,255,255,0.03);--card:#0c1116;--radius:12px;--gap:12px;--shadow:0 6px 18px rgba(0,0,0,0.4);--file-icon-size:40px;font-family:Inter,ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,'Helvetica Neue',Arial}*{box-sizing:border-box;font-style:normal !important}html,body{height:100%;margin:0;font-size:14px;color:#dce7ef;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:radial-gradient(1200px 600px at 10% 10%,rgba(110,231,183,0.04),transparent 8%),linear-gradient(180deg,rgba(255,255,255,0.01),transparent 20%),var(--bg);padding:28px;display:flex;gap:20px;align-items:flex-start;justify-content:center}.app{width:1100px;max-width:98vw;display:flex;gap:18px;padding:18px;border-radius:16px;box-shadow:var(--shadow);border:1px solid rgba(255,255,255,0.03);background:linear-gradient(180deg,rgba(255,255,255,0.02),rgba(255,255,255,0));overflow:hidden}.sidebar{width:260px;background:linear-gradient(180deg,rgba(255,255,255,0.01),transparent);border-radius:var(--radius);padding:14px}.brand{display:flex;gap:12px;align-items:center;margin-bottom:10px}.logo{width:46px;height:46px;border-radius:10px;background:linear-gradient(135deg,#b65b9f 0%,#804b8f 100%);display:flex;align-items:center;justify-content:center;font-weight:700}.brand h1{font-size:16px;margin:0}.muted{color:var(--muted);font-size:13px}.search{margin:12px 0}.search input{width:100%;padding:10px 12px;border-radius:10px;border:1px solid rgba(255,255,255,0.03);background:var(--glass);color:inherit}.quick-list{margin-top:12px}.quick-list a{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;background:transparent;color:var(--muted);text-decoration:none;cursor:pointer;transition:color 0.15s ease}.quick-list a:hover{color:var(--accent)}.main{flex:1;display:flex;flex-direction:column}.topbar{display:flex;align-items:center;gap:12px;padding-bottom:12px}.breadcrumbs{list-style:none;display:flex;gap:8px;align-items:center;background:var(--glass);padding:8px 12px;border-radius:var(--radius);margin:0}.breadcrumbs li{display:flex;align-items:center}.breadcrumbs li:not(:last-child)::after{content:'>';margin-left:8px;color:var(--muted)}.breadcrumbs a{color:var(--muted);text-decoration:none;transition:color 0.15s ease}.breadcrumbs a:hover{color:var(--accent)}.list{margin-top:14px;display:grid;grid-template-columns:1fr;gap:10px}.list a{display:flex;text-decoration:none;color:inherit}.folder-row,.file-row{display:flex;gap:12px;align-items:center;padding:10px;border-radius:10px;background:linear-gradient(180deg,rgba(255,255,255,0.01),transparent);border:1px solid rgba(255,255,255,0.02);transition:color 0.25s ease}.icon{width:var(--file-icon-size);height:var(--file-icon-size);border-radius:10px;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,0.02);flex-shrink:0;transition:background 0.25s ease,color 0.25s ease}.folder-row:hover,.file-row:hover{color:var(--accent)}.folder-row:hover .icon{background:rgba(152,195,121,0.2)}.file-row:hover .icon{background:rgba(224,108,117,0.2)}.folder-row:hover .icon i{color:#98C379}.file-row:hover .icon i{color:#e09c6c}.meta{display:flex;flex-direction:column}.name{font-weight:600}.sub{color:var(--muted);font-size:13px}.empty{padding:40px;text-align:center;color:var(--muted)}@media (max-width:880px){.app{flex-direction:column;padding:12px}.sidebar,.main{width:100%}}</style></head><body><div class=\"app\"><aside class=\"sidebar\"><div class=\"brand\"><div class=\"logo\">F</div><div><h1>xBuildFTP</h1><div class=\"muted\">Browse & serve files</div></div></div><div class=\"search\"><input placeholder=\"Search files & folders...\"/></div><div class=\"quick-list\"><a href=\"/\">🏠 Home</a><a href=\"${ up }\">⬆️ Up</a></div></aside><main class=\"main\"><div class=\"topbar\"><div class=\"topbar\"><ul class=\"breadcrumbs\"> ${ paths } </ul></div></div> ${ fileList } </main></div></body><script> const searchInput = document.querySelector('.search input'); const listItems = document.querySelectorAll('.list > .folder-row, .list > .file-row'); const emptyMessage = document.querySelector('.empty'); searchInput.addEventListener('input', () => { const query = searchInput.value.toLowerCase(); let anyVisible = false; listItems.forEach(item => { const name = item.querySelector('.name').textContent.toLowerCase(); if (name.includes(query)) { item.style.display = 'flex'; anyVisible = true; } else { item.style.display = 'none'; } }); emptyMessage.style.display = anyVisible ? 'none' : 'block'; }); </script></html>","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { Message } from 'esbuild';\nimport type { DeepPartialType } from '@interfaces/types.interface';\nimport type { ConfigurationInterface } from '@interfaces/configuration.interface';\nimport type { BuildResultInterface, LifecycleEventsType, LifecycleLogsType } from '@interfaces/lifecycle.interface';\n\n/**\n * Imports\n */\n\nimport { inject } from '@remotex-labs/xinject';\nimport { xBuildError } from '@errors/xbuild.error';\nimport { Subject } from '@remotex-labs/xobservable';\nimport { VariantService } from '@services/variant.service';\nimport { ConfigurationService } from '@services/configuration.service';\nimport { TypescriptService } from '@typescript/services/typescript.service';\n\n/**\n * Runs a whole configuration - every variant it declares, in the order their dependencies allow.\n *\n * @remarks\n * Owns the configuration for a run and the event stream the variants report on,\n * while each variant owns the build it runs.\n * A variant is constructed for every entry the configuration declares and reused from then on,\n * so re-reading an edited configuration adds what it gained and leaves the rest running.\n *\n * @example\n * ```ts\n * const build = new BuildService(config, { watch: true });\n * build.subscribe(event => event.type); // 'start', then 'end'\n *\n * const results = await build.build();\n * results.length; // 2 - one per variant\n * ```\n *\n * @see VariantService\n * @see ConfigurationInterface\n *\n * @since 3.0.0\n */\n\nexport class BuildService {\n /**\n * The stream every variant reports its start and end on.\n *\n * @remarks\n * Handed to each variant as it is constructed, so one stream carries the whole run\n * rather than a reader subscribing to each variant in turn.\n * Kept private and reached through `pipe` and `subscribe`,\n * which is what keeps a reader from pushing an event of its own onto it.\n *\n * @see LifecycleEventsType\n * @since 3.0.0\n */\n\n private readonly events$ = new Subject<LifecycleEventsType>();\n\n /**\n * The configuration service this run reads and writes through.\n *\n * @remarks\n * The injected instance rather than one of its own, and the same instance every variant selects from,\n * so a change written here reaches the variants without being handed to them.\n *\n * @see ConfigurationService\n * @since 3.0.0\n */\n\n private readonly config$ = inject(ConfigurationService);\n\n /**\n * Applies a configuration and constructs a variant for every entry it declares.\n *\n * @param config - Configuration to run, merged over whatever the service already holds\n * @param argv - Parsed command line the build was started with, empty when the caller passes none\n *\n * @remarks\n * The configuration is patched rather than put in place of what is there,\n * so the built-in defaults survive underneath what a configuration file states.\n * The subscription that follows is called at once with the merged configuration,\n * which is what constructs the variants before the constructor returns,\n * and it keeps them current with every later change.\n *\n * @example\n * ```ts\n * const build = new BuildService({ logLevel: 'warning', variants: { esm } }, { watch: true });\n * ```\n *\n * @see ConfigurationService.patch\n * @since 3.0.0\n */\n\n constructor(config: ConfigurationInterface, private argv: Record<string, unknown> = {}) {\n this.config$.patch(config);\n this.config$.subscribe(this.parseVariants.bind(this));\n }\n\n /**\n * The event stream's `pipe`, bound to the stream.\n *\n * @remarks\n * Hands out the operator chain without handing out the subject,\n * so a reader composes on the run's events and cannot report one of its own.\n *\n * @example\n * ```ts\n * const ended = build.pipe(filter(event => event.type === 'end'));\n * ended.subscribe(report);\n * ```\n *\n * @see BuildService.subscribe\n * @since 3.0.0\n */\n\n get pipe(): typeof this.events$.pipe {\n return this.events$.pipe.bind(this.events$);\n }\n\n /**\n * The event stream's `subscribe`, bound to the stream.\n *\n * @remarks\n * The plain way to watch a run, for a reader wanting every event rather than a filtered view.\n * Answers with the handle that ends the subscription, as the stream's own `subscribe` does.\n *\n * @example\n * ```ts\n * const unsubscribe = build.subscribe(event => event.type); // 'start', then 'end'\n * unsubscribe();\n * ```\n *\n * @see BuildService.pipe\n * @since 3.0.0\n */\n\n get subscribe(): typeof this.events$.subscribe {\n return this.events$.subscribe.bind(this.events$);\n }\n\n /**\n * Starts the configuration again from the one this service was constructed with.\n *\n * @param config - Configuration to apply over the initial one\n *\n * @remarks\n * Reloads rather than patches, so whatever accumulated since construction is dropped,\n * and only the initial configuration survives underneath.\n * That is what re-reading an edited file wants, since patching a list would extend it rather than replace it.\n * Assigning is also what ends a variant,\n * since one the new configuration no longer declares disposes of itself as the change reaches it.\n *\n * @example\n * ```ts\n * build.configuration = { common: { esbuild: { minify: false } } };\n * ```\n *\n * @see ConfigurationService.reload\n * @since 3.0.0\n */\n\n set configuration(config: DeepPartialType<ConfigurationInterface>) {\n this.config$.reload(config);\n }\n\n /**\n * Builds the variants named, or every variant the configuration declares, in the order `dependOn` asks for.\n *\n * @param names - Variants to build, building every variant the configuration declares when omitted\n * @returns One result per variant asked for, in the order they were named\n * @throws xBuildError - When a `dependOn` chain closes on itself, or names a variant that does not exist\n *\n * @remarks\n * Naming variants builds those and whatever they wait for, leaving everything else alone.\n * A name no variant answers to is passed over rather than reported as an error,\n * so a list naming nothing this configuration declares builds nothing at all.\n * A dependency built along the way reports on the event stream like any other build\n * while staying out of the results, which carry the variants that were asked for.\n * The whole graph is wired before any variant runs, and every variant waits on the same gate,\n * so a chain that turns out to be broken builds nothing at all rather than part of the output.\n * A variant that several others depend on is built once and its result shared,\n * since the graph is walked through a cache keyed by name.\n * A build that fails does not reject here - its errors arrive on its own result.\n * A dependency counts as failed where it produced no output, whether it threw or only reported errors.\n * The variant waiting on it is skipped rather than built,\n * and the result {@link skipped} shapes carries no output either, so its own dependents skip in turn.\n *\n * @example\n * ```ts\n * const results = await build.build();\n * results.length; // 2 - the types variant first, then the bundle that depends on it\n *\n * const [ app ] = await build.build([ 'app' ]); // types builds too, since app waits for it\n * await build.build([ 'umd' ]); // [] - no variant answers to the name\n * ```\n *\n * @see BuildResultInterface\n * @since 3.0.0\n */\n\n async build(names?: Array<string>): Promise<Array<BuildResultInterface>> {\n const variants = new Map(Array.from(VariantService.get(), variant => [ variant.name, variant ] as const));\n const cache = new Map<string, Promise<BuildResultInterface>>();\n const start = Promise.withResolvers<void>();\n\n const run = (name: string, path: Array<string> = []): Promise<BuildResultInterface> => {\n if (path.includes(name))\n throw new xBuildError(`Circular dependency detected: ${ [ ...path, name ].join(' → ') }`);\n if (!variants.has(name))\n throw new xBuildError(`Variant \"${ path.at(-1) }\" depends on \"${ name }\", which is not a variant`);\n\n if (!cache.has(name)) {\n const dependOn = this.getDependOn(name);\n\n cache.set(name, Promise\n .all([ start.promise, ...dependOn.map(dependency => run(dependency, [ ...path, name ])) ])\n .then(([ , ...results ]) => {\n const failed = dependOn.filter((_, index) => Object.keys(results[index]?.metafile?.outputs ?? {}).length < 1);\n if (failed.length) return this.skipped(name, failed);\n\n return variants.get(name)!.build();\n })\n );\n }\n\n return cache.get(name)!;\n };\n\n const results = Array.from(names?.filter(name => variants.has(name)) ?? variants.keys(), name => run(name));\n start.resolve();\n\n return Promise.all(results);\n }\n\n /**\n * Type-checks the variants named, or every variant the configuration declares, without building any of them.\n *\n * @param names - Variants to check, checking every variant the configuration declares when omitted\n * @returns The messages each variant's check reported, keyed by the variant's name\n *\n * @remarks\n * The variants are checked one at a time rather than together,\n * since every variant carries a TypeScript program of its own.\n * Each variant answers with the buckets a build would file its messages under,\n * so a diagnostic reads at the level the configuration gives it rather than in the compiler's own shape.\n * A variant that checks clean is present with its buckets empty rather than left out,\n * so a reader tells a clean variant from one that was never checked.\n * Only the variants named are checked, dependencies among them or not,\n * since a variant is checked against the files its own build reaches,\n * and what another variant reaches is that variant's own to report.\n * A name is matched against the variants rather than looked up,\n * so one no variant answers to is passed over,\n * and a list naming nothing this configuration declares checks nothing at all.\n *\n * @example\n * ```ts\n * const { esm } = await build.typeChack();\n * esm.error.length; // 0 - nothing to report\n *\n * await build.typeChack([ 'esm' ]); // { esm: { ... } } - cjs is left alone\n * await build.typeChack([ 'umd' ]); // {} - no variant answers to the name\n * ```\n *\n * @see LifecycleLogsType\n * @since 3.0.0\n */\n\n async typeChack(names?: Array<string>): Promise<Record<string, LifecycleLogsType>> {\n const result: Record<string, LifecycleLogsType> = {};\n\n for (const variant of VariantService.get()) {\n if (!names || names.includes(variant.name)) result[variant.name] = await variant.check();\n }\n\n return result;\n }\n\n /**\n * Re-reads the TypeScript configuration from disk.\n *\n * @remarks\n * Reparses the configuration so a later check or build reads it as it now stands,\n * which is what a watch cycle needs after an edit to `tsconfig.json`.\n * The list of files reparsed is dropped rather than passed on, so a caller learns only that the reparse ran.\n * Nothing here waits on anything, so the promise settles at once.\n *\n * @example\n * ```ts\n * await build.reload(); // the TypeScript configuration is read again\n * ```\n *\n * @see TypescriptService.reload\n * @since 3.0.0\n */\n\n async reload(): Promise<void> {\n TypescriptService.reload();\n }\n\n /**\n * Constructs a variant for every entry the configuration declares.\n *\n * @param config - Configuration as it now stands\n * @throws xBuildError - When there is no configuration to read variants from\n *\n * @remarks\n * A name that already has a variant is passed over,\n * so re-reading a configuration adds what it gained\n * and leaves the variants it kept running rather than replacing them.\n * Nothing is removed here,\n * since a variant the configuration stopped declaring watches its own entry and disposes of itself.\n *\n * @see VariantService\n * @since 3.0.0\n */\n\n private parseVariants(config: ConfigurationInterface): void {\n if (!config)\n throw new xBuildError('Variants are not defined in the configuration');\n\n for (const name of Object.keys(config.variants ?? [])) {\n if (VariantService.has(name)) continue;\n new VariantService(name, this.events$, this.argv);\n }\n }\n\n /**\n * Shapes the result of a variant that was skipped rather than run and reports it as an end.\n *\n * @param name - Variant that was not built\n * @param dependencies - Names of the dependencies that failed, in the order the variant declared them\n * @returns A result carrying one error naming them, and nothing at any other level\n *\n * @remarks\n * Shaped as a build result rather than as a thrown error,\n * so a skipped variant reads like a failed one to whatever reports the run.\n * It carries no metafile, which is what makes its own dependents skip in turn,\n * since a dependency that produced no output is what the graph reads as a failure.\n * Nothing was compiled, so every bucket but `errors` comes back empty.\n * The result is built from the buckets the context carries rather than from a second literal,\n * so a level cannot be named in one and missing from the other,\n * and a reader of the event and a reader of the result are looking at the same messages.\n * The same result goes out on the event stream as an end,\n * since a variant that never ran reports no end of its own.\n * A reader would otherwise see the run finish, with one variant missing from the count.\n * The context is assembled here rather than taken from a build,\n * so its options are the ones the configuration states, and its duration is zero.\n *\n * @example\n * ```ts\n * const { errors } = this.skipped('app', [ 'types' ]);\n * errors[0].text; // 'Variant \"app\" was not built, because \"types\" failed'\n * ```\n *\n * @see BuildResultInterface\n * @since 3.0.0\n */\n\n private skipped(name: string, dependencies: Array<string>): BuildResultInterface {\n const failed = dependencies.map(dependency => `\"${ dependency }\"`).join(', ');\n const errors: Array<Message> = [\n {\n id: 'dependency-failed',\n text: `Variant \"${ name }\" was not built, because ${ failed } failed`,\n notes: [],\n detail: undefined,\n location: null,\n pluginName: name\n }\n ];\n\n const variant = this.config$.getValue().variants?.[name];\n const logs: LifecycleLogsType = { info: [], verbose: [], error: errors, warning: [] };\n const buildResult = <BuildResultInterface> <unknown> {\n info: logs.info, verbose: logs.verbose, errors: logs.error, warnings: logs.warning\n };\n\n this.events$.next({\n type: 'end',\n duration: 0,\n context: {\n argv: this.argv,\n logs,\n options: variant?.esbuild ?? {},\n overrides: variant?.logOverride ?? {},\n variantName: name,\n stage: {\n startTime: new Date(),\n dropped: new Set<string>(),\n reachableFiles: new Set<string>()\n }\n },\n buildResult\n });\n\n return buildResult;\n }\n\n /**\n * Returns the variants one variant waits for.\n *\n * @param name - Variant whose dependencies are wanted\n * @returns The names it depends on, empty when it depends on none\n *\n * @remarks\n * Read from the configuration as it stands rather than from a copy taken when the run began.\n * A single name is flattened into a list, so both forms `dependOn` accepts read the same way here.\n *\n * @see VariantConfigurationInterface\n * @since 3.0.0\n */\n\n private getDependOn(name: string): Array<string> {\n return [ this.config$.getValue().variants?.[name]?.dependOn ?? [] ].flat();\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { StackTraceInterface } from '@providers/interfaces/stack-provider.interface';\n\n/**\n * Imports\n */\n\nimport { xBuildBaseError } from '@errors/base.error';\n\n/**\n * A general framework error, resolved against its sources as it is constructed.\n *\n * @remarks\n * Throw this when the failure needs no error type of its own.\n * Extend {@link xBuildBaseError} instead when callers have to branch on the type,\n * or when the error has to carry extra fields.\n * Framework frames stay eligible for the code window by default, since a failure raised here is usually raised\n * inside the build itself and the snippet would otherwise be dropped.\n *\n * @example\n * ```ts\n * throw new xBuildError('tsconfig.json was not found');\n * // xBuildBaseError: tsconfig.json was not found\n * //\n * // Enhanced Stack Trace:\n * // at run src/bash.ts:41:11\n * ```\n *\n * @see xBuildBaseError\n * @see StackTraceInterface\n *\n * @since 1.0.0\n */\n\nexport class xBuildError extends xBuildBaseError {\n\n /**\n * Creates the error and resolves its stack right away.\n *\n * @param message - Message describing what went wrong\n * @param options - Frame selection and code window size, keeping framework frames by default\n *\n * @remarks\n * Resolution happens here rather than on first print, so the frames describe the throw site even when the error\n * travels before anything renders it.\n *\n * @example\n * ```ts\n * new xBuildError('entry point missing').metadata?.formatCode; // the highlighted throw site\n * new xBuildError('entry point missing', { linesBefore: 1, linesAfter: 1 }); // a tighter code window\n * ```\n *\n * @see StackTraceInterface\n * @see xBuildBaseError.reformatStack\n *\n * @since 1.0.0\n */\n\n constructor(message: string, options: StackTraceInterface = { withFrameworkFrames: true }) {\n super(message);\n this.reformatStack(this, options);\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { PartialMessage, Loader } from 'esbuild';\nimport type { OnResolveArgs, OnResolveResult } from 'esbuild';\nimport type { OnStartResult, OnLoadArgs, OnLoadResult } from 'esbuild';\nimport type { DiagnosticInterface } from '@typescript/typescript.module';\nimport type { Subject, UnsubscribeType } from '@remotex-labs/xobservable';\nimport type { BuildOptions, Plugin, PluginBuild, BuildResult } from 'esbuild';\nimport type { LifecycleContextInterface } from '@interfaces/lifecycle.interface';\nimport type { LogLevelType } from '@providers/interfaces/log-provider.interface';\nimport type { VariantConfigurationInterface } from '@interfaces/configuration.interface';\nimport type { BuildResultType } from '@services/interfaces/transpiler-service.interface';\nimport type { CallType, HandleType } from '@services/interfaces/variant-service.interface';\nimport type { LifecycleEventsType, BuildResultInterface } from '@interfaces/lifecycle.interface';\nimport type { LifecyclePluginInterface, LifecycleLogsType } from '@interfaces/lifecycle.interface';\nimport type { VariantSubscriptionInterface } from '@services/interfaces/variant-service.interface';\n\n/**\n * Imports\n */\n\nimport { parseSync } from 'oxc-parser';\nimport { relative } from '@remotex-labs/xmap';\nimport { inject } from '@remotex-labs/xinject';\nimport { FilesModel } from '@models/files.model';\nimport { xBuildError } from '@errors/xbuild.error';\nimport { collectLogs } from '@providers/log.provider';\nimport { Typescript } from '@typescript/typescript.module';\nimport { analyzeMacros } from '@directives/analyze.directive';\nimport { transformMacros } from '@directives/macros.directive';\nimport { resolveSource } from '@components/transformer.component';\nimport { deepMerge, stringify } from '@components/object.component';\nimport { ConfigurationService } from '@services/configuration.service';\nimport { extractEntryPoints } from '@components/entry-points.component';\nimport { TextBlocks, DiagnosticLevels } from '@constants/variant.constant';\nimport { errorToMessage, isEsbuildError } from '@providers/message.provider';\nimport { buildFiles, analyzeDependencies } from '@services/transpiler.service';\n\n/**\n * Runs one named variant of a build, from the configuration it watches to the result it reports.\n *\n * @remarks\n * One instance per entry in `variants`, kept in a static registry under that name and reused by every build,\n * so a watch cycle rebuilds through the same variant rather than replacing it each time.\n * The instance follows the configuration it was named in:\n * it re-reads its settings whenever they change and disposes of itself once the configuration drops its entry.\n * A build runs as a single esbuild plugin, which is what gives the configured hooks their place in the run.\n *\n * @example\n * ```ts\n * const variant = new VariantService('esm', events$, { watch: true });\n * const result = await variant.build();\n *\n * result.errors.length; // 0\n * variant.dispose();\n * ```\n *\n * @see LifecyclePluginInterface\n * @see VariantConfigurationInterface\n *\n * @since 3.0.0\n */\n\nexport class VariantService {\n /**\n * The file model every variant reads its sources through.\n *\n * @remarks\n * Held on the class rather than the instance, so one cache of snapshots serves every variant,\n * which is what keeps two variants of the same project from reading the same file twice.\n *\n * @since 3.0.0\n */\n\n private static readonly filesModel: FilesModel = inject(FilesModel);\n\n /**\n * The live variants, keyed by the name each was constructed under.\n *\n * @remarks\n * What {@link VariantService.has} and {@link VariantService.get} read,\n * and what {@link VariantService.dispose} removes an entry from,\n * so a name a disposed variant held is free for a later configuration to claim.\n *\n * @since 3.0.0\n */\n\n private static readonly instances = new Map<string, VariantService>();\n\n /**\n * The handle that ends this variant's configuration subscription.\n *\n * @remarks\n * Called as the variant is disposed,\n * so one the configuration has dropped stops reacting to a configuration it no longer belongs to.\n *\n * @since 3.0.0\n */\n\n private readonly configUnsubscribe: UnsubscribeType;\n\n /**\n * The hook sets these variant dispatches to, in the order they run.\n *\n * @remarks\n * Rebuilt on every configuration change as the declared plugins followed by the variant's own `lifecycle` set,\n * so a shared plugin runs ahead of the hooks a variant adds for itself.\n * The `lifecycle` set is given the variant's name, which is what lets its messages be credited as a plugin's.\n *\n * @since 3.0.0\n */\n\n private hooks: Array<LifecyclePluginInterface> = [];\n\n /**\n * Whether this variant has been torn down.\n *\n * @remarks\n * Guards {@link VariantService.build},\n * so a variant the configuration dropped reports rather than building against settings that are gone.\n *\n * @since 3.0.0\n */\n\n private isDisposed = false;\n\n /**\n * The TypeScript module this variant checks and emits through.\n *\n * @remarks\n * Replaced whenever the configuration changes, since a different `tsconfig` needs a program of its own,\n * and the one it replaces is disposed of only after the swap.\n * Populated by the subscription the constructor opens rather than by the constructor itself.\n *\n * @since 3.0.0\n */\n\n private typescriptModule!: Typescript;\n\n /**\n * The merged settings this variant builds under.\n *\n * @remarks\n * The common block with the variant merged over it, so a read here needs no further merging.\n * Populated by the subscription the constructor opens rather than by the constructor itself.\n *\n * @see VariantConfigurationInterface\n * @since 3.0.0\n */\n\n private buildConfig!: VariantConfigurationInterface;\n\n /**\n * Registers a variant under its name and starts following the configuration.\n *\n * @param name - Name the configuration declares this variant under, readable afterward\n * @param events$ - Subject the variant reports its start and end on\n * @param argv - Parsed command line the build was started with, empty when the caller passes none\n *\n * @remarks\n * The variant is usable as soon as it is constructed, since the subscription it opens delivers the settings\n * before the constructor returns.\n * An error in the subscription reports is rethrown rather than collected\n * because a variant that cannot read its configuration has nothing to build.\n *\n * @example\n * ```ts\n * const variant = new VariantService('esm', events$, { watch: true });\n * variant.name; // 'esm'\n * ```\n *\n * @since 3.0.0\n */\n\n constructor(readonly name: string, private events$: Subject<LifecycleEventsType>, private argv: Record<string, unknown> = {}) {\n VariantService.instances.set(name, this);\n this.configUnsubscribe = inject(ConfigurationService).select(config => ({\n common: config.common,\n variant: config.variants?.[this.name]\n })).subscribe(this.handleConfigChange.bind(this), error => {\n throw error;\n });\n }\n\n /**\n * Reports whether a variant is already registered under a name.\n *\n * @param name - Name to look for\n * @returns `true` when a live variant holds that name\n *\n * @remarks\n * What keeps a second variant from being constructed for a name that already has one,\n * so re-reading a configuration adds the entries it gained without disturbing the ones it kept.\n *\n * @example\n * ```ts\n * VariantService.has('esm'); // true\n * VariantService.has('umd'); // false - never constructed, or disposed since\n * ```\n *\n * @since 3.0.0\n */\n\n static has(name: string): boolean {\n return VariantService.instances.has(name);\n }\n\n /**\n * Returns every variant currently registered.\n *\n * @returns An iterator over the live variants, in the order they were constructed\n *\n * @remarks\n * Walks the registry itself rather than a copy of it,\n * so a variant that disposes of itself part way through a walk is not visited afterward.\n *\n * @example\n * ```ts\n * for (const variant of VariantService.get()) variant.name; // 'esm', then 'cjs'\n * ```\n *\n * @since 3.0.0\n */\n\n static get(): MapIterator<VariantService> {\n return VariantService.instances.values();\n }\n\n /**\n * Type-checks the variant's sources without building them.\n *\n * @returns The diagnostics as build messages, filed under the level each was reported at\n *\n * @remarks\n * A dependency scan of the variant's entry points settles which files the check covers,\n * so it reports against what this variant builds rather than against every file the project holds.\n * The scan runs with the plugins stripped, which keeps it out of the variant's own hooks.\n * The diagnostics come back as messages rather than in the compiler's own shape,\n * so the override table a build reads decides the level each one is filed under.\n * An error stays an error whatever `types.failOnError` says, since nothing is being emitted for it to stop.\n * Nothing is built here, so the messages belong to no result and a run wanting them on one build instead.\n *\n * @example\n * ```ts\n * const logs = await variant.check();\n * logs.error.length; // 2\n * logs.warning.length; // 0\n * ```\n *\n * @see LifecycleLogsType\n * @since 3.0.0\n */\n\n async check(): Promise<LifecycleLogsType> {\n const { metafile } = await analyzeDependencies({ ...this.buildConfig.esbuild, plugins: undefined });\n\n const logs: LifecycleLogsType = { info: [], verbose: [], error: [], warning: [] };\n this.diagnostics(this.typescriptModule.check(new Set(Object.keys(metafile.inputs))), logs);\n\n return logs;\n }\n\n /**\n * Runs one build of this variant.\n *\n * @returns The finished build, carrying every message the run reported at every level\n * @throws xBuildError - When the variant has already been disposed\n *\n * @remarks\n * The context is raised here rather than inside the plugin, so it outlives a run the plugin never filled in.\n * Its `options` block stands empty until the plugin writes the ones esbuild resolved onto it.\n * esbuild runs at `silent` with no log limit, so every message reaches the result through the plugin\n * instead of the console, and nothing is dropped for being the hundredth of its kind.\n * A build that fails resolves to an empty esbuild result rather than rejecting,\n * since what went wrong is already in the logs the plugin collected.\n * A rejection the start stage never saw is announced here instead:\n * esbuild validates the options only once every plugin is set up,\n * so an option it turns away leaves the run with no stage left to report its end.\n *\n * @example\n * ```ts\n * const result = await variant.build();\n * result.errors.length; // 0\n * result.warnings.length; // 2\n * ```\n *\n * @see BuildResultInterface\n * @see LifecycleContextInterface\n *\n * @since 3.0.0\n */\n\n async build(): Promise<BuildResultInterface> {\n if (this.isDisposed) throw new xBuildError(`Variant ${ this.name } is disposed`);\n\n const context: LifecycleContextInterface = {\n argv: this.argv,\n options: {},\n overrides: this.buildConfig.logOverride!,\n variantName: this.name,\n logs: {\n info: [],\n error: [],\n verbose: [],\n warning: []\n },\n stage: {\n startTime: new Date(),\n dropped: new Set<string>(),\n reachableFiles: new Set<string>()\n }\n };\n\n const result = await buildFiles({\n ...this.buildConfig.esbuild,\n plugins: [ this.lifecycle(context) ],\n logLimit: 0,\n logLevel: 'silent'\n }).catch(() => {\n if(!context.stage.start) {\n this.events$.next({\n context,\n type: 'end',\n duration: Date.now() - context.stage.startTime.getTime(),\n buildResult: this.toResult({\n errors: [],\n warnings: [],\n metafile: undefined,\n outputFiles: undefined,\n mangleCache: undefined\n }, context.logs)\n });\n }\n\n return <BuildResult> {};\n });\n\n return this.toResult(result, context.logs);\n }\n\n /**\n * Tears the variant down and frees its name.\n *\n * @remarks\n * Ends the configuration subscription, disposes the TypeScript module, and drops the variant from the registry,\n * so the name is free for a later configuration to claim.\n * The instance stays marked as disposed, which is what makes a later build report rather than run.\n *\n * @example\n * ```ts\n * variant.dispose();\n * VariantService.has('esm'); // false\n * await variant.build(); // throws - the variant is disposed\n * ```\n *\n * @since 3.0.0\n */\n\n dispose(): void {\n this.isDisposed = true;\n this.configUnsubscribe?.();\n this.typescriptModule?.dispose?.();\n VariantService.instances.delete(this.name);\n }\n\n /**\n * Disposes the variant at the end of a `using` block.\n *\n * @remarks\n * Defers to {@link VariantService.dispose}, so a variant held by a `using` declaration is torn down\n * when the block ends rather than waiting for a caller to remember.\n *\n * @example\n * ```ts\n * using variant = new VariantService('esm', events$);\n * await variant.build(); // disposed as the block ends\n * ```\n *\n * @see VariantService.dispose\n * @since 3.0.0\n */\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n /**\n * Files a batch of messages under a level, credited to a plugin.\n *\n * @param logs - Buckets the messages are appended to\n * @param messages - Messages to file, absent where the stage produced none\n * @param level - Level a message takes when no override claims it\n * @param name - Plugin to credit the messages to, left as reported when omitted\n *\n * @remarks\n * An absent or empty batch is skipped, so nothing walks a list with nothing in it.\n * The variant's own override table is what decides each message's level,\n * which is how a configuration re-levels or silences one without the stage knowing.\n *\n * @since 3.0.0\n */\n\n private collect(logs: LifecycleLogsType, messages: Array<PartialMessage> | undefined, level: LogLevelType, name?: string): void {\n if (messages?.length) collectLogs(logs, this.buildConfig.logOverride!, messages, level, name);\n }\n\n /**\n * Records a thrown value as an error on the build.\n *\n * @param logs - Buckets the error is appended to\n * @param error - Value that was thrown, of any shape\n * @param name - Plugin to credit the error to, the variant itself by default\n *\n * @remarks\n * A value that is not an `Error` is wrapped in one first, so the message carries a text either way.\n * The error goes straight to the bucket rather than through the override table,\n * since a failure a stage could not handle is not something a configuration silences.\n *\n * @since 3.0.0\n */\n\n private fail(logs: LifecycleLogsType, error: unknown, name: string = this.name): void {\n logs.error.push(errorToMessage(error instanceof Error ? error : new Error(String(error)), '', name));\n }\n\n /**\n * Widens an esbuild result with the levels esbuild does not report on one.\n *\n * @param result - Result esbuild returned, empty when the build threw\n * @param logs - Messages the run collected, at every level\n * @returns The same result, carrying the quieter levels beside the two esbuild reports\n *\n * @remarks\n * Assigns onto the result rather than copying it, so the returned object is the one esbuild produced.\n * The error and warning buckets replace esbuild's own instead of joining them,\n * because the logs already hold those messages along with whatever the hooks added.\n *\n * @see BuildResultInterface\n * @since 3.0.0\n */\n\n private toResult(result: BuildResult, logs: LifecycleLogsType): BuildResultInterface {\n return Object.assign(<BuildResultType> result, {\n info: logs.info,\n errors: logs.error,\n verbose: logs.verbose,\n warnings: logs.warning\n }) as BuildResultInterface;\n }\n\n /**\n * Runs one call against every hook in order and collects what each reports.\n *\n * @typeParam T - Result the call produces for a hook that answers\n *\n * @param logs - Buckets each hook's messages are filed under\n * @param call - Invocation to run against a hook, returning its result or nothing\n * @param handle - Decides whether a result ends the walk, never ending it by default\n * @returns The result that ended the walk, or `undefined` when no result ended it\n *\n * @remarks\n * Each hook's errors and warnings are filed under that hook's own name,\n * so a message reads as the plugin that raised it rather than as the variant.\n * A hook that throws is recorded against its name, and the walk carries on,\n * which keeps one broken plugin from taking the rest of the stage with it.\n * A hook returning nothing is passed over without its result being inspected.\n *\n * @see LifecyclePluginInterface\n * @since 3.0.0\n */\n\n private async dispatch<T>(logs: LifecycleLogsType, call: CallType, handle: HandleType<T> = () => false): Promise<T | undefined> {\n for (const hook of this.hooks) {\n try {\n const result = <T & OnStartResult | undefined> await call(hook);\n if (!result) continue;\n\n this.collect(logs, result.errors, 'error', hook.name);\n this.collect(logs, result.warnings, 'warning', hook.name);\n if (handle(result)) return result;\n } catch (error) {\n this.fail(logs, error, hook.name);\n }\n }\n }\n\n /**\n * Emits the declaration files for this build.\n *\n * @param context - Context of the build being emitted for, read for its resolved options\n *\n * @remarks\n * Written to the directory `declaration` names, falling back to the build's own `outdir` when it names none.\n * A bundled build emits through `emitBundle` so each entry point becomes one declaration,\n * while an unbundled one emits file by file.\n *\n * @see DeclarationOptionsInterface\n * @since 3.0.0\n */\n\n private async declarations(context: LifecycleContextInterface): Promise<void> {\n const { declaration } = this.buildConfig;\n const entryPoints = <Record<string, string>> context.options.entryPoints;\n const outdir = (typeof declaration === 'object' ? declaration.outDir : undefined) ?? context.options.outdir;\n\n if (context.options.bundle) await this.typescriptModule.emitBundle(entryPoints, outdir);\n else await this.typescriptModule.emit(entryPoints, outdir);\n }\n\n /**\n * Re-reads the variant's settings whenever the configuration changes.\n *\n * @param change - The common block and this variant's entry, as the configuration now stands\n *\n * @remarks\n * A change carrying no entry for this variant means the configuration dropped it,\n * so the variant disposes of itself instead of rebuilding its settings.\n * The common block is merged under the variant, entry points are resolved,\n * and the TypeScript module is swapped before the one it replaces is disposed of,\n * so a failure part-way through does not leave the variant without a module.\n * The hook list is rebuilt with the declared plugins ahead of the variant's own `lifecycle` set.\n *\n * @see VariantSubscriptionInterface\n * @since 3.0.0\n */\n\n private handleConfigChange({ common, variant }: VariantSubscriptionInterface): void {\n if (!variant) return this.dispose();\n\n const previous = this.typescriptModule;\n const config = deepMerge(<VariantConfigurationInterface> {}, common ?? {}, variant);\n\n this.typescriptModule = inject(Typescript, config.esbuild.tsconfig);\n config.esbuild.entryPoints = extractEntryPoints(config.esbuild.entryPoints);\n config.logOverride ??= {};\n previous?.dispose();\n\n this.buildConfig = config;\n this.hooks = [ ...config.plugins ?? [], { name: this.name, ...config.lifecycle }];\n }\n\n /**\n * Writes one text block into the esbuild options.\n *\n * @param options - Options the block is written onto, modified in place\n * @param type - Block to write, one of `banner`, `footer`, or `define`\n *\n * @remarks\n * A value written as a function is called with the variant's name and the arguments the build was started with,\n * so an injected value can carry something the configuration file cannot know.\n * A value resolving to `null` or `undefined` is left out rather than written as text,\n * which is how a definition can decline to apply to a given variant.\n *\n * A `banner` and a `footer` hold code, so a string is written as it stands.\n * A `define` holds an expression instead and takes the quoted form {@link stringify} gives it,\n * since esbuild reads a bare `1.0.0` as an expression rather than as text.\n * A value of any other type goes through {@link stringify} whichever block it belongs to.\n *\n * @see stringify\n * @see TextBlocks\n *\n * @since 3.0.0\n */\n\n private injectTextBlock(options: BuildOptions, type: 'banner' | 'footer' | 'define'): void {\n const source = this.buildConfig[type];\n if (!source) return;\n\n const target = options[type] ??= {};\n for (const [ key, value ] of Object.entries(source)) {\n const content = typeof value === 'function' ? value(this.name, this.argv) : value;\n if (content === undefined || content === null) continue;\n target[key] = type !== 'define' && typeof content === 'string' ? content : stringify(content);\n }\n }\n\n /**\n * Files a batch of TypeScript diagnostics as messages.\n *\n * @param diagnostics - Diagnostics to file, as the TypeScript module reported them\n * @param logs - Buckets the messages are filed under\n * @param failOnError - Whether an error keeps its level, filed as a warning instead when `false`\n *\n * @remarks\n * Each diagnostic carries its code as `TS<code>`, so an override claims one by that id,\n * spelled the way the compiler itself spells it rather than in a shape of this package's own.\n * The code, category, and text also travel whole on the message's `detail`,\n * so a reporter reads the diagnostic itself rather than parsing it back out of the message text.\n * The level comes from the diagnostic's category, and a category the table does not reach is filed as `verbose`.\n * A build passes `types.failOnError` in, while a check leaves it alone,\n * since nothing is being emitted there for an error to stop.\n * Nothing here runs the check, so which files it covered is the caller's to decide.\n *\n * @see DiagnosticLevels\n * @see DiagnosticInterface\n * @see TypeCheckOptionsInterface\n *\n * @since 3.0.0\n */\n\n private diagnostics(diagnostics: Array<DiagnosticInterface>, logs: LifecycleLogsType, failOnError: boolean = true): void {\n for (const { category, code, message: text, file, line, column } of diagnostics) {\n const message: PartialMessage = { text };\n if (code !== undefined) message.id = `TS${ code }`;\n if (file) message.location = { file, line, column };\n\n const level = <LogLevelType> (DiagnosticLevels[category] ?? 'verbose');\n message.detail = { code, category, message: text };\n\n this.collect(logs, [ message ], level === 'error' && !failOnError ? 'warning' : level, 'typescript');\n }\n }\n\n /**\n * Runs the start stage of a build.\n *\n * @param context - Context shared by every hook of this build\n * @param esbuild - The esbuild module driving the build, handed to each start hook\n * @returns The errors collected so far, which is what fails the build when any were\n *\n * @remarks\n * The stage marks itself on `stage.start` ahead of everything else,\n * which is what tells {@link VariantService.build} that a rejection belongs to a build that began\n * rather than to options esbuild turned away before it did.\n * The start hooks run next, and the sources are type-checked only where nothing has failed yet,\n * since diagnostics against a build that already broke report noise rather than a cause.\n * The check covers the files the setup stage recorded on the stage,\n * so a build reports against its own inputs without scanning for them a second time.\n * `types.failOnError` decides whether a type error fails the build or is filed as a warning beside it.\n * The error bucket comes back rather than the hooks' own results,\n * so esbuild stops on anything the stage collected, whichever hook raised it.\n *\n * @see StartContextInterface\n * @since 3.0.0\n */\n\n private async start(context: LifecycleContextInterface, esbuild: PluginBuild['esbuild']): Promise<OnStartResult> {\n const { logs } = context;\n context.stage.start = true;\n\n await this.dispatch(logs, hook => hook.onStart?.({ context, esbuild }));\n if (this.buildConfig.types && logs.error.length < 1) {\n const types = this.buildConfig.types;\n const failOnError = typeof types === 'object' ? types.failOnError : true;\n this.diagnostics(this.typescriptModule.check(context.stage.reachableFiles), context.logs, failOnError);\n }\n\n return { errors: logs.error };\n }\n\n /**\n * Resolves one import through the hooks.\n *\n * @param context - Context shared by every hook of this build\n * @param args - The import being resolved, as esbuild described it\n * @returns The first result a hook returned, or the errors collected so far when none claimed the path\n *\n * @remarks\n * The first hook to return anything settles the path, and the rest are not consulted,\n * which is how esbuild itself behaves across plugins.\n * Where no hook claims the import, esbuild is left to resolve it.\n *\n * @see ResolveContextInterface\n * @since 3.0.0\n */\n\n private async resolve(context: LifecycleContextInterface, args: OnResolveArgs): Promise<OnResolveResult | undefined | null> {\n const result = await this.dispatch<OnResolveResult>(\n context.logs, hook => hook.onResolve?.({ context, args }), () => true\n );\n\n return result ?? { errors: context.logs.error };\n }\n\n /**\n * Loads one file and runs it through the hooks.\n *\n * @param context - Context shared by every hook of this build\n * @param args - The file esbuild is loading, as it described it\n * @returns The contents and loader the chain settled on, with the messages left to the variant's own logs\n *\n * @remarks\n * The file is read from the shared model, then rewritten so its imports resolve where the build is unbundled,\n * and its macros are transformed either way.\n * A failure in any of that is recorded, and the file still goes on to the hooks.\n * Each hook is handed what the one before it returned, so the list reads as a chain rather than a race,\n * and every hook is consulted rather than the first that answers.\n * The result carries no messages of its own, since the stage filed them under the variant's levels already.\n *\n * @see LoadContextInterface\n * @since 3.0.0\n */\n\n private async load(context: LifecycleContextInterface, args: OnLoadArgs): Promise<OnLoadResult | undefined | null> {\n const path = VariantService.filesModel.resolve(args.path);\n\n let loader: Loader = 'default';\n let contents = VariantService.filesModel.touch(path).snapshot?.text ?? '';\n\n try {\n const parsed = parseSync(path, contents, { sourceType: 'module' });\n contents = await transformMacros(parsed, path, contents, context);\n\n if (!context.options.bundle) {\n const parsed = parseSync(path, contents, { sourceType: 'module' });\n contents = resolveSource(parsed, path, contents, this.typescriptModule);\n }\n } catch (error) {\n this.fail(context.logs, error);\n }\n\n let merged: OnLoadResult = {};\n await this.dispatch<OnLoadResult>(context.logs,\n hook => hook.onLoad?.({ context, contents, loader, args }),\n result => {\n merged = { ...merged, ...result };\n loader = result.loader ?? loader;\n\n if (result.contents !== undefined)\n contents = typeof result.contents === 'string' ? result.contents : Buffer.from(result.contents).toString();\n\n return false;\n }\n );\n\n return { ...merged, contents, loader, errors: [], warnings: [] };\n }\n\n /**\n * Closes a build out and reports it.\n *\n * @param context - Context shared by every hook of this build\n * @param buildResult - The result esbuild produced for the run\n *\n * @remarks\n * Only the messages esbuild raised itself are collected here,\n * since one carrying a plugin name was already filed when its hook returned it.\n * Declarations are emitted only where nothing failed, so a broken build does not leave stale types behind.\n * `onSuccess` runs ahead of `onEnd` and only on a result with no errors,\n * after which the end event is reported whatever the outcome.\n *\n * @see EndContextInterface\n * @since 3.0.0\n */\n\n private async end(context: LifecycleContextInterface, buildResult: BuildResult): Promise<void> {\n this.collect(context.logs, buildResult.errors.filter(message => !message.pluginName), 'error');\n this.collect(context.logs, buildResult.warnings.filter(message => !message.pluginName), 'warning');\n\n const event = {\n context,\n duration: Date.now() - context.stage.startTime.getTime(),\n buildResult: this.toResult(buildResult, context.logs)\n };\n\n if (context.logs.error.length < 1) {\n try {\n if (this.buildConfig.declaration) await this.declarations(context);\n } catch (error) {\n errorToMessage(error as Error, '', this.name);\n }\n }\n\n await this.dispatch(context.logs, async hook => {\n if (event.buildResult.errors.length < 1) await hook.onSuccess?.(event);\n await hook.onEnd?.(event);\n });\n\n this.events$.next({ ...event, type: 'end' });\n }\n\n /**\n * Prepares the build's options before esbuild reads them.\n *\n * @param context - Context shared by every hook of this build\n * @param build - The esbuild plugin build whose initial options are being shaped\n *\n * @remarks\n * Injects the text blocks, records the files the build reaches on the stage,\n * and replaces the entry points with the dependency map where the build is unbundled.\n * The macro scan reads that same set,\n * so the bindings the run is to drop come from every input the build reaches rather than from the entry points.\n * A failure anywhere in that is recorded against the variant rather than thrown,\n * so a scan that cannot run reports itself and leaves the build to fail on the errors it filed.\n * The setup hooks run last, so a plugin changing an option overrides what this stage settled.\n *\n * @see analyzeMacros\n * @since 3.0.0\n */\n\n private async setup(context: LifecycleContextInterface, build: PluginBuild): Promise<void> {\n const options = build.initialOptions;\n\n try {\n for (const block of TextBlocks) this.injectTextBlock(options, block);\n\n const files = await this.buildDependencyMap();\n context.stage.reachableFiles = new Set(Object.values(files));\n if (!options.bundle) options.entryPoints = files;\n context.stage.dropped = analyzeMacros(context.stage.reachableFiles, options.define ?? {});\n } catch (error) {\n if(isEsbuildError(error) && error.errors) {\n context.logs.error.push(...error.errors);\n } else {\n this.fail(context.logs, error, '');\n }\n }\n\n await this.dispatch(context.logs, hook => hook.onSetup?.(context));\n }\n\n /**\n * Maps every input the build reaches to the output name it takes.\n *\n * @returns The inputs, keyed by their path below the root directory with the extension dropped\n *\n * @remarks\n * The scan runs with the plugins stripped, so it does not re-enter this variant's own hooks\n * and cannot recurse into the build it is preparing.\n * Each path is made relative to the root directory and loses its extension,\n * which is what gives an unbundled build one output per input rather than one bundle.\n *\n * @since 3.0.0\n */\n\n private async buildDependencyMap(): Promise<Record<string, string>> {\n const rootDir = this.typescriptModule.config.options.rootDir!;\n const { metafile } = await analyzeDependencies({ ...this.buildConfig.esbuild, plugins: undefined });\n\n return Object.fromEntries(Object.keys(metafile.inputs).map(file => {\n const path = relative(rootDir, VariantService.filesModel.resolve(file));\n const dot = path.lastIndexOf('.');\n\n return [ dot > 0 ? path.slice(0, dot) : path, file ];\n }));\n }\n\n /**\n * Builds the esbuild plugin this variant runs as.\n *\n * @param context - Context shared by every hook of this build, which the plugin writes the resolved options onto\n * @returns The plugin, named after the variant\n *\n * @remarks\n * The context comes from the caller rather than being raised here and is handed to every stage,\n * which is what makes `stage` a place one hook leaves a value for a later one.\n * Its `options` are written as the plugin is set up, since esbuild settles them only by then,\n * and its two sets start empty for setup to fill before the first hook reads one.\n * The four esbuild callbacks are registered before setup runs,\n * so a hook changing an option during setup is still ahead of the first file being read.\n * The plugin carries the variant's name, so message esbuild attributes to it read as the variant.\n *\n * @see LifecycleContextInterface\n * @since 3.0.0\n */\n\n private lifecycle(context: LifecycleContextInterface): Plugin {\n return {\n name: this.name,\n setup: async (build: PluginBuild): Promise<void> => {\n context.options = build.initialOptions;\n build.onEnd(this.end.bind(this, context));\n build.onStart(this.start.bind(this, context, build.esbuild));\n build.onLoad({ filter: /.*/ }, this.load.bind(this, context));\n build.onResolve({ filter: /.*/ }, this.resolve.bind(this, context));\n await this.setup(context, build);\n\n this.events$.next({ context, esbuild: build.esbuild, type: 'start' });\n }\n };\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { Message, PartialMessage } from 'esbuild';\nimport type { LifecycleLogsType } from '@interfaces/lifecycle.interface';\nimport type { LogLevelType, LogOverridesType } from '@providers/interfaces/log-provider.interface';\n\n/**\n * Resolves the level a message is reported under.\n *\n * @param overrides - The configured levels, keyed by message id or by a pattern matching one\n * @param id - ID the message was reported with, absent on a message that carries none\n * @param level - Level the message takes when no override claims it\n * @returns The level the message is reported under\n *\n * @remarks\n * An id is looked up as a key first and read against the pattern keys only when that misses,\n * so a table naming its ids outright is answered without a match being run at all.\n * A pattern is anchored with `^(?:...)$` to make it match a whole id rather than a part of one,\n * which is what lets a set of ids be written as a single alternation, and the first the table declared wins.\n * A key whose syntax does not parse is passed over rather than thrown on.\n *\n * @example\n * ```ts\n * const overrides: LogOverridesType = { 'direct-eval': 'silent', 'TS-2\\\\d{3}': 'warning' };\n *\n * resolveLevel(overrides, 'direct-eval', 'warning'); // 'silent' - claimed by name\n * resolveLevel(overrides, 'TS-2304', 'error'); // 'warning' - claimed by pattern\n * resolveLevel(overrides, 'empty-glob', 'warning'); // 'warning' - claimed by neither\n * ```\n *\n * @see collectLog\n * @see LogOverridesType\n *\n * @since 3.0.0\n */\n\nexport function resolveLevel(overrides: LogOverridesType, id: string | undefined, level: LogLevelType): LogLevelType {\n if (id === undefined) return level;\n if (Object.hasOwn(overrides, id)) return overrides[id];\n\n for (const key in overrides) {\n try {\n if (new RegExp(`^(?:${ key })$`).test(id)) return overrides[key];\n } catch {\n if(id === key) return overrides[key];\n }\n }\n\n return level;\n}\n\n/**\n * Files a message under the level it resolves to.\n *\n * @param logs - Buckets the message is appended to, keyed by level\n * @param overrides - The configured levels, consulted for the message id\n * @param message - Message to file\n * @param level - Level the message takes when no override claims it\n *\n * @remarks\n * A message that resolves to `silent` is dropped rather than filed,\n * which is what keeps the log record free of a bucket for it.\n *\n * @example\n * ```ts\n * const logs = { debug: [], info: [], warning: [], error: [] };\n *\n * collectLog(logs, { 'direct-eval': 'silent' }, { id: 'direct-eval', text: 'Using eval' }, 'warning');\n * logs.warning; // [] - the override silenced it\n * ```\n *\n * @see collectLogs\n * @see resolveLevel\n *\n * @since 3.0.0\n */\n\nexport function collectLog(\n logs: LifecycleLogsType, overrides: LogOverridesType, message: PartialMessage, level: LogLevelType\n): void {\n const resolved = resolveLevel(overrides, message.id, level);\n if (resolved !== 'silent') logs[resolved].push(<Message> message);\n}\n\n/**\n * Files a batch of messages, each under the level it resolves to.\n *\n * @param logs - Buckets the messages are appended to, keyed by level\n * @param overrides - The configured levels, consulted for each message id\n * @param messages - Messages to file, in the order they were reported\n * @param level - Level a message takes when no override claims it\n * @param name - Plugin to credit each message to, left as reported when omitted or empty\n *\n * @remarks\n * Every message is resolved on its own, so one batch can end up spread across several buckets.\n * A name replaces whatever `pluginName` a message already carried,\n * so a batch coming out of one plugin reads as that plugin's even where esbuild credited another.\n * It writes onto the messages themselves rather than onto copies,\n * so a caller holding the same objects sees the credit as well.\n * The credit lands before the level resolves, so a message an override silences still carries it.\n *\n * @example\n * ```ts\n * const logs = { debug: [], info: [], warning: [], error: [] };\n *\n * collectLogs(logs, {}, [ { text: 'first' } ], 'error');\n * logs.error; // [ { text: 'first' } ] - left uncredited\n *\n * collectLogs(logs, {}, [ { text: 'second' } ], 'error', 'timing');\n * logs.error; // [ { text: 'first' }, { text: 'second', pluginName: 'timing' } ]\n * ```\n *\n * @see collectLog\n * @since 3.0.0\n */\n\nexport function collectLogs(\n logs: LifecycleLogsType, overrides: LogOverridesType, messages: Array<PartialMessage>, level: LogLevelType, name?: string\n): void {\n for (const message of messages) {\n if(name) message.pluginName = name;\n collectLog(logs, overrides, message, level);\n }\n}\n","/**\n * Imports\n */\n\nimport { parseSync } from 'oxc-parser';\nimport { inject } from '@remotex-labs/xinject';\nimport { FilesModel } from '@models/files.model';\nimport { isDefined } from '@directives/define.directive';\nimport { Macros, MacroScanHint } from '@constants/macros.constant';\n\n/**\n * Collects the names of the macro declarations a build is to drop.\n *\n * @param files - Paths to scan, relative or absolute\n * @param defines - The definition table the build substitutes, holding the source text each flag stands for\n * @returns The names bound to a conditional macro whose condition does not hold\n *\n * @remarks\n * Each file is read through {@link FilesModel}, so a path already tracked is served from the cache rather than\n * from the disk, and a path that is missing is skipped.\n * A file is parsed only once it contains {@link MacroScanHint}, which spares the parse where no conditional\n * macro can be.\n *\n * - **What is looked at** - an exported top-level binding alone, `export const NAME = $$ifdef('FLAG')` or its\n * `$$ifndef` counterpart. A macro nested in a block, or bound without an export, is not seen.\n * - **What counts as defined** - a definition holds source text rather than a value, so the text is what decides.\n * Anything in {@link MacroFalsyDefines} leaves the flag unset, as does a flag that the table does not name.\n * Every other text sets the flag, `'0'` and the empty string among them.\n * - **What ends up in the set** - an `$$ifdef` name whose flag is absent, and an `$$ifndef` name whose flag is\n * present. {@link Macros.inline} is not read here.\n *\n * @example\n * ```ts\n * // src/feature.ts\n * export const $$dev = $$ifdef('DEV');\n * export const $$release = $$ifndef('DEV');\n *\n * analyzeMacros([ 'src/feature.ts' ], { DEV: 'true' }); // Set { '$$release' }\n * analyzeMacros([ 'src/feature.ts' ], { DEV: 'false' }); // Set { '$$dev' }\n * ```\n *\n * @see Macros\n * @see isDefined\n * @see MacroScanHint\n *\n * @since 3.0.0\n */\n\nexport function analyzeMacros(files: Iterable<string>, defines: Record<string, string>): Set<string> {\n const dropped = new Set<string>();\n const filesModel = inject(FilesModel);\n\n for (const file of files) {\n const content = filesModel.touch(file).snapshot?.text;\n\n if (!content?.includes(MacroScanHint)) continue;\n const { program } = parseSync(file, content, { sourceType: 'module' });\n\n for (const node of program.body) {\n if (node.type !== 'ExportNamedDeclaration') continue;\n if (node.declaration?.type !== 'VariableDeclaration') continue;\n\n for (const declarator of node.declaration.declarations) {\n const call = declarator.init;\n if (call?.type !== 'CallExpression' || call.callee.type !== 'Identifier') continue;\n\n const directive = call.callee.name;\n if (directive !== Macros.ifdef && directive !== Macros.ifndef) continue;\n\n const arg = call.arguments[0];\n if (arg?.type !== 'Literal' || typeof arg.value !== 'string') continue;\n if (declarator.id.type !== 'Identifier') continue;\n\n if ((directive === Macros.ifdef) !== isDefined(defines, arg.value)) {\n dropped.add(declarator.id.name);\n }\n }\n }\n }\n\n return dropped;\n}\n","/**\n * The prefix every macro name is expected to open with.\n *\n * @remarks\n * Keeps a macro apart from an ordinary binding and doubles as the cheapest test that a source holds one at all,\n * since a file without it carries nothing to expand.\n * A declared macro named without it still expands and draws a `macro-prefix` warning.\n *\n * @example\n * ```ts\n * '$$ifdef'.startsWith(MacroPrefix); // true\n * ```\n *\n * @see Macros\n * @see MacroScanHint\n *\n * @since 3.0.0\n */\n\nexport const MacroPrefix = '$$';\n\n/**\n * The prefix the two conditional macros share.\n *\n * @remarks\n * What `$$ifdef` and `$$ifndef` both open with, so a source without it declares neither of them,\n * and the walk looking for one is skipped.\n * {@link Macros.inline} does not carry it and is reached through {@link MacroPrefix} instead.\n *\n * @example\n * ```ts\n * MacroScanHint; // '$$if'\n * 'const $$dev = $$ifdef(\"DEV\", 1);'.includes(MacroScanHint); // true\n * ```\n *\n * @see Macros\n * @see MacroPrefix\n *\n * @since 3.0.0\n */\n\nexport const MacroScanHint = `${ MacroPrefix }if`;\n\n/**\n * The three names that mark a call as a macro.\n *\n * @remarks\n * The callee of the call names the macro, and the shape of the call has to match the name:\n * the two conditional macros take a flag as a string literal and the value that flag guards,\n * while `inline` takes the value alone.\n * A call that matches neither shape is left as it stands rather than reported.\n *\n * @example\n * ```ts\n * export const $$dev = $$ifdef('DEV', () => console.log('dev')); // kept while DEV is set\n * export const $$prod = $$ifndef('DEV', () => 0); // kept while DEV is not set\n * export const $$stamp = $$inline(() => 2 + 2); // becomes 4 in the output\n * ```\n *\n * @see MacroPrefix\n * @see transformMacros\n *\n * @since 3.0.0\n */\n\nexport const enum Macros {\n /**\n * Keeps its value while the flag is set.\n *\n * @remarks\n * The flag is read from the definition table, and the declaration is dropped when the flag is not set,\n * along with every reference to the name that it bound.\n *\n * @example\n * ```ts\n * export const $$dev = $$ifdef('DEV', () => log()); // dropped while DEV is 'false'\n * ```\n *\n * @since 3.0.0\n */\n\n ifdef = `${ MacroPrefix }ifdef`,\n\n /**\n * Keeps its value while the flag is not set.\n *\n * @remarks\n * The counterpart of `ifdef`, reading the same definitions and dropped on the opposite answer,\n * which is what a fallback for an absent flag is written as.\n *\n * @example\n * ```ts\n * export const $$prod = $$ifndef('DEV', () => 0); // dropped while DEV is set\n * ```\n *\n * @since 3.0.0\n */\n\n ifndef = `${ MacroPrefix }ifndef`,\n\n /**\n * Replaces the call with what its value evaluates to.\n *\n * @remarks\n * Evaluated while the build runs, so the output carries the result rather than the call.\n * A failure is reported as a `macro-inline` error and leaves `undefined` behind.\n *\n * @example\n * ```ts\n * export const $$stamp = $$inline(() => 2 + 2); // export const $$stamp = 4;\n * ```\n *\n * @since 3.0.0\n */\n\n inline = `${ MacroPrefix }inline`\n}\n\n/**\n * The definition values that leave a flag unset.\n *\n * @remarks\n * A definition holds source text rather than a value, so `false` reaches the build as the string `'false'`.\n * These three leave the flag unset, and every other text sets it, `'0'` and the empty string among them.\n * A flag that the definition table does not name is not set either, which {@link isDefined} tests on its own.\n * The text is trimmed before the lookup.\n *\n * @example\n * ```ts\n * MacroFalsyDefines.has('false'); // true\n * MacroFalsyDefines.has('0'); // false - '0' sets the flag\n * ```\n *\n * @see Macros\n * @see isDefined\n *\n * @since 3.0.0\n */\n\nexport const MacroFalsyDefines = new Set([ 'false', 'null', 'undefined' ]);\n\n/**\n * The parent properties under which an identifier names something rather than reads it.\n *\n * @remarks\n * A dropped macro's identifier becomes `undefined` wherever it is read, and is left alone where it is only a name -\n * the `id` of a declaration, a label, an import or export binding, or a parameter.\n * An object key and a member property are decided by the parent's `computed` flag instead of by this set.\n *\n * @example\n * ```ts\n * MacroNameKeys.has('id'); // true - `const $$dev = ...` keeps the name it declares\n * MacroNameKeys.has('object'); // false - `$$dev.run()` has the reference replaced\n * ```\n *\n * @see transformMacros\n * @since 3.0.0\n */\n\nexport const MacroNameKeys = new Set([ 'id', 'label', 'local', 'params', 'exported', 'imported' ]);\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { MacroTargetInterface } from '@directives/interfaces/macros-directive.interface';\n\n/**\n * Imports\n */\n\nimport { MacroFalsyDefines } from '@constants/macros.constant';\n\n/**\n * Whether the definition table sets a flag.\n *\n * @param defines - The definition table the build substitutes, holding the source text each flag stands for\n * @param name - Name of the flag to test\n * @returns `true` when the table names the flag and holds something other than a falsy text for it\n *\n * @remarks\n * A definition holds source text rather than a value, so the text is what decides.\n * A flag that the table does not name is not set, and neither is one whose text is in {@link MacroFalsyDefines}.\n * The text is trimmed before the lookup, so padding around it does not change the answer.\n * Every other text sets the flag, `'0'` and the empty string among them.\n *\n * @example\n * ```ts\n * isDefined({ DEV: 'true' }, 'DEV'); // true\n * isDefined({ DEV: ' false ' }, 'DEV'); // false - trimmed before the lookup\n * isDefined({}, 'DEV'); // false - the table does not name it\n * ```\n *\n * @see MacroFalsyDefines\n * @since 3.0.0\n */\n\nexport function isDefined(defines: Record<string, string>, name: string): boolean {\n const value = defines[name];\n\n return value !== undefined && !MacroFalsyDefines.has(value.trim());\n}\n\n/**\n * Builds the replacement source for a declaration that a macro initializes.\n *\n * @param code - Source text the target's spans point into\n * @param name - Name the declaration binds\n * @param target - The macro call and whatever call text followed it\n * @param prefix - Text placed in front of the result, `'export '` for an exported declaration\n * @returns The source that replaces the whole declaration\n *\n * @remarks\n * The value the macro guards is its second argument, and the way that argument is written decides the form:\n *\n * - **A function the source already invokes** - parenthesized and left invoked, so the binding holds the result.\n * - **A function the source does not invoke** - rewritten as a function declaration under the same name, carrying\n * its parameters, its return type, and its `async` keyword. An expression body becomes a `return` statement, and\n * a function without a body becomes an empty one.\n * - **Anything else** - substituted as written, with the trailing call kept.\n *\n * @example\n * ```ts\n * // source: export const $$log = $$ifdef('DEV', (m: string) => console.log(m));\n * defineDeclaration(code, '$$log', target, 'export ');\n * // result: export function $$log(m: string) { return console.log(m); }\n *\n * // source: const $$now = $$ifdef('DEV', () => Date.now())();\n * defineDeclaration(code, '$$now', target, '');\n * // result: const $$now = (() => Date.now())();\n * ```\n *\n * @see defineExpression\n * @see MacroTargetInterface\n *\n * @since 3.0.0\n */\n\nexport function defineDeclaration(code: string, name: string, target: MacroTargetInterface, prefix: string): string {\n const { call, suffix } = target;\n const callback = call.arguments[1];\n const text = code.slice(callback.start, callback.end);\n\n if (callback.type !== 'ArrowFunctionExpression' && callback.type !== 'FunctionExpression')\n return `${ prefix }const ${ name } = ${ text }${ suffix };`;\n\n if (suffix) return `${ prefix }const ${ name } = (${ text })${ suffix };`;\n\n const { body } = callback;\n const params = callback.params.map(param => code.slice(param.start, param.end)).join(', ');\n const returns = callback.returnType ? code.slice(callback.returnType.start, callback.returnType.end) : '';\n const head = `${ prefix }${ callback.async ? 'async ' : '' }function ${ name }(${ params })${ returns }`;\n\n if (!body) return `${ head } {}`;\n if (body.type === 'BlockStatement') return `${ head } ${ code.slice(body.start, body.end) }`;\n\n return `${ head } { return ${ code.slice(body.start, body.end) }; }`;\n}\n\n/**\n * Builds the replacement source for a macro standing in an expression.\n *\n * @param code - Source text the target's spans point into\n * @param target - The macro call and whatever call text followed it\n * @param statement - Whether the macro stands as a statement of its own\n * @returns The source that replaces the macro call\n *\n * @remarks\n * The value the macro guards is its second argument, and the way that argument is written decides the form:\n *\n * - **A function inside an expression** - parenthesized and invoked, so the expression evaluates to what the\n * function returns. The call the source wrote is used where there is one, and `()` where there is not.\n * - **A function standing as a statement** - its body is inlined where the call stood, with no wrapper around it.\n * An expression body becomes that expression, and a function without a body leaves nothing behind.\n * - **Anything else** - substituted as written, with the trailing call kept.\n *\n * @example\n * ```ts\n * // source: $$ifdef('DEV', () => console.log('on'));\n * defineExpression(code, target, true);\n * // result: console.log('on');\n *\n * // source: const x = $$ifdef('DEV', () => 1);\n * defineExpression(code, target, false);\n * // result: (() => 1)()\n * ```\n *\n * @see defineDeclaration\n * @since 3.0.0\n */\n\nexport function defineExpression(code: string, target: MacroTargetInterface, statement: boolean): string {\n const { call, suffix } = target;\n const callback = call.arguments[1];\n const text = code.slice(callback.start, callback.end);\n const tail = statement ? ';' : '';\n\n if (callback.type !== 'ArrowFunctionExpression' && callback.type !== 'FunctionExpression')\n return `${ text }${ suffix }${ tail }`;\n\n if (suffix || !statement) return `(${ text })${ suffix || '()' }${ tail }`;\n\n const { body } = callback;\n if (!body) return '';\n if (body.type !== 'BlockStatement') return `${ code.slice(body.start, body.end) };`;\n\n return code.slice(body.start + 1, body.end - 1).trim();\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { PartialMessage } from 'esbuild';\nimport type { ParseResult } from 'oxc-parser';\nimport type { LifecycleContextInterface } from '@interfaces/lifecycle.interface';\nimport type { LogLevelType } from '@providers/interfaces/log-provider.interface';\nimport type { NodeVisitorType } from '@directives/interfaces/macros-directive.interface';\nimport type { ExportNamedDeclaration, ImportDeclaration, Node, Span } from '@oxc-project/types';\nimport type { SourceEditInterface } from '@components/interfaces/transformer-component.interface';\nimport type { DeclaredMacroType, MacroCallType } from '@directives/interfaces/macros-directive.interface';\nimport type { MacroStateInterface, MacroTargetInterface } from '@directives/interfaces/macros-directive.interface';\n\n/**\n * Imports\n */\n\nimport { visitorKeys } from 'oxc-parser';\nimport { collectLog } from '@providers/log.provider';\nimport { evaluate } from '@directives/inline.directive';\nimport { applyEdits } from '@components/transformer.component';\nimport { defineDeclaration, defineExpression, isDefined } from '@directives/define.directive';\nimport { MacroNameKeys, MacroPrefix, Macros, MacroScanHint } from '@constants/macros.constant';\n\n/**\n * Whether a value read out of a node is itself a node.\n *\n * @param value - Value read out of a parent node's property\n * @returns `true` when the value is an object carrying a string `type`\n *\n * @remarks\n * The test the walk applies before it steps into a property,\n * since a visitor key can hold a node, an array of them, or a plain value such as a name or a flag.\n *\n * @since 3.0.0\n */\n\nexport function isNode(value: unknown): value is Node {\n return typeof value === 'object' && value !== null && typeof (<Node> value).type === 'string';\n}\n\n/**\n * Visits a node and everything under it, depth-first.\n *\n * @param node - Node the walk starts from\n * @param visit - Called for each node, returning `true` to leave the subtree unvisited\n * @param parent - Node the current one hangs from, `null` at the root\n * @param key - Property of the parent the current node sits under, empty at the root\n *\n * @remarks\n * Child properties come from oxc's `visitorKeys`, so a node type that the table does not name is treated as a leaf.\n * A visitor returning `true` prunes the subtree,\n * so a rule further down never rewrites a node that an earlier one already replaced.\n *\n * @see NodeVisitorType\n * @since 3.0.0\n */\n\nexport function walk(node: Node, visit: NodeVisitorType, parent: Node | null = null, key = ''): void {\n if (visit(node, parent, key)) return;\n\n const keys: Array<string> | undefined = visitorKeys[node.type];\n\n for (const childKey of keys ?? []) {\n const value = (<Record<string, unknown>> <unknown> node)[childKey];\n\n if (Array.isArray(value)) {\n for (const item of value) if (isNode(item)) walk(item, visit, node, childKey);\n } else if (isNode(value)) walk(value, visit, node, childKey);\n }\n}\n\n/**\n * Files a message against a position in the file being transformed.\n *\n * @param state - Transform state, read for the source text and the file name\n * @param offset - Offset in the source the message points at\n * @param level - Level the message is filed under, before any override applies\n * @param message - Message to file, whose `location` this fills in\n *\n * @remarks\n * The line and the column are counted by scanning the source up to the offset,\n * since the parser reports spans rather than positions.\n * The message is filled in where it stands rather than copied, and it reaches the log through {@link collectLog},\n * so the overrides the build declared still decide the level it lands at.\n *\n * @see collectLog\n * @since 3.0.0\n */\n\nexport function report(state: MacroStateInterface, offset: number, level: LogLevelType, message: PartialMessage): void {\n const { code } = state;\n let line = 1;\n let start = 0;\n\n for (let index = code.indexOf('\\n'); index !== -1 && index < offset; index = code.indexOf('\\n', index + 1)) {\n line++;\n start = index + 1;\n }\n\n message.location = { file: state.target, line, column: offset - start };\n collectLog(state.logs, state.overrides, message, level);\n}\n\n/**\n * Queues an edit that replaces a span with text.\n *\n * @param state - Transform state the edit is collected on\n * @param span - Span of the source the edit replaces\n * @param text - Replacement text, empty to delete the span\n * @returns `true`, so a caller can hand it straight back to the walk\n *\n * @remarks\n * Returning `true` is what tells the walk that this node is dealt with and that it should not descend into it.\n * The edit is applied later along with the rest, so the offsets it carries stay valid for the whole walk.\n *\n * @see applyEdits\n * @since 3.0.0\n */\n\nexport function record(state: MacroStateInterface, span: Span, text: string): boolean {\n state.edits.push({ start: span.start, end: span.end, text });\n\n return true;\n}\n\n/**\n * Queues an edit whose text is known only once an inline call has run.\n *\n * @param state - Transform state the edit and the promise are collected on\n * @param span - Span of the source the edit replaces\n * @param call - The `$$inline` call to evaluate\n * @param wrap - Turns the value that comes back into the text that replaces the span\n * @returns `true`, so a caller can hand it straight back to the walk\n *\n * @remarks\n * The edit is queued empty and filled in when the call finishes, so the walk carries on while it runs.\n * The promise is collected on `state.pending` for the caller to await before the edits are applied.\n * A failure fills the edit with `wrap('undefined')` and reports a `macro-inline` error,\n * so a macro that cannot be evaluated still leaves the file parsable.\n *\n * @see evaluate\n * @since 3.0.0\n */\n\nexport function defer(state: MacroStateInterface, span: Span, call: MacroCallType, wrap: (value: string) => string): boolean {\n const edit: SourceEditInterface = { start: span.start, end: span.end, text: '' };\n\n state.edits.push(edit);\n state.pending.push(evaluate(state, call).then(value => {\n edit.text = wrap(value);\n }, (error: unknown) => {\n edit.text = wrap('undefined');\n report(state, call.start, 'error', {\n detail: error,\n id: 'macro-inline',\n text: `${ Macros.inline } failed: ${ (<Error> error)?.message ?? String(error) }`\n });\n }));\n\n return true;\n}\n\n/**\n * Whether a node is a macro call this transform handles.\n *\n * @param value - Node to test\n * @returns `true` when the callee names a macro and the arguments match that name\n *\n * @remarks\n * The callee has to be a plain identifier naming one of {@link Macros}, and the arguments have to match the name:\n * one for `inline`, and two for the conditional pair, the first of which is a string literal naming the flag.\n * Anything else is an ordinary call and is left alone.\n *\n * @see MacroCallType\n * @since 3.0.0\n */\n\nexport function isMacroCall(value: Node): value is MacroCallType {\n if (value.type !== 'CallExpression' || value.callee.type !== 'Identifier') return false;\n\n const { name } = value.callee;\n if (name === Macros.inline) return value.arguments.length === 1;\n if (name !== Macros.ifdef && name !== Macros.ifndef || value.arguments.length !== 2) return false;\n\n const flag = value.arguments[0];\n\n return flag.type === 'Literal' && typeof flag.value === 'string';\n}\n\n/**\n * Whether a conditional macro keeps its value.\n *\n * @param state - Transform state, read for the definition table\n * @param call - The `$$ifdef` or `$$ifndef` call to weigh\n * @returns `true` when the macro's condition holds\n *\n * @remarks\n * `$$ifdef` holds while its flag is set and `$$ifndef` while it is not, which {@link isDefined} answers.\n * A flag that is not a string literal is read as the empty name, which no table sets.\n *\n * @see isDefined\n * @since 3.0.0\n */\n\nexport function isActive(state: MacroStateInterface, call: MacroCallType): boolean {\n const flag = call.arguments[0];\n const name = flag.type === 'Literal' ? String(flag.value) : '';\n\n return (call.callee.name === Macros.ifdef) === isDefined(state.defines, name);\n}\n\n/**\n * Whether a node calls a macro that the build dropped.\n *\n * @param state - Transform state, read for the dropped names\n * @param node - Node to test\n * @returns `true` when the node calls an identifier that the build dropped\n *\n * @remarks\n * How a use of a disabled macro is recognized once its own declaration is gone,\n * which is what lets the transform replace the call rather than leave it to fail while the output runs.\n *\n * @since 3.0.0\n */\n\nexport function isDropped(state: MacroStateInterface, node: Node): boolean {\n return node.type === 'CallExpression' && node.callee.type === 'Identifier' && state.dropped.has(node.callee.name);\n}\n\n/**\n * The macro call a node holds, with whatever call followed it.\n *\n * @param state - Transform state, read for the source text\n * @param node - Node to look in, which may be absent\n * @returns The macro call and its trailing text, or `undefined` where the node holds none\n *\n * @remarks\n * Three shapes reach here.\n * A macro call on its own yields an empty suffix, a call whose callee is the macro yields the text of the outer\n * call as the suffix, and a TypeScript `as` expression is unwrapped and retried.\n *\n * @see MacroTargetInterface\n * @since 3.0.0\n */\n\nexport function macroTarget(state: MacroStateInterface, node?: Node | null): MacroTargetInterface | undefined {\n if (!node) return;\n if (isMacroCall(node)) return { call: node, suffix: '' };\n if (node.type === 'TSAsExpression') return macroTarget(state, node.expression);\n if (node.type !== 'CallExpression' || !isMacroCall(node.callee)) return;\n\n return { call: node.callee, suffix: state.code.slice(node.callee.end, node.end) };\n}\n\n/**\n * The name a declaration binds, together with the macro that initializes it.\n *\n * @param state - Transform state, read for the source text\n * @param node - Declaration to look at, exported or bare\n * @returns The declared name and its macro target, or `undefined` where the node declares no macro\n *\n * @remarks\n * An `export` wrapper is stepped through first, so one test serves the exported form and the bare one alike.\n * A single declarator alone qualifies, which leaves `const a = $$ifdef('DEV', 1), b = 2` untouched.\n *\n * @see DeclaredMacroType\n * @since 3.0.0\n */\n\nexport function declaredMacro(state: MacroStateInterface, node: Node): DeclaredMacroType | undefined {\n const declaration = node.type === 'ExportNamedDeclaration' ? node.declaration : node;\n if (declaration?.type !== 'VariableDeclaration' || declaration.declarations.length !== 1) return;\n\n const { id, init } = declaration.declarations[0];\n if (id.type !== 'Identifier') return;\n\n const target = macroTarget(state, init);\n\n return target && [ id, target ];\n}\n\n/**\n * Rewrites an import that names a dropped macro.\n *\n * @param state - Transform state the edit is collected on\n * @param node - Import declaration to prune\n * @returns `true` when the statement was rewritten\n *\n * @remarks\n * A named specifier bound to a dropped macro is removed, while a default or a namespace import is kept as written.\n * An import left with no specifiers at all becomes a bare `import 'source';`,\n * so a module imported for its side effect still runs.\n *\n * @since 3.0.0\n */\n\nexport function pruneImport(state: MacroStateInterface, node: ImportDeclaration): boolean {\n const named: Array<string> = [];\n const parts: Array<string> = [];\n let dropped = false;\n\n for (const specifier of node.specifiers) {\n const text = state.code.slice(specifier.start, specifier.end);\n\n if (specifier.type !== 'ImportSpecifier') parts.push(text);\n else if (state.dropped.has(specifier.local.name)) dropped = true;\n else named.push(text);\n }\n\n if (!dropped) return false;\n const source = state.code.slice(node.source.start, node.source.end);\n if (named.length > 0) parts.push(`{ ${ named.join(', ') } }`);\n\n if (parts.length < 1) return record(state, node, `import ${ source };`);\n\n return record(state, node, `import ${ parts.join(', ') } from ${ source };`);\n}\n\n/**\n * Rewrites an export list that names a dropped macro.\n *\n * @param state - Transform state the edit is collected on\n * @param node - Export declaration to prune\n * @returns `true` when the statement was rewritten\n *\n * @remarks\n * The specifiers that survive are re-emitted as they were written, and a list left with none is deleted outright.\n * A list that names nothing dropped is reported untouched, so the walk descends into it as usual.\n *\n * @since 3.0.0\n */\n\nexport function pruneExport(state: MacroStateInterface, node: ExportNamedDeclaration): boolean {\n const { specifiers } = node;\n const kept = specifiers.filter(\n ({ local }) => !state.dropped.has(local.type === 'Literal' ? local.value : local.name)\n );\n\n if (kept.length === specifiers.length) return false;\n if (kept.length < 1) return record(state, node, '');\n\n return record(state, node, `export { ${ kept.map(item => state.code.slice(item.start, item.end)).join(', ') } };`);\n}\n\n/**\n * Replaces a declaration whose value comes from a macro.\n *\n * @param state - Transform state the edit is collected on\n * @param node - Declaration to expand, exported or bare\n * @returns `true` when the declaration was rewritten\n *\n * @remarks\n * A name that does not open with {@link MacroPrefix} draws a `macro-prefix` warning and expands either way.\n * An `inline` declaration is deferred until its value has run.\n * A conditional declaration becomes what {@link defineDeclaration} builds while it is active\n * and is deleted where it is not.\n *\n * @since 3.0.0\n */\n\nexport function expandDeclaration(state: MacroStateInterface, node: Node): boolean {\n const declared = declaredMacro(state, node);\n if (!declared) return false;\n\n const [ id, target ] = declared;\n const { call, suffix } = target;\n const prefix = node.type === 'ExportNamedDeclaration' ? 'export ' : '';\n\n if (!id.name.startsWith(MacroPrefix)) report(state, id.start, 'warning', {\n id: 'macro-prefix',\n text: `Macro '${ id.name }' does not start with the '${ MacroPrefix }' prefix to avoid conflicts`\n });\n\n if (call.callee.name === Macros.inline)\n return defer(state, node, call, value => `${ prefix }const ${ id.name } = ${ value }${ suffix };`);\n\n return record(state, node, isActive(state, call) ? defineDeclaration(state.code, id.name, target, prefix) : '');\n}\n\n/**\n * Replaces a macro used as a value.\n *\n * @param state - Transform state the edit is collected on\n * @param node - Node the replacement stands in for\n * @param target - The macro call and whatever call followed it\n * @param statement - Whether the macro stands as a statement of its own\n * @returns `true`, since every call that reaches here rewrites something\n *\n * @remarks\n * An `inline` call is deferred until its value has run.\n * A conditional call becomes what {@link defineExpression} builds while it is active.\n * An inactive one leaves nothing behind as a statement, and `undefined` where a value is expected.\n *\n * @since 3.0.0\n */\n\nexport function expand(state: MacroStateInterface, node: Node, target: MacroTargetInterface, statement: boolean): boolean {\n const { call, suffix } = target;\n\n if (call.callee.name === Macros.inline)\n return defer(state, node, call, value => statement ? '' : `${ value }${ suffix }`);\n\n if (!isActive(state, call)) return record(state, node, statement ? '' : 'undefined');\n\n return record(state, node, defineExpression(state.code, target, statement));\n}\n\n/**\n * Rewrites one node and reports whether the walk should stop there.\n *\n * @param state - Transform state the edits are collected on\n * @param node - Node the walk arrived at\n * @param parent - Node it hangs from, `null` at the root\n * @param key - Property of the parent it sits under\n * @returns `true` when the node was rewritten and the walk should not descend into it\n *\n * @remarks\n * The visitor the rewriting walk runs, dispatching on the type of the node:\n *\n * - **An identifier** - a dropped name becomes `undefined` where it is read, and is left alone where it only names\n * something, which {@link MacroNameKeys} and the parent's `computed` flag decide between.\n * - **An import or an export list** - pruned of the names the build dropped.\n * - **A declaration** - expanded, or pruned where it re-exports rather than declares.\n * - **An expression statement or a call** - expanded, or replaced where it calls something dropped.\n *\n * Any other node is reported untouched, so the walk descends into it.\n *\n * @since 3.0.0\n */\n\nexport function expandNode(state: MacroStateInterface, node: Node, parent: Node | null, key: string): boolean {\n switch (node.type) {\n case 'Identifier': {\n if (!state.dropped.has(node.name) || !parent) return false;\n\n const keyed = key === 'key' || key === 'property';\n const named = keyed ? !('computed' in parent) || !parent.computed : MacroNameKeys.has(key);\n\n return !named && record(state, node, 'undefined');\n }\n\n case 'ImportDeclaration':\n return pruneImport(state, node);\n\n case 'ExportNamedDeclaration':\n if (expandDeclaration(state, node)) return true;\n if (node.source || node.specifiers.length < 1) return false;\n\n return pruneExport(state, node);\n\n case 'VariableDeclaration':\n return expandDeclaration(state, node);\n\n case 'ExpressionStatement': {\n if (isDropped(state, node.expression)) return record(state, node, '');\n const target = macroTarget(state, node.expression);\n\n return target !== undefined && expand(state, node, target, true);\n }\n\n case 'CallExpression':\n case 'TSAsExpression': {\n if (isDropped(state, node)) return record(state, node, 'undefined');\n const target = macroTarget(state, node);\n\n return target !== undefined && expand(state, node, target, false);\n }\n }\n\n return false;\n}\n\n/**\n * Expands every macro in a file and returns the rewritten source.\n *\n * @param parse - The file's parse result, walked rather than parsed again\n * @param target - Absolute path of the file, named in messages and used to resolve an inline value's packages\n * @param content - Source text of the file\n * @param context - Lifecycle context, read for the logs, the flags, and the names the build has dropped\n * @returns The rewritten source, or `content` itself where there was nothing to expand\n *\n * @remarks\n * An empty file comes back untouched, and so does any file under `node_modules`.\n * So does a file that carries no {@link MacroPrefix}, unless an earlier file dropped a name this one may still use.\n * A first walk over a file carrying {@link MacroScanHint} collects the conditional macros that are not active and\n * adds their names to the set the build shares, so dropping a name where it was declared.\n * also drops it where it is imported.\n * The rewriting walk follows, and any deferred `inline` value is awaited before the edits are applied.\n *\n * @example\n * ```ts\n * // source: export const $$dev = $$ifdef('DEV', () => log());\n * await transformMacros(parse, '/src/a.ts', content, context);\n * // result: export function $$dev() { return log(); } - while DEV is set\n * ```\n *\n * @see analyzeMacros\n * @see MacroStateInterface\n *\n * @since 3.0.0\n */\n\nexport async function transformMacros(\n parse: ParseResult, target: string, content: string, context: LifecycleContextInterface\n): Promise<string> {\n if (content.length < 1 || target.includes('node_modules')) return content;\n\n const { dropped } = context.stage;\n if (dropped.size < 1 && !content.includes(MacroPrefix)) return content;\n\n const state: MacroStateInterface = {\n target,\n dropped,\n code: content,\n logs: context.logs,\n edits: [],\n pending: [],\n defines: context.options.define ?? {},\n overrides: context.overrides\n };\n\n if (content.includes(MacroScanHint)) walk(parse.program, node => {\n const declared = declaredMacro(state, node);\n if (!declared) return false;\n\n const [ id, { call }] = declared;\n if (call.callee.name !== Macros.inline && !isActive(state, call)) dropped.add(id.name);\n\n return false;\n });\n\n walk(parse.program, expandNode.bind(null, state));\n if (state.pending.length > 0) await Promise.all(state.pending);\n\n return applyEdits(content, state.edits);\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { MacroCallType, MacroStateInterface } from '@directives/interfaces/macros-directive.interface';\n\n/**\n * Imports\n */\n\nimport { createRequire } from 'module';\nimport { inject } from '@remotex-labs/xinject';\nimport { sandboxExecute } from '@services/vm.service';\nimport { stringify } from '@components/object.component';\nimport { FrameworkService } from '@services/framework.service';\nimport { buildFromString } from '@services/transpiler.service';\n\n/**\n * Renders an evaluated value as the source text that stands in for the call.\n *\n * @param value - Value the callback produced\n * @returns Source text for the value, or `'undefined'` where there is nothing to render\n *\n * @remarks\n * `undefined` and `null` both come out as `undefined`, since the call has to leave an expression behind.\n * A function comes out as its own source, and a number or a boolean through `String`.\n * Everything else goes through {@link stringify}, which is JSON,\n * so a `Map` or a `Set` arrives as `{}` and a `bigint` as a quoted string.\n *\n * @since 3.0.0\n */\n\nexport function serialize(value: unknown): string {\n if (value === undefined || value === null) return 'undefined';\n if (typeof value === 'function') return value.toString();\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n\n return stringify(value) ?? 'undefined';\n}\n\n/**\n * Runs the callback of an `$$inline` call and renders what it produced.\n *\n * @param state - Transform state, read for the source text and for the file the call sits in\n * @param call - The `$$inline` call whose only argument is the callback to run\n * @returns Source text standing for the value the callback produced\n *\n * @throws BuildFailure - Rejected by esbuild when the callback does not build\n * @throws Error - Whatever the callback itself threw while it ran\n *\n * @remarks\n * The callback is taken from the source as written, wrapped in a CommonJS module that calls it,\n * and built through {@link buildFromString}.\n * A relative specifier inside it therefore resolves against the working directory rather than against the file that\n * the call sits in.\n * A package stays external and is required through a `require` bound to that file as the callback runs.\n * The built code runs through {@link sandboxExecute}, and the value is read from what the run returned,\n * falling back to `module.exports`.\n * What comes back is source text rather than a value, since {@link serialize} renders it.\n *\n * @example\n * ```ts\n * // $$inline(() => 2 + 2)\n * await evaluate(state, call); // '4'\n *\n * // $$inline(() => ({ region: 'eu' }))\n * await evaluate(state, call); // '{\"region\":\"eu\"}'\n * ```\n *\n * @see serialize\n * @see sandboxExecute\n * @see buildFromString\n *\n * @since 3.0.0\n */\n\nexport async function evaluate(state: MacroStateInterface, call: MacroCallType): Promise<string> {\n const target = state.target + '.inline';\n const thunk = state.code.slice(call.arguments[0].start, call.arguments[0].end);\n const [ map, output ] = (await buildFromString(`module.exports = (${ thunk })();`, target, {\n format: 'cjs',\n platform: 'node',\n packages: 'external'\n })).outputFiles!;\n\n const module = { exports: undefined };\n inject(FrameworkService).addSourceMap(target, map.text, true);\n const value = await sandboxExecute(output.text, { module, require: createRequire(state.target) }, {\n filename: target\n });\n\n return serialize(value ?? module.exports);\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { Context, ScriptOptions } from 'vm';\n\n/**\n * Imports\n */\n\nimport { Script, createContext } from 'vm';\n\n/**\n * Runs code in a VM context that shares the host's globals.\n *\n * @param code - Source to compile and run\n * @param sandbox - Values to expose as globals, each shadowing the host value of the same name\n * @param options - Compile-time options, such as the filename errors are reported against\n * @param isolateLogs - Whether to keep the code's console output from reaching the host\n * @returns The completion value of the last expression, awaited when it is a promise\n *\n * @throws SyntaxError - Thrown when the code does not compile\n * @throws Error - Whatever the code itself throws, propagated unchanged\n *\n * @remarks\n * The host's own globals are copied into the context before the sandbox is applied,\n * so the code inside sees the same intrinsics the caller does.\n * A value the code builds crosses back out intact - a `RegExp` made inside satisfies `instanceof RegExp` outside,\n * which a fresh context's own intrinsics would not.\n * This isolates the global scope, not the process.\n * `process` and the timers are reachable from the code being run,\n * so it is a scoping tool for code you trust rather than a boundary against code you do not.\n * Only compilation is configurable - the run is fixed to break on `SIGINT` and to leave errors undecorated.\n * It carries no timeout, so code that never finishes blocks the caller.\n *\n * `isolateLogs` drops the host `console` rather than replacing it,\n * so the code falls back to the console a fresh context is given and its output reaches nothing the caller sees.\n * A call still succeeds, since `console.log` is a function either way,\n * so quieting the output does not break code that logs.\n * The drop happens after the sandbox is applied, so it takes a `console` the caller injected as well.\n * It covers the console alone - code writing to `process.stdout` reaches the host whatever this is set to.\n *\n * @example\n * ```ts\n * await sandboxExecute('2 + 2'); // 4\n * (await sandboxExecute('new RegExp(\"a\")')) instanceof RegExp; // true - the host's RegExp\n *\n * const module = { exports: {} };\n * await sandboxExecute('module.exports = process.cwd();', { module });\n * module.exports; // 'D:/app' - read back through the injected object\n *\n * await sandboxExecute('console.log(\"noisy\"); 1', {}, {}, true); // 1 - nothing printed\n * ```\n *\n * @see Context\n * @see ScriptOptions\n *\n * @since 3.0.0\n */\n\nexport async function sandboxExecute(code: string, sandbox: Context = {}, options: ScriptOptions = {}, isolateLogs = false): Promise<unknown> {\n const base: Record<string, unknown> = {};\n const descriptors: { [x: string]: PropertyDescriptor; } = Object.getOwnPropertyDescriptors(globalThis);\n delete descriptors.globalThis;\n if(isolateLogs) delete descriptors.console;\n\n Object.defineProperties(base, descriptors);\n Object.assign(base, sandbox);\n\n const context = createContext(base);\n const script = new Script(code, options);\n\n return await script.runInContext(context, { breakOnSigint: true, displayErrors: false });\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { BuildOptions, BuildResult, Metafile } from 'esbuild';\nimport type { BuildResultType } from '@services/interfaces/transpiler-service.interface';\n\n/**\n * Imports\n */\n\nimport { cwd } from 'process';\nimport { build } from 'esbuild';\nimport { dirname, basename } from '@remotex-labs/xmap';\nimport { DefaultBuildOptions } from '@constants/transpiler.constant';\n\n/**\n * Builds whatever the options describe and returns the result in memory.\n *\n * @typeParam T - Extra fields to widen the result with, for a caller that attaches its own\n *\n * @param buildOptions - esbuild options, the entry points among them, overriding {@link DefaultBuildOptions}\n * @returns The build result, carrying a metafile the type still marks optional\n *\n * @throws BuildFailure - Rejected by esbuild when the build fails, carrying its errors and warnings\n *\n * @remarks\n * Options are layered in four steps: the working directory, then {@link DefaultBuildOptions},\n * then the caller's own, and last the metafile.\n * Only the metafile is applied after the caller's, so it is the single option that cannot be turned off.\n * Everything else is the caller's to change, including the working directory and whether output is written at all.\n * Entry points travel in the options like any other setting,\n * so a build is described by a single object rather than by an argument and an object that have to agree.\n *\n * @example\n * ```ts\n * const result = await buildFiles({ entryPoints: [ 'src/index.ts' ] });\n *\n * result.outputFiles?.length; // 2 - the source map and the code\n * Object.keys(result.metafile!.inputs); // [ 'src/index.ts', 'src/builder.ts' ]\n * ```\n *\n * @see DefaultBuildOptions\n * @since 3.0.0\n */\n\nexport async function buildFiles<T = object>(buildOptions: BuildOptions = {}): Promise<BuildResultType & T> {\n return await build({\n absWorkingDir: cwd(),\n ...DefaultBuildOptions,\n ...buildOptions,\n metafile: true\n }) as BuildResultType & T;\n}\n\n/**\n * Builds source text that has no file behind it.\n *\n * @typeParam T - Extra fields to widen the result with, for a caller that attaches its own\n *\n * @param source - TypeScript source to build\n * @param path - Name the source is reported under in its map and in errors, which need not exist on the disk\n * @param buildOptions - Options overriding {@link DefaultBuildOptions}\n * @returns The build result, carrying the code and its map in `outputFiles`\n *\n * @throws BuildFailure - Rejected by esbuild when the build fails, carrying its errors and warnings\n *\n * @remarks\n * The text is fed in through esbuild's `stdin` rather than read from a file,\n * which is what lets a macro body or a generated snippet be built before any file exists.\n * It is loaded as TypeScript, and its relative imports resolve against the working directory rather than against\n * `path`, which names the source in the map and in errors without pointing at a real location.\n * Four options are fixed after the caller's and cannot be overridden: the stdin input, in-memory output, the metafile,\n * and an external source map.\n * Logging is not among them: it arrives silent from {@link DefaultBuildOptions} and stays the caller's to raise.\n *\n * @example\n * ```ts\n * const result = await buildFromString('export const x: number = 42;', 'virtual.ts');\n *\n * result.outputFiles?.length; // 2 - the source map and the code\n * Object.keys(result.metafile!.inputs); // [ 'virtual.ts' ] - keyed by the name that was passed\n * ```\n *\n * @see DefaultBuildOptions\n * @since 3.0.0\n */\n\nexport async function buildFromString<T = object>(source: string, path: string, buildOptions: BuildOptions = {}): Promise<BuildResultType & T> {\n return await build({\n absWorkingDir: cwd(),\n ...DefaultBuildOptions,\n ...buildOptions,\n stdin: {\n loader: 'ts',\n contents: source,\n resolveDir: dirname(path),\n sourcefile: basename(path)\n },\n write: false,\n metafile: true,\n sourcemap: 'external'\n }) as BuildResultType & T;\n}\n\n/**\n * Walks the imports of the entry points named in the options and returns the dependency graph, building no output.\n *\n * @param buildOptions - esbuild options, the entry points to walk among them, applied under the ones it fixes\n * @returns The result, its `metafile` describing every input reached and the imports between them\n *\n * @throws BuildFailure - Rejected by esbuild when a specifier does not resolve\n *\n * @remarks\n * Bundling is what does the walking,\n * so the graph matches what a bundler would resolve rather than a reading of the import statements.\n * An unresolvable specifier therefore fails the call instead of being reported as a missing edge.\n * Packages are marked external, so the walk stops at the project's edge rather than descending into `node_modules`.\n * Nothing reaches the disk: output is kept in memory,\n * and the output directory is nominal, named only because esbuild insists on one.\n * {@link DefaultBuildOptions} is not applied here, unlike {@link buildFiles}, so the caller's options and the seven\n * fixed after them are the whole of the configuration.\n *\n * @example\n * ```ts\n * const result = await analyzeDependencies({ entryPoints: [ 'src/index.ts' ] });\n *\n * Object.keys(result.metafile.inputs); // [ 'src/index.ts', 'src/builder.ts' ]\n * result.metafile.inputs['src/index.ts'].imports; // [ { path: 'src/builder.ts', kind: 'import-statement' } ]\n * ```\n *\n * @see Metafile\n * @since 3.0.0\n */\n\nexport async function analyzeDependencies(buildOptions: BuildOptions = {}): Promise<\n BuildResult & { metafile: Metafile }\n> {\n return await build({\n ...buildOptions,\n write: false,\n bundle: true,\n outdir: 'tmp',\n outfile: undefined,\n metafile: true,\n packages: 'external',\n logLevel: 'silent'\n });\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { BuildOptions } from 'esbuild';\n\n/**\n * Base esbuild options every build in this package starts from.\n *\n * @remarks\n * Output is kept in memory rather than written,\n * so a caller reads `outputFiles` and decides for itself what reaches the disk.\n * The source map is emitted as its own output file rather than inlined,\n * which keeps the code readable and lets a consumer attach the map only when it wants it.\n * An output directory is set even though nothing is written,\n * since esbuild insists on one as soon as a build has more than a single entry point.\n * Spread before the caller's options wherever it is used,\n * so any of these can be overridden - unlike the options each build helper fixes after them.\n *\n * @example\n * ```ts\n * defaultBuildOptions.write; // false - the result is returned, not written\n * await buildFiles({ entryPoints: [ 'src/index.ts' ], minify: false }); // overrides one, keeps the rest\n * ```\n *\n * @see BuildOptions\n * @since 2.0.0\n */\n\nexport const DefaultBuildOptions: BuildOptions = {\n write: false,\n bundle: true,\n minify: true,\n outdir: 'dist',\n format: 'cjs',\n target: 'esnext',\n logLimit: 0,\n logLevel: 'silent',\n platform: 'browser',\n sourcemap: 'external'\n};\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { BuildOptions } from 'esbuild';\n\n/**\n * Imports\n */\n\nimport { cwd } from 'process';\nimport { relative } from '@remotex-labs/xmap';\nimport { collectFiles } from '@components/glob.component';\nimport { FrameworkService } from '@services/framework.service';\n\n/**\n * Normalizes entry points of any esbuild form into an output name to input path record.\n *\n * @param entryPoints - Entry points in any form esbuild accepts, or `undefined`\n * @param root - Directory the output names are shortened against, defaulting to the working directory\n * @returns The entry points keyed by the output each one produces, or `undefined` when none were given\n *\n * @throws Error - When the entry points are neither an array, an object, nor `undefined`\n *\n * @remarks\n * The three forms differ only in where the output name comes from:\n * - A list of globs is matched from the working directory, and each file is keyed by its path with `root` stripped\n * off the front and the extension dropped, so `src` as the root turns `src/components/interactive.component.ts`\n * into `components/interactive.component`.\n * - A list of `in` and `out` pairs is keyed by `out`, both paths passing through untouched.\n * - A record is already in the target shape and is returned as it stands, without a copy.\n *\n * Globs are always matched from the working directory, whatever `root` says: `root` shortens the output names and\n * does nothing else, matching no files itself and excluding none.\n * A file the globs reach from outside `root` is therefore kept rather than dropped,\n * and is named by its whole path from the working directory instead.\n * One call can therefore carry files from either side of `root`:\n * an outside file lands in a directory of its own in the output, while an inside file lands at the top.\n * The values are the paths the walk produced, relative to the working directory,\n * so nothing is resolved a second time, and a key costs one slice.\n * An empty list yields an empty record rather than every file under the working directory, which a pattern set with\n * no includes would otherwise match.\n *\n * @example\n * ```ts\n * extractEntryPoints([ 'src/**' ]);\n * // { 'src/index': 'src/index.ts', 'src/components/glob.component': 'src/components/glob.component.ts' }\n *\n * extractEntryPoints([ 'src/**' ], 'src/components');\n * // {\n * // 'glob.component': 'src/components/glob.component.ts', // under the root, shortened to its own name\n * // 'src/services/vm.service': 'src/services/vm.service.ts' // outside it, named by its whole path\n * // }\n *\n * extractEntryPoints([ { in: 'src/index.ts', out: 'bundle' } ]);\n * // { bundle: 'src/index.ts' }\n * ```\n *\n * @see collectFiles\n * @see {@link https://esbuild.github.io/api/#entry-points | esbuild entry points}\n *\n * @since 3.0.0\n */\n\nexport function extractEntryPoints(entryPoints: BuildOptions['entryPoints'], root: string = cwd()): Record<string, string> | undefined {\n if (entryPoints === undefined) return undefined;\n if (!Array.isArray(entryPoints)) {\n if (typeof entryPoints !== 'object' || entryPoints === null) throw new Error('Unsupported entry points format');\n\n return entryPoints;\n }\n\n const result: Record<string, string> = {};\n if (entryPoints.length < 1) return result;\n\n if (typeof entryPoints[0] === 'object') {\n for (const entry of <Array<{ in: string, out: string }>> entryPoints) result[entry.out] = entry.in;\n\n return result;\n }\n\n const prefix = relative(cwd(), FrameworkService.resolve(root));\n const scope = prefix && prefix !== '.' ? `${ prefix }/` : '';\n\n for (const file of collectFiles(cwd(), <Array<string>> entryPoints)) {\n const name = scope && file.startsWith(scope) ? file.slice(scope.length) : file;\n const dot = name.lastIndexOf('.');\n result[dot > name.lastIndexOf('/') + 1 ? name.slice(0, dot) : name] = file;\n }\n\n return result;\n}\n","/**\n * The configuration blocks a build injects into its esbuild options as text.\n *\n * @remarks\n * The three settings a configuration states as a table of names to code rather than as a plain option,\n * so one pass over this list injects all of them instead of naming each at its own call site.\n * A value written as a function is called for the variant being built and its result injected,\n * which is what makes the three interchangeable here.\n *\n * @example\n * ```ts\n * for (const block of TextBlocks) injectTextBlock(options, block); // banner, then footer, then define\n * ```\n *\n * @see VariantService\n * @since 3.0.0\n */\n\nexport const TextBlocks = [ 'banner', 'footer', 'define' ] as const;\n\n/**\n * The reporting level each TypeScript diagnostic category maps to.\n *\n * @remarks\n * Indexed by `ts.DiagnosticCategory`, which counts `Warning` as `0`, `Error` as `1`, and `Suggestion` as `2`,\n * so the order of the entries is the mapping itself rather than a preference.\n * `Message` counts as `3` and falls off the end,\n * so whatever reads the table settles that one for itself.\n *\n * @example\n * ```ts\n * DiagnosticLevels[1]; // 'error' - ts.DiagnosticCategory.Error\n * DiagnosticLevels[3]; // undefined - a plain message, left to the reader\n * ```\n *\n * @see LogLevelType\n * @see VariantService\n *\n * @since 3.0.0\n */\n\nexport const DiagnosticLevels = [ 'warning', 'error', 'info' ];\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { PartialMessage, Message, OnStartResult } from 'esbuild';\n\n/**\n * Imports\n */\n\nimport { parseErrorStack } from '@remotex-labs/xmap/parser.component';\n\n/**\n * Reports whether a caught value carries esbuild's own messages rather than being an ordinary error.\n *\n * @param error - Value caught from a build, of unknown shape\n * @returns `true` when the value holds esbuild messages, which narrows it to {@link OnStartResult}\n *\n * @remarks\n * The test is a non-null object whose `errors` array holds at least one entry,\n * and whose first entry is an object carrying a `detail` key.\n * esbuild puts `detail` on every message it produces, so the key is there even where it holds nothing,\n * and the guard reads whether the key is present rather than what it holds.\n * That is what separates a nested build that failed from an error a hook threw:\n * the first already carries messages a reporter files as they stand,\n * while the second reaches {@link errorToMessage} to become one.\n * A result assembled by hand goes unrecognized, since a message written as `{ text }` carries no `detail` key.\n *\n * @example\n * ```ts\n * isEsbuildError(buildFailure); // true - errors[0] came from esbuild\n * isEsbuildError(new Error('boom')); // false - no errors\n * isEsbuildError({ errors: [] }); // false - nothing to report\n * isEsbuildError({ errors: [ { text: 'oops' } ] }); // false - no detail key\n * ```\n *\n * @see errorToMessage\n * @since 3.0.0\n */\n\nexport function isEsbuildError(error: unknown): error is OnStartResult {\n if (error === null || typeof error !== 'object') return false;\n\n const errors = (error as { errors?: unknown }).errors;\n if (!Array.isArray(errors) || errors.length === 0) return false;\n const first = errors[0];\n\n return first !== null && typeof first === 'object' && 'detail' in first;\n}\n\n/**\n * Converts a thrown error into an esbuild message.\n *\n * @param error - Error to convert, kept whole on the message's `detail`\n * @param id - Message id to file the diagnostic under, empty when the caller names none\n * @param name - Plugin name to credit the message to, empty when the caller names none\n * @returns The message, carrying a location when the error's first frame named one\n *\n * @remarks\n * The error travels on `detail` rather than flattened into the text,\n * so {@link getErrorStack} unwraps it later and resolves the whole trace instead of the summary line alone.\n * `text` is the message the stack parsed out, and `location` comes from the first frame,\n * set only when that frame names a file, a line, and a column.\n * A frame of the three leaves the message without a location,\n * which leaves a reader with the text alone.\n * The location is filed under the `file` namespace, since a parsed frame points at a path on disk\n * rather than at something a plugin serves itself.\n *\n * @example\n * ```ts\n * const message = errorToMessage(new Error('boom'), 'macro-failed', 'xbuild');\n * message.text; // 'boom'\n * message.id; // 'macro-failed'\n * message.location?.line; // 19 - the line the first frame points at\n * ```\n *\n * @see getErrorStack\n * @see parseErrorStack\n *\n * @since 3.0.0\n */\n\nexport function errorToMessage(error: Error, id: string = '', name: string = ''): Message {\n const message = { detail: error, id, pluginName: name } as PartialMessage;\n\n const parsedStack = parseErrorStack(error);\n const frame = parsedStack.stack[0];\n\n message.text = parsedStack.message;\n if (frame?.fileName && frame.line && frame.column) {\n message.location = {\n line: frame.line,\n file: frame.fileName,\n column: frame.column,\n namespace: 'file'\n };\n }\n\n return message as Message;\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { FSWatcher, Dirent } from 'fs';\nimport type { ErrorType, CompleteType, UnsubscribeType } from '@remotex-labs/xobservable';\nimport type { WatchEventType, ChangeType, ObserverType } from './interfaces/watch-service.interface';\nimport type { WatchChangeInterface, WatchOptionsInterface } from './interfaces/watch-service.interface';\n\n/**\n * Imports\n */\n\nimport { Injectable } from '@remotex-labs/xinject';\nimport { Subject } from '@remotex-labs/xobservable';\nimport { ChangeCode } from '@constants/watch.constant';\nimport { createMatcher } from '@components/glob.component';\nimport { resolve, join, relative } from '@remotex-labs/xmap';\nimport { watch, realpathSync, readdirSync, lstatSync, statSync } from 'fs';\n\n/**\n * A filesystem watcher that multicasts debounced batches of path changes to every subscriber.\n *\n * @remarks\n * Extends a multicast {@link Subject}: the underlying `fs.watch` handles are opened on the **first** subscription and\n * torn down only when the **last** subscription ends, while every active subscriber receives each emitted batch.\n * Events are filtered by a glob matcher, coalesced within a debounced window, and delivered as a single\n * {@link WatchEventType} keyed by path relative to the base.\n * Because `fs.watch` never follows symbolic links,\n * {@link WatchOptionsInterface.followSymlinks} places explicit watchers on the links it finds.\n * As a {@link Subject}, the emitted stream can be reshaped with `pipe` and operators before subscribing.\n *\n * @example\n * <caption>Multiple independent subscribers - each receives every batch</caption>\n * ```ts\n * const watcher = new WatchService('src', { recursive: true, filter: [ '**\\/*.{ts,js}' ], debounce: 100 });\n *\n * const stopA = watcher.subscribe((changes) => rebuild(changes)); // opens the fs watchers\n * const stopB = watcher.subscribe((changes) => reloadTypes(changes)); // reuses them\n *\n * stopB(); // watchers stay open - `stopA` is still subscribed\n * stopA(); // last subscriber leaves - every handle is closed\n * ```\n *\n * @example\n * <caption>Scoped teardown - the subscription disposes automatically at the end of the block</caption>\n * ```ts\n * const watcher = new WatchService(cwd(), { followSymlinks: true, filter: [ '**\\/*.{ts,js}' ] });\n * using sub = watcher.subscribe((changes) => console.log(Object.keys(changes)));\n * ```\n *\n * @see Subject.pipe\n * @see WatchEventType\n * @see WatchOptionsInterface\n *\n * @since 3.0.0\n */\n\n@Injectable({\n scope: 'singleton'\n})\nexport class WatchService extends Subject<WatchEventType> {\n /**\n * The absolute root path being watched.\n *\n * @since 3.0.0\n */\n\n private readonly base: string;\n\n /**\n * Predicate deciding whether a path passes the configured filter.\n *\n * @since 3.0.0\n */\n\n private readonly matcher: ReturnType<typeof createMatcher>;\n\n /**\n * Active `fs.watch` handles, keyed by the path each was opened on.\n *\n * @since 3.0.0\n */\n\n private readonly watchers = new Map<string, FSWatcher>();\n\n /**\n * Changes accumulated in the current debounced window, keyed by path relative to the base.\n *\n * @since 3.0.0\n */\n\n private readonly pending = new Map<string, WatchChangeInterface>();\n\n /**\n * Count of currently active subscriptions, used to start watchers on the first and stop them on the last.\n *\n * @since 3.0.0\n */\n\n private subscriptions = 0;\n\n /**\n * Handle for the scheduled debounced flush, or `undefined` while idle.\n *\n * @since 3.0.0\n */\n\n private timer?: ReturnType<typeof setTimeout>;\n\n /**\n * Creates a watcher rooted at a base path.\n *\n * @param base - Directory to watch, resolved to an absolute path\n * @param options - Filtering, debounce, recursion, and symlink behavior\n *\n * @remarks\n * No watcher is opened until the first subscriber attaches, so constructing one costs a resolve and a matcher.\n *\n * @example\n * ```ts\n * const watcher = new WatchService('src', { filter: [ '**\\/*.ts' ] }); // nothing is watched yet\n * ```\n *\n * @see WatchOptionsInterface\n * @since 3.0.0\n */\n\n constructor(base: string, private options?: WatchOptionsInterface) {\n super();\n\n this.base = resolve(base);\n this.matcher = createMatcher(this.options?.filter ?? [], {\n dot: this.options?.dot ?? false\n });\n }\n\n /**\n * Subscribes to the debounced change stream, starting the watchers on the first subscriber.\n *\n * @param observerOrNext - A full observer object, or a `next` callback\n * @param error - Error handler, used when the first argument is a `next` callback\n * @param complete - Completion handler, used when the first argument is a `next` callback\n * @returns Idempotent, disposable unsubscribe function that detaches this subscriber and,\n * once it is the last one, closes every open watcher\n *\n * @remarks\n * The first subscription opens the `fs.watch` handles, and each later subscription reuses them.\n * Unsubscribing runs at most once.\n * The handles, the pending batch, and the flush timer are released only when the final subscriber leaves,\n * so a watcher shared by several consumers stays alive until all of them detach.\n *\n * @example\n * ```ts\n * const stop = watcher.subscribe((changes) => rebuild(changes));\n * stop(); // detaches, and closes the handles when no other subscriber is left\n * ```\n *\n * @see ObserverType\n * @see Subject.subscribe\n *\n * @since 3.0.0\n */\n\n override subscribe(observerOrNext?: ObserverType, error?: ErrorType, complete?: CompleteType): UnsubscribeType {\n const unsubscribe = super.subscribe(observerOrNext, error, complete);\n if (++this.subscriptions === 1) this.start();\n\n return this.toUnsubscribe(() => {\n unsubscribe();\n if (--this.subscriptions === 0) this.stop();\n });\n }\n\n /**\n * The debounced window in milliseconds, defaulting to 150.\n *\n * @since 3.0.0\n */\n\n private get debounce(): number {\n return this.options?.debounce ?? 150;\n }\n\n /**\n * Opens the base watcher and the symlink watchers when configured.\n *\n * @remarks\n * Invoked once when the subscriber count rises from zero to one.\n *\n * @since 3.0.0\n */\n\n private start(): void {\n this.watch(this.base, this.ignored.bind(this), this.options?.recursive);\n if (this.options?.followSymlinks) this.watchSymlinks(this.base);\n }\n\n /**\n * Clears the pending timer and closes every open watcher.\n *\n * @remarks\n * Invoked once when the subscriber count falls back to zero, returning the service to its pre-subscription state so\n * a later subscription can start clean.\n *\n * @since 3.0.0\n */\n\n private stop(): void {\n if (this.timer) clearTimeout(this.timer);\n for (const watcher of this.watchers.values()) watcher.close();\n\n this.timer = undefined;\n this.pending.clear();\n this.watchers.clear();\n }\n\n /**\n * Emits the accumulated batch to every subscriber and clears the window.\n *\n * @remarks\n * A no-op when nothing is pending, so an expired timer with no changes emits nothing.\n * A `next` that throws is reported to that subscriber's own `error` handler by the {@link Subject},\n * which then rethrows the failures as one aggregate.\n * That aggregate is swallowed here, so one faulty consumer cannot stop the watcher for the others.\n *\n * @since 3.0.0\n */\n\n private flush(): void {\n this.timer = undefined;\n if (this.pending.size === 0) return;\n\n const batch = Object.fromEntries(this.pending) as WatchEventType;\n this.pending.clear();\n\n try {\n this.next(batch);\n } catch {\n /* handled per-observer by the Subject */\n }\n }\n\n /**\n * Closes and forgets the watcher registered on a path, if any.\n *\n * @param path - Path whose watcher should be released\n *\n * @since 3.0.0\n */\n\n private watcherClose(path: string): void {\n const watcher = this.watchers.get(path);\n if (!watcher) return;\n\n watcher.close();\n this.watchers.delete(path);\n }\n\n /**\n * Classifies a raw watch event and queues it for the next flush.\n *\n * @param event - The `fs.watch` event name, either `rename` or `change`\n * @param path - Absolute path the event refers to\n *\n * @remarks\n * A symlink is stat-followed: when it resolves to a matching file, it is watched directly,\n * and when it resolves to a directory under a recursive watch, it is watched recursively.\n * A broken link is dropped.\n * The change type is read from that followed `stat` - a missing entry is {@link ChangeCode.Deleted} and closes its\n * watcher, an entry whose `birthtime` equals its `mtime` is {@link ChangeCode.Added},\n * and anything else is {@link ChangeCode.Change}.\n * Only paths that pass the filter arm the debounced timer and enter the pending batch.\n *\n * @since 3.0.0\n */\n\n private watcherEvent(event: string, path: string): void {\n const relativePath = relative(this.base, path);\n const link = lstatSync(path, { throwIfNoEntry: false });\n const stats = link?.isSymbolicLink() ? statSync(path, { throwIfNoEntry: false }) : link;\n\n if (link?.isSymbolicLink()) {\n if (!stats) return;\n if (event === 'rename') this.watcherClose(path);\n\n if (stats.isFile() && this.matcher(path)) this.watch(path);\n else if (stats.isDirectory() && this.options?.recursive)\n this.watch(path, this.ignored.bind(this), true);\n }\n\n if (!this.matcher(relativePath)) return;\n if (this.timer) this.timer.refresh();\n else this.timer = setTimeout(this.flush.bind(this), this.debounce);\n\n let type: ChangeType;\n if (!stats) {\n this.watcherClose(path);\n type = ChangeCode.Deleted;\n } else {\n type = stats.birthtimeMs === stats.mtimeMs ? ChangeCode.Added : ChangeCode.Change;\n }\n\n this.pending.set(relativePath, { type, stats });\n }\n\n /**\n * Opens an `fs.watch` on a path and registers its change and error handlers.\n *\n * @param path - Path to watch, ignored if already watched or filtered out by {@link ignored}\n * @param ignore - Optional per-entry ignore predicate forwarded to `fs.watch`\n * @param recursive - Whether the watch should cover nested entries\n *\n * @remarks\n * The watch is opened on the real (symlink-resolved) path, while events are reported against the original `path`.\n * A watcher error closes the watcher and forwards the error to every subscriber.\n *\n * @since 3.0.0\n */\n\n private watch(path: string, ignore?: (filename: string) => boolean, recursive: boolean = false): void {\n if (this.watchers.has(path) || this.ignored(path)) return;\n const watcher = watch(realpathSync(path), { recursive, ignore }, (event, filename) => {\n if (!filename) return;\n const target = path.includes(filename) ? path : join(path, filename);\n this.watcherEvent(event, target);\n });\n\n watcher.on('error', (error: Error) => {\n this.watcherClose(path);\n this.error(error);\n });\n\n this.watchers.set(path, watcher);\n }\n\n /**\n * Whether a path should be skipped by the watcher.\n *\n * @param target - Path to test\n * @returns `true` for an empty path, a `~` backup file, or - unless `dot` is set - any dot-prefixed segment\n *\n * @since 3.0.0\n */\n\n private ignored(target: string): boolean {\n if (!target || target.endsWith('~')) return true;\n if (!this.options?.dot) {\n if (target && target.split(/[/\\\\]/).some(\n seg => seg.startsWith('.'))\n ) return true;\n }\n\n return false;\n }\n\n /**\n * Walks the tree under a root and watches every symbolic link found.\n *\n * @param root - Directory to scan for links\n *\n * @remarks\n * Iterative and single-level per read, so ignored directories are pruned before entry and never fully materialized.\n * Descends into real subdirectories only when recursion is enabled.\n * Unreadable directories are skipped silently.\n *\n * @since 3.0.0\n */\n\n private watchSymlinks(root: string): void {\n const stack: Array<string> = [ root ];\n\n while (stack.length) {\n const dir = stack.pop()!;\n\n let entries: Array<Dirent>;\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n continue;\n }\n\n for (const entry of entries) {\n const full = join(entry.parentPath ?? dir, entry.name);\n if (this.ignored(full)) continue;\n\n if (entry.isSymbolicLink()) {\n this.watch(full, this.ignored.bind(this), this.options?.recursive);\n } else if (this.options?.recursive && entry.isDirectory()) {\n stack.push(full);\n }\n }\n }\n }\n}\n","/**\n * Type-only imports erased during TypeScript compilation.\n */\n\nimport type { xBuildConfigInterface } from '@providers/interfaces/config-file-provider.interface';\n\n/**\n * Imports\n */\n\nimport { resolve } from 'path';\nimport process from 'node:process';\nimport { createRequire } from 'module';\nimport { dirname } from '@remotex-labs/xmap';\nimport { ArgvModule } from '@argv/argv.module';\nimport { inject } from '@remotex-labs/xinject';\nimport { FilesModel } from '@models/files.model';\nimport { sandboxExecute } from '@services/vm.service';\nimport { deepMerge } from '@components/object.component';\nimport { FrameworkService } from '@services/framework.service';\nimport { buildFromString } from '@services/transpiler.service';\n\n/**\n * Runs a compiled configuration file and returns what it exported.\n *\n * @typeParam T - Shape the export is cast to, which the caller states rather than this function checks\n *\n * @param code - The file, already compiled to CommonJS\n * @param path - Path the file came from, which binds its `require` and names it in a stack\n * @param $argv - Arguments to expose to the file as a global, empty where none have been parsed yet\n * @param isolation - Whether to keep the file's console output from reaching the host\n * @returns The named `config` export, the default export where there is none, or an empty object for neither\n *\n * @throws Error - Whatever the file itself threw while it ran\n *\n * @remarks\n * The `require` handed in is bound to the file's own path rather than to this module,\n * so a configuration file resolves a package the way a file in its own directory would.\n * A named `config` export wins over a default export, and a file exporting neither comes back empty.\n * Compiled CommonJS replaces `module.exports` outright,\n * which is what leaves the two exports to be told apart rather than read off the object this function seeded.\n * Reach for `isolation` on a run whose output would only be repeated, since a file may be run more than once.\n *\n * @example\n * ```ts\n * // the file: export const config = { serve: { dir: 'dist' } };\n * const config = await execConfigFile(code, 'xbuild.config.ts', { watch: true });\n * config.serve; // { dir: 'dist' }\n * ```\n *\n * @see sandboxExecute\n * @see configFileProvider\n *\n * @since 3.0.0\n */\n\nexport async function execConfigFile<T>(code: string, path: string, $argv = {}, isolation = false): Promise<T> {\n const module = { exports: { config: {}, default: {} } };\n await sandboxExecute(code, { require: createRequire(resolve(path)), module, $argv }, { filename: path }, isolation);\n const config = module.exports.config ?? module.exports.default;\n\n return (config ?? {}) as T;\n}\n\n/**\n * Loads a configuration file and returns what it exported.\n *\n * @typeParam T - Shape the result is cast to, which the caller states rather than this provider checks\n * @param path - Path of the configuration file, relative or absolute\n * @param argv - Object the parsed arguments are written onto, left untouched where the file is missing\n * @returns What the file exported over the default watch settings, or an empty object where it exported nothing\n *\n * @throws BuildFailure - Rejected by esbuild when the file does not compile\n * @throws Error - Whatever the file itself threw while it ran\n *\n * @remarks\n * A configuration file is built as CommonJS and runs through {@link sandboxExecute},\n * with its `require` bound to its own path,\n * so it may import a package the project already depends on rather than only what this build bundles.\n * Its identifiers survive the build, and its source map is registered with {@link FrameworkService},\n * so an error thrown while it runs is reported against the source that was written.\n *\n * The file runs twice, since the options it declares through `userArgv` are known only once it has been read.\n * The first run is a throwaway: it sees an empty `$argv`, and its output is isolated,\n * so a file that logs does not report the same lines on both passes.\n * The command line is then parsed knowing those options, and the second run sees the whole option set on `$argv`.\n * The caller's `argv` object receives those arguments too, which is how a caller reads them back.\n * Anything the file does on its way to an export therefore happens twice.\n *\n * {@link execConfigFile} settles which of the two exports is read,\n * and what comes back here is that export merged over a default watch filter and recursive watching, key by key,\n * so a file naming one watch setting keeps the others.\n * A `filter` the file names joins the default list rather than replacing it,\n * since {@link deepMerge} concatenates two arrays.\n * A file that exports nothing still picks up those defaults,\n * while one that is missing or holds no text returns before the merge and comes back as a bare empty object.\n * The result is cast rather than validated, so a file exporting something else entirely reaches the caller unchanged.\n *\n * @example\n * ```ts\n * // the configuration file\n * export const config = { serve: { dir: 'dist', start: true }, watch: { debounce: 50 } };\n *\n * const loaded = await configFileProvider('xbuild.config.ts');\n * loaded.serve; // { dir: 'dist', start: true }\n * loaded.watch; // { filter: [ ... ], recursive: true, debounce: 50 } - the defaults kept\n * ```\n *\n * @see deepMerge\n * @see execConfigFile\n * @see buildFromString\n * @see xBuildConfigInterface\n *\n * @since 3.0.0\n */\n\nexport async function configFileProvider<T extends xBuildConfigInterface>(path: string, argv: Record<string, unknown> = {}): Promise<T> {\n const fileObject = inject(FilesModel).touch(path);\n const text = fileObject.snapshot?.text;\n if (!text) return <T> {};\n\n const [ map, code ] = (await buildFromString(text, path, {\n minify: false,\n format: 'cjs',\n outdir: dirname(path),\n platform: 'node',\n logLevel: 'silent',\n packages: 'external',\n minifySyntax: true,\n minifyWhitespace: true,\n minifyIdentifiers: false\n })).outputFiles!;\n\n const argvService = inject(ArgvModule);\n inject(FrameworkService).addSourceMap(path, map.text, true);\n\n const preConfig = await execConfigFile<T>(code.text, path, {}, true);\n const args = argvService.enhancedParse(process.argv, preConfig.userArgv ?? {});\n\n Object.assign(argv, args);\n const config = await execConfigFile<T>(code.text, path, args);\n\n return deepMerge({} as T, {\n watch: {\n filter: [ '**/*.{js,ts,json}', '!**/*.d.ts' ],\n recursive: true\n }\n }, config as T);\n}\n"],"mappings":"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","names":["rmSync","process","inject","readFileSync","statSync","resolve","Injectable","FilesModel","path","encoding","target","stats","paths","pathList","resolve","info","entry","readFileSync","oldText","newText","oldLength","newLength","max","prefix","suffix","text","start","end","previous","statSync","__decorateClass","Injectable","resolveError","xterm","cwd","readFileSync","inject","Injectable","normalize","SourceService","FRAMEWORK_PATH_REGEX","EMPTY_MAPPINGS_REGEX","FrameworkService","normalize","cwd","path","inject","FilesModel","position","source","force","key","readFileSync","error","SourceService","__publicField","__decorateClass","Injectable","parseErrorStack","formatErrorCode","highlightCode","getSource","fileName","mapped","inject","FrameworkService","snapshot","FilesModel","code","lines","line","column","_bias","options","after","before","startLine","endLine","getErrorStack","raw","getErrorMetadata","verbose","framework","parsed","resolved","resolveError","path","frame","xterm","formatStack","metadata","name","message","notes","parts","note","stack","xBuildBaseError","message","name","error","options","getErrorMetadata","formatStack","formatErrors","reason","err","xBuildBaseError","metadata","getErrorMetadata","formatStack","process","exit","exec","readline","resolve","stdout","xterm","asciiLogo","bannerUi","prefix","inject","stripAnsi","cursorTo","clearScreenDown","dirname","relative","xterm","xterm","okColor","textColor","infoColor","warnColor","pathColor","errorColor","keywordColor","mutedColor","Levels","createActionPrefix","action","symbol","infoColor","prefix","visible","text","stripAnsi","pad","size","sourcePath","file","frameworkRoot","inject","FrameworkService","dirname","absolute","resolve","relative","formatLocation","line","column","separator","mutedColor","pathColor","warnColor","formatDetail","metadata","indent","root","lines","xterm","frame","describeMessage","message","code","typescript","getErrorMetadata","point","printGroup","messages","title","color","left","middle","rows","row","index","id","location","detail","tag","clearScreen","stdout","cursorTo","clearScreenDown","width","formatSize","bytes","printOutputs","metafile","limit","outputs","a","b","listed","sizes","right","total","sum","room","header","okColor","path","rest","more","platform","stdin","stdout","exit","xterm","ANSI","moveCursor","writeRaw","ShadowRenderer","OpenCommands","Keys","session","activity","row","repaint","cursorRow","resolve","answer","data","reported","stdin","writeRaw","stdout","openInBrowser","url","exec","platform","helpMenu","lines","keywordColor","key","describe","server","mutedColor","xterm","drawStatusBar","force","parts","infoColor","pathColor","ANSI","setActivity","text","startInteractive","screen","printed","claimRow","_","handleKey","stopInteractive","moveCursor","anchor","last","back","ShadowRenderer","width","exit","clearScreen","Injectable","inject","Injectable","BehaviorSubject","isObject","item","isPlainObject","prototype","deepMerge","target","sources","source","key","sourceValue","targetValue","equals","a","b","strictCheck","deepEquals","hasKey","obj","val","i","aKeys","bKeys","stringify","value","_","entry","map","distinctUntilChanged","DefaultsCommonConfig","ConfigurationService","initialConfig","DefaultsCommonConfig","BehaviorSubject","deepMerge","selector","observer","map","distinctUntilChanged","prev","curr","equals","partial","mergedConfig","config","__decorateClass","Injectable","ts","Injectable","normalize","relative","dirname","existsSync","parseSync","inject","mkdir","writeFile","join","dirname","relative","removeNode","node","content","edits","cursor","code","applyEdits","left","right","parts","index","i","edit","rewrite","source","target","ts","resolved","extension","relativeFileName","path","resolveSource","parse","statement","HeaderDeclarationBundle","DeclarationModel","ts","inject","FilesModel","path","target","file","cached","entry","entryPoints","outdir","outputs","contents","visited","names","name","pending","dependency","output","existsSync","options","base","join","node","directories","dirname","directory","mkdir","index","writeFile","source","declarationDir","outDir","rootDir","root","relative","closure","nested","exports","statements","binding","module","bindings","star","merged","clauses","surface","parts","HeaderDeclarationBundle","imports","content","service","version","declaration","context","parseSync","kept","body","statement","applyEdits","removeNode","moduleReference","named","exposed","local","bundleEdits","inner","comment","resolved","extension","relativeFileName","resolvedFileName","alias","start","end","code","ts","relative","inject","readdirSync","join","RegexCloser","lit","char","at","glob","index","isGlobstar","group","body","classEnd","openIndex","scan","lead","findClose","cursor","depth","braceClose","comma","compileClass","end","out","segmentEnd","from","compileFragment","isSegmentStart","alt","options","dot","wasStart","guard","DS","GLOBSTAR","nChar","RegexCloser","close","inner","tailEnd","tail","root","src","next","globToRegExp","createMatcher","globs","include","exclude","neg","path","r","collectFiles","base","FrameworkService","matcher","dotted","files","stack","directory","entries","readdirSync","join","entry","LanguageHostService","config","inject","FilesModel","file","path","paths","ts","encoding","extensions","exclude","include","depth","options","globs","createMatcher","target","excluded","relative","TypescriptService","configPath","LanguageHostService","ts","DeclarationModel","file","encoding","force","reloaded","path","entry","reachable","program","ignore","skip","affected","diagnostic","entryPoints","outdir","files","specifier","containingFile","container","dirname","cached","result","relative","key","normalize","instance","version","name","diagnostics","line","character","config","__publicField","__decorateClass","Injectable","Screen","build","inject","ConfigurationService","value","event","infoColor","mutedColor","keywordColor","createActionPrefix","errors","warnings","info","notes","metafile","failed","printOutputs","symbol","errorColor","okColor","name","warnColor","pathColor","diagnostics","logs","total","exit","reason","force","clearScreen","TypescriptService","activity","line","setActivity","lowest","Levels","code","printGroup","__decorateClass","Injectable","yargs","hideBin","Injectable","ArgsConfigPath","ArgsDefaultOptions","ArgsUsageExamples","ArgvModule","argv","yargs","ArgsDefaultOptions","userExtensions","parser","hideBin","originalShowHelp","consoleFunction","ArgsUsageExamples","command","description","__decorateClass","Injectable","inject","http","https","extname","readFileSync","server_default","join","inject","Subject","readdir","stat","readFile","ServerModule","config","dir","FrameworkService","Subject","inject","resolve","reject","err","address","req","res","options","readFileSync","join","defaultHandler","error","ext","requestPath","fullPath","stats","stat","fileList","readdir","file","extname","activePath","segments","path","htmlResult","server_default","contentType","data","readFile","inject","xBuildError","xBuildBaseError","message","options","Subject","parseSync","relative","inject","resolveLevel","overrides","id","level","key","collectLog","logs","message","resolved","collectLogs","messages","name","parseSync","inject","MacroPrefix","MacroScanHint","Macros","MacroFalsyDefines","MacroNameKeys","isDefined","defines","name","value","MacroFalsyDefines","defineDeclaration","code","target","prefix","call","suffix","callback","text","body","params","param","returns","head","defineExpression","statement","tail","analyzeMacros","files","defines","dropped","filesModel","inject","FilesModel","file","content","MacroScanHint","program","parseSync","node","declarator","call","directive","Macros","arg","isDefined","visitorKeys","createRequire","inject","Script","createContext","sandboxExecute","code","sandbox","options","isolateLogs","base","descriptors","context","cwd","build","dirname","basename","DefaultBuildOptions","buildFiles","buildOptions","build","cwd","DefaultBuildOptions","buildFromString","source","path","dirname","basename","analyzeDependencies","serialize","value","stringify","evaluate","state","call","target","thunk","map","output","buildFromString","module","inject","FrameworkService","sandboxExecute","createRequire","isNode","value","walk","node","visit","parent","key","keys","visitorKeys","childKey","item","report","state","offset","level","message","code","line","start","index","collectLog","record","span","text","defer","call","wrap","edit","evaluate","error","Macros","isMacroCall","name","flag","isActive","isDefined","isDropped","macroTarget","declaredMacro","declaration","id","init","target","pruneImport","named","parts","dropped","specifier","source","pruneExport","specifiers","kept","local","expandDeclaration","declared","suffix","prefix","defineDeclaration","expand","statement","defineExpression","expandNode","MacroNameKeys","transformMacros","parse","content","context","MacroScanHint","applyEdits","cwd","relative","extractEntryPoints","entryPoints","root","cwd","result","entry","prefix","relative","FrameworkService","scope","file","collectFiles","name","dot","TextBlocks","DiagnosticLevels","parseErrorStack","isEsbuildError","error","errors","first","errorToMessage","id","name","message","parsedStack","frame","VariantService","_VariantService","name","events$","argv","inject","ConfigurationService","config","error","FilesModel","metafile","analyzeDependencies","logs","xBuildError","context","result","buildFiles","messages","level","collectLogs","errorToMessage","call","handle","hook","declaration","entryPoints","outdir","common","variant","previous","deepMerge","TypescriptService","extractEntryPoints","options","type","source","target","key","value","content","stringify","diagnostics","failOnError","category","code","text","file","line","column","message","DiagnosticLevels","esbuild","types","args","path","loader","contents","parsed","parseSync","transformMacros","resolveSource","merged","buildResult","event","build","block","TextBlocks","files","analyzeMacros","isEsbuildError","rootDir","relative","dot","BuildService","config","argv","Subject","inject","ConfigurationService","names","variants","VariantService","variant","cache","start","run","name","path","xBuildError","dependOn","dependency","results","failed","_","index","result","TypescriptService","dependencies","errors","logs","buildResult","Injectable","Subject","resolve","join","relative","watch","realpathSync","readdirSync","lstatSync","statSync","WatchService","Subject","base","options","resolve","createMatcher","observerOrNext","error","complete","unsubscribe","watcher","batch","path","event","relativePath","relative","link","lstatSync","stats","statSync","type","ignore","recursive","watch","realpathSync","filename","target","join","seg","root","stack","dir","entries","readdirSync","entry","full","__decorateClass","Injectable","resolve","process","createRequire","dirname","inject","execConfigFile","code","path","$argv","isolation","module","sandboxExecute","createRequire","resolve","configFileProvider","argv","text","inject","FilesModel","map","buildFromString","dirname","argvService","ArgvModule","FrameworkService","preConfig","args","process","config","deepMerge","configureEntryPoints","config","args","applyCommandLineOverrides","commonOutDir","variants","variant","executeBuild","build","rmSync","startServer","screen","serveDir","server","ServerModule","startWatchMode","buildService","files","inject","FilesModel","configVersion","WatchService","changedFiles","configFileProvider","count","startInteractive","main","bannerUi","preConfig","ArgvModule","BuildService","Screen"]}