@savvy-web/rslib-builder 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +15 -92
  2. package/index.d.ts +224 -4
  3. package/index.js +281 -98
  4. package/package.json +6 -3
package/README.md CHANGED
@@ -8,122 +8,45 @@ Build modern ESM Node.js libraries with minimal configuration. Handles
8
8
  TypeScript declarations, package.json transformations, and PNPM workspace
9
9
  resolution automatically.
10
10
 
11
- Building TypeScript packages for npm involves repetitive setup: configuring
12
- bundlers, generating declarations, transforming package.json exports, and
13
- resolving workspace references. rslib-builder handles these tasks so you can
14
- focus on your code.
15
-
16
11
  ## Features
17
12
 
18
- - **Zero Config** - Auto-detects entry points from package.json exports
19
- - **Fast Type Generation** - Uses tsgo (native TypeScript) for 10-100x faster
20
- declaration generation
21
- - **Bundled Declarations** - Rolls up TypeScript types via API Extractor for
22
- cleaner public APIs, with multi-entry support for packages with multiple exports
23
- - **Multi-Target Builds** - Separate dev (source maps) and npm (optimized)
24
- outputs
25
- - **PNPM Integration** - Automatically resolves `catalog:` and `workspace:`
26
- references
27
- - **Package.json Transform** - Converts `.ts` exports to `.js`, generates files
28
- array, removes dev-only fields
29
- - **TSDoc Validation** - Pre-build TSDoc validation with automatic public API discovery
30
- - **API Model Generation** - Optional API model and resolved tsconfig output for
31
- documentation tooling
32
- - **Extensible** - Add custom RSlib/Rsbuild plugins for advanced use cases
33
-
34
- ## Prerequisites
35
-
36
- - Node.js 24.x or later
37
- - pnpm 10.x or later
38
- - TypeScript 5.9.x or later
13
+ - **Zero-Config Entry Detection** - Auto-discovers entry points from package.json
14
+ exports, no manual configuration needed
15
+ - **10-100x Faster Types** - Uses tsgo (native TypeScript compiler) with API
16
+ Extractor for bundled, clean public API declarations
17
+ - **Production-Ready Transforms** - Converts `.ts` exports to `.js`, resolves
18
+ PNPM `catalog:` and `workspace:` references, generates files array
19
+ - **Multi-Target Builds** - Separate dev (with source maps) and npm (optimized)
20
+ outputs from a single configuration
21
+ - **TSDoc Validation** - Pre-build documentation validation with automatic
22
+ public API discovery
39
23
 
40
24
  ## Installation
41
25
 
42
26
  ```bash
43
- pnpm add -D @savvy-web/rslib-builder
44
- ```
45
-
46
- ### Peer Dependencies
47
-
48
- Install the required peer dependencies:
49
-
50
- ```bash
51
- pnpm add -D @rslib/core @microsoft/api-extractor @typescript/native-preview
27
+ npm install --save-dev @savvy-web/rslib-builder @rslib/core @microsoft/api-extractor @typescript/native-preview
52
28
  ```
53
29
 
54
30
  ## Quick Start
55
31
 
56
- Extend the provided tsconfig for optimal settings:
57
-
58
- ```jsonc
59
- // tsconfig.json
60
- {
61
- "extends": "@savvy-web/rslib-builder/tsconfig/ecma/lib.json"
62
- }
63
- ```
64
-
65
- Create an `rslib.config.ts` in your project root:
66
-
67
32
  ```typescript
33
+ // rslib.config.ts
68
34
  import { NodeLibraryBuilder } from '@savvy-web/rslib-builder';
69
35
 
70
36
  export default NodeLibraryBuilder.create({
71
37
  externals: ['@rslib/core'],
72
- transform({ pkg, target }) {
73
- if (target === 'npm') {
74
- delete pkg.devDependencies;
75
- }
76
- return pkg;
77
- },
78
38
  });
79
39
  ```
80
40
 
81
- Add scripts to your `package.json`:
82
-
83
- ```json
84
- {
85
- "scripts": {
86
- "build": "rslib build --env-mode dev",
87
- "build:npm": "rslib build --env-mode npm"
88
- }
89
- }
90
- ```
41
+ Build with `rslib build --env-mode dev` or `rslib build --env-mode npm`.
91
42
 
92
43
  ## Documentation
93
44
 
