Fix package by testing real world examples (#1)
Co-authored-by: Chris Daßler <chris.dassler@me.com> Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
151
plugins/babel-plugin-ior.js
Normal file
151
plugins/babel-plugin-ior.js
Normal file
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* Babel plugin for IOR import transformation
|
||||
* This plugin can transform IOR imports at build time for better optimization
|
||||
*/
|
||||
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
// Cache for IOR mappings
|
||||
let iorMappings = null;
|
||||
|
||||
/**
|
||||
* Build IOR mappings from component package.json files
|
||||
*/
|
||||
function buildMappings(projectRoot) {
|
||||
if (iorMappings) return iorMappings;
|
||||
|
||||
iorMappings = new Map();
|
||||
const componentsDir = path.join(projectRoot, 'src', 'components');
|
||||
|
||||
try {
|
||||
const scanDirectory = (dir, depth = 0) => {
|
||||
if (depth > 3) return; // Limit recursion depth
|
||||
|
||||
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
scanDirectory(fullPath, depth + 1);
|
||||
} else if (entry.name === 'package.json') {
|
||||
try {
|
||||
const content = fs.readFileSync(fullPath, 'utf-8');
|
||||
const pkg = JSON.parse(content);
|
||||
|
||||
if (pkg.metatrom?.ior) {
|
||||
const componentDir = path.dirname(fullPath);
|
||||
const mainFile = pkg.main || 'index.ts';
|
||||
const componentPath = path.join(componentDir, mainFile);
|
||||
|
||||
// Create relative path from project root
|
||||
const relativePath = path.relative(projectRoot, componentPath).replace(/\\/g, '/'); // Normalize path separators
|
||||
|
||||
// Store both with and without esm: prefix
|
||||
iorMappings.set(`ior:esm:${pkg.metatrom.ior}`, `./${relativePath}`);
|
||||
iorMappings.set(`ior:${pkg.metatrom.ior}`, `./${relativePath}`);
|
||||
}
|
||||
} catch (_err) {
|
||||
// Ignore parse errors
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
scanDirectory(componentsDir);
|
||||
} catch (_err) {
|
||||
console.warn('[Babel IOR Plugin] Could not scan components:', _err);
|
||||
}
|
||||
|
||||
return iorMappings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Babel plugin factory
|
||||
*/
|
||||
module.exports = (babel) => {
|
||||
const { types: t } = babel;
|
||||
|
||||
return {
|
||||
name: 'babel-plugin-ior',
|
||||
|
||||
visitor: {
|
||||
// Transform import declarations
|
||||
ImportDeclaration(path, state) {
|
||||
const source = path.node.source.value;
|
||||
|
||||
if (source.startsWith('ior:')) {
|
||||
const projectRoot = state.opts.projectRoot || process.cwd();
|
||||
const mappings = buildMappings(projectRoot);
|
||||
|
||||
const resolvedPath = mappings.get(source);
|
||||
|
||||
if (resolvedPath) {
|
||||
// Replace the IOR import with the resolved path
|
||||
path.node.source = t.stringLiteral(resolvedPath);
|
||||
|
||||
console.log(`[Babel IOR] Transformed: ${source} -> ${resolvedPath}`);
|
||||
} else {
|
||||
console.warn(`[Babel IOR] No mapping found for: ${source}`);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Transform dynamic imports
|
||||
CallExpression(path, state) {
|
||||
if (
|
||||
path.node.callee.type === 'Import' ||
|
||||
(path.node.callee.type === 'Identifier' && path.node.callee.name === 'require')
|
||||
) {
|
||||
const arg = path.node.arguments[0];
|
||||
|
||||
if (t.isStringLiteral(arg) && arg.value.startsWith('ior:')) {
|
||||
const projectRoot = state.opts.projectRoot || process.cwd();
|
||||
const mappings = buildMappings(projectRoot);
|
||||
|
||||
const resolvedPath = mappings.get(arg.value);
|
||||
|
||||
if (resolvedPath) {
|
||||
// Replace the IOR path with the resolved path
|
||||
path.node.arguments[0] = t.stringLiteral(resolvedPath);
|
||||
|
||||
console.log(
|
||||
`[Babel IOR] Transformed dynamic import: ${arg.value} -> ${resolvedPath}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Transform require() calls for CommonJS compatibility
|
||||
MemberExpression(path, state) {
|
||||
if (
|
||||
path.node.object.type === 'CallExpression' &&
|
||||
path.node.object.callee.type === 'Identifier' &&
|
||||
path.node.object.callee.name === 'require'
|
||||
) {
|
||||
const arg = path.node.object.arguments[0];
|
||||
|
||||
if (t.isStringLiteral(arg) && arg.value.startsWith('ior:')) {
|
||||
const projectRoot = state.opts.projectRoot || process.cwd();
|
||||
const mappings = buildMappings(projectRoot);
|
||||
|
||||
const resolvedPath = mappings.get(arg.value);
|
||||
|
||||
if (resolvedPath) {
|
||||
path.node.object.arguments[0] = t.stringLiteral(resolvedPath);
|
||||
console.log(`[Babel IOR] Transformed require: ${arg.value} -> ${resolvedPath}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// Export utility functions for testing
|
||||
module.exports.buildMappings = buildMappings;
|
||||
module.exports.clearCache = () => {
|
||||
iorMappings = null;
|
||||
};
|
||||
Reference in New Issue
Block a user