-
-
Notifications
You must be signed in to change notification settings - Fork 7
/
compile.ts
123 lines (117 loc) · 4.23 KB
/
compile.ts
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import * as ts from 'typescript';
import { isMatch } from 'micromatch';
import FS from 'fs-extra';
import path from 'path';
import recursiveReaddirFiles from 'recursive-readdir-files';
import { transform } from '../babel';
import { BuildOptions } from '../build';
import { outputFiles, outputLog, copyFiles } from '../utils/output';
export interface CompileOptions extends BuildOptions {}
export async function compile(
fileNames: string[],
tsOptions: ts.CompilerOptions = {},
options: CompileOptions,
): Promise<void> {
let { entry, disableBabel, cjs = tsOptions.outDir || 'lib', esm = 'esm', ...other } = options || {};
const outDir = path.resolve(process.cwd(), tsOptions.outDir || cjs);
const entryDir = path.dirname(entry);
cjs = path.relative(ts.sys.getCurrentDirectory(), cjs);
return new Promise(async (resolve, reject) => {
try {
if (tsOptions.outDir || cjs) {
await FS.remove(outDir);
}
if (esm) {
await FS.remove(path.resolve(process.cwd(), esm));
}
const dirToFiles = await recursiveReaddirFiles(path.dirname(entry), {
exclude: /(tsconfig.json|\.d\.ts|\.(test|spec)\.(ts|tsx|js|jsx))$/,
});
await Promise.all(
dirToFiles.map(async (item) => {
if (cjs) {
const cjsPath = item.path.replace(entryDir, cjs);
if (
!disableBabel &&
isMatch(item.path, ['**/*.[jt]s?(x)']) &&
!isMatch(item.path, ['**/?(*.)+(spec|test).[jt]s?(x)'])
) {
transform(item.path, { entryDir, cjs, ...other });
} else {
copyFiles(item.path, cjsPath);
}
}
if (esm) {
const esmPath = item.path.replace(entryDir, esm);
if (
!disableBabel &&
isMatch(item.path, ['**/*.[jt]s?(x)']) &&
!isMatch(item.path, ['**/?(*.)+(spec|test).[jt]s?(x)'])
) {
transform(item.path, { entryDir, esm, ...other });
} else {
copyFiles(item.path, esmPath);
}
}
}),
);
// Create a Program with an in-memory emit
const createdFiles: Record<string, string> = {};
tsOptions = { ...tsOptions, outDir: cjs || esm, target: tsOptions.target || ts.ScriptTarget.ESNext };
if (tsOptions.noEmit) {
resolve();
return;
}
const host = ts.createCompilerHost(tsOptions, true);
// ts.getParsedCommandLineOfConfigFile('', tsOptions, host)
host.readFile = (file) => {
const result = ts.sys.readFile(file);
if (!/node_modules/.test(file)) {
// const output = path.resolve(tsOptions.outDir || cjs, path.relative(entryDir, file));
// const outputLib = path.relative(process.cwd(), output);
// if (/.d.ts$/.test(outputLib)) {
// createdFiles[outputLib] = result;
// }
}
return result;
};
host.writeFile = (fileName: string, contents: string) => {
return (createdFiles[fileName] = contents);
};
const program = ts.createProgram(fileNames, tsOptions, host);
// Prepare and emit the `d.ts` files
program.emit();
await Promise.all(
Object.keys(createdFiles).map(async (filepath) => {
try {
if (disableBabel) {
ts.sys.writeFile(filepath, createdFiles[filepath]);
outputLog(filepath);
}
if (/\.d\.ts$/.test(filepath)) {
if (new RegExp(`${esm}`).test(filepath)) {
outputFiles(filepath, createdFiles[filepath]);
if (cjs) {
const fileCjs = filepath.replace(esm, cjs);
outputFiles(fileCjs, createdFiles[filepath]);
}
}
if (new RegExp(`${cjs}`).test(filepath)) {
outputFiles(filepath, createdFiles[filepath]);
if (esm) {
const fileEsm = filepath.replace(cjs, esm);
outputFiles(fileEsm, createdFiles[filepath]);
}
}
}
} catch (error) {
reject(error);
}
}),
);
resolve();
} catch (error) {
reject(error);
}
});
}