Skip to content

Commit

Permalink
fix: Provide file extensions for ESM build
Browse files Browse the repository at this point in the history
  • Loading branch information
amannn committed Jul 5, 2023
1 parent 3fce1cb commit 09314f9
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 2 deletions.
4 changes: 3 additions & 1 deletion packages/next-intl/tsup.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable import/no-extraneous-dependencies */
import {defineConfig} from 'tsup';
import TsupPluginAddRelativeEsmExtensions from '../../scripts/TsupPluginAddRelativeEsmExtensions';

export default defineConfig({
entry: ['src'],
Expand All @@ -9,5 +10,6 @@ export default defineConfig({
clean: true,
bundle: false,
dts: true,
minify: true
minify: true,
plugins: [new TsupPluginAddRelativeEsmExtensions()]
});
4 changes: 3 additions & 1 deletion packages/use-intl/tsup.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable import/no-extraneous-dependencies */
import {defineConfig} from 'tsup';
import TsupPluginAddRelativeEsmExtensions from '../../scripts/TsupPluginAddRelativeEsmExtensions';

const config = {
entry: ['src'],
Expand All @@ -9,7 +10,8 @@ const config = {
clean: true,
bundle: false,
dts: true,
minify: true
minify: true,
plugins: [new TsupPluginAddRelativeEsmExtensions()]
};

export default defineConfig([
Expand Down
101 changes: 101 additions & 0 deletions scripts/TsupPluginAddRelativeEsmExtensions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import {existsSync, readFileSync, statSync, writeFileSync} from 'fs';
import path from 'path';
import glob from 'glob';
import {parse, print, visit} from 'recast';

// See:
// - https://github.com/evanw/esbuild/issues/622#issuecomment-1480099602
// - https://gist.github.com/ds300/f6177171ac673f98f6028799563a06db

const extensions = ['.mjs', '.js', '.cjs'];

function resolveRelativePath(importingFile, relativePath) {
if (!relativePath.startsWith('.')) {
return relativePath;
}

const containingDir = path.dirname(importingFile);

if (
existsSync(path.join(containingDir, relativePath)) &&
!statSync(path.join(containingDir, relativePath)).isDirectory()
) {
// If the file already exists, e.g. .css files, just use it
return relativePath;
}

// Strip the file extension if applicable
relativePath.replace(/\.(m|c)?js$/, '');

for (const extension of extensions) {
if (relativePath.endsWith(extension)) {
return relativePath;
} else {
let candidate = `${relativePath}${extension}`;
if (existsSync(path.join(containingDir, candidate))) {
return candidate;
}

candidate = `${relativePath}/index${extension}`;

if (existsSync(path.join(containingDir, candidate))) {
return candidate;
}
}
}

throw new Error(
`Could not resolve relative path ${relativePath} from ${importingFile}`
);
}

function addExtensions(distDir) {
for (const file of glob.sync(path.join(distDir, '**/*.{mjs,cjs,js}'))) {
const code = parse(readFileSync(file, 'utf8'), {
parser: require('recast/parsers/typescript')
});

visit(code, {
visitImportDeclaration(path) {
path.value.source.value = resolveRelativePath(
file,
path.value.source.value
);
return false;
},
visitExportAllDeclaration(path) {
path.value.source.value = resolveRelativePath(
file,
path.value.source.value
);
return false;
},
visitExportNamedDeclaration(path) {
if (path.value.source) {
path.value.source.value = resolveRelativePath(
file,
path.value.source.value
);
}
return false;
}
});

writeFileSync(file, print(code).code);
}
}

function TsupPluginAddRelativeEsmExtensions(distFolder = 'dist') {
return {
name: 'esbuild-plugin-add-relative-extensions',
buildEnd(context) {
const isEsmBuild = context.writtenFiles.some((file) =>
file.name.endsWith('.mjs')
);
if (!isEsmBuild) return;
addExtensions(distFolder);
}
};
}

export default TsupPluginAddRelativeEsmExtensions;

0 comments on commit 09314f9

Please sign in to comment.