Created
April 30, 2020 08:36
-
-
Save ashleydavis/0a9e03ec5f4e4f9ed4ab8c0d6b17154b to your computer and use it in GitHub Desktop.
An example of using the TypeScript compiler from TypeScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as path from "path"; | |
import { IDiagnostic } from "./language-code-generator"; | |
import { readJsonFile } from "../common/file"; | |
// | |
// Result of compiling TypeScript code. | |
// | |
export interface ICompilationResult { | |
code?: string; | |
diagnostics: IDiagnostic[]; | |
sourceMap?: any; | |
}; | |
// | |
// Convert a TS diagnostic. | |
// | |
function convertDiagnostic(diagnostic: any, ts: any) { | |
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); | |
const file = diagnostic.file!; | |
if (!file) { | |
return { | |
message: message, | |
source: "TypeScript", | |
}; | |
} | |
let { line, character } = file.getLineAndCharacterOfPosition(diagnostic.start!); | |
return { | |
message: message, | |
location: { | |
fileName: file.fileName, | |
lineNumber: line + 1, | |
}, | |
source: "TypeScript", | |
}; | |
} | |
// | |
// Check and compile in-memory TypeScript code for errors. | |
// | |
export async function compileTypeScriptCode(code: string, projectPath: string, libs: string[], tsModule?: any): Promise<ICompilationResult> { | |
const ts = tsModule || require(path.join(projectPath, "node_modules/typescript")); | |
const tsConfigFilePath = path.join(projectPath, "tsconfig.json"); | |
const tsConfigFile = await readJsonFile(tsConfigFilePath); | |
const parsedOptions = ts.convertCompilerOptionsFromJson(tsConfigFile.compilerOptions, ""); | |
if (parsedOptions.errors && parsedOptions.errors.length > 0) { | |
return { | |
diagnostics: parsedOptions.errors | |
.map((diagnostic: any) => convertDiagnostic(diagnostic, ts)), | |
}; | |
} | |
const tsConfig = parsedOptions.options; | |
tsConfig.sourceMap = true; | |
tsConfig.inlineSourceMap = false; | |
const realHost = ts.createCompilerHost(tsConfig, true); | |
const baseDummyFilePath = path.join(projectPath, tsConfig.rootDir, "in-memory-file").replace(/\\/g, '/'); | |
const dummyFilePath = baseDummyFilePath + ".ts"; | |
const outputFilePath = path.join(tsConfig.outDir, "in-memory-file.js").replace(/\\/g, '/'); | |
const dummySourceFile = ts.createSourceFile(dummyFilePath, code, ts.ScriptTarget.ES5); | |
let outputCode: string | undefined = undefined; | |
let sourceMap: any | undefined = undefined; | |
const host = { | |
fileExists: (filePath: any) => filePath === dummyFilePath || realHost.fileExists(filePath), | |
directoryExists: realHost.directoryExists && realHost.directoryExists.bind(realHost), | |
getCurrentDirectory: () => projectPath, | |
getDirectories: realHost.getDirectories && realHost.getDirectories.bind(realHost), | |
getCanonicalFileName: realHost.getCanonicalFileName.bind(realHost), | |
getNewLine: realHost.getNewLine.bind(realHost), | |
getDefaultLibFileName: realHost.getDefaultLibFileName.bind(realHost), | |
getSourceFile: (fileName: any, languageVersion: any, onError: any, shouldCreateNewSourceFile: any) => fileName === dummyFilePath | |
? dummySourceFile | |
: realHost.getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile), | |
readFile: (filePath: any) => filePath === dummyFilePath | |
? code | |
: realHost.readFile(filePath), | |
useCaseSensitiveFileNames: realHost.useCaseSensitiveFileNames.bind(realHost), | |
writeFile: (fileName: any, data: any) => { | |
if (fileName === outputFilePath) { | |
outputCode = data; | |
} | |
else if (fileName === outputFilePath + ".map") { | |
sourceMap = JSON.parse(data); | |
} | |
} | |
}; | |
const program = ts.createProgram([dummyFilePath], tsConfig, host); | |
const emitResult = program.emit(); | |
const diagnostics = ts.getPreEmitDiagnostics(program); | |
return { | |
code: outputCode, | |
diagnostics: emitResult.diagnostics | |
.concat(diagnostics) | |
.map((diagnostic: any) => convertDiagnostic(diagnostic, ts)), | |
sourceMap, | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment