Create your Link in Bio for Bluesky
1import { createRequestHandler } from "@react-router/express";
2import express from "express";
3import pinoHttp from "pino-http";
4import type { ServerBuild } from "react-router";
5
6import { jetstream } from "./server/jetstream/subscription.js";
7import { env } from "./utils/env.js";
8import { createLogger } from "./utils/logger.js";
9
10// import { createServer } from "./generated/server/index.js";
11
12// OAuthログインを行うためにE2Eテスト実行時のprocess.env.NODE_ENVはdevelopmentになっている
13// 代わりにprocess.env.E2Eが設定されているので、その場合はviteを使わない
14const viteDevServer =
15 env.NODE_ENV === "production" || process.env.E2E
16 ? null
17 : await import("vite").then((vite) =>
18 vite.createServer({
19 server: { middlewareMode: true },
20 }),
21 );
22
23const app = express();
24
25app.use(
26 pinoHttp({
27 logger: createLogger("http"),
28 customSuccessMessage: (req, res, responseTime) => {
29 return `${req.method} ${res.statusCode} ${req.url} ${responseTime}ms`;
30 },
31 customErrorMessage: (req, res) => {
32 return `${req.method} ${res.statusCode} ${req.url}`;
33 },
34 ...(env.NODE_ENV === "development" && {
35 serializers: {
36 req: () => undefined,
37 res: () => undefined,
38 responseTime: () => undefined,
39 },
40 }),
41 }),
42);
43
44if (viteDevServer) {
45 app.use(viteDevServer.middlewares);
46} else {
47 app.use(
48 express.static("build/client", {
49 setHeaders: (res) => {
50 res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
51 },
52 }),
53 );
54}
55
56// 開発環境でのOAuthログイン時 http://127.0.0.1/oauth/callback にリダイレクトされるので、
57// そこからさらに http://linkat.localhost にリダイレクトさせる
58app.use((req, res, next) => {
59 if (env.NODE_ENV === "development" && req.hostname === "127.0.0.1") {
60 res.redirect(new URL(req.originalUrl, env.PUBLIC_URL).toString());
61 } else {
62 next();
63 }
64});
65
66// const server = createServer();
67// server.dev.mkizka.sample.sampleMethod(() => {
68// return {
69// encoding: "application/json",
70// body: {
71// foo: "bar",
72// },
73// };
74// });
75// app.use(server.xrpc.router);
76
77const build = viteDevServer
78 ? () =>
79 // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
80 viteDevServer.ssrLoadModule(
81 "virtual:react-router/server-build",
82 ) as Promise<ServerBuild>
83 : // eslint-disable-next-line
84 // @ts-ignore: ビルド成果物はあったりなかったりするのでts-expect-errorを使わない
85 // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
86 ((await import("../build/server/index.js")) as ServerBuild);
87
88app.use(createRequestHandler({ build }));
89
90const logger = createLogger("server");
91
92app.listen(env.PORT, "0.0.0.0", () => {
93 logger.info(`App listening on ${env.PUBLIC_URL}`);
94 if (!env.DISABLE_JETSTREAM) {
95 jetstream.start();
96 }
97});