@lewebsimple/nuxt-graphql 0.4.0 → 0.5.1
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 +130 -188
- package/dist/module.d.mts +71 -22
- package/dist/module.json +2 -2
- package/dist/module.mjs +406 -369
- package/dist/runtime/app/composables/useAsyncGraphQLQuery.d.ts +19 -0
- package/dist/runtime/app/composables/useAsyncGraphQLQuery.js +82 -0
- package/dist/runtime/app/composables/useGraphQLCache.client.d.ts +10 -7
- package/dist/runtime/app/composables/useGraphQLCache.client.js +16 -31
- package/dist/runtime/app/composables/useGraphQLMutation.d.ts +10 -18
- package/dist/runtime/app/composables/useGraphQLMutation.js +7 -11
- package/dist/runtime/app/composables/useGraphQLQuery.d.ts +11 -9
- package/dist/runtime/app/composables/useGraphQLQuery.js +20 -78
- package/dist/runtime/app/composables/useGraphQLSubscription.client.d.ts +19 -0
- package/dist/runtime/app/composables/{useGraphQLSubscription.js → useGraphQLSubscription.client.js} +9 -14
- package/dist/runtime/app/lib/cache.d.ts +18 -0
- package/dist/runtime/app/lib/cache.js +9 -0
- package/dist/runtime/app/lib/execute-http.d.ts +14 -0
- package/dist/runtime/app/lib/execute-http.js +8 -0
- package/dist/runtime/app/lib/in-flight.d.ts +14 -0
- package/dist/runtime/app/lib/{graphql-cache.js → in-flight.js} +2 -7
- package/dist/runtime/app/lib/persisted.d.ts +26 -0
- package/dist/runtime/app/plugins/graphql-request.d.ts +7 -2
- package/dist/runtime/app/plugins/graphql-request.js +13 -14
- package/dist/runtime/app/plugins/graphql-sse.client.d.ts +7 -2
- package/dist/runtime/server/api/graphql.d.ts +8 -0
- package/dist/runtime/server/api/graphql.js +16 -0
- package/dist/runtime/server/lib/default-context.d.ts +5 -0
- package/dist/runtime/server/lib/default-context.js +2 -0
- package/dist/runtime/server/lib/default-schema.d.ts +7 -0
- package/dist/runtime/server/lib/default-schema.js +18 -0
- package/dist/runtime/server/lib/execute-schema.d.ts +11 -0
- package/dist/runtime/server/lib/execute-schema.js +23 -0
- package/dist/runtime/server/lib/remote-executor.d.ts +17 -33
- package/dist/runtime/server/lib/remote-executor.js +24 -59
- package/dist/runtime/server/lib/yoga.d.ts +6 -0
- package/dist/runtime/server/lib/yoga.js +20 -0
- package/dist/runtime/server/utils/defineGraphQLContext.d.ts +10 -0
- package/dist/runtime/server/utils/defineGraphQLContext.js +3 -0
- package/dist/runtime/server/utils/defineGraphQLSchema.d.ts +14 -0
- package/dist/runtime/server/utils/defineGraphQLSchema.js +3 -0
- package/dist/runtime/server/utils/defineRemoteExecutorHooks.d.ts +13 -0
- package/dist/runtime/server/utils/defineRemoteExecutorHooks.js +3 -0
- package/dist/runtime/server/utils/useServerGraphQLMutation.d.ts +16 -8
- package/dist/runtime/server/utils/useServerGraphQLMutation.js +12 -11
- package/dist/runtime/server/utils/useServerGraphQLQuery.d.ts +16 -3
- package/dist/runtime/server/utils/useServerGraphQLQuery.js +16 -4
- package/dist/runtime/shared/lib/cache-config.d.ts +42 -0
- package/dist/runtime/{app → shared}/lib/cache-config.js +3 -3
- package/dist/runtime/shared/lib/error.d.ts +56 -0
- package/dist/runtime/shared/lib/error.js +61 -0
- package/dist/runtime/shared/lib/headers.d.ts +13 -3
- package/dist/runtime/shared/lib/headers.js +10 -35
- package/dist/runtime/shared/lib/registry.d.ts +12 -0
- package/dist/runtime/shared/lib/registry.js +8 -0
- package/dist/runtime/shared/lib/utils.d.ts +1 -0
- package/dist/runtime/shared/lib/utils.js +0 -0
- package/dist/runtime/{app → shared}/types/nuxt-graphql.d.ts +1 -5
- package/package.json +19 -33
- package/dist/helpers.d.mts +0 -3
- package/dist/helpers.mjs +0 -3
- package/dist/runtime/app/composables/useGraphQLSubscription.d.ts +0 -17
- package/dist/runtime/app/lib/cache-config.d.ts +0 -8
- package/dist/runtime/app/lib/graphql-cache.d.ts +0 -7
- package/dist/runtime/server/api/yoga-handler.d.ts +0 -2
- package/dist/runtime/server/api/yoga-handler.js +0 -42
- package/dist/runtime/server/lib/define-graphql-context.d.ts +0 -5
- package/dist/runtime/server/lib/define-graphql-context.js +0 -4
- package/dist/runtime/server/lib/define-remote-exec-middleware.d.ts +0 -30
- package/dist/runtime/server/lib/define-remote-exec-middleware.js +0 -3
- package/dist/runtime/server/lib/define-yoga-middleware.d.ts +0 -21
- package/dist/runtime/server/lib/define-yoga-middleware.js +0 -3
- package/dist/runtime/server/lib/execute-server-graphql.d.ts +0 -7
- package/dist/runtime/server/lib/execute-server-graphql.js +0 -34
- package/dist/runtime/shared/lib/graphql-error.d.ts +0 -17
- package/dist/runtime/shared/lib/graphql-error.js +0 -28
package/README.md
CHANGED
|
@@ -13,12 +13,12 @@ Opinionated Nuxt module that wires a typed GraphQL server + client into your app
|
|
|
13
13
|
## Features
|
|
14
14
|
|
|
15
15
|
- 🧘 **GraphQL Yoga** server at `/api/graphql` (**GraphiQL** in dev) + **SSE subscriptions**
|
|
16
|
-
- 🪡 **Stitched schema** from local and/or remote schemas (remote introspection at build time)
|
|
17
|
-
- 🪄 Code generation from `.gql` documents → **typed documents
|
|
18
|
-
- 🧠 **Type-safe
|
|
19
|
-
- 🧊 **SSR-friendly** by default: request header
|
|
20
|
-
- 🚀 **
|
|
21
|
-
-
|
|
16
|
+
- 🪡 **Stitched schema** from local and/or remote schemas (remote introspection at build time; subscriptions stripped)
|
|
17
|
+
- 🪄 Code generation from `.gql` documents → **typed operation documents** + **registry**
|
|
18
|
+
- 🧠 **Type-safe helpers** for **queries, mutations, and subscriptions**, shared across **client + server**
|
|
19
|
+
- 🧊 **SSR-friendly** by default: request header forwarding + server-side schema execution helpers
|
|
20
|
+
- 🚀 **Client-side cache** for `useAsyncGraphQLQuery` (cache policies + optional persistence in localStorage)
|
|
21
|
+
- 🧯 **Unified error model** via `SafeResult` and `NormalizedError`
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
## Getting started
|
|
@@ -26,80 +26,82 @@ Opinionated Nuxt module that wires a typed GraphQL server + client into your app
|
|
|
26
26
|
Install the module to your Nuxt application with one command:
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
pnpx
|
|
29
|
+
pnpx nuxt module add @lewebsimple/nuxt-graphql
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
### Configuration
|
|
34
34
|
|
|
35
|
-
Declare your schemas, context, documents glob and
|
|
35
|
+
Declare your schemas, context, documents glob and optional client cache in [nuxt.config.ts](nuxt.config.ts):
|
|
36
36
|
|
|
37
37
|
```ts
|
|
38
38
|
export default defineNuxtConfig({
|
|
39
39
|
modules: ["@lewebsimple/nuxt-graphql"],
|
|
40
40
|
graphql: {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
41
|
+
yoga: {
|
|
42
|
+
// Schemas to stitch together (local and/or remote)
|
|
43
|
+
schemas: {
|
|
44
|
+
local: {
|
|
45
|
+
type: "local",
|
|
46
|
+
path: "server/graphql/schema.ts",
|
|
47
|
+
},
|
|
48
|
+
// Remote schema example
|
|
49
|
+
swapi: {
|
|
50
|
+
type: "remote",
|
|
51
|
+
url: "https://swapi-graphql.netlify.app/graphql",
|
|
52
|
+
// Optional: static headers for this remote
|
|
53
|
+
headers: {
|
|
54
|
+
"X-Static-Header": "static-header-value",
|
|
55
|
+
},
|
|
56
|
+
// Optional: per-remote execution hooks
|
|
57
|
+
hooks: ["server/graphql/swapi-hooks.ts"],
|
|
54
58
|
},
|
|
55
|
-
// Optional: per-remote execution middleware (onRequest / onResponse / onError hooks)
|
|
56
|
-
middleware: "server/graphql/swapi-middleware.ts",
|
|
57
59
|
},
|
|
60
|
+
|
|
61
|
+
// Optional: custom GraphQL context factories (defaults to [])
|
|
62
|
+
context: ["server/graphql/context.ts"],
|
|
58
63
|
},
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
// Persist cache entries in localStorage with TTL in seconds
|
|
78
|
-
// - 0 = never expires
|
|
79
|
-
// - undefined = persistence disabled
|
|
80
|
-
ttl: 60,
|
|
64
|
+
|
|
65
|
+
client: {
|
|
66
|
+
// Optional: documents glob (defaults to **/*.gql)
|
|
67
|
+
documents: "**/*.gql",
|
|
68
|
+
|
|
69
|
+
// Optional: headers forwarded from SSR to graphql-request (defaults to ["authorization", "cookie"])
|
|
70
|
+
ssrForwardHeaders: ["authorization", "cookie"],
|
|
71
|
+
|
|
72
|
+
// Optional: query caching (client-side only, for useAsyncGraphQLQuery)
|
|
73
|
+
cache: {
|
|
74
|
+
policy: "cache-first", // "no-cache" | "cache-first" | "network-first" | "swr"
|
|
75
|
+
keyVersion: "1",
|
|
76
|
+
keyPrefix: "gql",
|
|
77
|
+
// Persist cache entries in localStorage with TTL in seconds
|
|
78
|
+
// - 0 = never expires
|
|
79
|
+
// - undefined = persistence disabled
|
|
80
|
+
ttl: 60,
|
|
81
|
+
},
|
|
81
82
|
},
|
|
82
83
|
|
|
83
|
-
// Optional: save path for the
|
|
84
|
-
|
|
84
|
+
// Optional: save path for the stitched SDL (defaults to "server/graphql/schema.graphql")
|
|
85
|
+
saveSDL: "server/graphql/schema.graphql",
|
|
86
|
+
|
|
87
|
+
// Optional: save path for the generated GraphQL config (defaults to "graphql.config.json")
|
|
88
|
+
saveConfig: "graphql.config.json",
|
|
85
89
|
},
|
|
86
90
|
});
|
|
87
91
|
```
|
|
88
92
|
|
|
89
93
|
|
|
90
|
-
### Define
|
|
94
|
+
### Define schema(s) (local and/or remote)
|
|
91
95
|
|
|
92
|
-
**Local schemas** must
|
|
96
|
+
**Local schemas** must live under `server/` and export a `GraphQLSchema` as `schema`. You can use the auto-imported `defineGraphQLSchema` helper for type-safety.
|
|
93
97
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
For the example configuration above, create `server/graphql/schema.ts`:
|
|
98
|
+
For the example configuration above, create [server/graphql/schema.ts](server/graphql/schema.ts):
|
|
97
99
|
|
|
98
100
|
```ts
|
|
99
101
|
import { createSchema } from "graphql-yoga";
|
|
100
102
|
import type { GraphQLContext } from "#graphql/context";
|
|
101
103
|
|
|
102
|
-
|
|
104
|
+
const schema = createSchema<GraphQLContext>({
|
|
103
105
|
typeDefs: /* GraphQL */ `
|
|
104
106
|
type Query {
|
|
105
107
|
hello: String!
|
|
@@ -130,19 +132,20 @@ export const schema = createSchema<GraphQLContext>({
|
|
|
130
132
|
},
|
|
131
133
|
},
|
|
132
134
|
});
|
|
135
|
+
|
|
136
|
+
export default defineGraphQLSchema({ schema });
|
|
133
137
|
```
|
|
134
138
|
|
|
135
|
-
**Remote schemas** are introspected at build time from the required endpoint URL
|
|
139
|
+
**Remote schemas** are introspected at build time from the required endpoint URL and executed via an HTTP executor at runtime. Subscriptions are stripped from remote schemas.
|
|
136
140
|
|
|
137
141
|
|
|
138
|
-
### Define
|
|
142
|
+
### Define GraphQL context factories (optional)
|
|
139
143
|
|
|
140
|
-
|
|
144
|
+
Context factories are optional and run on the server in order. Their return types are merged into a single `GraphQLContext` type. You can use the auto-imported `defineGraphQLContext` helper for type-safety.
|
|
141
145
|
|
|
142
|
-
For example,
|
|
146
|
+
For example, create [server/graphql/context.ts](server/graphql/context.ts):
|
|
143
147
|
|
|
144
148
|
```ts
|
|
145
|
-
import { defineGraphQLContext } from "@lewebsimple/nuxt-graphql/helpers";
|
|
146
149
|
import { getUserSession } from "nuxt-auth-utils";
|
|
147
150
|
|
|
148
151
|
export default defineGraphQLContext(async (event) => {
|
|
@@ -154,19 +157,20 @@ export default defineGraphQLContext(async (event) => {
|
|
|
154
157
|
```
|
|
155
158
|
|
|
156
159
|
|
|
157
|
-
### Write GraphQL documents (
|
|
160
|
+
### Write GraphQL documents (.gql)
|
|
158
161
|
|
|
159
|
-
Write operations in `.gql`
|
|
162
|
+
Write operations in `.gql` files; operation names become registry keys like `useGraphQLQuery("HelloWorld")`.
|
|
160
163
|
|
|
161
164
|
⚠️ Operation names are required and must be unique.
|
|
162
165
|
|
|
163
166
|
By default, the module scans `**/*.gql` and generates:
|
|
164
167
|
|
|
165
|
-
- Typed documents in `#graphql/
|
|
166
|
-
- Operation registry
|
|
167
|
-
-
|
|
168
|
+
- Typed documents and types in virtual modules under the `#graphql/operations` alias (internal)
|
|
169
|
+
- Operation registry in virtual modules under the `#graphql/registry` alias (internal)
|
|
170
|
+
- Fragment types in virtual modules under the `#graphql/fragments` alias
|
|
171
|
+
|
|
172
|
+
Example document files:
|
|
168
173
|
|
|
169
|
-
Example document files (filenaming convention can vary):
|
|
170
174
|
```graphql
|
|
171
175
|
# app/graphql/HelloWorld.query.gql
|
|
172
176
|
query HelloWorld {
|
|
@@ -190,15 +194,14 @@ subscription Time {
|
|
|
190
194
|
|
|
191
195
|
That's it! You can now use Nuxt GraphQL in your Nuxt app ✨
|
|
192
196
|
|
|
197
|
+
|
|
193
198
|
### Fragments
|
|
194
199
|
|
|
195
200
|
Fragments are fully supported and are the recommended way to share selection sets across operations.
|
|
196
201
|
|
|
197
202
|
- Fragment names must be unique across all `.gql` files (duplicates throw during generation).
|
|
198
|
-
-
|
|
199
|
-
|
|
200
|
-
- and a document constant like `TheFilmFragmentDoc`
|
|
201
|
-
- Fragments are **not executable by themselves** (GraphQL requires an operation), and they are **not part of the `#graphql/registry`**. The auto-imported composables and server utilities only accept operation names (`query` / `mutation` / `subscription`).
|
|
203
|
+
- Fragment types are re-exported from `#graphql/fragments`.
|
|
204
|
+
- Fragments are not executable by themselves and are not part of the registry.
|
|
202
205
|
|
|
203
206
|
Example with a fragment:
|
|
204
207
|
|
|
@@ -218,108 +221,92 @@ query SwapiFilms {
|
|
|
218
221
|
}
|
|
219
222
|
```
|
|
220
223
|
|
|
221
|
-
From TypeScript, you can also use fragment types explicitly when
|
|
224
|
+
From TypeScript, you can also use fragment types explicitly when needed:
|
|
222
225
|
|
|
223
226
|
```ts
|
|
224
|
-
import type { TheFilmFragment } from "#graphql/
|
|
227
|
+
import type { TheFilmFragment } from "#graphql/fragments";
|
|
225
228
|
```
|
|
226
229
|
|
|
227
230
|
|
|
228
231
|
### Use the auto-imported composables
|
|
229
232
|
|
|
230
|
-
The auto-imported
|
|
233
|
+
The auto-imported composables allow executing queries, mutations, and subscriptions based on their registry name with full type-safety (variables and return value).
|
|
231
234
|
|
|
232
235
|
```ts
|
|
233
|
-
//
|
|
234
|
-
const { data, pending, error, refresh } = await
|
|
235
|
-
"HelloWorld",
|
|
236
|
-
undefined,
|
|
236
|
+
// Cached query via useAsyncData
|
|
237
|
+
const { data, pending, error, refresh } = await useAsyncGraphQLQuery(
|
|
238
|
+
"HelloWorld",
|
|
239
|
+
undefined,
|
|
237
240
|
{
|
|
238
|
-
// Custom request headers
|
|
239
241
|
headers: {
|
|
240
|
-
"X-Request-Header": "request-header-value"
|
|
242
|
+
"X-Request-Header": "request-header-value",
|
|
241
243
|
},
|
|
242
|
-
// Additional useAsyncData options
|
|
243
|
-
// lazy: true,
|
|
244
244
|
},
|
|
245
245
|
);
|
|
246
246
|
|
|
247
|
-
//
|
|
248
|
-
const {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
},
|
|
253
|
-
});
|
|
254
|
-
const { data, pending, error } = await mutate({ message: "Hello from ping mutation!" }, {
|
|
255
|
-
// Each `mutate` call may send additional headers
|
|
247
|
+
// Direct HTTP query (SafeResult)
|
|
248
|
+
const { data: queryData, error: queryError } = await useGraphQLQuery("HelloWorld");
|
|
249
|
+
|
|
250
|
+
// Mutation (SafeResult)
|
|
251
|
+
const { mutate, pending: mutationPending } = useGraphQLMutation("Ping", {
|
|
256
252
|
headers: {
|
|
257
|
-
"X-
|
|
253
|
+
"X-Request-Header": "request-header-value",
|
|
258
254
|
},
|
|
259
255
|
});
|
|
256
|
+
const { data: mutationData, error: mutationError } = await mutate({ message: "Hello!" });
|
|
260
257
|
|
|
261
258
|
// Subscription (client-only, SSE)
|
|
262
259
|
const { data, error, start, stop } = useGraphQLSubscription("Time");
|
|
263
|
-
// data and error are shallowRef
|
|
264
260
|
```
|
|
265
261
|
|
|
262
|
+
|
|
266
263
|
### Use the auto-imported server-side utilities
|
|
267
264
|
|
|
268
|
-
In server routes, you can execute
|
|
265
|
+
In server routes, you can execute queries and mutations directly against the stitched schema (no HTTP roundtrip):
|
|
269
266
|
|
|
270
267
|
```ts
|
|
271
268
|
export default defineEventHandler(async (event) => {
|
|
272
269
|
// Server-side GraphQL query example
|
|
273
|
-
const {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
});
|
|
270
|
+
const { data: queryData, error: queryError } = await useServerGraphQLQuery(
|
|
271
|
+
event,
|
|
272
|
+
"HelloWorld",
|
|
273
|
+
);
|
|
278
274
|
|
|
279
275
|
// Server-side GraphQL mutation example
|
|
280
|
-
const {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
},
|
|
284
|
-
|
|
285
|
-
const { ping } = await mutate({ message: hello }, {
|
|
286
|
-
headers: {
|
|
287
|
-
"X-Mutation-Header": "mutation-header-value",
|
|
288
|
-
},
|
|
289
|
-
});
|
|
276
|
+
const { data: mutationData } = await useServerGraphQLMutation(
|
|
277
|
+
event,
|
|
278
|
+
"Ping",
|
|
279
|
+
{ message: queryData?.hello ?? "fallback" },
|
|
280
|
+
);
|
|
290
281
|
|
|
291
|
-
return {
|
|
282
|
+
return { queryData, mutationData, queryError };
|
|
292
283
|
});
|
|
293
284
|
```
|
|
294
285
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
Also, resulting data is returned directly from `useServerGraphQLQuery` and `mutate` (throws an error on failure).
|
|
286
|
+
Server helpers return a `SafeResult` in the same format as the client helpers.
|
|
298
287
|
|
|
299
288
|
|
|
300
289
|
### Query caching (client-side only)
|
|
301
290
|
|
|
302
|
-
`
|
|
291
|
+
`useAsyncGraphQLQuery` can cache query results based on the global cache configuration and per-query overrides.
|
|
303
292
|
|
|
304
|
-
- In-flight requests are
|
|
305
|
-
-
|
|
306
|
-
-
|
|
293
|
+
- In-flight requests are deduplicated (same operation + variables → one network call).
|
|
294
|
+
- In-memory cache uses Nuxt `useAsyncData`/`useNuxtData`.
|
|
295
|
+
- Persisted cache stores entries in localStorage for ttl seconds (0 = never expires).
|
|
307
296
|
|
|
308
297
|
#### Cache policies
|
|
309
298
|
|
|
310
|
-
-
|
|
311
|
-
-
|
|
312
|
-
-
|
|
313
|
-
-
|
|
299
|
+
- "no-cache": always fetches from the network (still dedupes in-flight).
|
|
300
|
+
- "cache-first": returns cached value when present, otherwise fetches.
|
|
301
|
+
- "network-first": tries the network first, falls back to cached value on error.
|
|
302
|
+
- "swr": returns cached value immediately and refreshes in the background.
|
|
314
303
|
|
|
315
304
|
#### Per-query overrides
|
|
316
305
|
|
|
317
|
-
Caching configuration can be overridden per-query:
|
|
318
|
-
|
|
319
306
|
```ts
|
|
320
|
-
const { data } = await
|
|
307
|
+
const { data } = await useAsyncGraphQLQuery("HelloWorld", undefined, {
|
|
321
308
|
cache: {
|
|
322
|
-
|
|
309
|
+
policy: "network-first",
|
|
323
310
|
ttl: undefined, // disable persistence for this call
|
|
324
311
|
},
|
|
325
312
|
});
|
|
@@ -327,92 +314,47 @@ const { data } = await useGraphQLQuery("HelloWorld", undefined, {
|
|
|
327
314
|
|
|
328
315
|
#### Manual invalidation
|
|
329
316
|
|
|
330
|
-
On the client, `useGraphQLCache()`
|
|
317
|
+
On the client, `useGraphQLCache()` can invalidate in-memory and persisted entries:
|
|
331
318
|
|
|
332
319
|
```ts
|
|
333
|
-
const {
|
|
320
|
+
const { invalidate } = useGraphQLCache();
|
|
334
321
|
|
|
335
322
|
// Invalidate a single entry (operation + variables)
|
|
336
|
-
await
|
|
323
|
+
await invalidate({ operation: "HelloWorld", variables: {} });
|
|
337
324
|
|
|
338
|
-
// Invalidate all entries for an operation
|
|
339
|
-
await
|
|
340
|
-
|
|
341
|
-
// Optional: target a specific layer
|
|
342
|
-
await invalidateByOperation("HelloWorld", { layer: "persisted" });
|
|
325
|
+
// Invalidate all entries for an operation
|
|
326
|
+
await invalidate({ operation: "HelloWorld" });
|
|
343
327
|
|
|
344
328
|
// Invalidate all entries
|
|
345
|
-
await
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
### Yoga middleware (optional)
|
|
350
|
-
|
|
351
|
-
You can define custom logic around the Yoga event handler by using the provided `defineYogaMiddleware` helper with the following hooks:
|
|
352
|
-
- `onRequest` runs before Yoga handles the request;
|
|
353
|
-
- `onResponse` runs after and can replace the outgoing `Response` via `setResponse`.
|
|
354
|
-
|
|
355
|
-
For the example configuration above, create `server/graphql/yoga-middleware.ts`:
|
|
356
|
-
|
|
357
|
-
```ts
|
|
358
|
-
import { defineYogaMiddleware } from "@lewebsimple/nuxt-graphql/helpers";
|
|
359
|
-
import { getUserSession } from "nuxt-auth-utils";
|
|
360
|
-
|
|
361
|
-
export default defineYogaMiddleware({
|
|
362
|
-
async onRequest({ event, context, request }) {
|
|
363
|
-
const session = await getUserSession(event);
|
|
364
|
-
if (!session?.user) {
|
|
365
|
-
throw createError({ statusCode: 401, message: "Unauthorized" });
|
|
366
|
-
}
|
|
367
|
-
},
|
|
368
|
-
async onResponse({ event, context, request, response, setResponse }) {
|
|
369
|
-
setHeader(event, "X-Custom-Yoga-Middleware-Response-Header", "my-custom-value");
|
|
370
|
-
},
|
|
371
|
-
});
|
|
329
|
+
await invalidate();
|
|
372
330
|
```
|
|
373
331
|
|
|
374
|
-
### Remote executor middleware (optional, per remote)
|
|
375
332
|
|
|
376
|
-
|
|
377
|
-
- `onRequest` runs before the fetch (headers are mutable);
|
|
378
|
-
- `onResponse` runs after an OK response before JSON parsing (cloned response);
|
|
379
|
-
- `onError` runs for non-2xx responses, GraphQL errors returned in the payload, JSON parse failures, or network errors (the `response` can be `undefined` in that last case).
|
|
333
|
+
### Remote executor hooks (optional, per remote)
|
|
380
334
|
|
|
381
|
-
|
|
335
|
+
You can define custom logic around the remote executor for each remote schema by using the auto-imported `defineRemoteExecutorHooks` helper.
|
|
382
336
|
|
|
383
|
-
For the example configuration above, create
|
|
337
|
+
For the example configuration above, create [server/graphql/swapi-hooks.ts](server/graphql/swapi-hooks.ts):
|
|
384
338
|
|
|
385
339
|
```ts
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
340
|
+
export default defineRemoteExecutorHooks({
|
|
341
|
+
onRequest(request) {
|
|
342
|
+
// Dynamically inject headers
|
|
343
|
+
request.extensions ??= {};
|
|
344
|
+
request.extensions.headers = {
|
|
345
|
+
...request.extensions.headers,
|
|
346
|
+
"X-Remote-Exec-Request-Header": "custom-value",
|
|
347
|
+
};
|
|
392
348
|
},
|
|
393
|
-
|
|
394
|
-
console.log(
|
|
349
|
+
onResult(result) {
|
|
350
|
+
console.log("Remote result", result);
|
|
395
351
|
},
|
|
396
|
-
onError(
|
|
397
|
-
console.error(
|
|
352
|
+
onError(error) {
|
|
353
|
+
console.error("Remote error", error);
|
|
398
354
|
},
|
|
399
355
|
});
|
|
400
356
|
```
|
|
401
357
|
|
|
402
|
-
### Client error hook (optional)
|
|
403
|
-
|
|
404
|
-
Handle normalized GraphQL errors globally on the client (toast, logging, etc.).
|
|
405
|
-
|
|
406
|
-
The client calls the `graphql:error` Nuxt hook when a `graphql-request` response contains errors:
|
|
407
|
-
|
|
408
|
-
```ts
|
|
409
|
-
export default defineNuxtPlugin((nuxtApp) => {
|
|
410
|
-
nuxtApp.hook("graphql:error", (error) => {
|
|
411
|
-
console.error("GraphQL error", error);
|
|
412
|
-
});
|
|
413
|
-
});
|
|
414
|
-
```
|
|
415
|
-
|
|
416
358
|
|
|
417
359
|
## Contribution
|
|
418
360
|
|
package/dist/module.d.mts
CHANGED
|
@@ -1,35 +1,84 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
-
import {
|
|
2
|
+
import { HeadersInput } from '../dist/runtime/shared/lib/headers.js';
|
|
3
|
+
import { CacheConfig } from '../dist/runtime/shared/lib/cache-config.js';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
* Find multiple files across directories
|
|
6
|
-
*
|
|
7
|
-
* @param dirs Directories to search in
|
|
8
|
-
* @param pattern Glob pattern relative to each directory
|
|
9
|
-
* @returns Array of found file paths
|
|
10
|
-
*/
|
|
11
|
-
type GlobPattern = string | string[];
|
|
12
|
-
|
|
13
|
-
type LocalSchemaDef = {
|
|
5
|
+
interface LocalSchemaDef {
|
|
14
6
|
type: "local";
|
|
7
|
+
/**
|
|
8
|
+
* Path to a server-side module exporting
|
|
9
|
+
* `export default defineLocalGraphQLSchema({ schema })`
|
|
10
|
+
* Resolved from rootDir.
|
|
11
|
+
*/
|
|
15
12
|
path: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
13
|
+
}
|
|
14
|
+
interface RemoteSchemaDef {
|
|
18
15
|
type: "remote";
|
|
16
|
+
/**
|
|
17
|
+
* Remote GraphQL endpoint.
|
|
18
|
+
* Used for build-time introspection and runtime delegation.
|
|
19
|
+
*/
|
|
19
20
|
url: string;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Static headers applied to all delegated requests.
|
|
23
|
+
* `null` unsets a header.
|
|
24
|
+
*/
|
|
25
|
+
headers?: HeadersInput;
|
|
26
|
+
/**
|
|
27
|
+
* Paths to remote execution hook modules.
|
|
28
|
+
* Resolved from rootDir.
|
|
29
|
+
*/
|
|
30
|
+
hooks?: string[];
|
|
31
|
+
}
|
|
23
32
|
type SchemaDef = LocalSchemaDef | RemoteSchemaDef;
|
|
24
33
|
|
|
25
34
|
interface NuxtGraphQLModuleOptions {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Client-side GraphQL configuration (HTTP + cache).
|
|
37
|
+
*/
|
|
38
|
+
client?: {
|
|
39
|
+
/**
|
|
40
|
+
* Global cache configuration for queries.
|
|
41
|
+
*/
|
|
42
|
+
cache?: Partial<CacheConfig>;
|
|
43
|
+
/**
|
|
44
|
+
* GraphQL documents glob pattern.
|
|
45
|
+
* Default: "**\/*.gql"
|
|
46
|
+
*/
|
|
47
|
+
documents?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Headers forwarded from the SSR request to graphql-request.
|
|
50
|
+
* Default: ["authorization", "cookie"]
|
|
51
|
+
*/
|
|
52
|
+
ssrForwardHeaders?: string[];
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Where to write graphql.config.json.
|
|
56
|
+
* Resolved from rootDir.
|
|
57
|
+
* Default: ./graphql.config.json
|
|
58
|
+
*/
|
|
29
59
|
saveConfig?: string;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Where to write the stitched GraphQL SDL.
|
|
62
|
+
* Resolved from rootDir.
|
|
63
|
+
* Default: server/graphql/schema.graphql
|
|
64
|
+
*/
|
|
65
|
+
saveSDL?: string;
|
|
66
|
+
/**
|
|
67
|
+
* Server-side GraphQL configuration (Yoga + execution).
|
|
68
|
+
*/
|
|
69
|
+
yoga?: {
|
|
70
|
+
/**
|
|
71
|
+
* Paths to GraphQL context factories.
|
|
72
|
+
* Must live in server/.
|
|
73
|
+
* Resolved from rootDir.
|
|
74
|
+
*/
|
|
75
|
+
context?: string[];
|
|
76
|
+
/**
|
|
77
|
+
* GraphQL schemas to stitch.
|
|
78
|
+
* Key = schemaName.
|
|
79
|
+
*/
|
|
80
|
+
schemas?: Record<string, SchemaDef>;
|
|
81
|
+
};
|
|
33
82
|
}
|
|
34
83
|
declare const _default: _nuxt_schema.NuxtModule<NuxtGraphQLModuleOptions, NuxtGraphQLModuleOptions, false>;
|
|
35
84
|
|