nitro-graphql 0.0.23 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +831 -241
- package/dist/ecosystem/nuxt.d.ts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/routes/apollo-server.d.ts +2 -2
- package/dist/routes/graphql-yoga.d.ts +2 -2
- package/dist/routes/health.d.ts +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,60 +1,107 @@
|
|
|
1
|
-
# Nitro GraphQL
|
|
1
|
+
# Nitro GraphQL
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
[![npm version][npm-version-src]][npm-version-href]
|
|
6
|
+
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
7
|
+
[![bundle][bundle-src]][bundle-href]
|
|
8
|
+
[![License][license-src]][license-href]
|
|
9
|
+
|
|
10
|
+
**A standalone Nitro module that integrates GraphQL servers into any Nitro application with automatic type generation, file watching, and seamless framework integration.**
|
|
11
|
+
|
|
12
|
+
[🚀 Quick Start](#-quick-start) • [📖 Documentation](#-documentation) • [🎮 Playground](#-playground) • [💬 Community](#-community--contributing)
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
---
|
|
2
17
|
|
|
3
18
|
> [!NOTE]
|
|
4
19
|
> This project is actively under development. We're always open to new ideas, different perspectives, and feature suggestions! If you have a suggestion, please first [open an issue](https://github.com/productdevbook/nitro-graphql/issues) to discuss it, then you can contribute with a PR.
|
|
5
20
|
|
|
6
|
-
|
|
21
|
+
## ✨ Features
|
|
22
|
+
|
|
23
|
+
- 🚀 **Multi-Framework Support**: Works with GraphQL Yoga and Apollo Server
|
|
24
|
+
- 🔧 **Auto-Discovery**: Automatically scans and loads GraphQL schema and resolver files
|
|
25
|
+
- 📝 **Type Generation**: Automatic TypeScript type generation from GraphQL schemas (server & client)
|
|
26
|
+
- 🎮 **Apollo Sandbox**: Built-in GraphQL playground for development
|
|
27
|
+
- 🏥 **Health Check**: Built-in health check endpoint
|
|
28
|
+
- 🔌 **Universal Compatibility**: Works with any Nitro-based application (Nuxt, standalone Nitro, etc.)
|
|
29
|
+
- 🎯 **Zero Configuration**: Sensible defaults with optional customization
|
|
30
|
+
- 📂 **File-Based Organization**: Domain-driven resolver and schema organization
|
|
31
|
+
- 🔄 **Hot Reload**: Development mode with automatic schema and resolver updates
|
|
32
|
+
- 📦 **Optimized Bundling**: Smart chunking and dynamic imports for production
|
|
33
|
+
- 🌐 **Nuxt Integration**: First-class Nuxt.js support with dedicated module
|
|
7
34
|
|
|
8
|
-
##
|
|
35
|
+
## 🚀 Quick Start
|
|
9
36
|
|
|
10
|
-
|
|
11
|
-
- 🔧 Auto-discovery of GraphQL schema and resolver files
|
|
12
|
-
- 📝 Automatic TypeScript type generation from GraphQL schemas
|
|
13
|
-
- 🎮 Apollo Sandbox integration (instead of GraphiQL)
|
|
14
|
-
- 🏥 Built-in health check endpoint
|
|
15
|
-
- 💾 Configurable cache headers for better performance
|
|
16
|
-
- 🔌 Works with any Nitro-based application
|
|
17
|
-
- 🎯 Zero-config with sensible defaults
|
|
18
|
-
- 📂 File-based resolver organization
|
|
19
|
-
- 🔄 Hot reload in development mode
|
|
20
|
-
- 📦 Optimized bundle size with dynamic imports
|
|
21
|
-
- 🏷️ Minimal logging with consistent tagging
|
|
37
|
+
### Step 1: Installation
|
|
22
38
|
|
|
23
|
-
|
|
39
|
+
Choose your preferred package manager:
|
|
24
40
|
|
|
25
41
|
```bash
|
|
42
|
+
# npm
|
|
26
43
|
npm install nitro-graphql
|
|
27
|
-
|
|
44
|
+
|
|
45
|
+
# pnpm (recommended)
|
|
28
46
|
pnpm add nitro-graphql
|
|
29
|
-
|
|
47
|
+
|
|
48
|
+
# yarn
|
|
30
49
|
yarn add nitro-graphql
|
|
31
50
|
```
|
|
32
51
|
|
|
33
|
-
|
|
52
|
+
### Step 2: Setup Your Project
|
|
34
53
|
|
|
35
|
-
|
|
54
|
+
<details>
|
|
55
|
+
<summary>🔧 <strong>For Standalone Nitro Projects</strong></summary>
|
|
36
56
|
|
|
57
|
+
1. **Update your `nitro.config.ts`:**
|
|
37
58
|
```ts
|
|
38
|
-
// nitro.config.ts
|
|
39
59
|
import { defineNitroConfig } from 'nitropack/config'
|
|
40
60
|
|
|
41
61
|
export default defineNitroConfig({
|
|
42
62
|
modules: ['nitro-graphql'],
|
|
63
|
+
graphql: {
|
|
64
|
+
framework: 'graphql-yoga', // or 'apollo-server'
|
|
65
|
+
},
|
|
66
|
+
})
|
|
67
|
+
```
|
|
43
68
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
69
|
+
2. **Create the GraphQL directory structure:**
|
|
70
|
+
```bash
|
|
71
|
+
mkdir -p server/graphql
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
</details>
|
|
75
|
+
|
|
76
|
+
<details>
|
|
77
|
+
<summary>🟢 <strong>For Nuxt.js Projects</strong></summary>
|
|
78
|
+
|
|
79
|
+
1. **Update your `nuxt.config.ts`:**
|
|
80
|
+
```ts
|
|
81
|
+
export default defineNuxtConfig({
|
|
82
|
+
modules: [
|
|
83
|
+
'nitro-graphql/nuxt',
|
|
84
|
+
],
|
|
85
|
+
nitro: {
|
|
86
|
+
modules: ['nitro-graphql'],
|
|
87
|
+
graphql: {
|
|
88
|
+
framework: 'graphql-yoga',
|
|
89
|
+
},
|
|
90
|
+
},
|
|
50
91
|
})
|
|
51
92
|
```
|
|
52
93
|
|
|
53
|
-
|
|
94
|
+
2. **Create the GraphQL directory structure:**
|
|
95
|
+
```bash
|
|
96
|
+
mkdir -p server/graphql
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
</details>
|
|
100
|
+
|
|
101
|
+
### Step 3: Create Your First Schema
|
|
54
102
|
|
|
55
|
-
|
|
103
|
+
Create your main schema file:
|
|
56
104
|
|
|
57
|
-
#### Main Schema File
|
|
58
105
|
```graphql
|
|
59
106
|
# server/graphql/schema.graphql
|
|
60
107
|
scalar DateTime
|
|
@@ -68,7 +115,79 @@ type Query {
|
|
|
68
115
|
type Mutation
|
|
69
116
|
```
|
|
70
117
|
|
|
71
|
-
|
|
118
|
+
### Step 4: Create Your First Resolver
|
|
119
|
+
|
|
120
|
+
Create a resolver for your queries:
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
// server/graphql/hello.resolver.ts
|
|
124
|
+
import { defineResolver } from 'nitro-graphql/utils/define'
|
|
125
|
+
|
|
126
|
+
export const helloResolver = defineResolver({
|
|
127
|
+
Query: {
|
|
128
|
+
hello: () => 'Hello from GraphQL!',
|
|
129
|
+
greeting: (_, { name }) => `Hello, ${name}!`,
|
|
130
|
+
},
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
// You can also export multiple resolvers from the same file
|
|
134
|
+
export const additionalResolver = defineResolver({
|
|
135
|
+
Query: {
|
|
136
|
+
// Additional query resolvers
|
|
137
|
+
},
|
|
138
|
+
})
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Step 5: Start Your Server
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# For Nitro
|
|
145
|
+
pnpm dev
|
|
146
|
+
|
|
147
|
+
# For Nuxt
|
|
148
|
+
pnpm dev
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Step 6: Test Your GraphQL API
|
|
152
|
+
|
|
153
|
+
🎉 **That's it!** Your GraphQL server is now running at:
|
|
154
|
+
|
|
155
|
+
- **GraphQL Endpoint**: `http://localhost:3000/api/graphql`
|
|
156
|
+
- **Apollo Sandbox**: `http://localhost:3000/api/graphql` (in browser)
|
|
157
|
+
- **Health Check**: `http://localhost:3000/api/graphql/health`
|
|
158
|
+
|
|
159
|
+
## 📖 Documentation
|
|
160
|
+
|
|
161
|
+
### Project Structure
|
|
162
|
+
|
|
163
|
+
The module uses a domain-driven file structure under `server/graphql/`:
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
server/
|
|
167
|
+
├── graphql/
|
|
168
|
+
│ ├── schema.graphql # Main schema with scalars and base types
|
|
169
|
+
│ ├── hello.resolver.ts # Global resolvers (use named exports)
|
|
170
|
+
│ ├── users/
|
|
171
|
+
│ │ ├── user.graphql # User schema definitions
|
|
172
|
+
│ │ ├── user-queries.resolver.ts # User query resolvers (use named exports)
|
|
173
|
+
│ │ └── create-user.resolver.ts # User mutation resolvers (use named exports)
|
|
174
|
+
│ ├── posts/
|
|
175
|
+
│ │ ├── post.graphql # Post schema definitions
|
|
176
|
+
│ │ ├── post-queries.resolver.ts # Post query resolvers (use named exports)
|
|
177
|
+
│ │ └── create-post.resolver.ts # Post mutation resolvers (use named exports)
|
|
178
|
+
│ └── config.ts # Optional GraphQL configuration
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
> [!TIP]
|
|
182
|
+
> **New Named Export Pattern**: The module now supports named exports for GraphQL resolvers, allowing you to export multiple resolvers from a single file. This provides better organization and flexibility in structuring your resolver code.
|
|
183
|
+
|
|
184
|
+
### Building Your First Feature
|
|
185
|
+
|
|
186
|
+
Let's create a complete user management feature:
|
|
187
|
+
|
|
188
|
+
<details>
|
|
189
|
+
<summary>👤 <strong>Step 1: Define User Schema</strong></summary>
|
|
190
|
+
|
|
72
191
|
```graphql
|
|
73
192
|
# server/graphql/users/user.graphql
|
|
74
193
|
type User {
|
|
@@ -93,267 +212,483 @@ extend type Mutation {
|
|
|
93
212
|
}
|
|
94
213
|
```
|
|
95
214
|
|
|
96
|
-
|
|
215
|
+
</details>
|
|
216
|
+
|
|
217
|
+
<details>
|
|
218
|
+
<summary>🔍 <strong>Step 2: Create Query Resolvers</strong></summary>
|
|
219
|
+
|
|
97
220
|
```ts
|
|
98
|
-
// server/graphql/users/user-queries.ts
|
|
99
|
-
import {
|
|
221
|
+
// server/graphql/users/user-queries.resolver.ts
|
|
222
|
+
import { defineQuery } from 'nitro-graphql/utils/define'
|
|
100
223
|
|
|
101
|
-
export
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
return users.find(user => user.id === id)
|
|
109
|
-
}
|
|
224
|
+
export const userQueries = defineQuery({
|
|
225
|
+
users: async (_, __, { storage }) => {
|
|
226
|
+
return await storage.getItem('users') || []
|
|
227
|
+
},
|
|
228
|
+
user: async (_, { id }, { storage }) => {
|
|
229
|
+
const users = await storage.getItem('users') || []
|
|
230
|
+
return users.find(user => user.id === id)
|
|
110
231
|
}
|
|
111
232
|
})
|
|
233
|
+
|
|
234
|
+
// You can also split queries into separate named exports
|
|
235
|
+
export const additionalUserQueries = defineQuery({
|
|
236
|
+
userCount: async (_, __, { storage }) => {
|
|
237
|
+
const users = await storage.getItem('users') || []
|
|
238
|
+
return users.length
|
|
239
|
+
},
|
|
240
|
+
})
|
|
112
241
|
```
|
|
113
242
|
|
|
114
|
-
|
|
115
|
-
// server/graphql/users/create-user.ts
|
|
116
|
-
import { defineResolver } from 'nitro-graphql'
|
|
243
|
+
</details>
|
|
117
244
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
245
|
+
<details>
|
|
246
|
+
<summary>✏️ <strong>Step 3: Create Mutation Resolvers</strong></summary>
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
// server/graphql/users/create-user.resolver.ts
|
|
250
|
+
import { defineMutation } from 'nitro-graphql/utils/define'
|
|
251
|
+
|
|
252
|
+
export const createUserMutation = defineMutation({
|
|
253
|
+
createUser: async (_, { input }, { storage }) => {
|
|
254
|
+
const users = await storage.getItem('users') || []
|
|
255
|
+
const user = {
|
|
256
|
+
id: Date.now().toString(),
|
|
257
|
+
...input,
|
|
258
|
+
createdAt: new Date()
|
|
130
259
|
}
|
|
260
|
+
users.push(user)
|
|
261
|
+
await storage.setItem('users', users)
|
|
262
|
+
return user
|
|
263
|
+
}
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
// You can also export multiple mutations from the same file
|
|
267
|
+
export const updateUserMutation = defineMutation({
|
|
268
|
+
updateUser: async (_, { id, input }, { storage }) => {
|
|
269
|
+
const users = await storage.getItem('users') || []
|
|
270
|
+
const userIndex = users.findIndex(user => user.id === id)
|
|
271
|
+
if (userIndex === -1)
|
|
272
|
+
throw new Error('User not found')
|
|
273
|
+
|
|
274
|
+
users[userIndex] = { ...users[userIndex], ...input }
|
|
275
|
+
await storage.setItem('users', users)
|
|
276
|
+
return users[userIndex]
|
|
131
277
|
}
|
|
132
278
|
})
|
|
133
279
|
```
|
|
134
280
|
|
|
135
|
-
|
|
281
|
+
</details>
|
|
136
282
|
|
|
137
|
-
|
|
283
|
+
<details>
|
|
284
|
+
<summary>🧪 <strong>Step 4: Test Your Feature</strong></summary>
|
|
138
285
|
|
|
139
|
-
|
|
140
|
-
// server/graphql/hello.ts
|
|
141
|
-
import { defineResolver } from 'nitro-graphql'
|
|
286
|
+
Open Apollo Sandbox at `http://localhost:3000/api/graphql` and try:
|
|
142
287
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
288
|
+
```graphql
|
|
289
|
+
# Create a user
|
|
290
|
+
mutation {
|
|
291
|
+
createUser(input: {
|
|
292
|
+
name: "John Doe"
|
|
293
|
+
email: "john@example.com"
|
|
294
|
+
}) {
|
|
295
|
+
id
|
|
296
|
+
name
|
|
297
|
+
email
|
|
298
|
+
createdAt
|
|
147
299
|
}
|
|
148
|
-
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
# Query users
|
|
303
|
+
query {
|
|
304
|
+
users {
|
|
305
|
+
id
|
|
306
|
+
name
|
|
307
|
+
email
|
|
308
|
+
}
|
|
309
|
+
}
|
|
149
310
|
```
|
|
150
311
|
|
|
151
|
-
|
|
312
|
+
</details>
|
|
152
313
|
|
|
153
|
-
|
|
314
|
+
### Type Generation
|
|
154
315
|
|
|
155
|
-
|
|
156
|
-
- **Type declarations**: `.nitro/types/graphql.d.ts`
|
|
316
|
+
The module automatically generates TypeScript types for you:
|
|
157
317
|
|
|
158
|
-
|
|
318
|
+
- **Server types**: `.nitro/types/nitro-graphql-server.d.ts`
|
|
319
|
+
- **Client types**: `.nitro/types/nitro-graphql-client.d.ts`
|
|
320
|
+
- **Auto-imports**: Available for `defineResolver` and other utilities
|
|
159
321
|
|
|
160
|
-
|
|
161
|
-
import type { QueryResolvers } from '#graphql/server'
|
|
162
|
-
// server/graphql/users/user-queries.ts
|
|
163
|
-
import { defineResolver } from 'nitro-graphql'
|
|
322
|
+
Your IDE will automatically provide type safety and autocomplete!
|
|
164
323
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
324
|
+
> [!TIP]
|
|
325
|
+
> **Nitro Auto-Imports**: Thanks to Nitro's auto-import feature, you don't need to manually import `defineResolver`, `defineQuery`, `defineMutation`, and other utilities in your resolver files. They're available globally! However, if you prefer explicit imports, you can use:
|
|
326
|
+
> ```ts
|
|
327
|
+
> import { defineResolver } from 'nitro-graphql/utils/define'
|
|
328
|
+
> ```
|
|
329
|
+
|
|
330
|
+
### Configuration
|
|
331
|
+
|
|
332
|
+
<details>
|
|
333
|
+
<summary>⚙️ <strong>Runtime Configuration</strong></summary>
|
|
334
|
+
|
|
335
|
+
```ts
|
|
336
|
+
// nitro.config.ts
|
|
337
|
+
export default defineNitroConfig({
|
|
338
|
+
modules: ['nitro-graphql'],
|
|
339
|
+
graphql: {
|
|
340
|
+
framework: 'graphql-yoga', // or 'apollo-server'
|
|
341
|
+
},
|
|
342
|
+
runtimeConfig: {
|
|
343
|
+
graphql: {
|
|
344
|
+
endpoint: {
|
|
345
|
+
graphql: '/api/graphql', // GraphQL endpoint
|
|
346
|
+
healthCheck: '/api/graphql/health' // Health check endpoint
|
|
347
|
+
},
|
|
348
|
+
playground: true, // Enable Apollo Sandbox
|
|
169
349
|
}
|
|
170
|
-
}
|
|
350
|
+
}
|
|
171
351
|
})
|
|
172
352
|
```
|
|
173
353
|
|
|
174
|
-
|
|
354
|
+
</details>
|
|
175
355
|
|
|
176
|
-
|
|
356
|
+
<details>
|
|
357
|
+
<summary>🔧 <strong>Advanced Configuration</strong></summary>
|
|
177
358
|
|
|
178
|
-
```
|
|
179
|
-
server/
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
│ └── comments/
|
|
196
|
-
│ ├── comment.graphql # Comment schema definitions
|
|
197
|
-
│ ├── comment-queries.ts # Comment query resolvers
|
|
198
|
-
│ └── add-comment.ts # Comment mutation resolvers
|
|
359
|
+
```ts
|
|
360
|
+
// server/graphql/config.ts
|
|
361
|
+
import { defineGraphQLConfig } from 'nitro-graphql/utils/define'
|
|
362
|
+
|
|
363
|
+
export default defineGraphQLConfig({
|
|
364
|
+
// Custom GraphQL Yoga or Apollo Server configuration
|
|
365
|
+
plugins: [
|
|
366
|
+
// Add custom plugins
|
|
367
|
+
],
|
|
368
|
+
context: async ({ request }) => {
|
|
369
|
+
// Enhanced context with custom properties
|
|
370
|
+
return {
|
|
371
|
+
user: await authenticateUser(request),
|
|
372
|
+
db: await connectDatabase(),
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
})
|
|
199
376
|
```
|
|
200
377
|
|
|
201
|
-
|
|
378
|
+
</details>
|
|
202
379
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
380
|
+
## 🎮 Playground
|
|
381
|
+
|
|
382
|
+
Try out the examples:
|
|
383
|
+
|
|
384
|
+
- **Standalone Nitro**: [`playground/`](playground/)
|
|
385
|
+
- **Nuxt.js Integration**: [`playground-nuxt/`](playground-nuxt/)
|
|
386
|
+
|
|
387
|
+
Both examples include working GraphQL schemas, resolvers, and demonstrate the module's capabilities.
|
|
388
|
+
|
|
389
|
+
## 🔧 API Reference
|
|
390
|
+
|
|
391
|
+
### Core Utilities
|
|
392
|
+
|
|
393
|
+
> [!NOTE]
|
|
394
|
+
> **Auto-Import Available**: All utilities are automatically imported in your resolver files thanks to Nitro's auto-import feature. You can use them directly without import statements, or use explicit imports if you prefer:
|
|
395
|
+
> ```ts
|
|
396
|
+
> import { defineMutation, defineQuery, defineResolver } from 'nitro-graphql/utils/define'
|
|
397
|
+
> ```
|
|
398
|
+
|
|
399
|
+
> [!IMPORTANT]
|
|
400
|
+
> **Named Exports Required**: All GraphQL resolvers must now use named exports instead of default exports. This allows you to export multiple resolvers from a single file, providing better organization and flexibility. For example:
|
|
401
|
+
> ```ts
|
|
402
|
+
> // ✅ Correct - Named exports
|
|
403
|
+
> export const userQueries = defineQuery({ ... })
|
|
404
|
+
> export const userMutations = defineMutation({ ... })
|
|
405
|
+
>
|
|
406
|
+
> // ❌ Incorrect - Default exports (deprecated)
|
|
407
|
+
> export default defineQuery({ ... })
|
|
408
|
+
> ```
|
|
409
|
+
|
|
410
|
+
<details>
|
|
411
|
+
<summary><strong>defineResolver</strong> - Define complete resolvers</summary>
|
|
207
412
|
|
|
208
413
|
```ts
|
|
209
|
-
|
|
210
|
-
import { defineResolver } from 'nitro-graphql'
|
|
414
|
+
import { defineResolver } from 'nitro-graphql/utils/define'
|
|
211
415
|
|
|
212
|
-
export
|
|
416
|
+
export const mainResolver = defineResolver({
|
|
213
417
|
Query: {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
418
|
+
// Query resolvers
|
|
419
|
+
},
|
|
420
|
+
Mutation: {
|
|
421
|
+
// Mutation resolvers
|
|
422
|
+
},
|
|
423
|
+
// Custom type resolvers
|
|
424
|
+
})
|
|
217
425
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
426
|
+
// You can also export multiple resolvers from the same file
|
|
427
|
+
export const additionalResolver = defineResolver({
|
|
428
|
+
Query: {
|
|
429
|
+
// Additional query resolvers
|
|
430
|
+
},
|
|
431
|
+
})
|
|
432
|
+
```
|
|
221
433
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
434
|
+
</details>
|
|
435
|
+
|
|
436
|
+
<details>
|
|
437
|
+
<summary><strong>defineQuery</strong> - Define only Query resolvers</summary>
|
|
438
|
+
|
|
439
|
+
```ts
|
|
440
|
+
import { defineQuery } from 'nitro-graphql/utils/define'
|
|
441
|
+
|
|
442
|
+
export const userQueries = defineQuery({
|
|
443
|
+
users: async (_, __, { storage }) => {
|
|
444
|
+
return await storage.getItem('users') || []
|
|
445
|
+
},
|
|
446
|
+
user: async (_, { id }, { storage }) => {
|
|
447
|
+
const users = await storage.getItem('users') || []
|
|
448
|
+
return users.find(user => user.id === id)
|
|
225
449
|
}
|
|
226
450
|
})
|
|
451
|
+
|
|
452
|
+
// You can also split queries into separate named exports
|
|
453
|
+
export const userStatsQueries = defineQuery({
|
|
454
|
+
userCount: async (_, __, { storage }) => {
|
|
455
|
+
const users = await storage.getItem('users') || []
|
|
456
|
+
return users.length
|
|
457
|
+
},
|
|
458
|
+
})
|
|
227
459
|
```
|
|
228
460
|
|
|
229
|
-
|
|
461
|
+
</details>
|
|
462
|
+
|
|
463
|
+
<details>
|
|
464
|
+
<summary><strong>defineMutation</strong> - Define only Mutation resolvers</summary>
|
|
230
465
|
|
|
231
466
|
```ts
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
467
|
+
import { defineMutation } from 'nitro-graphql/utils/define'
|
|
468
|
+
|
|
469
|
+
export const userMutations = defineMutation({
|
|
470
|
+
createUser: async (_, { input }, { storage }) => {
|
|
471
|
+
const users = await storage.getItem('users') || []
|
|
472
|
+
const user = {
|
|
473
|
+
id: Date.now().toString(),
|
|
474
|
+
...input,
|
|
475
|
+
createdAt: new Date()
|
|
476
|
+
}
|
|
477
|
+
users.push(user)
|
|
478
|
+
await storage.setItem('users', users)
|
|
479
|
+
return user
|
|
244
480
|
}
|
|
481
|
+
})
|
|
245
482
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
483
|
+
// You can also export multiple mutations from the same file
|
|
484
|
+
export const userUpdateMutations = defineMutation({
|
|
485
|
+
updateUser: async (_, { id, input }, { storage }) => {
|
|
486
|
+
const users = await storage.getItem('users') || []
|
|
487
|
+
const userIndex = users.findIndex(user => user.id === id)
|
|
488
|
+
if (userIndex === -1)
|
|
489
|
+
throw new Error('User not found')
|
|
490
|
+
|
|
491
|
+
users[userIndex] = { ...users[userIndex], ...input }
|
|
492
|
+
await storage.setItem('users', users)
|
|
493
|
+
return users[userIndex]
|
|
257
494
|
}
|
|
258
|
-
}
|
|
495
|
+
})
|
|
259
496
|
```
|
|
260
497
|
|
|
261
|
-
|
|
498
|
+
</details>
|
|
262
499
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
- Regenerates TypeScript types
|
|
266
|
-
- Reloads the GraphQL schema
|
|
267
|
-
- Updates resolvers
|
|
500
|
+
<details>
|
|
501
|
+
<summary><strong>defineSubscription</strong> - Define Subscription resolvers</summary>
|
|
268
502
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
- Optimized chunk organization for better caching
|
|
272
|
-
- Minimal logging output with consistent `[graphql]` tagging
|
|
273
|
-
|
|
274
|
-
### Health Check
|
|
275
|
-
Access the health check endpoint at `/api/graphql/health` to verify your GraphQL server status.
|
|
503
|
+
```ts
|
|
504
|
+
import { defineSubscription } from 'nitro-graphql/utils/define'
|
|
276
505
|
|
|
277
|
-
|
|
506
|
+
export const userSubscriptions = defineSubscription({
|
|
507
|
+
userAdded: {
|
|
508
|
+
subscribe: () => pubsub.asyncIterator('USER_ADDED'),
|
|
509
|
+
},
|
|
510
|
+
postUpdated: {
|
|
511
|
+
subscribe: withFilter(
|
|
512
|
+
() => pubsub.asyncIterator('POST_UPDATED'),
|
|
513
|
+
(payload, variables) => payload.postUpdated.id === variables.postId
|
|
514
|
+
),
|
|
515
|
+
}
|
|
516
|
+
})
|
|
278
517
|
|
|
279
|
-
|
|
518
|
+
// You can also export multiple subscriptions from the same file
|
|
519
|
+
export const notificationSubscriptions = defineSubscription({
|
|
520
|
+
notificationAdded: {
|
|
521
|
+
subscribe: () => pubsub.asyncIterator('NOTIFICATION_ADDED'),
|
|
522
|
+
},
|
|
523
|
+
})
|
|
524
|
+
```
|
|
280
525
|
|
|
281
|
-
|
|
526
|
+
</details>
|
|
282
527
|
|
|
283
|
-
|
|
528
|
+
<details>
|
|
529
|
+
<summary><strong>defineType</strong> - Define custom type resolvers</summary>
|
|
284
530
|
|
|
285
531
|
```ts
|
|
286
|
-
import {
|
|
287
|
-
import { useResponseCache } from '@graphql-yoga/plugin-response-cache'
|
|
288
|
-
// server/graphql/yoga.config.ts
|
|
289
|
-
import { defineYogaConfig } from 'nitro-graphql'
|
|
290
|
-
|
|
291
|
-
export default defineYogaConfig({
|
|
292
|
-
// Add custom plugins
|
|
293
|
-
plugins: [
|
|
294
|
-
useCORS({
|
|
295
|
-
origin: process.env.NODE_ENV === 'production' ? 'https://yourdomain.com' : '*',
|
|
296
|
-
credentials: true,
|
|
297
|
-
}),
|
|
298
|
-
useResponseCache({
|
|
299
|
-
session: () => null,
|
|
300
|
-
ttl: 60_000, // 1 minute
|
|
301
|
-
}),
|
|
302
|
-
],
|
|
303
|
-
|
|
304
|
-
// Enhanced context with custom properties
|
|
305
|
-
context: async ({ request }) => {
|
|
306
|
-
const event = request.$$event
|
|
532
|
+
import { defineType } from 'nitro-graphql/utils/define'
|
|
307
533
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
storage
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
startTime: Date.now(),
|
|
316
|
-
}
|
|
534
|
+
export const userTypes = defineType({
|
|
535
|
+
User: {
|
|
536
|
+
posts: async (parent, _, { storage }) => {
|
|
537
|
+
const posts = await storage.getItem('posts') || []
|
|
538
|
+
return posts.filter(post => post.authorId === parent.id)
|
|
539
|
+
},
|
|
540
|
+
fullName: parent => `${parent.firstName} ${parent.lastName}`,
|
|
317
541
|
},
|
|
542
|
+
})
|
|
318
543
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
return isDev ? error : new Error('Internal server error')
|
|
544
|
+
// You can also export multiple type resolvers from the same file
|
|
545
|
+
export const postTypes = defineType({
|
|
546
|
+
Post: {
|
|
547
|
+
author: async (parent, _, { storage }) => {
|
|
548
|
+
const users = await storage.getItem('users') || []
|
|
549
|
+
return users.find(user => user.id === parent.authorId)
|
|
326
550
|
},
|
|
327
551
|
},
|
|
552
|
+
})
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
</details>
|
|
328
556
|
|
|
329
|
-
|
|
330
|
-
|
|
557
|
+
<details>
|
|
558
|
+
<summary><strong>defineSchema</strong> - Define custom schema with validation</summary>
|
|
559
|
+
|
|
560
|
+
You can override schema types if needed. StandardSchema supported — Zod, Valibot, anything works:
|
|
561
|
+
|
|
562
|
+
```ts
|
|
563
|
+
import { defineSchema } from 'nitro-graphql/utils/define'
|
|
564
|
+
import { z } from 'zod'
|
|
565
|
+
|
|
566
|
+
export default defineSchema({
|
|
567
|
+
Todo: z.object({
|
|
568
|
+
id: z.string(),
|
|
569
|
+
title: z.string(),
|
|
570
|
+
completed: z.boolean(),
|
|
571
|
+
createdAt: z.date(),
|
|
572
|
+
}),
|
|
573
|
+
User: z.object({
|
|
574
|
+
id: z.string(),
|
|
575
|
+
name: z.string(),
|
|
576
|
+
email: z.string().email(),
|
|
577
|
+
age: z.number().min(0),
|
|
578
|
+
}),
|
|
331
579
|
})
|
|
332
580
|
```
|
|
333
581
|
|
|
334
|
-
**
|
|
582
|
+
**With Drizzle Schema:**
|
|
583
|
+
```ts
|
|
584
|
+
import { defineSchema } from 'nitro-graphql/utils/define'
|
|
585
|
+
import { z } from 'zod'
|
|
586
|
+
import { userSchema } from './drizzle/user'
|
|
587
|
+
|
|
588
|
+
export default defineSchema({
|
|
589
|
+
Todo: z.object({
|
|
590
|
+
id: z.string(),
|
|
591
|
+
title: z.string(),
|
|
592
|
+
}),
|
|
593
|
+
User: userSchema, // Import from Drizzle schema
|
|
594
|
+
})
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
</details>
|
|
598
|
+
|
|
599
|
+
## 🚨 Troubleshooting
|
|
600
|
+
|
|
601
|
+
<details>
|
|
602
|
+
<summary><strong>Common Issues</strong></summary>
|
|
603
|
+
|
|
604
|
+
### GraphQL endpoint returns 404
|
|
605
|
+
|
|
606
|
+
**Solution**: Make sure you have:
|
|
607
|
+
1. Added `nitro-graphql` to your modules
|
|
608
|
+
2. Set the `graphql.framework` option
|
|
609
|
+
3. Created at least one schema file
|
|
610
|
+
|
|
611
|
+
### Types not generating
|
|
612
|
+
|
|
613
|
+
**Solution**:
|
|
614
|
+
1. Restart your dev server
|
|
615
|
+
2. Check that your schema files end with `.graphql`
|
|
616
|
+
3. Verify your resolver files end with `.resolver.ts`
|
|
617
|
+
|
|
618
|
+
### Hot reload not working
|
|
619
|
+
|
|
620
|
+
**Solution**:
|
|
621
|
+
1. Make sure you're in development mode
|
|
622
|
+
2. Check file naming conventions
|
|
623
|
+
3. Restart the dev server
|
|
624
|
+
|
|
625
|
+
### Import errors with utilities
|
|
626
|
+
|
|
627
|
+
**Solution**:
|
|
628
|
+
```ts
|
|
629
|
+
// ❌ Incorrect import path
|
|
630
|
+
import { defineResolver } from 'nitro-graphql'
|
|
631
|
+
|
|
632
|
+
// ✅ Correct import path
|
|
633
|
+
import { defineResolver } from 'nitro-graphql/utils/define'
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
### Export pattern errors
|
|
637
|
+
|
|
638
|
+
**Solution**:
|
|
639
|
+
```ts
|
|
640
|
+
// ❌ Incorrect - Default exports (deprecated)
|
|
641
|
+
export default defineResolver({ ... })
|
|
642
|
+
|
|
643
|
+
// ✅ Correct - Named exports
|
|
644
|
+
export const myResolver = defineResolver({ ... })
|
|
645
|
+
export const anotherResolver = defineResolver({ ... })
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
</details>
|
|
335
649
|
|
|
336
|
-
|
|
650
|
+
## 🌟 Framework Support
|
|
337
651
|
|
|
338
|
-
|
|
652
|
+
<details>
|
|
653
|
+
<summary><strong>GraphQL Yoga</strong></summary>
|
|
339
654
|
|
|
340
655
|
```ts
|
|
341
656
|
// nitro.config.ts
|
|
342
657
|
export default defineNitroConfig({
|
|
343
|
-
|
|
344
|
-
|
|
658
|
+
graphql: {
|
|
659
|
+
framework: 'graphql-yoga',
|
|
660
|
+
},
|
|
345
661
|
})
|
|
346
662
|
```
|
|
347
663
|
|
|
348
|
-
|
|
664
|
+
</details>
|
|
665
|
+
|
|
666
|
+
<details>
|
|
667
|
+
<summary><strong>Apollo Server</strong></summary>
|
|
349
668
|
|
|
350
669
|
```ts
|
|
670
|
+
// nitro.config.ts
|
|
671
|
+
export default defineNitroConfig({
|
|
672
|
+
graphql: {
|
|
673
|
+
framework: 'apollo-server',
|
|
674
|
+
},
|
|
675
|
+
})
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
</details>
|
|
679
|
+
|
|
680
|
+
## 🔥 Advanced Features
|
|
681
|
+
|
|
682
|
+
<details>
|
|
683
|
+
<summary><strong>Custom Scalars</strong></summary>
|
|
684
|
+
|
|
685
|
+
```ts
|
|
686
|
+
// server/graphql/scalars/DateTime.resolver.ts
|
|
351
687
|
import { GraphQLScalarType } from 'graphql'
|
|
352
688
|
import { Kind } from 'graphql/language'
|
|
353
|
-
|
|
354
|
-
import { defineResolver } from 'nitro-graphql'
|
|
689
|
+
import { defineResolver } from 'nitro-graphql/utils/define'
|
|
355
690
|
|
|
356
|
-
export
|
|
691
|
+
export const dateTimeScalar = defineResolver({
|
|
357
692
|
DateTime: new GraphQLScalarType({
|
|
358
693
|
name: 'DateTime',
|
|
359
694
|
serialize: (value: Date) => value.toISOString(),
|
|
@@ -366,47 +701,282 @@ export default defineResolver({
|
|
|
366
701
|
}
|
|
367
702
|
})
|
|
368
703
|
})
|
|
704
|
+
|
|
705
|
+
// You can also export multiple scalars from the same file
|
|
706
|
+
export const jsonScalar = defineResolver({
|
|
707
|
+
JSON: new GraphQLScalarType({
|
|
708
|
+
name: 'JSON',
|
|
709
|
+
serialize: value => value,
|
|
710
|
+
parseValue: value => value,
|
|
711
|
+
parseLiteral: (ast) => {
|
|
712
|
+
if (ast.kind === Kind.STRING) {
|
|
713
|
+
return JSON.parse(ast.value)
|
|
714
|
+
}
|
|
715
|
+
return null
|
|
716
|
+
}
|
|
717
|
+
})
|
|
718
|
+
})
|
|
369
719
|
```
|
|
370
720
|
|
|
371
|
-
|
|
721
|
+
</details>
|
|
372
722
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
import { defineResolver } from 'nitro-graphql'
|
|
723
|
+
<details>
|
|
724
|
+
<summary><strong>Error Handling</strong></summary>
|
|
376
725
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
catch (error) {
|
|
388
|
-
console.error('[graphql] Error fetching user:', error)
|
|
389
|
-
throw error
|
|
726
|
+
```ts
|
|
727
|
+
// server/graphql/users/user-queries.resolver.ts
|
|
728
|
+
import { defineQuery } from 'nitro-graphql/utils/define'
|
|
729
|
+
|
|
730
|
+
export const userQueries = defineQuery({
|
|
731
|
+
user: async (_, { id }, { storage }) => {
|
|
732
|
+
try {
|
|
733
|
+
const user = await storage.getItem(`user:${id}`)
|
|
734
|
+
if (!user) {
|
|
735
|
+
throw new Error(`User with id ${id} not found`)
|
|
390
736
|
}
|
|
737
|
+
return user
|
|
738
|
+
}
|
|
739
|
+
catch (error) {
|
|
740
|
+
console.error('Error fetching user:', error)
|
|
741
|
+
throw error
|
|
391
742
|
}
|
|
392
743
|
}
|
|
393
744
|
})
|
|
745
|
+
|
|
746
|
+
// You can also export additional error handling queries
|
|
747
|
+
export const safeUserQueries = defineQuery({
|
|
748
|
+
userSafe: async (_, { id }, { storage }) => {
|
|
749
|
+
try {
|
|
750
|
+
const user = await storage.getItem(`user:${id}`)
|
|
751
|
+
return user || null // Return null instead of throwing
|
|
752
|
+
}
|
|
753
|
+
catch (error) {
|
|
754
|
+
console.error('Error fetching user:', error)
|
|
755
|
+
return null
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
})
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
</details>
|
|
762
|
+
|
|
763
|
+
<details>
|
|
764
|
+
<summary><strong>Nuxt Integration</strong></summary>
|
|
765
|
+
|
|
766
|
+
For Nuxt.js applications, the module provides enhanced integration:
|
|
767
|
+
|
|
768
|
+
```ts
|
|
769
|
+
// nuxt.config.ts
|
|
770
|
+
export default defineNuxtConfig({
|
|
771
|
+
modules: [
|
|
772
|
+
'nitro-graphql/nuxt',
|
|
773
|
+
],
|
|
774
|
+
nitro: {
|
|
775
|
+
modules: ['nitro-graphql'],
|
|
776
|
+
graphql: {
|
|
777
|
+
framework: 'graphql-yoga',
|
|
778
|
+
},
|
|
779
|
+
},
|
|
780
|
+
})
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
Client-side GraphQL files are automatically detected in the `app/graphql/` directory.
|
|
784
|
+
|
|
785
|
+
### Client-Side Usage
|
|
786
|
+
|
|
787
|
+
The module automatically generates a GraphQL SDK and provides type-safe client access for frontend usage.
|
|
788
|
+
|
|
789
|
+
<details>
|
|
790
|
+
<summary>📁 <strong>GraphQL File Structure</strong></summary>
|
|
791
|
+
|
|
792
|
+
Create your GraphQL queries and mutations in the `app/graphql/` directory:
|
|
793
|
+
|
|
794
|
+
```
|
|
795
|
+
app/
|
|
796
|
+
├── graphql/
|
|
797
|
+
│ ├── queries.graphql # GraphQL queries
|
|
798
|
+
│ ├── mutations.graphql # GraphQL mutations
|
|
799
|
+
│ └── subscriptions.graphql # GraphQL subscriptions (optional)
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
</details>
|
|
803
|
+
|
|
804
|
+
<details>
|
|
805
|
+
<summary>🔥 <strong>Creating GraphQL Files</strong></summary>
|
|
806
|
+
|
|
807
|
+
**Query File Example:**
|
|
808
|
+
```graphql
|
|
809
|
+
# app/graphql/queries.graphql
|
|
810
|
+
query GetUsers {
|
|
811
|
+
users {
|
|
812
|
+
id
|
|
813
|
+
name
|
|
814
|
+
email
|
|
815
|
+
createdAt
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
query GetUser($id: ID!) {
|
|
820
|
+
user(id: $id) {
|
|
821
|
+
id
|
|
822
|
+
name
|
|
823
|
+
email
|
|
824
|
+
createdAt
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
```
|
|
828
|
+
|
|
829
|
+
**Mutation File Example:**
|
|
830
|
+
```graphql
|
|
831
|
+
# app/graphql/mutations.graphql
|
|
832
|
+
mutation CreateUser($input: CreateUserInput!) {
|
|
833
|
+
createUser(input: $input) {
|
|
834
|
+
id
|
|
835
|
+
name
|
|
836
|
+
email
|
|
837
|
+
createdAt
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
mutation UpdateUser($id: ID!, $input: UpdateUserInput!) {
|
|
842
|
+
updateUser(id: $id, input: $input) {
|
|
843
|
+
id
|
|
844
|
+
name
|
|
845
|
+
email
|
|
846
|
+
createdAt
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
</details>
|
|
852
|
+
|
|
853
|
+
<details>
|
|
854
|
+
<summary>⚡ <strong>Using the Generated SDK</strong></summary>
|
|
855
|
+
|
|
856
|
+
The module automatically generates a type-safe SDK based on your GraphQL files:
|
|
857
|
+
|
|
858
|
+
```ts
|
|
859
|
+
// The SDK is automatically generated and available as an import
|
|
860
|
+
import { createGraphQLClient } from '#graphql/client'
|
|
861
|
+
|
|
862
|
+
// Create a client instance
|
|
863
|
+
const client = createGraphQLClient({
|
|
864
|
+
endpoint: '/api/graphql',
|
|
865
|
+
headers: {
|
|
866
|
+
'Authorization': 'Bearer your-token-here'
|
|
867
|
+
}
|
|
868
|
+
})
|
|
869
|
+
|
|
870
|
+
// Use the generated methods with full type safety
|
|
871
|
+
const getUsersData = await client.GetUsers()
|
|
872
|
+
console.log(getUsersData.users) // Fully typed response
|
|
873
|
+
|
|
874
|
+
const newUser = await client.CreateUser({
|
|
875
|
+
input: {
|
|
876
|
+
name: 'John Doe',
|
|
877
|
+
email: 'john@example.com'
|
|
878
|
+
}
|
|
879
|
+
})
|
|
880
|
+
console.log(newUser.createUser) // Fully typed response
|
|
394
881
|
```
|
|
395
882
|
|
|
396
|
-
|
|
883
|
+
</details>
|
|
884
|
+
|
|
885
|
+
<details>
|
|
886
|
+
<summary>🎯 <strong>Basic Usage Examples</strong></summary>
|
|
397
887
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
- Efficient chunk organization
|
|
888
|
+
**Fetching Data:**
|
|
889
|
+
```ts
|
|
890
|
+
// Import the generated client
|
|
891
|
+
import { createGraphQLClient } from '#graphql/client'
|
|
403
892
|
|
|
404
|
-
|
|
405
|
-
- Built-in cache headers for Apollo Sandbox (1 week)
|
|
406
|
-
- Configurable cache settings
|
|
407
|
-
- Lazy schema initialization
|
|
893
|
+
const client = createGraphQLClient()
|
|
408
894
|
|
|
409
|
-
|
|
895
|
+
// Query users
|
|
896
|
+
const { users } = await client.GetUsers()
|
|
897
|
+
console.log(users) // Array of User objects with full typing
|
|
898
|
+
|
|
899
|
+
// Query specific user
|
|
900
|
+
const { user } = await client.GetUser({ id: '123' })
|
|
901
|
+
console.log(user) // User object or null
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
**Creating Data:**
|
|
905
|
+
```ts
|
|
906
|
+
// Create a new user
|
|
907
|
+
const { createUser } = await client.CreateUser({
|
|
908
|
+
input: {
|
|
909
|
+
name: 'Jane Doe',
|
|
910
|
+
email: 'jane@example.com'
|
|
911
|
+
}
|
|
912
|
+
})
|
|
913
|
+
console.log(createUser) // Newly created user with full typing
|
|
914
|
+
```
|
|
915
|
+
|
|
916
|
+
**Error Handling:**
|
|
917
|
+
```ts
|
|
918
|
+
try {
|
|
919
|
+
const { users } = await client.GetUsers()
|
|
920
|
+
console.log(users)
|
|
921
|
+
} catch (error) {
|
|
922
|
+
console.error('GraphQL Error:', error)
|
|
923
|
+
// Handle GraphQL errors appropriately
|
|
924
|
+
}
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
</details>
|
|
928
|
+
|
|
929
|
+
<details>
|
|
930
|
+
<summary>🔧 <strong>Client Configuration</strong></summary>
|
|
931
|
+
|
|
932
|
+
```ts
|
|
933
|
+
import { createGraphQLClient } from '#graphql/client'
|
|
934
|
+
|
|
935
|
+
// Basic configuration
|
|
936
|
+
const client = createGraphQLClient({
|
|
937
|
+
endpoint: '/api/graphql',
|
|
938
|
+
headers: {
|
|
939
|
+
'Authorization': 'Bearer your-token',
|
|
940
|
+
'X-Client-Version': '1.0.0'
|
|
941
|
+
},
|
|
942
|
+
timeout: 10000
|
|
943
|
+
})
|
|
944
|
+
|
|
945
|
+
// Advanced configuration with dynamic headers
|
|
946
|
+
const client = createGraphQLClient({
|
|
947
|
+
endpoint: '/api/graphql',
|
|
948
|
+
headers: async () => {
|
|
949
|
+
const token = await getAuthToken()
|
|
950
|
+
return {
|
|
951
|
+
'Authorization': token ? `Bearer ${token}` : '',
|
|
952
|
+
'X-Request-ID': crypto.randomUUID()
|
|
953
|
+
}
|
|
954
|
+
},
|
|
955
|
+
retry: 3,
|
|
956
|
+
timeout: 30000
|
|
957
|
+
})
|
|
958
|
+
```
|
|
959
|
+
|
|
960
|
+
</details>
|
|
961
|
+
|
|
962
|
+
</details>
|
|
963
|
+
|
|
964
|
+
## 🛠️ Development
|
|
965
|
+
|
|
966
|
+
### Scripts
|
|
967
|
+
|
|
968
|
+
- `pnpm build` - Build the module
|
|
969
|
+
- `pnpm dev` - Watch mode with automatic rebuilding
|
|
970
|
+
- `pnpm lint` - ESLint with auto-fix
|
|
971
|
+
- `pnpm playground` - Run the Nitro playground example
|
|
972
|
+
- `pnpm release` - Build, version bump, and publish
|
|
973
|
+
|
|
974
|
+
### Requirements
|
|
975
|
+
|
|
976
|
+
- Node.js 20.x or later
|
|
977
|
+
- pnpm (required package manager)
|
|
978
|
+
|
|
979
|
+
## 💬 Community & Contributing
|
|
410
980
|
|
|
411
981
|
> [!TIP]
|
|
412
982
|
> **Want to contribute?** We believe you can play a role in the growth of this project!
|
|
@@ -442,6 +1012,26 @@ The module is optimized for minimal bundle size:
|
|
|
442
1012
|
|
|
443
1013
|
Thank you for using and developing this project. Every contribution makes the GraphQL ecosystem stronger!
|
|
444
1014
|
|
|
1015
|
+
## Sponsors
|
|
1016
|
+
|
|
1017
|
+
<p align="center">
|
|
1018
|
+
<a href="https://cdn.jsdelivr.net/gh/productdevbook/static/sponsors.svg">
|
|
1019
|
+
<img src='https://cdn.jsdelivr.net/gh/productdevbook/static/sponsors.svg?t=1721043966'/>
|
|
1020
|
+
</a>
|
|
1021
|
+
</p>
|
|
1022
|
+
|
|
445
1023
|
## License
|
|
446
1024
|
|
|
447
|
-
MIT
|
|
1025
|
+
[MIT](./LICENSE) License © 2023 [productdevbook](https://github.com/productdevbook)
|
|
1026
|
+
|
|
1027
|
+
<!-- Badges -->
|
|
1028
|
+
|
|
1029
|
+
[npm-version-src]: https://img.shields.io/npm/v/nitro-graphql?style=flat&colorA=080f12&colorB=1fa669
|
|
1030
|
+
[npm-version-href]: https://npmjs.com/package/nitro-graphql
|
|
1031
|
+
[npm-downloads-src]: https://img.shields.io/npm/dm/nitro-graphql?style=flat&colorA=080f12&colorB=1fa669
|
|
1032
|
+
[npm-downloads-href]: https://npmjs.com/package/nitro-graphql
|
|
1033
|
+
[bundle-src]: https://deno.bundlejs.com/badge?q=nitro-graphql@0.0.4
|
|
1034
|
+
[bundle-href]: https://deno.bundlejs.com/badge?q=nitro-graphql@0.0.4
|
|
1035
|
+
[license-src]: https://img.shields.io/github/license/productdevbook/nitro-graphql.svg?style=flat&colorA=080f12&colorB=1fa669
|
|
1036
|
+
[license-href]: https://github.com/productdevbook/nitro-graphql/blob/main/LICENSE
|
|
1037
|
+
[jsdocs-href]: https://www.jsdocs.io/package/nitro-graphql
|
package/dist/ecosystem/nuxt.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as _nuxt_schema0 from "@nuxt/schema";
|
|
2
2
|
|
|
3
3
|
//#region src/ecosystem/nuxt.d.ts
|
|
4
4
|
interface ModuleOptions {}
|
|
5
|
-
declare const _default:
|
|
5
|
+
declare const _default: _nuxt_schema0.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { ModuleOptions, _default as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { StandardSchemaV1 } from "./types/standard-schema.js";
|
|
2
2
|
import { CodegenClientConfig, CodegenServerConfig, GenImport, NitroGraphQLOptions } from "./types/index.js";
|
|
3
|
-
import * as
|
|
3
|
+
import * as nitropack3 from "nitropack";
|
|
4
4
|
|
|
5
5
|
//#region src/index.d.ts
|
|
6
6
|
type GraphQLFramework = 'graphql-yoga';
|
|
7
|
-
declare const _default:
|
|
7
|
+
declare const _default: nitropack3.NitroModule;
|
|
8
8
|
//#endregion
|
|
9
9
|
export { CodegenClientConfig, CodegenServerConfig, GenImport, GraphQLFramework, NitroGraphQLOptions, StandardSchemaV1, _default as default };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as h36 from "h3";
|
|
2
2
|
|
|
3
3
|
//#region src/routes/apollo-server.d.ts
|
|
4
|
-
declare const _default:
|
|
4
|
+
declare const _default: h36.EventHandler<h36.EventHandlerRequest, any>;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { _default as default };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as h31 from "h3";
|
|
2
2
|
|
|
3
3
|
//#region src/routes/graphql-yoga.d.ts
|
|
4
|
-
declare const _default:
|
|
4
|
+
declare const _default: h31.EventHandler<h31.EventHandlerRequest, Promise<Response>>;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { _default as default };
|
package/dist/routes/health.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as h34 from "h3";
|
|
2
2
|
|
|
3
3
|
//#region src/routes/health.d.ts
|
|
4
|
-
declare const _default:
|
|
4
|
+
declare const _default: h34.EventHandler<h34.EventHandlerRequest, Promise<{
|
|
5
5
|
status: string;
|
|
6
6
|
message: string;
|
|
7
7
|
timestamp: string;
|