@d1g1tal/tsbuild 1.6.3 → 1.6.4

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/CHANGELOG.md CHANGED
@@ -1,3 +1,32 @@
1
+ ## [1.6.4](https://github.com/D1g1talEntr0py/tsbuild/compare/v1.6.3...v1.6.4) (2026-03-21)
2
+
3
+ ### Bug Fixes
4
+
5
+ * **logging:** bypass formatting for empty error message arrays (7ced5ad268029ee763bafdfeda405c50faec8ad3)
6
+ - Check for messages length before invoking the format function
7
+ - Preclude unnecessary iteration over empty diagnostic outputs
8
+ - Prevent empty lines from being emitted to the console log stream
9
+
10
+
11
+ ### Performance Improvements
12
+
13
+ * **plugins:** optimize build plugins and file operations (d5669224bff868001baf43a99efb409ec33d521e)
14
+ - Cache SWC transformFile reference lazy-loaded for decorator metadata
15
+ - Build reusable O(1) matchers for external modules string and RegExp patterns
16
+ - Extract package names properly handling scoped and unscoped module paths
17
+ - Cache shared TextEncoder and TextDecoder instances for output generation
18
+ - Preserve shebangs and set correct execute permissions on output scripts
19
+ - Optimize extension rewriting to only trigger string replacements when modified
20
+
21
+
22
+ ### Miscellaneous Chores
23
+
24
+ * **deps:** update watchr and eslint dependencies (619d559159bb358cef75b36e99223999a0c6da57)
25
+ - Update @d1g1tal/watchr package to version 1.0.4
26
+ - Update eslint package to version 10.1.0
27
+ - Synchronize pnpm-lock.yaml with new dependency versions
28
+ - Update typescript-eslint plugin and parser dependencies in lockfile
29
+
1
30
  ## [1.6.3](https://github.com/D1g1talEntr0py/tsbuild/compare/v1.6.2...v1.6.3) (2026-03-18)
2
31
 
3
32
  ### Bug Fixes
@@ -18,6 +18,7 @@ var swcOptions = {
18
18
  configFile: false,
19
19
  swcrc: false
20
20
  };
