@remotex-labs/xbuild 2.3.2 → 2.4.1

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/index.d.ts CHANGED
@@ -3,8 +3,8 @@
3
3
  * DO NOT EDIT MANUALLY.
4
4
  */
5
5
 
6
- import ts, { CompilerOptions, DiagnosticCategory, IScriptSnapshot, LanguageService, ParsedCommandLine, ResolvedModuleWithFailedLookupLocations, SourceFile } from 'typescript';
7
6
  import { BuildOptions, BuildResult, Loader, Message, OnEndResult, OnLoadArgs, OnLoadResult, OnResolveArgs, OnResolveResult, OnStartResult, PartialMessage, Platform, PluginBuild } from 'esbuild';
7
+ import ts, { CompilerOptions, DiagnosticCategory, IScriptSnapshot, LanguageService, ParsedCommandLine, ResolvedModuleWithFailedLookupLocations, SourceFile } from 'typescript';
8
8
  import { IncomingMessage, ServerResponse } from 'http';
9
9
  import { ResolveMetadataInterface as xMapResolveMetadataInterface, ResolveOptionsInterface } from '@remotex-labs/xmap';
10
10
  import { Options } from 'yargs';
@@ -348,27 +348,36 @@ declare class BuildService {
348
348
  */
349
349
  typeChack(): Promise<Record<string, DiagnosticInterface[]>>;
350
350
  /**
351
- * Executes the build process for all or specific variants.
351
+ * Executes the build process for all or specific variants,
352
+ * respecting `dependOn` ordering and running independent variants in parallel.
352
353
  *
353
354
  * @param names - Optional array of variant names to build (builds all if omitted)
354
355
  *
355
356
  * @returns Promise resolving to a map of variant names to their enhanced build results
356
357
  *
358
+ * @throws xBuildError - When a circular dependency is detected before any build starts
357
359
  * @throws AggregateError - When any variant build fails, containing all error details
358
360
  *
359
361
  * @remarks
360
362
  * The build process:
361
- * 1. Filters variants if specific names are provided
362
- * 2. Builds all variants in parallel
363
- * 3. Collects results and errors from each variant
364
- * 4. Enhances build results with additional metadata
365
- * 5. Aggregates errors if any builds failed
366
- * 6. Throws AggregateError if errors occurred
363
+ * 1. Validates the dependency graph throws immediately on circular deps
364
+ * 2. Launches all requested variants concurrently
365
+ * 3. Each variant awaits its `dependOn` dependencies before running
366
+ * 4. Collects results and errors from each variant without stopping others
367
+ * 5. Enhances build results with additional metadata
368
+ * 6. Throws AggregateError if any builds failed
369
+ *
370
+ * **Dependency resolution**:
371
+ * - `dependOn` variants always finish before the dependent variant starts
372
+ * - A shared dependency (e.g. two variants both depending on `types`) builds
373
+ * only once — subsequent dependents await the same running promise
374
+ * - Independent variants run fully in parallel
367
375
  *
368
376
  * **Error handling**:
369
377
  * - Build failures don't stop other variants from building
370
- * - All errors are collected and thrown together after all builds are complete
371
- * - Supports both esbuild errors and generic JavaScript errors
378
+ * - All errors are collected into {@link BuildTreeInterface.errors} and thrown
379
+ * together after all builds complete
380
+ * - Supports both esbuild-specific errors and generic JavaScript errors
372
381
  *
373
382
  * **Result enhancement**:
374
383
  * Build results are processed by {@link enhancedBuildResult} to provide
@@ -392,22 +401,21 @@ declare class BuildService {
392
401
  * // Only production and staging variants are built
393
402
  * ```
394
403
  *
395
- * @example Handle individual variant errors
404
+ * @example With dependency ordering
396
405
  * ```ts
397
- * try {
398
- * await buildService.build();
399
- * } catch (error) {
400
- * if (error instanceof AggregateError) {
401
- * console.error(`${error.errors.length} variants failed`);
402
- * }
403
- * }
406
+ * // Given: main dependOn shared, shared dependOn types
407
+ * // Build order: types → shared → main (dependencies first)
408
+ * const results = await buildService.build();
404
409
  * ```
405
410
  *
411
+ * @see {@link buildVariant} for per-variant execution and caching logic
412
+ * @see {@link BuildTreeInterface}
406
413
  * @see {@link enhancedBuildResult}
407
414
  * @see {@link BuildResultInterface}
408
415
  * @see {@link VariantService.build}
416
+ * @see {@link validateDependencies} for circular dependency detection
409
417
  *
410
- * @since 2.0.0
418
+ * @since 2.4.0
411
419
  */
412
420
  build(names?: Array<string>): Promise<Record<string, BuildResultInterface>>;
413
421
  /**
@@ -504,778 +512,1167 @@ declare class BuildService {
504
512
  * @since 2.0.0
505
513
  */
506
514
  private parseVariants;
507
- }
508
- /**
509
- * Represents a cached TypeScript language service instance with reference counting for shared resource management.
510
- * Enables multiple consumers to share the same language service while tracking active usage through reference counts.
511
- *
512
- * @remarks
513
- * This interface is used internally by {@link TypescriptService} to implement a caching strategy that prevents
514
- * duplicate language service instances for the same configuration file. The lifecycle follows these rules:
515
- * - When a new service is created, `refCount` starts at 1
516
- * - Each additional consumer increments `refCount`
517
- * - Calling dispose decrements `refCount`
518
- * - When `refCount` reaches 0, the service is disposed and removed from cache
519
- *
520
- * The cached data includes all components needed to maintain a fully functional TypeScript compiler instance:
521
- * compiled configuration, language service host, and the language service itself.
522
- *
523
- * @example
524
- * ```ts
525
- * const cached: CachedServiceInterface = {
526
- * config: parsedConfig,
527
- * host: languageHost,
528
- * service: tsLanguageService,
529
- * refCount: 1
530
- * };
531
- *
532
- * // Another consumer acquires the same service
533
- * cached.refCount++; // Now 2
534
- *
535
- * // Consumers finish and dispose
536
- * cached.refCount--; // Now 1
537
- * cached.refCount--; // Now 0, triggers cleanup
538
- * ```
539
- *
540
- * @see {@link TypescriptService}
541
- * @see {@link LanguageHostService}
542
- *
543
- * @since 2.0.0
544
- */
545
- interface CachedServiceInterface {
546
515
  /**
547
- * Number of active consumers currently using this cached language service instance.
516
+ * Returns the normalized `dependOn` list for a variant.
548
517
  *
549
- * @remarks
550
- * This counter tracks how many TypeScript service instances are sharing this cached language service.
551
- * When it reaches zero, the service can be safely disposed of and removed from the cache.
518
+ * @param variantName - The variant to look up
552
519
  *
553
- * @since 2.0.0
554
- */
555
- refCount: number;
556
- /**
557
- * Language service host managing file system operations and compiler options for this instance.
558
- * @since 2.0.0
559
- */
560
- host: LanguageHostService;
561
- /**
562
- * TypeScript language service providing type checking, analysis, and compilation capabilities.
563
- * @since 2.0.0
564
- */
565
- service: LanguageService;
566
- /**
567
- * Parsed TypeScript configuration including compiler options, file names, and project references.
520
+ * @returns Array of dependency variant names, empty if none defined
568
521
  *
569
522
  * @remarks
570
- * This configuration is reloaded when the `tsconfig.json` file changes, ensuring the cached
571
- * service stays synchronized with the project's compilation settings.
523
+ * Normalizes the `dependOn` field from the variant configuration into
524
+ * a consistent array form, since the field accepts either a single
525
+ * string or an array of strings.
572
526
  *
573
- * @since 2.0.0
527
+ * @see {@link buildVariant}
528
+ * @see {@link validateDependencies}
529
+ *
530
+ * @since 2.4.0
574
531
  */
575
- config: ParsedCommandLine;
576
- }
577
- /**
578
- * Represents formatted diagnostic information from TypeScript compilation, including errors, warnings, and suggestions.
579
- * Provides a simplified interface for displaying compiler messages with optional source location details.
580
- *
581
- * @remarks
582
- * This interface normalizes TypeScript's diagnostic format into a structure suitable for display in logs,
583
- * editor integrations, or build output. All location information (file, line, column) is optional because
584
- * some diagnostics apply globally or lack specific source positions.
585
- *
586
- * Line and column numbers are 1-indexed to match standard editor conventions, even though TypeScript
587
- * internally uses 0-indexed positions.
588
- *
589
- * @example
590
- * ```ts
591
- * const diagnostic: DiagnosticInterface = {
592
- * file: 'src/index.ts',
593
- * line: 42,
594
- * column: 15,
595
- * code: 2304,
596
- * message: "Cannot find name 'unknownVariable'."
597
- * };
598
- *
599
- * console.log(`${diagnostic.file}:${diagnostic.line}:${diagnostic.column}`);
600
- * console.log(`TS${diagnostic.code}: ${diagnostic.message}`);
601
- * ```
602
- *
603
- * @see {@link TypescriptService.check}
604
- * @see {@link TypescriptService.formatDiagnostic}
605
- *
606
- * @since 2.0.0
607
- */
608
- interface DiagnosticInterface {
532
+ private getDependOn;
609
533
  /**
610
- * File path where the diagnostic occurred.
534
+ * Validates the dependency graph for all or specific variants before building starts.
611
535
  *
612
- * @remarks
613
- * Optional because some diagnostics are configuration-level errors that don't relate to a specific file.
536
+ * @param names - Optional subset of variant names to validate (validates all if omitted)
614
537
  *
615
- * @since 2.0.0
616
- */
617
- file?: string;
618
- /**
619
- * Line number where the diagnostic occurred, 1-indexed.
538
+ * @throws xBuildError - When a circular dependency is detected, with the full cycle
539
+ * path included in the message (e.g. `Circular dependency detected: main → shared → main`)
620
540
  *
621
541
  * @remarks
622
- * Optional because diagnostics without source location (like config errors) won't have line information.
623
- * When present, this value is 1-indexed to match standard editor conventions.
542
+ * Performs a depth-first traversal of the dependency graph using two sets:
543
+ * - `visited` variants fully processed, skipped on revisit
544
+ * - `inStack` — variants in the current traversal path, used to detect cycles
624
545
  *
625
- * @since 2.0.0
546
+ * Dependencies that exist in `dependOn` but have no matching variant instance
547
+ * in {@link variants} are silently skipped.
548
+ *
549
+ * Called by {@link build} before any variant starts, ensuring the entire
550
+ * graph is valid before any work begins.
551
+ *
552
+ * @see {@link build}
553
+ * @see {@link getDependOn}
554
+ *
555
+ * @since 2.4.0
626
556
  */
627
- line?: number;
557
+ private validateDependencies;
628
558
  /**
629
- * Column number where the diagnostic occurred, 1-indexed.
559
+ * Executes the build for a single variant after all its dependencies resolve.
560
+ *
561
+ * @param name - Variant name to build
562
+ * @param ctx - Isolated build context for this {@link build} invocation
630
563
  *
631
564
  * @remarks
632
- * Optional because diagnostics without source location won't have column information.
633
- * When present, this value is 1-indexed to match standard editor conventions.
565
+ * Called exclusively by {@link buildVariant} after the promise is registered
566
+ * in {@link BuildTreeInterface.cache}, preventing re-entry.
634
567
  *
635
- * @since 2.0.0
568
+ * Awaits all `dependOn` dependencies concurrently via `Promise.all` before
569
+ * running the variant. Dependencies missing from {@link variants} are silently skipped.
570
+ *
571
+ * Errors are pushed into {@link BuildTreeInterface.errors} rather than thrown,
572
+ * so all variants attempt to build even if a sibling fails. Handles both
573
+ * esbuild-specific errors via {@link isBuildResultError} and generic JavaScript errors.
574
+ *
575
+ * @see {@link buildVariant}
576
+ * @see {@link getDependOn}
577
+ * @see {@link isBuildResultError}
578
+ * @see {@link BuildTreeInterface}
579
+ * @see {@link enhancedBuildResult}
580
+ *
581
+ * @since 2.4.0
636
582
  */
637
- column?: number;
583
+ private executeBuild;
638
584
  /**
639
- * TypeScript diagnostic code identifying the specific error or warning type.
585
+ * Builds a single variant, first awaiting any `dependOn` dependencies.
586
+ *
587
+ * @param name - Variant name to build
588
+ * @param ctx - Isolated build context for this {@link build} invocation,
589
+ * carrying the promise cache, error list, and results map
590
+ *
591
+ * @returns Promise that resolves when the variant and all its dependencies finish
640
592
  *
641
593
  * @remarks
642
- * Optional because not all diagnostics have associated error codes. When present, this can be used
643
- * to look up detailed documentation or implement diagnostic-specific handling.
594
+ * Stores its promise in {@link BuildTreeInterface.cache} on first call so any
595
+ * subsequent caller depending on the same variant awaits the already-running
596
+ * promise rather than triggering a duplicate build.
644
597
  *
645
- * @example
646
- * Common codes include 2304 (cannot find name), 2322 (type not assignable), 2307 (cannot find module).
598
+ * Delegates actual execution to {@link executeBuild} after registering the promise,
599
+ * ensuring the cache is populated before any async work begins.
647
600
  *
648
- * @since 2.0.0
601
+ * @see {@link build}
602
+ * @see {@link executeBuild}
603
+ * @see {@link BuildTreeInterface}
604
+ *
605
+ * @since 2.4.0
649
606
  */
650
- code?: number;
607
+ private buildVariant;
608
+ }
609
+ /**
610
+ * Options used to reload the build service configuration.
611
+ *
612
+ * @remarks
613
+ * These options control how configuration reload behaves:
614
+ * - `config` replaces the current build configuration
615
+ * - `clearCache` clears cached file and TypeScript language service state before reloading
616
+ *
617
+ * @since 2.3.0
618
+ */
619
+ interface ReloadOptionsInterface {
651
620
  /**
652
- * Human-readable diagnostic message describing the error, warning, or suggestion.
621
+ * Optional new configuration to replace the current one.
653
622
  *
654
623
  * @remarks
655
- * This message is flattened from TypeScript's potentially nested diagnostic message structure
656
- * using newline separators for multi-line messages.
624
+ * When provided, the build service reloads using this configuration
625
+ * before recalculating variants.
657
626
  *
658
- * @since 2.0.0
627
+ * @since 2.3.0
659
628
  */
660
- message: string;
629
+ config?: PartialBuildConfigType;
661
630
  /**
662
- * Category of the diagnostic indicating its severity level.
631
+ * Whether to clear cached files and TypeScript language service state before reloading.
663
632
  *
664
633
  * @remarks
665
- * Determines how the diagnostic should be treated and displayed. TypeScript uses this to distinguish
666
- * between different severity levels:
667
- * - `DiagnosticCategory.Error` (1): Compilation-blocking errors
668
- * - `DiagnosticCategory.Warning` (0): Non-blocking warnings
669
- * - `DiagnosticCategory.Suggestion` (2): Code improvement suggestions
670
- * - `DiagnosticCategory.Message` (3): Informational messages
671
- *
672
- * This property is essential for filtering diagnostics by severity and determining whether
673
- * a build should fail or continue.
674
- *
675
- * @example
676
- * ```ts
677
- * if (diagnostic.category === DiagnosticCategory.Error) {
678
- * console.error(`Error: ${diagnostic.message}`);
679
- * process.exit(1);
680
- * }
681
- * ```
634
+ * When enabled, cached file tracking and language service state are reset
635
+ * before the configuration is reloaded.
682
636
  *
683
- * @since 2.0.0
637
+ * @since 2.3.0
684
638
  */
685
- category: DiagnosticCategory;
639
+ clearCache?: boolean;
686
640
  }
687
641
  /**
688
- * Implements a TypeScript Language Service host with file snapshot caching and module resolution.
642
+ * Isolated state container for a single {@link BuildService.build} invocation.
689
643
  *
690
644
  * @remarks
691
- * The `LanguageHostService` implements the {@link ts.LanguageServiceHost} interface to provide
692
- * TypeScript's language service with file system access, file snapshots, and compiler configuration.
693
- *
694
- * @example
695
- * ```ts
696
- * // Initialize with compiler options
697
- * const host = new LanguageHostService({
698
- * target: ts.ScriptTarget.ES2020,
699
- * module: ts.ModuleKind.ESNext,
700
- * paths: {
701
- * '@utils/*': ['src/utils/*'],
702
- * '@components/*': ['src/components/*']
703
- * }
704
- * });
705
- *
706
- * // Track files for analysis
707
- * host.touchFile('src/index.ts');
708
- * host.touchFiles(['src/utils.ts', 'src/types.ts']);
709
- *
710
- * // Get file snapshots for language service
711
- * const snapshot = host.getScriptSnapshot('src/index.ts');
645
+ * Created fresh on every `build()` call to ensure concurrent watch-mode
646
+ * rebuilds cannot share or overwrite each other's state.
712
647
  *
713
- * // Resolve module imports
714
- * const resolved = host.resolveModuleName('@utils/helpers', 'src/index.ts');
715
- *
716
- * // Check for path aliases
717
- * const hasAliases = host.aliasRegex !== undefined;
718
- *
719
- * // Update configuration
720
- * host.options = { target: ts.ScriptTarget.ES2022 };
721
- * ```
648
+ * Passed through {@link BuildService.buildVariant} to carry the promise
649
+ * cache, accumulated errors, and collected results across the full
650
+ * dependency graph traversal.
722
651
  *
723
- * @see {@link ts.LanguageServiceHost} for the implemented interface specification
724
- * @see {@link FilesModel} for file snapshot caching implementation
652
+ * @see {@link BuildService.build}
653
+ * @see {@link BuildService.buildVariant}
725
654
  *
726
- * @since 2.0.0
655
+ * @since 2.4.0
727
656
  */
