Created
March 27, 2023 15:32
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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