JavaScript build system hell

This commit is contained in:
Radon Rosborough 2020-06-06 10:28:13 -06:00
parent c7a62924e6
commit 73e74516a7
14 changed files with 2991 additions and 49 deletions

3
.gitignore vendored
View File

@ -1 +1,4 @@
*.log
.log
node_modules
out

54
backend/src/api.ts Normal file
View File

@ -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 }))
);
}
}

1
backend/src/global.d.ts vendored Normal file
View File

@ -0,0 +1 @@
declare module "heroku-ssl-redirect";

27
backend/src/langs.ts Normal file
View File

@ -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",
},
};

42
backend/src/server.ts Normal file
View File

@ -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}`)
);

View File

@ -3,6 +3,7 @@
<head>
<meta charset="utf-8" />
<title>Fast Sandbox</title>
<script src="/js/app.js" async defer></script>
</head>
<body>
Editor :)

1
frontend/src/app.ts Normal file
View File

@ -0,0 +1 @@
console.log("Hi there");

View File

@ -1,17 +0,0 @@
{
"c": {
"name": "C"
},
"c++": {
"name": "C++"
},
"haskell": {
"name": "Haskell"
},
"nodejs": {
"name": "Node.js"
},
"python": {
"name": "Python"
}
}

View File

@ -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"
}
}

View File

@ -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}`)
);

9
tsconfig.json Normal file
View File

@ -0,0 +1,9 @@
{
"compilerOptions": {
"outDir": "./backend/out",
"resolveJsonModule": true,
"rootDir": "./backend/src",
"sourceMap": true
},
"include": ["backend/src"]
}

10
webpack.config.js Normal file
View File

@ -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",
},
};

2835
yarn.lock

File diff suppressed because it is too large Load Diff