Skip to content

Commit 4dd57ea

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 75ccb8c commit 4dd57ea

File tree

3 files changed

+52
-36
lines changed

3 files changed

+52
-36
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: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import type { Compilation, Compiler, Module as WebpackModule } from "webpack";
2424
import { sources } from "webpack";
2525
import fs from "fs";
2626
import path from "path";
27+
import { loadConfig } from "tsconfig-paths";
2728

2829
interface Asset {
2930
name: string;
@@ -108,51 +109,52 @@ export default class CodePressWebpackPlugin {
108109
}
109110
}
110111

111-
// Always try to read @ alias from tsconfig.json if not already present
112-
// resolve.alias usually has Next.js internals but not the @ path alias
113-
if (!aliases.has("@")) {
114-
const tsconfigPath = path.join(compiler.context, "tsconfig.json");
115-
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)) {
116119
try {
117-
if (fs.existsSync(tsconfigPath)) {
118-
const tsconfigContent = fs.readFileSync(tsconfigPath, "utf8");
119-
120-
// Extract paths directly using regex (avoids JSON parsing issues with comments/globs)
121-
// Match: "paths": { "@/*": ["./src/*"] } or similar
122-
const pathsMatch = tsconfigContent.match(
123-
/"paths"\s*:\s*\{([^}]+)\}/
124-
);
125-
126-
if (pathsMatch) {
127-
const pathsContent = pathsMatch[1];
128-
129-
// Extract individual path mappings: "@/*": ["./src/*"]
130-
const pathPattern = /"([^"]+)"\s*:\s*\[\s*"([^"]+)"/g;
131-
let match;
132-
while ((match = pathPattern.exec(pathsContent)) !== null) {
133-
const aliasPattern = match[1]; // "@/*"
134-
const targetPattern = match[2]; // "./src/*"
135-
136-
// Convert "@/*" -> "@" and "./src/*" -> "src"
137-
const alias = aliasPattern.replace(/\/\*$/, "");
138-
const targetPath = targetPattern
139-
.replace(/^\.\//, "")
140-
.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+
}
141142

142143
aliases.set(alias, targetPath);
143144
}
144145
}
145146
}
146147
} catch (e) {
147-
console.warn("[CodePress] Error reading tsconfig.json:", e);
148+
console.warn("[CodePress] Error loading tsconfig.json paths:", e);
148149
}
150+
}
149151

150-
// Fallback: Next.js convention is @/* -> ./src/*
151-
if (!aliases.has("@")) {
152-
const srcDir = path.join(compiler.context, "src");
153-
if (fs.existsSync(srcDir)) {
154-
aliases.set("@", "src");
155-
}
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");
156158
}
157159
}
158160

0 commit comments

Comments
 (0)