Skip to content

Commit 4d25474

Browse files
feat: client type generate
1 parent 50806fa commit 4d25474

File tree

8 files changed

+107
-23
lines changed

8 files changed

+107
-23
lines changed

src/client-codegen.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { LoadSchemaOptions, UnnormalizedTypeDefPointer } from '@graphql-tools/load'
2+
import type { Source } from '@graphql-tools/utils'
23
import type { GraphQLSchema } from 'graphql'
34
import type { CodegenClientConfig } from './types'
45
import { codegen } from '@graphql-codegen/core'
@@ -97,12 +98,10 @@ export async function loadGraphQLDocuments(patterns: string | string[]) {
9798

9899
export async function generateClientTypes(
99100
schema: GraphQLSchema,
100-
patterns: string | string[],
101+
docs: Source[],
101102
config: CodegenClientConfig = {},
102103
outputPath?: string,
103104
) {
104-
const docs = await loadGraphQLDocuments(patterns)
105-
106105
if (docs.length === 0) {
107106
consola.info('[graphql] No client GraphQL files found. Skipping client type generation.')
108107
return ''

src/index.ts

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,44 @@
11
import type { Nitro } from 'nitropack/types'
2-
32
import { writeFileSync } from 'node:fs'
43
import { fileURLToPath } from 'node:url'
4+
import { watch } from 'chokidar'
55
import { defineNitroModule } from 'nitropack/kit'
66
import { dirname, join, resolve } from 'pathe'
7+
78
import { rollupConfig } from './rollup'
89
import { relativeWithDot, scanDefs, scanResolvers } from './utils'
9-
import { serverTypeGeneration } from './utils/server-type-generation'
10+
import { clientTypeGeneration, serverTypeGeneration } from './utils/server-type-generation'
1011

1112
export default defineNitroModule({
1213
name: 'nitro-graphql',
1314
async setup(nitro: Nitro) {
15+
nitro.graphql ||= {
16+
buildDir: '',
17+
watchDirs: [],
18+
}
19+
20+
const graphqlBuildDir = resolve(nitro.options.buildDir, 'graphql')
21+
nitro.graphql.buildDir = graphqlBuildDir
22+
23+
const watchDirs: string[] = []
24+
25+
switch (nitro.options.framework.name) {
26+
case 'nuxt':
27+
watchDirs.push(join(nitro.options.rootDir, 'app', 'graphql'))
28+
break
29+
default:
30+
}
31+
32+
watch(watchDirs, {
33+
persistent: true,
34+
ignoreInitial: true,
35+
ignored: nitro.options.ignore,
36+
}).on('all', async (event, path) => {
37+
if (path.endsWith('.graphql') || path.endsWith('.gql')) {
38+
await clientTypeGeneration(nitro, path)
39+
}
40+
})
41+
1442
const tsConfigPath = resolve(
1543
nitro.options.buildDir,
1644
nitro.options.typescript.tsconfigPath,
@@ -34,28 +62,27 @@ export default defineNitroModule({
3462

3563
await rollupConfig(nitro)
3664

37-
// Add GraphQL Yoga handlers
38-
const aendpoint = '/api/graphql'
65+
const endpoint = '/api/graphql'
3966

4067
const runtime = fileURLToPath(
4168
new URL('routes', import.meta.url),
4269
)
4370
// Main GraphQL endpoint
4471
nitro.options.handlers.push({
45-
route: aendpoint,
72+
route: endpoint,
4673
handler: join(runtime, 'graphql'),
4774
method: 'get',
4875
})
4976

5077
// Main GraphQL endpoint
5178
nitro.options.handlers.push({
52-
route: aendpoint,
79+
route: endpoint,
5380
handler: join(runtime, 'graphql'),
5481
method: 'post',
5582
})
5683

5784
nitro.options.handlers.push({
58-
route: aendpoint,
85+
route: endpoint,
5986
handler: join(runtime, 'graphql'),
6087
method: 'options',
6188
})
@@ -133,12 +160,13 @@ declare module 'nitro-graphql/types' {
133160
types.tsConfig.compilerOptions.paths['#graphql/server'] = [
134161
relativeWithDot(tsconfigDir, join(typesDir, 'nitro-graphql-server.d.ts')),
135162
]
136-
// types.tsConfig.compilerOptions.paths['#graphql/client'] = [
137-
// relativeWithDot(tsconfigDir, join(typesDir, 'graphql-client.generated.ts')),
138-
// ]
163+
types.tsConfig.compilerOptions.paths['#graphql/client'] = [
164+
relativeWithDot(tsconfigDir, join(typesDir, 'nitro-graphql-client.d.ts')),
165+
]
139166
types.tsConfig.include = types.tsConfig.include || []
140167
types.tsConfig.include.push(
141168
relativeWithDot(tsconfigDir, join(typesDir, 'nitro-graphql-server.d.ts')),
169+
relativeWithDot(tsconfigDir, join(typesDir, 'nitro-graphql-client.d.ts')),
142170
relativeWithDot(tsconfigDir, join(typesDir, 'graphql.d.ts')),
143171
)
144172
})

src/rollup.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,23 @@ export async function rollupConfig(app: Nitro) {
5252
name: 'nitro-graphql-watcher',
5353
async buildStart() {
5454
const graphqlFiles = await scanGraphql(nitro)
55+
// const clientGraphqlFiles = await scanClient(nitro)
5556

5657
for (const file of graphqlFiles) {
5758
this.addWatchFile(file)
5859
}
5960

61+
// for (const file of clientGraphqlFiles) {
62+
// this.addWatchFile(file)
63+
// }
64+
6065
// 2. Directory watching (partial çalışır)
6166
this.addWatchFile('server/graphql/')
67+
68+
// 3. Client GraphQL files
69+
// if (app.options.framework.name === 'nuxt') {
70+
// this.addWatchFile('app/graphql/')
71+
// }
6272
},
6373
})
6474
}
@@ -69,12 +79,6 @@ export async function rollupConfig(app: Nitro) {
6979
})
7080
}
7181

72-
declare module 'nitropack/types' {
73-
interface Nitro {
74-
scanDefs: string[]
75-
scanResolvers: any
76-
}
77-
}
7882
function getImportId(p: string, lazy?: boolean) {
7983
return (lazy ? '_lazy_' : '_') + hash(p).replace(/-/g, '').slice(0, 6)
8084
}

src/types.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@ import type { IncomingMessage, ServerResponse } from 'node:http'
77

88
export type CodegenServerConfig = TypeScriptPluginConfig & TypeScriptResolversPluginConfig
99

10+
declare module 'nitropack/types' {
11+
interface Nitro {
12+
scanDefs: string[]
13+
scanResolvers: any
14+
graphql: {
15+
buildDir: string
16+
watchDirs: string[]
17+
}
18+
}
19+
}
20+
1021
declare module 'nitropack' {
1122
interface NitroOptions {
1223
graphql?: NitroGraphQLOptions

src/utils/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ export function relativeWithDot(from: string, to: string) {
3333
return RELATIVE_RE.test(rel) ? rel : `./${rel}`
3434
}
3535

36+
// export async function scanClient(nitro: Nitro) {
37+
// if (nitro.options.framework.name === 'nuxt') {
38+
// const graphql = join(nitro.options.rootDir, 'app')
39+
// const files = await scanDir(nitro, graphql, 'graphql', '**/*.graphql')
40+
// return files.map(f => f.fullPath)
41+
// }
42+
43+
// return []
44+
// }
45+
3646
export async function scanGraphql(nitro: Nitro) {
3747
const files = await scanFiles(nitro, 'graphql')
3848
return files.map(f => f.fullPath)

src/utils/server-type-generation.ts

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import type { Nitro } from 'nitropack'
22

3-
import { writeFileSync } from 'node:fs'
3+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'
44
import { loadFilesSync } from '@graphql-tools/load-files'
55
import { mergeTypeDefs } from '@graphql-tools/merge'
6+
import { printSchemaWithDirectives } from '@graphql-tools/utils'
67
import consola from 'consola'
7-
import { buildASTSchema } from 'graphql'
8-
import { resolve } from 'pathe'
8+
import { buildASTSchema, buildSchema } from 'graphql'
9+
import { dirname, join, resolve } from 'pathe'
10+
import { generateClientTypes, loadGraphQLDocuments } from '../client-codegen'
911
import { generateTypes } from '../codegen'
1012

1113
export async function serverTypeGeneration(app: Nitro) {
@@ -21,9 +23,39 @@ export async function serverTypeGeneration(app: Nitro) {
2123

2224
const data = await generateTypes(schema, app.options.graphql?.codegen?.server ?? {})
2325

24-
writeFileSync(resolve(app.options.buildDir, 'types', 'nitro-graphql-server.d.ts'), data, 'utf-8')
26+
const printSchema = printSchemaWithDirectives(schema)
27+
28+
const schemaPath = resolve(app.graphql.buildDir, 'schema.graphql')
29+
mkdirSync(dirname(schemaPath), { recursive: true })
30+
writeFileSync(schemaPath, printSchema, 'utf-8')
31+
32+
const serverTypesPath = resolve(app.options.buildDir, 'types', 'nitro-graphql-server.d.ts')
33+
mkdirSync(dirname(serverTypesPath), { recursive: true })
34+
writeFileSync(serverTypesPath, data, 'utf-8')
2535
}
2636
catch (error) {
2737
consola.error('Server schema generation error:', error)
2838
}
2939
}
40+
41+
export async function clientTypeGeneration(
42+
app: Nitro,
43+
path: string,
44+
) {
45+
try {
46+
const root = app.graphql.watchDirs.find(dir => path.startsWith(dir)) || path
47+
if (!root) {
48+
return
49+
}
50+
const docs = await loadGraphQLDocuments(root)
51+
const graphqlString = readFileSync(join(app.graphql.buildDir, 'schema.graphql'), 'utf-8')
52+
const schema = buildSchema(graphqlString)
53+
54+
const types = await generateClientTypes(schema, docs)
55+
const clientTypesPath = resolve(app.options.buildDir, 'types', 'nitro-graphql-client.d.ts')
56+
writeFileSync(clientTypesPath, types, 'utf-8')
57+
}
58+
catch (error) {
59+
consola.error('Client schema generation error:', error)
60+
}
61+
}

0 commit comments

Comments
 (0)