Skip to content

Instantly share code, notes, and snippets.

@scvnc
Created March 27, 2023 15:32
Show Gist options
  • Save scvnc/ec7313d92642e79bf8ddda6d3650f660 to your computer and use it in GitHub Desktop.
Save scvnc/ec7313d92642e79bf8ddda6d3650f660 to your computer and use it in GitHub Desktop.
Have chatGPT make a util that detects whether a javascript module eventually imports @faker-js/faker
import fs from 'fs';
import path from 'path';
import * as acorn from 'acorn';
import * as walk from 'acorn-walk';
const getRelativeModuleFilePath = (
moduleFilePath: string,
adjacentModulePath: string
): string | false => {
const adjacentModuleFilePath = path.join(path.dirname(moduleFilePath), adjacentModulePath);
const adjacentModuleFilePathMjs = `${adjacentModuleFilePath}.mjs`;
if (fs.existsSync(adjacentModuleFilePath)) {
return adjacentModuleFilePath;
}
if (fs.existsSync(adjacentModuleFilePathMjs)) {
return adjacentModuleFilePathMjs;
}
return false;
};
const _getImportDeclarationValue = (node: acorn.Node) => {
// Acorn has bad types.
if (
'source' in node &&
typeof node.source === 'object' &&
node.source !== null &&
typeof node.source['value'] === 'string'
) {
return node.source['value'] as string;
}
throw new Error(`Could not get the module path for ${node}`);
};
const getDependencies = (mainModuleFilePath: string): string[] => {
const visitedModuleFilePaths = new Set<string>();
/**
* Recursively traverse the given module file and any modules it imports to build a flat list of all the imported module paths.
* @param {string} moduleFilePath The path of the module file to traverse.
* @returns {string[]} An array of all the imported module paths.
*/
const traverseModule = (moduleFilePath: string): void => {
// Skip if the module file has already been visited to avoid circular dependencies
if (visitedModuleFilePaths.has(moduleFilePath)) {
return;
}
// Mark the module file as visited
visitedModuleFilePaths.add(moduleFilePath);
// Read the file content and parse it with acorn
const fileContent = fs.readFileSync(moduleFilePath, 'utf8');
const ast = acorn.parse(fileContent, { sourceType: 'module', ecmaVersion: 'latest' });
// Traverse the AST to build the list of imported modules
walk.simple(ast, {
ImportDeclaration(node) {
const adjacentModulePath = _getImportDeclarationValue(node);
visitedModuleFilePaths.add(adjacentModulePath);
const adjacentModuleFilePath = getRelativeModuleFilePath(
moduleFilePath,
adjacentModulePath
);
if (adjacentModuleFilePath) {
// Recursively traverse the imported module to build the list of its imported modules
traverseModule(adjacentModuleFilePath);
}
}
});
};
// Traverse the main module and its imported modules to build the list of all imported modules
traverseModule(mainModuleFilePath);
return Array.from(visitedModuleFilePaths).sort();
};
const result = [
'dist/composables.mjs',
'dist/index.mjs',
'dist/models.mjs',
'dist/testUtilities.mjs'
].map(mod => ({ mod, detected: getDependencies(mod).includes('@faker-js/faker') }));
console.log(result);
// const deps = getDependencies(searchMod);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment