@savvy-web/rslib-builder 0.10.0 → 0.12.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.
package/index.js CHANGED
@@ -5,16 +5,19 @@ 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 { getWorkspaceManagerRoot } from "workspace-tools";
8
+ import { getCatalogs, getWorkspaceManagerAndRoot, getWorkspaceManagerRoot } from "workspace-tools";
9
+ import typescript, { ImportsNotUsedAsValues, JsxEmit, ModuleDetectionKind, ModuleKind, ModuleResolutionKind, NewLineKind, ScriptTarget, createCompilerHost, findConfigFile, formatDiagnostic, parseJsonConfigFileContent, readConfigFile, sys } from "typescript";
9
10
  import { spawn } from "node:child_process";
10
11
  import { StandardTags, Standardization, TSDocTagSyntaxKind } from "@microsoft/tsdoc";
11
12
  import deep_equal from "deep-equal";
12
- import typescript, { ImportsNotUsedAsValues, JsxEmit, ModuleDetectionKind, ModuleKind, ModuleResolutionKind, NewLineKind, ScriptTarget, createCompilerHost, findConfigFile, formatDiagnostic, parseJsonConfigFileContent, readConfigFile, sys } from "typescript";
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`;
@@ -83,16 +86,21 @@ class EntryExtractor {
83
86
  }
84
87
  extract(packageJson) {
85
88
  const entries = {};
86
- this.extractFromExports(packageJson.exports, entries);
89
+ const exportPaths = {};
90
+ this.extractFromExports(packageJson.exports, entries, exportPaths);
87
91
  this.extractFromBin(packageJson.bin, entries);
88
92
  return {
89
- entries
93
+ entries,
94
+ exportPaths
90
95
  };
91
96
  }
92
- extractFromExports(exports, entries) {
97
+ extractFromExports(exports, entries, exportPaths) {
93
98
  if (!exports) return;
94
99
  if ("string" == typeof exports) {
95
- if (this.isTypeScriptFile(exports)) entries.index = exports;
100
+ if (this.isTypeScriptFile(exports)) {
101
+ entries.index = exports;
102
+ exportPaths.index = ".";
103
+ }
96
104
  return;
97
105
  }
98
106
  if ("object" != typeof exports) return;
@@ -104,6 +112,7 @@ class EntryExtractor {
104
112
  if (!this.isTypeScriptFile(resolvedPath)) continue;
105
113
  const entryName = this.createEntryName(key);
106
114
  entries[entryName] = resolvedPath;
115
+ exportPaths[entryName] = key;
107
116
  }
108
117
  }
109
118
  extractFromBin(bin, entries) {
@@ -141,10 +150,6 @@ class EntryExtractor {
141
150
  return withoutPrefix.replace(/\//g, "-");
142
151
  }
143
152
  }
144
- function extractEntriesFromPackageJson(packageJson, options) {
145
- const extractor = new EntryExtractor(options);
146
- return extractor.extract(packageJson);
147
- }
148
153
  async function fileExistAsync(assetName) {
149
154
  const assetPath = join(process.cwd(), assetName);
150
155
  const assetExists = !!await stat(assetPath).catch(()=>false);
@@ -176,6 +181,223 @@ function getApiExtractorPath() {
176
181
  }
177
182
  throw new Error("API Extractor bundling requires @microsoft/api-extractor to be installed.\nInstall it with: pnpm add -D @microsoft/api-extractor");
178
183
  }
184
+ class ImportGraph {
185
+ options;
186
+ sys;
187
+ program = null;
188
+ compilerOptions = null;
189
+ moduleResolutionCache = null;
190
+ constructor(options){
191
+ this.options = options;
192
+ this.sys = options.sys ?? typescript.sys;
193
+ }
194
+ traceFromEntries(entryPaths) {
195
+ const errors = [];
196
+ const visited = new Set();
197
+ const entries = [];
198
+ const initResult = this.initializeProgram();
199
+ if (!initResult.success) return {
200
+ files: [],
201
+ entries: [],
202
+ errors: [
203
+ initResult.error
204
+ ]
205
+ };
206
+ for (const entryPath of entryPaths){
207
+ const absolutePath = this.resolveEntryPath(entryPath);
208
+ if (!this.sys.fileExists(absolutePath)) {
209
+ errors.push({
210
+ type: "entry_not_found",
211
+ message: `Entry file not found: ${entryPath}`,
212
+ path: absolutePath
213
+ });
214
+ continue;
215
+ }
216
+ entries.push(absolutePath);
217
+ this.traceImports(absolutePath, visited, errors);
218
+ }
219
+ const files = Array.from(visited).filter((file)=>this.isSourceFile(file));
220
+ return {
221
+ files: files.sort(),
222
+ entries,
223
+ errors
224
+ };
225
+ }
226
+ traceFromPackageExports(packageJsonPath) {
227
+ const absolutePath = this.resolveEntryPath(packageJsonPath);
228
+ let packageJson;
229
+ try {
230
+ const content = this.sys.readFile(absolutePath);
231
+ if (!content) return {
232
+ files: [],
233
+ entries: [],
234
+ errors: [
235
+ {
236
+ type: "package_json_not_found",
237
+ message: `Failed to read package.json: File not found at ${absolutePath}`,
238
+ path: absolutePath
239
+ }
240
+ ]
241
+ };
242
+ packageJson = JSON.parse(content);
243
+ } catch (error) {
244
+ const message = error instanceof Error ? error.message : String(error);
245
+ return {
246
+ files: [],
247
+ entries: [],
248
+ errors: [
249
+ {
250
+ type: "package_json_parse_error",
251
+ message: `Failed to parse package.json: ${message}`,
252
+ path: absolutePath
253
+ }
254
+ ]
255
+ };
256
+ }
257
+ const extractor = new EntryExtractor();
258
+ const { entries } = extractor.extract(packageJson);
259
+ const packageDir = dirname(absolutePath);
260
+ const entryPaths = Object.values(entries).map((p)=>external_node_path_resolve(packageDir, p));
261
+ return this.traceFromEntries(entryPaths);
262
+ }
263
+ initializeProgram() {
264
+ if (this.program) return {
265
+ success: true
266
+ };
267
+ const configPath = this.findTsConfig();
268
+ if (!configPath) return {
269
+ success: false,
270
+ error: {
271
+ type: "tsconfig_not_found",
272
+ message: `No tsconfig.json found in ${this.options.rootDir}`,
273
+ path: this.options.rootDir
274
+ }
275
+ };
276
+ const configFile = typescript.readConfigFile(configPath, (path)=>this.sys.readFile(path));
277
+ if (configFile.error) {
278
+ const message = typescript.flattenDiagnosticMessageText(configFile.error.messageText, "\n");
279
+ return {
280
+ success: false,
281
+ error: {
282
+ type: "tsconfig_read_error",
283
+ message: `Failed to read tsconfig.json: ${message}`,
284
+ path: configPath
285
+ }
286
+ };
287
+ }
288
+ const parsed = typescript.parseJsonConfigFileContent(configFile.config, this.sys, dirname(configPath));
289
+ if (parsed.errors.length > 0) {
290
+ const messages = parsed.errors.map((e)=>typescript.flattenDiagnosticMessageText(e.messageText, "\n")).join("\n");
291
+ return {
292
+ success: false,
293
+ error: {
294
+ type: "tsconfig_parse_error",
295
+ message: `Failed to parse tsconfig.json: ${messages}`,
296
+ path: configPath
297
+ }
298
+ };
299
+ }
300
+ this.compilerOptions = parsed.options;
301
+ this.moduleResolutionCache = typescript.createModuleResolutionCache(this.options.rootDir, (fileName)=>fileName.toLowerCase(), this.compilerOptions);
302
+ const host = typescript.createCompilerHost(this.compilerOptions, true);
303
+ host.getCurrentDirectory = ()=>this.options.rootDir;
304
+ this.program = typescript.createProgram([], this.compilerOptions, host);
305
+ return {
306
+ success: true
307
+ };
308
+ }
309
+ findTsConfig() {
310
+ if (this.options.tsconfigPath) {
311
+ const customPath = isAbsolute(this.options.tsconfigPath) ? this.options.tsconfigPath : external_node_path_resolve(this.options.rootDir, this.options.tsconfigPath);
312
+ if (this.sys.fileExists(customPath)) return customPath;
313
+ return null;
314
+ }
315
+ const configPath = typescript.findConfigFile(this.options.rootDir, (path)=>this.sys.fileExists(path));
316
+ return configPath ?? null;
317
+ }
318
+ resolveEntryPath(entryPath) {
319
+ if (isAbsolute(entryPath)) return normalize(entryPath);
320
+ return normalize(external_node_path_resolve(this.options.rootDir, entryPath));
321
+ }
322
+ traceImports(filePath, visited, errors) {
323
+ const normalizedPath = normalize(filePath);
324
+ if (visited.has(normalizedPath)) return;
325
+ if (this.isExternalModule(normalizedPath)) return;
326
+ visited.add(normalizedPath);
327
+ const content = this.sys.readFile(normalizedPath);
328
+ if (!content) return void errors.push({
329
+ type: "file_read_error",
330
+ message: `Failed to read file: ${normalizedPath}`,
331
+ path: normalizedPath
332
+ });
333
+ const sourceFile = typescript.createSourceFile(normalizedPath, content, typescript.ScriptTarget.Latest, true);
334
+ const imports = this.extractImports(sourceFile);
335
+ for (const importPath of imports){
336
+ const resolved = this.resolveImport(importPath, normalizedPath);
337
+ if (resolved) this.traceImports(resolved, visited, errors);
338
+ }
339
+ }
340
+ extractImports(sourceFile) {
341
+ const imports = [];
342
+ const visit = (node)=>{
343
+ if (typescript.isImportDeclaration(node)) {
344
+ const specifier = node.moduleSpecifier;
345
+ if (typescript.isStringLiteral(specifier)) imports.push(specifier.text);
346
+ } else if (typescript.isExportDeclaration(node)) {
347
+ const specifier = node.moduleSpecifier;
348
+ if (specifier && typescript.isStringLiteral(specifier)) imports.push(specifier.text);
349
+ } else if (typescript.isCallExpression(node)) {
350
+ const expression = node.expression;
351
+ if (expression.kind === typescript.SyntaxKind.ImportKeyword && node.arguments.length > 0) {
352
+ const arg = node.arguments[0];
353
+ if (arg && typescript.isStringLiteral(arg)) imports.push(arg.text);
354
+ }
355
+ }
356
+ typescript.forEachChild(node, visit);
357
+ };
358
+ visit(sourceFile);
359
+ return imports;
360
+ }
361
+ resolveImport(specifier, fromFile) {
362
+ if (!specifier.startsWith(".") && !specifier.startsWith("/")) {
363
+ if (!this.compilerOptions?.paths || !Object.keys(this.compilerOptions.paths).length) return null;
364
+ }
365
+ if (!this.compilerOptions || !this.moduleResolutionCache) return null;
366
+ const resolved = typescript.resolveModuleName(specifier, fromFile, this.compilerOptions, this.sys, this.moduleResolutionCache);
367
+ if (resolved.resolvedModule) {
368
+ const resolvedPath = resolved.resolvedModule.resolvedFileName;
369
+ if (resolved.resolvedModule.isExternalLibraryImport) return null;
370
+ if (resolvedPath.endsWith(".d.ts")) {
371
+ const sourcePath = resolvedPath.replace(/\.d\.ts$/, ".ts");
372
+ if (this.sys.fileExists(sourcePath)) return sourcePath;
373
+ return null;
374
+ }
375
+ return resolvedPath;
376
+ }
377
+ return null;
378
+ }
379
+ isExternalModule(filePath) {
380
+ return filePath.includes("/node_modules/") || filePath.includes("\\node_modules\\");
381
+ }
382
+ isSourceFile(filePath) {
383
+ if (!filePath.endsWith(".ts") && !filePath.endsWith(".tsx")) return false;
384
+ if (filePath.endsWith(".d.ts")) return false;
385
+ if (filePath.includes(".test.") || filePath.includes(".spec.")) return false;
386
+ if (filePath.includes("/__test__/") || filePath.includes("\\__test__\\")) return false;
387
+ if (filePath.includes("/__tests__/") || filePath.includes("\\__tests__\\")) return false;
388
+ const excludePatterns = this.options.excludePatterns ?? [];
389
+ for (const pattern of excludePatterns)if (filePath.includes(pattern)) return false;
390
+ return true;
391
+ }
392
+ static fromEntries(entryPaths, options) {
393
+ const graph = new ImportGraph(options);
394
+ return graph.traceFromEntries(entryPaths);
395
+ }
396
+ static fromPackageExports(packageJsonPath, options) {
397
+ const graph = new ImportGraph(options);
398
+ return graph.traceFromPackageExports(packageJsonPath);
399
+ }
400
+ }
179
401
  const AutoEntryPlugin = (options)=>{
180
402
  const buildStateMap = new WeakMap();
181
403
  return {
@@ -205,15 +427,16 @@ const AutoEntryPlugin = (options)=>{
205
427
  try {
206
428
  const packageJsonContent = await readFile(assetPath, "utf-8");
207
429
  const packageJson = JSON.parse(packageJsonContent);
208
- const { entries } = extractEntriesFromPackageJson(packageJson, options?.exportsAsIndexes != null ? {
430
+ const extractorOptions = options?.exportsAsIndexes != null ? {
209
431
  exportsAsIndexes: options.exportsAsIndexes
210
- } : void 0);
432
+ } : void 0;
433
+ const { entries } = new EntryExtractor(extractorOptions).extract(packageJson);
211
434
  if (options?.exportsAsIndexes && packageJson.exports) {
212
435
  const exports = packageJson.exports;
213
436
  if ("object" == typeof exports && !Array.isArray(exports)) for (const pkgExportKey of Object.keys(exports)){
214
437
  if ("./package.json" === pkgExportKey) continue;
215
438
  const normalizedExportKey = pkgExportKey.replace(/^\.\//, "");
216
- for (const [entryName] of Object.entries(entries)){
439
+ for (const entryName of Object.keys(entries)){
217
440
  const normalizedEntryName = entryName.replace(/\/index$/, "");
218
441
  if ("." === pkgExportKey && "index" === entryName || normalizedExportKey === normalizedEntryName) {
219
442
  const outputPath = `./${entryName}.js`;
@@ -229,7 +452,26 @@ const AutoEntryPlugin = (options)=>{
229
452
  }
230
453
  if (Object.keys(entries).length > 0) {
231
454
  const environments = Object.entries(config?.environments ?? {});
232
- environments.forEach(([_env, lib])=>{
455
+ if (options?.bundleless) {
456
+ const cwd = process.cwd();
457
+ const graph = new ImportGraph({
458
+ rootDir: cwd
459
+ });
460
+ const entrySourcePaths = Object.values(entries);
461
+ const result = graph.traceFromEntries(entrySourcePaths);
462
+ const tracedEntries = {};
463
+ for (const file of result.files){
464
+ const relPath = relative(cwd, file);
465
+ tracedEntries[relPath] = `./${relPath}`;
466
+ }
467
+ log.global.info(`bundleless: traced ${Object.keys(tracedEntries).length} files from ${entrySourcePaths.length} entries`);
468
+ environments.forEach(([_env, lib])=>{
469
+ lib.source = {
470
+ ...lib.source,
471
+ entry: tracedEntries
472
+ };
473
+ });
474
+ } else environments.forEach(([_env, lib])=>{
233
475
  lib.source = {
234
476
  ...lib.source,
235
477
  entry: {
@@ -310,21 +552,6 @@ class TSConfigFile {
310
552
  }
311
553
  }
312
554
  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
555
  writeBundleTempConfig(_target) {
329
556
  const cwd = process.cwd();
330
557
  const baseConfig = this.config;
@@ -786,7 +1013,7 @@ class TsDocConfigBuilder {
786
1013
  const tsdocConfig = {
787
1014
  $schema: "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
788
1015
  noStandardTags: !useStandardTags,
789
- reportUnsupportedHtmlElements: false
1016
+ reportUnsupportedHtmlElements: true
790
1017
  };
791
1018
  if (tagDefinitions.length > 0) tsdocConfig.tagDefinitions = tagDefinitions;
792
1019
  if (Object.keys(supportForTags).length > 0) tsdocConfig.supportForTags = supportForTags;
@@ -884,19 +1111,22 @@ async function collectDtsFiles(dir, baseDir = dir) {
884
1111
  await walk(dir);
885
1112
  return files;
886
1113
  }
1114
+ function resolveTsdocMetadataFilename(apiModel) {
1115
+ const option = "object" == typeof apiModel ? apiModel.tsdocMetadata : void 0;
1116
+ return "object" == typeof option && option.filename ? option.filename : "tsdoc-metadata.json";
1117
+ }
887
1118
  async function bundleDtsFiles(options) {
888
1119
  const { cwd, tempDtsDir, tempOutputDir, tsconfigPath, bundledPackages, entryPoints, banner, footer, apiModel } = options;
889
1120
  const bundledFiles = new Map();
890
- let apiModelPath;
1121
+ const apiModelPaths = new Map();
891
1122
  let tsdocMetadataPath;
892
1123
  const apiModelEnabled = true === apiModel || "object" == typeof apiModel;
893
- const apiModelFilename = "object" == typeof apiModel && apiModel.filename ? apiModel.filename : "api.json";
894
1124
  const tsdocOptions = "object" == typeof apiModel ? apiModel.tsdoc : void 0;
895
1125
  const tsdocMetadataOption = "object" == typeof apiModel ? apiModel.tsdocMetadata : void 0;
896
1126
  const tsdocWarnings = tsdocOptions?.warnings ?? (TsDocConfigBuilder.isCI() ? "fail" : "log");
897
1127
  const forgottenExports = ("object" == typeof apiModel ? apiModel.forgottenExports : void 0) ?? (TsDocConfigBuilder.isCI() ? "error" : "include");
898
1128
  const tsdocMetadataEnabled = apiModelEnabled && (void 0 === tsdocMetadataOption || true === tsdocMetadataOption || "object" == typeof tsdocMetadataOption && false !== tsdocMetadataOption.enabled);
899
- const tsdocMetadataFilename = "object" == typeof tsdocMetadataOption && tsdocMetadataOption.filename ? tsdocMetadataOption.filename : "tsdoc-metadata.json";
1129
+ const tsdocMetadataFilename = resolveTsdocMetadataFilename(apiModel);
900
1130
  getApiExtractorPath();
901
1131
  const lintConfig = "object" == typeof tsdocOptions?.lint ? tsdocOptions.lint : void 0;
902
1132
  const persistConfig = lintConfig?.persistConfig;
@@ -928,9 +1158,10 @@ async function bundleDtsFiles(options) {
928
1158
  }
929
1159
  const outputFileName = `${entryName}.d.ts`;
930
1160
  const tempBundledPath = join(tempOutputDir, outputFileName);
931
- const generateApiModel = apiModelEnabled && "index" === entryName;
932
- const tempApiModelPath = generateApiModel ? join(tempOutputDir, apiModelFilename) : void 0;
933
- const generateTsdocMetadata = tsdocMetadataEnabled && "index" === entryName;
1161
+ const isMainEntry = "index" === entryName || 1 === entryPoints.size;
1162
+ const generateApiModel = apiModelEnabled;
1163
+ const tempApiModelPath = generateApiModel ? join(tempOutputDir, `${entryName}.api.json`) : void 0;
1164
+ const generateTsdocMetadata = tsdocMetadataEnabled && isMainEntry;
934
1165
  const tempTsdocMetadataPath = generateTsdocMetadata ? join(tempOutputDir, tsdocMetadataFilename) : void 0;
935
1166
  const prepareOptions = {
936
1167
  configObject: {
@@ -960,7 +1191,7 @@ async function bundleDtsFiles(options) {
960
1191
  }
961
1192
  }
962
1193
  },
963
- bundledPackages: bundledPackages
1194
+ bundledPackages
964
1195
  },
965
1196
  packageJsonFullPath: join(cwd, "package.json"),
966
1197
  configObjectFullPath: void 0
@@ -1040,7 +1271,7 @@ async function bundleDtsFiles(options) {
1040
1271
  if ("error" === forgottenExports) throw new Error(`Forgotten exports detected for entry "${entryName}":\n ${forgottenMessages}`);
1041
1272
  if ("include" === forgottenExports) core_logger.warn(`Forgotten exports for entry "${entryName}":\n ${forgottenMessages}`);
1042
1273
  }
1043
- if (generateApiModel && tempApiModelPath) apiModelPath = tempApiModelPath;
1274
+ if (generateApiModel && tempApiModelPath) apiModelPaths.set(entryName, tempApiModelPath);
1044
1275
  if (generateTsdocMetadata && tempTsdocMetadataPath) tsdocMetadataPath = tempTsdocMetadataPath;
1045
1276
  if (banner || footer) {
1046
1277
  let content = await readFile(tempBundledPath, "utf-8");
@@ -1052,9 +1283,7 @@ async function bundleDtsFiles(options) {
1052
1283
  }
1053
1284
  return {
1054
1285
  bundledFiles,
1055
- ...apiModelPath && {
1056
- apiModelPath
1057
- },
1286
+ apiModelPaths,
1058
1287
  ...tsdocMetadataPath && {
1059
1288
  tsdocMetadataPath
1060
1289
  },
@@ -1066,6 +1295,45 @@ async function bundleDtsFiles(options) {
1066
1295
  function stripSourceMapComment(content) {
1067
1296
  return content.replace(/\/\/# sourceMappingURL=\S+\.d\.ts\.map\s*$/gm, "").trim();
1068
1297
  }
1298
+ function mergeApiModels(options) {
1299
+ const { perEntryModels, packageName, exportPaths } = options;
1300
+ if (0 === perEntryModels.size) throw new Error("Cannot merge zero API models");
1301
+ const firstModel = perEntryModels.values().next().value;
1302
+ const merged = JSON.parse(JSON.stringify(firstModel));
1303
+ const entryPointMembers = [];
1304
+ for (const [entryName, model] of perEntryModels){
1305
+ const entryPoints = model.members;
1306
+ if (!entryPoints || 0 === entryPoints.length) continue;
1307
+ const entryPoint = JSON.parse(JSON.stringify(entryPoints[0]));
1308
+ const exportPath = exportPaths[entryName] ?? ("index" === entryName ? "." : `./${entryName}`);
1309
+ const isMainEntry = "." === exportPath;
1310
+ if (isMainEntry) entryPointMembers.unshift(entryPoint);
1311
+ else {
1312
+ const subpath = exportPath.replace(/^\.\//, "");
1313
+ const originalPrefix = `${packageName}!`;
1314
+ const newPrefix = `${packageName}/${subpath}!`;
1315
+ entryPoint.canonicalReference = newPrefix;
1316
+ entryPoint.name = subpath;
1317
+ rewriteCanonicalReferences(entryPoint, originalPrefix, newPrefix);
1318
+ entryPointMembers.push(entryPoint);
1319
+ }
1320
+ }
1321
+ merged.members = entryPointMembers;
1322
+ return merged;
1323
+ }
1324
+ function rewriteCanonicalReferences(node, originalPrefix, newPrefix) {
1325
+ if (!node || "object" != typeof node) return;
1326
+ if (Array.isArray(node)) {
1327
+ for (const item of node)rewriteCanonicalReferences(item, originalPrefix, newPrefix);
1328
+ return;
1329
+ }
1330
+ const obj = node;
1331
+ if ("string" == typeof obj.canonicalReference && "EntryPoint" !== obj.kind) {
1332
+ const ref = obj.canonicalReference;
1333
+ if (ref.startsWith(originalPrefix)) obj.canonicalReference = ref.replace(originalPrefix, newPrefix);
1334
+ }
1335
+ if (Array.isArray(obj.members)) for (const member of obj.members)rewriteCanonicalReferences(member, originalPrefix, newPrefix);
1336
+ }
1069
1337
  async function ensureTempDeclarationDir(cwd, name) {
1070
1338
  const dir = join(cwd, ".rslib", "declarations", name);
1071
1339
  await rm(dir, {
@@ -1231,7 +1499,26 @@ function runTsgo(options) {
1231
1499
  return !path.includes("__test__/") && !path.includes(".test.d.ts");
1232
1500
  });
1233
1501
  if (0 === dtsFiles.length) return void log.global.warn("No declaration files were generated");
1234
- if (options.bundle) try {
1502
+ if (!options.bundle) {
1503
+ let emittedCount = 0;
1504
+ for (const file of dtsFiles){
1505
+ if (file.relativePath.endsWith(".d.ts.map")) continue;
1506
+ let outputPath = file.relativePath;
1507
+ if (outputPath.startsWith("src/")) outputPath = outputPath.slice(4);
1508
+ if (".d.ts" !== dtsExtension && outputPath.endsWith(".d.ts")) outputPath = outputPath.replace(/\.d\.ts$/, dtsExtension);
1509
+ const jsOutputPath = outputPath.replace(/\.d\.(ts|mts|cts)$/, ".js");
1510
+ if (!context.compilation.assets[jsOutputPath]) continue;
1511
+ let content = await readFile(file.path, "utf-8");
1512
+ content = stripSourceMapComment(content);
1513
+ const source = new context.sources.OriginalSource(content, outputPath);
1514
+ context.compilation.emitAsset(outputPath, source);
1515
+ emittedCount++;
1516
+ if (filesArray && outputPath.endsWith(".d.ts")) filesArray.add(outputPath);
1517
+ }
1518
+ core_logger.info(`${picocolors.dim(`[${envId}]`)} Emitted ${emittedCount} declaration file${1 === emittedCount ? "" : "s"} through asset pipeline`);
1519
+ }
1520
+ const apiModelEnabled = true === options.apiModel || "object" == typeof options.apiModel;
1521
+ if (options.bundle || apiModelEnabled) try {
1235
1522
  const exposedPackageJson = api.useExposed("api-extractor-package-json");
1236
1523
  let packageJson;
1237
1524
  if (exposedPackageJson) {
@@ -1242,8 +1529,7 @@ function runTsgo(options) {
1242
1529
  const packageJsonContent = await readFile(packageJsonPath, "utf-8");
1243
1530
  packageJson = JSON.parse(packageJsonContent);
1244
1531
  }
1245
- const extractor = new EntryExtractor();
1246
- const { entries } = extractor.extract(packageJson);
1532
+ const { entries, exportPaths } = new EntryExtractor().extract(packageJson);
1247
1533
  const entryPoints = new Map();
1248
1534
  const virtualEntryNames = api.useExposed("virtual-entry-names");
1249
1535
  for (const [entryName, sourcePath] of Object.entries(entries)){
@@ -1272,7 +1558,7 @@ function runTsgo(options) {
1272
1558
  await mkdir(tempBundledDir, {
1273
1559
  recursive: true
1274
1560
  });
1275
- const { bundledFiles, apiModelPath, tsdocMetadataPath, tsdocConfigPath } = await bundleDtsFiles({
1561
+ const { bundledFiles, apiModelPaths, tsdocMetadataPath, tsdocConfigPath } = await bundleDtsFiles({
1276
1562
  cwd,
1277
1563
  tempDtsDir,
1278
1564
  tempOutputDir: tempBundledDir,
@@ -1289,17 +1575,37 @@ function runTsgo(options) {
1289
1575
  apiModel: options.apiModel
1290
1576
  }
1291
1577
  });
1292
- let emittedCount = 0;
1293
- for (const [entryName, tempBundledPath] of bundledFiles){
1294
- const bundledFileName = `${entryName}.d.ts`;
1295
- let content = await readFile(tempBundledPath, "utf-8");
1296
- content = stripSourceMapComment(content);
1297
- const source = new context.sources.OriginalSource(content, bundledFileName);
1298
- context.compilation.emitAsset(bundledFileName, source);
1299
- emittedCount++;
1300
- if (filesArray) filesArray.add(bundledFileName);
1578
+ let apiModelPath;
1579
+ if (1 === apiModelPaths.size) apiModelPath = apiModelPaths.values().next().value;
1580
+ else if (apiModelPaths.size > 1 && packageJson.name) {
1581
+ core_logger.info(`${picocolors.dim(`[${envId}]`)} Merging API models from ${apiModelPaths.size} entries...`);
1582
+ const perEntryModels = new Map();
1583
+ for (const [entryName, modelPath] of apiModelPaths){
1584
+ const content = await readFile(modelPath, "utf-8");
1585
+ perEntryModels.set(entryName, JSON.parse(content));
1586
+ }
1587
+ const mergedModel = mergeApiModels({
1588
+ perEntryModels,
1589
+ packageName: packageJson.name,
1590
+ exportPaths
1591
+ });
1592
+ const mergedPath = join(tempBundledDir, "merged.api.json");
1593
+ await writeFile(mergedPath, JSON.stringify(mergedModel, null, 2), "utf-8");
1594
+ apiModelPath = mergedPath;
1595
+ }
1596
+ if (options.bundle) {
1597
+ let emittedCount = 0;
1598
+ for (const [entryName, tempBundledPath] of bundledFiles){
1599
+ const bundledFileName = `${entryName}.d.ts`;
1600
+ let content = await readFile(tempBundledPath, "utf-8");
1601
+ content = stripSourceMapComment(content);
1602
+ const source = new context.sources.OriginalSource(content, bundledFileName);
1603
+ context.compilation.emitAsset(bundledFileName, source);
1604
+ emittedCount++;
1605
+ if (filesArray) filesArray.add(bundledFileName);
1606
+ }
1607
+ core_logger.info(`${picocolors.dim(`[${envId}]`)} Emitted ${emittedCount} bundled declaration file${1 === emittedCount ? "" : "s"} through asset pipeline`);
1301
1608
  }
1302
- core_logger.info(`${picocolors.dim(`[${envId}]`)} Emitted ${emittedCount} bundled declaration file${1 === emittedCount ? "" : "s"} through asset pipeline`);
1303
1609
  if (apiModelPath) {
1304
1610
  const defaultApiModelFilename = packageJson.name ? `${getUnscopedPackageName(packageJson.name)}.api.json` : "api.json";
1305
1611
  const apiModelFilename = "object" == typeof options.apiModel && options.apiModel.filename ? options.apiModel.filename : defaultApiModelFilename;
@@ -1309,10 +1615,8 @@ function runTsgo(options) {
1309
1615
  if (filesArray) filesArray.add(`!${apiModelFilename}`);
1310
1616
  core_logger.info(`${picocolors.dim(`[${envId}]`)} Emitted API model: ${apiModelFilename} (excluded from npm publish)`);
1311
1617
  const localPaths = "object" == typeof options.apiModel ? options.apiModel.localPaths : void 0;
1312
- const isCI = "true" === process.env.GITHUB_ACTIONS || "true" === process.env.CI;
1313
- if (localPaths && localPaths.length > 0 && !isCI) {
1314
- const tsdocMetadataOption = "object" == typeof options.apiModel ? options.apiModel.tsdocMetadata : void 0;
1315
- const localTsdocFilename = "object" == typeof tsdocMetadataOption && tsdocMetadataOption.filename ? tsdocMetadataOption.filename : "tsdoc-metadata.json";
1618
+ if (localPaths && localPaths.length > 0 && !TsDocConfigBuilder.isCI()) {
1619
+ const localTsdocFilename = resolveTsdocMetadataFilename(options.apiModel);
1316
1620
  api.expose("dts-local-paths-data", {
1317
1621
  localPaths,
1318
1622
  apiModelFilename,
@@ -1325,8 +1629,7 @@ function runTsgo(options) {
1325
1629
  }
1326
1630
  }
1327
1631
  if (tsdocMetadataPath) {
1328
- const tsdocMetadataOption = "object" == typeof options.apiModel ? options.apiModel.tsdocMetadata : void 0;
1329
- const tsdocMetadataFilename = "object" == typeof tsdocMetadataOption && tsdocMetadataOption.filename ? tsdocMetadataOption.filename : "tsdoc-metadata.json";
1632
+ const tsdocMetadataFilename = resolveTsdocMetadataFilename(options.apiModel);
1330
1633
  const tsdocMetadataContent = (await readFile(tsdocMetadataPath, "utf-8")).replaceAll("\r\n", "\n");
1331
1634
  const tsdocMetadataSource = new context.sources.OriginalSource(tsdocMetadataContent, tsdocMetadataFilename);
1332
1635
  context.compilation.emitAsset(tsdocMetadataFilename, tsdocMetadataSource);
@@ -1349,7 +1652,7 @@ function runTsgo(options) {
1349
1652
  if (filesArray) filesArray.add("!tsconfig.json");
1350
1653
  core_logger.info(`${picocolors.dim(`[${envId}]`)} Emitted resolved tsconfig: tsconfig.json (excluded from npm publish)`);
1351
1654
  }
1352
- for (const [entryName] of bundledFiles){
1655
+ if (options.bundle) for (const [entryName] of bundledFiles){
1353
1656
  const bundledFileName = `${entryName}.d.ts`;
1354
1657
  const mapFileName = `${bundledFileName}.map`;
1355
1658
  for (const file of dtsFiles){
@@ -1367,22 +1670,6 @@ function runTsgo(options) {
1367
1670
  log.global.error("Failed to bundle declaration files:", error);
1368
1671
  if (abortOnError) throw error;
1369
1672
  }
1370
- else {
1371
- let emittedCount = 0;
1372
- for (const file of dtsFiles){
1373
- if (file.relativePath.endsWith(".d.ts.map")) continue;
1374
- let content = await readFile(file.path, "utf-8");
1375
- let outputPath = file.relativePath;
1376
- if (outputPath.startsWith("src/")) outputPath = outputPath.slice(4);
1377
- if (".d.ts" !== dtsExtension && outputPath.endsWith(".d.ts")) outputPath = outputPath.replace(/\.d\.ts$/, dtsExtension);
1378
- content = stripSourceMapComment(content);
1379
- const source = new context.sources.OriginalSource(content, outputPath);
1380
- context.compilation.emitAsset(outputPath, source);
1381
- emittedCount++;
1382
- if (filesArray && outputPath.endsWith(".d.ts")) filesArray.add(outputPath);
1383
- }
1384
- core_logger.info(`${picocolors.dim(`[${envId}]`)} Emitted ${emittedCount} declaration file${1 === emittedCount ? "" : "s"} through asset pipeline`);
1385
- }
1386
1673
  } catch (error) {
1387
1674
  log.global.error("Failed to generate declaration files:", error);
1388
1675
  if (abortOnError) throw error;
@@ -1576,75 +1863,76 @@ const FilesArrayPlugin = (options)=>({
1576
1863
  });
1577
1864
  const CATALOG_PREFIX = "catalog:";
1578
1865
  const WORKSPACE_PREFIX = "workspace:";
1579
- class PnpmCatalog {
1580
- catalogCache = null;
1581
- catalogCacheMtime = null;
1582
- cachedWorkspaceRoot = null;
1866
+ class WorkspaceCatalog {
1867
+ catalogsCache = null;
1868
+ cachedWorkspaceInfo = null;
1583
1869
  clearCache() {
1584
- this.catalogCache = null;
1585
- this.catalogCacheMtime = null;
1586
- this.cachedWorkspaceRoot = null;
1870
+ this.catalogsCache = null;
1871
+ this.cachedWorkspaceInfo = null;
1587
1872
  }
1588
- async getCatalog() {
1589
- try {
1590
- if (!this.cachedWorkspaceRoot) {
1591
- this.cachedWorkspaceRoot = getWorkspaceManagerRoot(process.cwd());
1592
- if (!this.cachedWorkspaceRoot) throw new Error("Could not find workspace root - ensure you're in a workspace");
1593
- }
1594
- const workspaceFile = external_node_path_resolve(this.cachedWorkspaceRoot, "pnpm-workspace.yaml");
1595
- const stats = await stat(workspaceFile);
1596
- const currentMtime = stats.mtime.getTime();
1597
- if (null !== this.catalogCache && this.catalogCacheMtime === currentMtime) return this.catalogCache;
1598
- const content = await readFile(workspaceFile, "utf-8");
1599
- const workspace = parse(content);
1600
- this.catalogCache = workspace.catalog ?? {};
1601
- this.catalogCacheMtime = currentMtime;
1602
- return this.catalogCache;
1603
- } catch (error) {
1604
- const errorMessage = error instanceof Error ? error.message : String(error);
1873
+ async getCatalogs() {
1874
+ if (null !== this.catalogsCache) return this.catalogsCache;
1875
+ const workspaceInfo = this.getWorkspaceInfo();
1876
+ if (!workspaceInfo) {
1605
1877
  const logger = createEnvLogger("catalog");
1606
- if (errorMessage.includes("ENOENT") && errorMessage.includes("pnpm-workspace.yaml")) {
1607
- logger.error("Failed to read pnpm catalog: workspace configuration not found");
1608
- logger.error(" -> Ensure you're in a pnpm workspace with proper configuration");
1609
- } else if (errorMessage.includes("YAML")) {
1610
- logger.error("Failed to read pnpm catalog: Invalid YAML syntax in workspace configuration");
1611
- logger.error(" -> Check workspace configuration file syntax");
1612
- } else logger.error(`Failed to read pnpm catalog from pnpm-workspace.yaml: ${errorMessage}`);
1878
+ logger.error("Could not find workspace root - ensure you're in a workspace");
1613
1879
  return {};
1614
1880
  }
1881
+ const { manager, root } = workspaceInfo;
1882
+ if ("pnpm" === manager) this.catalogsCache = await this.readPnpmCatalogs(root);
1883
+ else if ("yarn" === manager) this.catalogsCache = this.readYarnCatalogs(root);
1884
+ else this.catalogsCache = {};
1885
+ return this.catalogsCache;
1615
1886
  }
1616
1887
  async resolvePackageJson(packageJson, dir = process.cwd()) {
1617
- const logger = createEnvLogger("pnpm");
1888
+ const workspaceInfo = this.getWorkspaceInfo();
1889
+ const loggerName = workspaceInfo?.manager === "yarn" ? "yarn" : "pnpm";
1890
+ const logger = createEnvLogger(loggerName);
1618
1891
  try {
1619
- const catalog = await this.getCatalog();
1620
- const catalogDeps = this.collectDependencies(packageJson, CATALOG_PREFIX);
1892
+ const catalogs = await this.getCatalogs();
1893
+ const catalogDeps = this.collectCatalogDependencies(packageJson);
1621
1894
  const workspaceDeps = this.collectDependencies(packageJson, WORKSPACE_PREFIX);
1622
1895
  const hasCatalogDeps = catalogDeps.length > 0;
1623
1896
  const hasWorkspaceDeps = workspaceDeps.length > 0;
1624
- if (hasCatalogDeps && 0 === Object.keys(catalog).length) {
1625
- const error = `Package contains ${CATALOG_PREFIX} dependencies but catalog configuration is missing`;
1626
- logger.error(error);
1627
- logger.error(" -> Catalog dependencies found:");
1628
- for (const { field, dependency, version } of catalogDeps)logger.error(` - ${field}.${dependency}: ${version}`);
1629
- throw new Error(error);
1897
+ if (hasCatalogDeps) {
1898
+ const missingCatalogs = this.findMissingCatalogs(catalogDeps, catalogs);
1899
+ if (missingCatalogs.size > 0) {
1900
+ const available = Object.keys(catalogs).join(", ") || "none";
1901
+ const error = `Catalog(s) not found: ${[
1902
+ ...missingCatalogs
1903
+ ].join(", ")}. Available: ${available}`;
1904
+ logger.error(error);
1905
+ logger.error(" -> Catalog dependencies found:");
1906
+ for (const { field, dependency, version, catalogName } of catalogDeps)if (missingCatalogs.has(catalogName)) logger.error(` - ${field}.${dependency}: ${version}`);
1907
+ throw new Error(error);
1908
+ }
1909
+ logger.info(`Resolving ${catalogDeps.length} ${CATALOG_PREFIX} dependencies`);
1630
1910
  }
1631
- if (hasCatalogDeps) logger.info(`Resolving ${catalogDeps.length} ${CATALOG_PREFIX} dependencies`);
1632
1911
  if (hasWorkspaceDeps) logger.info(`Resolving ${workspaceDeps.length} ${WORKSPACE_PREFIX} dependencies`);
1633
1912
  const result = await createExportableManifest(dir, packageJson, {
1634
- catalogs: {
1635
- default: catalog
1636
- }
1913
+ catalogs
1637
1914
  });
1638
- if (hasCatalogDeps || hasWorkspaceDeps) this.logResolvedDependencies(result, [
1639
- ...catalogDeps,
1640
- ...workspaceDeps
1641
- ], logger);
1915
+ if (hasCatalogDeps || hasWorkspaceDeps) {
1916
+ const allDeps = [
1917
+ ...catalogDeps.map((d)=>({
1918
+ field: d.field,
1919
+ dependency: d.dependency,
1920
+ source: "default" === d.catalogName ? "catalog:" : `catalog:${d.catalogName}`
1921
+ })),
1922
+ ...workspaceDeps.map((d)=>({
1923
+ field: d.field,
1924
+ dependency: d.dependency,
1925
+ source: "workspace:"
1926
+ }))
1927
+ ];
1928
+ this.logResolvedDependencies(result, allDeps, logger);
1929
+ }
1642
1930
  this.validateNoUnresolvedReferences(result, logger);
1643
1931
  return result;
1644
1932
  } catch (error) {
1645
1933
  const errorMessage = error instanceof Error ? error.message : String(error);
1646
- if (errorMessage.startsWith("Transformation failed:") || errorMessage.includes(`Package contains ${CATALOG_PREFIX} dependencies`)) throw error;
1647
- logger.error(`Failed to apply pnpm transformations for directory ${dir}: ${errorMessage}`);
1934
+ if (errorMessage.startsWith("Transformation failed:") || errorMessage.startsWith("Catalog(s) not found:")) throw error;
1935
+ logger.error(`Failed to apply transformations for directory ${dir}: ${errorMessage}`);
1648
1936
  if (errorMessage.includes("catalog")) {
1649
1937
  logger.error(` -> Catalog resolution failed - check workspace configuration and ${CATALOG_PREFIX} dependencies`);
1650
1938
  throw new Error("Catalog resolution failed");
@@ -1658,8 +1946,89 @@ class PnpmCatalog {
1658
1946
  throw new Error(`Manifest processing failed: ${errorMessage}`);
1659
1947
  }
1660
1948
  logger.error(" -> Cannot proceed with invalid package.json transformations");
1661
- throw new Error(`PNPM transformation failed: ${errorMessage}`);
1949
+ throw new Error(`Transformation failed: ${errorMessage}`);
1950
+ }
1951
+ }
1952
+ getWorkspaceInfo() {
1953
+ if (null !== this.cachedWorkspaceInfo) return this.cachedWorkspaceInfo;
1954
+ const info = getWorkspaceManagerAndRoot(process.cwd());
1955
+ this.cachedWorkspaceInfo = info ?? null;
1956
+ return this.cachedWorkspaceInfo;
1957
+ }
1958
+ async readPnpmCatalogs(workspaceRoot) {
1959
+ const lockfileCatalogs = await this.readPnpmLockfileCatalogs(workspaceRoot);
1960
+ if (Object.keys(lockfileCatalogs).length > 0) return lockfileCatalogs;
1961
+ return this.readPnpmWorkspaceCatalogs(workspaceRoot);
1962
+ }
1963
+ async readPnpmLockfileCatalogs(workspaceRoot) {
1964
+ try {
1965
+ const lockfile = await readWantedLockfile(workspaceRoot, {
1966
+ ignoreIncompatible: true
1967
+ });
1968
+ if (!lockfile?.catalogs) return {};
1969
+ return this.convertLockfileCatalogs(lockfile.catalogs);
1970
+ } catch {
1971
+ return {};
1972
+ }
1973
+ }
1974
+ async readPnpmWorkspaceCatalogs(workspaceRoot) {
1975
+ try {
1976
+ const manifest = await readWorkspaceManifest(workspaceRoot);
1977
+ return getCatalogsFromWorkspaceManifest(manifest);
1978
+ } catch {
1979
+ return {};
1980
+ }
1981
+ }
1982
+ readYarnCatalogs(workspaceRoot) {
1983
+ const catalogs = getCatalogs(workspaceRoot, "yarn");
1984
+ if (!catalogs) return {};
1985
+ return this.convertWorkspaceToolsCatalogs(catalogs);
1986
+ }
1987
+ convertLockfileCatalogs(snapshots) {
1988
+ const result = {};
1989
+ for (const [name, entries] of Object.entries(snapshots)){
1990
+ result[name] = {};
1991
+ for (const [dep, entry] of Object.entries(entries))result[name][dep] = entry.specifier;
1992
+ }
1993
+ return result;
1994
+ }
1995
+ convertWorkspaceToolsCatalogs(catalogs) {
1996
+ const result = {};
1997
+ if (catalogs.default) result.default = {
1998
+ ...catalogs.default
1999
+ };
2000
+ if (catalogs.named) for (const [name, catalog] of Object.entries(catalogs.named))result[name] = {
2001
+ ...catalog
2002
+ };
2003
+ return result;
2004
+ }
2005
+ collectCatalogDependencies(packageJson) {
2006
+ const deps = [];
2007
+ const fields = [
2008
+ "dependencies",
2009
+ "devDependencies",
2010
+ "peerDependencies",
2011
+ "optionalDependencies"
2012
+ ];
2013
+ for (const field of fields){
2014
+ const fieldDeps = packageJson[field];
2015
+ if (fieldDeps) for (const [dependency, version] of Object.entries(fieldDeps)){
2016
+ if ("string" != typeof version || !version.startsWith(CATALOG_PREFIX)) continue;
2017
+ const catalogName = parseCatalogProtocol(version);
2018
+ if (catalogName) deps.push({
2019
+ field,
2020
+ dependency,
2021
+ version,
2022
+ catalogName
2023
+ });
2024
+ }
1662
2025
  }
2026
+ return deps;
2027
+ }
2028
+ findMissingCatalogs(deps, catalogs) {
2029
+ const missing = new Set();
2030
+ for (const { catalogName } of deps)if (!catalogs[catalogName]) missing.add(catalogName);
2031
+ return missing;
1663
2032
  }
1664
2033
  collectDependencies(packageJson, prefix) {
1665
2034
  const deps = [];
@@ -1683,28 +2052,35 @@ class PnpmCatalog {
1683
2052
  }
1684
2053
  logResolvedDependencies(resultPkg, originalDeps, logger) {
1685
2054
  const allResolved = {};
1686
- for (const { field, dependency } of originalDeps){
2055
+ for (const { field, dependency, source } of originalDeps){
1687
2056
  const deps = resultPkg[field];
1688
2057
  if (deps?.[dependency]) {
1689
2058
  if (!allResolved[field]) allResolved[field] = [];
1690
2059
  allResolved[field].push({
1691
2060
  dependency,
1692
- version: deps[dependency]
2061
+ version: deps[dependency],
2062
+ source
1693
2063
  });
1694
2064
  }
1695
2065
  }
1696
2066
  if (Object.keys(allResolved).length > 0) {
1697
- logger.info("Resolved dependencies:");
2067
+ logger.global.info("Resolved dependencies:");
1698
2068
  for (const [field, deps] of Object.entries(allResolved)){
1699
- logger.info(`- ${field}:`);
1700
- for (const { dependency, version } of deps)logger.info(` ${dependency}: ${version}`);
2069
+ logger.global.info(`- ${field}:`);
2070
+ for (const { dependency, version, source } of deps)logger.global.info(` ${dependency}: ${version} (${source})`);
1701
2071
  }
1702
2072
  }
1703
2073
  }
1704
2074
  validateNoUnresolvedReferences(resultPkg, logger) {
2075
+ const unresolvedCatalog = this.collectCatalogDependencies(resultPkg);
2076
+ const unresolvedWorkspace = this.collectDependencies(resultPkg, WORKSPACE_PREFIX);
1705
2077
  const unresolvedDeps = [
1706
- ...this.collectDependencies(resultPkg, CATALOG_PREFIX),
1707
- ...this.collectDependencies(resultPkg, WORKSPACE_PREFIX)
2078
+ ...unresolvedCatalog.map((d)=>({
2079
+ field: d.field,
2080
+ dependency: d.dependency,
2081
+ version: d.version
2082
+ })),
2083
+ ...unresolvedWorkspace
1708
2084
  ];
1709
2085
  if (unresolvedDeps.length > 0) {
1710
2086
  const catalogRefs = unresolvedDeps.filter((dep)=>dep.version.startsWith(CATALOG_PREFIX));
@@ -1721,10 +2097,8 @@ class PnpmCatalog {
1721
2097
  }
1722
2098
  }
1723
2099
  }
1724
- let defaultInstance = null;
1725
- function getDefaultPnpmCatalog() {
1726
- if (!defaultInstance) defaultInstance = new PnpmCatalog();
1727
- return defaultInstance;
2100
+ function createWorkspaceCatalog() {
2101
+ return new WorkspaceCatalog();
1728
2102
  }
1729
2103
  function transformExportPath(path, processTSExports = true, collapseIndex = false) {
1730
2104
  let transformedPath = path;
@@ -1829,8 +2203,9 @@ function applyRslibTransformations(packageJson, originalPackageJson, processTSEx
1829
2203
  });
1830
2204
  return sort_package_json(processedManifest);
1831
2205
  }
1832
- async function applyPnpmTransformations(packageJson, dir = process.cwd()) {
1833
- return getDefaultPnpmCatalog().resolvePackageJson(packageJson, dir);
2206
+ async function applyPnpmTransformations(packageJson, dir = process.cwd(), catalog) {
2207
+ const workspaceCatalog = catalog ?? createWorkspaceCatalog();
2208
+ return workspaceCatalog.resolvePackageJson(packageJson, dir);
1834
2209
  }
1835
2210
  async function buildPackageJson(packageJson, isProduction = false, processTSExports = true, entrypoints, exportToOutputMap, bundle, transform) {
1836
2211
  let result;
@@ -1841,12 +2216,9 @@ async function buildPackageJson(packageJson, isProduction = false, processTSExpo
1841
2216
  if (transform) result = transform(result);
1842
2217
  return result;
1843
2218
  }
1844
- const PackageJsonTransformPlugin = (options = {})=>{
1845
- const cache = new Map();
1846
- return {
2219
+ const PackageJsonTransformPlugin = (options = {})=>({
1847
2220
  name: "package-json-processor",
1848
2221
  setup (api) {
1849
- api.expose("files-cache", cache);
1850
2222
  let filesArray = api.useExposed("files-array");
1851
2223
  if (!filesArray) {
1852
2224
  filesArray = new Set();
@@ -1895,225 +2267,7 @@ const PackageJsonTransformPlugin = (options = {})=>{
1895
2267
  }
1896
2268
  });
1897
2269
  }
1898
- };
1899
- };
1900
- class ImportGraph {
1901
- options;
1902
- sys;
1903
- program = null;
1904
- compilerOptions = null;
1905
- moduleResolutionCache = null;
1906
- constructor(options){
1907
- this.options = options;
1908
- this.sys = options.sys ?? typescript.sys;
1909
- }
1910
- traceFromEntries(entryPaths) {
1911
- const errors = [];
1912
- const visited = new Set();
1913
- const entries = [];
1914
- const initResult = this.initializeProgram();
1915
- if (!initResult.success) return {
1916
- files: [],
1917
- entries: [],
1918
- errors: [
1919
- initResult.error
1920
- ]
1921
- };
1922
- for (const entryPath of entryPaths){
1923
- const absolutePath = this.resolveEntryPath(entryPath);
1924
- if (!this.sys.fileExists(absolutePath)) {
1925
- errors.push({
1926
- type: "entry_not_found",
1927
- message: `Entry file not found: ${entryPath}`,
1928
- path: absolutePath
1929
- });
1930
- continue;
1931
- }
1932
- entries.push(absolutePath);
1933
- this.traceImports(absolutePath, visited, errors);
1934
- }
1935
- const files = Array.from(visited).filter((file)=>this.isSourceFile(file));
1936
- return {
1937
- files: files.sort(),
1938
- entries,
1939
- errors
1940
- };
1941
- }
1942
- traceFromPackageExports(packageJsonPath) {
1943
- const absolutePath = this.resolveEntryPath(packageJsonPath);
1944
- let packageJson;
1945
- try {
1946
- const content = this.sys.readFile(absolutePath);
1947
- if (!content) return {
1948
- files: [],
1949
- entries: [],
1950
- errors: [
1951
- {
1952
- type: "package_json_not_found",
1953
- message: `Failed to read package.json: File not found at ${absolutePath}`,
1954
- path: absolutePath
1955
- }
1956
- ]
1957
- };
1958
- packageJson = JSON.parse(content);
1959
- } catch (error) {
1960
- const message = error instanceof Error ? error.message : String(error);
1961
- return {
1962
- files: [],
1963
- entries: [],
1964
- errors: [
1965
- {
1966
- type: "package_json_parse_error",
1967
- message: `Failed to parse package.json: ${message}`,
1968
- path: absolutePath
1969
- }
1970
- ]
1971
- };
1972
- }
1973
- const extractor = new EntryExtractor();
1974
- const { entries } = extractor.extract(packageJson);
1975
- const packageDir = dirname(absolutePath);
1976
- const entryPaths = Object.values(entries).map((p)=>external_node_path_resolve(packageDir, p));
1977
- return this.traceFromEntries(entryPaths);
1978
- }
1979
- initializeProgram() {
1980
- if (this.program) return {
1981
- success: true
1982
- };
1983
- const configPath = this.findTsConfig();
1984
- if (!configPath) return {
1985
- success: false,
1986
- error: {
1987
- type: "tsconfig_not_found",
1988
- message: `No tsconfig.json found in ${this.options.rootDir}`,
1989
- path: this.options.rootDir
1990
- }
1991
- };
1992
- const configFile = typescript.readConfigFile(configPath, (path)=>this.sys.readFile(path));
1993
- if (configFile.error) {
1994
- const message = typescript.flattenDiagnosticMessageText(configFile.error.messageText, "\n");
1995
- return {
1996
- success: false,
1997
- error: {
1998
- type: "tsconfig_read_error",
1999
- message: `Failed to read tsconfig.json: ${message}`,
2000
- path: configPath
2001
- }
2002
- };
2003
- }
2004
- const parsed = typescript.parseJsonConfigFileContent(configFile.config, this.sys, dirname(configPath));
2005
- if (parsed.errors.length > 0) {
2006
- const messages = parsed.errors.map((e)=>typescript.flattenDiagnosticMessageText(e.messageText, "\n")).join("\n");
2007
- return {
2008
- success: false,
2009
- error: {
2010
- type: "tsconfig_parse_error",
2011
- message: `Failed to parse tsconfig.json: ${messages}`,
2012
- path: configPath
2013
- }
2014
- };
2015
- }
2016
- this.compilerOptions = parsed.options;
2017
- this.moduleResolutionCache = typescript.createModuleResolutionCache(this.options.rootDir, (fileName)=>fileName.toLowerCase(), this.compilerOptions);
2018
- const host = typescript.createCompilerHost(this.compilerOptions, true);
2019
- host.getCurrentDirectory = ()=>this.options.rootDir;
2020
- this.program = typescript.createProgram([], this.compilerOptions, host);
2021
- return {
2022
- success: true
2023
- };
2024
- }
2025
- findTsConfig() {
2026
- if (this.options.tsconfigPath) {
2027
- const customPath = isAbsolute(this.options.tsconfigPath) ? this.options.tsconfigPath : external_node_path_resolve(this.options.rootDir, this.options.tsconfigPath);
2028
- if (this.sys.fileExists(customPath)) return customPath;
2029
- return null;
2030
- }
2031
- const configPath = typescript.findConfigFile(this.options.rootDir, (path)=>this.sys.fileExists(path));
2032
- return configPath ?? null;
2033
- }
2034
- resolveEntryPath(entryPath) {
2035
- if (isAbsolute(entryPath)) return normalize(entryPath);
2036
- return normalize(external_node_path_resolve(this.options.rootDir, entryPath));
2037
- }
2038
- traceImports(filePath, visited, errors) {
2039
- const normalizedPath = normalize(filePath);
2040
- if (visited.has(normalizedPath)) return;
2041
- if (this.isExternalModule(normalizedPath)) return;
2042
- visited.add(normalizedPath);
2043
- const content = this.sys.readFile(normalizedPath);
2044
- if (!content) return void errors.push({
2045
- type: "file_read_error",
2046
- message: `Failed to read file: ${normalizedPath}`,
2047
- path: normalizedPath
2048
- });
2049
- const sourceFile = typescript.createSourceFile(normalizedPath, content, typescript.ScriptTarget.Latest, true);
2050
- const imports = this.extractImports(sourceFile);
2051
- for (const importPath of imports){
2052
- const resolved = this.resolveImport(importPath, normalizedPath);
2053
- if (resolved) this.traceImports(resolved, visited, errors);
2054
- }
2055
- }
2056
- extractImports(sourceFile) {
2057
- const imports = [];
2058
- const visit = (node)=>{
2059
- if (typescript.isImportDeclaration(node)) {
2060
- const specifier = node.moduleSpecifier;
2061
- if (typescript.isStringLiteral(specifier)) imports.push(specifier.text);
2062
- } else if (typescript.isExportDeclaration(node)) {
2063
- const specifier = node.moduleSpecifier;
2064
- if (specifier && typescript.isStringLiteral(specifier)) imports.push(specifier.text);
2065
- } else if (typescript.isCallExpression(node)) {
2066
- const expression = node.expression;
2067
- if (expression.kind === typescript.SyntaxKind.ImportKeyword && node.arguments.length > 0) {
2068
- const arg = node.arguments[0];
2069
- if (arg && typescript.isStringLiteral(arg)) imports.push(arg.text);
2070
- }
2071
- }
2072
- typescript.forEachChild(node, visit);
2073
- };
2074
- visit(sourceFile);
2075
- return imports;
2076
- }
2077
- resolveImport(specifier, fromFile) {
2078
- if (!specifier.startsWith(".") && !specifier.startsWith("/")) {
2079
- if (!this.compilerOptions?.paths || !Object.keys(this.compilerOptions.paths).length) return null;
2080
- }
2081
- if (!this.compilerOptions || !this.moduleResolutionCache) return null;
2082
- const resolved = typescript.resolveModuleName(specifier, fromFile, this.compilerOptions, this.sys, this.moduleResolutionCache);
2083
- if (resolved.resolvedModule) {
2084
- const resolvedPath = resolved.resolvedModule.resolvedFileName;
2085
- if (resolved.resolvedModule.isExternalLibraryImport) return null;
2086
- if (resolvedPath.endsWith(".d.ts")) {
2087
- const sourcePath = resolvedPath.replace(/\.d\.ts$/, ".ts");
2088
- if (this.sys.fileExists(sourcePath)) return sourcePath;
2089
- return null;
2090
- }
2091
- return resolvedPath;
2092
- }
2093
- return null;
2094
- }
2095
- isExternalModule(filePath) {
2096
- return filePath.includes("/node_modules/") || filePath.includes("\\node_modules\\");
2097
- }
2098
- isSourceFile(filePath) {
2099
- if (!filePath.endsWith(".ts") && !filePath.endsWith(".tsx")) return false;
2100
- if (filePath.endsWith(".d.ts")) return false;
2101
- if (filePath.includes(".test.") || filePath.includes(".spec.")) return false;
2102
- if (filePath.includes("/__test__/") || filePath.includes("\\__test__\\")) return false;
2103
- if (filePath.includes("/__tests__/") || filePath.includes("\\__tests__\\")) return false;
2104
- const excludePatterns = this.options.excludePatterns ?? [];
2105
- for (const pattern of excludePatterns)if (filePath.includes(pattern)) return false;
2106
- return true;
2107
- }
2108
- static fromEntries(entryPaths, options) {
2109
- const graph = new ImportGraph(options);
2110
- return graph.traceFromEntries(entryPaths);
2111
- }
2112
- static fromPackageExports(packageJsonPath, options) {
2113
- const graph = new ImportGraph(options);
2114
- return graph.traceFromPackageExports(packageJsonPath);
2115
- }
2116
- }
2270
+ });
2117
2271
  function formatLintResults(results, cwd) {
2118
2272
  if (0 === results.messages.length) return "";
2119
2273
  const lines = [];
@@ -2157,6 +2311,41 @@ function discoverFilesToLint(options, cwd) {
2157
2311
  isGlobPattern: false
2158
2312
  };
2159
2313
  }
2314
+ function discoverFilesToLintPerEntry(cwd) {
2315
+ const packageJsonPath = join(cwd, "package.json");
2316
+ let packageJson;
2317
+ try {
2318
+ packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
2319
+ } catch {
2320
+ return {
2321
+ perEntry: new Map(),
2322
+ errors: []
2323
+ };
2324
+ }
2325
+ const { entries } = new EntryExtractor().extract(packageJson);
2326
+ const graph = new ImportGraph({
2327
+ rootDir: cwd
2328
+ });
2329
+ const perEntry = new Map();
2330
+ const allErrors = [];
2331
+ for (const [entryName, sourcePath] of Object.entries(entries)){
2332
+ if (entryName.startsWith("bin/")) continue;
2333
+ const resolvedPath = sourcePath.startsWith(".") ? external_node_path_resolve(cwd, sourcePath) : sourcePath;
2334
+ const result = graph.traceFromEntries([
2335
+ resolvedPath
2336
+ ]);
2337
+ perEntry.set(entryName, {
2338
+ files: result.files,
2339
+ errors: result.errors,
2340
+ isGlobPattern: false
2341
+ });
2342
+ allErrors.push(...result.errors);
2343
+ }
2344
+ return {
2345
+ perEntry,
2346
+ errors: allErrors
2347
+ };
2348
+ }
2160
2349
  async function runTsDocLint(options, cwd) {
2161
2350
  const tsdocOptions = options.tsdoc ?? {};
2162
2351
  const persistConfig = options.persistConfig;
@@ -2273,6 +2462,112 @@ async function runTsDocLint(options, cwd) {
2273
2462
  }
2274
2463
  };
2275
2464
  }
2465
+ async function runTsDocLintPerEntry(options, cwd) {
2466
+ const tsdocOptions = options.tsdoc ?? {};
2467
+ const persistConfig = options.persistConfig;
2468
+ const shouldPersist = TsDocConfigBuilder.shouldPersist(persistConfig);
2469
+ const tsdocConfigOutputPath = TsDocConfigBuilder.getConfigPath(persistConfig, cwd);
2470
+ const skipCIValidation = false === persistConfig;
2471
+ const tsdocConfigPath = await TsDocConfigBuilder.writeConfigFile(tsdocOptions, dirname(tsdocConfigOutputPath), skipCIValidation);
2472
+ const eslintModule = await import("eslint");
2473
+ const tsParserModule = await import("@typescript-eslint/parser");
2474
+ const tsdocPluginModule = await import("eslint-plugin-tsdoc");
2475
+ const { ESLint } = eslintModule;
2476
+ const tsParser = tsParserModule.default ?? tsParserModule;
2477
+ const tsdocPlugin = tsdocPluginModule.default ?? tsdocPluginModule;
2478
+ const { perEntry, errors: allErrors } = discoverFilesToLintPerEntry(cwd);
2479
+ if (0 === perEntry.size) return {
2480
+ results: {
2481
+ errorCount: 0,
2482
+ warningCount: 0,
2483
+ messages: []
2484
+ },
2485
+ ...shouldPersist && {
2486
+ tsdocConfigPath
2487
+ },
2488
+ ...allErrors.length > 0 && {
2489
+ discoveryErrors: allErrors
2490
+ }
2491
+ };
2492
+ const eslint = new ESLint({
2493
+ cwd,
2494
+ overrideConfigFile: true,
2495
+ overrideConfig: [
2496
+ {
2497
+ ignores: [
2498
+ "**/node_modules/**",
2499
+ "**/dist/**",
2500
+ "**/coverage/**"
2501
+ ]
2502
+ },
2503
+ {
2504
+ files: [
2505
+ "**/*.ts",
2506
+ "**/*.tsx"
2507
+ ],
2508
+ languageOptions: {
2509
+ parser: tsParser
2510
+ },
2511
+ plugins: {
2512
+ tsdoc: tsdocPlugin
2513
+ },
2514
+ rules: {
2515
+ "tsdoc/syntax": "error"
2516
+ }
2517
+ }
2518
+ ]
2519
+ });
2520
+ const allMessages = [];
2521
+ let totalErrors = 0;
2522
+ let totalWarnings = 0;
2523
+ for (const [entryName, discovery] of perEntry){
2524
+ if (0 === discovery.files.length) continue;
2525
+ const exportKey = "index" === entryName ? "." : `./${entryName}`;
2526
+ core_logger.info(`${picocolors.dim("[tsdoc-lint]")} Validating "${exportKey}" (${discovery.files.length} file${1 === discovery.files.length ? "" : "s"})...`);
2527
+ const eslintResults = await eslint.lintFiles(discovery.files);
2528
+ let entryErrors = 0;
2529
+ let entryWarnings = 0;
2530
+ for (const result of eslintResults)for (const msg of result.messages){
2531
+ allMessages.push({
2532
+ filePath: result.filePath,
2533
+ line: msg.line,
2534
+ column: msg.column,
2535
+ message: msg.message,
2536
+ ruleId: msg.ruleId,
2537
+ severity: msg.severity
2538
+ });
2539
+ if (2 === msg.severity) {
2540
+ entryErrors++;
2541
+ totalErrors++;
2542
+ } else {
2543
+ entryWarnings++;
2544
+ totalWarnings++;
2545
+ }
2546
+ }
2547
+ if (0 === entryErrors && 0 === entryWarnings) core_logger.info(`${picocolors.dim("[tsdoc-lint]")} ${picocolors.green(`\u2713 "${exportKey}" - All TSDoc comments valid`)}`);
2548
+ else {
2549
+ const errorText = 1 === entryErrors ? "error" : "errors";
2550
+ const warningText = 1 === entryWarnings ? "warning" : "warnings";
2551
+ const parts = [];
2552
+ if (entryErrors > 0) parts.push(`${entryErrors} ${errorText}`);
2553
+ if (entryWarnings > 0) parts.push(`${entryWarnings} ${warningText}`);
2554
+ core_logger.warn(`${picocolors.dim("[tsdoc-lint]")} ${picocolors.red(`\u2717 "${exportKey}" - ${parts.join(", ")} found`)}`);
2555
+ }
2556
+ }
2557
+ return {
2558
+ results: {
2559
+ errorCount: totalErrors,
2560
+ warningCount: totalWarnings,
2561
+ messages: allMessages
2562
+ },
2563
+ ...shouldPersist && {
2564
+ tsdocConfigPath
2565
+ },
2566
+ ...allErrors.length > 0 && {
2567
+ discoveryErrors: allErrors
2568
+ }
2569
+ };
2570
+ }
2276
2571
  async function cleanupTsDocConfig(configPath) {
2277
2572
  if (!configPath) return;
2278
2573
  try {
@@ -2293,7 +2588,7 @@ const TsDocLintPlugin = (options = {})=>{
2293
2588
  const onError = options.onError ?? (isCI ? "throw" : "error");
2294
2589
  core_logger.info(`${picocolors.dim("[tsdoc-lint]")} Validating TSDoc comments...`);
2295
2590
  try {
2296
- const { results, tsdocConfigPath, discoveryErrors } = await runTsDocLint(options, cwd);
2591
+ const { results, tsdocConfigPath, discoveryErrors } = options.perEntry ? await runTsDocLintPerEntry(options, cwd) : await runTsDocLint(options, cwd);
2297
2592
  if (discoveryErrors && discoveryErrors.length > 0) for (const error of discoveryErrors)core_logger.warn(`${picocolors.dim("[tsdoc-lint]")} ${error.message}`);
2298
2593
  if (!TsDocConfigBuilder.shouldPersist(options.persistConfig)) tempTsDocConfigPath = tsdocConfigPath;
2299
2594
  if (0 === results.errorCount && 0 === results.warningCount) return void core_logger.info(`${picocolors.dim("[tsdoc-lint]")} ${picocolors.green("All TSDoc comments are valid")}`);
@@ -2350,7 +2645,8 @@ const VirtualEntryPlugin = (options)=>{
2350
2645
  "npm"
2351
2646
  ],
2352
2647
  externals: [],
2353
- apiModel: true
2648
+ apiModel: true,
2649
+ bundle: true
2354
2650
  };
2355
2651
  static mergeOptions(options = {}) {
2356
2652
  const copyPatterns = [
@@ -2370,6 +2666,7 @@ const VirtualEntryPlugin = (options)=>{
2370
2666
  targets: options.targets ?? NodeLibraryBuilder.DEFAULT_OPTIONS.targets,
2371
2667
  externals: options.externals ?? NodeLibraryBuilder.DEFAULT_OPTIONS.externals,
2372
2668
  apiModel: options.apiModel ?? NodeLibraryBuilder.DEFAULT_OPTIONS.apiModel,
2669
+ bundle: options.bundle ?? NodeLibraryBuilder.DEFAULT_OPTIONS.bundle,
2373
2670
  ...void 0 !== options.entry && {
2374
2671
  entry: options.entry
2375
2672
  },
@@ -2415,20 +2712,31 @@ const VirtualEntryPlugin = (options)=>{
2415
2712
  },
2416
2713
  ..."object" == typeof lintConfig ? lintConfig : {}
2417
2714
  };
2418
- plugins.push(TsDocLintPlugin(lintOptions));
2715
+ plugins.push(TsDocLintPlugin({
2716
+ ...lintOptions,
2717
+ ...false === options.bundle && {
2718
+ perEntry: true
2719
+ }
2720
+ }));
2419
2721
  }
2420
- if (!options.entry) plugins.push(AutoEntryPlugin(null != options.exportsAsIndexes ? {
2421
- exportsAsIndexes: options.exportsAsIndexes
2422
- } : void 0));
2722
+ if (!options.entry) plugins.push(AutoEntryPlugin({
2723
+ ...null != options.exportsAsIndexes && {
2724
+ exportsAsIndexes: options.exportsAsIndexes
2725
+ },
2726
+ ...false === options.bundle && {
2727
+ bundleless: true
2728
+ }
2729
+ }));
2423
2730
  const userTransform = options.transform;
2424
2731
  const transformFn = userTransform ? (pkg)=>userTransform({
2425
2732
  target,
2426
2733
  pkg
2427
2734
  }) : void 0;
2428
2735
  const libraryFormat = options.format ?? "esm";
2736
+ const collapseIndex = (options.bundle ?? true) || !(options.exportsAsIndexes ?? false);
2429
2737
  plugins.push(PackageJsonTransformPlugin({
2430
2738
  forcePrivate: "dev" === target,
2431
- bundle: true,
2739
+ bundle: collapseIndex,
2432
2740
  target,
2433
2741
  format: libraryFormat,
2434
2742
  ...transformFn && {
@@ -2441,16 +2749,32 @@ const VirtualEntryPlugin = (options)=>{
2441
2749
  transformFiles: options.transformFiles
2442
2750
  }
2443
2751
  }));
2444
- if (options.plugins) plugins.push(...options.plugins);
2752
+ plugins.push(...options.plugins);
2445
2753
  const outputDir = `dist/${target}`;
2446
- const entry = options.entry;
2754
+ let entry = options.entry;
2755
+ if (false === options.bundle && !entry) {
2756
+ const cwd = process.cwd();
2757
+ const packageJsonPath = join(cwd, "package.json");
2758
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
2759
+ const { entries } = new EntryExtractor().extract(packageJson);
2760
+ const graph = new ImportGraph({
2761
+ rootDir: cwd
2762
+ });
2763
+ const result = graph.traceFromEntries(Object.values(entries));
2764
+ const tracedEntries = {};
2765
+ for (const file of result.files){
2766
+ const relPath = relative(cwd, file);
2767
+ tracedEntries[relPath] = `./${relPath}`;
2768
+ }
2769
+ entry = tracedEntries;
2770
+ }
2447
2771
  const apiModelForTarget = "npm" === target ? options.apiModel : void 0;
2448
2772
  plugins.push(DtsPlugin({
2449
2773
  ...options.tsconfigPath && {
2450
2774
  tsconfigPath: options.tsconfigPath
2451
2775
  },
2452
2776
  abortOnError: true,
2453
- bundle: true,
2777
+ bundle: options.bundle ?? true,
2454
2778
  ...options.dtsBundledPackages && {
2455
2779
  bundledPackages: options.dtsBundledPackages
2456
2780
  },
@@ -2462,12 +2786,16 @@ const VirtualEntryPlugin = (options)=>{
2462
2786
  }));
2463
2787
  const lib = {
2464
2788
  id: target,
2465
- outBase: outputDir,
2789
+ outBase: false === options.bundle ? "src" : outputDir,
2466
2790
  output: {
2467
2791
  target: "node",
2468
2792
  module: true,
2469
2793
  cleanDistPath: true,
2470
2794
  sourceMap: "dev" === target,
2795
+ // Prevent @preserve comments from generating .LICENSE.txt files
2796
+ ...false === options.bundle && {
2797
+ legalComments: "inline"
2798
+ },
2471
2799
  distPath: {
2472
2800
  root: outputDir
2473
2801
  },
@@ -2482,7 +2810,7 @@ const VirtualEntryPlugin = (options)=>{
2482
2810
  experiments: {
2483
2811
  advancedEsm: "esm" === libraryFormat
2484
2812
  },
2485
- bundle: true,
2813
+ bundle: options.bundle ?? true,
2486
2814
  plugins,
2487
2815
  source: {
2488
2816
  ...options.tsconfigPath && {
@@ -2507,10 +2835,13 @@ const VirtualEntryPlugin = (options)=>{
2507
2835
  const virtualByFormat = new Map();
2508
2836
  for (const [outputName, config] of Object.entries(virtualEntries)){
2509
2837
  const entryFormat = config.format ?? libraryFormat;
2510
- if (!virtualByFormat.has(entryFormat)) virtualByFormat.set(entryFormat, new Map());
2838
+ let formatMap = virtualByFormat.get(entryFormat);
2839
+ if (!formatMap) {
2840
+ formatMap = new Map();
2841
+ virtualByFormat.set(entryFormat, formatMap);
2842
+ }
2511
2843
  const entryName = outputName.replace(/\.(c|m)?js$/, "");
2512
- const formatMap = virtualByFormat.get(entryFormat);
2513
- if (formatMap) formatMap.set(entryName, config.source);
2844
+ formatMap.set(entryName, config.source);
2514
2845
  }
2515
2846
  for (const [format, entries] of virtualByFormat){
2516
2847
  const virtualEntryNames = new Set(entries.keys());
@@ -2584,4 +2915,4 @@ const VirtualEntryPlugin = (options)=>{
2584
2915
  }
2585
2916
  }
2586
2917
  }
2587
- export { AutoEntryPlugin, DtsPlugin, EntryExtractor, FilesArrayPlugin, ImportGraph, NodeLibraryBuilder, PackageJsonTransformPlugin, TsDocConfigBuilder, TsDocLintPlugin, TsconfigResolver, TsconfigResolverError, VirtualEntryPlugin, extractEntriesFromPackageJson };
2918
+ export { AutoEntryPlugin, DtsPlugin, EntryExtractor, FilesArrayPlugin, ImportGraph, NodeLibraryBuilder, PackageJsonTransformPlugin, TsDocConfigBuilder, TsDocLintPlugin, TsconfigResolver, TsconfigResolverError, VirtualEntryPlugin };