@d1g1tal/tsbuild 1.0.3 → 1.1.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.
@@ -78,7 +78,7 @@ var ConfigurationError = class extends BuildError {
78
78
  this.name = "ConfigurationError";
79
79
  }
80
80
  };
81
- var UnsupportedSyntaxError = class extends Error {
81
+ var UnsupportedSyntaxError = class extends BundleError {
82
82
  /**
83
83
  * Creates an instance of UnsupportedSyntaxError.
84
84
  * @param node The node with unsupported syntax
@@ -88,6 +88,7 @@ var UnsupportedSyntaxError = class extends Error {
88
88
  const syntaxKindName = SyntaxKind[node.kind] ?? `Unknown(${node.kind})`;
89
89
  const nodeText = node.getText ? node.getText().slice(0, 100) : "<no text>";
90
90
  super(`${message}: ${syntaxKindName} - "${nodeText}"`);
91
+ this.name = "UnsupportedSyntaxError";
91
92
  }
92
93
  };
93
94
  var castError = (exception) => {
@@ -557,7 +558,7 @@ var DeclarationProcessor = class _DeclarationProcessor {
557
558
  let hasDeclare = false;
558
559
  for (const modifier of node.modifiers ?? []) {
559
560
  if (modifier.kind === SyntaxKind2.DefaultKeyword || modifier.kind === SyntaxKind2.ExportKeyword) {
560
- code.remove(modifier.getStart(), modifier.getEnd() + 1);
561
+ code.remove(modifier.getStart(), modifier.getEnd() + getTrailingWhitespaceLength(modifier.getEnd(), node.getEnd()));
561
562
  } else if (modifier.kind === SyntaxKind2.DeclareKeyword) {
562
563
  hasDeclare = true;
563
564
  }
@@ -828,8 +829,10 @@ function mergeImports(imports) {
828
829
  return result;
829
830
  }
830
831
  var DeclarationBundler = class {
831
- /** d.ts Bundle Options (internally mutable for caching - stores pre-processed declarations) */
832
+ /** Project declaration files from in-memory FileManager */
832
833
  declarationFiles = /* @__PURE__ */ new Map();
834
+ /** External declaration files resolved from disk (node_modules) when resolve is enabled */
835
+ externalDeclarationFiles = /* @__PURE__ */ new Map();
833
836
  /** d.ts Bundle Options */
834
837
  options;
835
838
  /** WeakMap cache for identifier collection to avoid re-parsing same source files */
@@ -841,10 +844,10 @@ var DeclarationBundler = class {
841
844
  // Create a proper module resolution host that supports both in-memory files and disk files
842
845
  moduleResolutionHost = {
843
846
  fileExists: (fileName) => {
844
- return this.declarationFiles.has(fileName) || this.options.resolve && sys.fileExists(fileName);
847
+ return this.declarationFiles.has(fileName) || this.externalDeclarationFiles.has(fileName) || this.options.resolve && sys.fileExists(fileName);
845
848
  },
846
849
  readFile: (fileName) => {
847
- const cached = this.declarationFiles.get(fileName);
850
+ const cached = this.declarationFiles.get(fileName) ?? this.externalDeclarationFiles.get(fileName);
848
851
  if (cached) {
849
852
  return cached.code;
850
853
  }
@@ -854,7 +857,7 @@ var DeclarationBundler = class {
854
857
  const rawContent = sys.readFile(fileName, Encoding.utf8);
855
858
  if (rawContent !== void 0) {
856
859
  const preProcessOutput = DeclarationProcessor.preProcess(createSourceFile(fileName, rawContent, ScriptTarget.Latest, true));
857
- this.declarationFiles.set(fileName, preProcessOutput);
860
+ this.externalDeclarationFiles.set(fileName, preProcessOutput);
858
861
  return preProcessOutput.code;
859
862
  }
860
863
  return void 0;
@@ -888,6 +891,14 @@ var DeclarationBundler = class {
888
891
  }
889
892
  this.options = dtsBundleOptions;
890
893
  }
894
+ /**
895
+ * Clears external declaration files and module resolution cache to free memory.
896
+ * Called after all entry points have been bundled.
897
+ */
898
+ clearExternalFiles() {
899
+ this.externalDeclarationFiles.clear();
900
+ this.moduleResolutionCache.clear();
901
+ }
891
902
  /**
892
903
  * Convert a source file path to its corresponding declaration file path
893
904
  * @param sourcePath - Absolute path to a source file (.ts, .tsx)
@@ -984,7 +995,7 @@ var DeclarationBundler = class {
984
995
  return;
985
996
  }
986
997
  visited.add(path);
987
- const cached = this.declarationFiles.get(path);
998
+ const cached = this.declarationFiles.get(path) ?? this.externalDeclarationFiles.get(path);
988
999
  if (cached === void 0) {
989
1000
  return;
990
1001
  }
@@ -1001,7 +1012,7 @@ var DeclarationBundler = class {
1001
1012
  if (resolvedPath?.includes(nodeModules) && !this.matchesPattern(specifier, this.options.noExternal)) {
1002
1013
  continue;
1003
1014
  }
1004
- if (resolvedPath && this.declarationFiles.has(resolvedPath)) {
1015
+ if (resolvedPath && (this.declarationFiles.has(resolvedPath) || this.externalDeclarationFiles.has(resolvedPath))) {
1005
1016
  module.imports.add(resolvedPath);
1006
1017
  bundledSpecs.push(specifier);
1007
1018
  visit(resolvedPath);
@@ -1024,7 +1035,11 @@ var DeclarationBundler = class {
1024
1035
  const visited = /* @__PURE__ */ new Set();
1025
1036
  const visiting = /* @__PURE__ */ new Set();
1026
1037
  const visit = (path) => {
1027
- if (visited.has(path) || visiting.has(path)) {
1038
+ if (visited.has(path)) {
1039
+ return;
1040
+ }
1041
+ if (visiting.has(path)) {
1042
+ Logger.warn(`Circular dependency detected: ${Paths.relative(this.options.currentDirectory, path)}`);
1028
1043
  return;
1029
1044
  }
1030
1045
  visiting.add(path);
@@ -1203,9 +1218,15 @@ var DeclarationBundler = class {
1203
1218
  for (const [name, sourcesSet] of declarationSources) {
1204
1219
  if (sourcesSet.size > 1) {
1205
1220
  const sources = Array.from(sourcesSet);
1206
- sources.slice(1).forEach((modulePath, index) => {
1207
- renameMap.set(`${name}:${modulePath}`, `${name}$${index + 1}`);
1208
- });
1221
+ let suffix = 1;
1222
+ for (const modulePath of sources.slice(1)) {
1223
+ let candidate = `${name}$${suffix}`;
1224
+ while (declarationSources.has(candidate)) {
1225
+ candidate = `${name}$${++suffix}`;
1226
+ }
1227
+ renameMap.set(`${name}:${modulePath}`, candidate);
1228
+ suffix++;
1229
+ }
1209
1230
  }
1210
1231
  }
1211
1232
  for (const { path, typeReferences, fileReferences, sourceFile, code, identifiers } of sortedModules) {
@@ -1316,7 +1337,9 @@ async function bundleDeclarations(options) {
1316
1337
  await writeFile2(outPath, content, Encoding.utf8);
1317
1338
  return { path: Paths.relative(options.currentDirectory, outPath), size: content.length };
1318
1339
  });
1319
- return Promise.all(bundleTasks);
1340
+ const results = await Promise.all(bundleTasks);
1341
+ dtsBundler.clearExternalFiles();
1342
+ return results;
1320
1343
  }
1321
1344
 
1322
1345
  // src/plugins/output.ts
@@ -1815,6 +1838,97 @@ var IncrementalBuildCache = class {
1815
1838
  }
1816
1839
  };
1817
1840
 
1841
+ // src/entry-points.ts
1842
+ var importConditions = ["import", "default"];
1843
+ var outputToSourceExtension = /* @__PURE__ */ new Map([
1844
+ [".js", ".ts"],
1845
+ [".mjs", ".ts"],
1846
+ [".jsx", ".tsx"],
1847
+ [".d.ts", ".ts"],
1848
+ [".d.mts", ".ts"]
1849
+ ]);
1850
+ function outputToSourcePath(outputPath, outDir, sourceDir) {
1851
+ const normalizedOutput = outputPath.replace(/^\.\//, "");
1852
+ const normalizedOutDir = outDir.replace(/^\.\//, "").replace(/\/$/, "");
1853
+ if (!normalizedOutput.startsWith(normalizedOutDir + "/") && normalizedOutput !== normalizedOutDir) {
1854
+ return void 0;
1855
+ }
1856
+ const relativePortion = normalizedOutput.slice(normalizedOutDir.length + 1);
1857
+ for (const [outExt, srcExt] of outputToSourceExtension) {
1858
+ if (relativePortion.endsWith(outExt)) {
1859
+ const stem = relativePortion.slice(0, -outExt.length);
1860
+ return `./${sourceDir}/${stem}${srcExt}`;
1861
+ }
1862
+ }
1863
+ return void 0;
1864
+ }
1865
+ function resolveConditionalExport(exportValue) {
1866
+ if (typeof exportValue === "string") {
1867
+ return exportValue;
1868
+ }
1869
+ for (const condition of importConditions) {
1870
+ const value = exportValue[condition];
1871
+ if (typeof value === "string") {
1872
+ return value;
1873
+ }
1874
+ }
1875
+ return void 0;
1876
+ }
1877
+ function subpathToEntryName(subpath, packageName) {
1878
+ if (subpath === ".") {
1879
+ return packageName ?? "index";
1880
+ }
1881
+ const withoutPrefix = subpath.replace(/^\.\//, "");
1882
+ const lastSegment = withoutPrefix.lastIndexOf("/");
1883
+ return lastSegment === -1 ? withoutPrefix : withoutPrefix.slice(lastSegment + 1);
1884
+ }
1885
+ function inferEntryPoints(packageJson, outDir, sourceDir = "src") {
1886
+ const entryPoints = {};
1887
+ if (packageJson.exports !== void 0) {
1888
+ if (typeof packageJson.exports === "string") {
1889
+ const sourcePath = outputToSourcePath(packageJson.exports, outDir, sourceDir);
1890
+ if (sourcePath) {
1891
+ entryPoints[packageJson.name ?? "index"] = sourcePath;
1892
+ }
1893
+ } else {
1894
+ for (const [subpath, exportValue] of Object.entries(packageJson.exports)) {
1895
+ if (subpath.includes("*")) {
1896
+ continue;
1897
+ }
1898
+ const outputPath = resolveConditionalExport(exportValue);
1899
+ if (outputPath === void 0) {
1900
+ continue;
1901
+ }
1902
+ const sourcePath = outputToSourcePath(outputPath, outDir, sourceDir);
1903
+ if (sourcePath) {
1904
+ entryPoints[subpathToEntryName(subpath, packageJson.name)] = sourcePath;
1905
+ }
1906
+ }
1907
+ }
1908
+ }
1909
+ if (packageJson.bin !== void 0) {
1910
+ const binEntries = typeof packageJson.bin === "string" ? { [packageJson.name ?? "cli"]: packageJson.bin } : packageJson.bin;
1911
+ for (const [name, outputPath] of Object.entries(binEntries)) {
1912
+ if (entryPoints[name] === void 0) {
1913
+ const sourcePath = outputToSourcePath(outputPath, outDir, sourceDir);
1914
+ if (sourcePath) {
1915
+ entryPoints[name] = sourcePath;
1916
+ }
1917
+ }
1918
+ }
1919
+ }
1920
+ if (Object.keys(entryPoints).length === 0) {
1921
+ const legacyPath = packageJson.module ?? packageJson.main;
1922
+ if (legacyPath !== void 0) {
1923
+ const sourcePath = outputToSourcePath(legacyPath, outDir, sourceDir);
1924
+ if (sourcePath) {
1925
+ entryPoints["index"] = sourcePath;
1926
+ }
1927
+ }
1928
+ }
1929
+ return Object.keys(entryPoints).length > 0 ? entryPoints : void 0;
1930
+ }
1931
+
1818
1932
  // src/type-script-project.ts
1819
1933
  import { build as esbuild, formatMessages } from "esbuild";
1820
1934
  import { sys as sys3, createIncrementalProgram, formatDiagnostics, formatDiagnosticsWithColorAndContext, parseJsonConfigFileContent, readConfigFile, findConfigFile } from "typescript";
@@ -1840,6 +1954,7 @@ var _TypeScriptProject = class _TypeScriptProject {
1840
1954
  __publicField(this, "pendingChanges", []);
1841
1955
  __publicField(this, "buildDependencies", /* @__PURE__ */ new Set());
1842
1956
  __publicField(this, "dependencyPaths");
1957
+ __publicField(this, "packageJson");
1843
1958
  this.directory = Paths.absolute(directory);
1844
1959
  this.configuration = _TypeScriptProject.resolveConfiguration(this.directory, options);
1845
1960
  const { buildCache, rootNames, projectReferences, configFileParsingDiagnostics, tsbuild: { entryPoints, ...tsbuildOptions }, compilerOptions: { target, outDir } } = this.configuration;
@@ -1858,7 +1973,7 @@ var _TypeScriptProject = class _TypeScriptProject {
1858
1973
  return Files.empty(this.buildConfiguration.outDir);
1859
1974
  }
1860
1975
  async build() {
1861
- Logger.header(`\u{1F680} tsbuild v${"1.0.3"}${this.configuration.compilerOptions.incremental ? " [incremental]" : ""}`);
1976
+ Logger.header(`\u{1F680} tsbuild v${"1.1.0"}${this.configuration.compilerOptions.incremental ? " [incremental]" : ""}`);
1862
1977
  try {
1863
1978
  const processes = [];
1864
1979
  const filesWereEmitted = await this.typeCheck();
@@ -2073,6 +2188,19 @@ var _TypeScriptProject = class _TypeScriptProject {
2073
2188
  const bundle = typeScriptOptions.tsbuild?.bundle ?? configResult.config.tsbuild?.bundle ?? true;
2074
2189
  const platform2 = configResult.config.compilerOptions?.lib?.some(domPredicate) ? Platform.BROWSER : Platform.NODE;
2075
2190
  const noExternal = typeScriptOptions.tsbuild?.noExternal ?? configResult.config.tsbuild?.noExternal ?? [];
2191
+ const hasExplicitEntryPoints = typeScriptOptions.tsbuild?.entryPoints !== void 0 || configResult.config.tsbuild?.entryPoints !== void 0;
2192
+ let inferredEntryPoints;
2193
+ if (!hasExplicitEntryPoints && bundle) {
2194
+ const packageJsonContent = sys3.readFile(Paths.join(directory, "package.json"));
2195
+ if (packageJsonContent) {
2196
+ try {
2197
+ const pkgJson = JSON.parse(packageJsonContent);
2198
+ const outDir = typeScriptOptions.compilerOptions?.outDir ?? configResult.config.compilerOptions?.outDir ?? defaultOutDirectory;
2199
+ inferredEntryPoints = inferEntryPoints(pkgJson, outDir);
2200
+ } catch {
2201
+ }
2202
+ }
2203
+ }
2076
2204
  const defaultTsbuildConfig = {
2077
2205
  splitting: bundle,
2078
2206
  minify: false,
@@ -2084,7 +2212,7 @@ var _TypeScriptProject = class _TypeScriptProject {
2084
2212
  platform: platform2,
2085
2213
  dts: { resolve: platform2 !== Platform.NODE, entryPoints: bundle ? void 0 : [] },
2086
2214
  watch: { enabled: false, recursive: true, ignoreInitial: true, persistent: true },
2087
- entryPoints: bundle ? { [defaultEntryPoint]: defaultEntryFile } : { src: defaultSourceDirectory }
2215
+ entryPoints: inferredEntryPoints ?? (bundle ? { [defaultEntryPoint]: defaultEntryFile } : { src: defaultSourceDirectory })
2088
2216
  };
2089
2217
  const baseConfig = {
2090
2218
  ...configResult.config,
@@ -2140,11 +2268,14 @@ var _TypeScriptProject = class _TypeScriptProject {
2140
2268
  }
2141
2269
  /**
2142
2270
  * Gets the project dependency paths, cached after first call.
2271
+ * Reads package.json and caches it for reuse.
2143
2272
  * @returns A promise that resolves to an array of project dependency paths.
2144
2273
  */
2145
2274
  getProjectDependencyPaths() {
2146
2275
  return this.dependencyPaths ??= Files.read(Paths.absolute(this.directory, "package.json")).then((content) => {
2147
- const { dependencies = {}, peerDependencies = {} } = Json.parse(content);
2276
+ const packageJson = Json.parse(content);
2277
+ this.packageJson = packageJson;
2278
+ const { dependencies = {}, peerDependencies = {} } = packageJson;
2148
2279
  return [.../* @__PURE__ */ new Set([...Object.keys(dependencies), ...Object.keys(peerDependencies)])];
2149
2280
  });
2150
2281
  }
package/dist/index.d.ts CHANGED
@@ -258,6 +258,7 @@ declare class TypeScriptProject implements Closable {
258
258
  private readonly pendingChanges;
259
259
  private readonly buildDependencies;
260
260
  private dependencyPaths?;
261
+ private packageJson?;
261
262
  /**
262
263
  * Creates a TypeScript project and prepares it for building/bundling.
263
264
  * @param directory - Project root directory (defaults to current working directory)
@@ -319,6 +320,7 @@ declare class TypeScriptProject implements Closable {
319
320
  private getEntryPoints;
320
321
  /**
321
322
  * Gets the project dependency paths, cached after first call.
323
+ * Reads package.json and caches it for reuse.
322
324
  * @returns A promise that resolves to an array of project dependency paths.
323
325
  */
324
326
  private getProjectDependencyPaths;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  TypeScriptProject
3
- } from "./7SPSROV3.js";
3
+ } from "./BLUMG6XT.js";
4
4
  import "./VMWNQL2J.js";
5
5
  export {
6
6
  TypeScriptProject
package/dist/tsbuild.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  BuildError,
4
4
  TypeScriptProject
5
- } from "./7SPSROV3.js";
5
+ } from "./BLUMG6XT.js";
6
6
  import "./VMWNQL2J.js";
7
7
 
8
8
  // src/tsbuild.ts
@@ -30,7 +30,7 @@ if (help) {
30
30
  process.exit(0);
31
31
  }
32
32
  if (version) {
33
- console.log("1.0.3");
33
+ console.log("1.1.0");
34
34
  process.exit(0);
35
35
  }
36
36
  var typeScriptOptions = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@d1g1tal/tsbuild",
3
- "version": "1.0.3",
3
+ "version": "1.1.0",
4
4
  "packageManager": "pnpm@10.29.3",
5
5
  "description": "A fast, ESM-only TypeScript build tool combining the TypeScript API for type checking and declaration generation, esbuild for bundling, and SWC for decorator metadata.",
6
6
  "type": "module",
package/schema.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "additionalProperties": false,
17
17
  "properties": {
18
18
  "entryPoints": {
19
- "markdownDescription": "Files that each serve as an input to the bundling algorithm. Can be an array of paths or an object mapping output names to input paths.",
19
+ "markdownDescription": "Files that each serve as an input to the bundling algorithm. Can be an array of paths or an object mapping output names to input paths.\n\nWhen omitted, tsbuild auto-infers entry points from the `exports`, `bin`, `main`, or `module` fields in `package.json` by reverse-mapping output paths to source paths.",
20
20
  "oneOf": [
21
21
  {
22
22
  "type": "array",