-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsuffix.js
109 lines (90 loc) · 2.83 KB
/
suffix.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#!/usr/bin/env/node
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);
const resolvedPath = resolveImportPath(filePath, importPath, options);
if (resolvedPath) {
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$/.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('./path/to/an/esm/module/index.ts', './out.ts', defaultOptions);
} else {
await run('./dist/src', defaultOptions);
}