@savvy-web/rslib-builder 0.2.2 → 0.4.0

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.
Files changed (4) hide show
  1. package/README.md +70 -18
  2. package/index.d.ts +1013 -392
  3. package/index.js +491 -209
  4. package/package.json +14 -5
package/index.d.ts CHANGED
@@ -46,6 +46,7 @@ import type { RawCopyPattern } from '@rspack/binding';
46
46
  import type { RsbuildPlugin } from '@rsbuild/core';
47
47
  import type { RslibConfig } from '@rslib/core';
48
48
  import type { SourceConfig } from '@rsbuild/core';
49
+ import ts from 'typescript';
49
50
 
50
51
  /**
51
52
  * Options for API model generation.
@@ -84,10 +85,12 @@ export declare interface ApiModelOptions {
84
85
  *
85
86
  * @example
86
87
  * ```typescript
87
- * apiModel: {
88
+ * import type { ApiModelOptions } from '@savvy-web/rslib-builder';
89
+ *
90
+ * const apiModel: ApiModelOptions = {
88
91
  * enabled: true,
89
- * localPaths: ["../docs-site/lib/packages/my-package"],
90
- * }
92
+ * localPaths: ['../docs-site/lib/packages/my-package'],
93
+ * };
91
94
  * ```
92
95
  */
93
96
  localPaths?: string[];
