-
-
Notifications
You must be signed in to change notification settings - Fork 184
Expand file tree
/
Copy pathindex.ts
More file actions
118 lines (100 loc) · 4.53 KB
/
index.ts
File metadata and controls
118 lines (100 loc) · 4.53 KB
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
import * as fs from "fs";
import * as path from "path";
import * as ts from "typescript";
import { parseConfigFileWithSystem } from "../cli/tsconfig";
import { CompilerOptions } from "../CompilerOptions";
import { normalizeSlashes } from "../utils";
import { createEmitOutputCollector, TranspiledFile } from "./output-collector";
import { EmitResult, Transpiler } from "./transpiler";
export { Plugin } from "./plugins";
export * from "./transpile";
export * from "./transpiler";
export { EmitHost } from "./utils";
export { TranspiledFile };
export function transpileFiles(
rootNames: string[],
options: CompilerOptions = {},
writeFile?: ts.WriteFileCallback
): EmitResult {
const program = ts.createProgram(rootNames, options);
const preEmitDiagnostics = ts.getPreEmitDiagnostics(program);
const { diagnostics: transpileDiagnostics, emitSkipped } = new Transpiler().emit({ program, writeFile });
const diagnostics = ts.sortAndDeduplicateDiagnostics([...preEmitDiagnostics, ...transpileDiagnostics]);
return { diagnostics: [...diagnostics], emitSkipped };
}
export function transpileProject(
configFileName: string,
optionsToExtend?: CompilerOptions,
writeFile?: ts.WriteFileCallback
): EmitResult {
const parseResult = parseConfigFileWithSystem(configFileName, optionsToExtend);
if (parseResult.errors.length > 0) {
return { diagnostics: parseResult.errors, emitSkipped: true };
}
return transpileFiles(parseResult.fileNames, parseResult.options, writeFile);
}
const libCache: { [key: string]: ts.SourceFile } = {};
/** @internal */
export function createVirtualProgram(input: Record<string, string>, options: CompilerOptions = {}): ts.Program {
const normalizedFiles: Record<string, string> = {};
for (const [path, file] of Object.entries(input)) {
normalizedFiles[normalizeSlashes(path)] = file;
}
const compilerHost: ts.CompilerHost = {
fileExists: fileName => fileName in normalizedFiles || ts.sys.fileExists(fileName),
getCanonicalFileName: fileName => fileName,
getCurrentDirectory: () => "",
getDefaultLibFileName: ts.getDefaultLibFileName,
readFile: () => "",
getNewLine: () => "\n",
useCaseSensitiveFileNames: () => false,
writeFile() {},
getSourceFile(fileName) {
if (fileName in normalizedFiles) {
return ts.createSourceFile(fileName, normalizedFiles[fileName], ts.ScriptTarget.Latest, false);
}
let filePath: string | undefined;
if (fileName.startsWith("lib.")) {
const typeScriptDir = path.dirname(require.resolve("typescript"));
filePath = path.join(typeScriptDir, fileName);
}
if (fileName.includes("language-extensions")) {
const dtsName = fileName.replace(/(\.d)?(\.ts)$/, ".d.ts");
filePath = path.resolve(dtsName);
}
if (filePath !== undefined) {
if (libCache[fileName]) return libCache[fileName];
const content = fs.readFileSync(filePath, "utf8");
libCache[fileName] = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, false);
return libCache[fileName];
}
},
};
return ts.createProgram(Object.keys(normalizedFiles), options, compilerHost);
}
export interface TranspileVirtualProjectResult {
diagnostics: ts.Diagnostic[];
transpiledFiles: TranspiledFile[];
}
export function transpileVirtualProject(
files: Record<string, string>,
options: CompilerOptions = {}
): TranspileVirtualProjectResult {
const program = createVirtualProgram(files, options);
const preEmitDiagnostics = ts.getPreEmitDiagnostics(program);
const collector = createEmitOutputCollector();
const { diagnostics: transpileDiagnostics } = new Transpiler().emit({ program, writeFile: collector.writeFile });
const diagnostics = ts.sortAndDeduplicateDiagnostics([...preEmitDiagnostics, ...transpileDiagnostics]);
return { diagnostics: [...diagnostics], transpiledFiles: collector.files };
}
export interface TranspileStringResult {
diagnostics: ts.Diagnostic[];
file?: TranspiledFile;
}
export function transpileString(main: string, options: CompilerOptions = {}): TranspileStringResult {
const { diagnostics, transpiledFiles } = transpileVirtualProject({ "main.ts": main }, options);
return {
diagnostics,
file: transpiledFiles.find(({ sourceFiles }) => sourceFiles.some(f => f.fileName === "main.ts")),
};
}