|
// @ts-check |
|
|
|
// Script to either host a local web server or run npm scripts |
|
|
|
const http = require("http"); |
|
const fs = require("fs"); |
|
const path = require("path"); |
|
const cp = require("child_process"); |
|
|
|
const folder = process.argv.length <= 2 ? process.cwd() : path.resolve(process.argv[2]); |
|
|
|
console.log(folder); |
|
|
|
if (!fs.existsSync(folder)) { |
|
console.log("Error: Path does not exist"); |
|
process.exit(1); |
|
} |
|
|
|
if (fs.existsSync(folder + "/package.json")) { |
|
let obj; |
|
try { |
|
obj = JSON.parse(fs.readFileSync(folder + "/package.json", "utf8")); |
|
} catch (err) { |
|
console.log("Could not interpret package json:"); |
|
console.log(err); |
|
} |
|
if (!obj) { |
|
startLocalWebServer(); |
|
} else { |
|
const npmArgs = ["run"]; |
|
if (obj.scripts && obj.scripts.start) { |
|
npmArgs.push('start'); |
|
} else if (obj.scripts && obj.scripts.serve) { |
|
npmArgs.push('serve'); |
|
} |
|
|
|
if (npmArgs.length > 1) { |
|
startNPMScript(npmArgs); |
|
} else { |
|
startLocalWebServer(); |
|
} |
|
} |
|
} else { |
|
startLocalWebServer(); |
|
} |
|
|
|
/** |
|
* Returns a UTC-3 datetime string in the format "yyyy-mm-dd hh/mm/ss" |
|
* @param {Date} date |
|
*/ |
|
function getBrazilianDateTimeString(date = new Date()) { |
|
date.setTime(date.getTime() - 3 * 60 * 60 * 1000); |
|
return date.toISOString().replace("T", " ").split(".")[0]; |
|
} |
|
|
|
function getLogPrefix() { |
|
return "[" + getBrazilianDateTimeString() + "]"; |
|
} |
|
|
|
function startLocalWebServer() { |
|
const server = http.createServer(onRequestStart); |
|
|
|
server.listen(8080, onStartListening); |
|
|
|
function onStartListening() { |
|
const htmlFiles = fs.readdirSync(folder).filter(file => file.endsWith(".html")); |
|
let startScript = "start http://localhost:8080/"; |
|
if (htmlFiles.length > 0 && !htmlFiles.includes("index.html")) { |
|
startScript = "start http://localhost:8080/"+htmlFiles[0]; |
|
} |
|
cp.execSync(startScript); |
|
console.log(getLogPrefix(), "Started web server at http://localhost:8080/"); |
|
} |
|
|
|
|
|
function getMimeTypeFromExtension(extension = "txt") { |
|
if (extension[0] === ".") { |
|
extension = extension.substr(1); |
|
} |
|
return { |
|
"aac": "audio/aac", |
|
"abw": "application/x-abiword", |
|
"arc": "application/x-freearc", |
|
"avi": "video/x-msvideo", |
|
"azw": "application/vnd.amazon.ebook", |
|
"bin": "application/octet-stream", |
|
"bmp": "image/bmp", |
|
"bz": "application/x-bzip", |
|
"bz2": "application/x-bzip2", |
|
"cda": "application/x-cdf", |
|
"csh": "application/x-csh", |
|
"css": "text/css", |
|
"csv": "text/csv", |
|
"doc": "application/msword", |
|
"docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", |
|
"eot": "application/vnd.ms-fontobject", |
|
"epub": "application/epub+zip", |
|
"gz": "application/gzip", |
|
"gif": "image/gif", |
|
"htm": "text/html", |
|
"html": "text/html", |
|
"ico": "image/vnd.microsoft.icon", |
|
"ics": "text/calendar", |
|
"jar": "application/java-archive", |
|
"jpeg": "image/jpeg", |
|
"jpg": "image/jpeg", |
|
"js": "text/javascript", |
|
"json": "application/json", |
|
"jsonld": "application/ld+json", |
|
"mid": "audio/midi audio/x-midi", |
|
"midi": "audio/midi audio/x-midi", |
|
"mjs": "text/javascript", |
|
"mp3": "audio/mpeg", |
|
"mp4": "video/mp4", |
|
"mpeg": "video/mpeg", |
|
"mpkg": "application/vnd.apple.installer+xml", |
|
"odp": "application/vnd.oasis.opendocument.presentation", |
|
"ods": "application/vnd.oasis.opendocument.spreadsheet", |
|
"odt": "application/vnd.oasis.opendocument.text", |
|
"oga": "audio/ogg", |
|
"ogv": "video/ogg", |
|
"ogx": "application/ogg", |
|
"opus": "audio/opus", |
|
"otf": "font/otf", |
|
"png": "image/png", |
|
"pdf": "application/pdf", |
|
"php": "application/x-httpd-php", |
|
"ppt": "application/vnd.ms-powerpoint", |
|
"pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation", |
|
"rar": "application/vnd.rar", |
|
"rtf": "application/rtf", |
|
"sh": "application/x-sh", |
|
"svg": "image/svg+xml", |
|
"swf": "application/x-shockwave-flash", |
|
"tar": "application/x-tar", |
|
"tif": "image/tiff", |
|
"tiff": "image/tiff", |
|
"ts": "video/mp2t", |
|
"ttf": "font/ttf", |
|
"txt": "text/plain", |
|
"vsd": "application/vnd.visio", |
|
"wav": "audio/wav", |
|
"weba": "audio/webm", |
|
"webm": "video/webm", |
|
"webp": "image/webp", |
|
"woff": "font/woff", |
|
"woff2": "font/woff2", |
|
"xhtml": "application/xhtml+xml", |
|
"xls": "application/vnd.ms-excel", |
|
"xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", |
|
"xml": "application/xml", |
|
"xul": "application/vnd.mozilla.xul+xml", |
|
"zip": "application/zip", |
|
"3gp": "video/3gpp", |
|
"3g2": "video/3gpp2", |
|
"7z": "application/x-7z-compressed" |
|
}[extension] || "application/octet-stream"; |
|
} |
|
|
|
/** |
|
* @param {http.IncomingMessage} req |
|
* @param {http.ServerResponse} res |
|
*/ |
|
function onRequestStart(req, res) { |
|
console.log(getLogPrefix(), req.method + " request from", req.socket.address(), "for", req.url); |
|
if (req.method !== "GET") { |
|
res.writeHead(405, "Method Not Allowed"); |
|
return res.end(); |
|
} |
|
const target = path.resolve(folder + req.url); |
|
if (!fs.existsSync(target)) { |
|
res.writeHead(404, "Not Found"); |
|
return res.end(); |
|
} |
|
res.setHeader("Content-type", getMimeTypeFromExtension(path.extname(target) || ".html")); |
|
if (fs.statSync(target).isDirectory()) { |
|
if (fs.existsSync(target + "/index.html")) { |
|
res.write(fs.readFileSync(target + "/index.html"), (err) => { |
|
if (err) { |
|
console.log(err); |
|
} |
|
res.end(); |
|
}); |
|
return; |
|
} else { |
|
res.writeHead(404, "Not Found"); |
|
return res.end(); |
|
} |
|
} |
|
res.write(fs.readFileSync(target), (err) => { |
|
if (err) { |
|
console.log(err); |
|
} |
|
res.end(); |
|
}); |
|
return; |
|
} |
|
} |
|
|
|
function startNPMScript(npmArgs) { |
|
const npmPath = "C:\\Program Files\\nodejs\\npm"; |
|
if (!fs.existsSync(npmPath)) { |
|
console.log("Could not find npm at " + npmPath); |
|
return process.exit(1); |
|
} |
|
const child = cp.spawn( |
|
"\"" + npmPath + "\"", |
|
npmArgs, |
|
{ stdio: "inherit", cwd: folder, env: undefined, shell: true } |
|
); |
|
child.on("error", function(err) { |
|
console.log(err); |
|
process.exit(1); |
|
}); |
|
child.on("close", function(code) { |
|
process.exit(code); |
|
}); |
|
} |