@@ -102,12 +105,14 @@ export declare interface ApiModelOptions {
102
105
  *
103
106
  * @example
104
107
  * ```typescript
105
- * apiModel: {
108
+ * import type { ApiModelOptions } from '@savvy-web/rslib-builder';
109
+ *
110
+ * const apiModel: ApiModelOptions = {
106
111
  * enabled: true,
107
112
  * tsdoc: {
108
- * tagDefinitions: [{ tagName: "@error", syntaxKind: "inline" }]
109
- * }
110
- * }
113
+ * tagDefinitions: [{ tagName: '@error', syntaxKind: 'inline' }],
114
+ * },
115
+ * };
111
116
  * ```
112
117
  */
113
118
  tsdoc?: TsDocOptions;
@@ -119,30 +124,109 @@ export declare interface ApiModelOptions {
119
124
  }
120
125
 
121
126
  /**
122
- * Plugin to read package.json and configure entry points based on exports.
127
+ * Plugin to automatically detect and configure entry points from package.json exports.
128
+ *
129
+ * @remarks
130
+ * This plugin reads your package.json exports field and automatically configures
131
+ * RSlib entry points, eliminating the need to manually specify entries in your config.
132
+ *
133
+ * ## Features
134
+ *
135
+ * - Automatically extracts entry points from package.json `exports` field
136
+ * - Supports both string and object export values
137
+ * - Handles bin field entries for CLI tools
138
+ * - Exposes entrypoints map for other plugins to consume
139
+ *
140
+ * ## How It Works
141
+ *
142
+ * 1. Reads package.json from the project root
143
+ * 2. Extracts entry points from the `exports` field
144
+ * 3. Configures RSlib with the discovered entries
145
+ * 4. Exposes the entrypoints map via `api.useExposed("entrypoints")`
146
+ *
147
+ * @param options - Plugin configuration options
148
+ *
149
+ * @example
150
+ * Basic usage (entries detected from package.json):
151
+ * ```typescript
152
+ * import { AutoEntryPlugin } from '@savvy-web/rslib-builder';
153
+ *
154
+ * export default {
155
+ * plugins: [AutoEntryPlugin()],
156
+ * };
157
+ * ```
158
+ *
159
+ * @example
160
+ * With nested directory output:
161
+ * ```typescript
162
+ * import { AutoEntryPlugin } from '@savvy-web/rslib-builder';
163
+ *
164
+ * export default {
165
+ * plugins: [
166
+ * AutoEntryPlugin({ exportsAsIndexes: true }),
167
+ * ],
168
+ * };
169
+ * ```
123
170
  *
124
- * @param options - Plugin configuration options with properties:
125
- * - `exportsAsIndexes`: When true, export paths create index files in nested directories
126
171
  * @public
127
172
  */
128
- export declare const AutoEntryPlugin: (options?: {
129
- exportsAsIndexes?: boolean | undefined;
130
- } | undefined) => RsbuildPlugin;
173
+ export declare const AutoEntryPlugin: (options?: AutoEntryPluginOptions | undefined) => RsbuildPlugin;
131
174
 
132
175
  /**
176
+ * Options for the AutoEntryPlugin.
133
177
  * @public
134
178
  */
135
- export declare type BuildTarget = "dev" | "npm";
179
+ export declare interface AutoEntryPluginOptions {
180
+ /**
181
+ * When enabled, export paths create `index.js` files in nested directories
182
+ * instead of using the export name as the filename.
183
+ *
184
+ * @remarks
185
+ * This is useful when you want cleaner import paths that don't require
186
+ * specifying a filename, relying on Node's directory index resolution.
187
+ *
188
+ * @example
189
+ * With `exportsAsIndexes: true` and this package.json:
190
+ * ```json
191
+ * {
192
+ * "exports": {
193
+ * ".": "./src/index.ts",
194
+ * "./utils": "./src/utils/index.ts"
195
+ * }
196
+ * }
197
+ * ```
198
+ *
199
+ * Output structure:
200
+ * ```
201
+ * dist/
202
+ * index.js
203
+ * utils/
204
+ * index.js
205
+ * ```
206
+ *
207
+ * @defaultValue false
208
+ */
209
+ exportsAsIndexes?: boolean;
210
+ }
136
211
 
137
212
  /**
138
- * Recursively collects all .d.ts and .d.ts.map files from a directory.
213
+ * Build target environment for library output.
214
+ *
215
+ * @remarks
216
+ * Each target produces different output optimizations:
217
+ * - `"dev"`: Development build with source maps for debugging
218
+ * - `"npm"`: Production build optimized for npm publishing
219
+ *
220
+ * @example
221
+ * Specifying targets via CLI:
222
+ * ```bash
223
+ * rslib build --env-mode dev
224
+ * rslib build --env-mode npm
225
+ * ```
139
226
  *
140
227
  * @public
141
228
  */
142
- export declare function collectDtsFiles(dir: string, baseDir?: string): Promise<Array<{
143
- path: string;
144
- relativePath: string;
145
- }>>;
229
+ export declare type BuildTarget = "dev" | "npm";
146
230
 
147
231
  /**
148
232
  * Plugin to generate TypeScript declaration files using tsgo and emit them through Rslib's asset pipeline.
@@ -180,7 +264,7 @@ export declare function collectDtsFiles(dir: string, baseDir?: string): Promise<
180
264
  *
181
265
  * @example
182
266
  * ```typescript
183
- * import { DtsPlugin } from "@savvy-web/shared/rslib";
267
+ * import { DtsPlugin } from "@savvy-web/rslib-builder";
184
268
  *
185
269
  * export default {
186
270
  * plugins: [
@@ -261,195 +345,540 @@ export declare interface DtsPluginOptions {
261
345
  }
262
346
 
263
347
  /**
264
- * Ensures a temp directory exists for declaration file generation.
265
- * @internal
348
+ * Plugin to manage the `files` array in package.json for npm publishing.
349
+ *
350
+ * @remarks
351
+ * This plugin automatically populates the `files` field in the output package.json
352
+ * with all compiled assets and essential files. Other plugins can add files via
353
+ * the shared `files-array` exposed through the Rsbuild API.
354
+ *
355
+ * ## Files Included
356
+ *
357
+ * - Essential files: package.json, README.md, LICENSE
358
+ * - All compiled JavaScript files
359
+ * - All declaration files (.d.ts)
360
+ * - Files added by other plugins via `api.useExposed("files-array")`
361
+ *
362
+ * ## Files Excluded
363
+ *
364
+ * - Source map files (.map)
365
+ * - Files prefixed with `!` in the files array (negated patterns)
366
+ *
367
+ * ## Plugin Interoperability
368
+ *
369
+ * Other plugins can add files to the array:
370
+ * ```typescript
371
+ * const filesArray = api.useExposed("files-array") as Set<string>;
372
+ * filesArray.add("my-custom-file.json");
373
+ * ```
374
+ *
375
+ * @param options - Plugin configuration options
376
+ *
377
+ * @example
378
+ * Basic usage:
379
+ * ```typescript
380
+ * import { FilesArrayPlugin } from '@savvy-web/rslib-builder';
381
+ *
382
+ * export default {
383
+ * plugins: [
384
+ * FilesArrayPlugin({ target: 'npm' }),
385
+ * ],
386
+ * };
387
+ * ```
388
+ *
389
+ * @example
390
+ * With custom file transformation:
391
+ * ```typescript
392
+ * import { FilesArrayPlugin } from '@savvy-web/rslib-builder';
393
+ *
394
+ * export default {
395
+ * plugins: [
396
+ * FilesArrayPlugin({
397
+ * target: 'npm',
398
+ * transformFiles({ filesArray }) {
399
+ * filesArray.add('CHANGELOG.md');
400
+ * },
401
+ * }),
402
+ * ],
403
+ * };
404
+ * ```
405
+ *
406
+ * @public
266
407
  */
267
- export declare function ensureTempDeclarationDir(cwd: string, name: string): Promise<string>;
408
+ export declare const FilesArrayPlugin: <TTarget extends string = string>(options?: FilesArrayPluginOptions<TTarget> | undefined) => RsbuildPlugin;
409
+
410
+ /**
411
+ * Options for the FilesArrayPlugin.
412
+ *
413
+ * @typeParam TTarget - The build target type, defaults to string
414
+ *
415
+ * @public
416
+ */
417
+ export declare interface FilesArrayPluginOptions<TTarget extends string = string> {
418
+ /**
419
+ * Optional callback to transform files after they're built but before the files array is finalized.
420
+ *
421
+ * @remarks
422
+ * Called during the "additional" stage of asset processing, after all other assets are created.
423
+ * Use this to copy/rename files or add additional files to the build output.
424
+ *
425
+ * @param context - Transform context containing:
426
+ * - `compilation`: Rspack compilation object with assets
427
+ * - `filesArray`: Set of files to be included in package.json `files` field
428
+ * - `target`: Current build target
429
+ *
430
+ * @example
431
+ * ```typescript
432
+ * import type { FilesArrayPluginOptions } from '@savvy-web/rslib-builder';
433
+ *
434
+ * const options: FilesArrayPluginOptions = {
435
+ * target: 'npm',
436
+ * transformFiles({ compilation, filesArray }) {
437
+ * // Add a custom file to the output
438
+ * filesArray.add('custom-file.txt');
439
+ * },
440
+ * };
441
+ * ```
442
+ */
443
+ transformFiles?: (context: {
444
+ /** Rspack compilation object with assets */
445
+ compilation: {
446
+ assets: Record<string, unknown>;
447
+ };
448
+ /** Set of files to include in package.json files array */
449
+ filesArray: Set<string>;
450
+ /** Current build target */
451
+ target: TTarget;
452
+ }) => void | Promise<void>;
453
+ /**
454
+ * Build target identifier (e.g., "dev", "npm").
455
+ *
456
+ * @remarks
457
+ * Passed to the `transformFiles` callback to allow target-specific transformations.
458
+ */
459
+ target: TTarget;
460
+ }
268
461
 
269
462
  /**
270
- * Extracts TypeScript entry points from package.json for build configuration.
463
+ * Analyzes TypeScript import relationships to discover all files
464
+ * reachable from specified entry points.
271
465
  *
272
466
  * @remarks
273
- * This class analyzes package.json export and bin configurations to identify
274
- * TypeScript source files that need to be built. It handles various export
275
- * formats and automatically maps JavaScript output paths back to their
276
- * TypeScript source files.
277
- *
278
- * **Export Path Mapping:**
279
- * - Converts export keys to entry names (e.g., "./utils" becomes "utils")
280
- * - Maps the root export "." to "index" entry
281
- * - Replaces path separators with hyphens for nested exports (default)
282
- * - When `exportsAsIndexes` is true, preserves path structure
283
- *
284
- * **Source Path Resolution:**
285
- * - Prioritizes TypeScript files (.ts/.tsx) over JavaScript files
286
- * - Maps /dist/ JavaScript paths back to /src/ TypeScript sources
287
- * - Supports conditional exports (import, default, types fields)
467
+ * This class uses the TypeScript compiler API to trace import statements
468
+ * and discover all files that are part of the public API. It handles:
469
+ *
470
+ * - Static imports: `import { foo } from "./module"`
471
+ * - Dynamic imports: `import("./module")`
472
+ * - Re-exports: `export * from "./module"` and `export { foo } from "./module"`
473
+ * - Circular imports (via visited set tracking)
474
+ *
475
+ * The class automatically filters out:
476
+ * - Files in node_modules
477
+ * - Declaration files (.d.ts)
478
+ * - Test files (*.test.ts, *.spec.ts)
479
+ * - Files in __test__ directories
480
+ *
481
+ * ## Static Methods vs Instance Methods
482
+ *
483
+ * For simple one-off analysis, use the static convenience methods:
484
+ * - {@link ImportGraph.fromEntries} - Trace from explicit entry paths
485
+ * - {@link ImportGraph.fromPackageExports} - Trace from package.json exports
486
+ *
487
+ * For repeated analysis or custom configuration, create an instance
488
+ * and use the instance methods which reuse the TypeScript program.
288
489
  *
289
490
  * @example
491
+ * Using static methods (recommended for most cases):
290
492
  * ```typescript
291
- * const extractor = new EntryExtractor();
493
+ * import { ImportGraph } from '@savvy-web/rslib-builder';
292
494
  *
293
- * const packageJson = {
294
- * exports: {
295
- * ".": "./src/index.ts",
296
- * "./utils": "./src/utils.ts",
297
- * },
298
- * bin: {
299
- * "my-cli": "./src/bin/cli.ts"
300
- * }
301
- * };
495
+ * // Trace from explicit entries
496
+ * const result = ImportGraph.fromEntries(
497
+ * ['./src/index.ts', './src/cli.ts'],
498
+ * { rootDir: process.cwd() }
499
+ * );
500
+ *
501
+ * // Trace from package.json exports
502
+ * const result = ImportGraph.fromPackageExports(
503
+ * './package.json',
504
+ * { rootDir: process.cwd() }
505
+ * );
506
+ * ```
302
507
  *
303
- * const result = extractor.extract(packageJson);
304
- * console.log(result.entries);
305
- * // {
306
- * // "index": "./src/index.ts",
307
- * // "utils": "./src/utils.ts",
308
- * // "bin/my-cli": "./src/bin/cli.ts"
309
- * // }
508
+ * @example
509
+ * Using instance methods (for repeated analysis):
510
+ * ```typescript
511
+ * import { ImportGraph } from '@savvy-web/rslib-builder';
512
+ *
513
+ * const graph = new ImportGraph({ rootDir: '/path/to/project' });
514
+ *
515
+ * // Reuses the TypeScript program across multiple calls
516
+ * const libResult = graph.traceFromEntries(['./src/index.ts']);
517
+ * const cliResult = graph.traceFromEntries(['./src/cli.ts']);
310
518
  * ```
311
519
  *
312
520
  * @public
313
521
  */
314
- export declare class EntryExtractor {
522
+ export declare class ImportGraph {
315
523
  private readonly options;
316
- constructor(options?: EntryExtractorOptions);
524
+ private readonly sys;
525
+ private program;
526
+ private compilerOptions;
527
+ private moduleResolutionCache;
528
+ constructor(options: ImportGraphOptions);
317
529
  /**
318
- * Extracts entry points from package.json exports and bin fields.
530
+ * Trace all imports from the given entry points.
319
531
  *
320
- * @param packageJson - The package.json to extract entries from
321
- * @returns Object containing the extracted entries
532
+ * @param entryPaths - Paths to entry files (relative to rootDir or absolute)
533
+ * @returns Deduplicated list of all reachable TypeScript files
322
534
  */
323
- extract(packageJson: PackageJson): ExtractedEntries;
535
+ traceFromEntries(entryPaths: string[]): ImportGraphResult;
324
536
  /**
325
- * Extracts entries from the exports field.
537
+ * Trace imports from package.json exports.
538
+ *
539
+ * @remarks
540
+ * Convenience method that extracts entry points from package.json
541
+ * using EntryExtractor, then traces all imports from those entries.
542
+ *
543
+ * @param packageJsonPath - Path to package.json (relative to rootDir or absolute)
544
+ * @returns Deduplicated list of all reachable TypeScript files
326
545
  */
327
- private extractFromExports;
546
+ traceFromPackageExports(packageJsonPath: string): ImportGraphResult;
328
547
  /**
329
- * Extracts entries from the bin field.
548
+ * Initialize the TypeScript program for module resolution.
330
549
  */
331
- private extractFromBin;
550
+ private initializeProgram;
332
551
  /**
333
- * Resolves a source path from various export value formats.
552
+ * Find tsconfig.json path.
334
553
  */
335
- private resolveSourcePath;
554
+ private findTsConfig;
336
555
  /**
337
- * Resolves a path to its TypeScript source equivalent.
338
- * Maps /dist/ JavaScript paths back to /src/ TypeScript sources.
556
+ * Resolve entry path to absolute path.
339
557
  */
340
- private resolveToTypeScript;
558
+ private resolveEntryPath;
341
559
  /**
342
- * Checks if a path points to a TypeScript file.
560
+ * Recursively trace imports from a source file.
343
561
  */
344
- private isTypeScriptFile;
562
+ private traceImports;
345
563
  /**
346
- * Creates an entry name from an export key.
564
+ * Extract all import/export module specifiers from a source file.
347
565
  */
348
- private createEntryName;
349
- }
350
-
351
- /**
352
- * Options for entry extraction.
353
- * @public
354
- */
355
- export declare interface EntryExtractorOptions {
566
+ private extractImports;
356
567
  /**
357
- * When true, export paths create index files in nested directories.
358
- * "./foo/bar" becomes "foo/bar/index" instead of "foo-bar".
568
+ * Resolve a module specifier to an absolute file path.
359
569
  */
360
- exportsAsIndexes?: boolean;
570
+ private resolveImport;
571
+ /**
572
+ * Check if a path is an external module (node_modules).
573
+ */
574
+ private isExternalModule;
575
+ /**
576
+ * Check if a file should be included in results.
577
+ * Filters out test files and non-TypeScript files.
578
+ */
579
+ private isSourceFile;
580
+ /**
581
+ * Traces TypeScript imports from entry points.
582
+ *
583
+ * @remarks
584
+ * Static convenience method that creates an ImportGraph instance
585
+ * and traces imports in one call. For repeated analysis where you want
586
+ * to reuse the TypeScript program, create an instance and use
587
+ * {@link ImportGraph.traceFromEntries} instead.
588
+ *
589
+ * @param entryPaths - Paths to entry files (relative to rootDir or absolute)
590
+ * @param options - Import graph configuration options
591
+ * @returns All TypeScript files reachable from the entries
592
+ *
593
+ * @example
594
+ * ```typescript
595
+ * import { ImportGraph } from '@savvy-web/rslib-builder';
596
+ *
597
+ * const result = ImportGraph.fromEntries(
598
+ * ['./src/index.ts', './src/cli.ts'],
599
+ * { rootDir: process.cwd() }
600
+ * );
601
+ * console.log('Found files:', result.files);
602
+ * ```
603
+ */
604
+ static fromEntries(entryPaths: string[], options: ImportGraphOptions): ImportGraphResult;
605
+ /**
606
+ * Traces TypeScript imports from package.json exports.
607
+ *
608
+ * @remarks
609
+ * Static convenience method that extracts entry points from package.json exports
610
+ * and traces all imports to find public API files. For repeated analysis,
611
+ * create an instance and use {@link ImportGraph.traceFromPackageExports} instead.
612
+ *
613
+ * @param packageJsonPath - Path to package.json (relative to rootDir or absolute)
614
+ * @param options - Import graph configuration options
615
+ * @returns All TypeScript files reachable from the package exports
616
+ *
617
+ * @example
618
+ * ```typescript
619
+ * import { ImportGraph } from '@savvy-web/rslib-builder';
620
+ *
621
+ * const result = ImportGraph.fromPackageExports(
622
+ * './package.json',
623
+ * { rootDir: process.cwd() }
624
+ * );
625
+ * console.log('Public API files:', result.files);
626
+ * ```
627
+ */
628
+ static fromPackageExports(packageJsonPath: string, options: ImportGraphOptions): ImportGraphResult;
361
629
  }
362
630
 
363
631
  /**
364
- * Result of entry extraction.
632
+ * Structured error from import graph analysis.
633
+ *
634
+ * @remarks
635
+ * Provides detailed error information including the error type for
636
+ * programmatic handling, a human-readable message, and the relevant
637
+ * file path when applicable.
638
+ *
639
+ * @example
640
+ * ```typescript
641
+ * import type { ImportGraphError } from '@savvy-web/rslib-builder';
642
+ *
643
+ * function handleErrors(errors: ImportGraphError[]): void {
644
+ * for (const error of errors) {
645
+ * switch (error.type) {
646
+ * case 'tsconfig_not_found':
647
+ * console.warn('No tsconfig.json found, using defaults');
648
+ * break;
649
+ * case 'entry_not_found':
650
+ * console.error(`Missing entry: ${error.path}`);
651
+ * break;
652
+ * default:
653
+ * console.error(error.message);
654
+ * }
655
+ * }
656
+ * }
657
+ * ```
658
+ *
365
659
  * @public
366
660
  */
367
- export declare interface ExtractedEntries {
661
+ export declare interface ImportGraphError {
368
662
  /**
369
- * Entry name to TypeScript source path mapping.
663
+ * The type of error that occurred.
664
+ *
665
+ * @remarks
666
+ * Use this field for programmatic error handling to distinguish
667
+ * between different failure modes.
370
668
  */
371
- entries: Record<string, string>;
669
+ type: ImportGraphErrorType;
670
+ /**
671
+ * Human-readable error message.
672
+ *
673
+ * @remarks
674
+ * Suitable for logging or displaying to users.
675
+ */
676
+ message: string;
677
+ /**
678
+ * The file path related to the error, if applicable.
679
+ *
680
+ * @remarks
681
+ * Present for errors related to specific files like missing entries
682
+ * or file read failures.
683
+ */
684
+ path?: string;
372
685
  }
373
686
 
374
687
  /**
375
- * Plugin to manage the files array in package.json
376
- * Adds essential files like package.json, README.md, LICENSE and compiled outputs
377
- * Other plugins can use api.useExposed("files-array") to add additional files
688
+ * Types of errors that can occur during import graph analysis.
689
+ *
690
+ * @remarks
691
+ * These error types allow consumers to handle different failure modes
692
+ * appropriately. For example, a missing tsconfig might be handled differently
693
+ * than a missing entry file.
694
+ *
378
695
  * @public
379
696
  */
380
- export declare const FilesArrayPlugin: <TTarget extends string = string>(options?: FilesArrayPluginOptions<TTarget> | undefined) => RsbuildPlugin;
697
+ export declare type ImportGraphErrorType = "tsconfig_not_found" | "tsconfig_read_error" | "tsconfig_parse_error" | "package_json_not_found" | "package_json_parse_error" | "entry_not_found" | "file_read_error";
381
698
 
382
699
  /**
700
+ * Options for configuring the ImportGraph analyzer.
701
+ *
702
+ * @remarks
703
+ * These options control how the ImportGraph traverses and resolves
704
+ * TypeScript module imports. The `rootDir` is required and serves as
705
+ * the base for resolving relative paths and finding the tsconfig.json.
706
+ *
707
+ * @example
708
+ * ```typescript
709
+ * import type { ImportGraphOptions } from '@savvy-web/rslib-builder';
710
+ *
711
+ * const options: ImportGraphOptions = {
712
+ * rootDir: '/path/to/project',
713
+ * tsconfigPath: './tsconfig.build.json',
714
+ * };
715
+ * ```
716
+ *
383
717
  * @public
384
718
  */
385
- export declare interface FilesArrayPluginOptions<TTarget extends string = string> {
719
+ export declare interface ImportGraphOptions {
386
720
  /**
387
- * Optional callback to transform files after they're built but before the files array is finalized.
388
- * Called in the additional stage, after all assets are created.
721
+ * The project root directory.
722
+ *
723
+ * @remarks
724
+ * All relative paths (entry points, tsconfig path) are resolved from this directory.
725
+ * This should typically be the package root containing your `package.json`.
389
726
  */
390
- transformFiles?: (context: {
391
- /** Rspack compilation object with assets */
392
- compilation: {
393
- assets: Record<string, unknown>;
394
- };
395
- filesArray: Set<string>;
396
- target: TTarget;
397
- }) => void | Promise<void>;
398
- /** Build target (dev/npm/jsr) */
399
- target: TTarget;
727
+ rootDir: string;
728
+ /**
729
+ * Custom path to the TypeScript configuration file.
730
+ *
731
+ * @remarks
732
+ * If not provided, the analyzer searches for `tsconfig.json` starting from `rootDir`
733
+ * and walking up the directory tree. The tsconfig is used for module resolution
734
+ * settings including path aliases and module resolution strategy.
735
+ *
736
+ * @defaultValue Searches for tsconfig.json from rootDir
737
+ */
738
+ tsconfigPath?: string;
739
+ /**
740
+ * Custom TypeScript system for file operations.
741
+ *
742
+ * @remarks
743
+ * This is primarily used for testing to provide a mock filesystem.
744
+ * In production use, this defaults to `ts.sys` which uses the real filesystem.
745
+ *
746
+ * @defaultValue ts.sys
747
+ * @internal
748
+ */
749
+ sys?: ts.System;
750
+ /**
751
+ * Additional patterns to exclude from results.
752
+ *
753
+ * @remarks
754
+ * Patterns are matched against file paths using simple string inclusion.
755
+ * Use this to exclude files that don't match the default test file patterns.
756
+ *
757
+ * The default exclusions are always applied:
758
+ * - `.test.` and `.spec.` files
759
+ * - `__test__` and `__tests__` directories
760
+ * - `.d.ts` declaration files
761
+ *
762
+ * @example
763
+ * ```typescript
764
+ * const graph = new ImportGraph({
765
+ * rootDir: process.cwd(),
766
+ * excludePatterns: ['/fixtures/', '/mocks/', '.stories.'],
767
+ * });
768
+ * ```
769
+ *
770
+ * @defaultValue []
771
+ */
772
+ excludePatterns?: string[];
400
773
  }
401
774
 
402
775
  /**
403
- * Finds the TypeScript config file.
404
- * @internal
405
- */
406
- export declare function findTsConfig(cwd: string, tsconfigPath?: string): string | null;
407
-
408
- /**
409
- * Flexible type definition for package.json exports field that accommodates various export formats.
776
+ * Result of import graph analysis.
410
777
  *
411
778
  * @remarks
412
- * This type extends the standard PackageJson.Exports to allow for custom fields and nested
413
- * structures commonly found in complex package configurations. It supports:
414
- * - Standard exports objects with conditions
415
- * - Custom field exports
416
- * - Array-based exports (for fallbacks)
417
- * - Null/undefined values for conditional exports
418
- */
419
- declare type FlexibleExports = PackageJson.Exports | Record<string, unknown> | FlexibleExports[] | undefined | null;
420
-
421
- /**
422
- * Generates command-line arguments for tsgo.
779
+ * Contains the complete set of TypeScript source files discovered by tracing
780
+ * imports from entry points. The analysis is non-fatal: errors are collected
781
+ * and tracing continues for other paths even when some imports fail to resolve.
782
+ *
783
+ * @example
784
+ * ```typescript
785
+ * import type { ImportGraphResult } from '@savvy-web/rslib-builder';
786
+ *
787
+ * function processResult(result: ImportGraphResult): void {
788
+ * if (result.errors.length > 0) {
789
+ * console.warn('Some imports could not be resolved:', result.errors);
790
+ * }
791
+ * console.log(`Found ${result.files.length} files from ${result.entries.length} entries`);
792
+ * }
793
+ * ```
423
794
  *
424
795
  * @public
425
796
  */
426
- export declare function generateTsgoArgs(options: {
427
- configPath: string;
428
- declarationDir: string;
429
- rootDir?: string;
430
- tsBuildInfoFile?: string;
431
- }): string[];
432
-
433
- /**
434
- * Gets the path to the tsgo (TypeScript native compiler) executable.
435
- * Uses workspace-tools to find the workspace root and searches for tsgo binary.
436
- * Supports npm, pnpm, yarn, rush, and lerna workspaces.
437
- * @returns The absolute path to the tsgo binary
438
- * @internal
439
- */
440
- export declare function getTsgoBinPath(): string;
441
-
442
- /**
443
- * Extracts the unscoped package name from a potentially scoped package name.
444
- * @param name - The package name (e.g., `@scope/package` or `package`)
445
- * @returns The unscoped name (e.g., `package`)
446
- * @internal
447
- */
448
- export declare function getUnscopedPackageName(name: string): string;
797
+ export declare interface ImportGraphResult {
798
+ /**
799
+ * All TypeScript source files reachable from the entry points.
800
+ *
801
+ * @remarks
802
+ * Paths are absolute, normalized, and sorted alphabetically.
803
+ * Test files (`.test.ts`, `.spec.ts`) and test directories (`__test__`, `__tests__`)
804
+ * are automatically filtered out from results.
805
+ */
806
+ files: string[];
807
+ /**
808
+ * The entry points that were traced.
809
+ *
810
+ * @remarks
811
+ * Paths are absolute and normalized. These are the starting points
812
+ * from which the import graph was traversed.
813
+ */
814
+ entries: string[];
815
+ /**
816
+ * Errors encountered during import graph analysis.
817
+ *
818
+ * @remarks
819
+ * These errors are non-fatal: tracing continues despite individual failures.
820
+ * Common errors include missing entry files, unresolvable imports,
821
+ * or tsconfig parsing failures.
822
+ *
823
+ * Each error includes a `type` field for programmatic handling and
824
+ * a human-readable `message`. Some errors also include a `path` field
825
+ * indicating the relevant file.
826
+ */
827
+ errors: ImportGraphError[];
828
+ }
449
829
 
450
830
  /**
831
+ * Builder for Node.js ESM libraries using RSlib.
832
+ *
833
+ * @remarks
834
+ * NodeLibraryBuilder provides a high-level API for building modern ESM Node.js libraries.
835
+ * It handles TypeScript compilation, declaration bundling, package.json transformation,
836
+ * and multi-target builds (dev and npm).
837
+ *
838
+ * Features:
839
+ * - Automatic entry point detection from package.json exports
840
+ * - TypeScript declarations via tsgo + API Extractor
841
+ * - pnpm catalog and workspace protocol resolution
842
+ * - Source maps for development builds
843
+ * - Configurable external dependencies and type bundling
844
+ *
845
+ * @example
846
+ * Basic usage in `rslib.config.ts`:
847
+ * ```typescript
848
+ * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder';
849
+ *
850
+ * export default NodeLibraryBuilder.create();
851
+ * ```
852
+ *
853
+ * @example
854
+ * With custom options:
855
+ * ```typescript
856
+ * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder';
857
+ *
858
+ * export default NodeLibraryBuilder.create({
859
+ * externals: ['@rslib/core', '@rsbuild/core'],
860
+ * dtsBundledPackages: ['picocolors'],
861
+ * apiModel: true,
862
+ * transform({ target, pkg }) {
863
+ * if (target === 'npm') {
864
+ * delete pkg.devDependencies;
865
+ * }
866
+ * return pkg;
867
+ * },
868
+ * });
869
+ * ```
870
+ *
871
+ * @example
872
+ * Build commands:
873
+ * ```bash
874
+ * # Development build (with source maps)
875
+ * rslib build --env-mode dev
876
+ *
877
+ * # Production build (for npm publishing)
878
+ * rslib build --env-mode npm
879
+ * ```
880
+ *
451
881
  * @public
452
- * Node library builder class
453
882
  */
454
883
  export declare class NodeLibraryBuilder {
455
884
  static DEFAULT_OPTIONS: NodeLibraryBuilderOptions;
@@ -518,9 +947,11 @@ export declare interface NodeLibraryBuilderOptions {
518
947
  *
519
948
  * @example
520
949
  * ```typescript
521
- * NodeLibraryBuilder.create({
522
- * externals: ['@rslib/core', '@rsbuild/core']
523
- * })
950
+ * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder';
951
+ *
952
+ * export default NodeLibraryBuilder.create({
953
+ * externals: ['@rslib/core', '@rsbuild/core'],
954
+ * });
524
955
  * ```
525
956
  */
526
957
  externals?: (string | RegExp)[];
@@ -536,9 +967,11 @@ export declare interface NodeLibraryBuilderOptions {
536
967
  *
537
968
  * @example
538
969
  * ```typescript
539
- * NodeLibraryBuilder.create({
540
- * dtsBundledPackages: ['@pnpm/lockfile.types', '@pnpm/types', 'picocolors']
541
- * })
970
+ * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder';
971
+ *
972
+ * export default NodeLibraryBuilder.create({
973
+ * dtsBundledPackages: ['@pnpm/lockfile.types', '@pnpm/types', 'picocolors'],
974
+ * });
542
975
  * ```
543
976
  */
544
977
  dtsBundledPackages?: string[];
@@ -553,16 +986,18 @@ export declare interface NodeLibraryBuilderOptions {
553
986
  *
554
987
  * @example
555
988
  * ```typescript
556
- * NodeLibraryBuilder.create({
557
- * transformFiles({ compilation, filesArray, target }) {
989
+ * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder';
990
+ *
991
+ * export default NodeLibraryBuilder.create({
992
+ * transformFiles({ compilation, filesArray }) {
558
993
  * // Copy index.cjs to .pnpmfile.cjs
559
994
  * const indexAsset = compilation.assets['index.cjs'];
560
995
  * if (indexAsset) {
561
996
  * compilation.assets['.pnpmfile.cjs'] = indexAsset;
562
997
  * filesArray.add('.pnpmfile.cjs');
563
998
  * }
564
- * }
565
- * })
999
+ * },
1000
+ * });
566
1001
  * ```
567
1002
  */
568
1003
  transformFiles?: (context: {
@@ -582,16 +1017,17 @@ export declare interface NodeLibraryBuilderOptions {
582
1017
  *
583
1018
  * @example
584
1019
  * ```typescript
585
- * NodeLibraryBuilder.create({
1020
+ * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder';
1021
+ *
1022
+ * export default NodeLibraryBuilder.create({
586
1023
  * transform({ target, pkg }) {
587
1024
  * if (target === 'npm') {
588
- * // Mutation approach
589
1025
  * delete pkg.devDependencies;
590
1026
  * delete pkg.scripts;
591
1027
  * }
592
1028
  * return pkg;
593
- * }
594
- * })
1029
+ * },
1030
+ * });
595
1031
  * ```
596
1032
  */
597
1033
  transform?: TransformPackageJsonFn;
@@ -606,282 +1042,249 @@ export declare interface NodeLibraryBuilderOptions {
606
1042
  * The file is emitted to dist but excluded from npm publish (added as negated pattern in `files` array).
607
1043
  *
608
1044
  * @example
1045
+ * Enable API model generation with defaults:
1046
+ * ```typescript
1047
+ * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder';
1048
+ *
1049
+ * export default NodeLibraryBuilder.create({
1050
+ * apiModel: true,
1051
+ * });
1052
+ * ```
1053
+ *
1054
+ * @example
1055
+ * Enable with custom filename:
1056
+ * ```typescript
1057
+ * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder';
1058
+ *
1059
+ * export default NodeLibraryBuilder.create({
1060
+ * apiModel: {
1061
+ * enabled: true,
1062
+ * filename: 'my-package.api.json',
1063
+ * },
1064
+ * });
1065
+ * ```
1066
+ */
1067
+ apiModel?: ApiModelOptions | boolean;
1068
+ /**
1069
+ * Options for TSDoc lint validation.
1070
+ * When enabled, validates TSDoc comments before the build starts.
1071
+ *
1072
+ * @remarks
1073
+ * Uses ESLint with `eslint-plugin-tsdoc` to validate TSDoc syntax.
1074
+ * By default, throws errors in CI environments and logs errors locally.
1075
+ * The generated `tsdoc.json` config is persisted locally for IDE integration.
1076
+ *
1077
+ * @example
1078
+ * Enable with defaults (throws in CI, errors locally):
1079
+ * ```typescript
1080
+ * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder';
1081
+ *
1082
+ * export default NodeLibraryBuilder.create({
1083
+ * tsdocLint: true,
1084
+ * });
1085
+ * ```
1086
+ *
1087
+ * @example
1088
+ * Enable with custom configuration:
609
1089
  * ```typescript
610
- * // Enable API model generation with defaults
611
- * NodeLibraryBuilder.create({
612
- * apiModel: true,
613
- * })
1090
+ * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder';
614
1091
  *
615
- * // Enable with custom filename
616
- * NodeLibraryBuilder.create({
617
- * apiModel: {
618
- * enabled: true,
619
- * filename: "my-package.api.json",
1092
+ * export default NodeLibraryBuilder.create({
1093
+ * tsdocLint: {
1094
+ * tsdoc: {
1095
+ * tagDefinitions: [{ tagName: '@error', syntaxKind: 'block' }],
1096
+ * },
1097
+ * onError: 'throw',
1098
+ * persistConfig: true,
620
1099
  * },
621
- * })
1100
+ * });
622
1101
  * ```
623
1102
  */
624
- apiModel?: ApiModelOptions | boolean;
1103
+ tsdocLint?: TsDocLintPluginOptions | boolean;
625
1104
  }
626
1105
 
627
1106
  /**
628
- * Transforms package.json for build output and publishing.
1107
+ * Plugin to transform package.json for distribution.
629
1108
  *
630
1109
  * @remarks
631
- * This class consolidates all package.json transformation logic including:
632
- * - Path transformations (src/ to dist/, .ts to .js)
633
- * - Export conditions generation (types, import, require)
634
- * - Bin field transformations
635
- * - PNPM catalog and workspace resolution
636
- * - Field cleanup for publishing
1110
+ * This plugin processes the source package.json and transforms it for the build output.
1111
+ * It handles path transformations, pnpm catalog/workspace resolution, and field cleanup.
1112
+ *
1113
+ * ## Transformations Applied
1114
+ *
1115
+ * - **Path Updates**: Converts source paths to output paths (e.g., `./src/index.ts` → `./index.js`)
1116
+ * - **Type Conditions**: Adds `types` fields to exports pointing to `.d.ts` files
1117
+ * - **pnpm Resolution**: Resolves `catalog:` and `workspace:*` dependency versions
1118
+ * - **Field Cleanup**: Removes `scripts`, `publishConfig`, and other dev-only fields
1119
+ * - **Private Flag**: Sets based on `publishConfig.access` or `forcePrivate` option
1120
+ *
1121
+ * ## Plugin Interoperability
1122
+ *
1123
+ * - Consumes `entrypoints` map from AutoEntryPlugin
1124
+ * - Consumes `exportToOutputMap` for exportsAsIndexes mode
1125
+ * - Exposes `files-cache` for asset caching
1126
+ * - Consumes `use-rollup-types` flag from DtsPlugin
1127
+ *
1128
+ * @param options - Plugin configuration options
637
1129
  *
638
1130
  * @example
1131
+ * Basic usage:
639
1132
  * ```typescript
640
- * const transformer = new PackageJsonTransformer({
641
- * processTSExports: true,
642
- * collapseIndex: true,
643
- * });
1133
+ * import { PackageJsonTransformPlugin } from '@savvy-web/rslib-builder';
644
1134
  *
645
- * // For production builds (resolves catalog: and workspace: references)
646
- * const prodPkg = await transformer.transform(packageJson, { isProduction: true });
1135
+ * export default {
1136
+ * plugins: [
1137
+ * PackageJsonTransformPlugin({
1138
+ * bundle: true,
1139
+ * processTSExports: true,
1140
+ * }),
1141
+ * ],
1142
+ * };
1143
+ * ```
1144
+ *
1145
+ * @example
1146
+ * With custom transform:
1147
+ * ```typescript
1148
+ * import { PackageJsonTransformPlugin } from '@savvy-web/rslib-builder';
647
1149
  *
648
- * // For development builds (preserves workspace links)
649
- * const devPkg = await transformer.transform(packageJson, { isProduction: false });
1150
+ * export default {
1151
+ * plugins: [
1152
+ * PackageJsonTransformPlugin({
1153
+ * target: 'npm',
1154
+ * transform(pkg) {
1155
+ * delete pkg.devDependencies;
1156
+ * return pkg;
1157
+ * },
1158
+ * }),
1159
+ * ],
1160
+ * };
650
1161
  * ```
651
1162
  *
652
1163
  * @public
653
1164
  */
654
- export declare class PackageJsonTransformer {
655
- private readonly options;
656
- private readonly pnpmCatalog;
657
- constructor(options?: PackageJsonTransformOptions);
1165
+ export declare const PackageJsonTransformPlugin: (options?: PackageJsonTransformPluginOptions) => RsbuildPlugin;
1166
+
1167
+ /**
1168
+ * Options for the PackageJsonTransformPlugin.
1169
+ *
1170
+ * @public
1171
+ */
1172
+ export declare interface PackageJsonTransformPluginOptions {
658
1173
  /**
659
- * Transforms a single export path for RSLib compatibility.
1174
+ * Override the package name in the output package.json.
660
1175
  *
661
1176
  * @remarks
662
- * Performs several transformations:
663
- * 1. Strips source directory prefixes (exports/, public/, src/)
664
- * 2. Converts TypeScript extensions to JavaScript
665
- * 3. Preserves bin/ prefix for executables
666
- *
667
- * @param path - The file path to transform
668
- * @returns The transformed path
1177
+ * - When a string is provided, the package name is replaced with that value
1178
+ * - When `true`, the original name is preserved (no override)
1179
+ * - When undefined, the original name is preserved
669
1180
  *
670
1181
  * @example
671
1182
  * ```typescript
672
- * transformer.transformExportPath("./src/index.ts"); // "./index.js"
673
- * transformer.transformExportPath("./bin/cli.ts"); // "./bin/cli.js"
674
- * ```
675
- */
676
- transformExportPath(path: string): string;
677
- /**
678
- * Creates a TypeScript declaration file path from a JavaScript file path.
679
- *
680
- * @param jsPath - The JavaScript file path
681
- * @returns The corresponding .d.ts file path
1183
+ * import type { PackageJsonTransformPluginOptions } from '@savvy-web/rslib-builder';
682
1184
  *
683
- * @example
684
- * ```typescript
685
- * transformer.createTypePath("./index.js"); // "./index.d.ts"
686
- * transformer.createTypePath("./rslib/index.js"); // "./rslib.d.ts" (bundled)
1185
+ * const options: PackageJsonTransformPluginOptions = {
1186
+ * name: '@scope/my-package-dist',
1187
+ * };
687
1188
  * ```
688
1189
  */
689
- createTypePath(jsPath: string): string;
690
- /**
691
- * Transforms package.json exports field recursively.
692
- *
693
- * @param exports - The exports value to transform
694
- * @param exportKey - The current export key for context
695
- * @returns The transformed exports value
696
- */
697
- transformExports(exports: FlexibleExports, exportKey?: string): FlexibleExports;
1190
+ name?: string | true;
698
1191
  /**
699
- * Transforms the bin field for build output.
1192
+ * Force the output package.json to have `"private": true`.
700
1193
  *
701
1194
  * @remarks
702
- * TypeScript bin entries are compiled to `./bin/{command-name}.js` by RSlib.
703
- * Non-TypeScript entries (shell scripts, compiled JS) are preserved as-is.
1195
+ * Useful for development builds that should never be published.
1196
+ * When true, overrides the `publishConfig.access` setting.
704
1197
  *
705
- * @param bin - The bin field from package.json
706
- * @returns The transformed bin field
1198
+ * @defaultValue false
707
1199
  */
708
- transformBin(bin: PackageJson["bin"]): PackageJson["bin"];
1200
+ forcePrivate?: boolean;
709
1201
  /**
710
- * Performs the complete package.json transformation.
1202
+ * Whether to process TypeScript exports and generate type conditions.
711
1203
  *
712
- * @param packageJson - The source package.json
713
- * @param context - Transform context with properties:
714
- * - `isProduction`: Whether this is a production build
715
- * - `customTransform`: Optional custom transform function
716
- * @returns The transformed package.json
717
- */
718
- transform(packageJson: PackageJson, context?: {
719
- isProduction?: boolean;
720
- customTransform?: (pkg: PackageJson) => PackageJson;
721
- }): Promise<PackageJson>;
722
- private applyPnpmTransformations;
723
- /**
724
- * Applies RSLib-specific transformations.
725
- */
726
- private applyRslibTransformations;
727
- /**
728
- * Transforms a string export value.
729
- */
730
- private transformStringExport;
731
- /**
732
- * Transforms an object export value.
733
- */
734
- private transformObjectExports;
735
- /**
736
- * Determines if an export object represents export conditions.
737
- */
738
- private isConditionsObject;
739
- /**
740
- * Transforms a single export entry.
741
- */
742
- private transformExportEntry;
743
- }
744
-
745
- /**
746
- * Options for transforming package.json.
747
- * @public
748
- */
749
- export declare interface PackageJsonTransformOptions {
750
- /**
751
- * Whether to process TypeScript exports (convert .ts to .js and add types field).
752
- * @defaultValue true
1204
+ * @remarks
1205
+ * When enabled, transforms export paths from `.ts` to `.js` and adds
1206
+ * `types` conditions pointing to the corresponding `.d.ts` files.
1207
+ *
1208
+ * @example
1209
+ * Input: `"./src/index.ts"`
1210
+ * Output: `{ "types": "./index.d.ts", "import": "./index.js" }`
753
1211
  */
754
1212
  processTSExports?: boolean;
755
1213
  /**
756
- * Whether to collapse index files (./foo/index.ts becomes ./foo.js).
757
- * This is typically true for bundled builds.
1214
+ * Whether the build is in bundle mode.
1215
+ *
1216
+ * @remarks
1217
+ * Affects export path transformations - in bundle mode, nested index files
1218
+ * are collapsed (e.g., `./utils/index.ts` becomes `./utils.js`).
1219
+ *
758
1220
  * @defaultValue false
759
1221
  */
760
- collapseIndex?: boolean;
761
- /**
762
- * Map of export paths to entry files (from AutoEntryPlugin).
763
- */
764
- entrypoints?: Map<string, string>;
765
- /**
766
- * Map of export paths to output files (for exportsAsIndexes mode).
767
- */
768
- exportToOutputMap?: Map<string, string>;
769
- }
770
-
771
- /**
772
- * Plugin to process package.json for distribution
773
- * @public
774
- */
775
- export declare const PackageJsonTransformPlugin: (options?: PackageJsonTransformPluginOptions) => RsbuildPlugin;
776
-
777
- /**
778
- * @public
779
- */
780
- export declare interface PackageJsonTransformPluginOptions {
781
- /** Override the name property of the source package.json when building to a target */
782
- name?: string | true;
783
- /** Whether to force include private packages (with "private": true) in the output */
784
- forcePrivate?: boolean;
785
- /** Whether to process package.json exports of into */
786
- processTSExports?: boolean;
787
- /** Whether the build is in bundle mode (affects export path transformation) */
788
1222
  bundle?: boolean;
789
- /** Build target (dev, npm) - used for custom transformations */
790
- target?: string;
791
- /** Optional transform function to modify package.json after standard transformations */
792
- transform?: (pkg: PackageJson) => PackageJson;
793
- }
794
-
795
- /**
796
- * Manages PNPM catalog resolution with caching.
797
- *
798
- * @remarks
799
- * This class handles the resolution of PNPM-specific dependency references:
800
- * - `catalog:` references to centralized version definitions
801
- * - `workspace:` references to local workspace packages
802
- *
803
- * The class caches the catalog data based on file modification time to avoid
804
- * repeated filesystem operations during builds.
805
- *
806
- * @example
807
- * ```typescript
808
- * const catalog = new PnpmCatalog();
809
- *
810
- * // Get the catalog data
811
- * const versions = await catalog.getCatalog();
812
- * console.log(versions);
813
- * // { "react": "^18.2.0", "typescript": "^5.0.0" }
814
- *
815
- * // Resolve package.json dependencies
816
- * const resolved = await catalog.resolvePackageJson(packageJson);
817
- * ```
818
- *
819
- * @public
820
- */
821
- export declare class PnpmCatalog {
822
- private catalogCache;
823
- private catalogCacheMtime;
824
- private cachedWorkspaceRoot;
825
1223
  /**
826
- * Clears the cached catalog data.
1224
+ * Build target identifier for custom transformations.
827
1225
  *
828
1226
  * @remarks
829
- * Useful in testing scenarios to ensure clean state between tests.
1227
+ * Passed to the transform function to allow target-specific modifications.
1228
+ * Common values: "dev", "npm"
830
1229
  */
831
- clearCache(): void;
1230
+ target?: string;
832
1231
  /**
833
- * Gets the PNPM catalog from pnpm-workspace.yaml.
1232
+ * Custom transform function to modify package.json after standard transformations.
834
1233
  *
835
1234
  * @remarks
836
- * The catalog is cached based on file modification time. If the file hasn't
837
- * changed since the last read, the cached version is returned.
1235
+ * Called after all built-in transformations (path updates, pnpm resolution, etc.)
1236
+ * are applied. Mutations to the object are also supported.
838
1237
  *
839
- * @returns The catalog mapping dependency names to versions
840
- */
841
- getCatalog(): Promise<Record<string, string>>;
842
- /**
843
- * Resolves catalog: and workspace: references in a package.json.
1238
+ * @param pkg - The package.json object after standard transformations
1239
+ * @returns The modified package.json object
844
1240
  *
845
- * @param packageJson - The package.json to resolve
846
- * @param dir - The directory containing the package (defaults to cwd)
847
- * @returns The resolved package.json
1241
+ * @example
1242
+ * ```typescript
1243
+ * import type { PackageJsonTransformPluginOptions } from '@savvy-web/rslib-builder';
848
1244
  *
849
- * @throws When resolution fails for critical dependencies
850
- */
851
- resolvePackageJson(packageJson: PackageJson, dir?: string): Promise<PackageJson>;
852
- /**
853
- * Collects dependencies with a specific prefix (catalog: or workspace:).
854
- */
855
- private collectDependencies;
856
- /**
857
- * Logs resolved dependencies in a formatted way.
858
- */
859
- private logResolvedDependencies;
860
- /**
861
- * Validates that no unresolved catalog: or workspace: references remain.
1245
+ * const options: PackageJsonTransformPluginOptions = {
1246
+ * transform(pkg) {
1247
+ * delete pkg.devDependencies;
1248
+ * pkg.publishConfig = { access: 'public' };
1249
+ * return pkg;
1250
+ * },
1251
+ * };
1252
+ * ```
862
1253
  */
863
- private validateNoUnresolvedReferences;
1254
+ transform?: (pkg: PackageJson) => PackageJson;
864
1255
  }
865
1256
 
866
1257
  /**
867
1258
  * Async RSLib configuration function type.
868
1259
  * @public
869
1260
  */
870
- export declare type RslibConfigAsyncFn = (env: ConfigParams) => Promise<RslibConfig>;
1261
+ declare type RslibConfigAsyncFn = (env: ConfigParams) => Promise<RslibConfig>;
871
1262
 
872
1263
  /**
873
- * Strips sourceMappingURL comment from declaration file content.
874
- * This removes comments like: `//# source` + `MappingURL=index.d.ts.map`
1264
+ * Function to transform package.json during the build process.
875
1265
  *
876
1266
  * @remarks
877
- * Source maps are preserved in the temp directory for API Extractor documentation
878
- * but are excluded from the final dist output to reduce package size.
1267
+ * This function is called after all standard transformations are applied,
1268
+ * allowing you to modify the package.json before it's written to the output directory.
1269
+ * Mutations to the `pkg` object are also supported.
879
1270
  *
880
- * @public
881
- */
882
- export declare function stripSourceMapComment(content: string): string;
883
-
884
- /**
1271
+ * @param context - Transform context containing:
1272
+ * - `target`: The current build target ("dev" or "npm")
1273
+ * - `pkg`: The package.json object to transform
1274
+ * @returns The modified package.json object
1275
+ *
1276
+ * @example
1277
+ * ```typescript
1278
+ * import type { TransformPackageJsonFn } from '@savvy-web/rslib-builder';
1279
+ *
1280
+ * const transform: TransformPackageJsonFn = ({ target, pkg }) => {
1281
+ * if (target === 'npm') {
1282
+ * delete pkg.devDependencies;
1283
+ * delete pkg.scripts;
1284
+ * }
1285
+ * return pkg;
1286
+ * };
1287
+ * ```
885
1288
  * @public
886
1289
  */
887
1290
  export declare type TransformPackageJsonFn = (context: {
@@ -890,8 +1293,50 @@ export declare type TransformPackageJsonFn = (context: {
890
1293
  }) => PackageJson;
891
1294
 
892
1295
  /**
893
- * Builder for TSDoc configuration files.
894
- * Handles tag group expansion, config generation, and file persistence.
1296
+ * Builder for TSDoc configuration files used by API Extractor.
1297
+ *
1298
+ * @remarks
1299
+ * This class provides utilities for generating `tsdoc.json` configuration files
1300
+ * that control TSDoc tag support during API documentation generation.
1301
+ *
1302
+ * ## Features
1303
+ *
1304
+ * - Expands tag groups into individual tag definitions
1305
+ * - Generates properly formatted tsdoc.json files
1306
+ * - Handles config persistence based on environment (CI vs local)
1307
+ * - Supports custom tag definitions
1308
+ *
1309
+ * ## Tag Groups
1310
+ *
1311
+ * The builder supports three standardization groups from `\@microsoft/tsdoc`:
1312
+ * - `core`: Essential tags (`\@param`, `\@returns`, `\@remarks`, etc.)
1313
+ * - `extended`: Additional tags (`\@example`, `\@defaultValue`, `\@see`, etc.)
1314
+ * - `discretionary`: Release tags (`\@alpha`, `\@beta`, `\@public`, `\@internal`)
1315
+ *
1316
+ * @example
1317
+ * Build tag configuration from options:
1318
+ * ```typescript
1319
+ * import { TsDocConfigBuilder } from '@savvy-web/rslib-builder';
1320
+ *
1321
+ * const config = TsDocConfigBuilder.build({
1322
+ * groups: ['core', 'extended'],
1323
+ * tagDefinitions: [
1324
+ * { tagName: '@error', syntaxKind: 'inline' },
1325
+ * ],
1326
+ * });
1327
+ * ```
1328
+ *
1329
+ * @example
1330
+ * Write a tsdoc.json file:
1331
+ * ```typescript
1332
+ * import { TsDocConfigBuilder } from '@savvy-web/rslib-builder';
1333
+ *
1334
+ * const configPath = await TsDocConfigBuilder.writeConfigFile(
1335
+ * { groups: ['core', 'extended', 'discretionary'] },
1336
+ * process.cwd(),
1337
+ * );
1338
+ * ```
1339
+ *
895
1340
  * @public
896
1341
  */
897
1342
  export declare class TsDocConfigBuilder {
@@ -961,6 +1406,168 @@ export declare class TsDocConfigBuilder {
961
1406
  private static syntaxKindToString;
962
1407
  }
963
1408
 
1409
+ /**
1410
+ * Error behavior for TSDoc lint errors.
1411
+ *
1412
+ * @remarks
1413
+ * - `"warn"`: Log warnings but continue the build
1414
+ * - `"error"`: Log errors but continue the build
1415
+ * - `"throw"`: Fail the build with an error
1416
+ *
1417
+ * @public
1418
+ */
1419
+ export declare type TsDocLintErrorBehavior = "warn" | "error" | "throw";
1420
+
1421
+ /**
1422
+ * Creates a plugin to validate TSDoc comments before build using ESLint with eslint-plugin-tsdoc.
1423
+ *
1424
+ * @remarks
1425
+ * This plugin runs TSDoc validation during the `onBeforeBuild` hook, ensuring that
1426
+ * documentation errors are caught before compilation begins. It generates a virtual
1427
+ * `tsdoc.json` configuration file that can be persisted for IDE and tool integration.
1428
+ *
1429
+ * ## Features
1430
+ *
1431
+ * - Programmatic ESLint execution with `eslint-plugin-tsdoc`
1432
+ * - Configurable error handling (warn, error, throw)
1433
+ * - Automatic CI detection for stricter defaults
1434
+ * - Optional tsdoc.json persistence for tool integration
1435
+ * - Automatic file discovery via import graph analysis
1436
+ * - Customizable file patterns when needed
1437
+ *
1438
+ * ## Error Handling
1439
+ *
1440
+ * | Environment | Default Behavior | On Lint Errors |
1441
+ * |-------------|------------------|----------------|
1442
+ * | Local | `"error"` | Log and continue |
1443
+ * | CI | `"throw"` | Fail the build |
1444
+ *
1445
+ * ## Required Dependencies
1446
+ *
1447
+ * This plugin requires the following optional peer dependencies:
1448
+ * - `eslint`
1449
+ * - `@typescript-eslint/parser`
1450
+ * - `eslint-plugin-tsdoc`
1451
+ *
1452
+ * Install with: `pnpm add -D eslint @typescript-eslint/parser eslint-plugin-tsdoc`
1453
+ *
1454
+ * @param options - Plugin configuration options
1455
+ * @returns An Rsbuild plugin that validates TSDoc comments before the build
1456
+ *
1457
+ * @example
1458
+ * ```typescript
1459
+ * import { TsDocLintPlugin } from '@savvy-web/rslib-builder';
1460
+ *
1461
+ * export default defineConfig({
1462
+ * plugins: [
1463
+ * TsDocLintPlugin({
1464
+ * onError: 'throw',
1465
+ * persistConfig: true,
1466
+ * }),
1467
+ * ],
1468
+ * });
1469
+ * ```
1470
+ *
1471
+ * @public
1472
+ */
1473
+ export declare const TsDocLintPlugin: (options?: TsDocLintPluginOptions) => RsbuildPlugin;
1474
+
1475
+ /**
1476
+ * Options for the TSDoc lint plugin.
1477
+ *
1478
+ * @remarks
1479
+ * This plugin validates TSDoc comments in your source files before the build
1480
+ * starts using ESLint with `eslint-plugin-tsdoc`. It helps catch documentation
1481
+ * errors early in the development cycle.
1482
+ *
1483
+ * @example
1484
+ * Enable with defaults (throws in CI, errors locally):
1485
+ * ```typescript
1486
+ * import { TsDocLintPlugin } from '@savvy-web/rslib-builder';
1487
+ *
1488
+ * export default defineConfig({
1489
+ * plugins: [TsDocLintPlugin()],
1490
+ * });
1491
+ * ```
1492
+ *
1493
+ * @example
1494
+ * Custom configuration:
1495
+ * ```typescript
1496
+ * import { TsDocLintPlugin } from '@savvy-web/rslib-builder';
1497
+ *
1498
+ * export default defineConfig({
1499
+ * plugins: [
1500
+ * TsDocLintPlugin({
1501
+ * tsdoc: {
1502
+ * tagDefinitions: [{ tagName: '@error', syntaxKind: 'block' }],
1503
+ * },
1504
+ * onError: 'throw',
1505
+ * persistConfig: true,
1506
+ * }),
1507
+ * ],
1508
+ * });
1509
+ * ```
1510
+ *
1511
+ * @public
1512
+ */
1513
+ export declare interface TsDocLintPluginOptions {
1514
+ /**
1515
+ * Whether to enable TSDoc linting.
1516
+ * @defaultValue true
1517
+ */
1518
+ enabled?: boolean;
1519
+ /**
1520
+ * TSDoc configuration for custom tag definitions.
1521
+ * Uses the same options as the DtsPlugin's apiModel.tsdoc option.
1522
+ *
1523
+ * @remarks
1524
+ * By default, all standard tag groups (core, extended, discretionary) are
1525
+ * enabled. Custom tags defined in `tagDefinitions` are automatically
1526
+ * supported.
1527
+ */
1528
+ tsdoc?: TsDocOptions;
1529
+ /**
1530
+ * Override automatic file discovery with explicit file paths or glob patterns.
1531
+ *
1532
+ * @remarks
1533
+ * By default, TsDocLintPlugin uses import graph analysis to discover files
1534
+ * from your package's exports. This ensures only public API files are linted.
1535
+ *
1536
+ * Use this option only when you need to lint specific files that aren't
1537
+ * part of the export graph, or to override the automatic discovery.
1538
+ *
1539
+ * When specified as glob patterns, test files and `__test__` directories
1540
+ * are still excluded unless explicitly included.
1541
+ *
1542
+ * @example
1543
+ * ```typescript
1544
+ * // Explicit patterns override automatic discovery
1545
+ * TsDocLintPlugin({
1546
+ * include: ["src/**\/*.ts", "!**\/*.test.ts"],
1547
+ * })
1548
+ * ```
1549
+ */
1550
+ include?: string[];
1551
+ /**
1552
+ * How to handle TSDoc lint errors.
1553
+ * - `"warn"`: Log warnings but continue the build
1554
+ * - `"error"`: Log errors but continue the build
1555
+ * - `"throw"`: Fail the build with an error
1556
+ *
1557
+ * @defaultValue `"throw"` in CI environments, `"error"` locally
1558
+ */
1559
+ onError?: TsDocLintErrorBehavior;
1560
+ /**
1561
+ * Persist tsdoc.json to disk for tool integration (ESLint, IDEs).
1562
+ * - `true`: Write to project root as "tsdoc.json"
1563
+ * - `PathLike`: Write to specified path
1564
+ * - `false`: Clean up after linting
1565
+ *
1566
+ * @defaultValue `true` when not in CI, `false` in CI environments
1567
+ */
1568
+ persistConfig?: boolean | PathLike;
1569
+ }
1570
+
964
1571
  /**
965
1572
  * Options for tsdoc-metadata.json generation.
966
1573
  * @public
@@ -1016,10 +1623,12 @@ export declare interface TsDocOptions {
1016
1623
  *
1017
1624
  * @example
1018
1625
  * ```typescript
1019
- * tagDefinitions: [
1020
- * { tagName: "@error", syntaxKind: "inline" },
1021
- * { tagName: "@category", syntaxKind: "block", allowMultiple: false }
1022
- * ]
1626
+ * import type { TsDocTagDefinition } from '@savvy-web/rslib-builder';
1627
+ *
1628
+ * const tagDefinitions: TsDocTagDefinition[] = [
1629
+ * { tagName: '@error', syntaxKind: 'inline' },
1630
+ * { tagName: '@category', syntaxKind: 'block', allowMultiple: false },
1631
+ * ];
1023
1632
  * ```
1024
1633
  */
1025
1634
  tagDefinitions?: TsDocTagDefinition[];
@@ -1028,9 +1637,9 @@ export declare interface TsDocOptions {
1028
1637
  * Tags from enabled groups and custom tagDefinitions are auto-supported.
1029
1638
  *
1030
1639
  * @example
1640
+ * Disable \@beta even though "extended" group is enabled:
1031
1641
  * ```typescript
1032
- * // Disable @beta even though "extended" group is enabled
1033
- * supportForTags: { "@beta": false }
1642
+ * const supportForTags: Record<string, boolean> = { '@beta': false };
1034
1643
  * ```
1035
1644
  */
1036
1645
  supportForTags?: Record<string, boolean>;
@@ -1054,15 +1663,6 @@ export declare interface TsDocOptions {
1054
1663
  * TSDoc warnings include unknown tags, malformed syntax, and other
1055
1664
  * documentation issues detected by API Extractor during processing.
1056
1665
  *
1057
- * @example
1058
- * ```typescript
1059
- * // Fail build on any TSDoc issues (CI default)
1060
- * warnings: "fail"
1061
- *
1062
- * // Show warnings but continue build (local default)
1063
- * warnings: "log"
1064
- * ```
1065
- *
1066
1666
  * @defaultValue `"fail"` in CI environments (`CI` or `GITHUB_ACTIONS` env vars),
1067
1667
  * `"log"` otherwise
1068
1668
  */
@@ -1084,6 +1684,27 @@ export declare interface TsDocTagDefinition {
1084
1684
 
1085
1685
  /**
1086
1686
  * TSDoc standardization groups for predefined tag sets.
1687
+ *
1688
+ * @remarks
1689
+ * These groups correspond to the TSDoc specification's standardization levels
1690
+ * as defined in `\@microsoft/tsdoc`. Each group contains a set of related tags:
1691
+ *
1692
+ * - `"core"`: Essential tags for basic documentation
1693
+ * (`\@param`, `\@returns`, `\@remarks`, `\@deprecated`, `\@privateRemarks`, etc.)
1694
+ *
1695
+ * - `"extended"`: Additional tags for richer documentation
1696
+ * (`\@example`, `\@defaultValue`, `\@see`, `\@throws`, `\@typeParam`, etc.)
1697
+ *
1698
+ * - `"discretionary"`: Release stage and visibility modifiers
1699
+ * (`\@alpha`, `\@beta`, `\@public`, `\@internal`, `\@experimental`)
1700
+ *
1701
+ * @example
1702
+ * ```typescript
1703
+ * import type { TsDocTagGroup } from '@savvy-web/rslib-builder';
1704
+ *
1705
+ * const groups: TsDocTagGroup[] = ['core', 'extended'];
1706
+ * ```
1707
+ *
1087
1708
  * @public
1088
1709
  */
1089
1710
  export declare type TsDocTagGroup = "core" | "extended" | "discretionary";