2018-06-28 00:31:24 +04:00

107 lines
3.5 KiB
JavaScript

var moduleDeps = require("./module-deps");
var fs = require("fs");
var send = require("send");
exports.transform = function(code, options) {
if (/^"disable compress"/.test(code))
return code;
if (options.amd && moduleDeps.isCJS(code)) {
code = "define(function(require, exports, module) {" + code + "\n})";
}
if (options.mode == "ts" || options.mode == "es5") {
var ts = require("typescript");
return ts.transpileModule(code, {
compilerOptions: {
downlevelIteration: true,
suppressExcessPropertyErrors: true,
removeComments: true,
newLine: "lf",
module: ts.ModuleKind.CommonJS,
sourceMap: !!options.srcPath,
inlineSourceMap: true
},
fileName: options.srcPath
}).outputText;
}
return code;
};
var cache = Object.create(null);
exports.sendFile = function(req, res, next) {
var path = req.params.path;
var transform = req.params.transform;
var filePath = moduleDeps.resolveModulePath(path, req.pathConfig.pathMap);
if (!/\.(js|ts)$/.test(filePath) || /(browserified|\.min|test\d)\.js$/.test(filePath)) {
return send(req, filePath.substr(req.pathConfig.root.length))
.root(req.pathConfig.root)
.on('error', next)
.pipe(res);
}
function resolvePath(callback) {
fs.stat(filePath, function(err, stat) {
if (err && err.code == "ENOENT") {
var tsPath = filePath.replace(/\.js$/, ".ts");
if (tsPath != filePath) {
return fs.stat(tsPath, function(err, stat) {
callback(err, stat, tsPath);
});
}
}
callback(err, stat);
});
}
resolvePath(function(err, stat, srcPath) {
if (err) return next(err);
var mtime = stat.mtime.valueOf();
var etag = 'W/"' + stat.size.toString(16) + "-" + mtime.toString(16) + '"';
var noneMatch = req.headers && req.headers['if-none-match'];
if (noneMatch && noneMatch == etag) {
res.statusCode = 304;
res.end();
return;
}
var key = transform + "|" + path;
if (cache[key] && cache[key].etag == etag)
return sendResponse(cache[key].value);
res.setHeader("ETag", etag);
cache[key] = null;
fs.readFile(srcPath || filePath, "utf8", function(err, value) {
if (err)
return next(err);
var t = Date.now();
try {
value = exports.transform(value, {
path: filePath,
mode: srcPath ? "ts" : transform,
amd: true,
srcPath: srcPath ? path.replace(/\.js/, ".ts") : ""
});
} catch (e) {
return next(e);
}
cache[key] = { value: value, etag: etag };
var delta = Date.now() - t;
res.setHeader('Server-Timing', 'transform=' + delta);
sendResponse(value);
});
function sendResponse(value) {
res.setHeader('Content-Type', 'application/javascript');
res.setHeader('Cache-Control', 'public, max-age=0');
res.setHeader('Last-Modified', stat.mtime.toUTCString());
res.end(value);
}
});
};