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:
2025-08-29 07:42:17 +02:00
parent 7d1935dde5
commit 54d0d245d6
8 changed files with 6393 additions and 26 deletions

151
plugins/babel-plugin-ior.js Normal file
View 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;
};