/** * RSLib-based build system for Node.js libraries with automatic package.json transformation, * TypeScript declaration bundling, and multi-target support. * * @remarks * This package provides a powerful builder system built on top of RSLib that simplifies the * process of building modern ESM Node.js libraries. It offers: * * - **Automatic Entry Detection**: Auto-detects entry points from package.json exports * - **Multi-Target Builds**: Support for dev and npm build targets * - **Bundled ESM Output**: Optimized single-file outputs with rolled-up types * - **Package.json Transformation**: Automatic path updates, PNPM catalog resolution * - **TypeScript Declaration Bundling**: Using tsgo and API Extractor * - **File Array Generation**: Automatic files array creation for package.json * - **API Model Generation**: Optional `.api.json` for documentation tooling * * @example * Basic usage in rslib.config.ts: * ```typescript * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder'; * * export default NodeLibraryBuilder.create({}); * ``` * * @example * With custom transformations: * ```typescript * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder'; * * export default NodeLibraryBuilder.create({ * externals: ['@rslib/core'], * transform({ pkg }) { * delete pkg.devDependencies; * return pkg; * } * }); * ``` * * @packageDocumentation */ import type { ConfigParams } from '@rslib/core'; import { JsxEmit } from 'typescript'; import { ModuleDetectionKind } from 'typescript'; import { ModuleKind } from 'typescript'; import { ModuleResolutionKind } from 'typescript'; import { NewLineKind } from 'typescript'; import type { ParsedCommandLine } from 'typescript'; import type { PathLike } from 'node:fs'; import type { RsbuildPlugin } from '@rsbuild/core'; import type { RslibConfig } from '@rslib/core'; import { ScriptTarget } from 'typescript'; import type { SourceConfig } from '@rsbuild/core'; import ts from 'typescript'; import type { TSConfigJsonWithSchema } from '../types/tsconfig-json.js'; /** * Options for API model generation. * Generates an `.api.json` file using API Extractor. * * @remarks * API model generation is enabled by default. To disable, set `apiModel: false`. * Providing an options object implicitly enables API model generation. * * When a package has multiple entry points, API Extractor runs for each entry and the * resulting per-entry models are merged into a single API model with multiple * EntryPoint members. Canonical references are scoped per entry point. * * @public */ export declare interface ApiModelOptions { /** * Filename for the generated API model file. * @defaultValue `.api.json` (e.g., `rslib-builder.api.json`) */ filename?: string; /** * Local paths to copy the API model and package.json to. * Used for local testing with documentation systems. * * @remarks * Each path must be a directory. The parent directory must exist, * but the final directory will be created if it doesn't exist. * Both the API model and the processed package.json will be copied. * * The API model file is emitted to dist but excluded from npm publish * (added as negated pattern `!` in the `files` array). * * @example * ```typescript * import type { ApiModelOptions } from '@savvy-web/rslib-builder'; * * const apiModel: ApiModelOptions = { * localPaths: ['../docs-site/lib/packages/my-package'], * }; * ``` */ localPaths?: string[]; /** * TSDoc configuration for custom tag definitions. * Passed to API Extractor for documentation processing. * * @remarks * By default, all standard tag groups (core, extended, discretionary) are * enabled. Custom tags defined in `tagDefinitions` are automatically * supported. Use `supportForTags` only to disable specific tags. * * @example * ```typescript * import type { ApiModelOptions } from '@savvy-web/rslib-builder'; * * const apiModel: ApiModelOptions = { * tsdoc: { * tagDefinitions: [{ tagName: '@error', syntaxKind: 'inline' }], * }, * }; * ``` */ tsdoc?: TsDocOptions; /** * Options for tsdoc-metadata.json generation. * @defaultValue true (enabled when apiModel is enabled) */ tsdocMetadata?: TsDocMetadataOptions | boolean; /** * Controls handling of API Extractor's "forgotten export" messages. * A forgotten export occurs when a public API references a declaration * that isn't exported from the entry point. * * - `"include"`: Log a warning, include in the API model * - `"error"`: Fail the build with details about the forgotten exports * - `"ignore"`: Turn off detection — suppress all messages * * @defaultValue `"error"` in CI environments (`CI` or `GITHUB_ACTIONS` env vars), * `"include"` otherwise */ forgottenExports?: "include" | "error" | "ignore"; /** * Declarative rules for suppressing specific API Extractor warning messages. * * @remarks * Each rule matches on `messageId` (exact), `pattern` (RegExp with substring fallback), * or both (AND logic). Suppression is evaluated before `forgottenExports` and TSDoc * warning handling and takes priority over both. * * After each entry, the number of suppressed messages is logged at info level. * * @example * ```typescript * import type { ApiModelOptions } from '@savvy-web/rslib-builder'; * * const apiModel: ApiModelOptions = { * forgottenExports: 'error', * suppressWarnings: [ * // Suppress forgotten-export for Effect _base symbols * { messageId: 'ae-forgotten-export', pattern: '_base' }, * // Suppress a specific TSDoc warning category * { messageId: 'tsdoc-param-tag-missing-hyphen' }, * ], * }; * ``` */ suppressWarnings?: WarningSuppressionRule[]; } /** * Plugin to automatically detect and configure entry points from package.json exports. * * @remarks * This plugin reads your package.json exports field and automatically configures * RSlib entry points, eliminating the need to manually specify entries in your config. * * ## Features * * - Automatically extracts entry points from package.json `exports` field * - Supports both string and object export values * - Handles bin field entries for CLI tools * - Exposes entrypoints map for other plugins to consume * * ## How It Works * * 1. Reads package.json from the project root * 2. Extracts entry points from the `exports` field * 3. Configures RSlib with the discovered entries * 4. Exposes the entrypoints map via `api.useExposed("entrypoints")` * * @param options - Plugin configuration options * * @example * Basic usage (entries detected from package.json): * ```typescript * import { AutoEntryPlugin } from '@savvy-web/rslib-builder'; * * export default { * plugins: [AutoEntryPlugin()], * }; * ``` * * @example * With nested directory output: * ```typescript * import { AutoEntryPlugin } from '@savvy-web/rslib-builder'; * * export default { * plugins: [ * AutoEntryPlugin({ exportsAsIndexes: true }), * ], * }; * ``` * * @public */ export declare const AutoEntryPlugin: (options?: AutoEntryPluginOptions) => RsbuildPlugin; /** * Options for the AutoEntryPlugin. * @public */ export declare interface AutoEntryPluginOptions { /** * When enabled, export paths create `index.js` files in nested directories * instead of using the export name as the filename. * * @remarks * This is useful when you want cleaner import paths that don't require * specifying a filename, relying on Node's directory index resolution. * * @example * With `exportsAsIndexes: true` and this package.json: * ```json * { * "exports": { * ".": "./src/index.ts", * "./utils": "./src/utils/index.ts" * } * } * ``` * * Output structure: * ``` * dist/ * index.js * utils/ * index.js * ``` * * @defaultValue false */ exportsAsIndexes?: boolean; /** * When enabled, uses import graph analysis to discover all reachable files * from entry points, and sets RSlib's source.entry to the traced file list * instead of named entries. * * @remarks * Named entries are still exposed via the `entrypoints` map for DtsPlugin * and PackageJsonTransformPlugin to use. * * @defaultValue false */ bundleless?: boolean; } /** * Build mode environment for library output. * * @remarks * Each mode produces different output optimizations: * - `"dev"`: Development build with source maps for debugging * - `"npm"`: Production build optimized for npm publishing * * @example * Specifying modes via CLI: * ```bash * rslib build --env-mode dev * rslib build --env-mode npm * ``` * * @public */ export declare type BuildMode = "dev" | "npm"; /** * Configuration for copying files during the build process. * * @remarks * This interface mirrors rspack's copy pattern configuration and is passed directly * to the rspack CopyPlugin. All properties except `from` are optional. * * @example * ```typescript * // Copy a directory * { from: "./public", to: "./", context: process.cwd() } * * // Copy specific files * { from: "**\/*.json", to: "./config" } * ``` * * @public */ export declare interface CopyPatternConfig { /** Source path or glob pattern to copy from */ from: string; /** Destination path (relative to output directory) */ to?: string; /** Base directory for resolving `from` path */ context?: string; /** Type of destination: "dir", "file", or "template" */ toType?: "dir" | "file" | "template"; /** If true, does not emit an error if the source is missing */ noErrorOnMissing?: boolean; /** Glob options for pattern matching */ globOptions?: { /** Patterns to ignore */ ignore?: string[]; /** Whether to match dotfiles */ dot?: boolean; }; /** Filter function to include/exclude files */ filter?: (filepath: string) => boolean | Promise; /** Transform function to modify file contents */ transform?: { transformer: (input: Buffer, absoluteFilename: string) => string | Buffer | Promise | Promise; } | ((input: Buffer, absoluteFilename: string) => string | Buffer | Promise | Promise); /** Priority for conflicting files (higher = higher priority) */ priority?: number; } /** * Plugin to generate TypeScript declaration files using tsgo and emit them through Rslib's asset pipeline. * * @remarks * This plugin uses tsgo (`\@typescript/native-preview`) for faster declaration file generation * and integrates with Rslib's build system by emitting generated files as compilation assets. * * ## Features * * - Uses tsgo exclusively for .d.ts generation (faster than tsc) * - Emits .d.ts and .d.ts.map files through Rslib's asset pipeline * - Optional bundling with API Extractor for rollup mode * - Supports watch mode * - Integrates seamlessly with other Rslib plugins * - Respects tsconfig.json settings * * ## Build Workflow * * 1. **Config Phase** (`modifyRsbuildConfig`): * - Finds and loads tsconfig.json * - Creates temp directory for .d.ts generation * - Validates configuration * * 2. **Asset Processing Phase** (`processAssets`): * - Cleans temp directory at start of build (to remove stale files) * - Spawns tsgo to generate .d.ts files to temp directory * - Recursively collects all generated .d.ts and .d.ts.map files * - If bundling: uses API Extractor to bundle declarations per entry point * - Emits files through compilation.emitAsset() * - Adds .d.ts files (not .d.ts.map) to the files array for npm publishing * - Preserves temp directory after build for API Extractor documentation generation * * @param options - Plugin configuration options * * @example * ```typescript * import { DtsPlugin } from "@savvy-web/rslib-builder"; * * export default { * plugins: [ * DtsPlugin({ * abortOnError: true, * bundle: true, * bundledPackages: ['type-fest', '@commitlint/*'] * }) * ] * }; * ``` * * @public */ export declare const DtsPlugin: (options?: DtsPluginOptions) => RsbuildPlugin; /** * Options for configuring the DTS plugin. * @public */ export declare interface DtsPluginOptions { /** * Path to TypeScript configuration file. * If not specified, uses the tsconfigPath from Rsbuild config or searches for tsconfig.json. */ tsconfigPath?: string; /** * Custom output directory for declaration files relative to dist root. * If not specified, uses the declarationDir from tsconfig.json or falls back to dist root. */ distPath?: string; /** * Whether to abort the build on TypeScript errors. * @defaultValue true */ abortOnError?: boolean; /** * Custom file extension for declaration files. * @defaultValue ".d.ts" */ dtsExtension?: string; /** * Whether to bundle declaration files using API Extractor. * When true, generates a single .d.ts file per entry point. * @defaultValue false */ bundle?: boolean; /** * Packages whose types should be bundled (inlined) into the output .d.ts files. * Only applies when bundle is true. * Supports glob patterns (e.g., '\@commitlint/*', 'type-fest') * @defaultValue [] */ bundledPackages?: string[]; /** * Banner text to add at the top of bundled declaration files. * Only applies when bundle is true. */ banner?: string; /** * Footer text to add at the bottom of bundled declaration files. * Only applies when bundle is true. */ footer?: string; /** * Build mode (dev, npm). * Used to generate the correct temp tsconfig when tsconfigPath is not provided. */ buildMode?: "dev" | "npm"; /** * Output format for the library. * Affects the resolved tsconfig.json module settings: * - `"esm"`: Uses ESNext module and Bundler resolution (default) * - `"cjs"`: Uses CommonJS module and Node10 resolution */ format?: "esm" | "cjs"; /** * Options for API model generation. * When enabled, generates an `.api.json` file in the dist directory. * Only applies when bundle is true. * * The API model is excluded from npm publish (not added to `files` array). */ apiModel?: ApiModelOptions | boolean; /** * Path prefix for emitted DTS files. * Used in dual format builds to place declarations in format subdirectories * (e.g., `esm/index.d.ts`, `cjs/index.d.cts`). * Metadata files (api.json, tsdoc-metadata.json, tsconfig.json) are NOT prefixed. */ dtsPathPrefix?: string; /** Override the default LibraryTSConfigFile used for temp tsconfig generation. */ tsconfigPreset?: LibraryTSConfigFile; /** * Explicitly provide entry points instead of discovering from package.json exports. * Map of entry name to source path (e.g., `{ index: "./src/index.ts" }`). * * @remarks * Used by RSPressPluginBuilder to prevent cross-contamination between the plugin lib * and runtime lib — each lib's DtsPlugin only processes its own entries. * When set, the EntryExtractor is bypassed entirely. */ overrideEntries?: Record; } /** * Extracts TypeScript entry points from package.json for build configuration. * * @remarks * This class analyzes package.json export and bin configurations to identify * TypeScript source files that need to be built. It handles various export * formats and automatically maps JavaScript output paths back to their * TypeScript source files. * * **Export Path Mapping:** * - Converts export keys to entry names (e.g., "./utils" becomes "utils") * - Maps the root export "." to "index" entry * - Replaces path separators with hyphens for nested exports (default) * - When `exportsAsIndexes` is true, preserves path structure * * **Source Path Resolution:** * - Prioritizes TypeScript files (.ts/.tsx) over JavaScript files * - Maps /dist/ JavaScript paths back to /src/ TypeScript sources * - Supports conditional exports (import, default, types fields) * * @example * ```typescript * const extractor = new EntryExtractor(); * * const packageJson = { * exports: { * ".": "./src/index.ts", * "./utils": "./src/utils.ts", * }, * bin: { * "my-cli": "./src/bin/cli.ts" * } * }; * * const result = extractor.extract(packageJson); * console.log(result.entries); * // { * // "index": "./src/index.ts", * // "utils": "./src/utils.ts", * // "bin/my-cli": "./src/bin/cli.ts" * // } * ``` * * @public */ export declare class EntryExtractor { private readonly options; constructor(options?: EntryExtractorOptions); /** * Extracts entry points from package.json exports and bin fields. * * @param packageJson - The package.json to extract entries from * @returns Object containing the extracted entries */ extract(packageJson: PackageJson): ExtractedEntries; /** * Extracts entries from the exports field. */ private extractFromExports; /** * Extracts entries from the bin field. */ private extractFromBin; /** * Resolves a source path from various export value formats. */ private resolveSourcePath; /** * Resolves a path to its TypeScript source equivalent. * Maps /dist/ JavaScript paths back to /src/ TypeScript sources. */ private resolveToTypeScript; /** * Checks if a path points to a TypeScript file. */ private isTypeScriptFile; /** * Creates an entry name from an export key. */ private createEntryName; } /** * Options for entry extraction. * @public */ export declare interface EntryExtractorOptions { /** * When true, export paths create index files in nested directories. * "./foo/bar" becomes "foo/bar/index" instead of "foo-bar". */ exportsAsIndexes?: boolean; } /** * Result of entry extraction. * @public */ export declare interface ExtractedEntries { /** * Entry name to TypeScript source path mapping. */ entries: Record; /** * Entry name to original export key mapping. * Maps entry names back to the original package.json export path * (e.g., `"nested-one"` → `"./nested/one"`). */ exportPaths: Record; } /** * Plugin to manage the `files` array in package.json for npm publishing. * * @remarks * This plugin automatically populates the `files` field in the output package.json * with all compiled assets and essential files. Other plugins can add files via * the shared `files-array` exposed through the Rsbuild API. * * ## Files Included * * - Essential files: package.json, README.md, LICENSE * - All compiled JavaScript files * - All declaration files (.d.ts) * - Files added by other plugins via `api.useExposed("files-array")` * * ## Files Excluded * * - Source map files (.map) * - Files prefixed with `!` in the files array (negated patterns) * * ## Plugin Interoperability * * Other plugins can add files to the array: * ```typescript * const filesArray = api.useExposed("files-array") as Set; * filesArray.add("my-custom-file.json"); * ``` * * @param options - Plugin configuration options * * @example * Basic usage: * ```typescript * import { FilesArrayPlugin } from '@savvy-web/rslib-builder'; * * export default { * plugins: [ * FilesArrayPlugin({ mode: 'npm' }), * ], * }; * ``` * * @example * With custom file transformation: * ```typescript * import { FilesArrayPlugin } from '@savvy-web/rslib-builder'; * * export default { * plugins: [ * FilesArrayPlugin({ * mode: 'npm', * transformFiles({ filesArray }) { * filesArray.add('CHANGELOG.md'); * }, * }), * ], * }; * ``` * * @public */ export declare const FilesArrayPlugin: (options?: FilesArrayPluginOptions) => RsbuildPlugin; /** * Options for the FilesArrayPlugin. * * @typeParam TMode - The build mode type, defaults to string * * @public */ export declare interface FilesArrayPluginOptions { /** * Optional callback to transform files after they're built but before the files array is finalized. * * @remarks * Called during the "additional" stage of asset processing, after all other assets are created. * Use this to copy/rename files or add additional files to the build output. * * @param context - Transform context containing: * - `compilation`: Rspack compilation object with assets * - `filesArray`: Set of files to be included in package.json `files` field * - `mode`: Current build mode * * @example * ```typescript * import type { FilesArrayPluginOptions } from '@savvy-web/rslib-builder'; * * const options: FilesArrayPluginOptions = { * mode: 'npm', * transformFiles({ compilation, filesArray }) { * // Add a custom file to the output * filesArray.add('custom-file.txt'); * }, * }; * ``` */ transformFiles?: (context: { /** Rspack compilation object with assets */ compilation: { assets: Record; }; /** Set of files to include in package.json files array */ filesArray: Set; /** Current build mode */ mode: TMode; }) => void | Promise; /** * Build mode identifier (e.g., "dev", "npm"). * * @remarks * Passed to the `transformFiles` callback to allow mode-specific transformations. */ mode: TMode; /** * Format directories to include in the files array. * Used in dual format builds so npm's `files` field includes * format directories (e.g., `["esm", "cjs"]`). * Directory names are treated as recursive includes by npm, * so individual files under these dirs are filtered out. */ formatDirs?: string[]; } /** * Analyzes TypeScript import relationships to discover all files * reachable from specified entry points. * * @remarks * This class uses the TypeScript compiler API to trace import statements * and discover all files that are part of the public API. It handles: * * - Static imports: `import { foo } from "./module"` * - Dynamic imports: `import("./module")` * - Re-exports: `export * from "./module"` and `export { foo } from "./module"` * - Circular imports (via visited set tracking) * * The class automatically filters out: * - Files in node_modules * - Declaration files (.d.ts) * - Test files (*.test.ts, *.spec.ts) * - Files in __test__ directories * * ## Static Methods vs Instance Methods * * For simple one-off analysis, use the static convenience methods: * - {@link ImportGraph.fromEntries} - Trace from explicit entry paths * - {@link ImportGraph.fromPackageExports} - Trace from package.json exports * * For repeated analysis or custom configuration, create an instance * and use the instance methods which reuse the TypeScript program. * * @example * Using static methods (recommended for most cases): * ```typescript * import { ImportGraph } from '@savvy-web/rslib-builder'; * * // Trace from explicit entries * const result = ImportGraph.fromEntries( * ['./src/index.ts', './src/cli.ts'], * { rootDir: process.cwd() } * ); * * // Trace from package.json exports * const result = ImportGraph.fromPackageExports( * './package.json', * { rootDir: process.cwd() } * ); * ``` * * @example * Using instance methods (for repeated analysis): * ```typescript * import { ImportGraph } from '@savvy-web/rslib-builder'; * * const graph = new ImportGraph({ rootDir: '/path/to/project' }); * * // Reuses the TypeScript program across multiple calls * const libResult = graph.traceFromEntries(['./src/index.ts']); * const cliResult = graph.traceFromEntries(['./src/cli.ts']); * ``` * * @public */ export declare class ImportGraph { private readonly options; private readonly sys; private program; private compilerOptions; private moduleResolutionCache; constructor(options: ImportGraphOptions); /** * Trace all imports from the given entry points. * * @param entryPaths - Paths to entry files (relative to rootDir or absolute) * @returns Deduplicated list of all reachable TypeScript files */ traceFromEntries(entryPaths: string[]): ImportGraphResult; /** * Trace imports from package.json exports. * * @remarks * Convenience method that extracts entry points from package.json * using EntryExtractor, then traces all imports from those entries. * * @param packageJsonPath - Path to package.json (relative to rootDir or absolute) * @returns Deduplicated list of all reachable TypeScript files */ traceFromPackageExports(packageJsonPath: string): ImportGraphResult; /** * Initialize the TypeScript program for module resolution. */ private initializeProgram; /** * Find tsconfig.json path. */ private findTsConfig; /** * Resolve entry path to absolute path. */ private resolveEntryPath; /** * Recursively trace imports from a source file. */ private traceImports; /** * Extract all import/export module specifiers from a source file. */ private extractImports; /** * Resolve a module specifier to an absolute file path. */ private resolveImport; /** * Check if a path is an external module (node_modules). */ private isExternalModule; /** * Check if a file should be included in results. * Filters out test files and non-TypeScript files. */ private isSourceFile; /** * Traces TypeScript imports from entry points. * * @remarks * Static convenience method that creates an ImportGraph instance * and traces imports in one call. For repeated analysis where you want * to reuse the TypeScript program, create an instance and use * {@link ImportGraph.traceFromEntries} instead. * * @param entryPaths - Paths to entry files (relative to rootDir or absolute) * @param options - Import graph configuration options * @returns All TypeScript files reachable from the entries * * @example * ```typescript * import { ImportGraph } from '@savvy-web/rslib-builder'; * * const result = ImportGraph.fromEntries( * ['./src/index.ts', './src/cli.ts'], * { rootDir: process.cwd() } * ); * console.log('Found files:', result.files); * ``` */ static fromEntries(entryPaths: string[], options: ImportGraphOptions): ImportGraphResult; /** * Traces TypeScript imports from package.json exports. * * @remarks * Static convenience method that extracts entry points from package.json exports * and traces all imports to find public API files. For repeated analysis, * create an instance and use {@link ImportGraph.traceFromPackageExports} instead. * * @param packageJsonPath - Path to package.json (relative to rootDir or absolute) * @param options - Import graph configuration options * @returns All TypeScript files reachable from the package exports * * @example * ```typescript * import { ImportGraph } from '@savvy-web/rslib-builder'; * * const result = ImportGraph.fromPackageExports( * './package.json', * { rootDir: process.cwd() } * ); * console.log('Public API files:', result.files); * ``` */ static fromPackageExports(packageJsonPath: string, options: ImportGraphOptions): ImportGraphResult; } /** * Structured error from import graph analysis. * * @remarks * Provides detailed error information including the error type for * programmatic handling, a human-readable message, and the relevant * file path when applicable. * * @example * ```typescript * import type { ImportGraphError } from '@savvy-web/rslib-builder'; * * function handleErrors(errors: ImportGraphError[]): void { * for (const error of errors) { * switch (error.type) { * case 'tsconfig_not_found': * console.warn('No tsconfig.json found, using defaults'); * break; * case 'entry_not_found': * console.error(`Missing entry: ${error.path}`); * break; * default: * console.error(error.message); * } * } * } * ``` * * @public */ export declare interface ImportGraphError { /** * The type of error that occurred. * * @remarks * Use this field for programmatic error handling to distinguish * between different failure modes. */ type: ImportGraphErrorType; /** * Human-readable error message. * * @remarks * Suitable for logging or displaying to users. */ message: string; /** * The file path related to the error, if applicable. * * @remarks * Present for errors related to specific files like missing entries * or file read failures. */ path?: string; } /** * Types of errors that can occur during import graph analysis. * * @remarks * These error types allow consumers to handle different failure modes * appropriately. For example, a missing tsconfig might be handled differently * than a missing entry file. * * @public */ 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"; /** * Options for configuring the ImportGraph analyzer. * * @remarks * These options control how the ImportGraph traverses and resolves * TypeScript module imports. The `rootDir` is required and serves as * the base for resolving relative paths and finding the tsconfig.json. * * @example * ```typescript * import type { ImportGraphOptions } from '@savvy-web/rslib-builder'; * * const options: ImportGraphOptions = { * rootDir: '/path/to/project', * tsconfigPath: './tsconfig.build.json', * }; * ``` * * @public */ export declare interface ImportGraphOptions { /** * The project root directory. * * @remarks * All relative paths (entry points, tsconfig path) are resolved from this directory. * This should typically be the package root containing your `package.json`. */ rootDir: string; /** * Custom path to the TypeScript configuration file. * * @remarks * If not provided, the analyzer searches for `tsconfig.json` starting from `rootDir` * and walking up the directory tree. The tsconfig is used for module resolution * settings including path aliases and module resolution strategy. * * @defaultValue Searches for tsconfig.json from rootDir */ tsconfigPath?: string; /** * Custom TypeScript system for file operations. * * @remarks * This is primarily used for testing to provide a mock filesystem. * In production use, this defaults to `ts.sys` which uses the real filesystem. * * @defaultValue ts.sys * @internal */ sys?: ts.System; /** * Additional patterns to exclude from results. * * @remarks * Patterns are matched against file paths using simple string inclusion. * Use this to exclude files that don't match the default test file patterns. * * The default exclusions are always applied: * - `.test.` and `.spec.` files * - `__test__` and `__tests__` directories * - `.d.ts` declaration files * * @example * ```typescript * const graph = new ImportGraph({ * rootDir: process.cwd(), * excludePatterns: ['/fixtures/', '/mocks/', '.stories.'], * }); * ``` * * @defaultValue [] */ excludePatterns?: string[]; } /** * Result of import graph analysis. * * @remarks * Contains the complete set of TypeScript source files discovered by tracing * imports from entry points. The analysis is non-fatal: errors are collected * and tracing continues for other paths even when some imports fail to resolve. * * @example * ```typescript * import type { ImportGraphResult } from '@savvy-web/rslib-builder'; * * function processResult(result: ImportGraphResult): void { * if (result.errors.length > 0) { * console.warn('Some imports could not be resolved:', result.errors); * } * console.log(`Found ${result.files.length} files from ${result.entries.length} entries`); * } * ``` * * @public */ export declare interface ImportGraphResult { /** * All TypeScript source files reachable from the entry points. * * @remarks * Paths are absolute, normalized, and sorted alphabetically. * Test files (`.test.ts`, `.spec.ts`) and test directories (`__test__`, `__tests__`) * are automatically filtered out from results. */ files: string[]; /** * The entry points that were traced. * * @remarks * Paths are absolute and normalized. These are the starting points * from which the import graph was traversed. */ entries: string[]; /** * Errors encountered during import graph analysis. * * @remarks * These errors are non-fatal: tracing continues despite individual failures. * Common errors include missing entry files, unresolvable imports, * or tsconfig parsing failures. * * Each error includes a `type` field for programmatic handling and * a human-readable `message`. Some errors also include a `path` field * indicating the relevant file. */ errors: ImportGraphError[]; } /** * Matches a JSON array. * * @public */ export declare type JsonArray = JsonValue[] | readonly JsonValue[]; /** * Matches a JSON object. * * @remarks * This type can be useful to enforce some input to be JSON-compatible or as a * super-type to be extended from. * * @public */ export declare type JsonObject = { [Key in string]: JsonValue; }; /** * Package.json type definitions. * * @remarks * This is a local copy of type-fest's PackageJson types with TSDoc fixes. * Original source: https://github.com/sindresorhus/type-fest * * TSDoc fixes applied: * - Added deprecation messages to `@deprecated` tags * - Fixed code fence formatting in `packageManager` docs * */ /** * Matches any valid JSON primitive value. * * @public */ export declare type JsonPrimitive = string | number | boolean | null; /** * Matches any valid JSON value. * * @public */ export declare type JsonValue = JsonPrimitive | JsonObject | JsonArray; /** * Output format for library builds. * * @remarks * - `"esm"` - ES Modules format (sets `type: "module"` in package.json) * - `"cjs"` - CommonJS format (sets `type: "commonjs"` in package.json) * * @public */ export declare type LibraryFormat = "esm" | "cjs"; /** * Represents a TypeScript configuration file for library builds. * * @remarks * This class extends {@link TSConfigFile} to add library-specific build methods for * generating bundled build configurations. It provides methods to: * - Generate build-mode specific configurations * - Write temporary configuration files for build tools * - Transform paths and filter includes based on build mode * * @see {@link TSConfigFile} for the base class * @internal */ export declare class LibraryTSConfigFile extends TSConfigFile { /** * Write the bundle-mode configuration to a temporary file. * * @remarks * Creates a temporary tsconfig.json file with absolute paths that work from /tmp. * Uses the base compiler options from the template but generates include patterns * dynamically based on the actual package structure. * * The temporary file will be automatically cleaned up when the process exits. * * @param mode - Build mode (dev, npm) * @returns Absolute path to the temporary file */ writeBundleTempConfig(_mode: "dev" | "npm", options?: { types?: string[]; }): string; } /** * Allows creating a union type by combining primitive types and literal types * without sacrificing auto-completion in IDEs for the literal type part of the union. * * @remarks * Currently, when a union type of a primitive type is combined with literal types, * TypeScript loses all information about the combined literals. Thus, when such * type is used in an IDE with autocompletion, no suggestions are made for the * declared literals. * * This type is a workaround for Microsoft/TypeScript#29729. * * @typeParam LiteralType - The literal type(s) to include * @typeParam BaseType - The base primitive type * * @public */ export declare type LiteralUnion = LiteralType | (BaseType & Record); /** * Builder for Node.js ESM libraries using RSlib. * * @remarks * NodeLibraryBuilder provides a high-level API for building modern ESM Node.js libraries. * It handles TypeScript compilation, declaration bundling, package.json transformation, * and multi-target builds (dev and npm). * * Features: * - Automatic entry point detection from package.json exports * - TypeScript declarations via tsgo + API Extractor * - pnpm catalog and workspace protocol resolution * - Source maps for development builds * - Configurable external dependencies and type bundling * * @example * Basic usage in `rslib.config.ts`: * ```typescript * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder'; * * export default NodeLibraryBuilder.create(); * ``` * * @example * With custom options: * ```typescript * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder'; * * export default NodeLibraryBuilder.create({ * externals: ['@rslib/core', '@rsbuild/core'], * dtsBundledPackages: ['picocolors'], * transform({ mode, pkg }) { * if (mode === 'npm') { * delete pkg.devDependencies; * } * return pkg; * }, * }); * ``` * * @example * Build commands: * ```bash * # Development build (with source maps) * rslib build --env-mode dev * * # Production build (for npm publishing) * rslib build --env-mode npm * ``` * * @public */ export declare class NodeLibraryBuilder { /** Valid build modes for validation. */ private static readonly VALID_MODES; /** * Default configuration options for NodeLibraryBuilder. * * @remarks * These defaults are merged with user-provided options in {@link NodeLibraryBuilder.mergeOptions}. * Arrays are deep-copied to prevent mutation of this object. */ static readonly DEFAULT_OPTIONS: { format: "esm"; plugins: never[]; define: {}; copyPatterns: never[]; targets: ("dev" | "npm")[]; externals: never[]; apiModel: true; bundle: true; cjsInterop: false; }; /** * Merges user-provided options with default options. * * @remarks * This method performs a shallow merge of options with special handling for arrays * (deep-copied to avoid mutation). If a `public` directory exists in the project root, * it's automatically added to `copyPatterns`. * * @param options - Partial configuration options to merge * @returns Complete configuration with all required fields */ static mergeOptions(options?: Partial): NodeLibraryBuilderOptions; /** * Creates an async RSLib configuration function that determines build mode from envMode. * * @remarks * This is the primary entry point for using NodeLibraryBuilder. The returned function * is passed to RSLib and called with environment parameters to generate the build config. * * @param options - Configuration options for the builder * @returns An async function compatible with RSLib's config system */ static create(options?: Partial): RslibConfigAsyncFn; /** * Creates a single-mode build configuration. * * @remarks * This method is called internally by {@link NodeLibraryBuilder.create} for each build mode. * It configures all plugins and RSLib options based on the mode and user options. * * @param mode - The build mode ("dev" or "npm") * @param opts - Configuration options (will be merged with defaults) * @returns Promise resolving to the RSLib configuration */ static createSingleMode(mode: BuildMode, opts: NodeLibraryBuilderOptions): Promise; } /** * Configuration options for the NodeLibraryBuilder. * * @remarks * All options are optional with sensible defaults. The most commonly customized options are: * - `externals`: For dependencies that should remain external * - `dtsBundledPackages`: For inlining type definitions * - `transform`: For custom package.json modifications * * @example * ```typescript * import type { NodeLibraryBuilderOptions } from '@savvy-web/rslib-builder'; * * const options: NodeLibraryBuilderOptions = { * externals: ['@rslib/core'], * dtsBundledPackages: ['picocolors'], * apiModel: { * localPaths: ['../docs/packages/my-package'], * }, * }; * ``` * * @public */ export declare interface NodeLibraryBuilderOptions { /** * Output format for main entry points. * Also determines package.json `type` field: * - `"esm"` → `"type": "module"` * - `"cjs"` → `"type": "commonjs"` * * When an array is provided, the package is built in both formats. * The first format in the array is the primary format (determines `type` field). * Each format outputs to its own subdirectory (`dist/{target}/esm/`, `dist/{target}/cjs/`). * * @defaultValue `"esm"` * * @example * Dual format output: * ```typescript * NodeLibraryBuilder.create({ * format: ['esm', 'cjs'], * }) * ``` */ format?: LibraryFormat | LibraryFormat[]; /** * Per-entry format overrides. * Maps export paths (matching package.json exports keys like `"./markdownlint"`) * to a specific format. Entries not listed inherit the top-level `format`. * * @remarks * When both `entryFormats` and array `format` are used, `entryFormats` takes precedence. * An entry with a specific format override will only be built in that format, * even if the global format is dual. * * @example * ```typescript * NodeLibraryBuilder.create({ * format: 'esm', * entryFormats: { * './markdownlint': 'cjs', * }, * }) * ``` */ entryFormats?: Record; /** * Additional entry points bundled with custom output names. * These entries bypass type generation and package.json exports * but are included in the published package. * * @remarks * Virtual entries are useful for special files like pnpm config files * that need to be bundled but don't require type declarations or * exposure as package exports. * * A module may have ONLY virtualEntries with no regular entry points. * * @example * Mixed: regular entries + virtual entries * ```typescript * NodeLibraryBuilder.create({ * virtualEntries: { * "pnpmfile.cjs": { * source: "./src/pnpmfile.ts", * format: "cjs", * }, * }, * }) * ``` * * @example * Virtual-only: no regular entry points * ```typescript * NodeLibraryBuilder.create({ * format: "cjs", * virtualEntries: { * "pnpmfile.cjs": { * source: "./src/pnpmfile.ts", * }, * }, * }) * ``` */ virtualEntries?: Record; /** Override entry points (optional - will auto-detect from package.json) */ entry?: Record; /** * When enabled, each export path will generate an index.js file in a directory * structure matching the export path, rather than using the export name as the filename. * * @example * When `exportsAsIndexes` is `true`, given this package.json configuration: * ```json * { * "exports": { * ".": "./src/entrypoint.ts", * "./foo/bar": "./src/foo/bar.ts", * "./foo/baz": "./src/foo/baz.ts" * } * } * ``` * * You would get this output file structure: * ``` * dist/ * index.js * foo/ * bar/ * index.js * baz/ * index.js * ``` */ exportsAsIndexes?: boolean; /** * Patterns for files to copy to the output directory. * * @remarks * Supports both string paths and detailed configuration objects. * A `public/` directory in the project root is automatically added if it exists. * * @defaultValue `[]` */ copyPatterns: (string | CopyPatternConfig)[]; /** * Additional Rsbuild plugins to include in the build. * * @remarks * These plugins run after the built-in plugins (AutoEntryPlugin, DtsPlugin, etc.). * * @defaultValue `[]` */ plugins: RsbuildPlugin[]; /** * Compile-time constants for code replacement. * * @remarks * Values are stringified and replaced in the source code during bundling. * The `process.env.__PACKAGE_VERSION__` constant is automatically defined. * * @see {@link https://rsbuild.dev/config/source/define | Rsbuild define documentation} * * @defaultValue `{}` */ define: SourceConfig["define"]; /** * Path to the TypeScript configuration file for the build. * * @remarks * If not specified, the plugin searches for `tsconfig.json` in the project root. * A temporary tsconfig is generated for declaration generation regardless of this setting. * * @defaultValue `undefined` (auto-detected) */ tsconfigPath: string | undefined; /** Build modes to include (default: ["dev", "npm"]) */ targets?: BuildMode[]; /** * External dependencies that should not be bundled. * These modules will be imported at runtime instead of being included in the bundle. * * @remarks * This is useful for dependencies that are in devDependencies but needed at runtime, * such as build tools that the package uses to build other packages. * * @example * ```typescript * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder'; * * export default NodeLibraryBuilder.create({ * externals: ['@rslib/core', '@rsbuild/core'], * }); * ``` */ externals?: (string | RegExp)[]; /** * Packages whose type declarations should be bundled into the output .d.ts files. * * @remarks * By default, RSlib bundles types from packages in package.json. Use this to explicitly * specify which packages (including transitive dependencies) should have their types bundled. * This is particularly useful for ensuring devDependencies are fully inlined without external imports. * * Supports minimatch patterns (e.g., '\@pnpm/**', 'picocolors') * * @example * ```typescript * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder'; * * export default NodeLibraryBuilder.create({ * dtsBundledPackages: ['@pnpm/lockfile.types', '@pnpm/types', 'picocolors'], * }); * ``` */ dtsBundledPackages?: string[]; /** * Optional callback to transform files after they're built but before the files array is finalized. * Useful for copying/renaming files or adding additional files to the build output. * * @param context - Transform context with properties: * - `compilation`: Rspack compilation object with assets * - `filesArray`: Set of files that will be included in package.json files field * - `mode`: Current build mode (dev/npm) * * @example * ```typescript * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder'; * * export default NodeLibraryBuilder.create({ * transformFiles({ compilation, filesArray }) { * // Copy index.cjs to .pnpmfile.cjs * const indexAsset = compilation.assets['index.cjs']; * if (indexAsset) { * compilation.assets['.pnpmfile.cjs'] = indexAsset; * filesArray.add('.pnpmfile.cjs'); * } * }, * }); * ``` */ transformFiles?: (context: { /** Rspack compilation object with assets */ compilation: { assets: Record; }; filesArray: Set; /** Current build mode */ mode: BuildMode; }) => void | Promise; /** * Optional transform function to modify package.json before it's saved. * Called after all standard transformations are applied. * * @param context - Transform context containing the target and package.json * @returns The modified package.json (mutations are also supported) * * @example * ```typescript * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder'; * * export default NodeLibraryBuilder.create({ * transform({ mode, pkg }) { * if (mode === 'npm') { * delete pkg.devDependencies; * delete pkg.scripts; * } * return pkg; * }, * }); * ``` */ transform?: TransformPackageJsonFn; /** * Options for API model generation. * Generates an `.api.json` file in the dist directory. * Only applies when mode is "npm". * * @remarks * API model generation is **enabled by default**. The generated file contains * full API documentation in a machine-readable format for documentation generators. * The file is emitted to dist but excluded from npm publish (added as negated pattern in `files` array). * * @defaultValue true * * @example * Disable API model generation: * ```typescript * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder'; * * export default NodeLibraryBuilder.create({ * apiModel: false, * }); * ``` * * @example * Customize with options (implicitly enabled): * ```typescript * import { NodeLibraryBuilder } from '@savvy-web/rslib-builder'; * * export default NodeLibraryBuilder.create({ * apiModel: { * filename: 'my-package.api.json', * }, * }); * ``` */ apiModel?: ApiModelOptions | boolean; /** * Whether to bundle JavaScript output into single files per entry point. * * @remarks * - `true` (default): RSlib bundles JS into single files per entry (current behavior) * - `false`: RSlib runs in bundleless mode, preserving file structure for JS output. * DTS is still bundled per entry via API Extractor (hybrid mode). * When `apiModel` is enabled with multiple entries, per-entry API models are * merged into a single `api.model.json` with multiple EntryPoint members. * * @defaultValue true */ bundle?: boolean; /** * Enable CJS default export interop for CommonJS output files. * When true, CJS files are patched so `require('module')` returns * the default export directly instead of `{ default: value }`. * Named exports are preserved as properties on the default value. * Only affects CJS format output; ESM is unchanged. * @defaultValue false */ cjsInterop?: boolean; } /** * PackageJson namespace containing all sub-types. * * @public */ export declare namespace PackageJson { /** * A person who has been involved in creating or maintaining the package. */ export type Person = string | { name: string; url?: string; email?: string; }; /** * Location for reporting bugs. */ export type BugsLocation = string | { /** The URL to the package's issue tracker. */ url?: string; /** The email address to which issues should be reported. */ email?: string; }; /** * Directory locations within the package. */ export interface DirectoryLocations { [directoryType: string]: JsonValue | undefined; /** Location for executable scripts. Sugar to generate entries in the `bin` property by walking the folder. */ bin?: string; /** Location for Markdown files. */ doc?: string; /** Location for example scripts. */ example?: string; /** Location for the bulk of the library. */ lib?: string; /** Location for man pages. Sugar to generate a `man` array by walking the folder. */ man?: string; /** Location for test files. */ test?: string; } /** * Script commands that are run at various times in the lifecycle of the package. */ export type Scripts = { /** Run before the package is published (Also run on local `npm install` without any arguments). */ prepublish?: string; /** Run both before the package is packed and published, and on local `npm install` without any arguments. */ prepare?: string; /** Run before the package is prepared and packed, only on `npm publish`. */ prepublishOnly?: string; /** Run before a tarball is packed (on `npm pack`, `npm publish`, and when installing git dependencies). */ prepack?: string; /** Run after the tarball has been generated and moved to its final destination. */ postpack?: string; /** Run after the package is published. */ publish?: string; /** Run after the package is published. */ postpublish?: string; /** Run before the package is installed. */ preinstall?: string; /** Run after the package is installed. */ install?: string; /** Run after the package is installed and after `install`. */ postinstall?: string; /** Run before the package is uninstalled and before `uninstall`. */ preuninstall?: string; /** Run before the package is uninstalled. */ uninstall?: string; /** Run after the package is uninstalled. */ postuninstall?: string; /** Run before bump the package version and before `version`. */ preversion?: string; /** Run before bump the package version. */ version?: string; /** Run after bump the package version. */ postversion?: string; /** Run with the `npm test` command, before `test`. */ pretest?: string; /** Run with the `npm test` command. */ test?: string; /** Run with the `npm test` command, after `test`. */ posttest?: string; /** Run with the `npm stop` command, before `stop`. */ prestop?: string; /** Run with the `npm stop` command. */ stop?: string; /** Run with the `npm stop` command, after `stop`. */ poststop?: string; /** Run with the `npm start` command, before `start`. */ prestart?: string; /** Run with the `npm start` command. */ start?: string; /** Run with the `npm start` command, after `start`. */ poststart?: string; /** Run with the `npm restart` command, before `restart`. */ prerestart?: string; /** Run with the `npm restart` command. */ restart?: string; /** Run with the `npm restart` command, after `restart`. */ postrestart?: string; } & Partial>; /** * Dependencies of the package. The version range is a string which has one or * more space-separated descriptors. */ export type Dependency = Partial>; /** * Recursive map describing selective dependency version overrides supported by npm. */ export type DependencyOverrides = { [packageName in string]: string | undefined | DependencyOverrides; }; /** * Specifies requirements for development environment components. */ export interface DevEngineDependency { name: string; version?: string; onFail?: "ignore" | "warn" | "error" | "download"; } /** * A mapping of conditions and the paths to which they resolve. */ export interface ExportConditions { [condition: string]: Exports; } /** * Entry points of a module, optionally with conditions and subpath exports. */ export type Exports = null | string | Array | ExportConditions; /** * Import map entries of a module, optionally with conditions and subpath imports. */ export interface Imports { [key: `#${string}`]: Exports; } /** * Non-standard entry point fields used by various bundlers. */ export interface NonStandardEntryPoints { /** An ECMAScript module ID that is the primary entry point to the program. */ module?: string; /** A module ID with untranspiled code that is the primary entry point to the program. */ esnext?: string | { [moduleName: string]: string | undefined; main?: string; browser?: string; }; /** A hint to JavaScript bundlers or component tools when packaging modules for client side use. */ browser?: string | Partial>; /** * Denote which files in your project are "pure" and therefore safe for Webpack to prune if unused. * * @see {@link https://webpack.js.org/guides/tree-shaking/ | Webpack Tree Shaking} */ sideEffects?: boolean | string[]; } /** * TypeScript-specific configuration fields. */ export interface TypeScriptConfiguration { /** Location of the bundled TypeScript declaration file. */ types?: string; /** Version selection map of TypeScript. */ typesVersions?: Partial>>>; /** Location of the bundled TypeScript declaration file. Alias of `types`. */ typings?: string; } /** * An alternative configuration for workspaces. */ export interface WorkspaceConfig { /** An array of workspace pattern strings which contain the workspace packages. */ packages?: WorkspacePattern[]; /** * Designed to solve the problem of packages which break when their `node_modules` * are moved to the root workspace directory - a process known as hoisting. * * @see {@link https://classic.yarnpkg.com/blog/2018/02/15/nohoist/ | Yarn nohoist} */ nohoist?: WorkspacePattern[]; } /** * A workspace pattern points to a directory or group of directories which * contain packages that should be included in the workspace installation process. * * @example * `docs` - Include the docs directory and install its dependencies. * * @example * `packages/*` - Include all nested directories within the packages directory. */ export type WorkspacePattern = string; /** * Yarn-specific configuration fields. */ export interface YarnConfiguration { /** * If your package only allows one version of a given dependency, and you'd like * to enforce the same behavior as `yarn install --flat` on the command-line, * set this to `true`. */ flat?: boolean; /** Selective version resolutions. Allows the definition of custom package versions inside dependencies. */ resolutions?: Dependency; } /** * JSPM-specific configuration fields. */ export interface JSPMConfiguration { /** JSPM configuration. */ jspm?: PackageJson; } /** * Publish configuration options. */ export interface PublishConfig { /** Additional properties from the npm docs on `publishConfig`. */ [additionalProperties: string]: JsonValue | undefined; /** * When publishing scoped packages, the access level defaults to restricted. * If you want your scoped package to be publicly viewable set `--access=public`. */ access?: "public" | "restricted"; /** * The base URL of the npm registry. * * @defaultValue `'https://registry.npmjs.org/'` */ registry?: string; /** * The tag to publish the package under. * * @defaultValue `'latest'` */ tag?: string; /** * Publish targets for multi-registry publishing. * Supports shorthand strings (`"npm"`, `"github"`, `"jsr"`, or a URL) * and full target objects. */ targets?: Array | string>; } /** * Type for npm's `package.json` file containing standard npm properties. * * @see {@link https://docs.npmjs.com/creating-a-package-json-file | npm docs} */ export interface PackageJsonStandard { /** The name of the package. */ name?: string; /** Package version, parseable by `node-semver`. */ version?: string; /** Package description, listed in `npm search`. */ description?: string; /** Keywords associated with package, listed in `npm search`. */ keywords?: string[]; /** The URL to the package's homepage. */ homepage?: LiteralUnion<".", string>; /** The URL to the package's issue tracker and/or the email address to which issues should be reported. */ bugs?: BugsLocation; /** The license for the package. */ license?: string; /** The licenses for the package. */ licenses?: Array<{ type?: string; url?: string; }>; /** The author of the package. */ author?: Person; /** A list of people who contributed to the package. */ contributors?: Person[]; /** A list of people who maintain the package. */ maintainers?: Person[]; /** The files included in the package. */ files?: string[]; /** * Resolution algorithm for importing ".js" files from the package's scope. * * @see {@link https://nodejs.org/api/esm.html#esm_package_json_type_field | Node.js ESM docs} */ type?: "module" | "commonjs"; /** The module ID that is the primary entry point to the program. */ main?: string; /** * Subpath exports to define entry points of the package. * * @see {@link https://nodejs.org/api/packages.html#subpath-exports | Node.js Subpath exports} */ exports?: Exports; /** * Subpath imports to define internal package import maps. * * @see {@link https://nodejs.org/api/packages.html#subpath-imports | Node.js Subpath imports} */ imports?: Imports; /** The executable files that should be installed into the `PATH`. */ bin?: string | Partial>; /** Filenames to put in place for the `man` program to find. */ man?: string | string[]; /** Indicates the structure of the package. */ directories?: DirectoryLocations; /** Location for the code repository. */ repository?: string | { type: string; url: string; /** Relative path to package.json if it is placed in non-root directory (for monorepos). */ directory?: string; }; /** Script commands that are run at various times in the lifecycle of the package. */ scripts?: Scripts; /** Is used to set configuration parameters used in package scripts that persist across upgrades. */ config?: JsonObject; /** The dependencies of the package. */ dependencies?: Dependency; /** Additional tooling dependencies that are not required for the package to work. */ devDependencies?: Dependency; /** Dependencies that are skipped if they fail to install. */ optionalDependencies?: Dependency; /** Dependencies that will usually be required by the package user directly or via another dependency. */ peerDependencies?: Dependency; /** Indicate peer dependencies that are optional. */ peerDependenciesMeta?: Partial>; /** Package names that are bundled when the package is published. */ bundledDependencies?: string[]; /** Alias of `bundledDependencies`. */ bundleDependencies?: string[]; /** Overrides is used to support selective version overrides using npm. */ overrides?: DependencyOverrides; /** Engines that this package runs on. */ engines?: { [EngineName in "npm" | "node" | string]?: string; }; /** * Whether to enforce engine requirements strictly. * * @deprecated This field is no longer used by npm. Use the `engine-strict` npm config instead. */ engineStrict?: boolean; /** Operating systems the module runs on. */ os?: Array>; /** CPU architectures the module runs on. */ cpu?: Array>; /** Define the runtime and package manager for developing the current project. */ devEngines?: { os?: DevEngineDependency | DevEngineDependency[]; cpu?: DevEngineDependency | DevEngineDependency[]; libc?: DevEngineDependency | DevEngineDependency[]; runtime?: DevEngineDependency | DevEngineDependency[]; packageManager?: DevEngineDependency | DevEngineDependency[]; }; /** * If set to `true`, a warning will be shown if package is installed locally. * * @deprecated This field is no longer used by npm. Use the `bin` field to create CLI tools instead. */ preferGlobal?: boolean; /** If set to `true`, then npm will refuse to publish it. */ private?: boolean; /** A set of config values that will be used at publish-time. */ publishConfig?: PublishConfig; /** * Describes and notifies consumers of a package's monetary support information. * * @see {@link https://github.com/npm/rfcs/blob/main/implemented/0017-add-funding-support.md | npm funding RFC} */ funding?: string | { /** The type of funding. */ type?: LiteralUnion<"github" | "opencollective" | "patreon" | "individual" | "foundation" | "corporation", string>; /** The URL to the funding page. */ url: string; }; /** * Used to configure npm workspaces / Yarn workspaces. * * @remarks * Workspaces allow you to manage multiple packages within the same repository * in such a way that you only need to run your install command once in order * to install all of them in a single pass. * * Please note that the top-level `private` property of `package.json` must * be set to `true` in order to use workspaces. * * @see {@link https://docs.npmjs.com/cli/using-npm/workspaces | npm workspaces} * @see {@link https://classic.yarnpkg.com/docs/workspaces/ | Yarn workspaces} */ workspaces?: WorkspacePattern[] | WorkspaceConfig; } /** * Type for `package.json` file used by the Node.js runtime. * * @see {@link https://nodejs.org/api/packages.html#nodejs-packagejson-field-definitions | Node.js docs} */ export interface NodeJsStandard { /** * Defines which package manager is expected to be used when working on the current project. * * @remarks * It can be set to any of the supported package managers, and will ensure that * your teams use the exact same package manager versions without having to * install anything else other than Node.js. * * This field is currently experimental and needs to be opted-in; check the * Corepack page for details about the procedure. * * @example * ```json * { * "packageManager": "pnpm@8.0.0" * } * ``` * * @see {@link https://nodejs.org/api/corepack.html | Node.js Corepack docs} */ packageManager?: string; } } /** * Type for npm's `package.json` file. * * @remarks * Also includes types for fields used by other popular projects, like TypeScript and Yarn. * * @see {@link https://docs.npmjs.com/creating-a-package-json-file | npm docs} * * @public */ export declare type PackageJson = JsonObject & PackageJson.NodeJsStandard & PackageJson.PackageJsonStandard & PackageJson.NonStandardEntryPoints & PackageJson.TypeScriptConfiguration & PackageJson.YarnConfiguration & PackageJson.JSPMConfiguration; /** * Plugin to transform package.json for distribution. * * @remarks * This plugin processes the source package.json and transforms it for the build output. * It handles path transformations, pnpm catalog/workspace resolution, and field cleanup. * * ## Transformations Applied * * - **Path Updates**: Converts source paths to output paths (e.g., `./src/index.ts` → `./index.js`) * - **Type Conditions**: Adds `types` fields to exports pointing to `.d.ts` files * - **pnpm Resolution**: Resolves `catalog:` and `workspace:*` dependency versions * - **Field Cleanup**: Removes `scripts`, `publishConfig`, and other dev-only fields * - **Private Flag**: Sets based on `publishConfig.access` or `forcePrivate` option * * ## Plugin Interoperability * * - Consumes `entrypoints` map from AutoEntryPlugin * - Consumes `exportToOutputMap` for exportsAsIndexes mode * - Consumes `use-rollup-types` flag from DtsPlugin * - Exposes `base-package-json` after standard transforms (before user transform) * * @param options - Plugin configuration options * * @example * Basic usage: * ```typescript * import { PackageJsonTransformPlugin } from '@savvy-web/rslib-builder'; * * export default { * plugins: [ * PackageJsonTransformPlugin({ * bundle: true, * processTSExports: true, * }), * ], * }; * ``` * * @example * With custom transform: * ```typescript * import { PackageJsonTransformPlugin } from '@savvy-web/rslib-builder'; * * export default { * plugins: [ * PackageJsonTransformPlugin({ * target: 'npm', * transform(pkg) { * delete pkg.devDependencies; * return pkg; * }, * }), * ], * }; * ``` * * @public */ export declare const PackageJsonTransformPlugin: (options?: PackageJsonTransformPluginOptions) => RsbuildPlugin; /** * Options for the PackageJsonTransformPlugin. * * @public */ export declare interface PackageJsonTransformPluginOptions { /** * Output format for the library. * Determines the package.json `type` field: * - `"esm"` → `"type": "module"` * - `"cjs"` → `"type": "commonjs"` * * @defaultValue `"esm"` */ format?: LibraryFormat; /** * Override the package name in the output package.json. * * @remarks * - When a string is provided, the package name is replaced with that value * - When `true`, the original name is preserved (no override) * - When undefined, the original name is preserved * * @example * ```typescript * import type { PackageJsonTransformPluginOptions } from '@savvy-web/rslib-builder'; * * const options: PackageJsonTransformPluginOptions = { * name: '@scope/my-package-dist', * }; * ``` */ name?: string | true; /** * Force the output package.json to have `"private": true`. * * @remarks * Useful for development builds that should never be published. * When true, overrides the `publishConfig.access` setting. * * @defaultValue false */ forcePrivate?: boolean; /** * Whether to process TypeScript exports and generate type conditions. * * @remarks * When enabled, transforms export paths from `.ts` to `.js` and adds * `types` conditions pointing to the corresponding `.d.ts` files. * * @example * Input: `"./src/index.ts"` * Output: `{ "types": "./index.d.ts", "import": "./index.js" }` */ processTSExports?: boolean; /** * Whether the build is in bundle mode. * * @remarks * Affects export path transformations - in bundle mode, nested index files * are collapsed (e.g., `./utils/index.ts` becomes `./utils.js`). * * @defaultValue false */ bundle?: boolean; /** * Build mode identifier for custom transformations. * * @remarks * Passed to the transform function to allow mode-specific modifications. * Common values: "dev", "npm" */ mode?: string; /** * Custom transform function to modify package.json after standard transformations. * * @remarks * Called after all built-in transformations (path updates, pnpm resolution, etc.) * are applied. Mutations to the object are also supported. * * @param pkg - The package.json object after standard transformations * @returns The modified package.json object * * @example * ```typescript * import type { PackageJsonTransformPluginOptions } from '@savvy-web/rslib-builder'; * * const options: PackageJsonTransformPluginOptions = { * transform(pkg) { * delete pkg.devDependencies; * pkg.publishConfig = { access: 'public' }; * return pkg; * }, * }; * ``` */ transform?: (pkg: PackageJson) => PackageJson; /** * Per-entry format overrides for export conditions. * Maps export paths to their format (e.g., `{ "./markdownlint": "cjs" }`). * Entries not listed inherit the top-level `format`. */ entryFormats?: Record; /** * Whether the build uses dual format (both ESM and CJS). * When true, exports get both `import` and `require` conditions * with format directory prefixes. */ dualFormat?: boolean; } /** * Matches any primitive value. * * @see {@link https://developer.mozilla.org/en-US/docs/Glossary/Primitive | MDN Primitive} * * @public */ export declare type Primitive = null | undefined | string | number | boolean | symbol | bigint; /** * Publishing protocol for a publish target. * * @remarks * - `"npm"` - npm-compatible registries (npmjs, GitHub Packages, Verdaccio, etc.) * - `"jsr"` - JavaScript Registry (jsr.io) * * @public */ export declare type PublishProtocol = "npm" | "jsr"; /** * A resolved publish target from `publishConfig.targets`. * * @remarks * Aligns with `ResolvedTarget` from silk-release-action, * minus authentication-specific fields. * * @public */ export declare interface PublishTarget { /** The publishing protocol. */ protocol: PublishProtocol; /** The registry URL, or `null` for JSR targets. */ registry: string | null; /** The absolute path to the output directory for this target. */ directory: string; /** Package access level for scoped packages. */ access: "public" | "restricted"; /** Whether provenance attestations are configured. */ provenance: boolean; /** The publish tag (e.g., "latest", "next", "beta"). */ tag: string; } /** * Plugin to produce per-target output directories for multi-registry publishing. * * @remarks * Runs in `onCloseBuild` after the main RSlib build completes. For each * publish target: * * 1. Creates the target directory * 2. Copies all build output from the staging directory * 3. Reads the exposed `base-package-json` (after standard transforms, before user transform) * 4. Applies the user transform with the target-specific context * 5. Applies optional name override * 6. Copies the `files` array from the staging directory's package.json * 7. Writes the final package.json to the target directory * * @param options - Plugin configuration options * * @public */ export declare const PublishTargetPlugin: (options: PublishTargetPluginOptions) => RsbuildPlugin; /** * Options for the PublishTargetPlugin. * * @public */ export declare interface PublishTargetPluginOptions { /** * Publish targets to write output for. * * @remarks * Each target gets a copy of the build staging output with per-target * package.json transformations applied. */ targets: PublishTarget[]; /** * Absolute path to the build staging directory (dist/<mode>). * * @remarks * Build artifacts are copied from this directory to each target's * directory (when they differ). */ stagingDir: string; /** * Current build mode. */ mode: BuildMode; /** * Optional user transform function applied to each target's package.json. * * @remarks * Called after copying the base package.json state for each target. */ transform?: TransformPackageJsonFn; /** * Optional package name override. * * @remarks * When provided, overrides the `name` field in each target's package.json. */ name?: string; } /** * Compiler options with enum values converted to strings. * * @remarks * This is an open-ended record type because TypeScript compiler options * can vary by version. Known options use their proper types internally, * but the public interface allows for flexibility. * * @public */ export declare interface ResolvedCompilerOptions { [key: string]: unknown; } /** * Resolved tsconfig.json structure for JSON serialization. * * @remarks * This interface represents a flattened tsconfig.json file that can be * serialized to JSON. All enum values are converted to their string * equivalents, and path-dependent options are excluded. * * The resolved config is designed for virtual TypeScript environments * where file paths and emit settings are controlled externally. * * **Excluded options:** * - Path-dependent: `rootDir`, `outDir`, `baseUrl`, `paths`, `typeRoots` * - Emit-related: `declaration`, `sourceMap`, `inlineSourceMap`, etc. * - File selection: `include`, `exclude`, `files`, `references` * * @public */ export declare interface ResolvedTsconfig { /** * JSON schema for IDE support. */ $schema: string; /** * Compiler options with enum values converted to strings. */ compilerOptions: ResolvedCompilerOptions; } /** * Resolve publish targets from package.json's `publishConfig.targets`. * * @remarks * Expands shorthand strings (`"npm"`, `"github"`, `"jsr"`, or a URL) into * fully resolved {@link PublishTarget} objects. Mirrors the resolution logic * in silk-release-action, but only produces the subset of fields * relevant to the build process. * * @param packageJson - The parsed package.json * @param cwd - The package root directory (for resolving relative directories) * @param outdir - The default output directory (used when no target directory is specified) * @returns Array of resolved publish targets (empty if none configured) * * @public */ export declare function resolvePublishTargets(packageJson: PackageJson, cwd: string, outdir: string): PublishTarget[]; /** * Async RSLib configuration function type. * @public */ export declare type RslibConfigAsyncFn = (env: ConfigParams) => Promise; /** Built-in externals for RSPress plugin bundles. */ export declare const RSPRESS_PLUGIN_EXTERNALS: readonly string[]; /** Built-in externals for RSPress runtime bundles. */ export declare const RSPRESS_RUNTIME_EXTERNALS: readonly string[]; /** * Builder for RSPress plugin packages with dual-bundle architecture. * * @remarks * Produces up to two RSlib lib configs: * - **Plugin lib**: The main RSPress plugin entry (always generated) * - **Runtime lib**: React components for the RSPress theme (auto-detected or explicit) * * @public */ export declare class RSPressPluginBuilder { private static readonly VALID_MODES; /** * Merges user-provided options with defaults. * * @param options - Partial configuration options to merge * @returns Merged options with defaults applied */ static mergeOptions(options?: Partial): RSPressPluginBuilderOptions; /** * Creates an async RSLib configuration function for RSPress plugin packages. * * @param options - Configuration options for the builder * @returns An async function compatible with RSLib's config system */ static create(options?: Partial): RslibConfigAsyncFn; /** * Creates a single-mode build configuration with plugin and optional runtime libs. * * @param mode - The build mode ("dev" or "npm") * @param options - Configuration options * @returns Promise resolving to the RSLib configuration */ static createSingleMode(mode: BuildMode, options: RSPressPluginBuilderOptions): Promise; /** * Determines whether the runtime bundle should be enabled. */ private static shouldEnableRuntime; /** * Creates the plugin lib configuration. */ private static createPluginLib; /** * Creates the runtime lib configuration. */ private static createRuntimeLib; } /** * Options for RSPressPluginBuilder. * @public */ export declare interface RSPressPluginBuilderOptions { /** Plugin bundle configuration. Always generated. */ plugin?: RSPressPluginBundleOptions; /** Runtime bundle configuration. Auto-detected from `src/runtime/index.tsx`, or `false` to disable. */ runtime?: RSPressPluginBundleOptions | false; /** API model generation options. Default: `true`. */ apiModel?: ApiModelOptions | boolean; /** Packages to bundle in TypeScript declarations. */ dtsBundledPackages?: string[]; /** Custom package.json transform function. */ transform?: TransformPackageJsonFn; /** Path to custom tsconfig.json. Overrides the default RSPress plugin preset. */ tsconfigPath?: string; /** Build modes to produce. Default: `["dev", "npm"]`. */ modes?: BuildMode[]; /** Static files to copy to output (e.g., i18n JSON). */ copyPatterns?: (string | CopyPatternConfig)[]; } /** * Options for an individual RSPress plugin bundle (plugin or runtime). * @public */ export declare interface RSPressPluginBundleOptions { /** Entry point path. Plugin default: `"./src/index.ts"`, runtime default: `"./src/runtime/index.tsx"` */ entry?: string; /** Additional externals merged with built-in RSPress externals. */ externals?: (string | RegExp)[]; /** Additional Rsbuild plugins. `pluginReact()` is auto-added on runtime. */ plugins?: RsbuildPlugin[]; /** Additional define constants merged with `{ "import.meta.env": "import.meta.env" }`. */ define?: SourceConfig["define"]; } /** * Function to transform package.json during the build process. * * @remarks * This function is called after all standard transformations are applied, * allowing you to modify the package.json before it's written to the output directory. * Mutations to the `pkg` object are also supported. * * @param context - Transform context containing: * - `mode`: The current build mode ("dev" or "npm") * - `target`: The publish target for the current output. For single-registry builds * or dev mode, this is `undefined`. For multi-registry builds (`publishConfig.targets`), * the primary target receives the first resolved target and additional targets receive * their respective target via `PublishTargetPlugin` * - `pkg`: The package.json object to transform * @returns The modified package.json object * * @example * ```typescript * import type { TransformPackageJsonFn } from '@savvy-web/rslib-builder'; * * const transform: TransformPackageJsonFn = ({ mode, target, pkg }) => { * if (mode === 'npm') { * delete pkg.devDependencies; * delete pkg.scripts; * } * return pkg; * }; * ``` * @public */ export declare type TransformPackageJsonFn = (context: { mode: BuildMode; target: PublishTarget | undefined; pkg: PackageJson; }) => PackageJson; /** * Represents a TypeScript configuration file with utilities for path resolution. * * @remarks * This class provides convenient access to TypeScript configuration files, * with automatic path resolution and JSON parsing. It implements custom * inspection for improved debugging output in Node.js console. * * The class handles workspace-aware path resolution that correctly handles * cross-package references by using node_modules symlinks when crossing * package boundaries. * * The class uses lazy getters for both path resolution and configuration * parsing, ensuring that file I/O only occurs when these properties are * accessed. This makes it efficient to create instances without immediately * reading from disk. * * This base class is suitable for workspace-level configurations. For library * build configurations that require bundle transformations, use * {@link LibraryTSConfigFile}. * * @see {@link LibraryTSConfigFile} for library build configurations * @internal */ export declare class TSConfigFile { pathname: string; /** * Human-readable description of what this configuration is used for. * * @remarks * This description helps developers understand the purpose and intended use * case for this particular TypeScript configuration. */ readonly description: string; /** * Relative path from current working directory to the config file. * * @remarks * Returns a relative path string prefixed with `./` that points from the * current working directory to the TypeScript configuration file. This is * useful for displaying user-friendly paths in logs and error messages. * * The path is computed lazily each time it's accessed, so it will reflect * changes if the current working directory changes during execution. * * @returns A relative path string with `./` prefix (e.g., `./tsconfig/ecma/lib.json`) */ get path(): string; /** * Get configuration with `$\{configDir\}` variables replaced. * * @remarks * Returns the configuration with all `${configDir}` template variables replaced * with the relative path to the package root. This is useful for configurations * that use template variables for path resolution. * * @returns The configuration with transformed paths */ get bundled(): TSConfigJsonWithSchema; /** * Parsed TypeScript configuration object. * * @remarks * Returns the TypeScript configuration object imported at build time. * The configuration object includes standard TypeScript compiler options * and other tsconfig.json fields with JSON schema validation. * * @returns The parsed TypeScript configuration as a {@link TSConfigJsonWithSchema} object * * @throws If the configuration file is not found in imports * * @see {@link TSConfigJsonWithSchema} for the configuration type definition */ get config(): TSConfigJsonWithSchema; /** * Creates a new TSConfigFile instance. * * @remarks * Initializes a TSConfigFile with the specified description and absolute path * to a TypeScript configuration file. The constructor sets up lazy getters for * the `path` and `config` properties using `Object.defineProperty`, making * them enumerable but computed on demand. * * Additionally, it configures custom Node.js inspection behavior via * `util.inspect.custom` to provide pretty-printed output when the * instance is logged to the console. This includes showing all nested * levels, colors, and unlimited array lengths for better debugging. * * No file I/O occurs during construction - files are only read when * the `config` getter is accessed. * * @param description - Human-readable description of what this configuration is used for * @param pathname - Absolute path to the TypeScript configuration file */ constructor(description: string, pathname: string); } /** * Resolves TypeScript ParsedCommandLine to a JSON-serializable tsconfig format. * * @remarks * This class converts TypeScript's internal `ParsedCommandLine` representation * back to a portable JSON format suitable for virtual TypeScript environments * like API Extractor or other tooling that needs type information without * actually emitting files. * * **Key transformations:** * - Converts enum values (target, module, jsx, etc.) to their string equivalents * - Sets `composite: false` and `noEmit: true` for virtual environment compatibility * - Excludes path-dependent options that would be invalid outside the original project * - Excludes emit-related options since the virtual environment handles output * - Converts lib references from full paths (e.g., "lib.esnext.d.ts") to short names * * **Static conversion methods:** * The class provides static methods for converting individual TypeScript enum * values to their string representations. These are useful when you need to * convert specific options without creating a full resolver instance. * * @example Basic usage with ParsedCommandLine * ```typescript * import { parseJsonConfigFileContent, readConfigFile, sys } from 'typescript'; * import { TsconfigResolver } from '@savvy-web/rslib-builder'; * * // Parse the tsconfig.json using TypeScript API * const configFile = readConfigFile('tsconfig.json', sys.readFile.bind(sys)); * const parsed = parseJsonConfigFileContent(configFile.config, sys, process.cwd()); * * // Resolve to JSON-serializable format * const resolver = new TsconfigResolver(); * const resolved = resolver.resolve(parsed, process.cwd()); * * // Write to file for tooling consumption * const json = JSON.stringify(resolved, null, 2); * console.log(json); * ``` * * @example Using static enum conversion methods * ```typescript * import { ScriptTarget, ModuleKind } from 'typescript'; * import { TsconfigResolver } from '@savvy-web/rslib-builder'; * * // Convert individual enum values * const target = TsconfigResolver.convertScriptTarget(ScriptTarget.ES2022); * console.log(target); // "es2022" * * const module = TsconfigResolver.convertModuleKind(ModuleKind.NodeNext); * console.log(module); // "nodenext" * ``` * * @public */ export declare class TsconfigResolver { /** * Mapping of ScriptTarget enum values to their string representations. * @internal */ private static readonly SCRIPT_TARGET_MAP; /** * Mapping of ModuleKind enum values to their string representations. * @internal */ private static readonly MODULE_KIND_MAP; /** * Mapping of ModuleResolutionKind enum values to their string representations. * @internal */ private static readonly MODULE_RESOLUTION_MAP; /** * Mapping of JsxEmit enum values to their string representations. * @internal */ private static readonly JSX_EMIT_MAP; /** * Mapping of ModuleDetectionKind enum values to their string representations. * @internal */ private static readonly MODULE_DETECTION_MAP; /** * Mapping of NewLineKind enum values to their string representations. * @internal */ private static readonly NEW_LINE_MAP; /** * Converts a TypeScript ScriptTarget enum value to its string representation. * * @remarks * Handles all standard ECMAScript targets including the special cases * where `ESNext` and `Latest` share the same numeric value (99). * * @param target - The ScriptTarget enum value to convert * @returns The string representation (e.g., "es2022", "esnext"), or undefined if input is undefined * * @example * ```typescript * import { ScriptTarget } from 'typescript'; * import { TsconfigResolver } from '@savvy-web/rslib-builder'; * * const result = TsconfigResolver.convertScriptTarget(ScriptTarget.ES2022); * console.log(result); // "es2022" * * const latest = TsconfigResolver.convertScriptTarget(ScriptTarget.Latest); * console.log(latest); // "esnext" * ``` * * @public */ static convertScriptTarget(target: ScriptTarget | undefined): string | undefined; /** * Converts a TypeScript ModuleKind enum value to its string representation. * * @remarks * Handles all standard module systems including Node.js-specific module * kinds like `Node16`, `Node18`, `Node20`, and `NodeNext`. * * Note: `Node18` (101) and `Node20` (102) are handled by their numeric * values since they may not be exported in all TypeScript versions. * * @param module - The ModuleKind enum value to convert * @returns The string representation (e.g., "nodenext", "esnext"), or undefined if input is undefined * * @example * ```typescript * import { ModuleKind } from 'typescript'; * import { TsconfigResolver } from '@savvy-web/rslib-builder'; * * const nodeNext = TsconfigResolver.convertModuleKind(ModuleKind.NodeNext); * console.log(nodeNext); // "nodenext" * * const esm = TsconfigResolver.convertModuleKind(ModuleKind.ESNext); * console.log(esm); // "esnext" * ``` * * @public */ static convertModuleKind(module: ModuleKind | undefined): string | undefined; /** * Converts a TypeScript ModuleResolutionKind enum value to its string representation. * * @remarks * Maps module resolution strategies to their tsconfig.json equivalents. * Note that `NodeJs` is a deprecated alias for `Node10` and both share * the same numeric value (2). * * @param resolution - The ModuleResolutionKind enum value to convert * @returns The string representation (e.g., "nodenext", "bundler"), or undefined if input is undefined * * @example * ```typescript * import { ModuleResolutionKind } from 'typescript'; * import { TsconfigResolver } from '@savvy-web/rslib-builder'; * * const bundler = TsconfigResolver.convertModuleResolution(ModuleResolutionKind.Bundler); * console.log(bundler); // "bundler" * * const nodeNext = TsconfigResolver.convertModuleResolution(ModuleResolutionKind.NodeNext); * console.log(nodeNext); // "nodenext" * ``` * * @public */ static convertModuleResolution(resolution: ModuleResolutionKind | undefined): string | undefined; /** * Converts a TypeScript JsxEmit enum value to its string representation. * * @remarks * Maps JSX transformation modes to their tsconfig.json equivalents. * Includes both classic React modes and the modern `react-jsx` transform. * * @param jsx - The JsxEmit enum value to convert * @returns The string representation (e.g., "react-jsx", "preserve"), or undefined if input is undefined * * @example * ```typescript * import { JsxEmit } from 'typescript'; * import { TsconfigResolver } from '@savvy-web/rslib-builder'; * * const reactJsx = TsconfigResolver.convertJsxEmit(JsxEmit.ReactJSX); * console.log(reactJsx); // "react-jsx" * * const preserve = TsconfigResolver.convertJsxEmit(JsxEmit.Preserve); * console.log(preserve); // "preserve" * ``` * * @public */ static convertJsxEmit(jsx: JsxEmit | undefined): string | undefined; /** * Converts a TypeScript ModuleDetectionKind enum value to its string representation. * * @remarks * Maps module detection strategies that control how TypeScript determines * whether a file is a module or a script. * * @param detection - The ModuleDetectionKind enum value to convert * @returns The string representation (e.g., "auto", "force"), or undefined if input is undefined * * @example * ```typescript * import { ModuleDetectionKind } from 'typescript'; * import { TsconfigResolver } from '@savvy-web/rslib-builder'; * * const auto = TsconfigResolver.convertModuleDetection(ModuleDetectionKind.Auto); * console.log(auto); // "auto" * * const force = TsconfigResolver.convertModuleDetection(ModuleDetectionKind.Force); * console.log(force); // "force" * ``` * * @public */ static convertModuleDetection(detection: ModuleDetectionKind | undefined): string | undefined; /** * Converts a TypeScript NewLineKind enum value to its string representation. * * @remarks * Maps line ending preferences to their tsconfig.json equivalents. * * @param newLine - The NewLineKind enum value to convert * @returns The string representation ("lf" or "crlf"), or undefined if input is undefined * * @example * ```typescript * import { NewLineKind } from 'typescript'; * import { TsconfigResolver } from '@savvy-web/rslib-builder'; * * const lf = TsconfigResolver.convertNewLine(NewLineKind.LineFeed); * console.log(lf); // "lf" * * const crlf = TsconfigResolver.convertNewLine(NewLineKind.CarriageReturnLineFeed); * console.log(crlf); // "crlf" * ``` * * @public */ static convertNewLine(newLine: NewLineKind | undefined): string | undefined; /** * Converts a lib reference to its canonical name. * * @remarks * TypeScript's `ParsedCommandLine` stores lib references as full paths like * `lib.esnext.d.ts` or `/path/to/node_modules/typescript/lib/lib.dom.d.ts`. * This method converts them to the canonical short form used in tsconfig.json * like `esnext` or `dom`. * * @param lib - The lib reference (e.g., "lib.esnext.d.ts" or "/path/to/lib.dom.d.ts") * @returns The canonical name (e.g., "esnext", "dom") * * @example * ```typescript * import { TsconfigResolver } from '@savvy-web/rslib-builder'; * * const lib1 = TsconfigResolver.convertLibReference('lib.esnext.d.ts'); * console.log(lib1); // "esnext" * * const lib2 = TsconfigResolver.convertLibReference('/path/to/lib.dom.d.ts'); * console.log(lib2); // "dom" * * const lib3 = TsconfigResolver.convertLibReference('lib.es2022.intl.d.ts'); * console.log(lib3); // "es2022.intl" * ``` * * @public */ static convertLibReference(lib: string): string; /** * Resolves a TypeScript ParsedCommandLine to a JSON-serializable tsconfig object. * * @remarks * This method transforms the parsed TypeScript configuration into a format * suitable for virtual TypeScript environments. It performs the following: * * - Converts enum values (target, module, moduleResolution, jsx) to strings * - Converts lib array format (lib.esnext.d.ts to esnext) * - Sets `composite: false` for virtual environment compatibility * - Sets `noEmit: true` since the virtual environment handles emit * - Excludes path-dependent options (rootDir, outDir, paths, typeRoots, etc.) * - Excludes emit-related options (declaration, sourceMap, etc.) * - Excludes file selection (include, exclude, files, references) * - Adds $schema for IDE support * * When `format` is `"cjs"`, the resolved config uses CommonJS-compatible settings: * - `module: "commonjs"` * - `moduleResolution: "node10"` * - `esModuleInterop: true` * * @param parsed - The parsed TypeScript configuration from `parseJsonConfigFileContent` * @param _rootDir - Reserved for future path normalization (currently unused) * @param format - Optional output format to adjust module settings (`"esm"` or `"cjs"`) * @returns A JSON-serializable tsconfig object * @throws {@link TsconfigResolverError} If resolution fails for any option * * @example * ```typescript * import { parseJsonConfigFileContent, readConfigFile, sys } from 'typescript'; * import { TsconfigResolver } from '@savvy-web/rslib-builder'; * * const configFile = readConfigFile('tsconfig.json', sys.readFile.bind(sys)); * const parsed = parseJsonConfigFileContent(configFile.config, sys, process.cwd()); * * const resolver = new TsconfigResolver(); * const resolved = resolver.resolve(parsed, process.cwd()); * * console.log(JSON.stringify(resolved, null, 2)); * ``` * * @public */ resolve(parsed: ParsedCommandLine, _rootDir: string, format?: LibraryFormat): ResolvedTsconfig; /** * Adds converted enum options to the compiler options object. * @internal */ private addEnumOptions; /** * Adds preserved boolean options to the compiler options object. * @internal */ private addPreservedBooleanOptions; /** * Adds preserved string options to the compiler options object. * @internal */ private addPreservedStringOptions; } /** * Error thrown when tsconfig resolution fails. * * @remarks * This error provides detailed context about what went wrong during * tsconfig resolution, including the specific option or configuration * that caused the failure. * * @example * ```typescript * import { TsconfigResolverError } from '@savvy-web/rslib-builder'; * * try { * const resolver = new TsconfigResolver(); * const config = resolver.resolve(parsedConfig, '/project'); * } catch (error) { * if (error instanceof TsconfigResolverError) { * console.error(`Resolution failed: ${error.message}`); * if (error.option) { * console.error(`Problematic option: ${error.option}`); * } * } * } * ``` * * @public */ export declare class TsconfigResolverError extends Error { /** * The compiler option that caused the error, if applicable. */ readonly option?: string; /** * The value that caused the error, if applicable. */ readonly value?: unknown; constructor(message: string, option?: string, value?: unknown); } /** * Builder for TSDoc configuration files used by API Extractor. * * @remarks * This class provides utilities for generating `tsdoc.json` configuration files * that control TSDoc tag support during API documentation generation. * * ## Features * * - Expands tag groups into individual tag definitions * - Generates properly formatted tsdoc.json files * - Handles config persistence based on environment (CI vs local) * - Supports custom tag definitions * * ## Tag Groups * * The builder supports three standardization groups from `\@microsoft/tsdoc`: * - `core`: Essential tags (`\@param`, `\@returns`, `\@remarks`, etc.) * - `extended`: Additional tags (`\@example`, `\@defaultValue`, `\@see`, etc.) * - `discretionary`: Release tags (`\@alpha`, `\@beta`, `\@public`, `\@internal`) * * @example * Build tag configuration from options: * ```typescript * import { TsDocConfigBuilder } from '@savvy-web/rslib-builder'; * * const config = TsDocConfigBuilder.build({ * groups: ['core', 'extended'], * tagDefinitions: [ * { tagName: '@error', syntaxKind: 'inline' }, * ], * }); * ``` * * @example * Write a tsdoc.json file: * ```typescript * import { TsDocConfigBuilder } from '@savvy-web/rslib-builder'; * * const configPath = await TsDocConfigBuilder.writeConfigFile( * { groups: ['core', 'extended', 'discretionary'] }, * process.cwd(), * ); * ``` * * @public */ export declare class TsDocConfigBuilder { /** All available TSDoc tag groups. */ static readonly ALL_GROUPS: TsDocTagGroup[]; /** Maps group names to TSDoc Standardization enum values. */ private static readonly GROUP_TO_STANDARDIZATION; /** * Standard TSDoc tag definitions organized by standardization group. * Lazily computed from `\@microsoft/tsdoc` StandardTags. */ static readonly TAG_GROUPS: Record; /** * Detects if running in a CI environment. * @returns true if CI or GITHUB_ACTIONS environment variable is "true" */ static isCI(): boolean; /** * Gets standard TSDoc tag definitions for a specific group. * Uses StandardTags from `\@microsoft/tsdoc` package. */ static getTagsForGroup(group: TsDocTagGroup): TsDocTagDefinition[]; /** * Determines if the TSDoc config should be persisted to disk. * @param persistConfig - The persistConfig option value * @returns true if the config should be persisted */ static shouldPersist(persistConfig: boolean | PathLike | undefined): boolean; /** * Gets the output path for the tsdoc.json file. * @param persistConfig - The persistConfig option value * @param cwd - The current working directory * @returns The absolute path where tsdoc.json should be written */ static getConfigPath(persistConfig: boolean | PathLike | undefined, cwd: string): string; /** * Builds the complete TSDoc configuration from options. * * @remarks * When all groups are enabled (default), returns `useStandardTags: true` to signal * that the generated config should use `noStandardTags: false` and let TSDoc * automatically load all standard tags. However, `supportForTags` is still populated * because API Extractor requires explicit support declarations for each tag. * * When a subset of groups is specified, returns `useStandardTags: false` to signal * that we must explicitly define which tags to include via `noStandardTags: true`. */ static build(options?: TsDocOptions): { tagDefinitions: TsDocTagDefinition[]; supportForTags: Record; useStandardTags: boolean; }; /** * Builds the tsdoc.json configuration object from options. * @internal */ static buildConfigObject(options?: TsDocOptions): Record; /** * Validates that the existing tsdoc.json matches the expected configuration. * Used in CI environments to ensure the committed config is up-to-date. * * @param options - TSDoc options to build expected configuration * @param configPath - Path to the existing tsdoc.json file * @throws Error if the file doesn't exist, can't be parsed, or doesn't match */ static validateConfigFile(options: TsDocOptions | undefined, configPath: string): Promise; /** * Generates a tsdoc.json file from options. * * @remarks * When all groups are enabled (default), generates a minimal config with * `noStandardTags: false` so TSDoc automatically loads all standard tags. * Only custom tags need to be defined in this case. * * When a subset of groups is specified, generates a config with * `noStandardTags: true` and explicitly defines only the tags from * the enabled groups. * * In CI environments (`CI` or `GITHUB_ACTIONS` env vars set to "true"), * this method validates the existing file instead of writing, throwing * an error if the config is out of date. Set `skipCIValidation` to true * to skip this validation (useful when `persistConfig: false`). * * @param options - TSDoc configuration options * @param outputDir - Directory to write the config file * @param skipCIValidation - Skip CI validation even in CI environments */ static writeConfigFile(options: TsDocOptions | undefined, outputDir: string, skipCIValidation?: boolean): Promise; /** Converts TSDocTagSyntaxKind enum to string format. */ private static syntaxKindToString; } /** * Error behavior for TSDoc lint errors. * * @remarks * - `"warn"`: Log warnings but continue the build * - `"error"`: Log errors but continue the build * - `"throw"`: Fail the build with an error * * @public */ export declare type TsDocLintErrorBehavior = "warn" | "error" | "throw"; /** * Options for TSDoc lint validation (subset of TsDocLintPluginOptions). * TSDoc configuration is inherited from the parent TsDocOptions. * * @public */ export declare interface TsDocLintOptions { /** * Override automatic file discovery with explicit file paths or glob patterns. * * @remarks * By default, uses import graph analysis to discover files from your package's exports. * This ensures only public API files are linted. * * @example * ```typescript * lint: { * include: ["src/**\/*.ts", "!**\/*.test.ts"], * } * ``` */ include?: string[]; /** * How to handle TSDoc lint errors. * - `"warn"`: Log warnings but continue the build * - `"error"`: Log errors but continue the build * - `"throw"`: Fail the build with an error * * @defaultValue `"throw"` in CI environments, `"error"` locally */ onError?: TsDocLintErrorBehavior; /** * Persist tsdoc.json to disk for tool integration (ESLint, IDEs). * - `true`: Write to project root as "tsdoc.json" (or validate in CI) * - `PathLike`: Write to specified path (or validate in CI) * - `false`: Clean up after linting (not recommended) * * @remarks * In CI environments (`CI` or `GITHUB_ACTIONS` env vars set to "true"), * the config file is validated instead of written. If the existing file * doesn't match the expected configuration, the build fails with an error * instructing the developer to regenerate the file locally. * * @defaultValue `true` */ persistConfig?: boolean | PathLike; } /** * Creates a plugin to validate TSDoc comments before build using ESLint with eslint-plugin-tsdoc. * * @remarks * This plugin runs TSDoc validation during the `onBeforeBuild` hook, ensuring that * documentation errors are caught before compilation begins. It generates a virtual * `tsdoc.json` configuration file that can be persisted for IDE and tool integration. * * ## Features * * - Programmatic ESLint execution with `eslint-plugin-tsdoc` * - Configurable error handling (warn, error, throw) * - Automatic CI detection for stricter defaults * - Optional tsdoc.json persistence for tool integration * - Automatic file discovery via import graph analysis * - Customizable file patterns when needed * * ## Error Handling * * | Environment | Default Behavior | On Lint Errors | * |-------------|------------------|----------------| * | Local | `"error"` | Log and continue | * | CI | `"throw"` | Fail the build | * * ## Dependencies * * This plugin uses ESLint programmatically with the following packages: * - `eslint` * - `@typescript-eslint/parser` * - `eslint-plugin-tsdoc` * * @param options - Plugin configuration options * @returns An Rsbuild plugin that validates TSDoc comments before the build * * @example * ```typescript * import { TsDocLintPlugin } from '@savvy-web/rslib-builder'; * * export default defineConfig({ * plugins: [ * TsDocLintPlugin({ * onError: 'throw', * persistConfig: true, * }), * ], * }); * ``` * * @public */ export declare const TsDocLintPlugin: (options?: TsDocLintPluginOptions) => RsbuildPlugin; /** * Options for the TSDoc lint plugin. * * @remarks * This plugin validates TSDoc comments in your source files before the build * starts using ESLint with `eslint-plugin-tsdoc`. It helps catch documentation * errors early in the development cycle. * * @example * Enable with defaults (throws in CI, errors locally): * ```typescript * import { TsDocLintPlugin } from '@savvy-web/rslib-builder'; * * export default defineConfig({ * plugins: [TsDocLintPlugin()], * }); * ``` * * @example * Custom configuration: * ```typescript * import { TsDocLintPlugin } from '@savvy-web/rslib-builder'; * * export default defineConfig({ * plugins: [ * TsDocLintPlugin({ * tsdoc: { * tagDefinitions: [{ tagName: '@error', syntaxKind: 'block' }], * }, * onError: 'throw', * persistConfig: true, * }), * ], * }); * ``` * * @public */ export declare interface TsDocLintPluginOptions { /** * Whether to enable TSDoc linting. * @defaultValue true */ enabled?: boolean; /** * TSDoc configuration for custom tag definitions. * Uses the same options as the DtsPlugin's apiModel.tsdoc option. * * @remarks * By default, all standard tag groups (core, extended, discretionary) are * enabled. Custom tags defined in `tagDefinitions` are automatically * supported. */ tsdoc?: TsDocOptions; /** * Override automatic file discovery with explicit file paths or glob patterns. * * @remarks * By default, TsDocLintPlugin uses import graph analysis to discover files * from your package's exports. This ensures only public API files are linted. * * Use this option only when you need to lint specific files that aren't * part of the export graph, or to override the automatic discovery. * * When specified as glob patterns, test files and `__test__` directories * are still excluded unless explicitly included. * * @example * ```typescript * // Explicit patterns override automatic discovery * TsDocLintPlugin({ * include: ["src/**\/*.ts", "!**\/*.test.ts"], * }) * ``` */ include?: string[]; /** * How to handle TSDoc lint errors. * - `"warn"`: Log warnings but continue the build * - `"error"`: Log errors but continue the build * - `"throw"`: Fail the build with an error * * @defaultValue `"throw"` in CI environments, `"error"` locally */ onError?: TsDocLintErrorBehavior; /** * Persist tsdoc.json to disk for tool integration (ESLint, IDEs). * - `true`: Write to project root as "tsdoc.json" (or validate in CI) * - `PathLike`: Write to specified path (or validate in CI) * - `false`: Clean up after linting (not recommended) * * @remarks * In CI environments (`CI` or `GITHUB_ACTIONS` env vars set to "true"), * the config file is validated instead of written. If the existing file * doesn't match the expected configuration, the build fails with an error * instructing the developer to regenerate the file locally. * * @defaultValue `true` */ persistConfig?: boolean | PathLike; /** * Whether to run lint per entry point individually with per-entry logging. * * @remarks * When enabled, each entry point is linted separately and results are * logged per entry for better visibility in bundleless mode. * * @defaultValue false */ perEntry?: boolean; } /** * Options for tsdoc-metadata.json generation. * @public */ export declare interface TsDocMetadataOptions { /** * Whether to generate tsdoc-metadata.json. * @defaultValue true (when apiModel is enabled) */ enabled?: boolean; /** * Custom filename for the TSDoc metadata file. * @defaultValue "tsdoc-metadata.json" */ filename?: string; } /** * TSDoc configuration options for API Extractor. * @remarks * Provides ergonomic defaults - standard tags are auto-enabled via `groups`, * custom tags are auto-supported, and `supportForTags` is only needed to * disable specific tags. * * **Config optimization:** When all groups are enabled (default), the generated * `tsdoc.json` uses `noStandardTags: false` to let TSDoc automatically load * all standard tags, producing a minimal config file. When a subset of groups * is specified, `noStandardTags: true` is used and only the enabled groups' * tags are explicitly defined. * * @public */ export declare interface TsDocOptions { /** * TSDoc tag groups to enable. Each group includes predefined standard tags * from the official `\@microsoft/tsdoc` package. * - "core": Essential TSDoc tags (\@param, \@returns, \@remarks, \@deprecated, etc.) * - "extended": Additional tags (\@example, \@defaultValue, \@see, \@throws, etc.) * - "discretionary": Release stage tags (\@alpha, \@beta, \@public, \@internal) * * @remarks * When all groups are enabled (the default), the generated config uses * `noStandardTags: false` and TSDoc loads standard tags automatically. * When a subset is specified, `noStandardTags: true` is used and only * the tags from enabled groups are defined. * * @defaultValue ["core", "extended", "discretionary"] */ groups?: TsDocTagGroup[]; /** * Custom TSDoc tag definitions beyond the standard groups. * These are automatically added to supportForTags (no need to declare twice). * * @example * ```typescript * import type { TsDocTagDefinition } from '@savvy-web/rslib-builder'; * * const tagDefinitions: TsDocTagDefinition[] = [ * { tagName: '@error', syntaxKind: 'inline' }, * { tagName: '@category', syntaxKind: 'block', allowMultiple: false }, * ]; * ``` */ tagDefinitions?: TsDocTagDefinition[]; /** * Override support for specific tags. Only needed to DISABLE tags. * Tags from enabled groups and custom tagDefinitions are auto-supported. * * @example * Disable \@beta even though "extended" group is enabled: * ```typescript * const supportForTags: Record = { '@beta': false }; * ``` */ supportForTags?: Record; /** * How to handle TSDoc validation warnings from API Extractor. * - `"log"`: Show warnings in the console but continue the build * - `"fail"`: Show warnings and fail the build if any are found * - `"none"`: Suppress TSDoc warnings entirely * * @remarks * TSDoc warnings include unknown tags, malformed syntax, and other * documentation issues detected by API Extractor during processing. * * **Important:** This setting only applies to first-party warnings (from your * project's source code). Third-party warnings from dependencies in * `node_modules/` are always logged but never fail the build, since they * cannot be fixed by the consuming project. * * @defaultValue `"fail"` in CI environments (`CI` or `GITHUB_ACTIONS` env vars), * `"log"` otherwise */ warnings?: "log" | "fail" | "none"; /** * TSDoc lint validation options. * Validates TSDoc comments before the build starts using ESLint. * * @remarks * Lint validation is **enabled by default**. Set to `false` to disable. * When enabled, it uses the parent TSDoc configuration (tagDefinitions, groups, etc.) * for validation rules. * * @defaultValue true * * @example * Disable lint validation: * ```typescript * apiModel: { * tsdoc: { * lint: false, * }, * } * ``` * * @example * Customize lint behavior: * ```typescript * apiModel: { * tsdoc: { * tagDefinitions: [{ tagName: '@error', syntaxKind: 'inline' }], * lint: { * onError: 'throw', * include: ['src/**\/*.ts'], * }, * }, * } * ``` */ lint?: TsDocLintOptions | boolean; } /** * TSDoc tag definition for custom documentation tags. * @public */ export declare interface TsDocTagDefinition { /** The tag name including the at-sign prefix (e.g., `\@error`, `\@category`) */ tagName: string; /** How the tag is parsed: "block" | "inline" | "modifier" */ syntaxKind: "block" | "inline" | "modifier"; /** Whether the tag can appear multiple times on a declaration */ allowMultiple?: boolean; } /** * TSDoc standardization groups for predefined tag sets. * * @remarks * These groups correspond to the TSDoc specification's standardization levels * as defined in `\@microsoft/tsdoc`. Each group contains a set of related tags: * * - `"core"`: Essential tags for basic documentation * (`\@param`, `\@returns`, `\@remarks`, `\@deprecated`, `\@privateRemarks`, etc.) * * - `"extended"`: Additional tags for richer documentation * (`\@example`, `\@defaultValue`, `\@see`, `\@throws`, `\@typeParam`, etc.) * * - `"discretionary"`: Release stage and visibility modifiers * (`\@alpha`, `\@beta`, `\@public`, `\@internal`, `\@experimental`) * * @example * ```typescript * import type { TsDocTagGroup } from '@savvy-web/rslib-builder'; * * const groups: TsDocTagGroup[] = ['core', 'extended']; * ``` * * @public */ export declare type TsDocTagGroup = "core" | "extended" | "discretionary"; /** * Configuration for a virtual entry point. * * @remarks * Virtual entries are bundled entry points that bypass type generation * and package.json exports while still being included in the published package. * * @example * ```typescript * const config: VirtualEntryConfig = { * source: "./src/pnpmfile.ts", * format: "cjs", * }; * ``` * * @public */ export declare interface VirtualEntryConfig { /** * Path to source file (relative to package root). */ source: string; /** * Output format for this entry. * If not specified, inherits from the primary format * (first element when `format` is an array, or the single format value). */ format?: LibraryFormat; } /** * Plugin to handle virtual entry points in RSlib builds. * * @remarks * Virtual entries are special entry points that: * - Are bundled like regular entries * - Do NOT generate TypeScript declarations (.d.ts files) * - Are NOT added to package.json exports * - ARE added to package.json files array for publishing * * This plugin: * 1. Exposes the virtual entry names for DtsPlugin to skip type generation * 2. Adds virtual entry outputs to the files array in the additional stage * * @example * ```typescript * import { VirtualEntryPlugin } from '@savvy-web/rslib-builder'; * * const plugin = VirtualEntryPlugin({ * virtualEntryNames: new Set(['pnpmfile']), * }); * ``` * * @public */ export declare const VirtualEntryPlugin: (options: VirtualEntryPluginOptions) => RsbuildPlugin; /** * Options for the VirtualEntryPlugin. * * @remarks * Virtual entries are used for special files that need bundling but should not * generate type declarations or appear in package.json exports. Common use cases * include pnpmfile.cjs or other configuration files. * * @public */ export declare interface VirtualEntryPluginOptions { /** * Set of virtual entry names (without file extensions). * * @remarks * These names are exposed to DtsPlugin to skip type generation. * For example, if `virtualEntryNames` contains `"pnpmfile"`, the * entry `pnpmfile.cjs` will be bundled but no `pnpmfile.d.ts` will be generated. */ virtualEntryNames: Set; } /** * A declarative rule for suppressing a specific API Extractor warning message. * * @remarks * Both `messageId` and `pattern` must match when both are specified (AND logic). * Specify at least one field per rule — a rule with neither field matches all messages. * * `pattern` is first tried as a RegExp. If the string is not a valid regular * expression it falls back to substring matching. * * @public */ export declare interface WarningSuppressionRule { /** * Exact match against the message's `messageId` property * (e.g., `"ae-forgotten-export"`, `"tsdoc-param-tag-missing-hyphen"`). */ messageId?: string; /** * Pattern matched against the message's `text` property. * Tried as a RegExp first; falls back to case-sensitive substring match. */ pattern?: string; } export { }