mirror of https://github.com/certd/certd
				
				
				
			
		
			
				
	
	
		
			97 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
| import * as fs from "fs";
 | |
| import * as path from "path";
 | |
| 
 | |
| // https://gist.github.com/lovasoa/8691344
 | |
| async function* walk(dir) {
 | |
|   for await (const d of await fs.promises.opendir(dir)) {
 | |
|     const entry = path.join(dir, d.name);
 | |
|     if (d.isDirectory()) {
 | |
|       yield* walk(entry);
 | |
|     } else if (d.isFile()) {
 | |
|       yield entry;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| function resolveImportPath(sourceFile, importPath, options) {
 | |
|   const sourceFileAbs = path.resolve(process.cwd(), sourceFile);
 | |
|   const root = path.dirname(sourceFileAbs);
 | |
|   const { moduleFilter = defaultModuleFilter } = options;
 | |
| 
 | |
|   if (moduleFilter(importPath)) {
 | |
|     const importPathAbs = path.resolve(root, importPath);
 | |
|     let possiblePath = [path.resolve(importPathAbs, "./index.ts"), path.resolve(importPathAbs, "./index.js"), importPathAbs + ".ts", importPathAbs + ".js"];
 | |
| 
 | |
|     if (possiblePath.length) {
 | |
|       for (let i = 0; i < possiblePath.length; i++) {
 | |
|         let entry = possiblePath[i];
 | |
|         if (fs.existsSync(entry)) {
 | |
|           const resolved = path.relative(root, entry.replace(/\.ts$/, ".js"));
 | |
| 
 | |
|           if (!resolved.startsWith(".")) {
 | |
|             return "./" + resolved;
 | |
|           }
 | |
| 
 | |
|           return resolved;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return null;
 | |
| }
 | |
| 
 | |
| function replace(filePath, outFilePath, options) {
 | |
|   const code = fs.readFileSync(filePath).toString();
 | |
|   const newCode = code.replace(/(import|export) (.+?) from ('[^\n']+'|"[^\n"]+");/gs, function (found, action, imported, from) {
 | |
|     const importPath = from.slice(1, -1);
 | |
|     let resolvedPath = resolveImportPath(filePath, importPath, options);
 | |
| 
 | |
|     if (resolvedPath) {
 | |
|       resolvedPath = resolvedPath.replaceAll("\\", "/");
 | |
|       console.log("\t", importPath, resolvedPath);
 | |
|       return `${action} ${imported} from "${resolvedPath}";`;
 | |
|     }
 | |
| 
 | |
|     return found;
 | |
|   });
 | |
| 
 | |
|   if (code !== newCode) {
 | |
|     fs.writeFileSync(outFilePath, newCode);
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Then, use it with a simple async for loop
 | |
| async function run(srcDir, options = defaultOptions) {
 | |
|   const { sourceFileFilter = defaultSourceFileFilter } = options;
 | |
| 
 | |
|   for await (const entry of walk(srcDir)) {
 | |
|     if (sourceFileFilter(entry)) {
 | |
|       console.log(entry);
 | |
|       replace(entry, entry, options);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| const defaultSourceFileFilter = function (sourceFilePath) {
 | |
|   return /\.(js|ts)$/.test(sourceFilePath) && !/node_modules/.test(sourceFilePath);
 | |
| };
 | |
| 
 | |
| const defaultModuleFilter = function (importedModule) {
 | |
|   return !path.isAbsolute(importedModule) && !importedModule.startsWith("@") && !importedModule.endsWith(".js");
 | |
| };
 | |
| 
 | |
| const defaultOptions = {
 | |
|   sourceFileFilter: defaultSourceFileFilter,
 | |
|   moduleFilter: defaultModuleFilter,
 | |
| };
 | |
| 
 | |
| // Switch this to test on one file or directly run on a directory.
 | |
| const DEBUG = false;
 | |
| 
 | |
| if (DEBUG) {
 | |
|   replace("./src/index.ts", "./out.ts", defaultOptions);
 | |
| } else {
 | |
|   await run("./src/", defaultOptions);
 | |
| }
 |