152 lines
4.6 KiB
JavaScript
152 lines
4.6 KiB
JavaScript
/**
|
|
* 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;
|
|
};
|