Skip to content

Commit 8997961

Browse files
committed
feat: Add Apollo Server at '/api/graphql'
1 parent 11980c6 commit 8997961

File tree

7 files changed

+1062
-89
lines changed

7 files changed

+1062
-89
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import type { NextRequest } from 'next/server'
2+
import { createGraphQLServerHandler } from '@app/core/graphql/graphqlServer'
3+
4+
/* --- Handler --------------------------------------------------------------------------------- */
5+
6+
const handler = createGraphQLServerHandler()
7+
8+
/* --- /api/graphql ---------------------------------------------------------------------------- */
9+
10+
export const GET = (req: NextRequest) => handler(req)
11+
12+
export const POST = (req: NextRequest) => handler(req)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { ApolloServer } from '@apollo/server'
2+
import type { NextRequest } from 'next/server'
3+
import { startServerAndCreateNextHandler } from '@as-integrations/next'
4+
import { createRequestContext } from '../middleware/createRequestContext'
5+
import { schemaBundle } from './schema'
6+
7+
/* --- Apollo Server --------------------------------------------------------------------------- */
8+
9+
export const graphqlServer = new ApolloServer({
10+
typeDefs: schemaBundle.typeDefs,
11+
resolvers: schemaBundle.resolvers,
12+
introspection: true,
13+
})
14+
15+
/** --- createGraphQLServerHandler() ----------------------------------------------------------- */
16+
/** -i- Create the apollo graphql server handler for Next.js API router and provides context to resolvers */
17+
export const createGraphQLServerHandler = () => {
18+
return startServerAndCreateNextHandler(graphqlServer, {
19+
context: async (req: NextRequest) => {
20+
return await createRequestContext({ req })
21+
},
22+
})
23+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import path from 'path'
2+
import { fileURLToPath } from 'node:url'
3+
import { loadFilesSync } from '@graphql-tools/load-files'
4+
import { mergeTypeDefs, mergeResolvers } from '@graphql-tools/merge'
5+
import { makeExecutableSchema } from '@graphql-tools/schema'
6+
import type { RequestContext } from '../middleware/createRequestContext'
7+
import { healthCheck } from '../resolvers/healthCheck'
8+
9+
/** --- createResolver() ----------------------------------------------------------------------- */
10+
/** -i- Helper to wrap a resolver function and map context and args to it */
11+
export const createResolver = <T>(resolver: (input: { args: T, context: RequestContext }) => Promise<unknown>) => {
12+
return async (parent: unknown, { args }: { args: T }, context: RequestContext, info: unknown) => {
13+
return resolver({ args, context: { ...context, parent, info } })
14+
}
15+
}
16+
17+
/* --- Custom Resolvers ------------------------------------------------------------------------ */
18+
19+
const customResolvers = {
20+
Query: {
21+
healthCheck: createResolver(healthCheck),
22+
},
23+
}
24+
25+
/** --- createRootResolver() ------------------------------------------------------------------- */
26+
/** -i- Combine all custom and other (e.g. injected) resolvers */
27+
export const createRootResolver = () => mergeResolvers([
28+
customResolvers,
29+
/* other resolvers? */
30+
])
31+
32+
/** --- createSchemaDefinitions() -------------------------------------------------------------- */
33+
/** -i- Combine all custom and other (e.g. generated) graphql schema definitions */
34+
export const createSchemaDefinitions = () => {
35+
const currentDir = path.dirname(fileURLToPath(import.meta.url))
36+
const rootDir = path.resolve(currentDir, '../../..')
37+
const schemaPathPattern = `${rootDir}/(features|packages)/**/*.graphql`
38+
const customGraphQLDefinitions = loadFilesSync(schemaPathPattern)
39+
return mergeTypeDefs([
40+
...customGraphQLDefinitions,
41+
/* other typedefs? */
42+
])
43+
}
44+
45+
/* --- Schema ---------------------------------------------------------------------------------- */
46+
47+
export const schemaBundle = {
48+
typeDefs: createSchemaDefinitions(),
49+
resolvers: createRootResolver(),
50+
}
51+
52+
export const executableSchema = makeExecutableSchema(schemaBundle)
53+
54+
/* --- Exports --------------------------------------------------------------------------------- */
55+
56+
export default executableSchema

features/app-core/package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22
"name": "@app/core",
33
"version": "1.0.0",
44
"private": true,
5-
"dependencies": {},
5+
"dependencies": {
6+
"@apollo/server": "^4.10.2",
7+
"@as-integrations/next": "^3.0.0",
8+
"@graphql-tools/load-files": "^7.0.0",
9+
"graphql-tag": "^2.12.6"
10+
},
611
"devDependencies": {
712
"typescript": "5.3.3"
813
},
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
type Query {
2+
healthCheck(args: HealthCheckArgs): HealthCheckData!
3+
}
4+
5+
input HealthCheckArgs {
6+
echo: String
7+
}
8+
9+
type HealthCheckData {
10+
echo: String
11+
status: String!
12+
alive: Boolean!
13+
kicking: Boolean!
14+
now: String!
15+
aliveTime: Float!
16+
aliveSince: String!
17+
serverTimezone: String!
18+
requestHost: String
19+
requestProtocol: String
20+
requestURL: String
21+
baseURL: String
22+
apiURL: String
23+
port: Int
24+
debugPort: Int
25+
nodeVersion: String
26+
v8Version: String
27+
systemArch: String
28+
systemPlatform: String
29+
systemRelease: String
30+
systemFreeMemory: Float
31+
systemTotalMemory: Float
32+
systemLoadAverage: [Float]
33+
}

0 commit comments

Comments
 (0)