Created
February 13, 2022 04:12
-
-
Save statico/bf531ff8d005d09c844f2ed459e0d2f9 to your computer and use it in GitHub Desktop.
Next.js API route helpers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { encode } from "html-entities" | |
import { getReasonPhrase, StatusCodes } from "http-status-codes" | |
import stringify from "json-stringify-safe" | |
import { NextApiResponse } from "next" | |
// Semantic sugar for returning various status codes, optionally with messages. | |
export const statusHelper = (res: NextApiResponse) => ({ | |
codes: StatusCodes, | |
status(code: number, message?: string): void { | |
const phrase = getReasonPhrase(code) | |
const body = phrase + (message ? ` - ${message}` : "") | |
res.status(code).send(body) | |
}, | |
// Extra helper to pretty-print JSON in development mode or if true is passed | |
// as the second param. | |
json(object: any, pretty?: boolean): void { | |
res.setHeader("Content-Type", "application/json; charset=utf-8") | |
if (pretty === undefined) pretty = __DEV__ | |
const text = pretty ? stringify(object, null, 2) : stringify(object) | |
res.send(text) | |
}, | |
// Make simple CGI-like pages using a zero-markup CSS library. | |
html(body = "", raw?: boolean): void { | |
const buildId = process.env.NEXT_PUBLIC_BUILD_ID | |
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL | |
res.setHeader("Content-Type", "text/html; charset=utf-8") | |
if (raw) { | |
res.send(body) | |
} else { | |
res.send(` | |
<!doctype html> | |
<html> | |
<head> | |
<title>Admin</title> | |
<meta charset="utf-8"/> | |
<meta name="viewport" content="width=device-width, initial-scale=1"/> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mini.css/3.0.1/mini-default.min.css"/> | |
<style type="text/css"> | |
nav { | |
position: fixed; | |
margin: 0; | |
left: 0; | |
top: 0; | |
bottom: 0; | |
width: 200px; | |
background: #eee; | |
} | |
main { margin-left: 220px; } | |
nav * { line-height: 1; margin: 0; } | |
pre * { font-family: monospace; } | |
hr { padding: 0 } | |
input[type="text"] { min-width:400px; } | |
h6 { opacity: 0.5; overflow: hidden; text-overflo: ellipsis; } | |
</style> | |
</head> | |
<body> | |
<nav> | |
<a href="/"><img src="/favicon.ico" width="32"/></a> | |
<h5>Admin</h5> | |
<hr/> | |
<a href="/api/admin/me">Me</a> | |
<a href="/api/admin/users">Users</a> | |
<a href="/api/admin/communities">Communities</a> | |
<hr/> | |
<a href="/api/admin/test">Test</a> | |
<hr/> | |
<h6> | |
${baseUrl}<br/> | |
Build ID<br/> | |
${buildId} | |
</h6> | |
</nav> | |
<main>${body}</main> | |
</body> | |
</html> | |
`) | |
} | |
}, | |
// Additional HTML helpers | |
stringify: (obj: any) => stringify(obj, null, 2), | |
escape: encode, | |
}) | |
// The type of values in req.query is string | string[], but this isn't true | |
// since a value could be undefined. This guarantees what you expect from | |
// req.query in most cases: you get a string (which might be empty) or null. | |
export const singleParam = (value: any): string | null => { | |
if (value == null) { | |
return null | |
} else if (Array.isArray(value)) { | |
return String(value[0]) | |
} else { | |
return String(value) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment