-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: client options, client context, server utils (#45)
* implement graphqlMiddleware.clientOptions with client context * use client context in server options * fix generated types, create server utils * move shared composable helpers to helpers folder * fix tests * clean up imports * Make client context in server options partial * add docs for server utils * update vitepress
- Loading branch information
Showing
51 changed files
with
13,610 additions
and
8,461 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,3 +52,4 @@ Temporary Items | |
.apdisk | ||
|
||
cypress/videos/ | ||
cypress/screenshots |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
describe('The clientOptions', () => { | ||
it('are working correctly with SSR', () => { | ||
cy.visit('/de') | ||
cy.get('#nuxt-language').first().should('have.text', 'de') | ||
cy.get('#response-language').first().should('have.text', 'de') | ||
}) | ||
|
||
it('are working correctly with SPA', () => { | ||
cy.visit('/') | ||
cy.get('#link-client-options').click() | ||
cy.get('#nuxt-language').first().should('have.text', 'de') | ||
cy.get('#response-language').first().should('have.text', 'de') | ||
|
||
cy.get('#lang-switch-fr').click() | ||
|
||
cy.get('#nuxt-language').first().should('have.text', 'fr') | ||
cy.get('#response-language').first().should('have.text', 'fr') | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
# Client Options | ||
|
||
`nuxt-graphql-middleware` will look for a file called | ||
`graphqlMiddleware.clientOptions.ts` in your app dir. This file can export so | ||
called "client options" which are used when _making a request to the GraphQL | ||
middleware_. | ||
|
||
::: warning | ||
|
||
Note that the client options are only used in a **Nuxt app context** - they are | ||
not used when using `useGraphqlQuery` or other utils in a **Nitro context** such | ||
as event handlers. | ||
|
||
::: | ||
|
||
## Defining Client Options | ||
|
||
When using a composable such as `useGraphqlQuery`, behind the scenes it will use | ||
`$fetch` to make a request to the GraphQL middleware server route. Sometimes | ||
it's useful to pass some additional context with this request that can then be | ||
used on the server. | ||
|
||
Similar to [serverOptions](/configuration/server-options), you can create a file | ||
called `graphqlMiddleware.clientOptions.ts` in your `app` directory (usually | ||
`<rootDir>/app`). | ||
|
||
::: code-group | ||
|
||
```typescript [~/app/graphqlMiddleware.clientOptions.ts] | ||
import { defineGraphqlClientOptions } from 'nuxt-graphql-middleware/dist/runtime/clientOptions' | ||
|
||
export default defineGraphqlClientOptions({}) | ||
``` | ||
|
||
::: | ||
|
||
## Defining Client Context | ||
|
||
Implement the `buildClientContext()` method to return an object with string | ||
values. | ||
|
||
::: code-group | ||
|
||
```typescript [~/app/graphqlMiddleware.clientOptions.ts] | ||
import { defineGraphqlClientOptions } from 'nuxt-graphql-middleware/dist/runtime/clientOptions' | ||
|
||
export default defineGraphqlClientOptions<{ | ||
language: string | ||
country: string | ||
}>({ | ||
buildClientContext() { | ||
const language = useCurrentLanguage() | ||
const country = useCurrentCountry() | ||
return { | ||
language: language.value, | ||
country: country.value, | ||
} | ||
}, | ||
}) | ||
``` | ||
|
||
::: | ||
|
||
::: info | ||
|
||
By passing a generic in `defineGraphqlClientOptions` you can define the type of | ||
your context object. | ||
|
||
::: | ||
|
||
Now everytime a request to the middleware is made with a composable such as | ||
`useGraphqlQuery`, the composable will call the `buildClientContext` method to | ||
get the current context. It then maps each property of the returned object to a | ||
query parameter while prefixing the property to prevent collisions with | ||
potential query parameters from GraphQL variables. | ||
|
||
So for example, when making a GraphQL query like so: | ||
|
||
```typescript | ||
const data = await useGraphqlQuery('loadProduct', { | ||
id: '123', | ||
}) | ||
``` | ||
|
||
The composable will make a fetch request to this URL. | ||
|
||
`/api/graphql_middleware/loadProduct?id=123&__gqlc_language=en&__gqlc_country=US` | ||
|
||
Both the `language` and `country` properties we returned in the object in | ||
`buildClientContext()` are appended as prefixed query parameters. | ||
|
||
## Using Client Context | ||
|
||
On the server you can then access this client context from within all | ||
[serverOptions](/configuration/server-options) methods: | ||
|
||
::: code-group | ||
|
||
```typescript [~/server/graphqlMiddleware.serverOptions.ts] | ||
import { defineGraphqlServerOptions } from 'nuxt-graphql-middleware/dist/runtime/serverOptions' | ||
|
||
export default defineGraphqlServerOptions({ | ||
graphqlEndpoint(event, operation, operationName, context) { | ||
// Use the language from the client context. | ||
const language = context?.client?.language || 'en' | ||
return `http://backend_server/${language}/graphql` | ||
}, | ||
|
||
serverFetchOptions: function (event, _operation, operationName, context) { | ||
// Pass the current country as a header when making a request to the | ||
// GraphQL server. | ||
return { | ||
headers: { | ||
'x-current-country': context.client?.country || 'US', | ||
}, | ||
} | ||
}, | ||
}) | ||
``` | ||
|
||
::: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# useGraphqlMutation() | ||
|
||
::: warning | ||
|
||
While this util has the same name as the composable it's a completely separate | ||
method. In particular, it **does not use** any state set using the | ||
`useGraphqlState` composable or the `graphqlMiddleware.clientOptions.ts` file. | ||
|
||
::: | ||
|
||
This util is auto-imported and available in a server (nitro) context. It's | ||
function signature is identical to the | ||
[useGraphqlMutation composable](/composables/useGraphqlMutation) composable | ||
available in a Nuxt app context. | ||
|
||
## Example | ||
|
||
```typescript | ||
import { getQuery } from 'h3' | ||
|
||
export default defineEventHandler(async (event) => { | ||
const id = getQuery(event).id | ||
const data = await useGraphqlMutation('trackVisit', { | ||
id, | ||
}) | ||
return data.data.success | ||
}) | ||
``` | ||
|
||
## Client Context | ||
|
||
Since the client context returned in | ||
[buildClientContext()](/configuration/client-options) is only available in a | ||
Nuxt app context you can manually pass the context when making a mutation with | ||
the server util: | ||
|
||
```typescript | ||
import { getQuery } from 'h3' | ||
|
||
export default defineEventHandler(async (event) => { | ||
const id = getQuery(event).id | ||
const data = await useGraphqlMutation({ | ||
name: 'trackVisit', | ||
variables: { | ||
id, | ||
}, | ||
clientContext: { | ||
language: 'de', | ||
}, | ||
}) | ||
return data.data.success | ||
}) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# useGraphqlQuery() | ||
|
||
::: warning | ||
|
||
While this util has the same name as the composable it's a completely separate | ||
method. In particular, it **does not use** any state set using the | ||
`useGraphqlState` composable or the `graphqlMiddleware.clientOptions.ts` file. | ||
|
||
::: | ||
|
||
This util is auto-imported and available in a server (nitro) context. It's | ||
function signature is identical to the | ||
[useGraphqlQuery composable](/composables/useGraphqlQuery) composable available | ||
in a Nuxt app context. | ||
|
||
## Example | ||
|
||
```typescript | ||
export default defineEventHandler(async () => { | ||
const data = await useGraphqlQuery('users') | ||
return data.data.users.map((v) => v.email) | ||
}) | ||
``` | ||
|
||
## Client Context | ||
|
||
Since the client context returned in | ||
[buildClientContext()](/configuration/client-options) is only available in a | ||
Nuxt app context you can manually pass the context when making a query with the | ||
server util: | ||
|
||
```typescript | ||
export default defineEventHandler(async () => { | ||
const data = await useGraphqlQuery({ | ||
name: 'users', | ||
clientContext: { | ||
language: 'de', | ||
}, | ||
}) | ||
return data.data.users.map((v) => v.email) | ||
}) | ||
``` |
Oops, something went wrong.