├── packages ├── urql │ ├── .yarnrc │ ├── src │ │ ├── logger.ts │ │ ├── types.ts │ │ ├── index.ts │ │ └── plugin.ts │ ├── index.cjs │ ├── build.config.ts │ ├── README.md │ └── package.json └── codegen │ ├── .yarnrc │ ├── src │ ├── logger.ts │ ├── types.ts │ └── index.ts │ ├── index.cjs │ ├── build.config.ts │ ├── package.json │ └── README.md ├── examples ├── minimal │ ├── .yarnrc │ ├── server │ │ ├── types │ │ │ ├── index.ts │ │ │ └── hello.ts │ │ ├── schema-loader.js │ │ ├── schema.ts │ │ └── api │ │ │ └── graphql.ts │ ├── graphql │ │ └── hello.query.graphql │ ├── .gitignore │ ├── tsconfig.schema.json │ ├── codegen.yml │ ├── generated │ │ ├── schema.graphql │ │ ├── schema.d.ts │ │ └── urql-introspection.json │ ├── tsconfig.json │ ├── pages │ │ └── index.vue │ ├── nuxt.config.ts │ ├── README.md │ ├── package.json │ └── composables │ │ └── urql-operations.ts └── prisma │ ├── .gitignore │ ├── app.vue │ ├── tsconfig.json │ ├── nuxt.config.ts │ ├── package.json │ └── README.md ├── .gitignore ├── tsconfig.json ├── package.json └── README.md /packages/urql/.yarnrc: -------------------------------------------------------------------------------- 1 | version-tag-prefix urql-v 2 | -------------------------------------------------------------------------------- /examples/minimal/.yarnrc: -------------------------------------------------------------------------------- 1 | version-tag-prefix minimal-v 2 | -------------------------------------------------------------------------------- /packages/codegen/.yarnrc: -------------------------------------------------------------------------------- 1 | version-tag-prefix codegen-v 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .nuxt 2 | .output 3 | dist 4 | node_modules 5 | *.log 6 | -------------------------------------------------------------------------------- /examples/minimal/server/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./hello"; 2 | -------------------------------------------------------------------------------- /examples/minimal/graphql/hello.query.graphql: -------------------------------------------------------------------------------- 1 | query Hello { 2 | hello 3 | } 4 | -------------------------------------------------------------------------------- /examples/minimal/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .nuxt 4 | nuxt.d.ts 5 | .output 6 | -------------------------------------------------------------------------------- /examples/prisma/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .nuxt 4 | nuxt.d.ts 5 | .output 6 | .env -------------------------------------------------------------------------------- /examples/prisma/app.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /packages/urql/src/logger.ts: -------------------------------------------------------------------------------- 1 | import consola from "consola"; 2 | 3 | export default consola.withScope("@nuxt3-graphql/urql"); 4 | -------------------------------------------------------------------------------- /examples/prisma/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://v3.nuxtjs.org/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | -------------------------------------------------------------------------------- /packages/codegen/src/logger.ts: -------------------------------------------------------------------------------- 1 | import consola from "consola"; 2 | 3 | export default consola.withScope("@nuxt3-graphql/codegen"); 4 | -------------------------------------------------------------------------------- /examples/minimal/tsconfig.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | }, 5 | "include": [ 6 | "server/**/*.ts" 7 | ] 8 | } -------------------------------------------------------------------------------- /examples/minimal/codegen.yml: -------------------------------------------------------------------------------- 1 | schema: server/schema-loader.js 2 | documents: graphql/**/*.graphql 3 | generates: 4 | generated/schema.d.ts: 5 | plugins: 6 | - typescript 7 | -------------------------------------------------------------------------------- /examples/minimal/generated/schema.graphql: -------------------------------------------------------------------------------- 1 | ### This file was generated by Nexus Schema 2 | ### Do not make changes to this file directly 3 | 4 | 5 | type Query { 6 | hello: String! 7 | } 8 | -------------------------------------------------------------------------------- /examples/prisma/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | import { defineNuxtConfig } from 'nuxt3' 2 | 3 | // https://v3.nuxtjs.org/docs/directory-structure/nuxt.config 4 | export default defineNuxtConfig({ 5 | 6 | }) 7 | -------------------------------------------------------------------------------- /packages/codegen/index.cjs: -------------------------------------------------------------------------------- 1 | module.exports = function (...args) { 2 | return import("./dist/index.mjs").then((m) => m.default.call(this, ...args)); 3 | }; 4 | 5 | module.exports.meta = require("./package.json"); 6 | -------------------------------------------------------------------------------- /packages/urql/index.cjs: -------------------------------------------------------------------------------- 1 | module.exports = function (...args) { 2 | return import("./dist/index.mjs").then((m) => m.default.call(this, ...args)); 3 | }; 4 | 5 | module.exports.meta = require("./package.json"); 6 | -------------------------------------------------------------------------------- /examples/minimal/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://v3.nuxtjs.org/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json", 4 | "compilerOptions": { 5 | "types": [ 6 | "@nuxt3-graphql/urql" 7 | ] 8 | } 9 | } -------------------------------------------------------------------------------- /examples/minimal/server/schema-loader.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/no-var-requires 2 | require("ts-node").register({ 3 | project: "tsconfig.schema.json", 4 | transpileOnly: true, 5 | }); 6 | module.exports = require("./schema"); 7 | -------------------------------------------------------------------------------- /examples/prisma/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "nuxi dev", 5 | "build": "nuxi build", 6 | "start": "node .output/server/index.mjs" 7 | }, 8 | "devDependencies": { 9 | "nuxt3": "latest" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/minimal/server/types/hello.ts: -------------------------------------------------------------------------------- 1 | import { extendType } from "nexus"; 2 | 3 | export const HelloQuery = extendType({ 4 | type: "Query", 5 | definition(t) { 6 | t.nonNull.field("hello", { 7 | type: "String", 8 | resolve: () => `Hello Nexus!`, 9 | }); 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /examples/minimal/pages/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 13 | -------------------------------------------------------------------------------- /examples/minimal/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | import { defineNuxtConfig } from "nuxt3"; 2 | 3 | export default defineNuxtConfig({ 4 | buildModules: ["@nuxt3-graphql/urql", "@nuxt3-graphql/codegen"], 5 | urql: { 6 | url: process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}/api/graphql` : "http://localhost:3000/api/graphql", 7 | }, 8 | }); 9 | -------------------------------------------------------------------------------- /examples/minimal/server/schema.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from "path"; 2 | import { makeSchema } from "nexus"; 3 | import * as types from "./types"; 4 | 5 | export const schema = makeSchema({ 6 | types, 7 | outputs: { 8 | schema: resolve(process.cwd(), "generated/schema.graphql"), 9 | }, 10 | shouldGenerateArtifacts: process.env.NODE_ENV === "development", 11 | }); 12 | -------------------------------------------------------------------------------- /packages/codegen/build.config.ts: -------------------------------------------------------------------------------- 1 | import { defineBuildConfig } from "unbuild"; 2 | 3 | export default defineBuildConfig({ 4 | declaration: true, 5 | emitCJS: false, 6 | entries: [{ input: "./src/index" }], 7 | externals: [ 8 | "@graphql-codegen/cli", 9 | "@graphql-codegen/plugin-helpers", 10 | "@nuxt/kit", 11 | "@nuxt/schema", 12 | "consola", 13 | "graphql", 14 | ], 15 | }); 16 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "ESNext", 5 | "moduleResolution": "node", 6 | "outDir": "dist", 7 | "declaration": true, 8 | "esModuleInterop": true, 9 | "strict": true, 10 | "resolveJsonModule": true, 11 | "skipLibCheck": true, 12 | "types": [ 13 | "@nuxt/types" 14 | ] 15 | }, 16 | "exclude": [ 17 | "**/dist/**", 18 | "**/.output/**" 19 | ] 20 | } -------------------------------------------------------------------------------- /packages/codegen/src/types.ts: -------------------------------------------------------------------------------- 1 | import type { Types } from "@graphql-codegen/plugin-helpers"; 2 | 3 | export type NuxtCodegenConfig = Types.Config & {}; 4 | 5 | type NuxtHookResult = Promise | void; 6 | 7 | declare module "@nuxt/schema" { 8 | interface NuxtConfig { 9 | codegen?: NuxtCodegenConfig; 10 | } 11 | interface NuxtOptions { 12 | codegen?: NuxtCodegenConfig; 13 | } 14 | interface NuxtHooks { 15 | "codegen:config": (config: NuxtCodegenConfig) => NuxtHookResult; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/urql/src/types.ts: -------------------------------------------------------------------------------- 1 | import type { Ref } from "vue"; 2 | import type { Client } from "@urql/vue"; 3 | 4 | export type NuxtUrqlOptions = { 5 | url: string; 6 | }; 7 | 8 | declare module "@nuxt/schema" { 9 | interface NuxtConfig { 10 | urql?: NuxtUrqlOptions; 11 | } 12 | interface NuxtOptions { 13 | urql?: NuxtUrqlOptions; 14 | } 15 | } 16 | 17 | // @ts-expect-error: #app resolved by Nuxt3 18 | declare module "#app" { 19 | interface NuxtApp { 20 | $urql: Ref; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/urql/build.config.ts: -------------------------------------------------------------------------------- 1 | import { defineBuildConfig } from "unbuild"; 2 | 3 | export default defineBuildConfig({ 4 | declaration: true, 5 | emitCJS: false, 6 | entries: [{ input: "./src/index" }, { input: "./src/plugin", declaration: false }], 7 | externals: [ 8 | "@nuxt/kit", 9 | "@nuxt/schema", 10 | "@urql/devtools", 11 | "@urql/exchange-graphcache", 12 | "@urql/vue", 13 | "pathe", 14 | "vue", 15 | "#app", 16 | "#build", 17 | "#build/urql.options.mjs", 18 | ], 19 | }); 20 | -------------------------------------------------------------------------------- /examples/prisma/README.md: -------------------------------------------------------------------------------- 1 | # Nuxt 3 Minimal Starter 2 | 3 | We recommend to look at the [documentation](https://v3.nuxtjs.org). 4 | 5 | ## Setup 6 | 7 | Make sure to install the dependencies 8 | 9 | ```bash 10 | yarn install 11 | ``` 12 | 13 | ## Development 14 | 15 | Start the development server on http://localhost:3000 16 | 17 | ```bash 18 | yarn dev 19 | ``` 20 | 21 | ## Production 22 | 23 | Build the application for production: 24 | 25 | ```bash 26 | yarn build 27 | ``` 28 | 29 | Checkout the [deployment documentation](https://v3.nuxtjs.org/docs/deployment). -------------------------------------------------------------------------------- /examples/minimal/README.md: -------------------------------------------------------------------------------- 1 | # Nuxt3 GraphQL minimal starter 2 | 3 | We recommend to look at the [documentation](https://v3.nuxtjs.org). 4 | 5 | ## Setup 6 | 7 | Make sure to install the dependencies 8 | 9 | ```bash 10 | yarn install 11 | ``` 12 | 13 | ## Development 14 | 15 | Start the development server on http://localhost:3000 16 | 17 | ```bash 18 | yarn dev 19 | ``` 20 | 21 | ## Production 22 | 23 | Build the application for production: 24 | 25 | ```bash 26 | yarn build 27 | ``` 28 | 29 | Checkout the [deployment documentation](https://v3.nuxtjs.org/docs/deployment). -------------------------------------------------------------------------------- /examples/minimal/generated/schema.d.ts: -------------------------------------------------------------------------------- 1 | export type Maybe = T | null; 2 | export type InputMaybe = Maybe; 3 | export type Exact = { [K in keyof T]: T[K] }; 4 | export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; 5 | export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; 6 | /** All built-in and custom scalars, mapped to their actual values */ 7 | export type Scalars = { 8 | ID: string; 9 | String: string; 10 | Boolean: boolean; 11 | Int: number; 12 | Float: number; 13 | }; 14 | 15 | export type Query = { 16 | __typename?: "Query"; 17 | hello: Scalars["String"]; 18 | }; 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt3-graphql-monorepo", 3 | "license": "MIT", 4 | "author": "Pascal Martineau ", 5 | "private": true, 6 | "workspaces": [ 7 | "packages/*", 8 | "examples/*" 9 | ], 10 | "scripts": { 11 | "build": "yarn workspaces run build", 12 | "clean": "rm -rf ./node_modules ./*/*/node_modules ./*/*/dist ./examples/*/.nuxt ./examples/*/.output" 13 | }, 14 | "devDependencies": { 15 | "@lewebsimple/eslint-config": "^0.3.0", 16 | "@nuxt/types": "^2.15.8", 17 | "esbuild": "^0.14.5", 18 | "eslint": "^8.4.1", 19 | "unbuild": "^0.5.11" 20 | }, 21 | "eslintConfig": { 22 | "extends": "@lewebsimple/eslint-config/vue3" 23 | } 24 | } -------------------------------------------------------------------------------- /examples/minimal/generated/urql-introspection.json: -------------------------------------------------------------------------------- 1 | { 2 | "__schema": { 3 | "queryType": { 4 | "name": "Query" 5 | }, 6 | "mutationType": null, 7 | "subscriptionType": null, 8 | "types": [ 9 | { 10 | "kind": "OBJECT", 11 | "name": "Query", 12 | "fields": [ 13 | { 14 | "name": "hello", 15 | "type": { 16 | "kind": "NON_NULL", 17 | "ofType": { 18 | "kind": "SCALAR", 19 | "name": "Any" 20 | } 21 | }, 22 | "args": [] 23 | } 24 | ], 25 | "interfaces": [] 26 | }, 27 | { 28 | "kind": "SCALAR", 29 | "name": "Any" 30 | } 31 | ], 32 | "directives": [] 33 | } 34 | } -------------------------------------------------------------------------------- /examples/minimal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nuxt3-graphql/minimal", 3 | "version": "0.5.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "nuxi dev", 7 | "build": "nuxi build", 8 | "start": "node .output/server/index.mjs", 9 | "lint": "eslint --ext .js,.ts,.vue --fix .", 10 | "preversion": "yarn lint", 11 | "version": "git add -A .", 12 | "postversion": "git push && git push --tags" 13 | }, 14 | "devDependencies": { 15 | "@envelop/core": "^1.6.5", 16 | "@graphql-codegen/typescript": "^2.4.1", 17 | "@graphql-codegen/typescript-operations": "^2.2.1", 18 | "@graphql-codegen/typescript-vue-urql": "^2.2.1", 19 | "@graphql-codegen/urql-introspection": "^2.1.0", 20 | "@nuxt3-graphql/codegen": "link:../../packages/codegen", 21 | "@nuxt3-graphql/urql": "link:../../packages/urql", 22 | "@urql/exchange-graphcache": "^4.3.6", 23 | "@urql/vue": "^0.6.1", 24 | "graphql": "^15", 25 | "nexus": "^1.1.0", 26 | "nuxt3": "latest" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nuxt3-graphql 2 | 3 | This package provides some useful modules for building fullstack GraphQL applications with Nuxt3. 4 | 5 | ## ⚠️ Deprecation warning 6 | 7 | This project is **deprecated** in favour of [**nuxt-module-codegen**](https://github.com/lewebsimple/nuxt-graphql-codegen/) which based on the latest Nuxt module starter template. 8 | 9 | As for `@nuxt3-graphql/urql`, it is being abandoned for now. 10 | 11 | ## Modules 12 | 13 | - [@nuxt3-graphql/codegen](packages/codegen) : GraphQL code generation based on [@graphql-codegen/cli](https://www.graphql-code-generator.com/) 14 | - [@nuxt3-graphql/urql](packages/urql) : GraphQL client based on [@urql/vue](https://formidable.com/open-source/urql/docs/basics/vue/) 15 | 16 | ## Examples 17 | 18 | - [examples/minimal](examples/minimal) : Minimal showcase of the various nuxt3-graphql modules 19 | 20 | ## Credits 21 | 22 | - Based on a project by [@bicouy0](https://github.com/bicouy0/nuxt3-urql) 23 | - Nuxt module structure [nuxt3-supabase](https://github.com/wobsoriano/nuxt3-supabase) 24 | -------------------------------------------------------------------------------- /examples/minimal/server/api/graphql.ts: -------------------------------------------------------------------------------- 1 | import { IncomingMessage, ServerResponse } from "http"; 2 | import { useBody, useQuery } from "h3"; 3 | import { envelop, useSchema } from "@envelop/core"; 4 | import { schema } from "../schema"; 5 | 6 | const getEnveloped = envelop({ 7 | plugins: [useSchema(schema)], 8 | }); 9 | 10 | export default async (req: IncomingMessage, res: ServerResponse) => { 11 | const { parse, validate, contextFactory, execute, schema } = getEnveloped({ req }); 12 | 13 | // Parse query / variables from incoming request 14 | const { query, variables } = req.method === "GET" ? useQuery(req) : await useBody(req); 15 | const document = parse(query); 16 | 17 | // Validate GraphQL document against schema 18 | const validationErrors = validate(schema, document); 19 | if (validationErrors.length > 0) { 20 | return { errors: validationErrors }; 21 | } 22 | 23 | // Return result from execution 24 | const context = await contextFactory(); 25 | const result = await execute({ 26 | document, 27 | schema, 28 | variableValues: variables, 29 | contextValue: context, 30 | }); 31 | 32 | return result; 33 | }; 34 | -------------------------------------------------------------------------------- /packages/urql/README.md: -------------------------------------------------------------------------------- 1 | # @nuxt3-graphql/urql 2 | 3 | [@urql/vue](https://formidable.com/open-source/urql/docs/basics/vue/) for Nuxt.js! ⚡️ 4 | 5 | ## Features 6 | 7 | - Provide urql client to your application 8 | - Configurable URL in `nuxt.config.ts` 9 | - SSR support with [ssrExchange](https://formidable.com/open-source/urql/docs/advanced/server-side-rendering/#the-ssr-exchange) 10 | 11 | # Install 12 | 13 | ```bash 14 | yarn add -D @nuxt3-graphql/urql @urql/vue graphql 15 | # npm i -D @nuxt3-graphql/urql @urql/vue graphql 16 | ``` 17 | 18 | ## Usage 19 | 20 | Within your `nuxt.config.js` add the following: 21 | 22 | ```js 23 | import { defineNuxtConfig } from "nuxt3"; 24 | 25 | export default defineNuxtConfig({ 26 | buildModules: [ 27 | "@nuxt3-graphql/urql", 28 | ], 29 | urql: { 30 | url: "https://rickandmortyapi.com/graphql/" 31 | }, 32 | }); 33 | ``` 34 | 35 | Refer to the `@urql/vue` [documentation](https://formidable.com/open-source/urql/docs/basics/vue/) for more information. 36 | 37 | ## Typescript 38 | 39 | For Nuxt config typescript support, add the following to `tsconfig.json`: 40 | 41 | ```json 42 | 43 | { 44 | "compilerOptions": { 45 | "types": [ 46 | "@nuxt3-graphql/urql" 47 | ] 48 | } 49 | } 50 | ``` 51 | 52 | ## Roadmap 53 | 54 | - [ ] Integration with [GraphQL Code Generator](https://www.graphql-code-generator.com/) 55 | - [ ] Normalized caching with [Graphcache](https://formidable.com/open-source/urql/docs/graphcache/normalized-caching/) 56 | -------------------------------------------------------------------------------- /packages/codegen/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nuxt3-graphql/codegen", 3 | "version": "0.5.0", 4 | "description": "GraphQL Code Generator for Nuxt.js! ⚡️", 5 | "keywords": [ 6 | "nuxt", 7 | "vue", 8 | "graphql", 9 | "codegen" 10 | ], 11 | "license": "MIT", 12 | "author": "Pascal Martineau ", 13 | "bugs": { 14 | "url": "https://github.com/lewebsimple/nuxt3-graphql/issues" 15 | }, 16 | "homepage": "https://github.com/lewebsimple/nuxt3-graphql/tree/main/packages/codegen#readme", 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/lewebsimple/nuxt3-graphql.git" 20 | }, 21 | "exports": { 22 | ".": { 23 | "require": "./index.cjs", 24 | "import": "./dist/index.mjs", 25 | "types": "./dist/index.d.ts" 26 | } 27 | }, 28 | "main": "./index.cjs", 29 | "module": "./dist/index.mjs", 30 | "types": "./dist/index.d.ts", 31 | "files": [ 32 | "dist", 33 | "index.cjs" 34 | ], 35 | "publishConfig": { 36 | "access": "public" 37 | }, 38 | "scripts": { 39 | "build": "unbuild", 40 | "dev": "unbuild --stub", 41 | "lint": "eslint --ext .js,.ts,.vue --fix .", 42 | "prepare": "yarn build", 43 | "prepublishOnly": "yarn lint", 44 | "preversion": "yarn lint", 45 | "version": "git add -A src", 46 | "postversion": "git push && git push --tags" 47 | }, 48 | "devDependencies": { 49 | "@graphql-codegen/cli": "^2.3.0", 50 | "@nuxt/kit": "latest", 51 | "graphql": "^15" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/urql/src/index.ts: -------------------------------------------------------------------------------- 1 | import { defineNuxtModule, addPluginTemplate, addTemplate } from "@nuxt/kit"; 2 | import { dirname, resolve } from "pathe"; 3 | import { fileURLToPath } from "url"; 4 | import type { NuxtUrqlOptions } from "./types"; 5 | 6 | export * from "./types"; 7 | 8 | export default defineNuxtModule((nuxt) => ({ 9 | name: "urql", 10 | configKey: "urql", 11 | setup(options: NuxtUrqlOptions) { 12 | const __dirname__ = dirname(fileURLToPath(import.meta.url)); 13 | 14 | // Generate operations and introspection if @nuxt3-graphql/codegen is used 15 | if (nuxt.options.buildModules.includes("@nuxt3-graphql/codegen")) { 16 | // @ts-expect-error Hook only present when @nuxt3-graphql/codegen types are included 17 | nuxt.hook("codegen:config", (config) => { 18 | config.generates["composables/urql-operations.ts"] = { 19 | config: { 20 | documentMode: "documentNode", 21 | }, 22 | plugins: ["typescript", "typescript-operations", "typescript-vue-urql"], 23 | }; 24 | config.generates["generated/urql-introspection.json"] = { 25 | plugins: ["urql-introspection"], 26 | }; 27 | }); 28 | } 29 | addTemplate({ 30 | filename: "urql.options.mjs", 31 | getContents: () => "export default " + JSON.stringify(options), 32 | }); 33 | 34 | addPluginTemplate({ 35 | src: resolve(__dirname__, "./plugin.mjs"), 36 | }); 37 | 38 | nuxt.options.build.transpile.push("@urql/vue"); 39 | }, 40 | })); 41 | -------------------------------------------------------------------------------- /examples/minimal/composables/urql-operations.ts: -------------------------------------------------------------------------------- 1 | import { DocumentNode } from "graphql"; 2 | import * as Urql from "@urql/vue"; 3 | export type Maybe = T | null; 4 | export type InputMaybe = Maybe; 5 | export type Exact = { [K in keyof T]: T[K] }; 6 | export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; 7 | export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; 8 | export type Omit = Pick>; 9 | /** All built-in and custom scalars, mapped to their actual values */ 10 | export type Scalars = { 11 | ID: string; 12 | String: string; 13 | Boolean: boolean; 14 | Int: number; 15 | Float: number; 16 | }; 17 | 18 | export type Query = { 19 | __typename?: "Query"; 20 | hello: Scalars["String"]; 21 | }; 22 | 23 | export type HelloQueryVariables = Exact<{ [key: string]: never }>; 24 | 25 | export type HelloQuery = { __typename?: "Query"; hello: string }; 26 | 27 | export const HelloDocument = { 28 | kind: "Document", 29 | definitions: [ 30 | { 31 | kind: "OperationDefinition", 32 | operation: "query", 33 | name: { kind: "Name", value: "Hello" }, 34 | selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "hello" } }] }, 35 | }, 36 | ], 37 | } as unknown as DocumentNode; 38 | 39 | export function useHelloQuery(options: Omit, "query"> = {}) { 40 | return Urql.useQuery({ query: HelloDocument, ...options }); 41 | } 42 | -------------------------------------------------------------------------------- /packages/codegen/README.md: -------------------------------------------------------------------------------- 1 | # @nuxt3-graphql/codegen 2 | 3 | [GraphQL Code Generator](https://www.graphql-code-generator.com/) for Nuxt.js! ⚡️ 4 | 5 | ## Features 6 | 7 | - Load your codegen config file from the root of your Nuxt3 project 8 | - Generate code from your GraphQL schema and operations on every build and in dev mode 9 | 10 | # Install 11 | 12 | ```bash 13 | yarn add -D @nuxt3-graphql/codegen @graphql-codegen/cli graphql 14 | # npm i -D @nuxt3-graphql/codegen @graphql-codegen/cli graphql 15 | ``` 16 | 17 | Create a [condegen config file](https://www.graphql-code-generator.com/docs/getting-started/codegen-config) either manually or with the wizard: 18 | 19 | ```bash 20 | yarn graphql-codegen init 21 | ``` 22 | 23 | ## Usage 24 | 25 | Within your `nuxt.config.js` add the following: 26 | 27 | ```js 28 | import { defineNuxtConfig } from "nuxt3"; 29 | 30 | export default defineNuxtConfig({ 31 | buildModules: [ 32 | "@nuxt3-graphql/codegen", 33 | ], 34 | codegen: { 35 | // Specify and/or override graphql-codegen configuration if needed 36 | }, 37 | }); 38 | ``` 39 | 40 | This will automativally generate the GraphQL code based on your codegen config file each time Nuxt builds your project (this also works in dev mode). 41 | 42 | Refer to the GraphQL Code Generator [documentation](https://www.graphql-code-generator.com/docs/getting-started/index/) for more information. 43 | 44 | ## Typescript 45 | 46 | For Nuxt config typescript support, add the following to `tsconfig.json`: 47 | 48 | ```json 49 | 50 | { 51 | "compilerOptions": { 52 | "types": [ 53 | "@nuxt3-graphql/codegen" 54 | ] 55 | } 56 | } 57 | ``` -------------------------------------------------------------------------------- /packages/urql/src/plugin.ts: -------------------------------------------------------------------------------- 1 | // @ts-expect-error #app resolved by Nuxt3 2 | import { defineNuxtPlugin, NuxtApp } from "#app"; 3 | // @ts-expect-error #build resolved by Nuxt3 4 | import nuxtUrqlOptions from "#build/urql.options.mjs"; 5 | import { 6 | createClient, 7 | ssrExchange, 8 | dedupExchange, 9 | cacheExchange as defaultCacheEchange, 10 | fetchExchange, 11 | } from "@urql/vue"; 12 | import { devtoolsExchange } from "@urql/devtools"; 13 | import { cacheExchange as normalizedCacheExchange } from "@urql/exchange-graphcache"; 14 | import { ref } from "vue"; 15 | 16 | export default defineNuxtPlugin((nuxt: NuxtApp) => { 17 | // SSR exchange 18 | const ssr = ssrExchange({ 19 | isClient: process.client, 20 | }); 21 | 22 | // Extract SSR payload once app is rendered 23 | if (process.server) { 24 | nuxt.hook("app:rendered", () => { 25 | nuxt.payload.data["urql"] = ssr.extractData(); 26 | }); 27 | } 28 | 29 | // Restore SSR payload once app is created 30 | if (process.client) { 31 | nuxt.hook("app:created", () => { 32 | ssr.restoreData(nuxt.payload.data["urql"]); 33 | }); 34 | } 35 | 36 | // Determine caching strategy 37 | const cacheExchange = defaultCacheEchange; 38 | // TODO: Load generated/urql-introspection.json somehow 39 | // cacheExchange = normalizedCacheExchange(); 40 | 41 | // Instantiate urql client 42 | const client = ref( 43 | createClient({ 44 | url: nuxtUrqlOptions.url, 45 | exchanges: [devtoolsExchange, dedupExchange, ssr, cacheExchange, fetchExchange], 46 | }), 47 | ); 48 | 49 | // Provide urql client to Nuxt / vueApp 50 | nuxt.provide("urql", client); 51 | nuxt.vueApp.provide("$urql", client); 52 | }); 53 | -------------------------------------------------------------------------------- /packages/urql/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nuxt3-graphql/urql", 3 | "version": "0.5.0", 4 | "description": "@urql/vue for Nuxt.js! ⚡️", 5 | "keywords": [ 6 | "nuxt", 7 | "vue", 8 | "graphql", 9 | "urql" 10 | ], 11 | "license": "MIT", 12 | "author": "Pascal Martineau ", 13 | "bugs": { 14 | "url": "https://github.com/lewebsimple/nuxt3-graphql/issues" 15 | }, 16 | "homepage": "https://github.com/lewebsimple/nuxt3-graphql/tree/main/packages/urql#readme", 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/lewebsimple/nuxt3-graphql.git" 20 | }, 21 | "exports": { 22 | ".": { 23 | "require": "./index.cjs", 24 | "import": "./dist/index.mjs", 25 | "types": "./dist/index.d.ts" 26 | }, 27 | "./plugin": { 28 | "import": "./dist/plugin.mjs" 29 | } 30 | }, 31 | "main": "./index.cjs", 32 | "module": "./dist/index.mjs", 33 | "types": "./dist/index.d.ts", 34 | "files": [ 35 | "dist", 36 | "index.cjs" 37 | ], 38 | "publishConfig": { 39 | "access": "public" 40 | }, 41 | "scripts": { 42 | "build": "unbuild", 43 | "dev": "unbuild --stub", 44 | "lint": "eslint --ext .js,.ts,.vue --fix .", 45 | "prepare": "yarn build", 46 | "prepublishOnly": "yarn lint", 47 | "preversion": "yarn lint", 48 | "version": "git add -A src", 49 | "postversion": "git push && git push --tags" 50 | }, 51 | "devDependencies": { 52 | "@nuxt/kit": "latest", 53 | "@urql/devtools": "^2.0.3", 54 | "@urql/exchange-graphcache": "^4.3.6", 55 | "@urql/vue": "^0.6.1", 56 | "graphql": "^15", 57 | "pathe": "^0.2.0", 58 | "vue": "^3" 59 | }, 60 | "peerDependencies": { 61 | "@urql/vue": "^0.6", 62 | "graphql": "^15" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /packages/codegen/src/index.ts: -------------------------------------------------------------------------------- 1 | import { defineNuxtModule } from "@nuxt/kit"; 2 | import logger from "./logger"; 3 | import { generate, loadCodegenConfig } from "@graphql-codegen/cli"; 4 | import type { NuxtCodegenConfig } from "./types"; 5 | 6 | export * from "./types"; 7 | 8 | export default defineNuxtModule((nuxt) => ({ 9 | name: "@nuxt3-graphql/codegen", 10 | configKey: "codegen", 11 | defaults: {}, 12 | async setup(userConfig, nuxt) { 13 | // Generate GraphQL typings using graphql-codegen 14 | async function codegenGenerateTypings() { 15 | const start = Date.now(); 16 | 17 | // Load config from codegen.yml 18 | const codegenConfig = await loadCodegenConfig({}); 19 | 20 | // Merge user config with codegen.yml 21 | const config = mergeDeep(userConfig, codegenConfig.config || {}); 22 | 23 | // Allow users to override config with hooks 24 | await nuxt.callHook("codegen:config", config); 25 | 26 | await generate(config, true); 27 | 28 | const time = Date.now() - start; 29 | logger.success(`GraphQL typings generated in ${time}ms`); 30 | } 31 | 32 | nuxt.hook("build:before", codegenGenerateTypings); 33 | nuxt.hook("builder:watch", codegenGenerateTypings); 34 | }, 35 | })); 36 | 37 | function isObject(item: any) { 38 | return item && typeof item === "object" && !Array.isArray(item); 39 | } 40 | 41 | function mergeDeep(target: any, source: any): any { 42 | const output = Object.assign({}, target); 43 | if (isObject(target) && isObject(source)) { 44 | Object.keys(source).forEach((key) => { 45 | if (isObject(source[key])) { 46 | if (!(key in target)) Object.assign(output, { [key]: source[key] }); 47 | else output[key] = mergeDeep(target[key], source[key]); 48 | } else { 49 | Object.assign(output, { [key]: source[key] }); 50 | } 51 | }); 52 | } 53 | return output; 54 | } 55 | --------------------------------------------------------------------------------