21
+ var swcTransformFile;
21
22
  var swcDecoratorMetadataPlugin = {
22
23
  name: "esbuild:swc-decorator-metadata",
23
24
  /**
@@ -29,8 +30,8 @@ var swcDecoratorMetadataPlugin = {
29
30
  setup(build) {
30
31
  build.initialOptions.keepNames = true;
31
32
  build.onLoad({ filter: typeScriptExtensionExpression }, async ({ path }) => {
32
- const { transformFile } = await import("@swc/core");
33
- const result = await transformFile(path, swcOptions);
33
+ swcTransformFile ??= (await import("@swc/core")).transformFile;
34
+ const result = await swcTransformFile(path, swcOptions);
34
35
  if (result.map) {
35
36
  const sources = [];
36
37
  for (const source of Json.parse(result.map).sources) {
@@ -625,10 +625,10 @@ var DeclarationProcessor = class _DeclarationProcessor {
625
625
  }
626
626
  } else {
627
627
  inlineTypePattern.lastIndex = 0;
628
- let match2;
628
+ let match;
629
629
  const replacements = [];
630
- while ((match2 = inlineTypePattern.exec(code.slice(node.getStart(), node.getEnd()))) !== null) {
631
- const typeKeywordStart = node.getStart() + match2.index + match2[1].length;
630
+ while ((match = inlineTypePattern.exec(code.slice(node.getStart(), node.getEnd()))) !== null) {
631
+ const typeKeywordStart = node.getStart() + match.index + match[1].length;
632
632
  const typeKeywordEnd = typeKeywordStart + "type".length;
633
633
  replacements.push({ start: typeKeywordStart, end: typeKeywordEnd + getTrailingWhitespaceLength(typeKeywordEnd, node.getEnd()) });
634
634
  }
@@ -826,9 +826,9 @@ function mergeImports(imports) {
826
826
  const moduleImports = /* @__PURE__ */ new Map();
827
827
  const nonMergeableImports = [];
828
828
  for (const importStatement of imports) {
829
- const match2 = importPattern.exec(importStatement);
830
- if (match2) {
831
- const [, namesString, moduleSpecifier] = match2;
829
+ const match = importPattern.exec(importStatement);
830
+ if (match) {
831
+ const [, namesString, moduleSpecifier] = match;
832
832
  const isType = importStatement.includes("import type");
833
833
  const key = `${isType ? "type:" : ""}${moduleSpecifier}`;
834
834
  if (!moduleImports.has(key)) {
@@ -1390,19 +1390,27 @@ async function bundleDeclarations(options) {
1390
1390
 
1391
1391
  // src/plugins/output.ts
1392
1392
  import { extname } from "node:path";
1393
- var FileMode = { READ_WRITE: 438, READ_WRITE_EXECUTE: 493 };
1393
+ var textEncoder = new TextEncoder();
1394
+ var textDecoder = new TextDecoder();
1395
+ var localFileIdentifier = /\.[a-z]+$/i;
1394
1396
  var relativeSpecifierPattern = /(from\s*['"])(\.\.?\/[^'"]*?)(['"])/g;
1397
+ var FileMode = { READ_WRITE: 438, READ_WRITE_EXECUTE: 493 };
1395
1398
  function rewriteRelativeSpecifiers(code) {
1396
- return code.replace(relativeSpecifierPattern, (_, before, path, after) => {
1397
- if (/\.[a-z]+$/i.test(path)) return before + path + after;
1398
- return `${before}${path}.js${after}`;
1399
- });
1399
+ return code.replace(relativeSpecifierPattern, (_, before, path, after) => localFileIdentifier.test(path) ? before + path + after : `${before}${path}.js${after}`);
1400
1400
  }
1401
1401
  async function fileMapper({ path, contents }) {
1402
- const isJs = extname(path) === FileExtension.JS;
1403
- const mode = isJs && contents[0] === 35 && contents[1] === 33 ? FileMode.READ_WRITE_EXECUTE : FileMode.READ_WRITE;
1404
- const finalContents = isJs ? new TextEncoder().encode(rewriteRelativeSpecifiers(new TextDecoder().decode(contents))) : contents;
1405
- return Files.write(path, finalContents, { mode });
1402
+ if (extname(path) !== FileExtension.JS) {
1403
+ return Files.write(path, contents, { mode: FileMode.READ_WRITE });
1404
+ }
1405
+ let rewritten = false;
1406
+ const result = textDecoder.decode(contents).replace(relativeSpecifierPattern, (_, before, specPath, after) => {
1407
+ if (localFileIdentifier.test(specPath)) {
1408
+ return before + specPath + after;
1409
+ }
1410
+ rewritten = true;
1411
+ return `${before}${specPath}.js${after}`;
1412
+ });
1413
+ return Files.write(path, rewritten ? textEncoder.encode(result) : contents, { mode: contents[0] === 35 && contents[1] === 33 ? FileMode.READ_WRITE_EXECUTE : FileMode.READ_WRITE });
1406
1414
  }
1407
1415
  var outputPlugin = () => {
1408
1416
  return {
@@ -1418,9 +1426,42 @@ var outputPlugin = () => {
1418
1426
  };
1419
1427
 
1420
1428
  // src/plugins/external-modules.ts
1421
- var match = (id, patterns) => {
1422
- return patterns.some((pattern) => pattern instanceof RegExp ? pattern.test(id) : id === pattern || id.startsWith(`${pattern}/`));
1423
- };
1429
+ function packageName(id) {
1430
+ if (id.charCodeAt(0) === 64) {
1431
+ const first = id.indexOf("/");
1432
+ if (first === -1) {
1433
+ return id;
1434
+ }
1435
+ const second = id.indexOf("/", first + 1);
1436
+ return second === -1 ? id : id.slice(0, second);
1437
+ }
1438
+ const slash = id.indexOf("/");
1439
+ return slash === -1 ? id : id.slice(0, slash);
1440
+ }
1441
+ function buildMatcher(patterns) {
1442
+ const exact = /* @__PURE__ */ new Set();
1443
+ const regexps = [];
1444
+ for (const p of patterns) {
1445
+ if (typeof p === "string") {
1446
+ exact.add(p);
1447
+ } else {
1448
+ regexps.push(p);
1449
+ }
1450
+ }
1451
+ if (exact.size === 0 && regexps.length === 0) {
1452
+ return () => false;
1453
+ }
1454
+ return (id) => {
1455
+ if (exact.has(id)) {
1456
+ return true;
1457
+ }
1458
+ const pkg = packageName(id);
1459
+ if (pkg !== id && exact.has(pkg)) {
1460
+ return true;
1461
+ }
1462
+ return regexps.length > 0 && regexps.some((r) => r.test(id));
1463
+ };
1464
+ }
1424
1465
  var externalModulesPlugin = ({ dependencies = [], noExternal = [] }) => {
1425
1466
  return {
1426
1467
  name: "esbuild:external-modules",
@@ -1430,11 +1471,13 @@ var externalModulesPlugin = ({ dependencies = [], noExternal = [] }) => {
1430
1471
  */
1431
1472
  setup(build) {
1432
1473
  const external = true;
1474
+ const matchNoExternal = buildMatcher(noExternal);
1475
+ const matchDependencies = buildMatcher(dependencies);
1433
1476
  build.onResolve({ filter: /.*/ }, ({ path }) => {
1434
1477
  switch (true) {
1435
- case match(path, noExternal):
1478
+ case matchNoExternal(path):
1436
1479
  return;
1437
- case match(path, dependencies):
1480
+ case matchDependencies(path):
1438
1481
  return { external };
1439
1482
  case !Paths.isPath(path):
1440
1483
  return { path, external };
@@ -2012,9 +2055,9 @@ function resolveConditionalExport(exportValue) {
2012
2055
  }
2013
2056
  return void 0;
2014
2057
  }
2015
- function subpathToEntryName(subpath, packageName) {
2058
+ function subpathToEntryName(subpath, packageName2) {
2016
2059
  if (subpath === ".") {
2017
- return packageName !== void 0 ? unscope(packageName) : "index";
2060
+ return packageName2 !== void 0 ? unscope(packageName2) : "index";
2018
2061
  }
2019
2062
  const withoutPrefix = subpath.replace(/^\.\//, "");
2020
2063
  const lastSegment = withoutPrefix.lastIndexOf("/");
@@ -2115,7 +2158,7 @@ var _TypeScriptProject = class _TypeScriptProject {
2115
2158
  }
2116
2159
  async build() {
2117
2160
  const tsLogo = TextFormat.bgBlue(TextFormat.bold(TextFormat.whiteBright(" TS ")));
2118
- Logger.header(`${tsLogo} tsbuild v${"1.6.3"}${this.configuration.compilerOptions.incremental && this.configuration.buildCache?.isValid() ? " [incremental]" : ""}`);
2161
+ Logger.header(`${tsLogo} tsbuild v${"1.6.4"}${this.configuration.compilerOptions.incremental && this.configuration.buildCache?.isValid() ? " [incremental]" : ""}`);
2119
2162
  try {
2120
2163
  const processes = [];
2121
2164
  const filesWereEmitted = await this.typeCheck();
@@ -2174,7 +2217,7 @@ var _TypeScriptProject = class _TypeScriptProject {
2174
2217
  }
2175
2218
  if (this.configuration.compilerOptions.emitDecoratorMetadata) {
2176
2219
  try {
2177
- const { swcDecoratorMetadataPlugin } = await import("./LEZQQWX3.js");
2220
+ const { swcDecoratorMetadataPlugin } = await import("./GQLOAEUW.js");
2178
2221
  plugins.push(swcDecoratorMetadataPlugin);
2179
2222
  } catch {
2180
2223
  throw new ConfigurationError("emitDecoratorMetadata is enabled but @swc/core is not installed. Install it with: pnpm add -D @swc/core");
@@ -2230,8 +2273,10 @@ var _TypeScriptProject = class _TypeScriptProject {
2230
2273
  supported: { decorators: false }
2231
2274
  });
2232
2275
  for (const [kind, logEntryType, messages] of [[BuildMessageType.WARNING, Logger.EntryType.Warn, warnings], [BuildMessageType.ERROR, Logger.EntryType.Error, errors]]) {
2233
- for (const message of await formatMessages(messages, { kind, color: true })) {
2234
- Logger.log(message, logEntryType);
2276
+ if (messages.length > 0) {
2277
+ for (const message of await formatMessages(messages, { kind, color: true })) {
2278
+ Logger.log(message, logEntryType);
2279
+ }
2235
2280
  }
2236
2281
  if (kind === BuildMessageType.ERROR && errors.length > 0) {
2237
2282
  return [];
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  TypeScriptProject
3
- } from "./XQW6Y6DJ.js";
3
+ } from "./LQR6E3EH.js";
4
4
  import "./7FPDHUPW.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 "./XQW6Y6DJ.js";
5
+ } from "./LQR6E3EH.js";
6
6
  import "./7FPDHUPW.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.6.3");
33
+ console.log("1.6.4");
34
34
  process.exit(0);
35
35
  }
36
36
  var typeScriptOptions = {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@d1g1tal/tsbuild",
3
3
  "author": "D1g1talEntr0py",
4
- "version": "1.6.3",
4
+ "version": "1.6.4",
5
5
  "license": "MIT",
6
6
  "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.",
7
7
  "homepage": "https://github.com/D1g1talEntr0py/tsbuild#readme",
@@ -43,7 +43,7 @@
43
43
  "tsbuild": "./dist/tsbuild.js"
44
44
  },
45
45
  "dependencies": {
46
- "@d1g1tal/watchr": "^1.0.3",
46
+ "@d1g1tal/watchr": "^1.0.4",
47
47
  "esbuild": "^0.27.4",
48
48
  "magic-string": "^0.30.21"
49
49
  },
@@ -55,7 +55,7 @@
55
55
  "@typescript-eslint/eslint-plugin": "^8.57.1",
56
56
  "@typescript-eslint/parser": "^8.57.1",
57
57
  "@vitest/coverage-v8": "^4.1.0",
58
- "eslint": "^10.0.3",
58
+ "eslint": "^10.1.0",
59
59
  "eslint-plugin-jsdoc": "^62.8.0",
60
60
  "fs-monkey": "^1.1.0",
61
61
  "memfs": "^4.56.11",