Skip to content

Commit ecb8a9f

Browse files
authored
Merge pull request #125 from victorhahncastell/main
Fix ESM build
2 parents cb6bbdd + 0e27d6f commit ecb8a9f

File tree

2 files changed

+76
-1
lines changed

2 files changed

+76
-1
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
},
1616
"scripts": {
1717
"build": "npm run build:ecu && npm run build:docs-class",
18-
"build:esm": "rm -rf dist/esm && tsc -p tsconfig-esm.json",
18+
"build:esm": "rm -rf dist/esm && tsc -p tsconfig-esm.json && node scripts/fix-esm-imports.cjs",
1919
"build:cjs": "rm -rf dist/cjs && tsc -p tsconfig-cjs.json",
2020
"build:umd": "tsup",
2121
"build:ecu": "npm run build:esm && npm run build:cjs && npm run build:umd",

scripts/fix-esm-imports.cjs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
const fs = require("fs");
2+
const path = require("path");
3+
4+
const ROOT = path.resolve(__dirname, "..", "dist", "esm");
5+
6+
function isRelativeBare(spec) {
7+
return (
8+
(spec.startsWith("./") || spec.startsWith("../")) &&
9+
!spec.endsWith(".js") &&
10+
!spec.endsWith(".mjs") &&
11+
!spec.endsWith(".cjs") &&
12+
!spec.endsWith(".json")
13+
);
14+
}
15+
16+
function resolveTarget(fileDir, spec) {
17+
const base = path.resolve(fileDir, spec);
18+
19+
// Case 1: "./foo.js" exists
20+
if (fs.existsSync(base + ".js")) {
21+
return spec + ".js";
22+
}
23+
24+
// Case 2: "./foo/index.js" exists
25+
const indexPath = path.join(base, "index.js");
26+
if (fs.existsSync(indexPath)) {
27+
// normalize to POSIX for import strings
28+
return spec.replace(/\\/g, "/") + "/index.js";
29+
}
30+
31+
// Could not resolve safely
32+
return null;
33+
}
34+
35+
function processFile(filePath) {
36+
if (!filePath.endsWith(".js")) return;
37+
38+
let code = fs.readFileSync(filePath, "utf8");
39+
let changed = false;
40+
41+
// matches: import ... from "spec" OR export ... from "spec"
42+
const importExportRegex =
43+
/(import\s+(?:[^"']+?\s+from\s+)?|export\s+(?:\*|{[^}]*})\s+from\s+)["']([^"']+)["']/g;
44+
45+
code = code.replace(importExportRegex, (full, prefix, spec) => {
46+
if (!isRelativeBare(spec)) return full;
47+
48+
const dir = path.dirname(filePath);
49+
const fixed = resolveTarget(dir, spec);
50+
if (!fixed) return full;
51+
52+
changed = true;
53+
return `${prefix}"${fixed}"`;
54+
});
55+
56+
if (changed) {
57+
fs.writeFileSync(filePath, code, "utf8");
58+
}
59+
}
60+
61+
function walk(dir) {
62+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
63+
const full = path.join(dir, entry.name);
64+
if (entry.isDirectory()) {
65+
walk(full);
66+
} else if (entry.isFile()) {
67+
processFile(full);
68+
}
69+
}
70+
}
71+
72+
if (fs.existsSync(ROOT)) {
73+
walk(ROOT);
74+
}
75+

0 commit comments

Comments
 (0)