@lewebsimple/nuxt-graphql 0.1.9 → 0.1.10

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": "@lewebsimple/nuxt-graphql",
3
3
  "configKey": "graphql",
4
- "version": "0.1.9",
4
+ "version": "0.1.10",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { useLogger, defineNuxtModule, createResolver, getLayerDirectories, addServerTemplate, addServerHandler, addImportsDir, addPlugin, addTypeTemplate } from '@nuxt/kit';
1
+ import { useLogger, defineNuxtModule, createResolver, getLayerDirectories, addServerTemplate, addServerHandler, addImportsDir, addServerImportsDir, addPlugin, addTypeTemplate } from '@nuxt/kit';
2
2
  import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
3
3
  import { join, dirname, relative } from 'node:path';
4
4
  import { glob } from 'tinyglobby';
@@ -238,7 +238,7 @@ const module$1 = defineNuxtModule({
238
238
  const layerServerDirs = layerDirs.map(({ server }) => server);
239
239
  const layerRootDirs = layerDirs.map(({ root }) => root);
240
240
  const schemaPath = await findSingleFile(layerServerDirs, "graphql/schema.{ts,mjs}", true);
241
- const contextPath = await findSingleFile(layerServerDirs, "graphql/context.{ts,mjs}") || resolve("./runtime/server/default-context.ts");
241
+ const contextPath = await findSingleFile(layerServerDirs, "graphql/context.{ts,mjs}") || resolve("./runtime/server/graphql/default-context.ts");
242
242
  nuxt.hook("nitro:config", (config) => {
243
243
  config.alias ||= {};
244
244
  config.alias["#graphql/schema"] = schemaPath;
@@ -304,6 +304,7 @@ const module$1 = defineNuxtModule({
304
304
  });
305
305
  }
306
306
  addImportsDir(resolve("./runtime/composables"));
307
+ addServerImportsDir(resolve("./runtime/server/utils"));
307
308
  addPlugin(resolve("./runtime/plugins/graphql"));
308
309
  addTypeTemplate({
309
310
  filename: "types/graphql-client.d.ts",
@@ -1,7 +1,7 @@
1
1
  import { type MutationName, type MutationResult, type MutationVariables } from "#graphql/registry";
2
2
  import type { IsEmptyObject } from "../utils/helpers.js";
3
3
  export declare function useGraphQLMutation<N extends MutationName>(operationName: N): {
4
- mutate: (...args: IsEmptyObject<MutationVariables<N>> extends true ? [variables?: MutationVariables<N>] : [variables: MutationVariables<N>]) => Promise<{
4
+ mutate: (...args: IsEmptyObject<MutationVariables<N>> extends true ? [variables?: MutationVariables<N>, headers?: HeadersInit] : [variables: MutationVariables<N>, headers?: HeadersInit]) => Promise<{
5
5
  data: MutationResult<N> | null;
6
6
  error: Error | null;
7
7
  }>;
@@ -1,14 +1,15 @@
1
1
  import { ref } from "vue";
2
- import { useGraphQL } from "./useGraphQL.js";
2
+ import { useNuxtApp } from "#imports";
3
3
  import { mutations } from "#graphql/registry";
4
4
  export function useGraphQLMutation(operationName) {
5
5
  const document = mutations[operationName];
6
- const { request } = useGraphQL();
6
+ const { $graphql } = useNuxtApp();
7
7
  const pending = ref(false);
8
8
  async function mutate(...args) {
9
9
  pending.value = true;
10
10
  try {
11
- const result = await request(document, args[0]);
11
+ const [variables, headers] = args;
12
+ const result = await $graphql().request(document, variables, headers);
12
13
  return { data: result, error: null };
13
14
  } catch (e) {
14
15
  const error = e instanceof Error ? e : new Error(String(e));
@@ -1,4 +1,4 @@
1
1
  import type { AsyncData, AsyncDataOptions } from "#app";
2
2
  import { type QueryName, type QueryResult, type QueryVariables } from "#graphql/registry";
3
3
  import type { IsEmptyObject } from "../utils/helpers.js";
4
- export declare function useGraphQLQuery<N extends QueryName>(operationName: N, ...args: IsEmptyObject<QueryVariables<N>> extends true ? [variables?: QueryVariables<N>, opts?: AsyncDataOptions<QueryResult<N>>] : [variables: QueryVariables<N>, opts?: AsyncDataOptions<QueryResult<N>>]): AsyncData<QueryResult<N>, Error | null>;
4
+ export declare function useGraphQLQuery<N extends QueryName>(operationName: N, ...args: IsEmptyObject<QueryVariables<N>> extends true ? [variables?: QueryVariables<N>, options?: AsyncDataOptions<QueryResult<N>>, headers?: HeadersInit] : [variables: QueryVariables<N>, options?: AsyncDataOptions<QueryResult<N>>, headers?: HeadersInit]): AsyncData<QueryResult<N>, Error | null>;
@@ -1,11 +1,10 @@
1
- import { useAsyncData } from "#imports";
1
+ import { useAsyncData, useNuxtApp } from "#imports";
2
2
  import { hash } from "ohash";
3
- import { useGraphQL } from "./useGraphQL.js";
4
3
  import { queries } from "#graphql/registry";
5
4
  export function useGraphQLQuery(operationName, ...args) {
5
+ const { $graphql } = useNuxtApp();
6
6
  const document = queries[operationName];
7
- const [variables, opts] = args;
8
- const { request } = useGraphQL();
7
+ const [variables, options, headers] = args;
9
8
  const key = `graphql:query:${operationName}:${hash(variables ?? {})}`;
10
- return useAsyncData(key, () => request(document, variables), opts);
9
+ return useAsyncData(key, () => $graphql().request(document, variables, headers), options);
11
10
  }
@@ -0,0 +1,10 @@
1
+ import { type MaybeRefOrGetter, type Ref } from "vue";
2
+ import { type SubscriptionName, type SubscriptionResult, type SubscriptionVariables } from "#graphql/registry";
3
+ import type { IsEmptyObject } from "../utils/helpers.js";
4
+ export type UseGraphQLSubscriptionReturn<N extends SubscriptionName> = {
5
+ data: Ref<SubscriptionResult<N> | null>;
6
+ error: Ref<Error | null>;
7
+ start: () => void;
8
+ stop: () => void;
9
+ };
10
+ export declare function useGraphQLSubscription<N extends SubscriptionName>(operationName: N, ...args: IsEmptyObject<SubscriptionVariables<N>> extends true ? [variables?: MaybeRefOrGetter<SubscriptionVariables<N>>] : [variables: MaybeRefOrGetter<SubscriptionVariables<N>>]): UseGraphQLSubscriptionReturn<N>;
@@ -0,0 +1,45 @@
1
+ import { ref, onScopeDispose, toValue } from "vue";
2
+ import { print } from "graphql";
3
+ import { useNuxtApp } from "#imports";
4
+ import { subscriptions } from "#graphql/registry";
5
+ export function useGraphQLSubscription(operationName, ...args) {
6
+ const { $graphqlSSE } = useNuxtApp();
7
+ const [variables] = args;
8
+ const data = ref(null);
9
+ const error = ref(null);
10
+ let unsubscribe = null;
11
+ function start() {
12
+ stop();
13
+ error.value = null;
14
+ unsubscribe = $graphqlSSE().subscribe(
15
+ {
16
+ query: print(subscriptions[operationName]),
17
+ variables: toValue(variables)
18
+ },
19
+ {
20
+ next: (result) => {
21
+ if (result.errors?.length) {
22
+ error.value = new Error(result.errors.map((e) => e.message).join(", "));
23
+ } else if (result.data) {
24
+ data.value = result.data;
25
+ }
26
+ },
27
+ error: (e) => {
28
+ error.value = e instanceof Error ? e : new Error(String(e));
29
+ },
30
+ complete: () => {
31
+ unsubscribe = null;
32
+ }
33
+ }
34
+ );
35
+ }
36
+ function stop() {
37
+ unsubscribe?.();
38
+ unsubscribe = null;
39
+ }
40
+ if (import.meta.client) {
41
+ start();
42
+ }
43
+ onScopeDispose(stop);
44
+ return { data, error, start, stop };
45
+ }
@@ -1,7 +1,10 @@
1
1
  import { GraphQLClient } from "graphql-request";
2
+ import { type Client as SSEClient } from "graphql-sse";
2
3
  declare const _default: import("nuxt/app").Plugin<{
3
- graphql: GraphQLClient;
4
+ graphql: () => GraphQLClient;
5
+ graphqlSSE: () => SSEClient;
4
6
  }> & import("nuxt/app").ObjectPlugin<{
5
- graphql: GraphQLClient;
7
+ graphql: () => GraphQLClient;
8
+ graphqlSSE: () => SSEClient;
6
9
  }>;
7
10
  export default _default;
@@ -1,12 +1,35 @@
1
1
  import { GraphQLClient } from "graphql-request";
2
- import { defineNuxtPlugin, useRequestURL, useRuntimeConfig } from "#imports";
2
+ import { createClient } from "graphql-sse";
3
+ import { defineNuxtPlugin, useRequestHeaders, useRequestURL, useRuntimeConfig } from "#imports";
3
4
  export default defineNuxtPlugin(() => {
4
- const config = useRuntimeConfig();
5
+ const { public: { graphql: { endpoint } } } = useRuntimeConfig();
5
6
  const { origin } = useRequestURL();
6
- const client = new GraphQLClient(`${origin}${config.public.graphql.endpoint}`);
7
+ const url = `${origin}${endpoint}`;
8
+ let client = null;
9
+ const getClient = () => {
10
+ if (!client) {
11
+ client = new GraphQLClient(url);
12
+ }
13
+ if (import.meta.server) {
14
+ const headers = useRequestHeaders(["cookie", "authorization"]);
15
+ client.setHeaders(headers);
16
+ }
17
+ return client;
18
+ };
19
+ let sseClient = null;
20
+ const getSSEClient = () => {
21
+ if (import.meta.server) {
22
+ throw new Error("SSE subscriptions are not available on the server");
23
+ }
24
+ if (!sseClient) {
25
+ sseClient = createClient({ url });
26
+ }
27
+ return sseClient;
28
+ };
7
29
  return {
8
30
  provide: {
9
- graphql: client
31
+ graphql: getClient,
32
+ graphqlSSE: getSSEClient
10
33
  }
11
34
  };
12
35
  });
@@ -0,0 +1,15 @@
1
+ import type { H3Event } from "h3";
2
+ import { GraphQLClient } from "graphql-request";
3
+ /**
4
+ * Create server-side GraphQL client instance for the given H3 event.
5
+ *
6
+ * @param event H3 event
7
+ *
8
+ * @returns GraphQL client instance
9
+ */
10
+ export declare function getGraphQLClient(event: H3Event): GraphQLClient;
11
+ declare module "h3" {
12
+ interface H3EventContext {
13
+ __nuxtGraphQLClient?: GraphQLClient;
14
+ }
15
+ }
@@ -0,0 +1,14 @@
1
+ import { getRequestHeaders, getRequestURL } from "h3";
2
+ import { GraphQLClient } from "graphql-request";
3
+ import { useRuntimeConfig } from "#imports";
4
+ export function getGraphQLClient(event) {
5
+ if (event.context.__nuxtGraphQLClient) {
6
+ return event.context.__nuxtGraphQLClient;
7
+ }
8
+ const { public: { graphql: { endpoint } } } = useRuntimeConfig();
9
+ const { origin } = getRequestURL(event);
10
+ const url = `${origin}${endpoint}`;
11
+ const headers = getRequestHeaders(event);
12
+ event.context.__nuxtGraphQLClient = new GraphQLClient(url, { headers });
13
+ return event.context.__nuxtGraphQLClient;
14
+ }
@@ -0,0 +1,9 @@
1
+ import type { H3Event } from "h3";
2
+ import { type MutationName, type MutationResult, type MutationVariables } from "#graphql/registry";
3
+ import type { IsEmptyObject } from "../../utils/helpers.js";
4
+ export declare function useGraphQLMutation<N extends MutationName>(event: H3Event, operationName: N): Promise<{
5
+ mutate: (...args: IsEmptyObject<MutationVariables<N>> extends true ? [variables?: MutationVariables<N>, headers?: HeadersInit] : [variables: MutationVariables<N>, headers?: HeadersInit]) => Promise<{
6
+ data: MutationResult<N> | null;
7
+ error: Error | null;
8
+ }>;
9
+ }>;
@@ -0,0 +1,16 @@
1
+ import { getGraphQLClient } from "./graphql-client.js";
2
+ import { mutations } from "#graphql/registry";
3
+ export async function useGraphQLMutation(event, operationName) {
4
+ const client = getGraphQLClient(event);
5
+ async function mutate(...args) {
6
+ try {
7
+ const [variables, headers] = args;
8
+ const result = await client.request(mutations[operationName], variables, headers);
9
+ return { data: result, error: null };
10
+ } catch (e) {
11
+ const error = e instanceof Error ? e : new Error(String(e));
12
+ return { data: null, error };
13
+ }
14
+ }
15
+ return { mutate };
16
+ }
@@ -0,0 +1,4 @@
1
+ import type { H3Event } from "h3";
2
+ import { type QueryName, type QueryResult, type QueryVariables } from "#graphql/registry";
3
+ import type { IsEmptyObject } from "../../utils/helpers.js";
4
+ export declare function useGraphQLQuery<N extends QueryName>(event: H3Event, operationName: N, ...args: IsEmptyObject<QueryVariables<N>> extends true ? [variables?: QueryVariables<N>, headers?: HeadersInit] : [variables: QueryVariables<N>, headers?: HeadersInit]): Promise<QueryResult<N>>;
@@ -0,0 +1,7 @@
1
+ import { getGraphQLClient } from "./graphql-client.js";
2
+ import { queries } from "#graphql/registry";
3
+ export async function useGraphQLQuery(event, operationName, ...args) {
4
+ const client = getGraphQLClient(event);
5
+ const [variables, headers] = args;
6
+ return client.request(queries[operationName], variables, headers);
7
+ }
@@ -1,8 +1,10 @@
1
1
  import type { GraphQLClient } from "graphql-request";
2
+ import type { Client as SSEClient } from "graphql-sse";
2
3
 
3
4
  declare module "#app" {
4
5
  interface NuxtApp {
5
- $graphql: GraphQLClient;
6
+ $graphql: () => GraphQLClient;
7
+ $graphqlSSE: () => SSEClient;
6
8
  }
7
9
  }
8
10
 
@@ -13,6 +13,7 @@ function getYoga() {
13
13
  graphqlEndpoint: "{{endpoint}}",
14
14
  fetchAPI: globalThis,
15
15
  graphiql: process.env.NODE_ENV !== "production",
16
+ subscriptions: { protocol: "SSE" },
16
17
  });
17
18
  }
18
19
  return yoga;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lewebsimple/nuxt-graphql",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Opinionated Nuxt module for using GraphQL",
5
5
  "repository": "lewebsimple/nuxt-graphql",
6
6
  "license": "MIT",
@@ -22,6 +22,17 @@
22
22
  "files": [
23
23
  "dist"
24
24
  ],
25
+ "scripts": {
26
+ "prepack": "nuxt-module-build build",
27
+ "dev": "npm run dev:prepare && nuxi dev playground",
28
+ "dev:build": "nuxi build playground",
29
+ "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
30
+ "release": "npm run lint && npm run test && npm run prepack && changelogen --release --push && npm publish",
31
+ "lint": "eslint .",
32
+ "test": "vitest run",
33
+ "test:watch": "vitest watch",
34
+ "test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
35
+ },
25
36
  "dependencies": {
26
37
  "@graphql-codegen/cli": "^5.0.7",
27
38
  "@graphql-codegen/typed-document-node": "^5.1.2",
@@ -31,6 +42,7 @@
31
42
  "@nuxt/kit": "^4.2.2",
32
43
  "graphql": "^16.12.0",
33
44
  "graphql-request": "^7.4.0",
45
+ "graphql-sse": "^2.6.0",
34
46
  "graphql-yoga": "^5.18.0",
35
47
  "jiti": "^2.6.1",
36
48
  "ohash": "^2.0.11",
@@ -58,15 +70,5 @@
58
70
  "types": {
59
71
  "chore": false
60
72
  }
61
- },
62
- "scripts": {
63
- "dev": "npm run dev:prepare && nuxi dev playground",
64
- "dev:build": "nuxi build playground",
65
- "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
66
- "release": "npm run lint && npm run test && npm run prepack && changelogen --release --push && npm publish",
67
- "lint": "eslint .",
68
- "test": "vitest run",
69
- "test:watch": "vitest watch",
70
- "test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
71
73
  }
72
74
  }
@@ -1,4 +0,0 @@
1
- import type { TypedDocumentNode } from "@graphql-typed-document-node/core";
2
- export declare function useGraphQL(): {
3
- request: <TResult, TVariables extends Record<string, unknown> | undefined>(document: TypedDocumentNode<TResult, TVariables>, variables?: TVariables) => Promise<TResult>;
4
- };
@@ -1,8 +0,0 @@
1
- import { useNuxtApp } from "#imports";
2
- export function useGraphQL() {
3
- const { $graphql } = useNuxtApp();
4
- async function request(document, variables) {
5
- return $graphql.request({ document, variables });
6
- }
7
- return { request };
8
- }