@lewebsimple/nuxt-graphql 0.5.13 → 0.6.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.
Files changed (53) hide show
  1. package/README.md +31 -57
  2. package/dist/module.d.mts +5 -38
  3. package/dist/module.json +2 -2
  4. package/dist/module.mjs +49 -155
  5. package/dist/runtime/app/composables/useAsyncGraphQLQuery.d.ts +7 -7
  6. package/dist/runtime/app/composables/useAsyncGraphQLQuery.js +12 -8
  7. package/dist/runtime/app/composables/useGraphQLCache.client.d.ts +9 -1
  8. package/dist/runtime/app/composables/useGraphQLCache.client.js +1 -1
  9. package/dist/runtime/app/composables/useGraphQLMutation.d.ts +3 -12
  10. package/dist/runtime/app/composables/useGraphQLMutation.js +11 -10
  11. package/dist/runtime/app/composables/useGraphQLQuery.d.ts +2 -11
  12. package/dist/runtime/app/composables/useGraphQLQuery.js +11 -21
  13. package/dist/runtime/app/composables/useGraphQLSubscription.client.d.ts +1 -1
  14. package/dist/runtime/app/composables/useGraphQLSubscription.client.js +1 -1
  15. package/dist/runtime/{shared → app}/lib/cache.d.ts +9 -3
  16. package/dist/runtime/{shared → app}/lib/cache.js +3 -3
  17. package/dist/runtime/app/plugins/execute-graphql.d.ts +25 -0
  18. package/dist/runtime/app/plugins/execute-graphql.js +25 -0
  19. package/dist/runtime/app/plugins/graphql-sse.client.d.ts +12 -2
  20. package/dist/runtime/server/api/graphql.d.ts +0 -6
  21. package/dist/runtime/server/api/graphql.js +4 -5
  22. package/dist/runtime/server/lib/execute-graphql-schema.d.ts +3 -0
  23. package/dist/runtime/server/lib/execute-graphql-schema.js +22 -0
  24. package/dist/runtime/server/lib/remote-executor.d.ts +22 -12
  25. package/dist/runtime/server/lib/remote-executor.js +17 -18
  26. package/dist/runtime/server/lib/yoga.d.ts +1 -2
  27. package/dist/runtime/server/lib/yoga.js +2 -4
  28. package/dist/runtime/server/tsconfig.json +2 -2
  29. package/dist/runtime/server/utils/defineRemoteExecutorHooks.d.ts +1 -6
  30. package/dist/runtime/server/utils/useGraphQLOperation.d.ts +16 -0
  31. package/dist/runtime/server/utils/useGraphQLOperation.js +12 -0
  32. package/dist/runtime/shared/lib/error.d.ts +7 -21
  33. package/dist/runtime/shared/lib/error.js +1 -18
  34. package/dist/runtime/shared/lib/headers.d.ts +2 -1
  35. package/dist/runtime/shared/lib/headers.js +1 -1
  36. package/dist/runtime/shared/lib/types.d.ts +16 -0
  37. package/dist/runtime/shared/utils/execute-graphql-http.d.ts +7 -0
  38. package/dist/runtime/shared/utils/execute-graphql-http.js +31 -0
  39. package/package.json +3 -9
  40. package/dist/runtime/app/lib/execute-http.d.ts +0 -13
  41. package/dist/runtime/app/lib/execute-http.js +0 -8
  42. package/dist/runtime/app/plugins/graphql-request.d.ts +0 -12
  43. package/dist/runtime/app/plugins/graphql-request.js +0 -20
  44. package/dist/runtime/server/lib/default-schema.d.ts +0 -4
  45. package/dist/runtime/server/lib/default-schema.js +0 -16
  46. package/dist/runtime/server/lib/execute-schema.d.ts +0 -11
  47. package/dist/runtime/server/lib/execute-schema.js +0 -23
  48. package/dist/runtime/server/utils/useServerGraphQLMutation.d.ts +0 -17
  49. package/dist/runtime/server/utils/useServerGraphQLMutation.js +0 -14
  50. package/dist/runtime/server/utils/useServerGraphQLQuery.d.ts +0 -17
  51. package/dist/runtime/server/utils/useServerGraphQLQuery.js +0 -14
  52. package/dist/runtime/shared/lib/utils.d.ts +0 -1
  53. /package/dist/runtime/shared/lib/{utils.js → types.js} +0 -0
package/README.md CHANGED
@@ -18,7 +18,7 @@ Opinionated Nuxt module that wires a typed GraphQL server + client into your app
18
18
  - 🧠 **Type-safe helpers** for **queries, mutations, and subscriptions**, shared across **client + server**
19
19
  - 🧊 **SSR-friendly** by default: request header forwarding + server-side schema execution helpers
20
20
  - 🚀 **Client-side cache** for `useAsyncGraphQLQuery` (cache policies + optional persistence in localStorage)
21
- - 🧯 **Unified error model** via `SafeResult` and `NormalizedError`
21
+ - 🧯 **Unified error model** via `GraphQLExecutionResult` and `NormalizedError`
22
22
 
23
23
 
24
24
  ## Getting started
@@ -38,13 +38,12 @@ Declare your schemas, context, documents glob and optional client cache in [nuxt
38
38
  export default defineNuxtConfig({
39
39
  modules: ["@lewebsimple/nuxt-graphql"],
40
40
  graphql: {
41
- yoga: {
41
+ server: {
42
42
  // Schemas to stitch together (local and/or remote)
43
- schemas: {
44
- local: {
45
- type: "local",
46
- path: "server/graphql/schema.ts",
47
- },
43
+ schema: {
44
+ // Local schema example
45
+ local: { type: "local", path: "server/graphql/schema.ts" },
46
+
48
47
  // Remote schema example
49
48
  swapi: {
50
49
  type: "remote",
@@ -91,7 +90,7 @@ export default defineNuxtConfig({
91
90
  ```
92
91
 
93
92
 
94
- ### Define schema(s) (local and/or remote)
93
+ ### Define GraphQL schema (local and/or remote)
95
94
 
96
95
  **Local schemas** must live under `server/` and export a `GraphQLSchema` as `schema`.
97
96
 
@@ -134,12 +133,14 @@ export const schema = createSchema<GraphQLContext>({
134
133
  });
135
134
  ```
136
135
 
137
- **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
+ **Remote schemas** are introspected at build time from the endpoint URL and executed via an HTTP executor at runtime. Subscriptions are stripped from remote schemas.
137
+
138
+ The final schema is stitched from the all of the defined local / remote schemas.
138
139
 
139
140
 
140
- ### Define GraphQL context factories (optional)
141
+ ### Define GraphQL context (optional)
141
142
 
142
- 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.
143
+ Context definition is optional and factories resolve in order on the server. Their return types are merged into a single `GraphQLContext` type which is exported from `#graphql/context`. You can use the auto-imported `defineGraphQLContext` helper for type-safety.
143
144
 
144
145
  For example, create [server/graphql/context.ts](server/graphql/context.ts):
145
146
 
@@ -157,15 +158,10 @@ export default defineGraphQLContext(async (event) => {
157
158
 
158
159
  ### Write GraphQL documents (.gql)
159
160
 
160
- Write operations in `.gql` files; operation names become registry keys like `useGraphQLQuery("HelloWorld")`.
161
+ By default, the module scans `**/*.gql` files for **named operations** and **fragments** which are converted into **types** and **typed document nodes** in `#graphql/operations`. The operations are exposed by name in `#graphql/registry` to allow type-safe execution with the provided **composables** and **server utils**.
161
162
 
162
163
  ⚠️ Operation names are required and must be unique.
163
164
 
164
- By default, the module scans `**/*.gql` and generates:
165
-
166
- - Typed documents and operations / fragments types in virtual modules under the `#graphql/operations` alias (internal)
167
- - Operation registry in virtual modules under the `#graphql/registry` alias (internal)
168
-
169
165
  Example document files:
170
166
 
171
167
  ```graphql
@@ -231,25 +227,13 @@ The auto-imported composables allow executing queries, mutations, and subscripti
231
227
 
232
228
  ```ts
233
229
  // Cached query via useAsyncData
234
- const { data, pending, error, refresh } = await useAsyncGraphQLQuery(
235
- "HelloWorld",
236
- undefined,
237
- {
238
- headers: {
239
- "X-Request-Header": "request-header-value",
240
- },
241
- },
242
- );
230
+ const { data, pending, error, refresh } = await useAsyncGraphQLQuery("HelloWorld", undefined);
243
231
 
244
232
  // Direct HTTP query (SafeResult)
245
233
  const { data: queryData, error: queryError } = await useGraphQLQuery("HelloWorld");
246
234
 
247
235
  // Mutation (SafeResult)
248
- const { mutate, pending: mutationPending } = useGraphQLMutation("Ping", {
249
- headers: {
250
- "X-Request-Header": "request-header-value",
251
- },
252
- });
236
+ const { mutate, pending: mutationPending } = useGraphQLMutation("Ping");
253
237
  const { data: mutationData, error: mutationError } = await mutate({ message: "Hello!" });
254
238
 
255
239
  // Subscription (client-only, SSE)
@@ -257,30 +241,24 @@ const { data, error, start, stop } = useGraphQLSubscription("Time");
257
241
  ```
258
242
 
259
243
 
260
- ### Use the auto-imported server-side utilities
244
+ ### Use the auto-imported server utils
261
245
 
262
246
  In server routes, you can execute queries and mutations directly against the stitched schema (no HTTP roundtrip):
263
247
 
264
248
  ```ts
265
249
  export default defineEventHandler(async (event) => {
266
250
  // Server-side GraphQL query example
267
- const { data: queryData, error: queryError } = await useServerGraphQLQuery(
268
- event,
269
- "HelloWorld",
270
- );
251
+ const { data: queryData, error: queryError } = await useGraphQLOperation(event, "HelloWorld" );
271
252
 
272
253
  // Server-side GraphQL mutation example
273
- const { data: mutationData } = await useServerGraphQLMutation(
274
- event,
275
- "Ping",
276
- { message: queryData?.hello ?? "fallback" },
254
+ const { data: mutationData } = await useGraphQLOperation(event, "Ping", { message: queryData?.hello ?? "Pong" },
277
255
  );
278
256
 
279
257
  return { queryData, mutationData, queryError };
280
258
  });
281
259
  ```
282
260
 
283
- Server helpers return a `SafeResult` in the same format as the client helpers.
261
+ Server helpers return a `GraphQLExecutionResult` in the same format as some composables, i.e. `{ data: TResult, error: null } | { data: null, error: NormalizedError }`
284
262
 
285
263
 
286
264
  ### Query caching (client-side only)
@@ -293,10 +271,10 @@ Server helpers return a `SafeResult` in the same format as the client helpers.
293
271
 
294
272
  #### Cache policies
295
273
 
296
- - "no-cache": always fetches from the network (still dedupes in-flight).
297
- - "cache-first": returns cached value when present, otherwise fetches.
298
- - "network-first": tries the network first, falls back to cached value on error.
299
- - "swr": returns cached value immediately and refreshes in the background.
274
+ - `"no-cache"`: always fetches from the network (still dedupes in-flight).
275
+ - `"cache-first"`: returns cached value when present, otherwise fetches.
276
+ - `"network-first"`: tries the network first, falls back to cached value on error.
277
+ - `"swr"`: returns cached value immediately and refreshes in the background.
300
278
 
301
279
  #### Per-query overrides
302
280
 
@@ -334,20 +312,16 @@ You can define custom logic around the remote executor for each remote schema by
334
312
  For the example configuration above, create [server/graphql/swapi-hooks.ts](server/graphql/swapi-hooks.ts):
335
313
 
336
314
  ```ts
315
+ import { defu } from "defu";
316
+
337
317
  export default defineRemoteExecutorHooks({
338
318
  onRequest(request) {
339
- // Dynamically inject headers
340
- request.extensions ??= {};
341
- request.extensions.headers = {
342
- ...request.extensions.headers,
343
- "X-Remote-Exec-Request-Header": "custom-value",
344
- };
345
- },
346
- onResult(result) {
347
- console.log("Remote result", result);
348
- },
349
- onError(error) {
350
- console.error("Remote error", error);
319
+ const { remoteAuthToken } = request.context || {};
320
+ request.extensions = defu(request.extensions, {
321
+ headers: {
322
+ "XAuthorization": `Bearer ${remoteAuthToken || ""}`,
323
+ },
324
+ });
351
325
  },
352
326
  });
353
327
  ```
package/dist/module.d.mts CHANGED
@@ -1,4 +1,6 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
+ import { HeadersInput } from '../dist/runtime/shared/lib/headers.js';
3
+ import { CacheConfig } from '../dist/runtime/app/lib/cache.js';
2
4
 
3
5
  type LocalSchemaDef = {
4
6
  type: "local";
@@ -13,52 +15,17 @@ type RemoteSchemaDef = {
13
15
  type SchemaDef = LocalSchemaDef | RemoteSchemaDef;
14
16
 
15
17
  interface NuxtGraphQLModuleOptions {
16
- /**
17
- * Client-side GraphQL configuration (HTTP + cache).
18
- */
19
18
  client?: {
20
- /**
21
- * Global cache configuration for queries.
22
- */
23
- cache?: Partial<GraphQLCacheConfig>;
24
- /**
25
- * GraphQL documents glob pattern.
26
- * Default: "**\/*.gql"
27
- */
28
19
  documents?: string;
29
- /**
30
- * Headers forwarded from the SSR request to graphql-request.
31
- * Default: ["authorization", "cookie"]
32
- */
20
+ cache?: Partial<CacheConfig>;
33
21
  ssrForwardHeaders?: string[];
34
22
  };
35
- /**
36
- * Where to write graphql.config.json.
37
- * Resolved from rootDir.
38
- * Default: ./graphql.config.json
39
- */
40
- saveConfig?: string;
41
- /**
42
- * Where to write the stitched GraphQL SDL.
43
- * Resolved from rootDir.
44
- * Default: server/graphql/schema.graphql
45
- */
46
- saveSDL?: string;
47
- /**
48
- * Server-side GraphQL configuration (Yoga server + execution).
49
- */
50
23
  server?: {
51
- /**
52
- * Paths to GraphQL server context factories relative to rootDir.
53
- * export default defineGraphQLContext((event: H3Event) => Promise<Record<string, unknown>>)
54
- */
55
24
  context?: string[];
56
- /**
57
- * GraphQL schema definition.
58
- * Key = schemaName.
59
- */
60
25
  schema?: Record<string, SchemaDef>;
61
26
  };
27
+ saveConfig?: string;
28
+ saveSDL?: string;
62
29
  }
63
30
  declare const _default: _nuxt_schema.NuxtModule<NuxtGraphQLModuleOptions, NuxtGraphQLModuleOptions, false>;
64
31
 
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
- "name": "nuxt-graphql",
2
+ "name": "@lewebsimple/nuxt-graphql",
3
3
  "configKey": "graphql",
4
- "version": "0.5.13",
4
+ "version": "0.6.1",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -2,17 +2,17 @@ import { mkdirSync, writeFileSync } from 'node:fs';
2
2
  import { relative, resolve, dirname } from 'node:path';
3
3
  import { defu } from 'defu';
4
4
  import { stitchSchemas } from '@graphql-tools/stitch';
5
- import { defineNuxtModule, useLogger, createResolver, addTemplate, addServerTemplate, addTypeTemplate, addServerHandler, addPlugin, addImportsDir, addServerImportsDir } from '@nuxt/kit';
5
+ import { addTemplate, addServerTemplate, defineNuxtModule, useLogger, createResolver, addServerHandler, addPlugin, addImportsDir, addServerImportsDir } from '@nuxt/kit';
6
6
  import { hash } from 'ohash';
7
7
  import { createRequire } from 'node:module';
8
8
  import { printSchema, lexicographicSortSchema, buildSchema, getIntrospectionQuery, buildClientSchema, GraphQLSchema, Kind } from 'graphql';
9
- import { resolveCacheConfig } from '../dist/runtime/shared/lib/cache.js';
10
9
  import { loadDocuments } from '@graphql-tools/load';
11
10
  import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
12
11
  import { codegen } from '@graphql-codegen/core';
13
12
  import * as typescriptPlugin from '@graphql-codegen/typescript';
14
13
  import * as typescriptOperationsPlugin from '@graphql-codegen/typescript-operations';
15
14
  import * as typedDocumentNodePlugin from '@graphql-codegen/typed-document-node';
15
+ import { resolveCacheConfig } from '../dist/runtime/app/lib/cache.js';
16
16
 
17
17
  const buildCache = /* @__PURE__ */ new Map();
18
18
  function getCachedLoader(baseKey, loader) {
@@ -118,9 +118,7 @@ ${localImports.join("\n")}
118
118
  ${remoteImports.join("\n")}
119
119
 
120
120
  export const schema = stitchSchemas({
121
- subschemas: [
122
- ${[mergedSchema, ...remoteSchemas].join(",\n ")}
123
- ],
121
+ subschemas: [${[mergedSchema, ...remoteSchemas].join(", ")}],
124
122
  });
125
123
  `.trim();
126
124
  return { ts, ...splitModule(ts) };
@@ -134,24 +132,18 @@ async function loadLocalSchema({ importPath }) {
134
132
  }
135
133
  return module.schema;
136
134
  }
137
- function getSchemaSDL(schema) {
138
- return printSchema(lexicographicSortSchema(schema));
139
- }
140
- function getDefaultSchema() {
141
- return buildSchema(`type Query { _empty: String }`);
142
- }
143
-
144
135
  async function getRemoteSchemaTemplate({ endpoint, headers, hooks, loadSchema }) {
145
136
  const hooksImports = hooks.map((hook, index) => `import hook${index} from ${JSON.stringify(hook.importPath)};`);
146
137
  const hooksArray = hooks.map((_, index) => `hook${index}`);
147
138
  const schema = await loadSchema();
148
139
  const sdl = getSchemaSDL(schema);
149
140
  const ts = `
141
+ import type { GraphQLSchema } from "graphql";
150
142
  import { buildSchema } from "graphql";
151
- import { createRemoteExecutor } from "#graphql/runtime/remote-executor";
143
+ import { getRemoteExecutor } from "#graphql/runtime/remote-executor";
152
144
  ${hooksImports.join("\n")}
153
145
 
154
- const executor = createRemoteExecutor({
146
+ const executor = getRemoteExecutor({
155
147
  endpoint: "${endpoint}",
156
148
  headers: ${JSON.stringify(headers)},
157
149
  hooks: [${hooksArray.join(", ")}],
@@ -163,7 +155,7 @@ const sdl = \`${sdl.replace(/`/g, "\\`")}\`;
163
155
  export const schema = {
164
156
  schema: buildSchema(sdl),
165
157
  executor,
166
- }
158
+ } as unknown as GraphQLSchema;
167
159
  `.trim();
168
160
  return { ts, ...splitModule(ts) };
169
161
  }
@@ -192,83 +184,26 @@ function stripSubscriptions(schema) {
192
184
  directives: schema.getDirectives()
193
185
  });
194
186
  }
195
-
196
- function getAppTypesTemplate() {
197
- return `
198
- import type { GraphQLClient } from "graphql-request";
199
- import type { Client as SSEClient } from "graphql-sse";
200
-
201
- declare module "#app/nuxt" {
202
- interface NuxtApp {
203
- $getGraphQLClient: () => GraphQLClient;
204
- $getGraphQLSSEClient: () => SSEClient;
205
- }
206
- }
207
-
208
- declare module "#app" {
209
- interface NuxtApp {
210
- $getGraphQLClient: () => GraphQLClient;
211
- $getGraphQLSSEClient: () => SSEClient;
212
- }
213
- }
214
-
215
- export {};
216
- `.trim();
217
- }
218
- function getServerTypesTemplate() {
219
- return `
220
- import type { ExecutionRequest, ExecutionResult } from "@graphql-tools/utils";
221
-
222
- declare module "h3" {
223
- interface H3EventContext {
224
- _graphqlInFlightRequestsMap?: Map<string, Promise<unknown>>;
225
- }
226
- }
227
-
228
- declare module "#graphql/runtime/remote-executor" {
229
- export type CreateRemoteExecutorInput = {
230
- endpoint: string;
231
- headers: HeadersInput;
232
- hooks: GraphQLRemoteExecHooks[];
233
- };
234
-
235
- export function createRemoteExecutor(options: {
236
- endpoint: string;
237
- headers: Record<string, string>;
238
- hooks: GraphQLRemoteExecHooks[];
239
- }): Executor;
240
- }
241
-
242
- export {};
243
- `.trim();
187
+ function getSchemaSDL(schema) {
188
+ return printSchema(lexicographicSortSchema(schema));
244
189
  }
245
- function getSharedTypesTemplate() {
246
- return `
247
- import type { DocumentNode } from "graphql";
248
-
249
- declare global {
250
- type GraphQLCacheConfig = {
251
- policy: "no-cache" | "cache-first" | "network-first" | "swr";
252
- ttl?: number;
253
- keyPrefix: string;
254
- keyVersion: string | number;
255
- };
256
-
257
- export type HeadersInput = Record<string, string | null>;
190
+ function getDefaultSchema() {
191
+ return buildSchema(`type Query { _empty: String }`);
258
192
  }
259
193
 
260
- declare module "nuxt/schema" {
261
- interface PublicRuntimeConfig {
262
- graphql: {
263
- cacheConfig: GraphQLCacheConfig;
264
- ssrForwardHeaders: string[];
265
- };
194
+ function addUniversalTemplate({ filename, getContents, emitTs }) {
195
+ let modulePath;
196
+ if (emitTs) {
197
+ modulePath = addTemplate({ filename: `${filename}.ts`, getContents: async () => (await getContents()).ts, write: true }).dst;
198
+ } else {
199
+ modulePath = addTemplate({ filename: `${filename}.mjs`, getContents: async () => (await getContents()).mjs, write: true }).dst;
200
+ addTemplate({ filename: `${filename}.d.ts`, getContents: async () => (await getContents()).dts });
266
201
  }
202
+ addServerTemplate({ filename: `${filename}.mjs`, getContents: async () => (await getContents()).mjs });
203
+ return modulePath;
267
204
  }
268
205
 
269
- export { };
270
- `.trim();
271
- }
206
+ const version = "0.6.1";
272
207
 
273
208
  async function getDocuments(documentsGlob) {
274
209
  try {
@@ -406,12 +341,13 @@ function collectOperations(documents) {
406
341
 
407
342
  const module$1 = defineNuxtModule({
408
343
  meta: {
409
- name: "nuxt-graphql",
344
+ name: "@lewebsimple/nuxt-graphql",
410
345
  configKey: "graphql"
411
346
  },
412
347
  defaults: {},
413
348
  async setup(options, nuxt) {
414
349
  const logger = useLogger("@lewebsimple/nuxt-graphql");
350
+ logger.info(`@lewebsimple/nuxt-graphql v${version} loaded`);
415
351
  const { resolve: resolveModule } = createResolver(import.meta.url);
416
352
  const { rootDir } = nuxt.options;
417
353
  const { resolve: resolveRoot, resolvePath: rawResolveRootPath } = createResolver(rootDir);
@@ -420,22 +356,15 @@ const module$1 = defineNuxtModule({
420
356
  }
421
357
  const nuxtAliases = {};
422
358
  const nitroAliases = {};
359
+ const emitTs = Boolean(nuxt.options.dev) || Boolean(process.env.NUXT_MODULE_PREPARE);
360
+ nuxtAliases["#graphql/runtime/remote-executor"] = resolveModule("./runtime/server/lib/remote-executor");
361
+ nitroAliases["#graphql/runtime/remote-executor"] = resolveModule("./runtime/server/lib/remote-executor");
423
362
  const contextInput = {
424
363
  importPaths: await Promise.all((options.server?.context || []).map((path) => resolveRootPath(path)))
425
364
  };
426
- let contextDst;
427
- if (nuxt.options.dev || process.env.NUXT_MODULE_PREPARE) {
428
- contextDst = addTemplate({ filename: "graphql/context.ts", getContents: () => getContextTemplate(contextInput).ts, write: true }).dst;
429
- addServerTemplate({ filename: "graphql/context.mjs", getContents: () => getContextTemplate(contextInput).mjs });
430
- } else {
431
- contextDst = addTemplate({ filename: "graphql/context.mjs", getContents: () => getContextTemplate(contextInput).mjs, write: true }).dst;
432
- addServerTemplate({ filename: "graphql/context.mjs", getContents: () => getContextTemplate(contextInput).mjs });
433
- addTypeTemplate({ filename: "graphql/context.d.ts", getContents: () => getContextTemplate(contextInput).dts });
434
- }
435
- nuxtAliases["#graphql/context"] = contextDst;
436
- nitroAliases["#graphql/context"] = contextDst;
437
- nuxtAliases["#graphql/runtime/remote-executor"] = resolveModule("./runtime/server/lib/remote-executor");
438
- nitroAliases["#graphql/runtime/remote-executor"] = resolveModule("./runtime/server/lib/remote-executor");
365
+ const contextPath = addUniversalTemplate({ filename: "graphql/context", getContents: () => getContextTemplate(contextInput), emitTs });
366
+ nuxtAliases["#graphql/context"] = contextPath;
367
+ nitroAliases["#graphql/context"] = contextPath;
439
368
  const schemaInput = { local: {}, remote: {} };
440
369
  const schemaLoaders = {};
441
370
  for (const [schemaName, schemaDef] of Object.entries(options.server?.schema || {})) {
@@ -444,34 +373,24 @@ const module$1 = defineNuxtModule({
444
373
  }
445
374
  if (schemaDef.type === "local") {
446
375
  const importPath = await resolveRootPath(schemaDef.path);
376
+ const loadSchema2 = getCachedLoader(`schema:local:${schemaName}`, async () => await loadLocalSchema({ importPath }));
447
377
  schemaInput.local[schemaName] = { importPath };
448
- schemaLoaders[schemaName] = getCachedLoader(`schema:local:${schemaName}`, async () => await loadLocalSchema({ importPath }));
378
+ schemaLoaders[schemaName] = loadSchema2;
449
379
  } else if (schemaDef.type === "remote") {
450
380
  const { endpoint } = schemaDef;
451
- const remoteSchemaInput = {
452
- endpoint,
453
- headers: schemaDef.headers || {},
454
- hooks: await Promise.all((schemaDef.hooks || []).map(async (hookPath) => ({ importPath: await resolveRootPath(hookPath) }))),
455
- loadSchema: getCachedLoader(`schema:remote:${schemaName}`, async () => await introspectRemoteSchema({ endpoint }))
456
- };
457
- if (nuxt.options.dev) {
458
- addTemplate({ filename: `graphql/schemas/${schemaName}.ts`, getContents: async () => (await getRemoteSchemaTemplate(remoteSchemaInput)).ts, write: true });
459
- addServerTemplate({ filename: `graphql/schemas/${schemaName}.ts`, getContents: async () => (await getRemoteSchemaTemplate(remoteSchemaInput)).ts });
460
- } else {
461
- addTemplate({ filename: `graphql/schemas/${schemaName}.mjs`, getContents: async () => (await getRemoteSchemaTemplate(remoteSchemaInput)).mjs, write: true });
462
- addServerTemplate({ filename: `graphql/schemas/${schemaName}.mjs`, getContents: async () => (await getRemoteSchemaTemplate(remoteSchemaInput)).mjs });
463
- addTypeTemplate({ filename: `graphql/schemas/${schemaName}.d.ts`, getContents: async () => (await getRemoteSchemaTemplate(remoteSchemaInput)).dts });
464
- }
381
+ const loadSchema2 = getCachedLoader(`schema:remote:${schemaName}`, async () => await introspectRemoteSchema({ endpoint }));
382
+ const hooks = await Promise.all((schemaDef.hooks || []).map(async (hookPath) => ({ importPath: await resolveRootPath(hookPath) })));
383
+ const remoteSchemaInput = { endpoint, headers: schemaDef.headers || {}, hooks, loadSchema: loadSchema2 };
384
+ addUniversalTemplate({ filename: `graphql/schemas/${schemaName}`, getContents: () => getRemoteSchemaTemplate(remoteSchemaInput), emitTs });
465
385
  schemaInput.remote[schemaName] = { importPath: `./schemas/${schemaName}` };
466
- schemaLoaders[schemaName] = remoteSchemaInput.loadSchema;
386
+ schemaLoaders[schemaName] = loadSchema2;
467
387
  } else {
468
388
  throw new Error(`Unknown schema type for schema "${schemaName}"`);
469
389
  }
470
390
  }
471
- const schemaDst = addTemplate({ filename: `graphql/schema.ts`, getContents: () => getSchemaTemplate(schemaInput).ts, write: true }).dst;
472
- addServerTemplate({ filename: `graphql/schema.ts`, getContents: () => getSchemaTemplate(schemaInput).ts });
473
- nuxtAliases["#graphql/schema"] = schemaDst;
474
- nitroAliases["#graphql/schema"] = schemaDst;
391
+ const schemaPath = addUniversalTemplate({ filename: "graphql/schema", getContents: () => getSchemaTemplate(schemaInput), emitTs });
392
+ nuxtAliases["#graphql/schema"] = schemaPath;
393
+ nitroAliases["#graphql/schema"] = schemaPath;
475
394
  const sdlPath = resolveRoot(options.saveSDL || "server/graphql/schema.graphql");
476
395
  const loadSchema = getCachedLoader("schema:stitched", async () => {
477
396
  const subschemas = await Promise.all(Object.values(schemaLoaders).map((loadSchema2) => loadSchema2()));
@@ -495,37 +414,14 @@ const module$1 = defineNuxtModule({
495
414
  }
496
415
  return documents;
497
416
  });
498
- const operationsInput = {
499
- loadSchema,
500
- loadDocuments,
501
- documentGlob: options.client?.documents || "**/*.gql"
502
- };
503
- let operationsDst;
504
- if (nuxt.options.dev || process.env.NUXT_MODULE_PREPARE) {
505
- operationsDst = addTemplate({ filename: "graphql/operations.ts", getContents: async () => (await getOperationsTemplate(operationsInput)).ts, write: true }).dst;
506
- addServerTemplate({ filename: "graphql/operations.ts", getContents: async () => (await getOperationsTemplate(operationsInput)).ts });
507
- } else {
508
- operationsDst = addTemplate({ filename: "graphql/operations.mjs", getContents: async () => (await getOperationsTemplate(operationsInput)).mjs, write: true }).dst;
509
- addServerTemplate({ filename: "graphql/operations.mjs", getContents: async () => (await getOperationsTemplate(operationsInput)).mjs });
510
- addTypeTemplate({ filename: "graphql/operations.d.ts", getContents: async () => (await getOperationsTemplate(operationsInput)).dts });
511
- }
512
- nuxtAliases["#graphql/operations"] = operationsDst;
513
- nitroAliases["#graphql/operations"] = operationsDst;
514
- const registryInput = {
515
- loadDocuments,
516
- documentGlob: options.client?.documents || "**/*.gql"
517
- };
518
- let registryDst;
519
- if (nuxt.options.dev || process.env.NUXT_MODULE_PREPARE) {
520
- registryDst = addTemplate({ filename: "graphql/registry.ts", getContents: async () => (await getRegistryTemplate(registryInput)).ts, write: true }).dst;
521
- addServerTemplate({ filename: "graphql/registry.ts", getContents: async () => (await getRegistryTemplate(registryInput)).ts });
522
- } else {
523
- registryDst = addTemplate({ filename: "graphql/registry.mjs", getContents: async () => (await getRegistryTemplate(registryInput)).mjs, write: true }).dst;
524
- addServerTemplate({ filename: "graphql/registry.mjs", getContents: async () => (await getRegistryTemplate(registryInput)).mjs });
525
- addTypeTemplate({ filename: "graphql/registry.d.ts", getContents: async () => (await getRegistryTemplate(registryInput)).dts });
526
- }
527
- nuxtAliases["#graphql/registry"] = registryDst;
528
- nitroAliases["#graphql/registry"] = registryDst;
417
+ const operationsInput = { loadSchema, loadDocuments, documentGlob: options.client?.documents || "**/*.gql" };
418
+ const operationsPath = addUniversalTemplate({ filename: "graphql/operations", getContents: () => getOperationsTemplate(operationsInput), emitTs });
419
+ nuxtAliases["#graphql/operations"] = operationsPath;
420
+ nitroAliases["#graphql/operations"] = operationsPath;
421
+ const registryInput = { loadDocuments, documentGlob: options.client?.documents || "**/*.gql" };
422
+ const registryPath = addUniversalTemplate({ filename: "graphql/registry", getContents: () => getRegistryTemplate(registryInput), emitTs });
423
+ nuxtAliases["#graphql/registry"] = registryPath;
424
+ nitroAliases["#graphql/registry"] = registryPath;
529
425
  if (nuxt.options.dev) {
530
426
  const configPath = resolveRoot(options.saveConfig || "graphql.config.json");
531
427
  const config = {
@@ -540,9 +436,6 @@ const module$1 = defineNuxtModule({
540
436
  nuxt.hook("nitro:config", (nitroConfig) => {
541
437
  nitroConfig.alias = defu(nitroConfig.alias, nitroAliases);
542
438
  });
543
- addTypeTemplate({ filename: "types/nuxt-graphql.app.d.ts", getContents: () => getAppTypesTemplate() }, { nuxt: true });
544
- addTypeTemplate({ filename: "types/nuxt-graphql.server.d.ts", getContents: () => getServerTypesTemplate() }, { nitro: true, node: true });
545
- addTypeTemplate({ filename: "types/nuxt-graphql.shared.d.ts", getContents: () => getSharedTypesTemplate() }, { nuxt: true, nitro: true, node: true });
546
439
  nuxt.options.runtimeConfig.public.graphql = defu(nuxt.options.runtimeConfig.public.graphql, {
547
440
  cacheConfig: resolveCacheConfig(options.client?.cache),
548
441
  ssrForwardHeaders: options.client?.ssrForwardHeaders || ["authorization", "cookie"]
@@ -560,9 +453,10 @@ const module$1 = defineNuxtModule({
560
453
  nuxt.hook("listen", (_, { url }) => {
561
454
  logger.success(`GraphQL Yoga ready: ${cyan}${url.replace(/\/$/, "")}/api/graphql${reset}`);
562
455
  });
563
- addPlugin(resolveModule("./runtime/app/plugins/graphql-request"));
456
+ addPlugin(resolveModule("./runtime/app/plugins/execute-graphql"));
564
457
  addPlugin(resolveModule("./runtime/app/plugins/graphql-sse.client"));
565
458
  addImportsDir(resolveModule("./runtime/app/composables"));
459
+ addImportsDir(resolveModule("./runtime/shared/utils"));
566
460
  addServerImportsDir(resolveModule("./runtime/server/utils"));
567
461
  }
568
462
  });
@@ -1,11 +1,11 @@
1
- import { useAsyncData, type AsyncDataOptions } from "#app";
1
+ import { type AsyncData, type AsyncDataOptions } from "#app";
2
2
  import type { QueryName, ResultOf, VariablesOf } from "#graphql/registry";
3
3
  import { type MaybeRefOrGetter } from "#imports";
4
- import { type ExecuteGraphQLHTTPOptions } from "../lib/execute-http.js";
5
- import type { IsEmptyObject } from "../../shared/lib/utils.js";
6
- type UseAsyncGraphQLQueryOptions<TName extends QueryName> = ExecuteGraphQLHTTPOptions & {
7
- cache?: Partial<GraphQLCacheConfig>;
8
- } & AsyncDataOptions<ResultOf<TName>>;
4
+ import type { IsEmptyObject } from "../../shared/lib/types.js";
5
+ import { type CacheConfig } from "../lib/cache.js";
6
+ type UseAsyncGraphQLQueryOptions<TName extends QueryName> = AsyncDataOptions<ResultOf<TName>> & {
7
+ cache?: Partial<CacheConfig>;
8
+ };
9
9
  /**
10
10
  * Async GraphQL query composable with caching support.
11
11
  *
@@ -13,5 +13,5 @@ type UseAsyncGraphQLQueryOptions<TName extends QueryName> = ExecuteGraphQLHTTPOp
13
13
  * @param args Operation variables (if any) and optional HTTP headers.
14
14
  * @returns Nuxt AsyncData wrapper for the query result.
15
15
  */
16
- export declare function useAsyncGraphQLQuery<TName extends QueryName>(operationName: TName, ...args: IsEmptyObject<VariablesOf<TName>> extends true ? [variables?: MaybeRefOrGetter<VariablesOf<TName>>, options?: UseAsyncGraphQLQueryOptions<TName>] : [variables: MaybeRefOrGetter<VariablesOf<TName>>, options?: UseAsyncGraphQLQueryOptions<TName>]): ReturnType<typeof useAsyncData<ResultOf<TName>>>;
16
+ export declare function useAsyncGraphQLQuery<TName extends QueryName>(operationName: TName, ...args: IsEmptyObject<VariablesOf<TName>> extends true ? [variables?: MaybeRefOrGetter<VariablesOf<TName>>, options?: UseAsyncGraphQLQueryOptions<TName>] : [variables: MaybeRefOrGetter<VariablesOf<TName>>, options?: UseAsyncGraphQLQueryOptions<TName>]): AsyncData<ResultOf<TName> | null, Error | undefined>;
17
17
  export {};
@@ -1,14 +1,16 @@
1
- import { useAsyncData, useNuxtData, useRuntimeConfig } from "#app";
1
+ import { useAsyncData, useNuxtApp, useNuxtData, useRuntimeConfig } from "#app";
2
2
  import { computed, toValue } from "#imports";
3
- import { executeGraphQLHTTP } from "../lib/execute-http.js";
3
+ import { getOperationDocument } from "../../shared/lib/registry.js";
4
+ import { getCacheKeyParts, resolveCacheConfig } from "../lib/cache.js";
4
5
  import { getInFlightRequests } from "../lib/in-flight.js";
5
6
  import { getPersistedEntry, setPersistedEntry } from "../lib/persisted.js";
6
- import { getCacheKeyParts, resolveCacheConfig } from "../../shared/lib/cache.js";
7
7
  export function useAsyncGraphQLQuery(operationName, ...args) {
8
+ const { $executeGraphQL } = useNuxtApp();
8
9
  const [variables, options] = args;
10
+ const document = getOperationDocument(operationName);
9
11
  const isClient = import.meta.client;
10
12
  const { public: { graphql } } = useRuntimeConfig();
11
- const { headers, cache, ...asyncDataOptions } = options ?? {};
13
+ const { cache, ...asyncDataOptions } = options ?? {};
12
14
  const cacheConfig = resolveCacheConfig(graphql.cacheConfig, cache);
13
15
  const cacheKey = computed(() => getCacheKeyParts(cacheConfig, operationName, toValue(variables)).key);
14
16
  const inFlight = getInFlightRequests();
@@ -17,16 +19,18 @@ export function useAsyncGraphQLQuery(operationName, ...args) {
17
19
  if (inFlight.has(key)) {
18
20
  return inFlight.get(key);
19
21
  }
20
- const promise = executeGraphQLHTTP(operationName, toValue(variables), { headers }).then((data) => {
22
+ const promise = $executeGraphQL({ query: document, variables: toValue(variables), operationName }).then((result) => {
23
+ if (result.error) {
24
+ throw result.error;
25
+ }
26
+ const data = result.data;
21
27
  if (isClient && cacheConfig.ttl !== void 0) {
22
28
  setPersistedEntry(key, data, cacheConfig.ttl);
23
29
  }
24
30
  return data;
25
31
  });
26
32
  inFlight.set(key, promise);
27
- promise.finally(() => {
28
- inFlight.delete(key);
29
- });
33
+ promise.finally(() => inFlight.delete(key));
30
34
  return promise;
31
35
  }
32
36
  async function asyncDataHandler() {