From d76144e4201e28a32d5c9f242fc31b165f10323d Mon Sep 17 00:00:00 2001 From: temz Date: Thu, 29 Jun 2023 23:31:18 +0700 Subject: [PATCH] feat: refactor gateway to nestjs --- apps/gateway/src/app/app.module.ts | 38 +++++++++++++++ apps/gateway/src/main.ts | 77 ++++++++++++++---------------- 2 files changed, 74 insertions(+), 41 deletions(-) create mode 100644 apps/gateway/src/app/app.module.ts diff --git a/apps/gateway/src/app/app.module.ts b/apps/gateway/src/app/app.module.ts new file mode 100644 index 0000000..58ef115 --- /dev/null +++ b/apps/gateway/src/app/app.module.ts @@ -0,0 +1,38 @@ +import { Module } from '@nestjs/common' +import { EventloopFrozenDetectorModule } from 'core/eventloop-frozen-detector' +import { GraphQLModule } from '@nestjs/graphql' +import * as env from 'env-var' +import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default' +import { ApolloGatewayDriver, ApolloGatewayDriverConfig } from '@nestjs/apollo' +import { IntrospectAndCompose } from '@apollo/gateway' + +@Module({ + imports: [ + EventloopFrozenDetectorModule.forRoot({ + delay: 3000, + }), + GraphQLModule.forRoot({ + driver: ApolloGatewayDriver, + server: { + playground: false, + plugins: [ApolloServerPluginLandingPageLocalDefault()], + }, + gateway: { + supergraphSdl: new IntrospectAndCompose({ + subgraphs: env + .get('GATEWAY_SUBGRAPHS') + .required() + .asJsonArray() as { + name: string + url: string + }[], + subgraphHealthCheck: true, + pollIntervalInMs: 10000, + }), + }, + }), + ], + controllers: [], + providers: [], +}) +export class AppModule {} diff --git a/apps/gateway/src/main.ts b/apps/gateway/src/main.ts index 7ff5695..fad1cff 100644 --- a/apps/gateway/src/main.ts +++ b/apps/gateway/src/main.ts @@ -1,23 +1,23 @@ -import { Logger } from '@nestjs/common' -import { ApolloServer } from '@apollo/server' -import { startStandaloneServer } from '@apollo/server/standalone' -import { ApolloGateway, IntrospectAndCompose } from '@apollo/gateway' +import env from 'env-var' +import { INestApplication, Logger } from '@nestjs/common' +import { NestFactory } from '@nestjs/core' +import { AppModule } from './app/app.module' +import { SpelunkerModule } from 'nestjs-spelunker' + const logger = new Logger('Application') -//do something when app is closing -process.on('exit', exitHandler.bind(null, { cleanup: true })) +async function bootstrap() { + const app = await NestFactory.create(AppModule) -//catches ctrl+c event -process.on('SIGINT', exitHandler.bind(null, { exit: true })) + // const diGraph = buildDIGraph(app) -// catches "kill pid" (for example: nodemon restart) -process.on('SIGUSR1', exitHandler.bind(null, { exit: true })) -process.on('SIGUSR2', exitHandler.bind(null, { exit: true })) - -//catches uncaught exceptions -process.on('uncaughtException', exitHandler.bind(null, { exit: true })) + const port = env.get('GATEWAY_PORT').default(3052).asPortNumber() -import env from 'env-var' + await app.listen(port, () => { + logger.log(`🚀 Gateway is running on: http://localhost:${port}/graphql`) + // logger.debug(`DI Graph tree\n${diGraph}`) + }) +} //do something when app is closing process.on('exit', exitHandler.bind(null, { cleanup: true })) @@ -32,32 +32,6 @@ process.on('SIGUSR2', exitHandler.bind(null, { exit: true })) //catches uncaught exceptions process.on('uncaughtException', exitHandler.bind(null, { exit: true })) -async function bootstrap() { - const port = env.get('GATEWAY_PORT').default(3052).asPortNumber() - const subgraphs = env.get('GATEWAY_SUBGRAPHS').required().asJsonArray() as { - name: string - url: string - }[] - - const server = new ApolloServer({ - gateway: new ApolloGateway({ - supergraphSdl: new IntrospectAndCompose({ - subgraphs, - subgraphHealthCheck: true, - pollIntervalInMs: 10000, - }), - }), - }) - - const { url } = await startStandaloneServer(server, { - listen: { - port, - }, - }) - - logger.log(`Gateway ready at ${url}`) -} - try { bootstrap().catch((err) => { logger.error(err, err.stack) @@ -81,3 +55,24 @@ function exitHandler(options, exitCode) { process.exit() } } + +// Copy output to mermaid.live +function buildDIGraph(app: INestApplication) { + const tree = SpelunkerModule.explore(app) + const root = SpelunkerModule.graph(tree) + const edges = SpelunkerModule.findGraphEdges(root) + + const mermaidEdges = edges + .filter( + ({ from, to }) => + !( + from.module.name === 'ConfigHostModule' || + from.module.name === 'LoggerModule' || + to.module.name === 'ConfigHostModule' || + to.module.name === 'LoggerModule' + ), + ) + .map(({ from, to }) => `${from.module.name}-->${to.module.name}`) + + return `graph TD\n\t${mermaidEdges.join('\n\t')}` +}