Skip to content

Commit 86ab625

Browse files
lightninglu10claude
andcommitted
refactor: Use tsconfig-paths library for robust config parsing
Replace fragile regex-based tsconfig.json parsing with the tsconfig-paths library which properly handles: - JSON with comments (TypeScript's JSON5-like syntax) - The "extends" field to resolve inherited configurations - Complex path patterns and multi-line definitions Also moves fs/path to top-level imports. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 71c2809 commit 86ab625

File tree

3 files changed

+54
-50
lines changed

3 files changed

+54
-50
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@
128128
"fastify": "^5.3.3",
129129
"node-fetch": "^2.6.7",
130130
"prettier": "^3.1.0",
131+
"tsconfig-paths": "^4.2.0",
131132
"ws": "^8.18.0"
132133
},
133134
"pnpm": {

pnpm-lock.yaml

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/webpack-plugin.ts

Lines changed: 40 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222

2323
import type { Compilation, Compiler, Module as WebpackModule } from "webpack";
2424
import { sources } from "webpack";
25+
import fs from "fs";
26+
import path from "path";
27+
import { loadConfig } from "tsconfig-paths";
2528

2629
interface Asset {
2730
name: string;
@@ -106,65 +109,52 @@ export default class CodePressWebpackPlugin {
106109
}
107110
}
108111

109-
// Always try to read @ alias from tsconfig.json if not already present
110-
// resolve.alias usually has Next.js internals but not the @ path alias
111-
const fs = require("fs");
112-
const path = require("path");
113-
114-
if (!aliases.has("@")) {
115-
const tsconfigPath = path.join(compiler.context, "tsconfig.json");
116-
console.log("[CodePress] Looking for @ alias in tsconfig:", tsconfigPath);
117-
112+
// Load path aliases from tsconfig.json using tsconfig-paths library
113+
// This properly handles:
114+
// - JSON with comments (TypeScript's JSON5-like syntax)
115+
// - The "extends" field to resolve inherited configurations
116+
// - Complex path patterns
117+
const tsconfigPath = path.join(compiler.context, "tsconfig.json");
118+
if (fs.existsSync(tsconfigPath)) {
118119
try {
119-
if (fs.existsSync(tsconfigPath)) {
120-
const tsconfigContent = fs.readFileSync(tsconfigPath, "utf8");
121-
122-
// Extract paths directly using regex (avoids JSON parsing issues with comments/globs)
123-
// Match: "paths": { "@/*": ["./src/*"] } or similar
124-
const pathsMatch = tsconfigContent.match(
125-
/"paths"\s*:\s*\{([^}]+)\}/
126-
);
127-
128-
if (pathsMatch) {
129-
const pathsContent = pathsMatch[1];
130-
console.log("[CodePress] Found paths block:", pathsContent.trim());
131-
132-
// Extract individual path mappings: "@/*": ["./src/*"]
133-
const pathPattern = /"([^"]+)"\s*:\s*\[\s*"([^"]+)"/g;
134-
let match;
135-
while ((match = pathPattern.exec(pathsContent)) !== null) {
136-
const aliasPattern = match[1]; // "@/*"
137-
const targetPattern = match[2]; // "./src/*"
138-
139-
// Convert "@/*" -> "@" and "./src/*" -> "src"
140-
const alias = aliasPattern.replace(/\/\*$/, "");
141-
const targetPath = targetPattern
142-
.replace(/^\.\//, "")
143-
.replace(/\/\*$/, "");
120+
const config = loadConfig(compiler.context);
121+
122+
if (config.resultType === "success" && config.paths) {
123+
for (const [pattern, targets] of Object.entries(config.paths)) {
124+
// Convert "@/*" -> "@" and "./src/*" -> "src"
125+
const alias = pattern.replace(/\/\*$/, "");
126+
127+
// Skip if we already have this alias from webpack config
128+
if (aliases.has(alias)) continue;
129+
130+
// Get the first target path
131+
const targetPattern = targets[0];
132+
if (targetPattern) {
133+
// Convert absolute or relative path to relative directory
134+
let targetPath = targetPattern
135+
.replace(/\/\*$/, "") // Remove trailing /*
136+
.replace(/^\.\//, ""); // Remove leading ./
137+
138+
// If it's an absolute path, make it relative to project root
139+
if (path.isAbsolute(targetPath)) {
140+
targetPath = path.relative(compiler.context, targetPath);
141+
}
144142

145143
aliases.set(alias, targetPath);
146-
console.log(
147-
"[CodePress] Added alias from tsconfig:",
148-
alias,
149-
"->",
150-
targetPath
151-
);
152144
}
153-
} else {
154-
console.log("[CodePress] No paths block found in tsconfig");
155145
}
156146
}
157147
} catch (e) {
158-
console.warn("[CodePress] Error reading tsconfig.json:", e);
148+
console.warn("[CodePress] Error loading tsconfig.json paths:", e);
159149
}
150+
}
160151

161-
// Fallback: Next.js convention is @/* -> ./src/*
162-
if (!aliases.has("@")) {
163-
const srcDir = path.join(compiler.context, "src");
164-
if (fs.existsSync(srcDir)) {
165-
aliases.set("@", "src");
166-
console.log("[CodePress] Using default Next.js alias: @ → src");
167-
}
152+
// Fallback: Next.js convention is @/* -> ./src/*
153+
// Only applies if no @ alias was configured
154+
if (!aliases.has("@")) {
155+
const srcDir = path.join(compiler.context, "src");
156+
if (fs.existsSync(srcDir)) {
157+
aliases.set("@", "src");
168158
}
169159
}
170160

0 commit comments

Comments
 (0)