UNPKG

3.18 kBPlain TextView Raw
1import * as fs from 'fs';
2import * as os from 'os';
3import * as path from 'path';
4import * as zlib from 'zlib';
5import { createHash } from 'crypto';
6
7export interface CompiledModule {
8 fileName: string;
9 text: string;
10 map?: string;
11 mapName?: string;
12}
13
14export function findCompiledModule(fileName: string): CompiledModule {
15 let baseFileName = fileName.replace(/(\.ts|\.tsx)$/, '');
16 let compiledFileName = `${baseFileName}.js`;
17
18 if (fs.existsSync(compiledFileName)) {
19 let mapFileName = `${baseFileName}.js.map`;
20 let isMapExists = fs.existsSync(mapFileName);
21 let result = {
22 fileName: compiledFileName,
23 text: fs.readFileSync(compiledFileName).toString(),
24 mapName: isMapExists
25 ? mapFileName
26 : null,
27 map: isMapExists
28 ? fs.readFileSync(mapFileName).toString()
29 : null
30 };
31 return result;
32 } else {
33 return null;
34 }
35}
36
37/**
38 * Read the contents from the compressed file.
39 */
40function read(filename: string) {
41 let content = fs.readFileSync(filename);
42 let jsonString = zlib.gunzipSync(content);
43 return JSON.parse(jsonString.toString());
44}
45
46/**
47 * Write contents into a compressed file.
48 *
49 * @params {String} filename
50 * @params {String} result
51 */
52function write(filename: string, result: any) {
53 let jsonString = JSON.stringify(result);
54 let content = zlib.gzipSync(jsonString as any);
55 return fs.writeFileSync(filename, content);
56}
57
58/**
59 * Build the filename for the cached file
60 *
61 * @params {String} source File source code
62 * @params {Object} options Options used
63 *
64 * @return {String}
65 */
66function filename(source: string, identifier, options) {
67 let hash = createHash('sha512') as any;
68 let contents = JSON.stringify({
69 identifier: identifier,
70 options: options,
71 source: source,
72 });
73
74 hash.end(contents);
75
76 return hash.read().toString('hex') + '.json.gzip';
77};
78
79export interface CacheParams<T> {
80 source: string;
81 options: any;
82 transform: () => Promise<T>;
83 identifier: any;
84 directory: string;
85}
86
87/**
88 * Retrieve file from cache, or create a new one for future reads
89 */
90export function cache<T>(params: CacheParams<T>): Promise<{cached: boolean, result: T}> {
91 // Spread params into named variables
92 // Forgive user whenever possible
93 let source = params.source;
94 let options = params.options || {};
95 let transform = params.transform;
96 let identifier = params.identifier;
97 let directory = (typeof params.directory === 'string') ?
98 params.directory :
99 os.tmpdir();
100
101 let file = path.join(directory, filename(source, identifier, options));
102
103 try {
104 // No errors mean that the file was previously cached
105 // we just need to return it
106 return Promise.resolve({cached: true, result: read(file)});
107 } catch(e) {
108 // Otherwise just transform the file
109 // return it to the user asap and write it in cache
110 return transform().then(result => {
111 write(file, result);
112 return {cached: false, result};
113 });
114 }
115}