Skip to content

Commit 5a5bfd8

Browse files
feat: implement GraphQL health check endpoint and enhance runtime configuration options
1 parent deb53c7 commit 5a5bfd8

File tree

3 files changed

+72
-9
lines changed

3 files changed

+72
-9
lines changed

src/index.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import type { Nitro } from 'nitropack/types'
2+
import type { NitroGraphQLOptions } from './types'
23
import { writeFileSync } from 'node:fs'
34
import { fileURLToPath } from 'node:url'
45
import { watch } from 'chokidar'
6+
import defu from 'defu'
7+
58
import { defineNitroModule } from 'nitropack/kit'
69
import { dirname, join, resolve } from 'pathe'
7-
810
import { rollupConfig } from './rollup'
911
import { relativeWithDot, scanDefs, scanResolvers } from './utils'
1012
import { clientTypeGeneration, serverTypeGeneration } from './utils/server-type-generation'
@@ -18,6 +20,14 @@ export default defineNitroModule({
1820
clientDir: '',
1921
}
2022

23+
nitro.options.runtimeConfig.graphql = defu(nitro.options.runtimeConfig.graphql || {}, {
24+
endpoint: {
25+
graphql: '/api/graphql',
26+
healthCheck: '/api/graphql/health',
27+
},
28+
playground: true,
29+
} as NitroGraphQLOptions)
30+
2131
const graphqlBuildDir = resolve(nitro.options.buildDir, 'graphql')
2232
nitro.graphql.buildDir = graphqlBuildDir
2333

@@ -72,32 +82,36 @@ export default defineNitroModule({
7282
await serverTypeGeneration(nitro)
7383
await clientTypeGeneration(nitro, nitro.graphql.clientDir)
7484

75-
// Define the main GraphQL endpoint
76-
const endpoint = '/api/graphql'
77-
7885
const runtime = fileURLToPath(
7986
new URL('routes', import.meta.url),
8087
)
8188
// Main GraphQL endpoint
8289
nitro.options.handlers.push({
83-
route: endpoint,
90+
route: nitro.options.runtimeConfig.graphql?.endpoint?.graphql || '/api/graphql',
8491
handler: join(runtime, 'graphql'),
8592
method: 'get',
8693
})
8794

8895
// Main GraphQL endpoint
8996
nitro.options.handlers.push({
90-
route: endpoint,
97+
route: nitro.options.runtimeConfig.graphql?.endpoint?.graphql || '/api/graphql',
9198
handler: join(runtime, 'graphql'),
9299
method: 'post',
93100
})
94101

95102
nitro.options.handlers.push({
96-
route: endpoint,
103+
route: nitro.options.runtimeConfig.graphql?.endpoint?.graphql || '/api/graphql',
97104
handler: join(runtime, 'graphql'),
98105
method: 'options',
99106
})
100107

108+
// Health check endpoint
109+
nitro.options.handlers.push({
110+
route: nitro.options.runtimeConfig.graphql?.endpoint?.healthCheck || '/api/graphql/health',
111+
handler: join(runtime, 'health'),
112+
method: 'get',
113+
})
114+
101115
// Auto-import utilities
102116
if (nitro.options.imports) {
103117
nitro.options.imports.presets.push({

src/routes/health.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { defineEventHandler, setResponseStatus } from 'h3'
2+
import { useRuntimeConfig } from 'nitropack/runtime'
3+
4+
export default defineEventHandler(async (event) => {
5+
const runtime = useRuntimeConfig()
6+
7+
if (!runtime.graphql || !runtime.graphql.endpoint?.graphql) {
8+
setResponseStatus(event, 404)
9+
return {
10+
status: 'error',
11+
message: 'GraphQL health check endpoint is not configured',
12+
timestamp: new Date().toISOString(),
13+
}
14+
}
15+
16+
try {
17+
const response = await $fetch(runtime.graphql!.endpoint?.graphql, {
18+
method: 'POST',
19+
body: {
20+
query: 'query Health { __typename }',
21+
operationName: 'Health',
22+
},
23+
headers: {
24+
'Content-Type': 'application/json',
25+
'Accept': 'application/json',
26+
},
27+
})
28+
29+
if (response && typeof response === 'object' && 'data' in response) {
30+
return {
31+
status: 'healthy',
32+
message: 'GraphQL server is running',
33+
timestamp: new Date().toISOString(),
34+
}
35+
}
36+
37+
throw new Error('Invalid response from GraphQL server')
38+
}
39+
catch (error) {
40+
setResponseStatus(event, 503)
41+
return {
42+
status: 'unhealthy',
43+
message: (error instanceof Error ? error.message : 'GraphQL server is not responding'),
44+
timestamp: new Date().toISOString(),
45+
}
46+
}
47+
})

src/types.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ export interface CodegenClientConfig extends TypeScriptPluginConfig, TypeScriptD
4444
}
4545

4646
export interface NitroGraphQLOptions {
47-
endpoint?: string
48-
healthCheckEndpoint?: string
47+
endpoint?: {
48+
graphql?: string
49+
healthCheck?: string
50+
}
4951
playground?: boolean
5052
cors?: YogaServerOptions<{ req: IncomingMessage, res: ServerResponse }, any>['cors']
5153
typedefs?: string[]

0 commit comments

Comments
 (0)