awesome-typescript-loader
Version:
Awesome TS loader for webpack
116 lines (103 loc) • 3.18 kB
text/typescript
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import * as zlib from 'zlib';
import { createHash } from 'crypto';
export interface CompiledModule {
fileName: string;
text: string;
map?: string;
mapName?: string;
}
export function findCompiledModule(fileName: string): CompiledModule {
let baseFileName = fileName.replace(/(\.ts|\.tsx)$/, '');
let compiledFileName = `${baseFileName}.js`;
if (fs.existsSync(compiledFileName)) {
let mapFileName = `${baseFileName}.js.map`;
let isMapExists = fs.existsSync(mapFileName);
let result = {
fileName: compiledFileName,
text: fs.readFileSync(compiledFileName).toString(),
mapName: isMapExists
? mapFileName
: null,
map: isMapExists
? fs.readFileSync(mapFileName).toString()
: null
};
return result;
} else {
return null;
}
}
/**
* Read the contents from the compressed file.
*/
function read(filename: string) {
let content = fs.readFileSync(filename);
let jsonString = zlib.gunzipSync(content);
return JSON.parse(jsonString.toString());
}
/**
* Write contents into a compressed file.
*
* @params {String} filename
* @params {String} result
*/
function write(filename: string, result: any) {
let jsonString = JSON.stringify(result);
let content = zlib.gzipSync(jsonString as any);
return fs.writeFileSync(filename, content);
}
/**
* Build the filename for the cached file
*
* @params {String} source File source code
* @params {Object} options Options used
*
* @return {String}
*/
function filename(source: string, identifier, options) {
let hash = createHash('sha512') as any;
let contents = JSON.stringify({
identifier: identifier,
options: options,
source: source,
});
hash.end(contents);
return hash.read().toString('hex') + '.json.gzip';
};
export interface CacheParams<T> {
source: string;
options: any;
transform: () => Promise<T>;
identifier: any;
directory: string;
}
/**
* Retrieve file from cache, or create a new one for future reads
*/
export function cache<T>(params: CacheParams<T>): Promise<{cached: boolean, result: T}> {
// Spread params into named variables
// Forgive user whenever possible
let source = params.source;
let options = params.options || {};
let transform = params.transform;
let identifier = params.identifier;
let directory = (typeof params.directory === 'string') ?
params.directory :
os.tmpdir();
let file = path.join(directory, filename(source, identifier, options));
try {
// No errors mean that the file was previously cached
// we just need to return it
return Promise.resolve({cached: true, result: read(file)});
} catch(e) {
// Otherwise just transform the file
// return it to the user asap and write it in cache
return transform().then(result => {
write(file, result);
return {cached: false, result};
});
}
}