@typed/test
Version:
Testing made simple.
113 lines • 4.35 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const crypto_1 = require("crypto");
const fs_1 = require("fs");
const path_1 = require("path");
const tempy_1 = require("tempy");
const typescript_1 = require("typescript");
const diagnosticToString_1 = require("./diagnosticToString");
// tslint:disable-next-line:no-var-requires
const sourceMapSupport = require('source-map-support');
const DEFAULT_COMPILER_OPTIONS = {
sourceMap: true,
inlineSourceMap: false,
inlineSources: true,
declaration: false,
noEmit: false,
outDir: '$$ts-transpilation$$',
};
function transpileNode(cwd, compilerOptions) {
compilerOptions = Object.assign(Object.assign({}, compilerOptions), DEFAULT_COMPILER_OPTIONS);
const cacheDirectory = tempy_1.directory();
const originalJsHandler = require.extensions['.js'];
const memoryCache = {
contents: Object.create(null),
outputs: Object.create(null),
};
const extensions = ['.ts', '.tsx'];
const compile = (code, fileName) => {
const result = typescript_1.transpileModule(code, {
fileName,
compilerOptions,
reportDiagnostics: true,
});
const diagnosticList = result.diagnostics;
if (diagnosticList && diagnosticList.length) {
throw new Error(diagnosticToString_1.diagnosticsToString(diagnosticList, cwd));
}
return [result.outputText, result.sourceMapText];
};
sourceMapSupport.install({
environment: 'node',
retrieveFile(path) {
return memoryCache.outputs[path];
},
});
const register = {
cwd,
cacheDirectory,
extensions,
compile: readThrough(cacheDirectory, memoryCache, compile, path_1.extname),
};
extensions.forEach(extension => {
registerExtension(extension, register, originalJsHandler);
});
}
exports.transpileNode = transpileNode;
function readThrough(cachedir, memoryCache, compile, getExtension) {
// Make sure the cache directory exists before continuing.
return (code, fileName) => {
const cachePath = path_1.join(cachedir, getCacheName(code, fileName));
const extension = getExtension(fileName);
const outputPath = `${cachePath}${extension}`;
try {
const contents = fs_1.readFileSync(outputPath, 'utf8');
if (isValidCacheContent(contents)) {
memoryCache.outputs[fileName] = contents;
return contents;
}
}
catch (err) {
/* Ignore. */
}
const [value, sourceMap] = compile(code, fileName);
const output = updateOutput(value, fileName, sourceMap, getExtension);
memoryCache.outputs[fileName] = output;
fs_1.writeFileSync(outputPath, output);
return output;
};
}
function updateOutput(outputText, fileName, sourceMap, getExtension) {
const base64Map = Buffer.from(updateSourceMap(sourceMap, fileName), 'utf8').toString('base64');
const sourceMapContent = `data:application/json;charset=utf-8;base64,${base64Map}`;
const sourceMapLength = `${path_1.basename(fileName)}.map`.length + (getExtension(fileName).length - path_1.extname(fileName).length);
return outputText.slice(0, -sourceMapLength) + sourceMapContent;
}
function updateSourceMap(sourceMapText, fileName) {
const sourceMap = JSON.parse(sourceMapText);
sourceMap.file = fileName;
sourceMap.sources = [fileName];
delete sourceMap.sourceRoot;
return JSON.stringify(sourceMap);
}
function isValidCacheContent(contents) {
return /(?:9|0=|Q==)$/.test(contents.slice(-3));
}
function getCacheName(sourceCode, fileName) {
return crypto_1.createHash('sha256')
.update(path_1.extname(fileName), 'utf8')
.update('\x00', 'utf8')
.update(sourceCode, 'utf8')
.digest('hex');
}
function registerExtension(ext, register, originalHandler) {
const old = require.extensions[ext] || originalHandler;
require.extensions[ext] = (m, filename) => {
const _compile = m._compile;
m._compile = function (code, fileName) {
return _compile.call(this, register.compile(code, fileName), fileName);
};
return old(m, filename);
};
}
//# sourceMappingURL=transpileNode.js.map