|
1 | | -import Koa, { Context } from "koa" |
2 | | -import BodyParser from "koa-bodyparser" |
3 | | -import RequestLogger from "koa-pino-logger" |
4 | | -import Router from "koa-router" |
| 1 | +import Fastify from "fastify" |
| 2 | +import Cors from "fastify-cors" |
| 3 | +import Helmet from "fastify-helmet" |
| 4 | +import { customAlphabet, urlAlphabet } from "nanoid" |
5 | 5 |
|
6 | 6 | import { config } from "@/config" |
7 | | -import { Logger } from "@/lib/logger" |
8 | | -import { requestHandler, sendErrorToSentry, tracingMiddleWare } from "@/lib/sentry" |
| 7 | +import { sendErrorToSentry } from "@/lib/sentry" |
| 8 | +import { apiPlugin } from "@/routes/ids" |
9 | 9 |
|
10 | | -import { routes } from "./routes" |
| 10 | +import pkgJson from "../package.json" |
11 | 11 |
|
12 | | -export const App = new Koa() |
13 | | -const router = new Router() |
| 12 | +const isProd = config.NODE_ENV === "production" |
14 | 13 |
|
15 | | -App.use( |
16 | | - RequestLogger({ |
17 | | - prettyPrint: config.NODE_ENV === "development", |
18 | | - }), |
19 | | -) |
| 14 | +const nanoid = customAlphabet(urlAlphabet, 16) |
20 | 15 |
|
21 | | -App.use(requestHandler) |
22 | | -App.use(tracingMiddleWare) |
| 16 | +export const buildApp = async () => { |
| 17 | + const App = Fastify({ |
| 18 | + ignoreTrailingSlash: true, |
| 19 | + onProtoPoisoning: "remove", |
| 20 | + onConstructorPoisoning: "remove", |
| 21 | + trustProxy: isProd, |
| 22 | + genReqId: nanoid, |
| 23 | + disableRequestLogging: process.env.NODE_ENV === "test", |
| 24 | + logger: { |
| 25 | + level: config.LOG_LEVEL, |
| 26 | + prettyPrint: !isProd, |
| 27 | + }, |
| 28 | + }) |
23 | 29 |
|
24 | | -App.on("error", (err, ctx) => { |
25 | | - Logger.error(err) |
| 30 | + await App.register(Cors, { |
| 31 | + origin: true, |
| 32 | + }) |
26 | 33 |
|
27 | | - sendErrorToSentry(err, ctx) |
28 | | -}) |
| 34 | + await App.register(Helmet, { |
| 35 | + hsts: false, |
| 36 | + contentSecurityPolicy: false, |
| 37 | + }) |
29 | 38 |
|
30 | | -App.use(BodyParser()) |
| 39 | + App.addHook("onError", (request, _reply, error, next) => { |
| 40 | + sendErrorToSentry(error, request as any) |
31 | 41 |
|
32 | | -router.get("/", (ctx: Context) => { |
33 | | - ctx.body = ` |
34 | | -<pre> |
35 | | -<b>Get IDs:</b> |
36 | | -<b>GET/POST /api/ids</b> |
| 42 | + next() |
| 43 | + }) |
37 | 44 |
|
38 | | -enum Source { |
39 | | - anilist, |
40 | | - anidb, |
41 | | - myanimelist, |
42 | | - kitsu, |
43 | | -} |
44 | | -
|
45 | | -<b>Either use GET query parameters:</b> |
46 | | -?source={Source}&id={number} |
47 | | -
|
48 | | -<b>or send the query as a POST JSON body:</b> |
| 45 | + await App.register(apiPlugin, { prefix: "/api" }) |
49 | 46 |
|
50 | | -{ "anilist": 1337 } |
| 47 | + App.get("/", async (_request, reply) => reply.redirect(301, pkgJson.homepage)) |
51 | 48 |
|
52 | | -[{ "anilist": 1337 }, { "anilist": 69 }, { "anidb": 420 }] |
53 | | -
|
54 | | -interface Entry { |
55 | | - anilist: number | null |
56 | | - anidb: number | null |
57 | | - myanimelist: number | null |
58 | | - kitsu: number | null |
| 49 | + return App |
59 | 50 | } |
60 | | -
|
61 | | -{ "anilist": 1337 } => Entry | null |
62 | | -[{ ... }] => Array<Entry | null> |
63 | | -
|
64 | | -<b>The response code will always be 200 (OK). |
65 | | -If an entry is not found null is returned instead.</b> |
66 | | -
|
67 | | -Source code is available on GitHub at <a href="https://github.com/BeeeQueue/arm-server">https://github.com/BeeeQueue/arm-server</a> |
68 | | -</pre> |
69 | | -` |
70 | | -}) |
71 | | - |
72 | | -router.use(routes) |
73 | | - |
74 | | -App.use(router.routes()) |
75 | | -App.use(router.allowedMethods()) |
0 commit comments