728
- declare class LanguageHostService implements ts.LanguageServiceHost {
729
- private compilerOptions;
657
+ interface BuildTreeInterface {
730
658
  /**
731
- * Reference to TypeScript's system interface for file operations.
659
+ * Promise cache keyed by variant name.
732
660
  *
733
661
  * @remarks
734
- * Static reference to `ts.sys` that provides abstracted file system operations
735
- * (read, write, directory traversal) compatible with different environments (Node.js, browsers, etc.).
736
- * Used for all file I/O operations in this service to maintain platform independence.
737
- *
738
- * @see {@link ts.sys}
662
+ * Ensures each variant builds exactly once per `build()` call.
663
+ * Subsequent callers depending on the same variant await the
664
+ * already-running promise instead of triggering a duplicate build.
739
665
  *
740
- * @since 2.0.0
666
+ * @since 2.4.0
741
667
  */
742
- private static readonly sys;
668
+ cache: Map<string, Promise<void>>;
743
669
  /**
744
- * Cached regular expression for matching import/export statements with path aliases.
670
+ * Accumulated build errors across all variants.
745
671
  *
746
672
  * @remarks
747
- * Compiled from `compilerOptions.paths` to efficiently detect imports using path aliases.
748
- * Regenerated when compiler options change. Undefined if no path aliases are configured.
749
- *
750
- * Used by tools that need to identify which import statements use aliases for proper
751
- * handling during transformation or bundling.
673
+ * Errors are pushed here rather than thrown immediately, so all
674
+ * variants attempt to build even if a sibling fails. Thrown together
675
+ * as an `AggregateError` after all builds complete.
752
676
  *
753
- * @see {@link generateAliasRegex} for pattern generation
754
- *
755
- * @since 2.0.0
677
+ * @since 2.4.0
756
678
  */
757
- private alias;
679
+ errors: Array<Error>;
758
680
  /**
759
- * Cache for resolved module specifiers.
681
+ * Collected build results keyed by variant name.
760
682
  *
761
683
  * @remarks
762
- * Stores the absolute resolved file path for each module name so repeated lookups
763
- * do not trigger TypeScript module resolution again. A value of `undefined` means
764
- * the module could not be resolved and that result is cached too.
765
- *
766
- * This cache is keyed by the raw import specifier, so it is only safe when the
767
- * same specifier is resolved in a compatible context.
684
+ * Populated by {@link BuildService.buildVariant} as each variant
685
+ * finishes. Only contains results for variants that built successfully.
768
686
  *
769
- * @since 2.3.0
687
+ * @since 2.4.0
770
688
  */
771
- private aliasCache;
772
- /**
773
- * Cache for TypeScript module resolution results.
774
- *
775
- * @remarks
776
- * TypeScript's internal module resolution cache that stores resolution results to avoid
777
- * redundant lookups. Improves performance significantly when resolving many imports,
778
- * especially in large projects with complex path mappings.
689
+ results: Record<string, BuildResultInterface>;
690
+ }
691
+ /**
692
+ * Extended build result interface with normalized error and warning arrays.
693
+ *
694
+ * @remarks
695
+ * This interface extends esbuild's {@link BuildResult} while replacing the `errors` and `warnings`
696
+ * properties with normalized Error instances instead of esbuild's Message objects. This normalization
697
+ * provides consistent error handling throughout the xBuild system with proper stack traces, formatting,
698
+ * and error classification.
699
+ *
700
+ * **Key differences from esbuild's BuildResult**:
701
+ * - `errors`: Changed from `Message[]` to `Error[]` with normalized error types
702
+ * - `warnings`: Changed from `Message[]` to `Error[]` with normalized error types
703
+ * - All other properties (metafile, outputFiles, mangleCache) are preserved unchanged
704
+ *
705
+ * **Benefits of normalization**:
706
+ * - Consistent error handling across different error sources (esbuild, TypeScript, VM runtime)
707
+ * - Proper error inheritance and type checking
708
+ * - Rich stack trace information with source mapping
709
+ * - Formatted error output with syntax highlighting
710
+ * - Integration with xBuild's custom error classes
711
+ *
712
+ * The normalized errors may include:
713
+ * - {@link TypesError} for TypeScript type checking failures
714
+ * - {@link xBuildError} for text errors during build hooks
715
+ * - {@link esBuildError} for esbuild compilation errors with location information
716
+ * - {@link VMRuntimeError} for runtime errors during build hooks
717
+ * - {@link xBuildBaseError} for custom build system errors
718
+ *
719
+ * @example
720
+ * ```ts
721
+ * const result: BuildResultInterface = {
722
+ * errors: [
723
+ * new esBuildError(esbuildMessage),
724
+ * new TypesError('Type checking failed', diagnostics)
725
+ * ],
726
+ * warnings: [
727
+ * new xBuildError('Deprecation warning')
728
+ * ],
729
+ * metafile: { ... },
730
+ * outputFiles: [ ... ],
731
+ * mangleCache: { ... }
732
+ * };
733
+ * ```
734
+ *
735
+ * @see {@link BuildResult} from esbuild for the base interface
736
+ *
737
+ * @since 2.0.0
738
+ */
739
+ interface BuildResultInterface extends Omit<BuildResult, 'errors' | 'warnings'> {
740
+ /**
741
+ * Array of normalized error instances encountered during the build.
779
742
  *
780
- * Recreated when compiler options change (since different options may affect resolution).
743
+ * @remarks
744
+ * Contains Error instances converted from esbuild messages and other error sources.
745
+ * Unlike esbuild's native error array which contains Message objects, this array
746
+ * contains fully normalized Error instances with proper stack traces and formatting.
781
747
  *
782
- * @see {@link ts.createModuleResolutionCache}
748
+ * Errors in this array may originate from:
749
+ * - Compilation errors (syntax, resolution failures)
750
+ * - Type checking failures
751
+ * - Build hook execution errors
752
+ * - Plugin errors
753
+ *
754
+ * @example
755
+ * ```ts
756
+ * if (result.errors.length > 0) {
757
+ * console.error(`Build failed with ${result.errors.length} errors`);
758
+ * result.errors.forEach(err => console.error(err.stack));
759
+ * }
760
+ * ```
783
761
  *
784
762
  * @since 2.0.0
785
763
  */
786
- private moduleResolutionCache;
764
+ errors: Array<Error>;
787
765
  /**
788
- * A set containing the file paths of all actively tracked script files.
766
+ * Array of normalized warning instances encountered during the build.
789
767
  *
790
768
  * @remarks
791
- * This set ensures that files are tracked for later operations, such as retrieving script versions
792
- * or snapshots. Files are added to this set when they are first processed or read by the service.
769
+ * Contains Error instances converted from esbuild warning messages and other warning sources.
770
+ * Unlike esbuild's native warning array which contains Message objects, this array
771
+ * contains fully normalized Error instances with proper stack traces and formatting.
772
+ *
773
+ * Warnings indicate non-fatal issues that don't prevent build completion but may
774
+ * require attention, such as:
775
+ * - Deprecated API usage
776
+ * - Type checking warnings
777
+ * - Performance concerns
778
+ * - Potential runtime issues
793
779
  *
794
780
  * @example
795
781
  * ```ts
796
- * trackFiles.add('/src/main.ts');
797
- * console.log(trackFiles.has('/src/main.ts')); // true
782
+ * if (result.warnings.length > 0) {
783
+ * console.warn(`Build completed with ${result.warnings.length} warnings`);
784
+ * result.warnings.forEach(warn => console.warn(warn.message));
785
+ * }
798
786
  * ```
799
787
  *
800
- * @see {@link getScriptFileNames} - Retrieves all tracked files.
788
+ * @since 2.0.0
789
+ */
790
+ warnings: Array<Error>;
791
+ }
792
+ /**
793
+ * Recursively makes all properties of a type optional.
794
+ *
795
+ * @remarks
796
+ * This utility type behaves like TypeScript’s built-in {@link Partial} type,
797
+ * but applies recursively to all nested object properties.
798
+ *
799
+ * It is commonly used for:
800
+ * - Partial configuration overrides
801
+ * - Patch / update objects
802
+ * - Programmatic configuration merging
803
+ * - Build variant and preset definitions
804
+ *
805
+ * This type only affects compile-time type checking and has no runtime impact.
806
+ *
807
+ * ⚠️ **Important limitations**:
808
+ * - Arrays and functions are treated as objects and will also be recursively
809
+ * transformed. If this is undesirable, a more specialized deep-partial
810
+ * implementation should be used.
811
+ * - Intended for configuration and data-shaping use cases, not strict domain models.
812
+ *
813
+ * @example
814
+ * ```ts
815
+ * interface Config {
816
+ * server: {
817
+ * host: string;
818
+ * port: number;
819
+ * };
820
+ * features: {
821
+ * experimental: boolean;
822
+ * };
823
+ * }
824
+ *
825
+ * const override: DeepPartialType<Config> = {
826
+ * server: {
827
+ * port: 8080
828
+ * }
829
+ * };
830
+ * ```
831
+ *
832
+ * @template T - The type to recursively make optional.
833
+ *
834
+ * @since 2.0.0
835
+ */
836
+ type DeepPartialType<T> = {
837
+ [K in keyof T]?: T[K] extends object ? DeepPartialType<T[K]> : T[K];
838
+ };
839
+ /**
840
+ * Represents code that can be injected into build output as a banner or footer.
841
+ * Can be a static string or a function that generates code dynamically based on build context.
842
+ *
843
+ * @remarks
844
+ * This type provides flexibility for injecting code at the top (banner) or bottom (footer) of
845
+ * bundled output files. The function form receives the plugin name and command-line arguments,
846
+ * allowing for context-aware code generation.
847
+ *
848
+ * Common use cases:
849
+ * - Static banners: Copyright notices, license headers, version information
850
+ * - Dynamic banners: Build timestamps, environment-specific code, conditional imports
851
+ * - Footer code: Analytics snippets, polyfills, initialization scripts
852
+ *
853
+ * When using the function form, the generated string is cached per build variant to avoid
854
+ * regenerating the same code multiple times.
855
+ *
856
+ * @example
857
+ * ```ts
858
+ * // Static banner
859
+ * const banner: InjectableCodeType = '\/* Copyright 2024 *\/';
860
+ *
861
+ * // Dynamic banner
862
+ * const banner: InjectableCodeType = (name, argv) => {
863
+ * const version = argv.version || '1.0.0';
864
+ * return `\/* Built by ${name} v${version} at ${new Date().toISOString()} *\/`;
865
+ * };
866
+ * ```
867
+ *
868
+ * @see {@link BaseBuildDefinitionInterface.banner}
869
+ * @see {@link BaseBuildDefinitionInterface.footer}
870
+ *
871
+ * @since 2.0.0
872
+ */
873
+ type InjectableCodeType = string | ((name: string, argv: Record<string, unknown>) => string);
874
+ /**
875
+ * Defines lifecycle hook handlers for build process stages.
876
+ * Allows registration of custom logic during resolution, loading, build start, build end, and success.
877
+ *
878
+ * @remarks
879
+ * This interface groups all available lifecycle hooks in a single configuration object.
880
+ * All hooks are optional, allowing selective registration of only necessary handlers.
881
+ *
882
+ * Hook execution order during a build:
883
+ * 1. `onStart` - Before any file processing
884
+ * 2. `onResolve` - During import path resolution
885
+ * 3. `onLoad` - When loading file contents
886
+ * 4. `onEnd` - After build completes (success or failure)
887
+ * 5. `onSuccess` - After a build completes successfully
888
+ *
889
+ * Each hook receives a specialized context object appropriate for its lifecycle stage, providing
890
+ * access to build configuration, variant information, and cross-hook communication through the
891
+ * shared stage object.
892
+ *
893
+ * @example
894
+ * ```ts
895
+ * const hooks: LifecycleHooksInterface = {
896
+ * onStart: async (context) => {
897
+ * console.log(`${context.variantName} build starting...`);
898
+ * },
899
+ * onLoad: async (context) => {
900
+ * if (context.args.path.endsWith('.custom')) {
901
+ * return { contents: transform(context.contents), loader: 'ts' };
902
+ * }
903
+ * },
904
+ * onSuccess: async (context) => {
905
+ * console.log(`Build succeeded in ${context.duration}ms!`);
906
+ * }
907
+ * };
908
+ * ```
909
+ *
910
+ * @see {@link OnEndType}
911
+ * @see {@link OnLoadType}
912
+ * @see {@link OnStartType}
913
+ * @see {@link OnResolveType}
914
+ *
915
+ * @since 2.0.0
916
+ */
917
+ interface LifecycleHooksInterface {
918
+ /**
919
+ * Hook handler executed when the build completes, regardless of success or failure.
920
+ *
921
+ * @remarks
922
+ * Called after all build operations finish with a result context containing the build result,
923
+ * calculated duration, variant name, arguments, and stage state. Useful for cleanup, logging,
924
+ * reporting, and post-processing.
925
+ *
926
+ * The handler receives `ResultContextInterface` providing access to:
927
+ * - `buildResult`: Final build outcome with errors and warnings
928
+ * - `duration`: Build duration in milliseconds
929
+ * - `variantName`: Build variant identifier
930
+ * - `argv`: Command-line arguments and configuration
931
+ * - `stage`: Shared state object for cross-hook communication
932
+ *
933
+ * @example
934
+ * ```ts
935
+ * onEnd: async (context) => {
936
+ * const { buildResult, duration, variantName } = context;
937
+ * console.log(`${variantName} completed in ${duration}ms`);
938
+ * if (buildResult.errors.length > 0) {
939
+ * // Handle errors
940
+ * }
941
+ * }
942
+ * ```
943
+ *
944
+ * @see {@link ResultContextInterface}
801
945
  *
802
946
  * @since 2.0.0
803
947
  */
804
- private readonly trackFiles;
948
+ onEnd?: OnEndType;
805
949
  /**
806
- * Model for managing file snapshots and version tracking.
950
+ * Hook handler executed when loading file contents during module processing.
807
951
  *
808
952
  * @remarks
809
- * Delegates file snapshot management to {@link FilesModel} for centralized
810
- * caching and change detection. Snapshots are tracked by modification time
811
- * to detect file changes efficiently.
953
+ * Called for each file being processed with a load context containing the current file contents
954
+ * (potentially transformed by previous hooks), loader type, load arguments, variant name, and
955
+ * stage state. Can transform contents and change the loader type. Multiple handlers execute in
956
+ * a pipeline pattern where each receives the output of previous hooks.
812
957
  *
813
- * @see {@link FilesModel}
958
+ * The handler receives `LoadContextInterface` providing access to:
959
+ * - `contents`: Current file contents (string or binary)
960
+ * - `loader`: Current loader type (e.g., 'ts', 'js', 'json')
961
+ * - `args`: Load arguments including file path and namespace
962
+ * - `variantName`: Build variant identifier
963
+ * - `argv`: Command-line arguments and configuration
964
+ * - `stage`: Shared state object for cross-hook communication
965
+ *
966
+ * @example
967
+ * ```ts
968
+ * onLoad: async (context) => {
969
+ * const { contents, args, variantName } = context;
970
+ * if (args.path.endsWith('.custom')) {
971
+ * return {
972
+ * contents: transform(contents.toString()),
973
+ * loader: 'ts'
974
+ * };
975
+ * }
976
+ * }
977
+ * ```
978
+ *
979
+ * @see {@link LoadContextInterface}
814
980
  *
815
981
  * @since 2.0.0
816
982
  */
817
- private readonly filesCache;
983
+ onLoad?: OnLoadType;
818
984
  /**
819
- * Initializes a new {@link LanguageHostService} instance.
985
+ * Hook handler executed when the build process begins.
820
986
  *
821
- * @param compilerOptions - Optional TypeScript compiler options (defaults to an empty object)
987
+ * @remarks
988
+ * Called before any file processing starts with a build context containing the esbuild build object,
989
+ * variant name, arguments, and stage state. Useful for initialization, validation, and setup tasks.
990
+ *
991
+ * The handler receives `BuildContextInterface` providing access to:
992
+ * - `build`: esbuild plugin build object with configuration and utilities
993
+ * - `variantName`: Build variant identifier
994
+ * - `argv`: Command-line arguments and configuration
995
+ * - `stage`: Shared state object for cross-hook communication
996
+ *
997
+ * @example
998
+ * ```ts
999
+ * onStart: async (context) => {
1000
+ * const { build, variantName, stage } = context;
1001
+ * console.log(`Starting ${variantName} build`);
1002
+ * stage.startTime = new Date();
1003
+ *
1004
+ * // Validate configuration
1005
+ * if (!build.initialOptions.outdir) {
1006
+ * return { errors: [{ text: 'Output directory required' }] };
1007
+ * }
1008
+ * }
1009
+ * ```
1010
+ *
1011
+ * @see {@link BuildContextInterface}
1012
+ *
1013
+ * @since 2.0.0
1014
+ */
1015
+ onStart?: OnStartType;
1016
+ /**
1017
+ * Hook handler executed when the build completes successfully without errors.
822
1018
  *
823
1019
  * @remarks
824
- * Performs initialization including:
825
- * 1. Stores compiler options for later use
826
- * 2. Generates path alias regex from options if configured
827
- * 3. Creates module resolution cache with appropriate settings
1020
+ * Only called when `buildResult.errors.length === 0`, after all regular end hooks have completed.
1021
+ * Receives the same result context as end hooks, containing build result, duration, variant name,
1022
+ * arguments, and stage state. Useful for deployment, success notifications, and success-only operations.
828
1023
  *
829
- * The module resolution cache is necessary for efficient resolution of imports in large projects.
830
- * Path alias regex is generated up-front and cached for performance.
1024
+ * The handler receives `ResultContextInterface` providing access to:
1025
+ * - `buildResult`: Final build outcome (guaranteed to have zero errors)
1026
+ * - `duration`: Build duration in milliseconds
1027
+ * - `variantName`: Build variant identifier
1028
+ * - `argv`: Command-line arguments and configuration
1029
+ * - `stage`: Shared state object for cross-hook communication
831
1030
  *
832
1031
  * @example
833
1032
  * ```ts
834
- * // Create host with default options
835
- * const host = new LanguageHostService();
1033
+ * onSuccess: async (context) => {
1034
+ * const { buildResult, duration, variantName } = context;
1035
+ * console.log(`${variantName} succeeded in ${duration}ms!`);
1036
+ * await deploy(buildResult.metafile);
1037
+ * }
1038
+ * ```
836
1039
  *
837
- * // Create host with specific compiler options
838
- * const host = new LanguageHostService({
839
- * target: ts.ScriptTarget.ES2020,
840
- * module: ts.ModuleKind.ESNext,
841
- * paths: {
842
- * '@utils/*': ['src/utils/*']
1040
+ * @see {@link ResultContextInterface}
1041
+ *
1042
+ * @since 2.0.0
1043
+ */
1044
+ onSuccess?: OnEndType;
1045
+ /**
1046
+ * Hook handler executed during module path resolution.
1047
+ *
1048
+ * @remarks
1049
+ * Called when resolving import paths to file system locations with a resolve context containing
1050
+ * the resolution arguments, variant name, and stage state. Can redirect imports, mark modules as
1051
+ * external, or implement custom resolution logic. Multiple handlers execute, and their results are
1052
+ * merged, with later hooks able to override earlier ones.
1053
+ *
1054
+ * The handler receives `ResolveContextInterface` providing access to:
1055
+ * - `args`: Resolution arguments including import path and importer info
1056
+ * - `variantName`: Build variant identifier
1057
+ * - `argv`: Command-line arguments and configuration
1058
+ * - `stage`: Shared state object for cross-hook communication
1059
+ *
1060
+ * @example
1061
+ * ```ts
1062
+ * onResolve: async (context) => {
1063
+ * const { args, variantName } = context;
1064
+ *
1065
+ * // Redirect '@/' imports to 'src/'
1066
+ * if (args.path.startsWith('@/')) {
1067
+ * return {
1068
+ * path: resolve('src', args.path.slice(2)),
1069
+ * namespace: 'file'
1070
+ * };
843
1071
  * }
844
- * });
1072
+ *
1073
+ * // Mark as external in production
1074
+ * if (variantName === 'production' && args.path.includes('node_modules')) {
1075
+ * return { path: args.path, external: true };
1076
+ * }
1077
+ * }
845
1078
  * ```
846
1079
  *
1080
+ * @see {@link ResolveContextInterface}
1081
+ *
847
1082
  * @since 2.0.0
848
1083
  */
849
- constructor(compilerOptions?: CompilerOptions);
1084
+ onResolve?: OnResolveType;
1085
+ }
1086
+ /**
1087
+ * Configuration options for TypeScript declaration file generation.
1088
+ *
1089
+ * @remarks
1090
+ * Controls how and where TypeScript declaration files (`.d.ts`) are generated during the build.
1091
+ * These options work in conjunction with the TypeScript compiler to produce type definitions
1092
+ * for bundled code.
1093
+ *
1094
+ * When `bundle` is true, declarations from multiple source files are combined into a single
1095
+ * declaration file per entry point. When false, individual declaration files are generated
1096
+ * for each source file.
1097
+ *
1098
+ * @example
1099
+ * ```ts
1100
+ * // Generate bundled declarations in custom directory
1101
+ * const options: DeclarationOptionsInterface = {
1102
+ * outDir: 'types',
1103
+ * bundle: true
1104
+ * };
1105
+ * ```
1106
+ *
1107
+ * @see {@link BaseBuildDefinitionInterface.declaration}
1108
+ *
1109
+ * @since 2.0.0
1110
+ */
1111
+ interface DeclarationOptionsInterface {
1112
+ /**
1113
+ * Output directory for generated declaration files.
1114
+ *
1115
+ * @remarks
1116
+ * Specifies where `.d.ts` files should be written. If not provided, uses the TypeScript
1117
+ * compiler's `declarationDir` or `outDir` from `tsconfig.json`.
1118
+ *
1119
+ * @example
1120
+ * ```ts
1121
+ * outDir: 'dist/types'
1122
+ * ```
1123
+ *
1124
+ * @since 2.0.0
1125
+ */
1126
+ outDir?: string;
1127
+ /**
1128
+ * Whether to bundle declarations into a single file per entry point.
1129
+ *
1130
+ * @remarks
1131
+ * When true, combines all declarations from imported modules into a single `.d.ts` file.
1132
+ * When false, generates individual declaration files mirroring the source structure.
1133
+ *
1134
+ * Bundling is useful for library distribution as it provides a single type definition file
1135
+ * that consumers can reference.
1136
+ *
1137
+ * @example
1138
+ * ```ts
1139
+ * bundle: true // Produces single bundled .d.ts
1140
+ * bundle: false // Produces multiple .d.ts files
1141
+ * ```
1142
+ *
1143
+ * @since 2.0.0
1144
+ */
1145
+ bundle?: boolean;
1146
+ }
1147
+ /**
1148
+ * Configuration options for TypeScript type checking during builds.
1149
+ *
1150
+ * @remarks
1151
+ * Controls how TypeScript type checking is performed and whether type errors should fail the build.
1152
+ * Type checking runs in parallel with the esbuild compilation process for better performance.
1153
+ *
1154
+ * @example
1155
+ * ```ts
1156
+ * // Fail build on type errors
1157
+ * const options: TypeCheckOptionsInterface = {
1158
+ * failOnError: true
1159
+ * };
1160
+ * ```
1161
+ *
1162
+ * @see {@link BaseBuildDefinitionInterface.types}
1163
+ *
1164
+ * @since 2.0.0
1165
+ */
1166
+ interface TypeCheckOptionsInterface {
850
1167
  /**
851
- * Regular expression that matches import/export statements using path aliases (if `paths` is configured).
1168
+ * Whether to fail the build when TypeScript errors are detected.
852
1169
  *
853
1170
  * @remarks
854
- * Used mainly for advanced refactoring or rewrite tools that need to identify aliased imports.
1171
+ * When true, any TypeScript errors will cause the build to fail with a non-zero exit code.
1172
+ * When false, errors are logged, but the build continues and succeeds.
855
1173
  *
856
- * @since 2.0.0
857
- */
858
- get aliasRegex(): RegExp | undefined;
859
- /**
860
- * Replaces current compiler options and regenerates derived state (alias regex, module cache).
1174
+ * Useful in CI/CD pipelines where type safety must be enforced before deployment.
861
1175
  *
862
- * @param options - new compiler configuration
1176
+ * @example
1177
+ * ```ts
1178
+ * failOnError: true // Build fails on type errors
1179
+ * failOnError: false // Type errors logged, but build continues
1180
+ * ```
863
1181
  *
864
1182
  * @since 2.0.0
865
1183
  */
866
- set options(options: CompilerOptions);
1184
+ failOnError?: boolean;
1185
+ }
1186
+ /**
1187
+ * Base configuration shared across all build definitions, including common and variant builds.
1188
+ * Provides common settings for hooks, type checking, code injection, and declaration generation.
1189
+ *
1190
+ * @remarks
1191
+ * This interface defines the foundation for build configuration that applies to both common
1192
+ * settings and individual build variants. Properties defined here can be overridden at the
1193
+ * variant level for customization.
1194
+ *
1195
+ * Configuration inheritance:
1196
+ * - Common build settings apply to all variants
1197
+ * - Variant settings override common settings
1198
+ * - Objects like `define` are merged (variant takes precedence)
1199
+ * - Arrays and primitives replace common values
1200
+ *
1201
+ * @example
1202
+ * ```ts
1203
+ * const base: BaseBuildDefinitionInterface = {
1204
+ * types: { failOnError: true },
1205
+ * declaration: { bundle: true, outDir: 'types' },
1206
+ * define: { 'process.env.NODE_ENV': '"production"' },
1207
+ * banner: 'const x = "test"',
1208
+ * hooks: {
1209
+ * onSuccess: async () => console.log('Build complete!')
1210
+ * }
1211
+ * };
1212
+ * ```
1213
+ *
1214
+ * @see {@link CommonBuildInterface}
1215
+ * @see {@link VariantBuildInterface}
1216
+ * @see {@link BuildConfigInterface}
1217
+ *
1218
+ * @since 2.0.0
1219
+ */
1220
+ interface BaseBuildDefinitionInterface {
867
1221
  /**
868
- * Reloads all tracked file snapshots in the shared {@link FilesModel} cache.
1222
+ * Lifecycle hook handlers for build process stages.
869
1223
  *
870
1224
  * @remarks
871
- * This method iterates over every currently tracked file path and touches each file again so
872
- * the cache can refresh its stored modification time, version, and content snapshot when needed.
873
- * It is useful in watch-mode or manual refresh scenarios where the underlying files may have changed
874
- * and dependent services need to observe the updated state.
875
- *
876
- * @since 2.3.0
877
- */
878
- static reload(): void;
879
- /**
880
- * Updates file snapshot in the cache and returns the current state.
1225
+ * Registers custom handlers for various build lifecycle events including start, resolve,
1226
+ * load, end, and success stages. All hooks are optional.
881
1227
  *
882
- * @param path - file path (relative or absolute)
883
- * @returns current snapshot data (version, mtime, content snapshot)
1228
+ * @see {@link LifecycleHooksInterface}
884
1229
  *
885
- * @see {@link FilesModel#touchFile}
886
1230
  * @since 2.0.0
887
1231
  */
888
- touchFile(path: string): FileSnapshotInterface;
1232
+ lifecycle?: LifecycleHooksInterface;
889
1233
  /**
890
- * Ensures multiple files are tracked and their snapshots are up to date.
1234
+ * TypeScript type checking configuration.
891
1235
  *
892
- * @param filesPath - list of file paths to touch
1236
+ * @remarks
1237
+ * Controls whether and how TypeScript type checking is performed during builds.
1238
+ * - `true`: Enable type checking with default options
1239
+ * - `false` or omitted: Disable type checking
1240
+ * - Object: Enable with specific options like `failOnError`
893
1241
  *
894
- * @since 2.0.0
895
- */
896
- touchFiles(filesPath: Array<string>): void;
897
- /**
898
- * Returns current compiler options used by this host.
1242
+ * @example
1243
+ * ```ts
1244
+ * types: true // Enable with default
1245
+ * types: { failOnError: true } // Enable and fail on errors
1246
+ * types: false // Disable
1247
+ * ```
899
1248
  *
900
- * @returns active TypeScript compiler configuration
1249
+ * @see {@link TypeCheckOptionsInterface}
901
1250
  *
902
1251
  * @since 2.0.0
903
1252
  */
904
- getCompilationSettings(): CompilerOptions;
1253
+ types?: boolean | TypeCheckOptionsInterface;
905
1254
  /**
906
- * Checks whether a file exists on disk.
1255
+ * Global constants to replace during bundling.
907
1256
  *
908
- * @param path - absolute path
909
- * @returns `true` if file exists
1257
+ * @remarks
1258
+ * Defines key-value pairs for constant replacement during the build. Keys are identifiers
1259
+ * or property access expressions, values are JSON-stringified replacements.
910
1260
  *
911
- * @since 2.0.0
912
- */
913
- fileExists(path: string): boolean;
914
- /**
915
- * Reads file content from disk.
1261
+ * Commonly used for environment variables, feature flags, and build-time constants.
916
1262
  *
917
- * @param path - absolute path
918
- * @param encoding - optional encoding (defaults to UTF-8)
919
- * @returns file content or `undefined` if read fails
1263
+ * @example
1264
+ * ```ts
1265
+ * define: {
1266
+ * 'process.env.NODE_ENV': '"production"',
1267
+ * 'DEBUG': 'false',
1268
+ * 'VERSION': '"1.2.3"'
1269
+ * }
1270
+ * ```
920
1271
  *
921
1272
  * @since 2.0.0
922
1273
  */
923
- readFile(path: string, encoding?: string): string | undefined;
1274
+ define?: Record<string, unknown>;
924
1275
  /**
925
- * Lists files and/or directories matching criteria.
1276
+ * Code to inject at the beginning of each output file.
926
1277
  *
927
- * @param path - starting directory
928
- * @param extensions - allowed file extensions
929
- * @param exclude - glob exclude patterns
930
- * @param include - glob include patterns
931
- * @param depth - max recursion depth
932
- * @returns matching file paths
1278
+ * @remarks
1279
+ * Can be a static string or a function that generates code based on build context.
1280
+ * Commonly used for copyright notices, license headers, or polyfill imports.
933
1281
  *
934
- * @since 2.0.0
935
- */
936
- readDirectory(path: string, extensions?: Array<string>, exclude?: Array<string>, include?: Array<string>, depth?: number): Array<string>;
937
- /**
938
- * Returns immediate subdirectories of a given path.
1282
+ * @example
1283
+ * ```ts
1284
+ * banner: 'const x = "test"'
1285
+ * banner: (name, argv) => `const x = "Built: ${new Date().toISOString()}"`
1286
+ * ```
939
1287
  *
940
- * @param path - directory to list
941
- * @returns subdirectory names
1288
+ * @see {@link InjectableCodeType}
942
1289
  *
943
1290
  * @since 2.0.0
944
1291
  */
945
- getDirectories(path: string): Array<string>;
1292
+ banner?: {
1293
+ [key: string]: InjectableCodeType;
1294
+ };
946
1295
  /**
947
- * Checks whether a directory exists.
1296
+ * Code to inject at the end of each output file.
948
1297
  *
949
- * @param path - absolute path
950
- * @returns `true` if directory exists
1298
+ * @remarks
1299
+ * Can be a static string or a function that generates code based on build context.
1300
+ * Commonly used for initialization code, analytics, or polyfills.
951
1301
  *
952
- * @since 2.0.0
953
- */
954
- directoryExists(path: string): boolean;
955
- /**
956
- * Returns the current working directory used as resolution base.
1302
+ * @example
1303
+ * ```ts
1304
+ * footer: '// End of bundle'
1305
+ * footer: (name, argv) => `console.log('Loaded ${name}');`
1306
+ * ```
957
1307
  *
958
- * @returns absolute path of cwd
1308
+ * @see {@link InjectableCodeType}
959
1309
  *
960
1310
  * @since 2.0.0
961
1311
  */
962
- getCurrentDirectory(): string;
1312
+ footer?: {
1313
+ [key: string]: InjectableCodeType;
1314
+ };
963
1315
  /**
964
- * Returns names of all known script files tracked by this host.
965
- *
966
- * @returns array of resolved absolute paths
1316
+ * TypeScript declaration file generation configuration.
967
1317
  *
968
1318
  * @remarks
969
- * Only includes files previously requested via `getScriptSnapshot` or explicitly `touchFile`/`touchFiles`.
970
- *
971
- * @since 2.0.0
972
- */
973
- getScriptFileNames(): Array<string>;
974
- /**
975
- * Returns a path to a default lib `.d.ts` file matching the given target.
976
- *
977
- * @param options - compiler options (mainly `target`)
978
- * @returns absolute path to lib.d.ts / lib.esxxxx.d.ts
979
- *
980
- * @since 2.0.0
981
- */
982
- getDefaultLibFileName(options: CompilerOptions): string;
983
- /**
984
- * Returns string version identifier for the given file.
1319
+ * Controls whether and how TypeScript declaration files are generated.
1320
+ * - `true`: Generate declarations with default options
1321
+ * - `false` or omitted: Do not generate declarations
1322
+ * - Object: Generate with specific options like `outDir` and `bundle`
985
1323
  *
986
- * @param path - file path
987
- * @returns version as string (usually `"0"`, `"1"`, `"2"`, …)
1324
+ * @example
1325
+ * ```ts
1326
+ * declaration: true // Generate with default
1327
+ * declaration: { outDir: 'types', bundle: true } // Generate bundled in custom dir
1328
+ * declaration: false // Disable
1329
+ * ```
988
1330
  *
989
- * @remarks
990
- * Tracks file in `trackFiles` set as a side effect so it appears in `getScriptFileNames()`.
1331
+ * @see {@link DeclarationOptionsInterface}
991
1332
  *
992
1333
  * @since 2.0.0
993
1334
  */
994
- getScriptVersion(path: string): string;
1335
+ declaration?: boolean | DeclarationOptionsInterface;
1336
+ }
1337
+ /**
1338
+ * Build configuration for a specific build variant including esbuild settings and entry points.
1339
+ * Extends base configuration with variant-specific esbuild options and required entry points.
1340
+ *
1341
+ * @remarks
1342
+ * A variant represents a distinct build target with its own entry points and esbuild configuration.
1343
+ * Variants inherit settings from the common configuration but can override any property.
1344
+ *
1345
+ * The `esbuild` property excludes fields that are managed by the build system:
1346
+ * - `plugins`: Managed by the hook provider
1347
+ * - `define`, `banner`, `footer`: Managed by base configuration
1348
+ * - `entryPoints`: Required at variant level (non-nullable)
1349
+ *
1350
+ * Multiple variants enable building different outputs from the same codebase, such as
1351
+ * - Different module formats (ESM, CJS)
1352
+ * - Different targets (Node.js, browser)
1353
+ * - Different bundles (main, worker, tests)
1354
+ *
1355
+ * @example
1356
+ * ```ts
1357
+ * const variant: VariantBuildInterface = {
1358
+ * esbuild: {
1359
+ * entryPoints: ['src/index.ts'],
1360
+ * outdir: 'dist/esm',
1361
+ * format: 'esm',
1362
+ * target: 'es2020'
1363
+ * },
1364
+ * types: true,
1365
+ * declaration: { bundle: true, outDir: 'dist/types' }
1366
+ * };
1367
+ * ```
1368
+ *
1369
+ * @see {@link VariantsType}
1370
+ * @see {@link CommonBuildInterface}
1371
+ * @see {@link BaseBuildDefinitionInterface}
1372
+ *
1373
+ * @since 2.0.0
1374
+ */
1375
+ interface VariantBuildInterface extends BaseBuildDefinitionInterface {
995
1376
  /**
996
- * Checks whether a file is actively tracked (has been requested before).
1377
+ * Esbuild-specific configuration for this variant including entry points.
997
1378
  *
998
- * @param path - file path
999
- * @returns `true` if the file is known to this host
1379
+ * @remarks
1380
+ * Contains all esbuild options except those managed by the build system.
1381
+ * The `entryPoints` field is required and must be non-empty to define what to build.
1382
+ *
1383
+ * Common options include:
1384
+ * - `format`: Output format (esm, cjs, iife)
1385
+ * - `outdir` or `outfile`: Output location
1386
+ * - `target`: ECMAScript target version
1387
+ * - `platform`: Target platform (browser, node, neutral)
1388
+ * - `minify`: Whether to minify output
1389
+ * - `sourcemap`: Whether to generate source maps
1390
+ *
1391
+ * @example
1392
+ * ```ts
1393
+ * esbuild: {
1394
+ * entryPoints: ['src/index.ts', 'src/worker.ts'],
1395
+ * outdir: 'dist',
1396
+ * format: 'esm',
1397
+ * target: 'es2020',
1398
+ * minify: true,
1399
+ * sourcemap: true
1400
+ * }
1401
+ * ```
1000
1402
  *
1001
1403
  * @since 2.0.0
1002
1404
  */
1003
- hasScriptSnapshot(path: string): boolean;
1405
+ esbuild: Omit<BuildOptions, 'plugins' | 'define' | 'banner' | 'footer'>;
1004
1406
  /**
1005
- * Returns an up-to-date script snapshot for the file.
1006
- *
1007
- * @param path - file path
1008
- * @returns `IScriptSnapshot` or `undefined` if a file is missing/empty
1407
+ * Variants that must finish building before this variant starts.
1009
1408
  *
1010
1409
  * @remarks
1011
- * Automatically touches the file (reads disk if needed) when no snapshot exists yet.
1410
+ * Use this field to express build ordering between variants when one output
1411
+ * depends on another being completed first.
1012
1412
  *
1013
- * @since 2.0.0
1014
- */
1015
- getScriptSnapshot(path: string): IScriptSnapshot | undefined;
1016
- /**
1017
- * Resolves module import using current compiler options and cache.
1413
+ * You can provide:
1414
+ * - a single variant name
1415
+ * - an array of variant names
1018
1416
  *
1019
- * @param moduleName - module specifier
1020
- * @param containingFile - path of a file containing the import
1021
- * @returns resolution result (success and failed lookups)
1417
+ * The build system should resolve these dependencies before running the current
1418
+ * variant and should also detect circular dependencies to avoid infinite loops.
1022
1419
  *
1023
- * @since 2.0.0
1024
- */
1025
- resolveModuleName(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations;
1026
- /**
1027
- * Resolves a module specifier to its absolute file path using the host.
1420
+ * @example
1421
+ * ```ts
1422
+ * dependOn: 'types'
1423
+ * ```
1028
1424
  *
1029
- * @param moduleName - import/export specifier (e.g. "lodash", "./utils")
1030
- * @param containingFile - path of a file containing the import
1031
- * @returns resolved absolute path or `undefined` if resolution fails
1425
+ * @example
1426
+ * ```ts
1427
+ * dependOn: ['types', 'shared']
1428
+ * ```
1032
1429
  *
1033
- * @since 2.0.0
1430
+ * @see {@link VariantsType}
1431
+ * @since 2.4.0
1034
1432
  */
1035
- resolveModuleFileName(moduleName: string, containingFile: string): string | undefined;
1433
+ dependOn?: string | Array<string>;
1434
+ }
1435
+ /**
1436
+ * Shared configuration applied to all build variants.
1437
+ * Extends base configuration with esbuild settings but without entry points.
1438
+ *
1439
+ * @remarks
1440
+ * Common configuration provides default settings that apply to all variants unless overridden.
1441
+ * This reduces duplication when multiple variants share similar settings.
1442
+ *
1443
+ * The `esbuild` property excludes managed fields and `entryPoints` (which must be variant-specific).
1444
+ * Settings defined here are merged with variant-specific settings, with variants taking precedence.
1445
+ *
1446
+ * Typical use cases:
1447
+ * - Shared compiler options (target, platform)
1448
+ * - Common minification and sourcemap settings
1449
+ * - Shared external dependencies
1450
+ * - Default output configuration
1451
+ *
1452
+ * @example
1453
+ * ```ts
1454
+ * const common: CommonBuildInterface = {
1455
+ * esbuild: {
1456
+ * target: 'es2020',
1457
+ * platform: 'node',
1458
+ * sourcemap: true,
1459
+ * external: ['react', 'react-dom']
1460
+ * },
1461
+ * types: { failOnError: true },
1462
+ * declaration: true
1463
+ * };
1464
+ * ```
1465
+ *
1466
+ * @see {@link BaseBuildDefinitionInterface}
1467
+ * @see {@link VariantBuildInterface}
1468
+ * @see {@link BuildConfigInterface}
1469
+ *
1470
+ * @since 2.0.0
1471
+ */
1472
+ interface CommonBuildInterface extends BaseBuildDefinitionInterface {
1036
1473
  /**
1037
- * Rewrites path aliases in declaration content to relative paths.
1038
- *
1039
- * @param content - raw declaration text
1040
- * @param fileName - source file name
1041
- * @param type - file extension to append to resolved paths (e.g., `'.d.ts'`, `'.js'`), defaults to empty string
1042
- * @returns content with aliases replaced by relative paths
1474
+ * Shared esbuild configuration for all variants.
1043
1475
  *
1044
1476
  * @remarks
1045
- * Ensures emitted files use portable relative imports instead of aliases.
1046
- * The `type` parameter allows flexible transformation of resolved TypeScript source file extensions
1047
- * (`.ts`, `.tsx`) to any target extension.
1477
+ * Contains esbuild options that apply to all variants by default. Variants can override
1478
+ * any of these settings with their own specific values.
1048
1479
  *
1049
- * **Common use cases**:
1050
- * - Pass `'.d.ts'` for declaration file generation
1051
- * - Pass `'.js'` for JavaScript output paths
1052
- * - Pass `''` (default) to preserve the resolved file extension
1480
+ * Excludes managed fields and `entryPoints` since entry points must be variant-specific.
1053
1481
  *
1054
1482
  * @example
1055
1483
  * ```ts
1056
- * // For regular source files (preserve extension)
1057
- * const code = host.resolveAliases(content, 'src/index.ts');
1058
- *
1059
- * // For declaration files
1060
- * const dts = host.resolveAliases(content, 'src/index.ts', '.d.ts');
1061
- * // '@utils/helpers' -> './utils/helpers.d.ts'
1062
- *
1063
- * // For JavaScript output
1064
- * const js = host.resolveAliases(content, 'src/index.ts', '.js');
1065
- * // '@utils/helpers' -> './utils/helpers.js'
1484
+ * esbuild: {
1485
+ * platform: 'node',
1486
+ * target: 'node18',
1487
+ * external: ['typescript']
1488
+ * }
1066
1489
  * ```
1067
1490
  *
1068
1491
  * @since 2.0.0
1069
1492
  */
1070
- resolveAliases(content: string, fileName: string, type?: string): string;
1071
- /**
1072
- * Builds regex that matches import/export declarations using any configured path alias.
1073
- *
1074
- * @param config - compiler options containing `paths`
1075
- * @returns regex or `undefined` if no `paths` configured
1076
- *
1077
- * @since 2.0.0
1078
- */
1079
- private static generateAliasRegex;
1493
+ esbuild?: Omit<BuildOptions, 'plugins' | 'define' | 'banner' | 'footer'>;
1080
1494
  }
1081
1495
  /**
1082
- * Extended TypeScript script snapshot that includes direct access to the underlying text content.
1496
+ * Maps variant names to their build configurations.
1497
+ * Allows defining multiple build targets with different entry points and settings.
1083
1498
  *
1084
1499
  * @remarks
1085
- * This type augments TypeScript's standard `IScriptSnapshot` interface with a `text` property,
1086
- * providing direct access to the original source text without requiring method calls.
1087
- *
1088
- * TypeScript's native `IScriptSnapshot` only exposes text through the `getText()` method.
1089
- * This extended type adds a `text` property for more convenient access to the full content,
1090
- * particularly useful in caching scenarios where the source text is frequently referenced.
1500
+ * This type represents a collection of named build variants. Each key is a user-defined
1501
+ * variant name (e.g., 'esm', 'cjs', 'browser'), and each value is the complete build
1502
+ * configuration for that variant.
1091
1503
  *
1092
- * Primarily used by {@link FilesModel} to store file content snapshots in an efficient,
1093
- * readily accessible format for incremental compilation and language service operations.
1504
+ * Variant names are used for:
1505
+ * - CLI targeting specific builds
1506
+ * - Build output organization
1507
+ * - Logging and error reporting
1508
+ * - Parallel build coordination
1094
1509
  *
1095
1510
  * @example
1096
1511
  * ```ts
1097
- * const snapshot: ScriptSnapshotType = {
1098
- * ...ts.ScriptSnapshot.fromString(content),
1099
- * text: content
1512
+ * const variants: VariantsType = {
1513
+ * esm: {
1514
+ * esbuild: {
1515
+ * entryPoints: ['src/index.ts'],
1516
+ * format: 'esm',
1517
+ * outdir: 'dist/esm'
1518
+ * }
1519
+ * },
1520
+ * cjs: {
1521
+ * esbuild: {
1522
+ * entryPoints: ['src/index.ts'],
1523
+ * format: 'cjs',
1524
+ * outdir: 'dist/cjs'
1525
+ * }
1526
+ * }
1100
1527
  * };
1101
- *
1102
- * // Direct text access (convenient)
1103
- * console.log(snapshot.text);
1104
- *
1105
- * // Method-based access (standard IScriptSnapshot)
1106
- * console.log(snapshot.getText(0, snapshot.getLength()));
1107
1528
  * ```
1108
1529
  *
1109
- * @see {@link IScriptSnapshot}
1110
- * @see {@link FilesModel.touchFile}
1111
- * @see {@link FileSnapshotInterface}
1530
+ * @see {@link VariantBuildInterface}
1531
+ * @see {@link BuildConfigInterface}
1112
1532
  *
1113
1533
  * @since 2.0.0
1114
1534
  */
1115
- type ScriptSnapshotType = IScriptSnapshot & {
1116
- text: string;
1535
+ type VariantsType = {
1536
+ [variantName: string]: VariantBuildInterface;
1117
1537
  };
1118
1538
  /**
1119
- * Represents the cached state of a single file for incremental TypeScript processing.
1539
+ * Complete build configuration including common settings, variants, and CLI options.
1540
+ * Serves as the root configuration object for the entire build system.
1120
1541
  *
1121
- * Stores the modification timestamp, a version counter that increments on every meaningful change,
1122
- * and an optional TypeScript `ScriptSnapshot` containing the file content in a memory-efficient form.
1542
+ * @remarks
1543
+ * This interface defines the complete structure of the build configuration file. It includes:
1544
+ * - Optional common settings shared across all variants
1545
+ * - Required variants mapping defining all build targets
1546
+ * - Optional verbose logging flag
1547
+ * - Optional custom command-line argument definitions
1123
1548
  *
1124
- * Used by language services and build tools to quickly determine whether a file needs to be reparsed.
1549
+ * The configuration is typically exported from a `build.config.ts` or similar file and
1550
+ * loaded by the build system at startup.
1551
+ *
1552
+ * Configuration resolution:
1553
+ * 1. Load the configuration file
1554
+ * 2. Parse command-line arguments using `userArgv` definitions
1555
+ * 3. Merge common settings with each variant
1556
+ * 4. Execute builds for all or selected variants
1557
+ *
1558
+ * @example
1559
+ * ```ts
1560
+ * const config: BuildConfigInterface = {
1561
+ * verbose: true,
1562
+ * common: {
1563
+ * esbuild: {
1564
+ * platform: 'node',
1565
+ * target: 'node18'
1566
+ * },
1567
+ * types: true
1568
+ * },
1569
+ * variants: {
1570
+ * esm: {
1571
+ * esbuild: {
1572
+ * entryPoints: ['src/index.ts'],
1573
+ * format: 'esm',
1574
+ * outdir: 'dist/esm'
1575
+ * }
1576
+ * },
1577
+ * cjs: {
1578
+ * esbuild: {
1579
+ * entryPoints: ['src/index.ts'],
1580
+ * format: 'cjs',
1581
+ * outdir: 'dist/cjs'
1582
+ * }
1583
+ * }
1584
+ * },
1585
+ * userArgv: {
1586
+ * watch: { type: 'boolean', description: 'Watch for changes' }
1587
+ * }
1588
+ * };
1589
+ * ```
1590
+ *
1591
+ * @see {@link VariantsType}
1592
+ * @see {@link CommonBuildInterface}
1593
+ * @see {@link PartialBuildConfigType}
1125
1594
  *
1126
1595
  * @since 2.0.0
1127
1596
  */
1128
- interface FileSnapshotInterface {
1597
+ interface BuildConfigInterface {
1129
1598
  /**
1130
- * Last known modification time of the file in milliseconds since epoch.
1131
- *
1132
- * Set to `0` when the file no longer exists or cannot be accessed.
1599
+ * Shared configuration applied to all build variants.
1133
1600
  *
1134
1601
  * @remarks
1135
- * Compared directly against `fs.stat().mtimeMs` to detect changes without reading content.
1602
+ * Optional common settings that are merged with each variant's configuration.
1603
+ * Variants can override these settings with their own specific values.
1604
+ *
1605
+ * @see {@link CommonBuildInterface}
1136
1606
  *
1137
1607
  * @since 2.0.0
1138
1608
  */
1139
- mtimeMs: number;
1609
+ common?: CommonBuildInterface;
1140
1610
  /**
1141
- * Monotonically increasing integer that changes whenever the file content or accessibility status changes.
1142
- *
1143
- * Used by TypeScript language services as the script version identifier.
1611
+ * Enable verbose logging output during builds.
1144
1612
  *
1145
1613
  * @remarks
1146
- * - Incremented on every successful content read with changed mtime
1147
- * - Incremented when a file becomes unreadable (if it previously had content or version bigger than 0)
1148
- * - Not incremented on no-op accesses (unchanged mtime)
1614
+ * When true, outputs detailed build information including file processing,
1615
+ * hook execution, and timing information. Useful for debugging build issues.
1149
1616
  *
1150
1617
  * @example
1151
1618
  * ```ts
1152
- * // Typical usage in LanguageServiceHost
1153
- * getScriptVersion(fileName: string): string {
1154
- * const snapshot = cache.touchFile(fileName);
1155
- * return String(snapshot.version);
1156
- * }
1619
+ * verbose: true // Detailed output
1620
+ * verbose: false // Minimal output
1157
1621
  * ```
1158
1622
  *
1159
1623
  * @since 2.0.0
1160
1624
  */
1161
- version: number;
1625
+ verbose?: boolean;
1162
1626
  /**
1163
- * TypeScript script snapshot containing the file's source text, or `undefined` if the file is missing,
1164
- * empty, or inaccessible.
1627
+ * Build variant definitions mapping names to configurations.
1165
1628
  *
1166
1629
  * @remarks
1167
- * - Created via `ts.ScriptSnapshot.fromString(content)`
1168
- * - Kept `undefined` for zero-length or non-readable files to save memory
1169
- * - Consumers should check existence before calling methods like `getText()`
1630
+ * Required field defining all build targets. At least one variant must be defined.
1631
+ * Each variant specifies its own entry points and can override common settings.
1170
1632
  *
1171
- * @see ScriptSnapshotType
1172
- * @see {@link https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API#script-snapshot | TypeScript Compiler API – Script Snapshots}
1633
+ * @see {@link VariantsType}
1173
1634
  *
1174
1635
  * @since 2.0.0
1175
1636
  */
1176
- contentSnapshot: ScriptSnapshotType | undefined;
1637
+ variants: VariantsType;
1177
1638
  }
1178
1639
  /**
1179
- * Extended build result interface with normalized error and warning arrays.
1640
+ * Partial build configuration for incremental or programmatic configuration building.
1641
+ * Allows omitting variants and userArgv while making other fields optional.
1180
1642
  *
1181
1643
  * @remarks
1182
- * This interface extends esbuild's {@link BuildResult} while replacing the `errors` and `warnings`
1183
- * properties with normalized Error instances instead of esbuild's Message objects. This normalization
1184
- * provides consistent error handling throughout the xBuild system with proper stack traces, formatting,
1185
- * and error classification.
1186
- *
1187
- * **Key differences from esbuild's BuildResult**:
1188
- * - `errors`: Changed from `Message[]` to `Error[]` with normalized error types
1189
- * - `warnings`: Changed from `Message[]` to `Error[]` with normalized error types
1190
- * - All other properties (metafile, outputFiles, mangleCache) are preserved unchanged
1191
- *
1192
- * **Benefits of normalization**:
1193
- * - Consistent error handling across different error sources (esbuild, TypeScript, VM runtime)
1194
- * - Proper error inheritance and type checking
1195
- * - Rich stack trace information with source mapping
1196
- * - Formatted error output with syntax highlighting
1197
- * - Integration with xBuild's custom error classes
1644
+ * This type is useful when building configuration programmatically or when providing
1645
+ * configuration fragments that will be merged with a base configuration. It makes
1646
+ * all properties optional except `variants` and `userArgv` which are completely omitted.
1198
1647
  *
1199
- * The normalized errors may include:
1200
- * - {@link TypesError} for TypeScript type checking failures
1201
- * - {@link xBuildError} for text errors during build hooks
1202
- * - {@link esBuildError} for esbuild compilation errors with location information
1203
- * - {@link VMRuntimeError} for runtime errors during build hooks
1204
- * - {@link xBuildBaseError} for custom build system errors
1648
+ * Common use cases:
1649
+ * - Configuration presets or templates
1650
+ * - Programmatic configuration generation
1651
+ * - Configuration merging utilities
1652
+ * - Partial overrides in build scripts
1205
1653
  *
1206
1654
  * @example
1207
1655
  * ```ts
1208
- * const result: BuildResultInterface = {
1209
- * errors: [
1210
- * new esBuildError(esbuildMessage),
1211
- * new TypesError('Type checking failed', diagnostics)
1212
- * ],
1213
- * warnings: [
1214
- * new xBuildError('Deprecation warning')
1215
- * ],
1216
- * metafile: { ... },
1217
- * outputFiles: [ ... ],
1218
- * mangleCache: { ... }
1656
+ * const preset: PartialBuildConfigType = {
1657
+ * verbose: true,
1658
+ * common: {
1659
+ * types: { failOnError: true },
1660
+ * declaration: true
1661
+ * }
1662
+ * };
1663
+ *
1664
+ * // Merge with full config
1665
+ * const fullConfig: BuildConfigInterface = {
1666
+ * ...preset,
1667
+ * variants: { ... }
1219
1668
  * };
1220
1669
  * ```
1221
1670
  *
1222
- * @see {@link BuildResult} from esbuild for the base interface
1671
+ * @see {@link BuildConfigInterface}
1223
1672
  *
1224
1673
  * @since 2.0.0
1225
1674
  */
1226
- interface BuildResultInterface extends Omit<BuildResult, 'errors' | 'warnings'> {
1227
- /**
1228
- * Array of normalized error instances encountered during the build.
1229
- *
1230
- * @remarks
1231
- * Contains Error instances converted from esbuild messages and other error sources.
1232
- * Unlike esbuild's native error array which contains Message objects, this array
1233
- * contains fully normalized Error instances with proper stack traces and formatting.
1234
- *
1235
- * Errors in this array may originate from:
1236
- * - Compilation errors (syntax, resolution failures)
1237
- * - Type checking failures
1238
- * - Build hook execution errors
1239
- * - Plugin errors
1240
- *
1241
- * @example
1242
- * ```ts
1243
- * if (result.errors.length > 0) {
1244
- * console.error(`Build failed with ${result.errors.length} errors`);
1245
- * result.errors.forEach(err => console.error(err.stack));
1246
- * }
1247
- * ```
1248
- *
1249
- * @since 2.0.0
1250
- */
1251
- errors: Array<Error>;
1252
- /**
1253
- * Array of normalized warning instances encountered during the build.
1254
- *
1255
- * @remarks
1256
- * Contains Error instances converted from esbuild warning messages and other warning sources.
1257
- * Unlike esbuild's native warning array which contains Message objects, this array
1258
- * contains fully normalized Error instances with proper stack traces and formatting.
1259
- *
1260
- * Warnings indicate non-fatal issues that don't prevent build completion but may
1261
- * require attention, such as:
1262
- * - Deprecated API usage
1263
- * - Type checking warnings
1264
- * - Performance concerns
1265
- * - Potential runtime issues
1266
- *
1267
- * @example
1268
- * ```ts
1269
- * if (result.warnings.length > 0) {
1270
- * console.warn(`Build completed with ${result.warnings.length} warnings`);
1271
- * result.warnings.forEach(warn => console.warn(warn.message));
1272
- * }
1273
- * ```
1274
- *
1275
- * @since 2.0.0
1276
- */
1277
- warnings: Array<Error>;
1278
- }
1675
+ type PartialBuildConfigType = Partial<BuildConfigInterface>;
1279
1676
  /**
1280
1677
  * Represents a value that may be synchronous, asynchronous, void, null, or the specified type.
1281
1678
  *
@@ -2004,889 +2401,675 @@ type OnResolveType = (context: ResolveContextInterface) => MaybeUndefinedPromise
2004
2401
  */
2005
2402
  type OnLoadType = (context: LoadContextInterface) => MaybeUndefinedPromiseType<OnLoadResult>;
2006
2403
  /**
2007
- * Options used to reload the build service configuration.
2008
- *
2009
- * @remarks
2010
- * These options control how configuration reload behaves:
2011
- * - `config` replaces the current build configuration
2012
- * - `clearCache` clears cached file and TypeScript language service state before reloading
2013
- *
2014
- * @since 2.3.0
2015
- */
2016
- interface ReloadOptionsInterface {
2017
- /**
2018
- * Optional new configuration to replace the current one.
2019
- *
2020
- * @remarks
2021
- * When provided, the build service reloads using this configuration
2022
- * before recalculating variants.
2023
- */
2024
- config?: PartialBuildConfigType;
2025
- /**
2026
- * Whether to clear cached files and TypeScript language service state before reloading.
2027
- *
2028
- * @remarks
2029
- * When enabled, cached file tracking and language service state are reset
2030
- * before the configuration is reloaded.
2031
- */
2032
- clearCache?: boolean;
2033
- }
2034
- /**
2035
- * Recursively makes all properties of a type optional.
2036
- *
2037
- * @remarks
2038
- * This utility type behaves like TypeScript’s built-in {@link Partial} type,
2039
- * but applies recursively to all nested object properties.
2040
- *
2041
- * It is commonly used for:
2042
- * - Partial configuration overrides
2043
- * - Patch / update objects
2044
- * - Programmatic configuration merging
2045
- * - Build variant and preset definitions
2046
- *
2047
- * This type only affects compile-time type checking and has no runtime impact.
2048
- *
2049
- * ⚠️ **Important limitations**:
2050
- * - Arrays and functions are treated as objects and will also be recursively
2051
- * transformed. If this is undesirable, a more specialized deep-partial
2052
- * implementation should be used.
2053
- * - Intended for configuration and data-shaping use cases, not strict domain models.
2054
- *
2055
- * @example
2056
- * ```ts
2057
- * interface Config {
2058
- * server: {
2059
- * host: string;
2060
- * port: number;
2061
- * };
2062
- * features: {
2063
- * experimental: boolean;
2064
- * };
2065
- * }
2066
- *
2067
- * const override: DeepPartialType<Config> = {
2068
- * server: {
2069
- * port: 8080
2070
- * }
2071
- * };
2072
- * ```
2073
- *
2074
- * @template T - The type to recursively make optional.
2075
- *
2076
- * @since 2.0.0
2077
- */
2078
- type DeepPartialType<T> = {
2079
- [K in keyof T]?: T[K] extends object ? DeepPartialType<T[K]> : T[K];
2080
- };
2081
- /**
2082
- * Represents code that can be injected into build output as a banner or footer.
2083
- * Can be a static string or a function that generates code dynamically based on build context.
2404
+ * Represents a cached TypeScript language service instance with reference counting for shared resource management.
2405
+ * Enables multiple consumers to share the same language service while tracking active usage through reference counts.
2084
2406
  *
2085
2407
  * @remarks
2086
- * This type provides flexibility for injecting code at the top (banner) or bottom (footer) of
2087
- * bundled output files. The function form receives the plugin name and command-line arguments,
2088
- * allowing for context-aware code generation.
2089
- *
2090
- * Common use cases:
2091
- * - Static banners: Copyright notices, license headers, version information
2092
- * - Dynamic banners: Build timestamps, environment-specific code, conditional imports
2093
- * - Footer code: Analytics snippets, polyfills, initialization scripts
2408
+ * This interface is used internally by {@link TypescriptService} to implement a caching strategy that prevents
2409
+ * duplicate language service instances for the same configuration file. The lifecycle follows these rules:
2410
+ * - When a new service is created, `refCount` starts at 1
2411
+ * - Each additional consumer increments `refCount`
2412
+ * - Calling dispose decrements `refCount`
2413
+ * - When `refCount` reaches 0, the service is disposed and removed from cache
2094
2414
  *
2095
- * When using the function form, the generated string is cached per build variant to avoid
2096
- * regenerating the same code multiple times.
2415
+ * The cached data includes all components needed to maintain a fully functional TypeScript compiler instance:
2416
+ * compiled configuration, language service host, and the language service itself.
2097
2417
  *
2098
2418
  * @example
2099
2419
  * ```ts
2100
- * // Static banner
2101
- * const banner: InjectableCodeType = '\/* Copyright 2024 *\/';
2102
- *
2103
- * // Dynamic banner
2104
- * const banner: InjectableCodeType = (name, argv) => {
2105
- * const version = argv.version || '1.0.0';
2106
- * return `\/* Built by ${name} v${version} at ${new Date().toISOString()} *\/`;
2420
+ * const cached: CachedServiceInterface = {
2421
+ * config: parsedConfig,
2422
+ * host: languageHost,
2423
+ * service: tsLanguageService,
2424
+ * refCount: 1
2107
2425
  * };
2426
+ *
2427
+ * // Another consumer acquires the same service
2428
+ * cached.refCount++; // Now 2
2429
+ *
2430
+ * // Consumers finish and dispose
2431
+ * cached.refCount--; // Now 1
2432
+ * cached.refCount--; // Now 0, triggers cleanup
2108
2433
  * ```
2109
2434
  *
2110
- * @see {@link BaseBuildDefinitionInterface.banner}
2111
- * @see {@link BaseBuildDefinitionInterface.footer}
2435
+ * @see {@link TypescriptService}
2436
+ * @see {@link LanguageHostService}
2112
2437
  *
2113
2438
  * @since 2.0.0
2114
2439
  */
2115
- type InjectableCodeType = string | ((name: string, argv: Record<string, unknown>) => string);
2440
+ interface CachedServiceInterface {
2441
+ /**
2442
+ * Number of active consumers currently using this cached language service instance.
2443
+ *
2444
+ * @remarks
2445
+ * This counter tracks how many TypeScript service instances are sharing this cached language service.
2446
+ * When it reaches zero, the service can be safely disposed of and removed from the cache.
2447
+ *
2448
+ * @since 2.0.0
2449
+ */
2450
+ refCount: number;
2451
+ /**
2452
+ * Language service host managing file system operations and compiler options for this instance.
2453
+ * @since 2.0.0
2454
+ */
2455
+ host: LanguageHostService;
2456
+ /**
2457
+ * TypeScript language service providing type checking, analysis, and compilation capabilities.
2458
+ * @since 2.0.0
2459
+ */
2460
+ service: LanguageService;
2461
+ /**
2462
+ * Parsed TypeScript configuration including compiler options, file names, and project references.
2463
+ *
2464
+ * @remarks
2465
+ * This configuration is reloaded when the `tsconfig.json` file changes, ensuring the cached
2466
+ * service stays synchronized with the project's compilation settings.
2467
+ *
2468
+ * @since 2.0.0
2469
+ */
2470
+ config: ParsedCommandLine;
2471
+ }
2116
2472
  /**
2117
- * Defines lifecycle hook handlers for build process stages.
2118
- * Allows registration of custom logic during resolution, loading, build start, build end, and success.
2473
+ * Represents formatted diagnostic information from TypeScript compilation, including errors, warnings, and suggestions.
2474
+ * Provides a simplified interface for displaying compiler messages with optional source location details.
2119
2475
  *
2120
2476
  * @remarks
2121
- * This interface groups all available lifecycle hooks in a single configuration object.
2122
- * All hooks are optional, allowing selective registration of only necessary handlers.
2123
- *
2124
- * Hook execution order during a build:
2125
- * 1. `onStart` - Before any file processing
2126
- * 2. `onResolve` - During import path resolution
2127
- * 3. `onLoad` - When loading file contents
2128
- * 4. `onEnd` - After build completes (success or failure)
2129
- * 5. `onSuccess` - After a build completes successfully
2477
+ * This interface normalizes TypeScript's diagnostic format into a structure suitable for display in logs,
2478
+ * editor integrations, or build output. All location information (file, line, column) is optional because
2479
+ * some diagnostics apply globally or lack specific source positions.
2130
2480
  *
2131
- * Each hook receives a specialized context object appropriate for its lifecycle stage, providing
2132
- * access to build configuration, variant information, and cross-hook communication through the
2133
- * shared stage object.
2481
+ * Line and column numbers are 1-indexed to match standard editor conventions, even though TypeScript
2482
+ * internally uses 0-indexed positions.
2134
2483
  *
2135
2484
  * @example
2136
2485
  * ```ts
2137
- * const hooks: LifecycleHooksInterface = {
2138
- * onStart: async (context) => {
2139
- * console.log(`${context.variantName} build starting...`);
2140
- * },
2141
- * onLoad: async (context) => {
2142
- * if (context.args.path.endsWith('.custom')) {
2143
- * return { contents: transform(context.contents), loader: 'ts' };
2144
- * }
2145
- * },
2146
- * onSuccess: async (context) => {
2147
- * console.log(`Build succeeded in ${context.duration}ms!`);
2148
- * }
2486
+ * const diagnostic: DiagnosticInterface = {
2487
+ * file: 'src/index.ts',
2488
+ * line: 42,
2489
+ * column: 15,
2490
+ * code: 2304,
2491
+ * message: "Cannot find name 'unknownVariable'."
2149
2492
  * };
2493
+ *
2494
+ * console.log(`${diagnostic.file}:${diagnostic.line}:${diagnostic.column}`);
2495
+ * console.log(`TS${diagnostic.code}: ${diagnostic.message}`);
2150
2496
  * ```
2151
2497
  *
2152
- * @see {@link OnEndType}
2153
- * @see {@link OnLoadType}
2154
- * @see {@link OnStartType}
2155
- * @see {@link OnResolveType}
2498
+ * @see {@link TypescriptService.check}
2499
+ * @see {@link TypescriptService.formatDiagnostic}
2156
2500
  *
2157
2501
  * @since 2.0.0
2158
2502
  */
2159
- interface LifecycleHooksInterface {
2503
+ interface DiagnosticInterface {
2160
2504
  /**
2161
- * Hook handler executed when the build completes, regardless of success or failure.
2505
+ * File path where the diagnostic occurred.
2162
2506
  *
2163
2507
  * @remarks
2164
- * Called after all build operations finish with a result context containing the build result,
2165
- * calculated duration, variant name, arguments, and stage state. Useful for cleanup, logging,
2166
- * reporting, and post-processing.
2167
- *
2168
- * The handler receives `ResultContextInterface` providing access to:
2169
- * - `buildResult`: Final build outcome with errors and warnings
2170
- * - `duration`: Build duration in milliseconds
2171
- * - `variantName`: Build variant identifier
2172
- * - `argv`: Command-line arguments and configuration
2173
- * - `stage`: Shared state object for cross-hook communication
2508
+ * Optional because some diagnostics are configuration-level errors that don't relate to a specific file.
2174
2509
  *
2175
- * @example
2176
- * ```ts
2177
- * onEnd: async (context) => {
2178
- * const { buildResult, duration, variantName } = context;
2179
- * console.log(`${variantName} completed in ${duration}ms`);
2180
- * if (buildResult.errors.length > 0) {
2181
- * // Handle errors
2182
- * }
2183
- * }
2184
- * ```
2510
+ * @since 2.0.0
2511
+ */
2512
+ file?: string;
2513
+ /**
2514
+ * Line number where the diagnostic occurred, 1-indexed.
2185
2515
  *
2186
- * @see {@link ResultContextInterface}
2516
+ * @remarks
2517
+ * Optional because diagnostics without source location (like config errors) won't have line information.
2518
+ * When present, this value is 1-indexed to match standard editor conventions.
2187
2519
  *
2188
2520
  * @since 2.0.0
2189
2521
  */
2190
- onEnd?: OnEndType;
2522
+ line?: number;
2191
2523
  /**
2192
- * Hook handler executed when loading file contents during module processing.
2524
+ * Column number where the diagnostic occurred, 1-indexed.
2193
2525
  *
2194
2526
  * @remarks
2195
- * Called for each file being processed with a load context containing the current file contents
2196
- * (potentially transformed by previous hooks), loader type, load arguments, variant name, and
2197
- * stage state. Can transform contents and change the loader type. Multiple handlers execute in
2198
- * a pipeline pattern where each receives the output of previous hooks.
2527
+ * Optional because diagnostics without source location won't have column information.
2528
+ * When present, this value is 1-indexed to match standard editor conventions.
2199
2529
  *
2200
- * The handler receives `LoadContextInterface` providing access to:
2201
- * - `contents`: Current file contents (string or binary)
2202
- * - `loader`: Current loader type (e.g., 'ts', 'js', 'json')
2203
- * - `args`: Load arguments including file path and namespace
2204
- * - `variantName`: Build variant identifier
2205
- * - `argv`: Command-line arguments and configuration
2206
- * - `stage`: Shared state object for cross-hook communication
2530
+ * @since 2.0.0
2531
+ */
2532
+ column?: number;
2533
+ /**
2534
+ * TypeScript diagnostic code identifying the specific error or warning type.
2535
+ *
2536
+ * @remarks
2537
+ * Optional because not all diagnostics have associated error codes. When present, this can be used
2538
+ * to look up detailed documentation or implement diagnostic-specific handling.
2207
2539
  *
2208
2540
  * @example
2209
- * ```ts
2210
- * onLoad: async (context) => {
2211
- * const { contents, args, variantName } = context;
2212
- * if (args.path.endsWith('.custom')) {
2213
- * return {
2214
- * contents: transform(contents.toString()),
2215
- * loader: 'ts'
2216
- * };
2217
- * }
2218
- * }
2219
- * ```
2541
+ * Common codes include 2304 (cannot find name), 2322 (type not assignable), 2307 (cannot find module).
2220
2542
  *
2221
- * @see {@link LoadContextInterface}
2543
+ * @since 2.0.0
2544
+ */
2545
+ code?: number;
2546
+ /**
2547
+ * Human-readable diagnostic message describing the error, warning, or suggestion.
2548
+ *
2549
+ * @remarks
2550
+ * This message is flattened from TypeScript's potentially nested diagnostic message structure
2551
+ * using newline separators for multi-line messages.
2222
2552
  *
2223
2553
  * @since 2.0.0
2224
2554
  */
2225
- onLoad?: OnLoadType;
2555
+ message: string;
2226
2556
  /**
2227
- * Hook handler executed when the build process begins.
2557
+ * Category of the diagnostic indicating its severity level.
2228
2558
  *
2229
2559
  * @remarks
2230
- * Called before any file processing starts with a build context containing the esbuild build object,
2231
- * variant name, arguments, and stage state. Useful for initialization, validation, and setup tasks.
2560
+ * Determines how the diagnostic should be treated and displayed. TypeScript uses this to distinguish
2561
+ * between different severity levels:
2562
+ * - `DiagnosticCategory.Error` (1): Compilation-blocking errors
2563
+ * - `DiagnosticCategory.Warning` (0): Non-blocking warnings
2564
+ * - `DiagnosticCategory.Suggestion` (2): Code improvement suggestions
2565
+ * - `DiagnosticCategory.Message` (3): Informational messages
2232
2566
  *
2233
- * The handler receives `BuildContextInterface` providing access to:
2234
- * - `build`: esbuild plugin build object with configuration and utilities
2235
- * - `variantName`: Build variant identifier
2236
- * - `argv`: Command-line arguments and configuration
2237
- * - `stage`: Shared state object for cross-hook communication
2567
+ * This property is essential for filtering diagnostics by severity and determining whether
2568
+ * a build should fail or continue.
2238
2569
  *
2239
2570
  * @example
2240
2571
  * ```ts
2241
- * onStart: async (context) => {
2242
- * const { build, variantName, stage } = context;
2243
- * console.log(`Starting ${variantName} build`);
2244
- * stage.startTime = new Date();
2245
- *
2246
- * // Validate configuration
2247
- * if (!build.initialOptions.outdir) {
2248
- * return { errors: [{ text: 'Output directory required' }] };
2249
- * }
2572
+ * if (diagnostic.category === DiagnosticCategory.Error) {
2573
+ * console.error(`Error: ${diagnostic.message}`);
2574
+ * process.exit(1);
2250
2575
  * }
2251
2576
  * ```
2252
2577
  *
2253
- * @see {@link BuildContextInterface}
2578
+ * @since 2.0.0
2579
+ */
2580
+ category: DiagnosticCategory;
2581
+ }
2582
+ /**
2583
+ * Implements a TypeScript Language Service host with file snapshot caching and module resolution.
2584
+ *
2585
+ * @remarks
2586
+ * The `LanguageHostService` implements the {@link ts.LanguageServiceHost} interface to provide
2587
+ * TypeScript's language service with file system access, file snapshots, and compiler configuration.
2588
+ *
2589
+ * @example
2590
+ * ```ts
2591
+ * // Initialize with compiler options
2592
+ * const host = new LanguageHostService({
2593
+ * target: ts.ScriptTarget.ES2020,
2594
+ * module: ts.ModuleKind.ESNext,
2595
+ * paths: {
2596
+ * '@utils/*': ['src/utils/*'],
2597
+ * '@components/*': ['src/components/*']
2598
+ * }
2599
+ * });
2600
+ *
2601
+ * // Track files for analysis
2602
+ * host.touchFile('src/index.ts');
2603
+ * host.touchFiles(['src/utils.ts', 'src/types.ts']);
2604
+ *
2605
+ * // Get file snapshots for language service
2606
+ * const snapshot = host.getScriptSnapshot('src/index.ts');
2607
+ *
2608
+ * // Resolve module imports
2609
+ * const resolved = host.resolveModuleName('@utils/helpers', 'src/index.ts');
2610
+ *
2611
+ * // Check for path aliases
2612
+ * const hasAliases = host.aliasRegex !== undefined;
2613
+ *
2614
+ * // Update configuration
2615
+ * host.options = { target: ts.ScriptTarget.ES2022 };
2616
+ * ```
2617
+ *
2618
+ * @see {@link ts.LanguageServiceHost} for the implemented interface specification
2619
+ * @see {@link FilesModel} for file snapshot caching implementation
2620
+ *
2621
+ * @since 2.0.0
2622
+ */
2623
+ declare class LanguageHostService implements ts.LanguageServiceHost {
2624
+ private compilerOptions;
2625
+ /**
2626
+ * Reference to TypeScript's system interface for file operations.
2627
+ *
2628
+ * @remarks
2629
+ * Static reference to `ts.sys` that provides abstracted file system operations
2630
+ * (read, write, directory traversal) compatible with different environments (Node.js, browsers, etc.).
2631
+ * Used for all file I/O operations in this service to maintain platform independence.
2632
+ *
2633
+ * @see {@link ts.sys}
2254
2634
  *
2255
2635
  * @since 2.0.0
2256
2636
  */
2257
- onStart?: OnStartType;
2637
+ private static readonly sys;
2258
2638
  /**
2259
- * Hook handler executed when the build completes successfully without errors.
2639
+ * Cached regular expression for matching import/export statements with path aliases.
2260
2640
  *
2261
2641
  * @remarks
2262
- * Only called when `buildResult.errors.length === 0`, after all regular end hooks have completed.
2263
- * Receives the same result context as end hooks, containing build result, duration, variant name,
2264
- * arguments, and stage state. Useful for deployment, success notifications, and success-only operations.
2265
- *
2266
- * The handler receives `ResultContextInterface` providing access to:
2267
- * - `buildResult`: Final build outcome (guaranteed to have zero errors)
2268
- * - `duration`: Build duration in milliseconds
2269
- * - `variantName`: Build variant identifier
2270
- * - `argv`: Command-line arguments and configuration
2271
- * - `stage`: Shared state object for cross-hook communication
2642
+ * Compiled from `compilerOptions.paths` to efficiently detect imports using path aliases.
2643
+ * Regenerated when compiler options change. Undefined if no path aliases are configured.
2272
2644
  *
2273
- * @example
2274
- * ```ts
2275
- * onSuccess: async (context) => {
2276
- * const { buildResult, duration, variantName } = context;
2277
- * console.log(`${variantName} succeeded in ${duration}ms!`);
2278
- * await deploy(buildResult.metafile);
2279
- * }
2280
- * ```
2645
+ * Used by tools that need to identify which import statements use aliases for proper
2646
+ * handling during transformation or bundling.
2281
2647
  *
2282
- * @see {@link ResultContextInterface}
2648
+ * @see {@link generateAliasRegex} for pattern generation
2283
2649
  *
2284
2650
  * @since 2.0.0
2285
2651
  */
2286
- onSuccess?: OnEndType;
2652
+ private alias;
2287
2653
  /**
2288
- * Hook handler executed during module path resolution.
2654
+ * Cache for resolved module specifiers.
2289
2655
  *
2290
2656
  * @remarks
2291
- * Called when resolving import paths to file system locations with a resolve context containing
2292
- * the resolution arguments, variant name, and stage state. Can redirect imports, mark modules as
2293
- * external, or implement custom resolution logic. Multiple handlers execute, and their results are
2294
- * merged, with later hooks able to override earlier ones.
2657
+ * Stores the absolute resolved file path for each module name so repeated lookups
2658
+ * do not trigger TypeScript module resolution again. A value of `undefined` means
2659
+ * the module could not be resolved and that result is cached too.
2295
2660
  *
2296
- * The handler receives `ResolveContextInterface` providing access to:
2297
- * - `args`: Resolution arguments including import path and importer info
2298
- * - `variantName`: Build variant identifier
2299
- * - `argv`: Command-line arguments and configuration
2300
- * - `stage`: Shared state object for cross-hook communication
2661
+ * This cache is keyed by the raw import specifier, so it is only safe when the
2662
+ * same specifier is resolved in a compatible context.
2301
2663
  *
2302
- * @example
2303
- * ```ts
2304
- * onResolve: async (context) => {
2305
- * const { args, variantName } = context;
2664
+ * @since 2.3.0
2665
+ */
2666
+ private aliasCache;
2667
+ /**
2668
+ * Cache for TypeScript module resolution results.
2306
2669
  *
2307
- * // Redirect '@/' imports to 'src/'
2308
- * if (args.path.startsWith('@/')) {
2309
- * return {
2310
- * path: resolve('src', args.path.slice(2)),
2311
- * namespace: 'file'
2312
- * };
2313
- * }
2670
+ * @remarks
2671
+ * TypeScript's internal module resolution cache that stores resolution results to avoid
2672
+ * redundant lookups. Improves performance significantly when resolving many imports,
2673
+ * especially in large projects with complex path mappings.
2314
2674
  *
2315
- * // Mark as external in production
2316
- * if (variantName === 'production' && args.path.includes('node_modules')) {
2317
- * return { path: args.path, external: true };
2318
- * }
2319
- * }
2320
- * ```
2675
+ * Recreated when compiler options change (since different options may affect resolution).
2321
2676
  *
2322
- * @see {@link ResolveContextInterface}
2677
+ * @see {@link ts.createModuleResolutionCache}
2323
2678
  *
2324
2679
  * @since 2.0.0
2325
2680
  */
2326
- onResolve?: OnResolveType;
2327
- }
2328
- /**
2329
- * Configuration options for TypeScript declaration file generation.
2330
- *
2331
- * @remarks
2332
- * Controls how and where TypeScript declaration files (`.d.ts`) are generated during the build.
2333
- * These options work in conjunction with the TypeScript compiler to produce type definitions
2334
- * for bundled code.
2335
- *
2336
- * When `bundle` is true, declarations from multiple source files are combined into a single
2337
- * declaration file per entry point. When false, individual declaration files are generated
2338
- * for each source file.
2339
- *
2340
- * @example
2341
- * ```ts
2342
- * // Generate bundled declarations in custom directory
2343
- * const options: DeclarationOptionsInterface = {
2344
- * outDir: 'types',
2345
- * bundle: true
2346
- * };
2347
- * ```
2348
- *
2349
- * @see {@link BaseBuildDefinitionInterface.declaration}
2350
- *
2351
- * @since 2.0.0
2352
- */
2353
- interface DeclarationOptionsInterface {
2681
+ private moduleResolutionCache;
2354
2682
  /**
2355
- * Output directory for generated declaration files.
2683
+ * A set containing the file paths of all actively tracked script files.
2356
2684
  *
2357
2685
  * @remarks
2358
- * Specifies where `.d.ts` files should be written. If not provided, uses the TypeScript
2359
- * compiler's `declarationDir` or `outDir` from `tsconfig.json`.
2686
+ * This set ensures that files are tracked for later operations, such as retrieving script versions
2687
+ * or snapshots. Files are added to this set when they are first processed or read by the service.
2360
2688
  *
2361
2689
  * @example
2362
2690
  * ```ts
2363
- * outDir: 'dist/types'
2691
+ * trackFiles.add('/src/main.ts');
2692
+ * console.log(trackFiles.has('/src/main.ts')); // true
2364
2693
  * ```
2365
2694
  *
2695
+ * @see {@link getScriptFileNames} - Retrieves all tracked files.
2696
+ *
2366
2697
  * @since 2.0.0
2367
2698
  */
2368
- outDir?: string;
2699
+ private readonly trackFiles;
2369
2700
  /**
2370
- * Whether to bundle declarations into a single file per entry point.
2701
+ * Model for managing file snapshots and version tracking.
2371
2702
  *
2372
2703
  * @remarks
2373
- * When true, combines all declarations from imported modules into a single `.d.ts` file.
2374
- * When false, generates individual declaration files mirroring the source structure.
2704
+ * Delegates file snapshot management to {@link FilesModel} for centralized
2705
+ * caching and change detection. Snapshots are tracked by modification time
2706
+ * to detect file changes efficiently.
2375
2707
  *
2376
- * Bundling is useful for library distribution as it provides a single type definition file
2377
- * that consumers can reference.
2708
+ * @see {@link FilesModel}
2709
+ *
2710
+ * @since 2.0.0
2711
+ */
2712
+ private readonly filesCache;
2713
+ /**
2714
+ * Initializes a new {@link LanguageHostService} instance.
2715
+ *
2716
+ * @param compilerOptions - Optional TypeScript compiler options (defaults to an empty object)
2717
+ *
2718
+ * @remarks
2719
+ * Performs initialization including:
2720
+ * 1. Stores compiler options for later use
2721
+ * 2. Generates path alias regex from options if configured
2722
+ * 3. Creates module resolution cache with appropriate settings
2723
+ *
2724
+ * The module resolution cache is necessary for efficient resolution of imports in large projects.
2725
+ * Path alias regex is generated up-front and cached for performance.
2378
2726
  *
2379
2727
  * @example
2380
2728
  * ```ts
2381
- * bundle: true // Produces single bundled .d.ts
2382
- * bundle: false // Produces multiple .d.ts files
2729
+ * // Create host with default options
2730
+ * const host = new LanguageHostService();
2731
+ *
2732
+ * // Create host with specific compiler options
2733
+ * const host = new LanguageHostService({
2734
+ * target: ts.ScriptTarget.ES2020,
2735
+ * module: ts.ModuleKind.ESNext,
2736
+ * paths: {
2737
+ * '@utils/*': ['src/utils/*']
2738
+ * }
2739
+ * });
2383
2740
  * ```
2384
2741
  *
2385
2742
  * @since 2.0.0
2386
2743
  */
2387
- bundle?: boolean;
2388
- }
2389
- /**
2390
- * Configuration options for TypeScript type checking during builds.
2391
- *
2392
- * @remarks
2393
- * Controls how TypeScript type checking is performed and whether type errors should fail the build.
2394
- * Type checking runs in parallel with the esbuild compilation process for better performance.
2395
- *
2396
- * @example
2397
- * ```ts
2398
- * // Fail build on type errors
2399
- * const options: TypeCheckOptionsInterface = {
2400
- * failOnError: true
2401
- * };
2402
- * ```
2403
- *
2404
- * @see {@link BaseBuildDefinitionInterface.types}
2405
- *
2406
- * @since 2.0.0
2407
- */
2408
- interface TypeCheckOptionsInterface {
2744
+ constructor(compilerOptions?: CompilerOptions);
2409
2745
  /**
2410
- * Whether to fail the build when TypeScript errors are detected.
2746
+ * Regular expression that matches import/export statements using path aliases (if `paths` is configured).
2411
2747
  *
2412
2748
  * @remarks
2413
- * When true, any TypeScript errors will cause the build to fail with a non-zero exit code.
2414
- * When false, errors are logged, but the build continues and succeeds.
2749
+ * Used mainly for advanced refactoring or rewrite tools that need to identify aliased imports.
2415
2750
  *
2416
- * Useful in CI/CD pipelines where type safety must be enforced before deployment.
2751
+ * @since 2.0.0
2752
+ */
2753
+ get aliasRegex(): RegExp | undefined;
2754
+ /**
2755
+ * Replaces current compiler options and regenerates derived state (alias regex, module cache).
2417
2756
  *
2418
- * @example
2419
- * ```ts
2420
- * failOnError: true // Build fails on type errors
2421
- * failOnError: false // Type errors logged, but build continues
2422
- * ```
2757
+ * @param options - new compiler configuration
2423
2758
  *
2424
2759
  * @since 2.0.0
2425
2760
  */
2426
- failOnError?: boolean;
2427
- }
2428
- /**
2429
- * Base configuration shared across all build definitions, including common and variant builds.
2430
- * Provides common settings for hooks, type checking, code injection, and declaration generation.
2431
- *
2432
- * @remarks
2433
- * This interface defines the foundation for build configuration that applies to both common
2434
- * settings and individual build variants. Properties defined here can be overridden at the
2435
- * variant level for customization.
2436
- *
2437
- * Configuration inheritance:
2438
- * - Common build settings apply to all variants
2439
- * - Variant settings override common settings
2440
- * - Objects like `define` are merged (variant takes precedence)
2441
- * - Arrays and primitives replace common values
2442
- *
2443
- * @example
2444
- * ```ts
2445
- * const base: BaseBuildDefinitionInterface = {
2446
- * types: { failOnError: true },
2447
- * declaration: { bundle: true, outDir: 'types' },
2448
- * define: { 'process.env.NODE_ENV': '"production"' },
2449
- * banner: 'const x = "test"',
2450
- * hooks: {
2451
- * onSuccess: async () => console.log('Build complete!')
2452
- * }
2453
- * };
2454
- * ```
2455
- *
2456
- * @see {@link CommonBuildInterface}
2457
- * @see {@link VariantBuildInterface}
2458
- * @see {@link BuildConfigInterface}
2459
- *
2460
- * @since 2.0.0
2461
- */
2462
- interface BaseBuildDefinitionInterface {
2761
+ set options(options: CompilerOptions);
2463
2762
  /**
2464
- * Lifecycle hook handlers for build process stages.
2763
+ * Reloads all tracked file snapshots in the shared {@link FilesModel} cache.
2465
2764
  *
2466
2765
  * @remarks
2467
- * Registers custom handlers for various build lifecycle events including start, resolve,
2468
- * load, end, and success stages. All hooks are optional.
2766
+ * This method iterates over every currently tracked file path and touches each file again so
2767
+ * the cache can refresh its stored modification time, version, and content snapshot when needed.
2768
+ * It is useful in watch-mode or manual refresh scenarios where the underlying files may have changed
2769
+ * and dependent services need to observe the updated state.
2770
+ *
2771
+ * @since 2.3.0
2772
+ */
2773
+ static reload(): void;
2774
+ /**
2775
+ * Updates file snapshot in the cache and returns the current state.
2469
2776
  *
2470
- * @see {@link LifecycleHooksInterface}
2777
+ * @param path - file path (relative or absolute)
2778
+ * @returns current snapshot data (version, mtime, content snapshot)
2471
2779
  *
2780
+ * @see {@link FilesModel#touchFile}
2472
2781
  * @since 2.0.0
2473
2782
  */
2474
- lifecycle?: LifecycleHooksInterface;
2783
+ touchFile(path: string): FileSnapshotInterface;
2475
2784
  /**
2476
- * TypeScript type checking configuration.
2785
+ * Ensures multiple files are tracked and their snapshots are up to date.
2477
2786
  *
2478
- * @remarks
2479
- * Controls whether and how TypeScript type checking is performed during builds.
2480
- * - `true`: Enable type checking with default options
2481
- * - `false` or omitted: Disable type checking
2482
- * - Object: Enable with specific options like `failOnError`
2787
+ * @param filesPath - list of file paths to touch
2483
2788
  *
2484
- * @example
2485
- * ```ts
2486
- * types: true // Enable with default
2487
- * types: { failOnError: true } // Enable and fail on errors
2488
- * types: false // Disable
2489
- * ```
2789
+ * @since 2.0.0
2790
+ */
2791
+ touchFiles(filesPath: Array<string>): void;
2792
+ /**
2793
+ * Returns current compiler options used by this host.
2490
2794
  *
2491
- * @see {@link TypeCheckOptionsInterface}
2795
+ * @returns active TypeScript compiler configuration
2492
2796
  *
2493
2797
  * @since 2.0.0
2494
2798
  */
2495
- types?: boolean | TypeCheckOptionsInterface;
2799
+ getCompilationSettings(): CompilerOptions;
2496
2800
  /**
2497
- * Global constants to replace during bundling.
2801
+ * Checks whether a file exists on disk.
2498
2802
  *
2499
- * @remarks
2500
- * Defines key-value pairs for constant replacement during the build. Keys are identifiers
2501
- * or property access expressions, values are JSON-stringified replacements.
2803
+ * @param path - absolute path
2804
+ * @returns `true` if file exists
2502
2805
  *
2503
- * Commonly used for environment variables, feature flags, and build-time constants.
2806
+ * @since 2.0.0
2807
+ */
2808
+ fileExists(path: string): boolean;
2809
+ /**
2810
+ * Reads file content from disk.
2504
2811
  *
2505
- * @example
2506
- * ```ts
2507
- * define: {
2508
- * 'process.env.NODE_ENV': '"production"',
2509
- * 'DEBUG': 'false',
2510
- * 'VERSION': '"1.2.3"'
2511
- * }
2512
- * ```
2812
+ * @param path - absolute path
2813
+ * @param encoding - optional encoding (defaults to UTF-8)
2814
+ * @returns file content or `undefined` if read fails
2513
2815
  *
2514
2816
  * @since 2.0.0
2515
2817
  */
2516
- define?: Record<string, unknown>;
2818
+ readFile(path: string, encoding?: string): string | undefined;
2517
2819
  /**
2518
- * Code to inject at the beginning of each output file.
2820
+ * Lists files and/or directories matching criteria.
2519
2821
  *
2520
- * @remarks
2521
- * Can be a static string or a function that generates code based on build context.
2522
- * Commonly used for copyright notices, license headers, or polyfill imports.
2822
+ * @param path - starting directory
2823
+ * @param extensions - allowed file extensions
2824
+ * @param exclude - glob exclude patterns
2825
+ * @param include - glob include patterns
2826
+ * @param depth - max recursion depth
2827
+ * @returns matching file paths
2523
2828
  *
2524
- * @example
2525
- * ```ts
2526
- * banner: 'const x = "test"'
2527
- * banner: (name, argv) => `const x = "Built: ${new Date().toISOString()}"`
2528
- * ```
2829
+ * @since 2.0.0
2830
+ */
2831
+ readDirectory(path: string, extensions?: Array<string>, exclude?: Array<string>, include?: Array<string>, depth?: number): Array<string>;
2832
+ /**
2833
+ * Returns immediate subdirectories of a given path.
2529
2834
  *
2530
- * @see {@link InjectableCodeType}
2835
+ * @param path - directory to list
2836
+ * @returns subdirectory names
2531
2837
  *
2532
2838
  * @since 2.0.0
2533
2839
  */
2534
- banner?: {
2535
- [key: string]: InjectableCodeType;
2536
- };
2840
+ getDirectories(path: string): Array<string>;
2537
2841
  /**
2538
- * Code to inject at the end of each output file.
2842
+ * Checks whether a directory exists.
2539
2843
  *
2540
- * @remarks
2541
- * Can be a static string or a function that generates code based on build context.
2542
- * Commonly used for initialization code, analytics, or polyfills.
2844
+ * @param path - absolute path
2845
+ * @returns `true` if directory exists
2543
2846
  *
2544
- * @example
2545
- * ```ts
2546
- * footer: '// End of bundle'
2547
- * footer: (name, argv) => `console.log('Loaded ${name}');`
2548
- * ```
2847
+ * @since 2.0.0
2848
+ */
2849
+ directoryExists(path: string): boolean;
2850
+ /**
2851
+ * Returns the current working directory used as resolution base.
2549
2852
  *
2550
- * @see {@link InjectableCodeType}
2853
+ * @returns absolute path of cwd
2551
2854
  *
2552
2855
  * @since 2.0.0
2553
2856
  */
2554
- footer?: {
2555
- [key: string]: InjectableCodeType;
2556
- };
2857
+ getCurrentDirectory(): string;
2557
2858
  /**
2558
- * TypeScript declaration file generation configuration.
2859
+ * Returns names of all known script files tracked by this host.
2860
+ *
2861
+ * @returns array of resolved absolute paths
2559
2862
  *
2560
2863
  * @remarks
2561
- * Controls whether and how TypeScript declaration files are generated.
2562
- * - `true`: Generate declarations with default options
2563
- * - `false` or omitted: Do not generate declarations
2564
- * - Object: Generate with specific options like `outDir` and `bundle`
2864
+ * Only includes files previously requested via `getScriptSnapshot` or explicitly `touchFile`/`touchFiles`.
2565
2865
  *
2566
- * @example
2567
- * ```ts
2568
- * declaration: true // Generate with default
2569
- * declaration: { outDir: 'types', bundle: true } // Generate bundled in custom dir
2570
- * declaration: false // Disable
2571
- * ```
2866
+ * @since 2.0.0
2867
+ */
2868
+ getScriptFileNames(): Array<string>;
2869
+ /**
2870
+ * Returns a path to a default lib `.d.ts` file matching the given target.
2572
2871
  *
2573
- * @see {@link DeclarationOptionsInterface}
2872
+ * @param options - compiler options (mainly `target`)
2873
+ * @returns absolute path to lib.d.ts / lib.esxxxx.d.ts
2574
2874
  *
2575
2875
  * @since 2.0.0
2576
2876
  */
2577
- declaration?: boolean | DeclarationOptionsInterface;
2578
- }
2579
- /**
2580
- * Build configuration for a specific build variant including esbuild settings and entry points.
2581
- * Extends base configuration with variant-specific esbuild options and required entry points.
2582
- *
2583
- * @remarks
2584
- * A variant represents a distinct build target with its own entry points and esbuild configuration.
2585
- * Variants inherit settings from the common configuration but can override any property.
2586
- *
2587
- * The `esbuild` property excludes fields that are managed by the build system:
2588
- * - `plugins`: Managed by the hook provider
2589
- * - `define`, `banner`, `footer`: Managed by base configuration
2590
- * - `entryPoints`: Required at variant level (non-nullable)
2591
- *
2592
- * Multiple variants enable building different outputs from the same codebase, such as
2593
- * - Different module formats (ESM, CJS)
2594
- * - Different targets (Node.js, browser)
2595
- * - Different bundles (main, worker, tests)
2596
- *
2597
- * @example
2598
- * ```ts
2599
- * const variant: VariantBuildInterface = {
2600
- * esbuild: {
2601
- * entryPoints: ['src/index.ts'],
2602
- * outdir: 'dist/esm',
2603
- * format: 'esm',
2604
- * target: 'es2020'
2605
- * },
2606
- * types: true,
2607
- * declaration: { bundle: true, outDir: 'dist/types' }
2608
- * };
2609
- * ```
2610
- *
2611
- * @see {@link VariantsType}
2612
- * @see {@link CommonBuildInterface}
2613
- * @see {@link BaseBuildDefinitionInterface}
2614
- *
2615
- * @since 2.0.0
2616
- */
2617
- interface VariantBuildInterface extends BaseBuildDefinitionInterface {
2877
+ getDefaultLibFileName(options: CompilerOptions): string;
2618
2878
  /**
2619
- * Esbuild-specific configuration for this variant including entry points.
2879
+ * Returns string version identifier for the given file.
2880
+ *
2881
+ * @param path - file path
2882
+ * @returns version as string (usually `"0"`, `"1"`, `"2"`, …)
2620
2883
  *
2621
2884
  * @remarks
2622
- * Contains all esbuild options except those managed by the build system.
2623
- * The `entryPoints` field is required and must be non-empty to define what to build.
2885
+ * Tracks file in `trackFiles` set as a side effect so it appears in `getScriptFileNames()`.
2624
2886
  *
2625
- * Common options include:
2626
- * - `format`: Output format (esm, cjs, iife)
2627
- * - `outdir` or `outfile`: Output location
2628
- * - `target`: ECMAScript target version
2629
- * - `platform`: Target platform (browser, node, neutral)
2630
- * - `minify`: Whether to minify output
2631
- * - `sourcemap`: Whether to generate source maps
2887
+ * @since 2.0.0
2888
+ */
2889
+ getScriptVersion(path: string): string;
2890
+ /**
2891
+ * Checks whether a file is actively tracked (has been requested before).
2632
2892
  *
2633
- * @example
2634
- * ```ts
2635
- * esbuild: {
2636
- * entryPoints: ['src/index.ts', 'src/worker.ts'],
2637
- * outdir: 'dist',
2638
- * format: 'esm',
2639
- * target: 'es2020',
2640
- * minify: true,
2641
- * sourcemap: true
2642
- * }
2643
- * ```
2893
+ * @param path - file path
2894
+ * @returns `true` if the file is known to this host
2644
2895
  *
2645
2896
  * @since 2.0.0
2646
2897
  */
2647
- esbuild: Omit<BuildOptions, 'plugins' | 'define' | 'banner' | 'footer'>;
2648
- }
2649
- /**
2650
- * Shared configuration applied to all build variants.
2651
- * Extends base configuration with esbuild settings but without entry points.
2652
- *
2653
- * @remarks
2654
- * Common configuration provides default settings that apply to all variants unless overridden.
2655
- * This reduces duplication when multiple variants share similar settings.
2656
- *
2657
- * The `esbuild` property excludes managed fields and `entryPoints` (which must be variant-specific).
2658
- * Settings defined here are merged with variant-specific settings, with variants taking precedence.
2659
- *
2660
- * Typical use cases:
2661
- * - Shared compiler options (target, platform)
2662
- * - Common minification and sourcemap settings
2663
- * - Shared external dependencies
2664
- * - Default output configuration
2665
- *
2666
- * @example
2667
- * ```ts
2668
- * const common: CommonBuildInterface = {
2669
- * esbuild: {
2670
- * target: 'es2020',
2671
- * platform: 'node',
2672
- * sourcemap: true,
2673
- * external: ['react', 'react-dom']
2674
- * },
2675
- * types: { failOnError: true },
2676
- * declaration: true
2677
- * };
2678
- * ```
2679
- *
2680
- * @see {@link BaseBuildDefinitionInterface}
2681
- * @see {@link VariantBuildInterface}
2682
- * @see {@link BuildConfigInterface}
2683
- *
2684
- * @since 2.0.0
2685
- */
2686
- interface CommonBuildInterface extends BaseBuildDefinitionInterface {
2898
+ hasScriptSnapshot(path: string): boolean;
2899
+ /**
2900
+ * Returns an up-to-date script snapshot for the file.
2901
+ *
2902
+ * @param path - file path
2903
+ * @returns `IScriptSnapshot` or `undefined` if a file is missing/empty
2904
+ *
2905
+ * @remarks
2906
+ * Automatically touches the file (reads disk if needed) when no snapshot exists yet.
2907
+ *
2908
+ * @since 2.0.0
2909
+ */
2910
+ getScriptSnapshot(path: string): IScriptSnapshot | undefined;
2687
2911
  /**
2688
- * Shared esbuild configuration for all variants.
2912
+ * Resolves module import using current compiler options and cache.
2913
+ *
2914
+ * @param moduleName - module specifier
2915
+ * @param containingFile - path of a file containing the import
2916
+ * @returns resolution result (success and failed lookups)
2917
+ *
2918
+ * @since 2.0.0
2919
+ */
2920
+ resolveModuleName(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations;
2921
+ /**
2922
+ * Resolves a module specifier to its absolute file path using the host.
2923
+ *
2924
+ * @param moduleName - import/export specifier (e.g. "lodash", "./utils")
2925
+ * @param containingFile - path of a file containing the import
2926
+ * @returns resolved absolute path or `undefined` if resolution fails
2927
+ *
2928
+ * @since 2.0.0
2929
+ */
2930
+ resolveModuleFileName(moduleName: string, containingFile: string): string | undefined;
2931
+ /**
2932
+ * Rewrites path aliases in declaration content to relative paths.
2933
+ *
2934
+ * @param content - raw declaration text
2935
+ * @param fileName - source file name
2936
+ * @param type - file extension to append to resolved paths (e.g., `'.d.ts'`, `'.js'`), defaults to empty string
2937
+ * @returns content with aliases replaced by relative paths
2689
2938
  *
2690
2939
  * @remarks
2691
- * Contains esbuild options that apply to all variants by default. Variants can override
2692
- * any of these settings with their own specific values.
2940
+ * Ensures emitted files use portable relative imports instead of aliases.
2941
+ * The `type` parameter allows flexible transformation of resolved TypeScript source file extensions
2942
+ * (`.ts`, `.tsx`) to any target extension.
2693
2943
  *
2694
- * Excludes managed fields and `entryPoints` since entry points must be variant-specific.
2944
+ * **Common use cases**:
2945
+ * - Pass `'.d.ts'` for declaration file generation
2946
+ * - Pass `'.js'` for JavaScript output paths
2947
+ * - Pass `''` (default) to preserve the resolved file extension
2695
2948
  *
2696
2949
  * @example
2697
2950
  * ```ts
2698
- * esbuild: {
2699
- * platform: 'node',
2700
- * target: 'node18',
2701
- * external: ['typescript']
2702
- * }
2951
+ * // For regular source files (preserve extension)
2952
+ * const code = host.resolveAliases(content, 'src/index.ts');
2953
+ *
2954
+ * // For declaration files
2955
+ * const dts = host.resolveAliases(content, 'src/index.ts', '.d.ts');
2956
+ * // '@utils/helpers' -> './utils/helpers.d.ts'
2957
+ *
2958
+ * // For JavaScript output
2959
+ * const js = host.resolveAliases(content, 'src/index.ts', '.js');
2960
+ * // '@utils/helpers' -> './utils/helpers.js'
2703
2961
  * ```
2704
2962
  *
2705
2963
  * @since 2.0.0
2706
2964
  */
2707
- esbuild?: Omit<BuildOptions, 'plugins' | 'define' | 'banner' | 'footer'>;
2965
+ resolveAliases(content: string, fileName: string, type?: string): string;
2966
+ /**
2967
+ * Builds regex that matches import/export declarations using any configured path alias.
2968
+ *
2969
+ * @param config - compiler options containing `paths`
2970
+ * @returns regex or `undefined` if no `paths` configured
2971
+ *
2972
+ * @since 2.0.0
2973
+ */
2974
+ private static generateAliasRegex;
2708
2975
  }
2709
2976
  /**
2710
- * Maps variant names to their build configurations.
2711
- * Allows defining multiple build targets with different entry points and settings.
2977
+ * Extended TypeScript script snapshot that includes direct access to the underlying text content.
2712
2978
  *
2713
2979
  * @remarks
2714
- * This type represents a collection of named build variants. Each key is a user-defined
2715
- * variant name (e.g., 'esm', 'cjs', 'browser'), and each value is the complete build
2716
- * configuration for that variant.
2980
+ * This type augments TypeScript's standard `IScriptSnapshot` interface with a `text` property,
2981
+ * providing direct access to the original source text without requiring method calls.
2717
2982
  *
2718
- * Variant names are used for:
2719
- * - CLI targeting specific builds
2720
- * - Build output organization
2721
- * - Logging and error reporting
2722
- * - Parallel build coordination
2983
+ * TypeScript's native `IScriptSnapshot` only exposes text through the `getText()` method.
2984
+ * This extended type adds a `text` property for more convenient access to the full content,
2985
+ * particularly useful in caching scenarios where the source text is frequently referenced.
2986
+ *
2987
+ * Primarily used by {@link FilesModel} to store file content snapshots in an efficient,
2988
+ * readily accessible format for incremental compilation and language service operations.
2723
2989
  *
2724
2990
  * @example
2725
2991
  * ```ts
2726
- * const variants: VariantsType = {
2727
- * esm: {
2728
- * esbuild: {
2729
- * entryPoints: ['src/index.ts'],
2730
- * format: 'esm',
2731
- * outdir: 'dist/esm'
2732
- * }
2733
- * },
2734
- * cjs: {
2735
- * esbuild: {
2736
- * entryPoints: ['src/index.ts'],
2737
- * format: 'cjs',
2738
- * outdir: 'dist/cjs'
2739
- * }
2740
- * }
2992
+ * const snapshot: ScriptSnapshotType = {
2993
+ * ...ts.ScriptSnapshot.fromString(content),
2994
+ * text: content
2741
2995
  * };
2996
+ *
2997
+ * // Direct text access (convenient)
2998
+ * console.log(snapshot.text);
2999
+ *
3000
+ * // Method-based access (standard IScriptSnapshot)
3001
+ * console.log(snapshot.getText(0, snapshot.getLength()));
2742
3002
  * ```
2743
3003
  *
2744
- * @see {@link VariantBuildInterface}
2745
- * @see {@link BuildConfigInterface}
3004
+ * @see {@link IScriptSnapshot}
3005
+ * @see {@link FilesModel.touchFile}
3006
+ * @see {@link FileSnapshotInterface}
2746
3007
  *
2747
3008
  * @since 2.0.0
2748
3009
  */
2749
- type VariantsType = {
2750
- [variantName: string]: VariantBuildInterface;
3010
+ type ScriptSnapshotType = IScriptSnapshot & {
3011
+ text: string;
2751
3012
  };
2752
3013
  /**
2753
- * Complete build configuration including common settings, variants, and CLI options.
2754
- * Serves as the root configuration object for the entire build system.
2755
- *
2756
- * @remarks
2757
- * This interface defines the complete structure of the build configuration file. It includes:
2758
- * - Optional common settings shared across all variants
2759
- * - Required variants mapping defining all build targets
2760
- * - Optional verbose logging flag
2761
- * - Optional custom command-line argument definitions
2762
- *
2763
- * The configuration is typically exported from a `build.config.ts` or similar file and
2764
- * loaded by the build system at startup.
2765
- *
2766
- * Configuration resolution:
2767
- * 1. Load the configuration file
2768
- * 2. Parse command-line arguments using `userArgv` definitions
2769
- * 3. Merge common settings with each variant
2770
- * 4. Execute builds for all or selected variants
3014
+ * Represents the cached state of a single file for incremental TypeScript processing.
2771
3015
  *
2772
- * @example
2773
- * ```ts
2774
- * const config: BuildConfigInterface = {
2775
- * verbose: true,
2776
- * common: {
2777
- * esbuild: {
2778
- * platform: 'node',
2779
- * target: 'node18'
2780
- * },
2781
- * types: true
2782
- * },
2783
- * variants: {
2784
- * esm: {
2785
- * esbuild: {
2786
- * entryPoints: ['src/index.ts'],
2787
- * format: 'esm',
2788
- * outdir: 'dist/esm'
2789
- * }
2790
- * },
2791
- * cjs: {
2792
- * esbuild: {
2793
- * entryPoints: ['src/index.ts'],
2794
- * format: 'cjs',
2795
- * outdir: 'dist/cjs'
2796
- * }
2797
- * }
2798
- * },
2799
- * userArgv: {
2800
- * watch: { type: 'boolean', description: 'Watch for changes' }
2801
- * }
2802
- * };
2803
- * ```
3016
+ * Stores the modification timestamp, a version counter that increments on every meaningful change,
3017
+ * and an optional TypeScript `ScriptSnapshot` containing the file content in a memory-efficient form.
2804
3018
  *
2805
- * @see {@link VariantsType}
2806
- * @see {@link CommonBuildInterface}
2807
- * @see {@link PartialBuildConfigType}
3019
+ * Used by language services and build tools to quickly determine whether a file needs to be reparsed.
2808
3020
  *
2809
3021
  * @since 2.0.0
2810
3022
  */
2811
- interface BuildConfigInterface {
3023
+ interface FileSnapshotInterface {
2812
3024
  /**
2813
- * Shared configuration applied to all build variants.
3025
+ * Last known modification time of the file in milliseconds since epoch.
2814
3026
  *
2815
- * @remarks
2816
- * Optional common settings that are merged with each variant's configuration.
2817
- * Variants can override these settings with their own specific values.
3027
+ * Set to `0` when the file no longer exists or cannot be accessed.
2818
3028
  *
2819
- * @see {@link CommonBuildInterface}
3029
+ * @remarks
3030
+ * Compared directly against `fs.stat().mtimeMs` to detect changes without reading content.
2820
3031
  *
2821
3032
  * @since 2.0.0
2822
3033
  */
2823
- common?: CommonBuildInterface;
3034
+ mtimeMs: number;
2824
3035
  /**
2825
- * Enable verbose logging output during builds.
3036
+ * Monotonically increasing integer that changes whenever the file content or accessibility status changes.
3037
+ *
3038
+ * Used by TypeScript language services as the script version identifier.
2826
3039
  *
2827
3040
  * @remarks
2828
- * When true, outputs detailed build information including file processing,
2829
- * hook execution, and timing information. Useful for debugging build issues.
3041
+ * - Incremented on every successful content read with changed mtime
3042
+ * - Incremented when a file becomes unreadable (if it previously had content or version bigger than 0)
3043
+ * - Not incremented on no-op accesses (unchanged mtime)
2830
3044
  *
2831
3045
  * @example
2832
3046
  * ```ts
2833
- * verbose: true // Detailed output
2834
- * verbose: false // Minimal output
3047
+ * // Typical usage in LanguageServiceHost
3048
+ * getScriptVersion(fileName: string): string {
3049
+ * const snapshot = cache.touchFile(fileName);
3050
+ * return String(snapshot.version);
3051
+ * }
2835
3052
  * ```
2836
3053
  *
2837
3054
  * @since 2.0.0
2838
3055
  */
2839
- verbose?: boolean;
3056
+ version: number;
2840
3057
  /**
2841
- * Build variant definitions mapping names to configurations.
3058
+ * TypeScript script snapshot containing the file's source text, or `undefined` if the file is missing,
3059
+ * empty, or inaccessible.
2842
3060
  *
2843
3061
  * @remarks
2844
- * Required field defining all build targets. At least one variant must be defined.
2845
- * Each variant specifies its own entry points and can override common settings.
3062
+ * - Created via `ts.ScriptSnapshot.fromString(content)`
3063
+ * - Kept `undefined` for zero-length or non-readable files to save memory
3064
+ * - Consumers should check existence before calling methods like `getText()`
2846
3065
  *
2847
- * @see {@link VariantsType}
3066
+ * @see ScriptSnapshotType
3067
+ * @see {@link https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API#script-snapshot | TypeScript Compiler API – Script Snapshots}
2848
3068
  *
2849
3069
  * @since 2.0.0
2850
3070
  */
2851
- variants: VariantsType;
3071
+ contentSnapshot: ScriptSnapshotType | undefined;
2852
3072
  }
2853
- /**
2854
- * Partial build configuration for incremental or programmatic configuration building.
2855
- * Allows omitting variants and userArgv while making other fields optional.
2856
- *
2857
- * @remarks
2858
- * This type is useful when building configuration programmatically or when providing
2859
- * configuration fragments that will be merged with a base configuration. It makes
2860
- * all properties optional except `variants` and `userArgv` which are completely omitted.
2861
- *
2862
- * Common use cases:
2863
- * - Configuration presets or templates
2864
- * - Programmatic configuration generation
2865
- * - Configuration merging utilities
2866
- * - Partial overrides in build scripts
2867
- *
2868
- * @example
2869
- * ```ts
2870
- * const preset: PartialBuildConfigType = {
2871
- * verbose: true,
2872
- * common: {
2873
- * types: { failOnError: true },
2874
- * declaration: true
2875
- * }
2876
- * };
2877
- *
2878
- * // Merge with full config
2879
- * const fullConfig: BuildConfigInterface = {
2880
- * ...preset,
2881
- * variants: { ... }
2882
- * };
2883
- * ```
2884
- *
2885
- * @see {@link BuildConfigInterface}
2886
- *
2887
- * @since 2.0.0
2888
- */
2889
- type PartialBuildConfigType = Partial<BuildConfigInterface>;
2890
3073
  /**
2891
3074
  * Provides a file-watching service that tracks changes in the framework's root directory.
2892
3075
  *