Created
March 20, 2023 18:58
-
-
Save hos/2b5db899ed66276174e58648b042d6b0 to your computer and use it in GitHub Desktop.
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 cors from "cors"; | |
import express, { Express, NextFunction } from "express"; | |
import { IncomingMessage, Server, ServerResponse } from "http"; | |
import inspector from "inspector"; | |
import { Duplex } from "stream"; | |
import { isDev, isLocal } from "./config.js"; | |
import * as middleware from "./middleware/index.js"; | |
import { firebaseAuthMiddleware } from "./middleware/installFirebaseAuth.js"; | |
import { makeShutdownActions, ShutdownAction } from "./shutdownActions.js"; | |
// Server may not always be supplied, e.g. where mounting on a sub-route | |
export function getHttpServer(app: Express): Server | null { | |
return app.get("httpServer") ?? null; | |
} | |
export function getShutdownActions(app: Express): ShutdownAction[] { | |
return app.get("shutdownActions"); | |
} | |
type UpgradeHandlers = Array<{ | |
name: string; | |
check: (req: IncomingMessage, socket: Duplex, head: Buffer) => boolean | Promise<boolean>; | |
upgrade: (req: IncomingMessage, socket: Duplex, head: Buffer) => void; | |
}>; | |
export function getUpgradeHandlers(app: Express): UpgradeHandlers { | |
return app.get("upgradeHandlers"); | |
} | |
export function getWebsocketMiddlewares(app: Express): Middleware<express.Request, express.Response>[] { | |
return app.get("websocketMiddlewares"); | |
} | |
export interface Middleware<Request extends IncomingMessage, Response extends ServerResponse> { | |
(req: Request, res: Response, next: NextFunction): void; | |
} | |
export async function makeApp({ | |
httpServer, | |
}: { | |
httpServer?: Server; | |
} = {}): Promise<Express> { | |
const shutdownActions = makeShutdownActions(); | |
if (isDev || isLocal) { | |
shutdownActions.push(() => { | |
inspector.close(); | |
}); | |
} | |
/* | |
* Our Express server | |
*/ | |
const app = express(); | |
app.use(cors({ origin: true })); | |
/* | |
* Getting access to the HTTP server directly means that we can do things | |
* with websockets if we need to (e.g. GraphQL subscriptions). | |
*/ | |
app.set("httpServer", httpServer); | |
/* | |
* For a clean nodemon shutdown, we need to close all our sockets otherwise | |
* we might not come up cleanly again (inside nodemon). | |
*/ | |
app.set("shutdownActions", shutdownActions); | |
/* | |
* Since multiple things in our server might want to handle websockets and | |
* this is handled in node via the 'upgrade' event which should have one handler | |
* only, we need a centralised location to listen for upgrade events that then | |
* decides which handler to dispatch the event to. This array stores these | |
* handlers. | |
*/ | |
const upgradeHandlers: UpgradeHandlers = []; | |
app.set("upgradeHandlers", upgradeHandlers); | |
/* | |
* When we're using websockets, we may want them to have access to | |
* sessions/etc for authentication. | |
*/ | |
const websocketMiddlewares: Middleware<express.Request, express.Response>[] = [firebaseAuthMiddleware]; | |
app.set("websocketMiddlewares", websocketMiddlewares); | |
/* | |
* Middleware is installed from the /server/middleware directory. These | |
* helpers may augment the express app with new settings and/or install | |
* express middleware. These helpers may be asynchronous, but they should | |
* operate very rapidly to enable quick as possible server startup. | |
*/ | |
await middleware.installHealth(app); | |
await middleware.installDatabasePools(app); | |
await middleware.installWorkerUtils(app); | |
await middleware.installGraphQLClient(app); | |
await middleware.installSameOrigin(app); | |
await middleware.installFirebaseAuth(app); | |
await middleware.installPostGraphile(app); | |
/* | |
* Error handling middleware | |
*/ | |
await middleware.installErrorHandler(app); | |
return app; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment