@lewebsimple/nuxt-graphql 0.5.2 → 0.5.4

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/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-graphql",
3
3
  "configKey": "graphql",
4
- "version": "0.5.2",
4
+ "version": "0.5.4",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  import { mkdirSync, writeFileSync } from 'node:fs';
2
- import { resolve, dirname, relative } from 'node:path';
3
- import { defineNuxtModule, useLogger, createResolver, addTemplate, addServerHandler, addPlugin, addImportsDir, addServerImportsDir } from '@nuxt/kit';
2
+ import { dirname, relative, resolve } from 'node:path';
3
+ import { defineNuxtModule, useLogger, createResolver, addTemplate, addServerTemplate, addTypeTemplate, addServerHandler, addPlugin, addImportsDir, addServerImportsDir } from '@nuxt/kit';
4
+ import { defu } from 'defu';
4
5
  import { hash } from 'ohash';
5
6
  import { loadDocuments as loadDocuments$1 } from '@graphql-tools/load';
6
7
  import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
@@ -18,15 +19,16 @@ const reset = "\x1B[0m";
18
19
 
19
20
  function renderContextTemplate({ contextModules }) {
20
21
  const imports = contextModules.map((module, index) => `import context${index} from ${JSON.stringify(module)};`);
21
- const types = contextModules.map((_, index) => `Awaited<ReturnType<typeof context${index}>>`);
22
+ const types = ["{}", ...contextModules.map((_, index) => `Awaited<ReturnType<typeof context${index}>>`)];
22
23
  return [
23
24
  `import type { H3Event } from "h3";`,
24
25
  ...imports,
25
26
  "",
26
- `export type GraphQLContext = ${types.join("\n & ")};`,
27
+ `export type GraphQLContext = ${types.join(" & ")};`,
27
28
  "",
28
29
  "export async function createContext(event: H3Event): Promise<GraphQLContext> {",
29
30
  " const parts = await Promise.all([",
31
+ " () => ({}),",
30
32
  ...contextModules.map((_, index) => ` context${index}(event),`),
31
33
  " ]);",
32
34
  " return Object.assign({}, ...parts) as GraphQLContext;",
@@ -56,7 +58,7 @@ async function renderFragmentsTemplate({ documents }) {
56
58
  }
57
59
  return [
58
60
  `export type {`,
59
- ...fragments.map((name) => ` ${name} as ${name}Fragment,`),
61
+ ...fragments.map((name) => ` ${name}Fragment,`),
60
62
  `} from "./operations";`
61
63
  ].join("\n");
62
64
  }
@@ -85,29 +87,51 @@ async function renderOperationsTemplate({ schema, documents }) {
85
87
  schema,
86
88
  documents,
87
89
  plugins: [
88
- { typescript: {} },
89
- { typescriptOperations: {} },
90
- { typedDocumentNode: {} }
90
+ {
91
+ typescript: {
92
+ avoidOptionals: true,
93
+ defaultScalarType: "never",
94
+ enumsAsTypes: true,
95
+ immutableTypes: true,
96
+ maybeValue: "T | null",
97
+ preResolveTypes: false,
98
+ strictScalars: true,
99
+ useTypeImports: true
100
+ }
101
+ },
102
+ {
103
+ typescriptOperations: {
104
+ avoidOptionals: true,
105
+ defaultScalarType: "never",
106
+ enumsAsTypes: true,
107
+ exportFragmentSpreadSubTypes: true,
108
+ immutableTypes: true,
109
+ inlineFragmentTypes: "combine",
110
+ maybeValue: "T | null",
111
+ operationResultSuffix: "Result",
112
+ operationVariablesSuffix: "Variables",
113
+ preResolveTypes: false,
114
+ skipTypename: true,
115
+ strictScalars: true,
116
+ useTypeImports: true
117
+ }
118
+ },
119
+ {
120
+ typedDocumentNode: {
121
+ documentVariableSuffix: "Document",
122
+ operationResultSuffix: "Result",
123
+ operationVariablesSuffix: "Variables",
124
+ optimizeDocumentNode: true,
125
+ useTypeImports: true
126
+ }
127
+ }
91
128
  ],
92
129
  pluginMap: {
93
130
  typescript: typescriptPlugin,
94
131
  typescriptOperations: typescriptOperationsPlugin,
95
132
  typedDocumentNode: typedDocumentNodePlugin
96
133
  },
97
- config: {
98
- defaultScalarType: "never",
99
- documentMode: "documentNode",
100
- documentVariableSuffix: "Document",
101
- enumsAsTypes: true,
102
- inlineFragmentTypes: "combine",
103
- omitOperationSuffix: true,
104
- operationResultSuffix: "Result",
105
- operationVariablesSuffix: "Variables",
106
- preResolveTypes: false,
107
- skipTypename: true,
108
- strictScalars: true,
109
- useTypeImports: true
110
- }
134
+ config: {}
111
135
  });
112
136
  return output;
113
137
  }
@@ -118,63 +142,41 @@ async function renderRegistryTemplate({ documents }) {
118
142
  `import type { DocumentNode } from "graphql";`,
119
143
  `import {`,
120
144
  ...operations.map(
121
- ({ name }) => ` ${name}Document, type ${name}Variables, type ${name}Result,`
145
+ ({ name }) => ` ${name}Document, type ${name}QueryVariables, type ${name}QueryResult,`
122
146
  ),
123
147
  `} from "./operations";`,
124
148
  ``,
125
149
  // Operation entry
126
- `export interface OperationEntry<`,
127
- ` TVariables,`,
128
- ` TResult,`,
129
- ` TKind extends "query" | "mutation" | "subscription"`,
130
- `> {`,
150
+ `export interface OperationEntry<TVariables, TResult, TKind extends "query" | "mutation" | "subscription"> {`,
131
151
  ` kind: TKind;`,
132
152
  ` variables: TVariables;`,
133
153
  ` result: TResult;`,
134
154
  ` document: DocumentNode;`,
135
155
  `}`,
136
156
  ``,
157
+ // Operation registry type
137
158
  `export type OperationRegistry = {`,
138
159
  ...operations.map(
139
- ({ name, kind }) => ` ${name}: OperationEntry<${name}Variables, ${name}Result, "${kind}">;`
160
+ ({ name, kind }) => ` ${name}: OperationEntry<${name}QueryVariables, ${name}QueryResult, "${kind}">;`
140
161
  ),
141
162
  `};`,
142
163
  ``,
143
- `export type OperationName = keyof OperationRegistry;`,
144
- ``,
145
- `export type QueryName = {`,
146
- ` [K in keyof OperationRegistry]:`,
147
- ` OperationRegistry[K]["kind"] extends "query" ? K : never`,
148
- `}[keyof OperationRegistry];`,
149
- ``,
150
- `export type MutationName = {`,
151
- ` [K in keyof OperationRegistry]:`,
152
- ` OperationRegistry[K]["kind"] extends "mutation" ? K : never`,
153
- `}[keyof OperationRegistry];`,
154
- ``,
155
- `export type SubscriptionName = {`,
156
- ` [K in keyof OperationRegistry]:`,
157
- ` OperationRegistry[K]["kind"] extends "subscription" ? K : never`,
158
- `}[keyof OperationRegistry];`,
159
- ``,
160
- // Projection helpers
161
- `export type VariablesOf<TName extends keyof OperationRegistry> =`,
162
- ` OperationRegistry[TName]["variables"];`,
164
+ // Operation name types
165
+ `export type QueryName = { [K in keyof OperationRegistry]: OperationRegistry[K]["kind"] extends "query" ? K : never }[keyof OperationRegistry];`,
166
+ `export type MutationName = { [K in keyof OperationRegistry]: OperationRegistry[K]["kind"] extends "mutation" ? K : never }[keyof OperationRegistry];`,
167
+ `export type SubscriptionName = { [K in keyof OperationRegistry]: OperationRegistry[K]["kind"] extends "subscription" ? K : never }[keyof OperationRegistry];`,
163
168
  ``,
164
- `export type ResultOf<TName extends keyof OperationRegistry> =`,
165
- ` OperationRegistry[TName]["result"];`,
169
+ // Projection helpers (variables / result)
170
+ `export type VariablesOf<TName extends keyof OperationRegistry> = OperationRegistry[TName]["variables"];`,
171
+ `export type ResultOf<TName extends keyof OperationRegistry> = OperationRegistry[TName]["result"];`,
166
172
  ``,
167
173
  // Runtime registry (document + kind only)
168
- `export const registry: {`,
169
- ` [K in keyof OperationRegistry]: {`,
170
- ` kind: OperationRegistry[K]["kind"];`,
171
- ` document: DocumentNode;`,
172
- ` };`,
173
- `} = {`,
174
+ `export const registry: { [K in keyof OperationRegistry]: { kind: OperationRegistry[K]["kind"]; document: DocumentNode; }; } = {`,
174
175
  ...operations.map(
175
176
  ({ name, kind }) => ` ${name}: { kind: "${kind}", document: ${name}Document },`
176
177
  ),
177
- `};`
178
+ `};`,
179
+ ``
178
180
  ].join("\n");
179
181
  }
180
182
  function collectOperations(documents) {
@@ -290,30 +292,65 @@ async function loadStitchedSchema(schemaDefs) {
290
292
  return stitchSchemas({ subschemas });
291
293
  }
292
294
 
293
- function renderTypesTemplate() {
294
- return `// Nuxt GraphQL types
295
- declare module "#graphql/context" {
296
- export { createContext } from "#build/graphql/context";
297
- export type { GraphQLContext } from "#build/graphql/context";
295
+ function renderAppTypesTemplate() {
296
+ return `// Nuxt GraphQL types (app)
297
+ import type { GraphQLClient } from "graphql-request";
298
+ import type { Client as SSEClient } from "graphql-sse";
299
+
300
+ declare module "#app/nuxt" {
301
+ interface NuxtApp {
302
+ $getGraphQLClient: () => GraphQLClient;
303
+ $getGraphQLSSEClient: () => SSEClient;
304
+ }
298
305
  }
299
306
 
300
- declare module "#graphql/operations" {
301
- export * from "#build/graphql/operations";
307
+ declare module "#app" {
308
+ interface NuxtApp {
309
+ $getGraphQLClient: () => GraphQLClient;
310
+ $getGraphQLSSEClient: () => SSEClient;
311
+ }
302
312
  }
303
313
 
304
- declare module "#graphql/fragments" {
305
- export * from "#build/graphql/fragments";
314
+ export {};
315
+ `;
306
316
  }
317
+ function renderServerTypesTemplate() {
318
+ return `// Nuxt GraphQL types (server)
319
+ import type { GraphQLSchema } from "graphql";
307
320
 
308
- declare module "#graphql/registry" {
309
- import type { DocumentNode } from "graphql";
310
- export type { OperationName, QueryName, MutationName, SubscriptionName, VariablesOf, ResultOf } from "#build/graphql/registry";
311
- export const registry: Readonly<Record<OperationName, { readonly document: DocumentNode; }>>;
321
+ declare module "#graphql/context" {
322
+ export type { GraphQLContext };
312
323
  }
313
324
 
314
325
  declare module "#graphql/schema" {
315
- export { schema } from "#build/graphql/schema";
316
- }`;
326
+ export const schema: GraphQLSchema;
327
+ }
328
+
329
+ declare module "h3" {
330
+ interface H3EventContext {
331
+ _graphqlInFlightRequestsMap?: Map<string, Promise<unknown>>;
332
+ }
333
+ }
334
+
335
+ export {};
336
+ `;
337
+ }
338
+ function renderSharedTypesTemplate() {
339
+ return `// Nuxt GraphQL types (shared)
340
+ import type { DocumentNode } from "graphql";
341
+ import type { CacheConfig } from "nuxt-graphql/runtime/shared/lib/cache-config";
342
+
343
+ declare module "nuxt/schema" {
344
+ interface PublicRuntimeConfig {
345
+ graphql: {
346
+ cacheConfig?: CacheConfig;
347
+ ssrForwardHeaders: string[];
348
+ };
349
+ }
350
+ }
351
+
352
+ export {};
353
+ `;
317
354
  }
318
355
 
319
356
  const module$1 = defineNuxtModule({
@@ -324,6 +361,7 @@ const module$1 = defineNuxtModule({
324
361
  defaults: {},
325
362
  async setup(options, nuxt) {
326
363
  const logger = useLogger("graphql");
364
+ const { resolve: resolveBuild } = createResolver(nuxt.options.buildDir);
327
365
  const { resolve: resolveModule } = createResolver(import.meta.url);
328
366
  const { resolve: resolveRoot, resolvePath: _resolveRootPath } = createResolver(nuxt.options.rootDir);
329
367
  async function resolveRootPath(path, required = true) {
@@ -345,32 +383,22 @@ const module$1 = defineNuxtModule({
345
383
  return relativePath;
346
384
  }
347
385
  nuxt.options.alias ||= {};
348
- nuxt.options.alias["#graphql"] = resolve(nuxt.options.buildDir, "graphql");
349
- const nitroAlias = {};
386
+ nuxt.options.alias["#graphql"] ||= resolveBuild("graphql");
350
387
  const contextModules = [
351
- resolveModule("./runtime/server/lib/default-context"),
352
388
  ...await Promise.all((options.yoga?.context || []).map((path) => resolveRootPath(path, true)))
353
389
  ];
354
- const contextTemplate = addTemplate({
355
- filename: "graphql/context.ts",
356
- getContents: () => renderContextTemplate({ contextModules }),
357
- write: true
358
- });
359
- nitroAlias["#graphql/context"] = contextTemplate.dst;
390
+ addTemplate({ filename: "graphql/context.ts", getContents: () => renderContextTemplate({ contextModules }), write: true });
391
+ addServerTemplate({ filename: "#graphql/#context.ts", getContents: () => renderContextTemplate({ contextModules }) });
360
392
  const schemaDefs = {};
361
393
  for (const [schemaName, schemaDef] of Object.entries(options.yoga?.schemas || {})) {
362
- let schemaTemplate2;
363
394
  if (schemaDef.type === "local") {
364
395
  const localSchemaDef = {
365
396
  ...schemaDef,
366
397
  path: await resolveRootPath(schemaDef.path, true)
367
398
  };
368
399
  schemaDefs[schemaName] = localSchemaDef;
369
- schemaTemplate2 = addTemplate({
370
- filename: `graphql/schemas/${schemaName}.ts`,
371
- getContents: async () => renderLocalSchemaTemplate({ ...localSchemaDef }),
372
- write: true
373
- });
400
+ addTemplate({ filename: `graphql/schemas/${schemaName}.ts`, getContents: async () => renderLocalSchemaTemplate({ ...localSchemaDef }), write: true });
401
+ addServerTemplate({ filename: `#graphql/schemas/${schemaName}.ts`, getContents: async () => renderLocalSchemaTemplate({ ...localSchemaDef }) });
374
402
  } else if (schemaDef.type === "remote") {
375
403
  const remoteSchemaDef = {
376
404
  ...schemaDef,
@@ -378,24 +406,14 @@ const module$1 = defineNuxtModule({
378
406
  remoteExecutorModule: resolveModule("./runtime/server/lib/remote-executor")
379
407
  };
380
408
  schemaDefs[schemaName] = remoteSchemaDef;
381
- schemaTemplate2 = addTemplate({
382
- filename: `graphql/schemas/${schemaName}.ts`,
383
- getContents: async () => await renderRemoteSchemaTemplate({ ...remoteSchemaDef }),
384
- write: true
385
- });
409
+ addTemplate({ filename: `graphql/schemas/${schemaName}.ts`, getContents: async () => await renderRemoteSchemaTemplate({ ...remoteSchemaDef }), write: true });
410
+ addServerTemplate({ filename: `#graphql/schemas/${schemaName}.ts`, getContents: async () => await renderRemoteSchemaTemplate({ ...remoteSchemaDef }) });
386
411
  } else {
387
412
  throw new Error(`Unknown schema type for schema "${schemaName}"`);
388
413
  }
389
- nitroAlias[`#graphql/schemas/${schemaName}`] = schemaTemplate2.dst;
390
414
  }
391
- const schemaTemplate = addTemplate({
392
- filename: "graphql/schema.ts",
393
- getContents: () => renderStitchedSchemaTemplate({
394
- schemaNames: Object.keys(options.yoga?.schemas || {})
395
- }),
396
- write: true
397
- });
398
- nitroAlias["#graphql/schema"] = schemaTemplate.dst;
415
+ addTemplate({ filename: "graphql/schema.ts", getContents: () => renderStitchedSchemaTemplate({ schemaNames: Object.keys(options.yoga?.schemas || {}) }), write: true });
416
+ addServerTemplate({ filename: "#graphql/schema.ts", getContents: () => renderStitchedSchemaTemplate({ schemaNames: Object.keys(options.yoga?.schemas || {}) }) });
399
417
  let documentsCache = null;
400
418
  async function getDocuments(glob) {
401
419
  const key = `documents:${glob}`;
@@ -439,27 +457,17 @@ const module$1 = defineNuxtModule({
439
457
  }),
440
458
  write: true
441
459
  });
460
+ addTypeTemplate({ filename: "types/nuxt-graphql.app.d.ts", getContents: () => renderAppTypesTemplate() }, { nuxt: true });
461
+ addTypeTemplate({ filename: "types/nuxt-graphql.server.d.ts", getContents: () => renderServerTypesTemplate() }, { nitro: true });
462
+ addTypeTemplate({ filename: "types/nuxt-graphql.shared.d.ts", getContents: () => renderSharedTypesTemplate() }, { nuxt: true, nitro: true });
442
463
  const configPath = resolveRoot(options.saveConfig || "graphql.config.json");
443
464
  const config = { schema: getRelativePath(sdlPath), documents: options.client?.documents || "**/*.gql" };
444
465
  mkdirSync(dirname(configPath), { recursive: true });
445
466
  writeFileSync(configPath, JSON.stringify(config, null, 2), { encoding: "utf-8" });
446
467
  logger.info(`GraphQL config saved to: ${cyan}${getRelativePath(configPath)}${reset}`);
447
- const typesTemplate = addTemplate({
448
- filename: "graphql/types.d.ts",
449
- getContents: () => renderTypesTemplate(),
450
- write: true
451
- });
452
- nuxt.options.runtimeConfig.public.graphql = {
468
+ nuxt.options.runtimeConfig.public.graphql = defu(nuxt.options.runtimeConfig.public.graphql, {
453
469
  cacheConfig: resolveCacheConfig(options.client?.cache),
454
470
  ssrForwardHeaders: options.client?.ssrForwardHeaders || ["authorization", "cookie"]
455
- };
456
- nuxt.hook("prepare:types", ({ sharedReferences }) => {
457
- sharedReferences.push({ path: typesTemplate.dst });
458
- sharedReferences.push({ path: resolveModule("./runtime/shared/types/nuxt-graphql.d.ts") });
459
- });
460
- nuxt.hook("nitro:config", (nitroConfig) => {
461
- nitroConfig.alias ||= {};
462
- Object.assign(nitroConfig.alias, nitroAlias);
463
471
  });
464
472
  if (nuxt.options.dev) {
465
473
  nuxt.hook("builder:watch", async (_event, changedPath) => {
@@ -471,7 +479,7 @@ const module$1 = defineNuxtModule({
471
479
  }
472
480
  addServerHandler({ route: "/api/graphql", handler: resolveModule("./runtime/server/api/graphql") });
473
481
  nuxt.hook("listen", (_, { url }) => {
474
- logger.success(`GraphQL Yoga ready: ${cyan}${url.replace(/\/$/, "")} / api / graphql${reset}`);
482
+ logger.success(`GraphQL Yoga ready: ${cyan}${url.replace(/\/$/, "")}/api/graphql${reset}`);
475
483
  });
476
484
  addPlugin(resolveModule("./runtime/app/plugins/graphql-request"));
477
485
  addPlugin(resolveModule("./runtime/app/plugins/graphql-sse.client"));
@@ -1,6 +1,7 @@
1
+ import type { GraphQLContext } from "#graphql/context";
1
2
  /**
2
3
  * Get or create the singleton GraphQL Yoga instance.
3
4
  *
4
5
  * @returns GraphQL Yoga server instance.
5
6
  */
6
- export declare function getYogaInstance(): import("graphql-yoga").YogaServerInstance<{}, {}>;
7
+ export declare function getYogaInstance(): import("graphql-yoga").YogaServerInstance<GraphQLContext, {}>;
@@ -1,5 +1,5 @@
1
1
  type GraphQLCachePolicy = "no-cache" | "cache-first" | "network-first" | "swr";
2
- export interface CacheConfig {
2
+ export type CacheConfig = {
3
3
  /**
4
4
  * Prefix used for all persisted cache keys.
5
5
  *
@@ -31,7 +31,7 @@ export interface CacheConfig {
31
31
  * - > 0 → expires after TTL
32
32
  */
33
33
  ttl?: number;
34
- }
34
+ };
35
35
  /**
36
36
  * Merge the default cache config with user overrides.
37
37
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lewebsimple/nuxt-graphql",
3
- "version": "0.5.2",
3
+ "version": "0.5.4",
4
4
  "description": "Opinionated Nuxt module for using GraphQL",
5
5
  "repository": "lewebsimple/nuxt-graphql",
6
6
  "license": "AGPL-3.0-only",
@@ -36,6 +36,7 @@
36
36
  "@graphql-tools/load": "^8.1.8",
37
37
  "@graphql-tools/stitch": "^10.1.8",
38
38
  "@nuxt/kit": "^4.2.2",
39
+ "defu": "^6.1.4",
39
40
  "graphql": "^16.12.0",
40
41
  "graphql-request": "^7.4.0",
41
42
  "graphql-sse": "^2.6.0",
@@ -1,5 +0,0 @@
1
- /**
2
- * Default empty GraphQL context factory.
3
- */
4
- declare const _default: (event: import("h3").H3Event) => {} | Promise<{}>;
5
- export default _default;
@@ -1,2 +0,0 @@
1
- import { defineGraphQLContext } from "../utils/defineGraphQLContext.js";
2
- export default defineGraphQLContext(() => ({}));
@@ -1,33 +0,0 @@
1
- import type { GraphQLClient } from "graphql-request";
2
- import type { Client as SSEClient } from "graphql-sse";
3
-
4
- declare module "h3" {
5
- interface H3EventContext {
6
- _graphqlInFlightRequestsMap?: Map<string, Promise<unknown>>;
7
- }
8
- }
9
-
10
- declare module "nuxt/schema" {
11
- interface PublicRuntimeConfig {
12
- graphql: {
13
- cacheConfig: GraphQLCacheConfig;
14
- ssrForwardHeaders: string[];
15
- };
16
- }
17
- }
18
-
19
- declare module "#app/nuxt" {
20
- interface NuxtApp {
21
- $getGraphQLClient: () => GraphQLClient;
22
- $getGraphQLSSEClient: () => SSEClient;
23
- }
24
- }
25
-
26
- declare module "#app" {
27
- interface NuxtApp {
28
- $getGraphQLClient: () => GraphQLClient;
29
- $getGraphQLSSEClient: () => SSEClient;
30
- }
31
- }
32
-
33
- export { };