- ${statusCode} ${status}
-
-
- ${error.message}
- diff --git a/packages/polydev/package.json b/packages/polydev/package.json index 79ede6d..be6825e 100644 --- a/packages/polydev/package.json +++ b/packages/polydev/package.json @@ -11,7 +11,7 @@ "src" ], "dependencies": { - "body-parser": "^1.18.3", + "ansi-to-html": "^0.6.10", "chokidar": "^2.0.4", "debug": "^4.1.1", "express": "^4.16.4", @@ -21,6 +21,8 @@ "opn": "^5.4.0", "raw-body": "^2.3.3", "uuid": "^3.3.2", - "wait-on": "^3.2.0" + "wait-on": "^3.2.0", + "youch": "^2.0.10", + "youch-terminal": "^1.0.0" } } diff --git a/packages/polydev/src/index.js b/packages/polydev/src/index.js index d95a471..32d216b 100644 --- a/packages/polydev/src/index.js +++ b/packages/polydev/src/index.js @@ -5,16 +5,27 @@ const middleware = require("./middleware") const { NODE_ENV = "development" } = process.env +const verify = (req, res, buffer, encoding = "utf8") => { + if (buffer && buffer.length) { + req.rawBody = buffer.toString(encoding) + } +} + module.exports.polydev = (options = {}) => { const { assets = "public", routes = "routes" } = options const app = express() + // req.body is needed + app.use(express.urlencoded({ extended: true, verify })) + app.use(express.json({ verify })) + app.use(middleware.assets(assets)) app.use(middleware.router(routes)) // TODO Merge 404 & errors together if (NODE_ENV === "development") { app.use("/_polydev", middleware.assets(path.resolve(__dirname, "./public"))) + app.use(middleware.router(path.resolve(__dirname, "./routes"))) app.use(middleware.notFound) app.use(middleware.error) } diff --git a/packages/polydev/src/middleware/error/index.js b/packages/polydev/src/middleware/error/index.js index 08377c9..2d10fc9 100644 --- a/packages/polydev/src/middleware/error/index.js +++ b/packages/polydev/src/middleware/error/index.js @@ -1,32 +1,73 @@ +const generateId = require("uuid/v1") +const Youch = require("youch") +const forTerminal = require("youch-terminal") + +const nonce = generateId() + module.exports = function errorHandler(error, req, res, next) { const { status = "", statusCode = 500 } = error - res.status(statusCode).send(` -
- - + const youch = new Youch(error, req) + youch.addLink((error) => { + return ` + + ` + }) + + if (error.code === "MODULE_NOT_FOUND") { + const [, missing] = error.message.match(/'(.*)'/) + + youch.addLink( + () => ` + + ` + ) + } + + youch.addLink(({ message }) => { + const url = `https://google.com/search?q=${encodeURIComponent(message)}` + + return `` + }) + + youch.addLink(({ message }) => { + const url = `https://stackoverflow.com/search?q=${encodeURIComponent( + message + )}` + + return `` + }) + + youch.toHTML().then((html) => { + res.status(statusCode).send(html) + }) -${statusCode} ${status}
- ${error.message}
- `)
+
+ const args = ["add", req.body.module]
+
+ if (req.body.dev) {
+ args.push("--dev")
+ }
+
+ const child = spawn("yarn", args)
+
+ res.write(`$ yarn ${args.join(" ")}\n`)
+
+ child.stderr.on("data", (data) => res.write(convert.toHtml(`${data}`)))
+ child.stdout.on("data", (data) => res.write(convert.toHtml(`${data}`)))
+
+ child.on("close", (code, signal) => {
+ if (!code) {
+ res.write(`
+
+ `)
+ }
+
+ res.end()
+ })
+}
diff --git a/routes/index.js b/routes/index.js
index 18493a2..8a4586b 100644
--- a/routes/index.js
+++ b/routes/index.js
@@ -37,6 +37,9 @@ module.exports = (req, res) => {
Logo
+
+ Missing Module
+
Next.js
diff --git a/routes/missing-module/index.js b/routes/missing-module/index.js
new file mode 100644
index 0000000..25c754c
--- /dev/null
+++ b/routes/missing-module/index.js
@@ -0,0 +1,22 @@
+const humanize = require("humanize")
+
+module.exports = (req, res) => {
+ res.send(`
+
+
+
+
+
+
+
+
+
+
+
+ 👋 Howdy from polydev
+
+
+
+
+ `)
+}
diff --git a/yarn.lock b/yarn.lock
index b249c25..a29aad0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1123,6 +1123,13 @@ ansi-styles@^3.2.1:
dependencies:
color-convert "^1.9.0"
+ansi-to-html@^0.6.10:
+ version "0.6.10"
+ resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.10.tgz#412114353bac2589a034db7ec5b371b8ba771131"
+ integrity sha512-znsY3gvsk4CiApWu1yVYF8Nx5Vy0FEe8B0YwyxdbCdErJu5lfKlRHB2twtUjR+dxR4WewTk2OP8XqTmWYnImOg==
+ dependencies:
+ entities "^1.1.1"
+
any-promise@^1.1.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
@@ -2022,7 +2029,7 @@ cookie-signature@1.0.6:
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
-cookie@0.3.1:
+cookie@0.3.1, cookie@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=
@@ -2373,6 +2380,11 @@ enhanced-resolve@^4.1.0:
memory-fs "^0.4.0"
tapable "^1.0.0"
+entities@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
+ integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
+
errno@^0.1.2, errno@^0.1.3, errno@~0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618"
@@ -4016,6 +4028,11 @@ ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
+mustache@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/mustache/-/mustache-3.0.1.tgz#873855f23aa8a95b150fb96d9836edbc5a1d248a"
+ integrity sha512-jFI/4UVRsRYdUbuDTKT7KzfOp7FiD5WzYmmwNwXyUVypC0xjoTL78Fqc0jHUPIvvGD+6DQSPHIt1NE7D1ArsqA==
+
nan@^2.9.2:
version "2.12.1"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552"
@@ -5339,6 +5356,11 @@ ssri@^6.0.1:
dependencies:
figgy-pudding "^3.5.1"
+stack-trace@0.0.10:
+ version "0.0.10"
+ resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
+ integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=
+
stackframe@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.0.4.tgz#357b24a992f9427cba6b545d96a14ed2cbca187b"
@@ -6125,6 +6147,22 @@ yn@^2.0.0:
resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a"
integrity sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=
+youch-terminal@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/youch-terminal/-/youch-terminal-1.0.0.tgz#03e2096ee360ef915816e62ea9ec94a6ff094d9e"
+ integrity sha512-rOVcJi5juKSUI3/mwAKOP+gjrUWUgb5AUTe2LZlfLBgLdfgnYtBKCrWc02GgRozDf/i6uXBu9/y3Vf6db+7k1A==
+ dependencies:
+ chalk "^2.3.0"
+
+youch@^2.0.10:
+ version "2.0.10"
+ resolved "https://registry.yarnpkg.com/youch/-/youch-2.0.10.tgz#e0f6312b12304fd330a0c4a0e0925b0123f7d495"
+ integrity sha512-qPLQW2TuwlcK9sm5i1Gbb9ezRZRZyzr6NsY5cqxsbh+2iEyKPxLlz0OSAc+pQ7mv1pYZLri1MXynggP6R2FcNQ==
+ dependencies:
+ cookie "^0.3.1"
+ mustache "^3.0.0"
+ stack-trace "0.0.10"
+
zen-observable-ts@^0.8.13:
version "0.8.13"
resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.13.tgz#ae1fd77c84ef95510188b1f8bca579d7a5448fc2"