94
- For detailed documentation, see the [docs/](./docs/) directory:
95
-
96
- - [Getting Started](./docs/guides/getting-started.md) - Installation and setup
97
- - [Configuration](./docs/guides/configuration.md) - All options explained
98
- - [Plugin System](./docs/guides/plugins.md) - Built-in and custom plugins
99
- - [Architecture](./docs/architecture/overview.md) - How it works internally
100
- - [Troubleshooting](./docs/troubleshooting.md) - Common issues and solutions
101
-
102
- ## Example
103
-
104
- This package builds itself using its own `NodeLibraryBuilder`. See
105
- [`rslib.config.ts`](./rslib.config.ts) for a production example.
106
-
107
- ## Support
108
-
109
- This software is provided as-is under the MIT License with no warranty or
110
- support guarantees. While we welcome bug reports and feature requests via
111
- GitHub Issues, we cannot guarantee response times or resolution.
112
-
113
- For security vulnerabilities, please see [SECURITY.md](./SECURITY.md).
114
-
115
- ## Links
116
-
117
- - [RSlib Documentation](https://rslib.dev/)
118
- - [Rsbuild Plugin API](https://rsbuild.dev/plugins/dev/core)
119
- - [API Extractor](https://api-extractor.com/)
120
- - [PNPM Workspace](https://pnpm.io/workspaces)
121
- - [PNPM Catalogs](https://pnpm.io/catalogs)
45
+ For configuration options, API reference, and advanced usage, see [docs](./docs/).
122
46
 
123
47
  ## Contributing
124
48
 
125
- Contributions welcome! See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup
126
- and guidelines.
49
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for development setup and guidelines.
127
50
 
128
51
  ## License
129
52
 
package/index.d.ts CHANGED
@@ -395,6 +395,13 @@ export declare interface DtsPluginOptions {
395
395
  * Used to generate the correct temp tsconfig when tsconfigPath is not provided.
396
396
  */
397
397
  buildTarget?: "dev" | "npm";
398
+ /**
399
+ * Output format for the library.
400
+ * Affects the resolved tsconfig.json module settings:
401
+ * - `"esm"`: Uses ESNext module and Bundler resolution (default)
402
+ * - `"cjs"`: Uses CommonJS module and Node10 resolution
403
+ */
404
+ format?: "esm" | "cjs";
398
405
  /**
399
406
  * Options for API model generation.
400
407
  * When enabled, generates an `<unscopedPackageName>.api.json` file in the dist directory.
@@ -1055,6 +1062,17 @@ export declare type JsonPrimitive = string | number | boolean | null;
1055
1062
  */
1056
1063
  export declare type JsonValue = JsonPrimitive | JsonObject | JsonArray;
1057
1064
 
1065
+ /**
1066
+ * Output format for library builds.
1067
+ *
1068
+ * @remarks
1069
+ * - `"esm"` - ES Modules format (sets `type: "module"` in package.json)
1070
+ * - `"cjs"` - CommonJS format (sets `type: "commonjs"` in package.json)
1071
+ *
1072
+ * @public
1073
+ */
1074
+ export declare type LibraryFormat = "esm" | "cjs";
1075
+
1058
1076
  /**
1059
1077
  * Allows creating a union type by combining primitive types and literal types
1060
1078
  * without sacrificing auto-completion in IDEs for the literal type part of the union.
@@ -1137,6 +1155,7 @@ export declare class NodeLibraryBuilder {
1137
1155
  * Arrays are deep-copied to prevent mutation of this object.
1138
1156
  */
1139
1157
  static readonly DEFAULT_OPTIONS: {
1158
+ format: "esm";
1140
1159
  plugins: never[];
1141
1160
  define: {};
1142
1161
  copyPatterns: never[];
@@ -1179,12 +1198,86 @@ export declare class NodeLibraryBuilder {
1179
1198
  * @returns Promise resolving to the RSLib configuration
1180
1199
  */
1181
1200
  static createSingleTarget(target: BuildTarget, opts: NodeLibraryBuilderOptions): Promise<RslibConfig>;
1201
+ /**
1202
+ * Checks if the current package has exports defined in package.json.
1203
+ * @internal
1204
+ */
1205
+ private static packageHasExports;
1182
1206
  }
1183
1207
 
1184
1208
  /**
1209
+ * Configuration options for the NodeLibraryBuilder.
1210
+ *
1211
+ * @remarks
1212
+ * All options are optional with sensible defaults. The most commonly customized options are:
1213
+ * - `externals`: For dependencies that should remain external
1214
+ * - `dtsBundledPackages`: For inlining type definitions
1215
+ * - `transform`: For custom package.json modifications
1216
+ *
1217
+ * @example
1218
+ * ```typescript
1219
+ * import type { NodeLibraryBuilderOptions } from '@savvy-web/rslib-builder';
1220
+ *
1221
+ * const options: NodeLibraryBuilderOptions = {
1222
+ * externals: ['@rslib/core'],
1223
+ * dtsBundledPackages: ['picocolors'],
1224
+ * apiModel: {
1225
+ * localPaths: ['../docs/packages/my-package'],
1226
+ * },
1227
+ * };
1228
+ * ```
1229
+ *
1185
1230
  * @public
1186
1231
  */
1187
1232
  export declare interface NodeLibraryBuilderOptions {
1233
+ /**
1234
+ * Output format for main entry points.
1235
+ * Also determines package.json `type` field:
1236
+ * - `"esm"` → `"type": "module"`
1237
+ * - `"cjs"` → `"type": "commonjs"`
1238
+ *
1239
+ * @defaultValue `"esm"`
1240
+ */
1241
+ format?: LibraryFormat;
1242
+ /**
1243
+ * Additional entry points bundled with custom output names.
1244
+ * These entries bypass type generation and package.json exports
1245
+ * but are included in the published package.
1246
+ *
1247
+ * @remarks
1248
+ * Virtual entries are useful for special files like pnpm config files
1249
+ * that need to be bundled but don't require type declarations or
1250
+ * exposure as package exports.
1251
+ *
1252
+ * A module may have ONLY virtualEntries with no regular entry points.
1253
+ *
1254
+ * @example
1255
+ * Mixed: regular entries + virtual entries
1256
+ * ```typescript
1257
+ * NodeLibraryBuilder.create({
1258
+ * virtualEntries: {
1259
+ * "pnpmfile.cjs": {
1260
+ * source: "./src/pnpmfile.ts",
1261
+ * format: "cjs",
1262
+ * },
1263
+ * },
1264
+ * })
1265
+ * ```
1266
+ *
1267
+ * @example
1268
+ * Virtual-only: no regular entry points
1269
+ * ```typescript
1270
+ * NodeLibraryBuilder.create({
1271
+ * format: "cjs",
1272
+ * virtualEntries: {
1273
+ * "pnpmfile.cjs": {
1274
+ * source: "./src/pnpmfile.ts",
1275
+ * },
1276
+ * },
1277
+ * })
1278
+ * ```
1279
+ */
1280
+ virtualEntries?: Record<string, VirtualEntryConfig>;
1188
1281
  /** Override entry points (optional - will auto-detect from package.json) */
1189
1282
  entry?: Record<string, string | string[]>;
1190
1283
  /**
@@ -1215,11 +1308,46 @@ export declare interface NodeLibraryBuilderOptions {
1215
1308
  * ```
1216
1309
  */
1217
1310
  exportsAsIndexes?: boolean;
1311
+ /**
1312
+ * Patterns for files to copy to the output directory.
1313
+ *
1314
+ * @remarks
1315
+ * Supports both string paths and detailed configuration objects.
1316
+ * A `public/` directory in the project root is automatically added if it exists.
1317
+ *
1318
+ * @defaultValue `[]`
1319
+ */
1218
1320
  copyPatterns: (string | CopyPatternConfig)[];
1219
- /** Additional plugins */
1321
+ /**
1322
+ * Additional Rsbuild plugins to include in the build.
1323
+ *
1324
+ * @remarks
1325
+ * These plugins run after the built-in plugins (AutoEntryPlugin, DtsPlugin, etc.).
1326
+ *
1327
+ * @defaultValue `[]`
1328
+ */
1220
1329
  plugins: RsbuildPlugin[];
1330
+ /**
1331
+ * Compile-time constants for code replacement.
1332
+ *
1333
+ * @remarks
1334
+ * Values are stringified and replaced in the source code during bundling.
1335
+ * The `process.env.__PACKAGE_VERSION__` constant is automatically defined.
1336
+ *
1337
+ * @see {@link https://rsbuild.dev/config/source/define | Rsbuild define documentation}
1338
+ *
1339
+ * @defaultValue `{}`
1340
+ */
1221
1341
  define: SourceConfig["define"];
1222
- /** Path to tsconfig for build (default: ./tsconfig.build.json) */
1342
+ /**
1343
+ * Path to the TypeScript configuration file for the build.
1344
+ *
1345
+ * @remarks
1346
+ * If not specified, the plugin searches for `tsconfig.json` in the project root.
1347
+ * A temporary tsconfig is generated for declaration generation regardless of this setting.
1348
+ *
1349
+ * @defaultValue `undefined` (auto-detected)
1350
+ */
1223
1351
  tsconfigPath: string | undefined;
1224
1352
  /** Build targets to include (default: ["dev", "npm"]) */
1225
1353
  targets?: BuildTarget[];
@@ -1800,7 +1928,6 @@ export declare type PackageJson = JsonObject & PackageJson.NodeJsStandard & Pack
1800
1928
  *
1801
1929
  * - Consumes `entrypoints` map from AutoEntryPlugin
1802
1930
  * - Consumes `exportToOutputMap` for exportsAsIndexes mode
1803
- * - Exposes `files-cache` for asset caching
1804
1931
  * - Consumes `use-rollup-types` flag from DtsPlugin
1805
1932
  *
1806
1933
  * @param options - Plugin configuration options
@@ -1848,6 +1975,15 @@ export declare const PackageJsonTransformPlugin: (options?: PackageJsonTransform
1848
1975
  * @public
1849
1976
  */
1850
1977
  export declare interface PackageJsonTransformPluginOptions {
1978
+ /**
1979
+ * Output format for the library.
1980
+ * Determines the package.json `type` field:
1981
+ * - `"esm"` → `"type": "module"`
1982
+ * - `"cjs"` → `"type": "commonjs"`
1983
+ *
1984
+ * @defaultValue `"esm"`
1985
+ */
1986
+ format?: LibraryFormat;
1851
1987
  /**
1852
1988
  * Override the package name in the output package.json.
1853
1989
  *
@@ -2332,8 +2468,14 @@ export declare class TsconfigResolver {
2332
2468
  * - Excludes file selection (include, exclude, files, references)
2333
2469
  * - Adds $schema for IDE support
2334
2470
  *
2471
+ * When `format` is `"cjs"`, the resolved config uses CommonJS-compatible settings:
2472
+ * - `module: "commonjs"`
2473
+ * - `moduleResolution: "node10"`
2474
+ * - `esModuleInterop: true`
2475
+ *
2335
2476
  * @param parsed - The parsed TypeScript configuration from `parseJsonConfigFileContent`
2336
2477
  * @param _rootDir - Reserved for future path normalization (currently unused)
2478
+ * @param format - Optional output format to adjust module settings (`"esm"` or `"cjs"`)
2337
2479
  * @returns A JSON-serializable tsconfig object
2338
2480
  * @throws {@link TsconfigResolverError} If resolution fails for any option
2339
2481
  *
@@ -2353,7 +2495,7 @@ export declare class TsconfigResolver {
2353
2495
  *
2354
2496
  * @public
2355
2497
  */
2356
- resolve(parsed: ParsedCommandLine, _rootDir: string): ResolvedTsconfig;
2498
+ resolve(parsed: ParsedCommandLine, _rootDir: string, format?: LibraryFormat): ResolvedTsconfig;
2357
2499
  /**
2358
2500
  * Adds converted enum options to the compiler options object.
2359
2501
  * @internal
@@ -2933,4 +3075,82 @@ export declare class TsconfigResolver {
2933
3075
  */
2934
3076
  export declare type TsDocTagGroup = "core" | "extended" | "discretionary";
2935
3077
 
3078
+ /**
3079
+ * Configuration for a virtual entry point.
3080
+ *
3081
+ * @remarks
3082
+ * Virtual entries are bundled entry points that bypass type generation
3083
+ * and package.json exports while still being included in the published package.
3084
+ *
3085
+ * @example
3086
+ * ```typescript
3087
+ * const config: VirtualEntryConfig = {
3088
+ * source: "./src/pnpmfile.ts",
3089
+ * format: "cjs",
3090
+ * };
3091
+ * ```
3092
+ *
3093
+ * @public
3094
+ */
3095
+ export declare interface VirtualEntryConfig {
3096
+ /**
3097
+ * Path to source file (relative to package root).
3098
+ */
3099
+ source: string;
3100
+ /**
3101
+ * Output format for this entry.
3102
+ * If not specified, inherits from top-level `format` option.
3103
+ */
3104
+ format?: LibraryFormat;
3105
+ }
3106
+
3107
+ /**
3108
+ * Plugin to handle virtual entry points in RSlib builds.
3109
+ *
3110
+ * @remarks
3111
+ * Virtual entries are special entry points that:
3112
+ * - Are bundled like regular entries
3113
+ * - Do NOT generate TypeScript declarations (.d.ts files)
3114
+ * - Are NOT added to package.json exports
3115
+ * - ARE added to package.json files array for publishing
3116
+ *
3117
+ * This plugin:
3118
+ * 1. Exposes the virtual entry names for DtsPlugin to skip type generation
3119
+ * 2. Adds virtual entry outputs to the files array in the additional stage
3120
+ *
3121
+ * @example
3122
+ * ```typescript
3123
+ * import { VirtualEntryPlugin } from '@savvy-web/rslib-builder';
3124
+ *
3125
+ * const plugin = VirtualEntryPlugin({
3126
+ * virtualEntryNames: new Set(['pnpmfile']),
3127
+ * });
3128
+ * ```
3129
+ *
3130
+ * @public
3131
+ */
3132
+ export declare const VirtualEntryPlugin: (options: VirtualEntryPluginOptions) => RsbuildPlugin;
3133
+
3134
+ /**
3135
+ * Options for the VirtualEntryPlugin.
3136
+ *
3137
+ * @remarks
3138
+ * Virtual entries are used for special files that need bundling but should not
3139
+ * generate type declarations or appear in package.json exports. Common use cases
3140
+ * include pnpmfile.cjs or other configuration files.
3141
+ *
3142
+ * @public
3143
+ */
3144
+ export declare interface VirtualEntryPluginOptions {
3145
+ /**
3146
+ * Set of virtual entry names (without file extensions).
3147
+ *
3148
+ * @remarks
3149
+ * These names are exposed to DtsPlugin to skip type generation.
3150
+ * For example, if `virtualEntryNames` contains `"pnpmfile"`, the
3151
+ * entry `pnpmfile.cjs` will be bundled but no `pnpmfile.d.ts` will be generated.
3152
+ */
3153
+ virtualEntryNames: Set<string>;
3154
+ }
3155
+
2936
3156
  export { }
package/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  /*! For license information please see index.js.LICENSE.txt */
2
- import { constants, existsSync, writeFileSync } from "node:fs";
2
+ import { constants, existsSync, readFileSync, writeFileSync } from "node:fs";
3
3
  import { dirname, isAbsolute, join, normalize, relative, resolve as external_node_path_resolve } from "node:path";
4
4
  import { defineConfig } from "@rslib/core";
5
5
  import { access, copyFile, mkdir, readFile, readdir, rm, stat, unlink as promises_unlink, writeFile } from "node:fs/promises";
6
6
  import { logger as core_logger } from "@rsbuild/core";
7
7
  import picocolors from "picocolors";
8
- import { getWorkspaceRoot } from "workspace-tools";
8
+ import { getCatalogs, getWorkspaceManagerAndRoot, getWorkspaceManagerRoot } from "workspace-tools";
9
9
  import { spawn } from "node:child_process";
10
10
  import { StandardTags, Standardization, TSDocTagSyntaxKind } from "@microsoft/tsdoc";
11
11
  import deep_equal from "deep-equal";
@@ -13,8 +13,11 @@ import typescript, { ImportsNotUsedAsValues, JsxEmit, ModuleDetectionKind, Modul
13
13
  import { createRequire } from "node:module";
14
14
  import { inspect } from "node:util";
15
15
  import sort_package_json from "sort-package-json";
16
+ import { getCatalogsFromWorkspaceManifest } from "@pnpm/catalogs.config";
17
+ import { parseCatalogProtocol } from "@pnpm/catalogs.protocol-parser";
16
18
  import { createExportableManifest } from "@pnpm/exportable-manifest";
17
- import { parse } from "yaml";
19
+ import { readWantedLockfile } from "@pnpm/lockfile.fs";
20
+ import { readWorkspaceManifest } from "@pnpm/workspace.read-manifest";
18
21
  const { cyan: cyan, dim: dim, bold: bold } = picocolors;
19
22
  function formatTime(ms) {
20
23
  if (ms < 1000) return `${ms}ms`;
@@ -169,7 +172,7 @@ function getApiExtractorPath() {
169
172
  const cwd = process.cwd();
170
173
  const localApiExtractor = join(cwd, "node_modules", "@microsoft", "api-extractor");
171
174
  if (existsSync(localApiExtractor)) return localApiExtractor;
172
- const workspaceRoot = getWorkspaceRoot(cwd);
175
+ const workspaceRoot = getWorkspaceManagerRoot(cwd);
173
176
  if (workspaceRoot) {
174
177
  const workspaceApiExtractor = join(workspaceRoot, "node_modules", "@microsoft", "api-extractor");
175
178
  if (existsSync(workspaceApiExtractor)) return workspaceApiExtractor;
@@ -310,21 +313,6 @@ class TSConfigFile {
310
313
  }
311
314
  }
312
315
  class LibraryTSConfigFile extends TSConfigFile {
313
- bundle(target) {
314
- const config = transformStringsDeep(this.config, (str)=>str.replace("${configDir}", "../../../../../.."));
315
- const include = config.include?.filter((pattern)=>pattern.includes("/src/") || pattern.includes("/types/") || pattern.includes("/public/") || pattern.includes("package.json")).filter((pattern)=>!pattern.includes(".tsx") && !pattern.includes(".cts"));
316
- return {
317
- ...config,
318
- compilerOptions: {
319
- ...config.compilerOptions,
320
- outDir: "dist",
321
- tsBuildInfoFile: `${process.cwd()}/dist/.tsbuildinfo.${target}.bundle`
322
- },
323
- ...void 0 !== include && include.length > 0 ? {
324
- include
325
- } : {}
326
- };
327
- }
328
316
  writeBundleTempConfig(_target) {
329
317
  const cwd = process.cwd();
330
318
  const baseConfig = this.config;
@@ -679,7 +667,7 @@ class TsconfigResolver {
679
667
  const filename = lib.includes("/") || lib.includes("\\") ? lib.split(/[\\/]/).pop() ?? lib : lib;
680
668
  return filename.replace(/^lib\./, "").replace(/\.d\.ts$/, "");
681
669
  }
682
- resolve(parsed, _rootDir) {
670
+ resolve(parsed, _rootDir, format) {
683
671
  const opts = parsed.options;
684
672
  const compilerOptions = {};
685
673
  this.addEnumOptions(compilerOptions, opts);
@@ -688,6 +676,11 @@ class TsconfigResolver {
688
676
  compilerOptions.noEmit = true;
689
677
  this.addPreservedBooleanOptions(compilerOptions, opts);
690
678
  this.addPreservedStringOptions(compilerOptions, opts);
679
+ if ("cjs" === format) {
680
+ compilerOptions.module = "commonjs";
681
+ compilerOptions.moduleResolution = "node10";
682
+ compilerOptions.esModuleInterop = true;
683
+ }
691
684
  return {
692
685
  $schema: TSCONFIG_SCHEMA_URL,
693
686
  compilerOptions
@@ -836,7 +829,7 @@ function getTsgoBinPath() {
836
829
  const cwd = process.cwd();
837
830
  const localTsgoBin = join(cwd, "node_modules", ".bin", "tsgo");
838
831
  if (existsSync(localTsgoBin)) return localTsgoBin;
839
- const workspaceRoot = getWorkspaceRoot(cwd);
832
+ const workspaceRoot = getWorkspaceManagerRoot(cwd);
840
833
  if (workspaceRoot) {
841
834
  const workspaceTsgoBin = join(workspaceRoot, "node_modules", ".bin", "tsgo");
842
835
  if (existsSync(workspaceTsgoBin)) return workspaceTsgoBin;
@@ -1240,8 +1233,13 @@ function runTsgo(options) {
1240
1233
  const extractor = new EntryExtractor();
1241
1234
  const { entries } = extractor.extract(packageJson);
1242
1235
  const entryPoints = new Map();
1236
+ const virtualEntryNames = api.useExposed("virtual-entry-names");
1243
1237
  for (const [entryName, sourcePath] of Object.entries(entries)){
1244
1238
  if (entryName.startsWith("bin/")) continue;
1239
+ if (virtualEntryNames?.has(entryName)) {
1240
+ log.global.info(`Skipping type generation for virtual entry: ${entryName}`);
1241
+ continue;
1242
+ }
1245
1243
  if (!sourcePath.match(/\.(ts|mts|cts|tsx)$/)) continue;
1246
1244
  if (sourcePath.includes(".test.") || sourcePath.includes("__test__")) continue;
1247
1245
  const resolvedSourcePath = sourcePath.startsWith(".") ? join(cwd, sourcePath) : sourcePath;
@@ -1332,7 +1330,7 @@ function runTsgo(options) {
1332
1330
  }
1333
1331
  if (apiModelPath && state.parsedConfig && state.tsconfigPath) {
1334
1332
  const resolver = new TsconfigResolver();
1335
- const resolvedTsconfig = resolver.resolve(state.parsedConfig, cwd);
1333
+ const resolvedTsconfig = resolver.resolve(state.parsedConfig, cwd, options.format);
1336
1334
  const tsconfigContent = `${JSON.stringify(resolvedTsconfig, null, "\t")}\n`;
1337
1335
  const tsconfigSource = new context.sources.OriginalSource(tsconfigContent, "tsconfig.json");
1338
1336
  context.compilation.emitAsset("tsconfig.json", tsconfigSource);
@@ -1566,75 +1564,76 @@ const FilesArrayPlugin = (options)=>({
1566
1564
  });
1567
1565
  const CATALOG_PREFIX = "catalog:";
1568
1566
  const WORKSPACE_PREFIX = "workspace:";
1569
- class PnpmCatalog {
1570
- catalogCache = null;
1571
- catalogCacheMtime = null;
1572
- cachedWorkspaceRoot = null;
1567
+ class WorkspaceCatalog {
1568
+ catalogsCache = null;
1569
+ cachedWorkspaceInfo = null;
1573
1570
  clearCache() {
1574
- this.catalogCache = null;
1575
- this.catalogCacheMtime = null;
1576
- this.cachedWorkspaceRoot = null;
1571
+ this.catalogsCache = null;
1572
+ this.cachedWorkspaceInfo = null;
1577
1573
  }
1578
- async getCatalog() {
1579
- try {
1580
- if (!this.cachedWorkspaceRoot) {
1581
- this.cachedWorkspaceRoot = getWorkspaceRoot(process.cwd());
1582
- if (!this.cachedWorkspaceRoot) throw new Error("Could not find workspace root - ensure you're in a workspace");
1583
- }
1584
- const workspaceFile = external_node_path_resolve(this.cachedWorkspaceRoot, "pnpm-workspace.yaml");
1585
- const stats = await stat(workspaceFile);
1586
- const currentMtime = stats.mtime.getTime();
1587
- if (null !== this.catalogCache && this.catalogCacheMtime === currentMtime) return this.catalogCache;
1588
- const content = await readFile(workspaceFile, "utf-8");
1589
- const workspace = parse(content);
1590
- this.catalogCache = workspace.catalog ?? {};
1591
- this.catalogCacheMtime = currentMtime;
1592
- return this.catalogCache;
1593
- } catch (error) {
1594
- const errorMessage = error instanceof Error ? error.message : String(error);
1574
+ async getCatalogs() {
1575
+ if (null !== this.catalogsCache) return this.catalogsCache;
1576
+ const workspaceInfo = this.getWorkspaceInfo();
1577
+ if (!workspaceInfo) {
1595
1578
  const logger = createEnvLogger("catalog");
1596
- if (errorMessage.includes("ENOENT") && errorMessage.includes("pnpm-workspace.yaml")) {
1597
- logger.error("Failed to read pnpm catalog: workspace configuration not found");
1598
- logger.error(" -> Ensure you're in a pnpm workspace with proper configuration");
1599
- } else if (errorMessage.includes("YAML")) {
1600
- logger.error("Failed to read pnpm catalog: Invalid YAML syntax in workspace configuration");
1601
- logger.error(" -> Check workspace configuration file syntax");
1602
- } else logger.error(`Failed to read pnpm catalog from pnpm-workspace.yaml: ${errorMessage}`);
1579
+ logger.error("Could not find workspace root - ensure you're in a workspace");
1603
1580
  return {};
1604
1581
  }
1582
+ const { manager, root } = workspaceInfo;
1583
+ if ("pnpm" === manager) this.catalogsCache = await this.readPnpmCatalogs(root);
1584
+ else if ("yarn" === manager) this.catalogsCache = this.readYarnCatalogs(root);
1585
+ else this.catalogsCache = {};
1586
+ return this.catalogsCache;
1605
1587
  }
1606
1588
  async resolvePackageJson(packageJson, dir = process.cwd()) {
1607
- const logger = createEnvLogger("pnpm");
1589
+ const workspaceInfo = this.getWorkspaceInfo();
1590
+ const loggerName = workspaceInfo?.manager === "yarn" ? "yarn" : "pnpm";
1591
+ const logger = createEnvLogger(loggerName);
1608
1592
  try {
1609
- const catalog = await this.getCatalog();
1610
- const catalogDeps = this.collectDependencies(packageJson, CATALOG_PREFIX);
1593
+ const catalogs = await this.getCatalogs();
1594
+ const catalogDeps = this.collectCatalogDependencies(packageJson);
1611
1595
  const workspaceDeps = this.collectDependencies(packageJson, WORKSPACE_PREFIX);
1612
1596
  const hasCatalogDeps = catalogDeps.length > 0;
1613
1597
  const hasWorkspaceDeps = workspaceDeps.length > 0;
1614
- if (hasCatalogDeps && 0 === Object.keys(catalog).length) {
1615
- const error = `Package contains ${CATALOG_PREFIX} dependencies but catalog configuration is missing`;
1616
- logger.error(error);
1617
- logger.error(" -> Catalog dependencies found:");
1618
- for (const { field, dependency, version } of catalogDeps)logger.error(` - ${field}.${dependency}: ${version}`);
1619
- throw new Error(error);
1598
+ if (hasCatalogDeps) {
1599
+ const missingCatalogs = this.findMissingCatalogs(catalogDeps, catalogs);
1600
+ if (missingCatalogs.size > 0) {
1601
+ const available = Object.keys(catalogs).join(", ") || "none";
1602
+ const error = `Catalog(s) not found: ${[
1603
+ ...missingCatalogs
1604
+ ].join(", ")}. Available: ${available}`;
1605
+ logger.error(error);
1606
+ logger.error(" -> Catalog dependencies found:");
1607
+ for (const { field, dependency, version, catalogName } of catalogDeps)if (missingCatalogs.has(catalogName)) logger.error(` - ${field}.${dependency}: ${version}`);
1608
+ throw new Error(error);
1609
+ }
1610
+ logger.info(`Resolving ${catalogDeps.length} ${CATALOG_PREFIX} dependencies`);
1620
1611
  }
1621
- if (hasCatalogDeps) logger.info(`Resolving ${catalogDeps.length} ${CATALOG_PREFIX} dependencies`);
1622
1612
  if (hasWorkspaceDeps) logger.info(`Resolving ${workspaceDeps.length} ${WORKSPACE_PREFIX} dependencies`);
1623
1613
  const result = await createExportableManifest(dir, packageJson, {
1624
- catalogs: {
1625
- default: catalog
1626
- }
1614
+ catalogs
1627
1615
  });
1628
- if (hasCatalogDeps || hasWorkspaceDeps) this.logResolvedDependencies(result, [
1629
- ...catalogDeps,
1630
- ...workspaceDeps
1631
- ], logger);
1616
+ if (hasCatalogDeps || hasWorkspaceDeps) {
1617
+ const allDeps = [
1618
+ ...catalogDeps.map((d)=>({
1619
+ field: d.field,
1620
+ dependency: d.dependency,
1621
+ source: "default" === d.catalogName ? "catalog:" : `catalog:${d.catalogName}`
1622
+ })),
1623
+ ...workspaceDeps.map((d)=>({
1624
+ field: d.field,
1625
+ dependency: d.dependency,
1626
+ source: "workspace:"
1627
+ }))
1628
+ ];
1629
+ this.logResolvedDependencies(result, allDeps, logger);
1630
+ }
1632
1631
  this.validateNoUnresolvedReferences(result, logger);
1633
1632
  return result;
1634
1633
  } catch (error) {
1635
1634
  const errorMessage = error instanceof Error ? error.message : String(error);
1636
- if (errorMessage.startsWith("Transformation failed:") || errorMessage.includes(`Package contains ${CATALOG_PREFIX} dependencies`)) throw error;
1637
- logger.error(`Failed to apply pnpm transformations for directory ${dir}: ${errorMessage}`);
1635
+ if (errorMessage.startsWith("Transformation failed:") || errorMessage.startsWith("Catalog(s) not found:")) throw error;
1636
+ logger.error(`Failed to apply transformations for directory ${dir}: ${errorMessage}`);
1638
1637
  if (errorMessage.includes("catalog")) {
1639
1638
  logger.error(` -> Catalog resolution failed - check workspace configuration and ${CATALOG_PREFIX} dependencies`);
1640
1639
  throw new Error("Catalog resolution failed");
@@ -1648,9 +1647,90 @@ class PnpmCatalog {
1648
1647
  throw new Error(`Manifest processing failed: ${errorMessage}`);
1649
1648
  }
1650
1649
  logger.error(" -> Cannot proceed with invalid package.json transformations");
1651
- throw new Error(`PNPM transformation failed: ${errorMessage}`);
1650
+ throw new Error(`Transformation failed: ${errorMessage}`);
1652
1651
  }
1653
1652
  }
1653
+ getWorkspaceInfo() {
1654
+ if (null !== this.cachedWorkspaceInfo) return this.cachedWorkspaceInfo;
1655
+ const info = getWorkspaceManagerAndRoot(process.cwd());
1656
+ this.cachedWorkspaceInfo = info ?? null;
1657
+ return this.cachedWorkspaceInfo;
1658
+ }
1659
+ async readPnpmCatalogs(workspaceRoot) {
1660
+ const lockfileCatalogs = await this.readPnpmLockfileCatalogs(workspaceRoot);
1661
+ if (Object.keys(lockfileCatalogs).length > 0) return lockfileCatalogs;
1662
+ return this.readPnpmWorkspaceCatalogs(workspaceRoot);
1663
+ }
1664
+ async readPnpmLockfileCatalogs(workspaceRoot) {
1665
+ try {
1666
+ const lockfile = await readWantedLockfile(workspaceRoot, {
1667
+ ignoreIncompatible: true
1668
+ });
1669
+ if (!lockfile?.catalogs) return {};
1670
+ return this.convertLockfileCatalogs(lockfile.catalogs);
1671
+ } catch {
1672
+ return {};
1673
+ }
1674
+ }
1675
+ async readPnpmWorkspaceCatalogs(workspaceRoot) {
1676
+ try {
1677
+ const manifest = await readWorkspaceManifest(workspaceRoot);
1678
+ return getCatalogsFromWorkspaceManifest(manifest);
1679
+ } catch {
1680
+ return {};
1681
+ }
1682
+ }
1683
+ readYarnCatalogs(workspaceRoot) {
1684
+ const catalogs = getCatalogs(workspaceRoot, "yarn");
1685
+ if (!catalogs) return {};
1686
+ return this.convertWorkspaceToolsCatalogs(catalogs);
1687
+ }
1688
+ convertLockfileCatalogs(snapshots) {
1689
+ const result = {};
1690
+ for (const [name, entries] of Object.entries(snapshots)){
1691
+ result[name] = {};
1692
+ for (const [dep, entry] of Object.entries(entries))result[name][dep] = entry.specifier;
1693
+ }
1694
+ return result;
1695
+ }
1696
+ convertWorkspaceToolsCatalogs(catalogs) {
1697
+ const result = {};
1698
+ if (catalogs.default) result.default = {
1699
+ ...catalogs.default
1700
+ };
1701
+ if (catalogs.named) for (const [name, catalog] of Object.entries(catalogs.named))result[name] = {
1702
+ ...catalog
1703
+ };
1704
+ return result;
1705
+ }
1706
+ collectCatalogDependencies(packageJson) {
1707
+ const deps = [];
1708
+ const fields = [
1709
+ "dependencies",
1710
+ "devDependencies",
1711
+ "peerDependencies",
1712
+ "optionalDependencies"
1713
+ ];
1714
+ for (const field of fields){
1715
+ const fieldDeps = packageJson[field];
1716
+ if (fieldDeps) for (const [dependency, version] of Object.entries(fieldDeps)){
1717
+ if ("string" != typeof version || !version.startsWith(CATALOG_PREFIX)) continue;
1718
+ const catalogName = parseCatalogProtocol(version);
1719
+ if (catalogName) deps.push({
1720
+ field,
1721
+ dependency,
1722
+ version,
1723
+ catalogName
1724
+ });
1725
+ }
1726
+ }
1727
+ return deps;
1728
+ }
1729
+ findMissingCatalogs(deps, catalogs) {
1730
+ const missing = new Set();
1731
+ for (const { catalogName } of deps)if (!catalogs[catalogName]) missing.add(catalogName);
1732
+ return missing;
1733
+ }
1654
1734
  collectDependencies(packageJson, prefix) {
1655
1735
  const deps = [];
1656
1736
  const fields = [
@@ -1673,28 +1753,35 @@ class PnpmCatalog {
1673
1753
  }
1674
1754
  logResolvedDependencies(resultPkg, originalDeps, logger) {
1675
1755
  const allResolved = {};
1676
- for (const { field, dependency } of originalDeps){
1756
+ for (const { field, dependency, source } of originalDeps){
1677
1757
  const deps = resultPkg[field];
1678
1758
  if (deps?.[dependency]) {
1679
1759
  if (!allResolved[field]) allResolved[field] = [];
1680
1760
  allResolved[field].push({
1681
1761
  dependency,
1682
- version: deps[dependency]
1762
+ version: deps[dependency],
1763
+ source
1683
1764
  });
1684
1765
  }
1685
1766
  }
1686
1767
  if (Object.keys(allResolved).length > 0) {
1687
- logger.info("Resolved dependencies:");
1768
+ logger.global.info("Resolved dependencies:");
1688
1769
  for (const [field, deps] of Object.entries(allResolved)){
1689
- logger.info(`- ${field}:`);
1690
- for (const { dependency, version } of deps)logger.info(` ${dependency}: ${version}`);
1770
+ logger.global.info(`- ${field}:`);
1771
+ for (const { dependency, version, source } of deps)logger.global.info(` ${dependency}: ${version} (${source})`);
1691
1772
  }
1692
1773
  }
1693
1774
  }
1694
1775
  validateNoUnresolvedReferences(resultPkg, logger) {
1776
+ const unresolvedCatalog = this.collectCatalogDependencies(resultPkg);
1777
+ const unresolvedWorkspace = this.collectDependencies(resultPkg, WORKSPACE_PREFIX);
1695
1778
  const unresolvedDeps = [
1696
- ...this.collectDependencies(resultPkg, CATALOG_PREFIX),
1697
- ...this.collectDependencies(resultPkg, WORKSPACE_PREFIX)
1779
+ ...unresolvedCatalog.map((d)=>({
1780
+ field: d.field,
1781
+ dependency: d.dependency,
1782
+ version: d.version
1783
+ })),
1784
+ ...unresolvedWorkspace
1698
1785
  ];
1699
1786
  if (unresolvedDeps.length > 0) {
1700
1787
  const catalogRefs = unresolvedDeps.filter((dep)=>dep.version.startsWith(CATALOG_PREFIX));
@@ -1711,10 +1798,8 @@ class PnpmCatalog {
1711
1798
  }
1712
1799
  }
1713
1800
  }
1714
- let defaultInstance = null;
1715
- function getDefaultPnpmCatalog() {
1716
- if (!defaultInstance) defaultInstance = new PnpmCatalog();
1717
- return defaultInstance;
1801
+ function createWorkspaceCatalog() {
1802
+ return new WorkspaceCatalog();
1718
1803
  }
1719
1804
  function transformExportPath(path, processTSExports = true, collapseIndex = false) {
1720
1805
  let transformedPath = path;
@@ -1819,8 +1904,9 @@ function applyRslibTransformations(packageJson, originalPackageJson, processTSEx
1819
1904
  });
1820
1905
  return sort_package_json(processedManifest);
1821
1906
  }
1822
- async function applyPnpmTransformations(packageJson, dir = process.cwd()) {
1823
- return getDefaultPnpmCatalog().resolvePackageJson(packageJson, dir);
1907
+ async function applyPnpmTransformations(packageJson, dir = process.cwd(), catalog) {
1908
+ const workspaceCatalog = catalog ?? createWorkspaceCatalog();
1909
+ return workspaceCatalog.resolvePackageJson(packageJson, dir);
1824
1910
  }
1825
1911
  async function buildPackageJson(packageJson, isProduction = false, processTSExports = true, entrypoints, exportToOutputMap, bundle, transform) {
1826
1912
  let result;
@@ -1831,12 +1917,9 @@ async function buildPackageJson(packageJson, isProduction = false, processTSExpo
1831
1917
  if (transform) result = transform(result);
1832
1918
  return result;
1833
1919
  }
1834
- const PackageJsonTransformPlugin = (options = {})=>{
1835
- const cache = new Map();
1836
- return {
1920
+ const PackageJsonTransformPlugin = (options = {})=>({
1837
1921
  name: "package-json-processor",
1838
1922
  setup (api) {
1839
- api.expose("files-cache", cache);
1840
1923
  let filesArray = api.useExposed("files-array");
1841
1924
  if (!filesArray) {
1842
1925
  filesArray = new Set();
@@ -1864,6 +1947,7 @@ const PackageJsonTransformPlugin = (options = {})=>{
1864
1947
  const processedPackageJson = await buildPackageJson(packageJson.data, isProduction, options.processTSExports, entrypoints, exportToOutputMap, options.bundle, options.transform);
1865
1948
  packageJson.data = processedPackageJson;
1866
1949
  if (options.forcePrivate) packageJson.data.private = true;
1950
+ if (options.format) packageJson.data.type = "esm" === options.format ? "module" : "commonjs";
1867
1951
  const useRollupTypes = api.useExposed("use-rollup-types");
1868
1952
  if (useRollupTypes && packageJson.data.exports && "object" == typeof packageJson.data.exports) {
1869
1953
  const exports = packageJson.data.exports;
@@ -1884,8 +1968,7 @@ const PackageJsonTransformPlugin = (options = {})=>{
1884
1968
  }
1885
1969
  });
1886
1970
  }
1887
- };
1888
- };
1971
+ });
1889
1972
  class ImportGraph {
1890
1973
  options;
1891
1974
  sys;
@@ -2302,12 +2385,35 @@ const TsDocLintPlugin = (options = {})=>{
2302
2385
  }
2303
2386
  };
2304
2387
  };
2388
+ const VirtualEntryPlugin = (options)=>{
2389
+ const { virtualEntryNames } = options;
2390
+ return {
2391
+ name: "virtual-entry-plugin",
2392
+ setup (api) {
2393
+ api.expose("virtual-entry-names", virtualEntryNames);
2394
+ api.processAssets({
2395
+ stage: "additional"
2396
+ }, async (context)=>{
2397
+ let filesArray = api.useExposed("files-array");
2398
+ if (!filesArray) {
2399
+ filesArray = new Set();
2400
+ api.expose("files-array", filesArray);
2401
+ }
2402
+ for (const assetName of Object.keys(context.compilation.assets)){
2403
+ const baseName = assetName.replace(/\.(c|m)?js$/, "");
2404
+ if (virtualEntryNames.has(baseName)) filesArray.add(assetName);
2405
+ }
2406
+ });
2407
+ }
2408
+ };
2409
+ };
2305
2410
  /* v8 ignore next -- @preserve */ class NodeLibraryBuilder {
2306
2411
  static VALID_TARGETS = [
2307
2412
  "dev",
2308
2413
  "npm"
2309
2414
  ];
2310
2415
  static DEFAULT_OPTIONS = {
2416
+ format: "esm",
2311
2417
  plugins: [],
2312
2418
  define: {},
2313
2419
  copyPatterns: [],
@@ -2332,6 +2438,7 @@ const TsDocLintPlugin = (options = {})=>{
2332
2438
  plugins: options.plugins ?? NodeLibraryBuilder.DEFAULT_OPTIONS.plugins,
2333
2439
  define: options.define ?? NodeLibraryBuilder.DEFAULT_OPTIONS.define,
2334
2440
  tsconfigPath: options.tsconfigPath,
2441
+ format: options.format ?? NodeLibraryBuilder.DEFAULT_OPTIONS.format,
2335
2442
  targets: options.targets ?? NodeLibraryBuilder.DEFAULT_OPTIONS.targets,
2336
2443
  externals: options.externals ?? NodeLibraryBuilder.DEFAULT_OPTIONS.externals,
2337
2444
  apiModel: options.apiModel ?? NodeLibraryBuilder.DEFAULT_OPTIONS.apiModel,
@@ -2349,6 +2456,9 @@ const TsDocLintPlugin = (options = {})=>{
2349
2456
  },
2350
2457
  ...void 0 !== options.transform && {
2351
2458
  transform: options.transform
2459
+ },
2460
+ ...void 0 !== options.virtualEntries && {
2461
+ virtualEntries: options.virtualEntries
2352
2462
  }
2353
2463
  };
2354
2464
  return merged;
@@ -2387,10 +2497,12 @@ const TsDocLintPlugin = (options = {})=>{
2387
2497
  target,
2388
2498
  pkg
2389
2499
  }) : void 0;
2500
+ const libraryFormat = options.format ?? "esm";
2390
2501
  plugins.push(PackageJsonTransformPlugin({
2391
2502
  forcePrivate: "dev" === target,
2392
2503
  bundle: true,
2393
2504
  target,
2505
+ format: libraryFormat,
2394
2506
  ...transformFn && {
2395
2507
  transform: transformFn
2396
2508
  }
@@ -2415,6 +2527,7 @@ const TsDocLintPlugin = (options = {})=>{
2415
2527
  bundledPackages: options.dtsBundledPackages
2416
2528
  },
2417
2529
  buildTarget: target,
2530
+ format: libraryFormat,
2418
2531
  ...void 0 !== apiModelForTarget && {
2419
2532
  apiModel: apiModelForTarget
2420
2533
  }
@@ -2437,9 +2550,9 @@ const TsDocLintPlugin = (options = {})=>{
2437
2550
  externals: options.externals
2438
2551
  }
2439
2552
  },
2440
- format: "esm",
2553
+ format: libraryFormat,
2441
2554
  experiments: {
2442
- advancedEsm: true
2555
+ advancedEsm: "esm" === libraryFormat
2443
2556
  },
2444
2557
  bundle: true,
2445
2558
  plugins,
@@ -2456,10 +2569,70 @@ const TsDocLintPlugin = (options = {})=>{
2456
2569
  }
2457
2570
  }
2458
2571
  };
2572
+ const hasRegularEntries = void 0 !== options.entry || NodeLibraryBuilder.packageHasExports();
2573
+ const virtualEntries = options.virtualEntries ?? {};
2574
+ const hasVirtualEntries = Object.keys(virtualEntries).length > 0;
2575
+ if (!hasRegularEntries && !hasVirtualEntries) throw new Error("No entry points configured. Provide package.json exports, explicit entry option, or virtualEntries.");
2576
+ const libConfigs = [];
2577
+ if (hasRegularEntries) libConfigs.push(lib);
2578
+ if (hasVirtualEntries) {
2579
+ const virtualByFormat = new Map();
2580
+ for (const [outputName, config] of Object.entries(virtualEntries)){
2581
+ const entryFormat = config.format ?? libraryFormat;
2582
+ if (!virtualByFormat.has(entryFormat)) virtualByFormat.set(entryFormat, new Map());
2583
+ const entryName = outputName.replace(/\.(c|m)?js$/, "");
2584
+ const formatMap = virtualByFormat.get(entryFormat);
2585
+ if (formatMap) formatMap.set(entryName, config.source);
2586
+ }
2587
+ for (const [format, entries] of virtualByFormat){
2588
+ const virtualEntryNames = new Set(entries.keys());
2589
+ const entryMap = Object.fromEntries(entries);
2590
+ const virtualLib = {
2591
+ id: `${target}-virtual-${format}`,
2592
+ format,
2593
+ bundle: true,
2594
+ output: {
2595
+ target: "node",
2596
+ cleanDistPath: false,
2597
+ sourceMap: false,
2598
+ distPath: {
2599
+ root: outputDir
2600
+ },
2601
+ ...options.externals && options.externals.length > 0 && {
2602
+ externals: options.externals
2603
+ }
2604
+ },
2605
+ source: {
2606
+ entry: entryMap
2607
+ },
2608
+ plugins: [
2609
+ VirtualEntryPlugin({
2610
+ virtualEntryNames
2611
+ }),
2612
+ FilesArrayPlugin({
2613
+ target
2614
+ })
2615
+ ]
2616
+ };
2617
+ libConfigs.push(virtualLib);
2618
+ }
2619
+ if (hasRegularEntries) {
2620
+ const allVirtualEntryNames = new Set();
2621
+ for (const outputName of Object.keys(virtualEntries)){
2622
+ const entryName = outputName.replace(/\.(c|m)?js$/, "");
2623
+ allVirtualEntryNames.add(entryName);
2624
+ }
2625
+ plugins.push({
2626
+ name: "virtual-entry-names-exposer",
2627
+ setup (api) {
2628
+ api.expose("virtual-entry-names", allVirtualEntryNames);
2629
+ }
2630
+ });
2631
+ lib.plugins = plugins;
2632
+ }
2633
+ }
2459
2634
  return defineConfig({
2460
- lib: [
2461
- lib
2462
- ],
2635
+ lib: libConfigs,
2463
2636
  ...options.tsconfigPath && {
2464
2637
  source: {
2465
2638
  tsconfigPath: options.tsconfigPath
@@ -2472,5 +2645,15 @@ const TsDocLintPlugin = (options = {})=>{
2472
2645
  }
2473
2646
  });
2474
2647
  }
2648
+ static packageHasExports() {
2649
+ try {
2650
+ const packageJsonPath = join(process.cwd(), "package.json");
2651
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
2652
+ const { exports } = packageJson;
2653
+ return null != exports && "object" == typeof exports && Object.keys(exports).length > 0;
2654
+ } catch {
2655
+ return false;
2656
+ }
2657
+ }
2475
2658
  }
2476
- export { AutoEntryPlugin, DtsPlugin, EntryExtractor, FilesArrayPlugin, ImportGraph, NodeLibraryBuilder, PackageJsonTransformPlugin, TsDocConfigBuilder, TsDocLintPlugin, TsconfigResolver, TsconfigResolverError, extractEntriesFromPackageJson };
2659
+ export { AutoEntryPlugin, DtsPlugin, EntryExtractor, FilesArrayPlugin, ImportGraph, NodeLibraryBuilder, PackageJsonTransformPlugin, TsDocConfigBuilder, TsDocLintPlugin, TsconfigResolver, TsconfigResolverError, VirtualEntryPlugin, extractEntriesFromPackageJson };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@savvy-web/rslib-builder",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "private": false,
5
5
  "description": "RSlib-based build system for Node.js libraries with automatic package.json transformation, TypeScript declaration bundling, and multi-target support",
6
6
  "keywords": [
@@ -45,7 +45,11 @@
45
45
  "dependencies": {
46
46
  "@microsoft/tsdoc": "^0.16.0",
47
47
  "@microsoft/tsdoc-config": "^0.18.0",
48
+ "@pnpm/catalogs.config": "^1000.0.5",
49
+ "@pnpm/catalogs.protocol-parser": "^1001.0.0",
48
50
  "@pnpm/exportable-manifest": "^1000.3.1",
51
+ "@pnpm/lockfile.fs": "^1001.1.29",
52
+ "@pnpm/workspace.read-manifest": "^1000.2.10",
49
53
  "@typescript-eslint/parser": "^8.53.1",
50
54
  "deep-equal": "^2.2.3",
51
55
  "eslint": "^9.39.2",
@@ -54,8 +58,7 @@
54
58
  "picocolors": "^1.1.1",
55
59
  "sort-package-json": "^3.6.1",
56
60
  "tmp": "^0.2.5",
57
- "workspace-tools": "^0.40.4",
58
- "yaml": "^2.8.2"
61
+ "workspace-tools": "^0.41.0"
59
62
  },
60
63
  "peerDependencies": {
61
64
  "@microsoft/api-extractor": "^7.55.2",