JavaScript build system hell
This commit is contained in:
parent
c7a62924e6
commit
73e74516a7
|
@ -1 +1,4 @@
|
|||
*.log
|
||||
.log
|
||||
node_modules
|
||||
out
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
import * as pty from "node-pty";
|
||||
import { IPty } from "node-pty";
|
||||
|
||||
import { LangConfig, langs } from "./langs";
|
||||
|
||||
export class Session {
|
||||
config: LangConfig;
|
||||
term: IPty;
|
||||
ws: WebSocket;
|
||||
|
||||
constructor(ws, lang) {
|
||||
this.ws = ws;
|
||||
this.config = langs[lang];
|
||||
this.term = null;
|
||||
this.run();
|
||||
ws.on("message", this.handleClientMessage);
|
||||
}
|
||||
handleClientMessage(msg) {
|
||||
try {
|
||||
msg = JSON.parse(msg);
|
||||
} catch (err) {
|
||||
console.error(`failed to parse client message: ${msg}`);
|
||||
return;
|
||||
}
|
||||
switch (msg.event) {
|
||||
case "terminalInput":
|
||||
if (!this.term) {
|
||||
console.error(`terminalInput: no terminal`);
|
||||
} else if (typeof msg.input !== "string") {
|
||||
console.error(`terminalInput: missing or malformed input field`);
|
||||
} else {
|
||||
this.term.write(msg.input);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.error(`unknown client message type: ${msg.event}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
run() {
|
||||
const cmdline = this.config.cmdline;
|
||||
if (this.term) {
|
||||
this.term.kill();
|
||||
}
|
||||
this.term = pty.spawn(cmdline[0], cmdline.slice(1), {
|
||||
name: "xterm-color",
|
||||
cwd: process.env.PWD,
|
||||
env: process.env,
|
||||
});
|
||||
this.term.on("data", (data) =>
|
||||
this.ws.send(JSON.stringify({ event: "terminalOutput", output: data }))
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
declare module "heroku-ssl-redirect";
|
|
@ -0,0 +1,27 @@
|
|||
export interface LangConfig {
|
||||
cmdline: string[];
|
||||
name: string;
|
||||
}
|
||||
|
||||
export const langs = {
|
||||
c: {
|
||||
cmdline: ["echo", "not implemented"],
|
||||
name: "C",
|
||||
},
|
||||
"c++": {
|
||||
cmdline: ["echo", "not implemented"],
|
||||
name: "C++",
|
||||
},
|
||||
haskell: {
|
||||
cmdline: ["ghci"],
|
||||
name: "Haskell",
|
||||
},
|
||||
nodejs: {
|
||||
cmdline: ["node"],
|
||||
name: "Node.js",
|
||||
},
|
||||
python: {
|
||||
cmdline: ["python3"],
|
||||
name: "Python",
|
||||
},
|
||||
};
|
|
@ -0,0 +1,42 @@
|
|||
import * as appRoot from "app-root-path";
|
||||
import * as express from "express";
|
||||
import * as ws from "express-ws";
|
||||
import * as sslRedirect from "heroku-ssl-redirect";
|
||||
|
||||
import * as api from "./api";
|
||||
import { langs } from "./langs";
|
||||
|
||||
const app = ws(express()).app;
|
||||
const host = process.env.HOST || "localhost";
|
||||
const port = parseInt(process.env.PORT) || 6119;
|
||||
|
||||
app.use(sslRedirect());
|
||||
app.get("/", (_, res) => {
|
||||
res.sendFile(appRoot.path + "/frontend/pages/index.html");
|
||||
});
|
||||
app.get("/:lang", (req, res) => {
|
||||
if (langs[req.params.lang]) {
|
||||
res.sendFile(appRoot.path + "/frontend/pages/app.html");
|
||||
} else {
|
||||
res.send(`No such language: ${req.params.lang}`);
|
||||
}
|
||||
});
|
||||
app.use("/js", express.static(appRoot.path + "/frontend/out"));
|
||||
app.use("/api/v1/ws", (req, res, next) => {
|
||||
if (!req.query.lang) {
|
||||
res.status(400);
|
||||
res.send("No language specified");
|
||||
} else if (!langs[req.query.lang as string]) {
|
||||
res.status(400);
|
||||
res.send(`No such language: ${req.query.lang}`);
|
||||
} else {
|
||||
return next();
|
||||
}
|
||||
});
|
||||
app.ws("/api/v1/ws", (ws, req) => {
|
||||
new api.Session(ws, req.query.lang);
|
||||
});
|
||||
|
||||
app.listen(port, host, () =>
|
||||
console.log(`Listening on http://${host}:${port}`)
|
||||
);
|
|
@ -3,6 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Fast Sandbox</title>
|
||||
<script src="/js/app.js" async defer></script>
|
||||
</head>
|
||||
<body>
|
||||
Editor :)
|
|
@ -0,0 +1 @@
|
|||
console.log("Hi there");
|
17
langs.json
17
langs.json
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"c": {
|
||||
"name": "C"
|
||||
},
|
||||
"c++": {
|
||||
"name": "C++"
|
||||
},
|
||||
"haskell": {
|
||||
"name": "Haskell"
|
||||
},
|
||||
"nodejs": {
|
||||
"name": "Node.js"
|
||||
},
|
||||
"python": {
|
||||
"name": "Python"
|
||||
}
|
||||
}
|
16
package.json
16
package.json
|
@ -4,10 +4,24 @@
|
|||
"license": "MIT",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@types/app-root-path": "^1.2.4",
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/express-ws": "^3.0.0",
|
||||
"app-root-path": "^3.0.0",
|
||||
"express": "^4.17.1",
|
||||
"express-ws": "^4.0.0",
|
||||
"heroku-ssl-redirect": "^0.0.4",
|
||||
"node-pty": "^0.9.0"
|
||||
"node-pty": "^0.9.0",
|
||||
"typescript": "^3.9.5",
|
||||
"webpack": "^4.43.0",
|
||||
"webpack-cli": "^3.3.11"
|
||||
},
|
||||
"scripts": {
|
||||
"backend": "tsc",
|
||||
"backend-dev": "tsc --watch",
|
||||
"frontend": "webpack --production",
|
||||
"frontend-dev": "webpack --development --watch",
|
||||
"server": "node server.js",
|
||||
"server-dev": "watchexec -w backend/out -r -n node backend/out/server.js"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
const appRoot = require("app-root-path");
|
||||
|
||||
const langs = require(appRoot + "/langs");
|
||||
|
||||
const express = require("express");
|
||||
const sslRedirect = require("heroku-ssl-redirect");
|
||||
|
||||
const app = express();
|
||||
const host = process.env.HOST || "localhost";
|
||||
const port = parseInt(process.env.PORT) || 6119;
|
||||
|
||||
app.use(sslRedirect());
|
||||
app.get("/:lang", (req, res) => {
|
||||
if (langs[req.params.lang]) {
|
||||
res.sendFile(appRoot + "/dynamic/app.html");
|
||||
} else {
|
||||
res.send(`No such language: ${req.params.lang}`);
|
||||
}
|
||||
});
|
||||
app.use("/", express.static(appRoot + "/static"));
|
||||
|
||||
app.listen(port, host, () =>
|
||||
console.log(`Listening on http://${host}:${port}`)
|
||||
);
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "./backend/out",
|
||||
"resolveJsonModule": true,
|
||||
"rootDir": "./backend/src",
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": ["backend/src"]
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
const path = require("path");
|
||||
|
||||
module.exports = {
|
||||
entry: "./frontend/src/app.ts",
|
||||
mode: process.env.NODE_ENV || "production",
|
||||
output: {
|
||||
path: path.resolve(__dirname, "frontend/out"),
|
||||
filename: "app.js",
|
||||
},
|
||||
};
|
Loading…
Reference in New Issue