apisurf
Version:
Analyze API surface changes between npm package versions to catch breaking changes
56 lines (55 loc) • 1.99 kB
JavaScript
/**
* Parse CommonJS module exports using static analysis (regex-based)
*/
export function parseCommonJSStatically(sourceContent, packageName, version) {
const namedExports = new Set();
const typeOnlyExports = new Set();
const starExports = [];
let defaultExport = false;
const lines = sourceContent.split('\n');
for (const line of lines) {
const trimmed = line.trim();
// Skip comments and empty lines
if (trimmed.startsWith('//') || trimmed.startsWith('/*') || !trimmed) {
continue;
}
// Direct exports: exports.foo = bar
const directExportMatch = trimmed.match(/^exports\.([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=/);
if (directExportMatch) {
namedExports.add(directExportMatch[1]);
continue;
}
// Computed exports: exports['foo'] = bar
const computedExportMatch = trimmed.match(/^exports\[['"]([^'"]+)['"]\]\s*=/);
if (computedExportMatch) {
namedExports.add(computedExportMatch[1]);
continue;
}
// Object.defineProperty exports: Object.defineProperty(exports, 'foo', ...)
const definePropertyMatch = trimmed.match(/^Object\.defineProperty\(exports,\s*['"]([^'"]+)['"],/);
if (definePropertyMatch) {
namedExports.add(definePropertyMatch[1]);
continue;
}
// Module.exports default export
if (trimmed.match(/^module\.exports\s*=/)) {
defaultExport = true;
continue;
}
// __exportStar calls (bundler generated)
const exportStarMatch = trimmed.match(/__exportStar\(require\(['"]([^'"]+)['"]\)/);
if (exportStarMatch) {
starExports.push(exportStarMatch[1]);
continue;
}
}
return {
namedExports,
typeOnlyExports,
defaultExport,
starExports,
packageName,
version,
typeDefinitions: new Map()
};
}