Skip to content

Instantly share code, notes, and snippets.

@krutoo
Last active October 11, 2023 10:06
Show Gist options
  • Save krutoo/70dd3068c9a0b8b1105da749bc475ede to your computer and use it in GitHub Desktop.
Save krutoo/70dd3068c9a0b8b1105da749bc475ede to your computer and use it in GitHub Desktop.
Babel plugin for remove Node module resolution imports
import { PluginObj } from '@babel/core';
import fs from 'node:fs';
import path from 'node:path';
export default function nodeModuleResolution(): PluginObj {
return {
visitor: {
ImportOrExportDeclaration: {
enter(nodePath, { file }) {
if (!file.opts.filename) {
return;
}
if (nodePath.node.type === 'ExportDefaultDeclaration') {
return;
}
if (!nodePath.node.source) {
return;
}
if (
!nodePath.node.source.value.startsWith('.') &&
!nodePath.node.source.value.startsWith('/')
) {
return;
}
const targetAbsPath = path.resolve(
path.dirname(file.opts.filename),
nodePath.node.source.value,
);
if (!fs.existsSync(targetAbsPath)) {
for (const ext of ['js', 'jsx', 'ts', 'tsx']) {
const result = `${targetAbsPath}.${ext}`;
if (fs.existsSync(result) && fs.lstatSync(result).isFile()) {
nodePath.node.source.value = `${nodePath.node.source.value}.js`;
return;
}
}
return;
}
const stats = fs.lstatSync(targetAbsPath);
// существующий файл без расширения - пропускаем
if (stats.isFile()) {
return;
}
// не директория - пропускаем
if (!stats.isDirectory()) {
return;
}
const entrypoint = findEntrypoint(targetAbsPath);
if (!entrypoint) {
return;
}
nodePath.node.source.value = `./${path.join(nodePath.node.source.value, 'index.js')}`;
},
},
},
};
}
function findEntrypoint(dirPath: string): string | null {
for (const ext of ['js', 'jsx', 'ts', 'tsx']) {
const result = path.resolve(dirPath, `index.${ext}`);
if (fs.existsSync(result) && fs.lstatSync(result).isFile()) {
return result;
}
}
return null;
}
// from https://gist.github.com/krutoo/70dd3068c9a0b8b1105da749bc475ede
import fs from 'node:fs';
import path from 'node:path';
const EXT = ['js', 'jsx', 'ts', 'tsx'];
// @todo наивная реализация замены импортов node module resolution на конкретные
// вероятно не учитывает какие-то кейсы
export default function nodeModuleResolution() {
return {
visitor: {
ImportOrExportDeclaration: {
enter(nodePath, { file }) {
// нет информации о файле - пропускаем
if (!file.opts.filename) {
return;
}
// у ExportDefaultDeclaration не может быть source - пропускаем
if (nodePath.node.type === 'ExportDefaultDeclaration') {
return;
}
// если нет source - пропускаем
if (!nodePath.node.source) {
return;
}
// если это не относительный и не абсолютный путь - пропускаем
if (
!nodePath.node.source.value.startsWith('.') &&
!nodePath.node.source.value.startsWith('/')
) {
return;
}
const targetAbsPath = path.resolve(
path.dirname(file.opts.filename),
nodePath.node.source.value,
);
if (!fs.existsSync(targetAbsPath)) {
for (const ext of EXT) {
const result = `${targetAbsPath}.${ext}`;
if (fs.existsSync(result) && fs.lstatSync(result).isFile()) {
nodePath.node.source.value = `${nodePath.node.source.value}.js`;
return;
}
}
return;
}
const stats = fs.lstatSync(targetAbsPath);
// существующий файл без расширения - пропускаем
if (stats.isFile()) {
return;
}
// не директория - пропускаем
if (!stats.isDirectory()) {
return;
}
let entrypoint = null;
for (const ext of EXT) {
const result = path.resolve(targetAbsPath, `index.${ext}`);
if (fs.existsSync(result) && fs.lstatSync(result).isFile()) {
entrypoint = result;
break;
}
}
if (!entrypoint) {
return;
}
nodePath.node.source.value = `./${path.join(nodePath.node.source.value, 'index.js')}`;
},
},
},
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment