-
Notifications
You must be signed in to change notification settings - Fork 124
/
simple-ts.js
104 lines (90 loc) · 2.83 KB
/
simple-ts.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
/**
* Copyright 2018 Google Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { spawn } from "child_process";
import { relative, join } from "path";
import { promises as fsp } from "fs";
import * as ts from "typescript";
const extRe = /\.tsx?$/;
function loadConfig(mainPath) {
const fileName = ts.findConfigFile(mainPath, ts.sys.fileExists);
if (!fileName) throw Error("tsconfig not found");
const text = ts.sys.readFile(fileName);
const loadedConfig = ts.parseConfigFileTextToJson(fileName, text).config;
const parsedTsConfig = ts.parseJsonConfigFileContent(
loadedConfig,
ts.sys,
process.cwd(),
undefined,
fileName
);
return parsedTsConfig;
}
export default function simpleTS(mainPath, { noBuild, watch } = {}) {
const config = loadConfig(mainPath);
const args = ["-b", mainPath];
let done = Promise.resolve();
if (!noBuild) {
done = new Promise(resolve => {
const proc = spawn("tsc", args, {
stdio: "inherit"
});
proc.on("exit", code => {
if (code !== 0) {
throw Error("TypeScript build failed");
}
resolve();
});
});
}
if (!noBuild && watch) {
done.then(() => {
spawn("tsc", [...args, "--watch", "--preserveWatchOutput"], {
stdio: "inherit"
});
});
}
return {
name: "simple-ts",
buildStart: () => done,
resolveId(id, importer) {
// If there isn't an importer, it's an entry point, so we don't need to resolve it relative
// to something.
if (!importer) return null;
const tsResolve = ts.resolveModuleName(
id,
importer,
config.options,
ts.sys
);
if (
// It didn't find anything
!tsResolve.resolvedModule ||
// Or if it's linking to a definition file, it's something in node_modules,
// or something local like css.d.ts
tsResolve.resolvedModule.extension === ".d.ts"
) {
return null;
}
return tsResolve.resolvedModule.resolvedFileName;
},
load(id) {
if (!extRe.test(id)) return null;
// Look for the JS equivalent in the tmp folder
const newId = join(
config.options.outDir,
relative(process.cwd(), id)
).replace(extRe, ".js");
return fsp.readFile(newId, { encoding: "utf8" });
}
};
}