///
"use strict";
var http = require("http");
var fs = require("fs");
var path = require("path");
var url = require("url");
var child_process = require("child_process");
var os = require("os");
/// Command line processing ///
if (process.argv[2] == '--help') {
console.log('Runs a node server on port 8888 by default, looking for tests folder in the current directory\n');
console.log('Syntax: node nodeServer.js [port] [typescriptEnlistmentDirectory] [tests] [--browser] [--verbose]\n');
console.log('Examples: \n\tnode nodeServer.js 8888 .');
console.log('\tnode nodeServer.js 3000 D:/src/typescript/public --verbose IE');
}
function switchToForwardSlashes(path) {
return path.replace(/\\/g, "/").replace(/\/\//g, '/');
}
var defaultPort = 8888;
var port = process.argv[2] || defaultPort;
var rootDir = switchToForwardSlashes(__dirname + '/../');
var browser;
if (process.argv[3]) {
browser = process.argv[3];
if (browser !== 'chrome' && browser !== 'IE') {
console.log('Invalid command line arguments. Got ' + browser + ' but expected chrome, IE or nothing.');
}
}
var grep = process.argv[4];
var verbose = false;
if (process.argv[5] == '--verbose') {
verbose = true;
}
else if (process.argv[5] && process.argv[5] !== '--verbose') {
console.log('Invalid command line arguments. Got ' + process.argv[5] + ' but expected --verbose or nothing.');
}
/// Utils ///
function log(msg) {
if (verbose) {
console.log(msg);
}
}
// Copied from the compiler sources
function dir(path, spec, options) {
options = options || {};
function filesInFolder(folder) {
var folder = switchToForwardSlashes(folder);
var paths = [];
// Everything after the current directory is relative
var baseDirectoryLength = process.cwd().length + 1;
try {
var files = fs.readdirSync(folder);
for (var i = 0; i < files.length; i++) {
var stat = fs.statSync(folder + "/" + files[i]);
if (options.recursive && stat.isDirectory()) {
paths = paths.concat(filesInFolder(folder + "/" + files[i]));
}
else if (stat.isFile() && (!spec || files[i].match(spec))) {
var relativePath = folder.substring(baseDirectoryLength);
paths.push(relativePath + "/" + files[i]);
}
}
}
catch (err) {
}
return paths;
}
return filesInFolder(path);
}
// fs.rmdirSync won't delete directories with files in it
function deleteFolderRecursive(path) {
if (fs.existsSync(path)) {
fs.readdirSync(path).forEach(function (file, index) {
var curPath = path + "/" + file;
if (fs.statSync(curPath).isDirectory()) {
deleteFolderRecursive(curPath);
}
else {
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(path);
}
}
;
function writeFile(path, data, opts) {
try {
fs.writeFileSync(path, data);
}
catch (e) {
// assume file was written to a directory that exists, if not, start recursively creating them as necessary
var parts = switchToForwardSlashes(path).split('/');
for (var i = 0; i < parts.length; i++) {
var subDir = parts.slice(0, i).join('/');
if (!fs.existsSync(subDir)) {
fs.mkdir(subDir);
}
}
fs.writeFileSync(path, data);
}
}
/// Request Handling ///
function handleResolutionRequest(filePath, res) {
var resolvedPath = path.resolve(filePath, '');
resolvedPath = resolvedPath.substring(resolvedPath.indexOf('tests'));
resolvedPath = switchToForwardSlashes(resolvedPath);
send('success', res, resolvedPath);
return;
}
function send(result, res, contents, contentType) {
if (contentType === void 0) { contentType = "binary"; }
var responseCode = result === "success" ? 200 : result === "fail" ? 500 : result === 'unknown' ? 404 : parseInt(result);
res.writeHead(responseCode, { "Content-Type": contentType });
res.end(contents);
return;
}
// Reads the data from a post request and passes it to the given callback
function processPost(req, res, callback) {
var queryData = "";
if (typeof callback !== 'function')
return null;
if (req.method == 'POST') {
req.on('data', function (data) {
queryData += data;
if (queryData.length > 1e8) {
queryData = "";
send("413", res, null);
console.log("ERROR: destroying connection");
req.connection.destroy();
}
});
req.on('end', function () {
//res.post = url.parse(req.url).query;
callback(queryData);
});
}
else {
send("405", res, null);
}
}
var RequestType;
(function (RequestType) {
RequestType[RequestType["GetFile"] = 0] = "GetFile";
RequestType[RequestType["GetDir"] = 1] = "GetDir";
RequestType[RequestType["ResolveFile"] = 2] = "ResolveFile";
RequestType[RequestType["WriteFile"] = 3] = "WriteFile";
RequestType[RequestType["DeleteFile"] = 4] = "DeleteFile";
RequestType[RequestType["WriteDir"] = 5] = "WriteDir";
RequestType[RequestType["DeleteDir"] = 6] = "DeleteDir";
RequestType[RequestType["AppendFile"] = 7] = "AppendFile";
RequestType[RequestType["Unknown"] = 8] = "Unknown";
})(RequestType || (RequestType = {}));
function getRequestOperation(req, filename) {
if (req.method === 'GET' && req.url.indexOf('?') === -1) {
if (req.url.indexOf('.') !== -1)
return RequestType.GetFile;
else
return RequestType.GetDir;
}
else {
var queryData = url.parse(req.url, true).query;
if (req.method === 'GET' && queryData.resolve !== undefined)
return RequestType.ResolveFile;
// mocha uses ?grep= query string as equivalent to the --grep command line option used to filter tests
if (req.method === 'GET' && queryData.grep !== undefined)
return RequestType.GetFile;
if (req.method === 'POST' && queryData.action) {
var path = req.url.substr(0, req.url.lastIndexOf('?'));
var isFile = path.substring(path.lastIndexOf('/')).indexOf('.') !== -1;
switch (queryData.action.toUpperCase()) {
case 'WRITE':
return isFile ? RequestType.WriteFile : RequestType.WriteDir;
case 'DELETE':
return isFile ? RequestType.DeleteFile : RequestType.DeleteDir;
case 'APPEND':
return isFile ? RequestType.AppendFile : RequestType.Unknown;
}
}
return RequestType.Unknown;
}
}
function handleRequestOperation(req, res, operation, reqPath) {
switch (operation) {
case RequestType.GetDir:
var filesInFolder = dir(reqPath, "", { recursive: true });
send('success', res, filesInFolder.join(','));
break;
case RequestType.GetFile:
fs.readFile(reqPath, function (err, file) {
var ext = reqPath.substr(reqPath.lastIndexOf('.'));
var contentType = 'binary';
if (ext === '.js')
contentType = 'text/javascript';
else if (ext === '.css')
contentType = 'text/javascript';
else if (ext === '.html')
contentType = 'text/html';
err
? send('fail', res, err.message, contentType)
: send('success', res, file, contentType);
});
break;
case RequestType.ResolveFile:
var resolveRequest = req.url.match(/(.*)\?resolve/);
handleResolutionRequest(resolveRequest[1], res);
break;
case RequestType.WriteFile:
processPost(req, res, function (data) {
writeFile(reqPath, data, { recursive: true });
});
send('success', res, null);
break;
case RequestType.WriteDir:
fs.mkdirSync(reqPath);
send('success', res, null);
break;
case RequestType.DeleteFile:
if (fs.existsSync(reqPath)) {
fs.unlinkSync(reqPath);
}
send('success', res, null);
break;
case RequestType.DeleteDir:
if (fs.existsSync(reqPath)) {
fs.rmdirSync(reqPath);
}
send('success', res, null);
break;
case RequestType.AppendFile:
processPost(req, res, function (data) {
fs.appendFileSync(reqPath, data);
});
send('success', res, null);
break;
case RequestType.Unknown:
default:
send('unknown', res, null);
break;
}
}
console.log("Static file server running at\n => http://localhost:" + port + "/\nCTRL + C to shutdown");
http.createServer(function (req, res) {
log(req.method + ' ' + req.url);
var uri = url.parse(req.url).pathname;
var reqPath = path.join(process.cwd(), uri);
var operation = getRequestOperation(req, reqPath);
handleRequestOperation(req, res, operation, reqPath);
}).listen(8888);
var browserPath;
if ((browser && browser === 'chrome')) {
var defaultChromePath = "";
switch (os.platform()) {
case "win32":
case "win64":
defaultChromePath = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe";
break;
case "darwin":
defaultChromePath = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
break;
case "linux":
defaultChromePath = "/opt/google/chrome/chrome";
break;
default:
console.log("default Chrome location is unknown for platform '" + os.platform() + "'");
break;
}
if (fs.existsSync(defaultChromePath)) {
browserPath = defaultChromePath;
}
else {
browserPath = browser;
}
}
else {
var defaultIEPath = 'C:/Program Files/Internet Explorer/iexplore.exe';
if (fs.existsSync(defaultIEPath)) {
browserPath = defaultIEPath;
}
else {
browserPath = browser;
}
}
console.log('Using browser: ' + browserPath);
var queryString = grep ? "?grep=" + grep : '';
child_process.spawn(browserPath, ['http://localhost:' + port + '/tests/webTestResults.html' + queryString], {
stdio: 'inherit'
});
//# sourceMappingURL=file:///E:/ts/tests/webTestServer.js.map