mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 02:14:01 +00:00
refactor: enforce import directions and expose source factories
This commit is contained in:
1 parent
704e0fcc51
commit
cc960b0dbe
41 files changed
+1080
-417
No files matched your search
@@ -0,0 +1,80 @@
|
||||
import { parsers } from 'prettier/plugins/babel.mjs';
|
||||
|
||||
const browserGlobals = new Set([
|
||||
'window',
|
||||
'document',
|
||||
'navigator',
|
||||
'HTMLElement',
|
||||
'HTMLCanvasElement',
|
||||
'Image',
|
||||
'Audio',
|
||||
'localStorage',
|
||||
'sessionStorage',
|
||||
'requestAnimationFrame',
|
||||
'cancelAnimationFrame',
|
||||
'getComputedStyle',
|
||||
]);
|
||||
|
||||
/** Inspect literal module dependencies and browser-platform references without executing code. */
|
||||
export function analyzeModule(source) {
|
||||
const imports = [];
|
||||
const browser = new Set();
|
||||
function walk(node, parent, field) {
|
||||
if (!node || typeof node !== 'object') return;
|
||||
if (
|
||||
[
|
||||
'ImportDeclaration',
|
||||
'ExportNamedDeclaration',
|
||||
'ExportAllDeclaration',
|
||||
'ImportExpression',
|
||||
].includes(node.type) &&
|
||||
node.source
|
||||
) {
|
||||
if (node.source.type !== 'StringLiteral')
|
||||
throw new Error(
|
||||
'Computed module imports are not allowed in runtime code',
|
||||
);
|
||||
imports.push(node.source.value);
|
||||
}
|
||||
if (node.type === 'CallExpression' && node.callee?.name === 'require')
|
||||
throw new Error('Runtime modules must use ES imports');
|
||||
if (node.type === 'Identifier' && browserGlobals.has(node.name)) {
|
||||
const property =
|
||||
(parent?.type === 'MemberExpression' ||
|
||||
parent?.type === 'OptionalMemberExpression') &&
|
||||
field === 'property' &&
|
||||
!parent.computed;
|
||||
const key =
|
||||
['ObjectProperty', 'ObjectMethod', 'ClassMethod'].includes(
|
||||
parent?.type,
|
||||
) &&
|
||||
field === 'key' &&
|
||||
!parent.computed;
|
||||
const declaration =
|
||||
field === 'id' ||
|
||||
field === 'params' ||
|
||||
parent?.type?.startsWith('Import');
|
||||
if (!property && !key && !declaration) browser.add(node.name);
|
||||
}
|
||||
if (
|
||||
['MemberExpression', 'OptionalMemberExpression'].includes(node.type) &&
|
||||
['globalThis', 'self'].includes(node.object?.name)
|
||||
) {
|
||||
const name = node.computed ? node.property?.value : node.property?.name;
|
||||
if (browserGlobals.has(name)) browser.add(name);
|
||||
}
|
||||
for (const [key, value] of Object.entries(node)) {
|
||||
if (['loc', 'comments', 'tokens', 'extra'].includes(key)) continue;
|
||||
if (Array.isArray(value))
|
||||
value.forEach((child) => walk(child, node, key));
|
||||
else if (value && typeof value === 'object') walk(value, node, key);
|
||||
}
|
||||
}
|
||||
walk(parsers.babel.parse(source));
|
||||
return { imports, browser: [...browser] };
|
||||
}
|
||||
|
||||
/** Return static imports, literal dynamic imports and re-exports. */
|
||||
export function moduleImports(source) {
|
||||
return analyzeModule(source).imports;
|
||||
}
|
||||
Reference in new issue
Block a user