Skip to content

Commit 8f103c3

Browse files
committed
Revert to create a temporary file
1 parent cdbd32e commit 8f103c3

File tree

3 files changed

+121
-60
lines changed

3 files changed

+121
-60
lines changed

src/index.ts

Lines changed: 2 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,6 @@
1-
import * as ts from 'typescript';
2-
import * as tmp from 'tmp-promise';
3-
import * as path from 'path';
1+
import { run } from './temporary';
42

5-
interface RunOptions {
6-
input: Buffer;
7-
}
8-
9-
interface RunResult {
10-
output: Buffer;
11-
}
12-
13-
export async function run(fileName: string, { input = Buffer.of() }: Partial<RunOptions> = {}): Promise<RunResult> {
14-
const callerFileName = await tmp.tmpName({ prefix: `compile-time-typescript`, postfix: `caller.ts` });
15-
const callerSourceFile = ts.createSourceFile(callerFileName, `
16-
import Main from ${JSON.stringify(path.resolve(fileName).replace(/\.ts$/, ''))};
17-
type Input = ${JSON.stringify(input.toString('binary'))};
18-
type Output = Main<Input>;
19-
`, ts.ScriptTarget.Latest);
20-
21-
const defaultCompilerHost = ts.createCompilerHost({});
22-
const customCompilerHost: ts.CompilerHost = {
23-
...defaultCompilerHost,
24-
getSourceFile(fileName: string, languageVersion: ts.ScriptTarget, onError?: ((message: string) => void), shouldCreateNewSourceFile?: boolean): ts.SourceFile | undefined {
25-
if (fileName === callerFileName) {
26-
return callerSourceFile;
27-
} else {
28-
return defaultCompilerHost.getSourceFile.call(this, fileName, languageVersion, onError, shouldCreateNewSourceFile);
29-
}
30-
},
31-
};
32-
33-
const program = ts.createProgram({
34-
rootNames: [callerFileName],
35-
options: {
36-
strict: true,
37-
},
38-
host: customCompilerHost,
39-
});
40-
const checker = program.getTypeChecker();
41-
const outputList: Buffer[] = [];
42-
43-
function visit(node: ts.Node) {
44-
const symbol = checker.getSymbolAtLocation(node);
45-
if (symbol && symbol.getName() === `Output`) {
46-
const type = checker.getDeclaredTypeOfSymbol(symbol);
47-
if (type.isStringLiteral()) {
48-
outputList.push(Buffer.from(type.value));
49-
} else {
50-
throw new Error(`type error: ${checker.typeToString(type)}`);
51-
}
52-
}
53-
node.forEachChild(visit);
54-
}
55-
56-
callerSourceFile.forEachChild(visit);
57-
58-
return {
59-
output: Buffer.concat(outputList),
60-
};
61-
}
3+
export { run } from './temporary';
624

635
export async function main(...args: string[]) {
646
if (!(args.length === 1 && typeof args[0] === 'string')) {

src/temporary.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import * as ts from 'typescript';
2+
import { promises as fs } from 'fs';
3+
import * as tmp from 'tmp-promise';
4+
import * as path from 'path';
5+
6+
interface RunOptions {
7+
input: Buffer;
8+
}
9+
10+
interface RunResult {
11+
output: Buffer;
12+
}
13+
14+
export async function run(fileName: string, { input = Buffer.of() }: Partial<RunOptions> = {}): Promise<RunResult> {
15+
const { path: tmpDirPath } = await tmp.dir({ prefix: `compile-time-typescript` });
16+
const calleeFileName = `callee.ts`;
17+
const callerFileName = `caller.ts`;
18+
await Promise.all([
19+
fs.copyFile(fileName, path.join(tmpDirPath, calleeFileName)),
20+
fs.writeFile(path.join(tmpDirPath, callerFileName), `
21+
import Main from './${path.basename(calleeFileName, path.extname(calleeFileName))}';
22+
type Input = ${JSON.stringify(input.toString('binary'))};
23+
type Output = Main<Input>;
24+
`),
25+
]);
26+
const program = ts.createProgram({
27+
rootNames: [path.join(tmpDirPath, callerFileName)],
28+
options: {
29+
strict: true,
30+
},
31+
});
32+
const source = program.getSourceFile(path.join(tmpDirPath, callerFileName))!;
33+
const checker = program.getTypeChecker();
34+
const outputList: Buffer[] = [];
35+
36+
function visit(node: ts.Node) {
37+
const symbol = checker.getSymbolAtLocation(node);
38+
if (symbol && symbol.getName() === `Output`) {
39+
const type = checker.getDeclaredTypeOfSymbol(symbol);
40+
if (type.isStringLiteral()) {
41+
outputList.push(Buffer.from(type.value));
42+
} else {
43+
throw new Error(`type error: ${checker.typeToString(type)}`);
44+
}
45+
}
46+
node.forEachChild(visit);
47+
}
48+
49+
source.forEachChild(visit);
50+
await Promise.all([
51+
fs.unlink(path.join(tmpDirPath, calleeFileName)),
52+
fs.unlink(path.join(tmpDirPath, callerFileName)),
53+
]);
54+
await fs.rmdir(tmpDirPath);
55+
return {
56+
output: Buffer.concat(outputList),
57+
};
58+
}

src/virtual.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import * as ts from 'typescript';
2+
import * as tmp from 'tmp-promise';
3+
import * as path from 'path';
4+
5+
interface RunOptions {
6+
input: Buffer;
7+
}
8+
9+
interface RunResult {
10+
output: Buffer;
11+
}
12+
13+
export async function run(fileName: string, { input = Buffer.of() }: Partial<RunOptions> = {}): Promise<RunResult> {
14+
const callerFileName = await tmp.tmpName({ prefix: `compile-time-typescript`, postfix: `caller.ts` });
15+
const callerSourceFile = ts.createSourceFile(callerFileName, `
16+
import Main from ${JSON.stringify(path.resolve(fileName).replace(/\.ts$/, ''))};
17+
type Input = ${JSON.stringify(input.toString('binary'))};
18+
type Output = Main<Input>;
19+
`, ts.ScriptTarget.Latest);
20+
21+
const defaultCompilerHost = ts.createCompilerHost({});
22+
const customCompilerHost: ts.CompilerHost = {
23+
...defaultCompilerHost,
24+
getSourceFile(fileName: string, languageVersion: ts.ScriptTarget, onError?: ((message: string) => void), shouldCreateNewSourceFile?: boolean): ts.SourceFile | undefined {
25+
if (fileName === callerFileName) {
26+
return callerSourceFile;
27+
} else {
28+
return defaultCompilerHost.getSourceFile.call(this, fileName, languageVersion, onError, shouldCreateNewSourceFile);
29+
}
30+
},
31+
};
32+
33+
const program = ts.createProgram({
34+
rootNames: [callerFileName],
35+
options: {
36+
strict: true,
37+
},
38+
host: customCompilerHost,
39+
});
40+
const checker = program.getTypeChecker();
41+
const outputList: Buffer[] = [];
42+
43+
function visit(node: ts.Node) {
44+
const symbol = checker.getSymbolAtLocation(node);
45+
if (symbol && symbol.getName() === `Output`) {
46+
const type = checker.getDeclaredTypeOfSymbol(symbol);
47+
if (type.isStringLiteral()) {
48+
outputList.push(Buffer.from(type.value));
49+
} else {
50+
throw new Error(`type error: ${checker.typeToString(type)}`);
51+
}
52+
}
53+
node.forEachChild(visit);
54+
}
55+
56+
callerSourceFile.forEachChild(visit);
57+
58+
return {
59+
output: Buffer.concat(outputList),
60+
};
61+
}

0 commit comments

Comments
 (0)