mirror of
https://github.com/graphql-hive/console
synced 2026-05-23 00:58:36 +00:00
docs: apollo client persisted documents (#5397)
This commit is contained in:
parent
70a8f0aff4
commit
9eab1af44f
1 changed files with 223 additions and 16 deletions
|
|
@ -59,17 +59,15 @@ flowchart LR
|
|||
document request" -->C
|
||||
```
|
||||
|
||||
## Create an App Deployment
|
||||
## Extracting Persisted Documents
|
||||
|
||||
To create an app deployment, you need to have
|
||||
[the Hive CLI installed](/docs/api-reference/cli#installation) and authenticated with your Hive
|
||||
target, on which you want to deploy your app.
|
||||
We need to extract the persisted documents from within our app. The method for doing this may vary
|
||||
depending on the tools you are using.
|
||||
|
||||
In addition you must have a JSON file containing a set of persisted documents generated by a tool
|
||||
such as
|
||||
[GraphQL Code Generator](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client#persisted-documents).
|
||||
The persisted documents must stored in a JSON file, which includes the documents along with their
|
||||
corresponding hashes. This JSON file will be uploaded to the Hive Registry.
|
||||
|
||||
```json filename="Example: persisted-operations.json"
|
||||
```json filename="persisted-operations.json"
|
||||
{
|
||||
"d9a00ec0c1ce": "query UsageEstimationQuery($input: UsageEstimationInput!) { __typename usageEstimation(input: $input) { __typename operations } }",
|
||||
"b8d98e796421": "mutation GenerateStripeLinkMutation($selector: OrganizationSelectorInput!) { __typename generateStripePortalLink(selector: $selector) }"
|
||||
|
|
@ -79,6 +77,77 @@ such as
|
|||
These persisted documents define all the possible operations that your app can execute against your
|
||||
GraphQL API.
|
||||
|
||||
As long as the app deployment using these persisted documents is active, any change of the GraphQL
|
||||
API that alters the GraphQL schema as used by any of the persisted documents would break that
|
||||
specific app version and therefore be an unsafe/breaking change.
|
||||
|
||||
<Tabs items={["GraphQL Code Generator", "Relay Compiler"]}>
|
||||
|
||||
<Tabs.Tab>
|
||||
|
||||
For GraphQL Code Generator, you can configure the client preset to generate the persisted document
|
||||
manifest.
|
||||
|
||||
```typescript filename="codegen.ts" {9-11}
|
||||
import { type CodegenConfig } from '@graphql-codegen/cli'
|
||||
|
||||
const config: CodegenConfig = {
|
||||
schema: 'schema.graphql',
|
||||
documents: ['src/**/*.tsx'],
|
||||
generates: {
|
||||
'./src/gql/': {
|
||||
preset: 'client',
|
||||
presetConfig: {
|
||||
persistedDocuments: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
After running the Relay Compiler, the file `persisted-documents.json` will be generated. This file
|
||||
can be used for creating a new app deployment on Hive.
|
||||
|
||||
For more information,
|
||||
[please refer to the GraphQL Code Generator documentation](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client#enable-persisted-documents).
|
||||
|
||||
</Tabs.Tab>
|
||||
|
||||
<Tabs.Tab>
|
||||
|
||||
For Relay Compiler, you can configure the compiler to generate the persisted document manifest.
|
||||
|
||||
```js filename="relay.config.js" {6-8}
|
||||
module.exports = {
|
||||
src: './src',
|
||||
language: 'javascript',
|
||||
schema: './data/schema.graphql',
|
||||
excludes: ['**/node_modules/**', '**/__mocks__/**', '**/__generated__/**'],
|
||||
persistConfig: {
|
||||
file: './persisted-documents.json'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
After running the Relay Compiler, the file `persisted-documents.json` will be generated. This file
|
||||
can be used for creating a new app deployment on Hive.
|
||||
|
||||
For more information,
|
||||
[please refer to the Relay documentation](https://relay.dev/docs/guides/persisted-queries/#local-persisted-queries).
|
||||
|
||||
</Tabs.Tab>
|
||||
|
||||
</Tabs>
|
||||
|
||||
## Create an App Deployment
|
||||
|
||||
To create an app deployment, you need to have
|
||||
[the Hive CLI installed](/docs/api-reference/cli#installation) and authenticated with your Hive
|
||||
target, on which you want to deploy your app.
|
||||
|
||||
The persisted documents define all the possible operations that your app can execute against your
|
||||
GraphQL API.
|
||||
|
||||
As long as the app is using these persisted documents is active, any change of the GraphQL API that
|
||||
alters the GraphQL schema as used by any of the persisted documents would break that specific app
|
||||
version and therefore be an unsafe/breaking change.
|
||||
|
|
@ -86,20 +155,19 @@ version and therefore be an unsafe/breaking change.
|
|||
> **Note:** The GraphQL operations being uploaded must pass validation against the target schema.
|
||||
> Otherwise, the app deployment creation will fail.
|
||||
|
||||
Once these pre-requisites are met, you can create an app deployment by running the following
|
||||
command:
|
||||
Once the pre-requisites are met, you can create an app deployment by running the following command.
|
||||
|
||||
```bash filename="Create an App Deployment via CLI"
|
||||
hive app:create --name "my-app" --version "1.0.0" persisted-operations.json
|
||||
hive app:create --name "my-app" --version "1.0.0" persisted-documents.json
|
||||
```
|
||||
|
||||
The parameters `--name` and `--version` are mandatory and uniquily identify your app deployment.
|
||||
|
||||
| Parameter | Description |
|
||||
| ------------------------ | ------------------------------------------------------------- |
|
||||
| `--name` | The name of the app deployment. |
|
||||
| `--version` | The version of the app deployment. |
|
||||
| `persistedDocumentsFile` | The path to the JSON file containing the persisted documents. |
|
||||
| Parameter | Description |
|
||||
| -------------------------- | ------------------------------------------------------------- |
|
||||
| `--name` | The name of the app deployment. |
|
||||
| `--version` | The version of the app deployment. |
|
||||
| `<persistedDocumentsFile>` | The path to the JSON file containing the persisted documents. |
|
||||
|
||||
An app deployment is uniquely identified by the combination of the `name` and `version` parameters
|
||||
for each target.
|
||||
|
|
@ -315,6 +383,10 @@ curl \
|
|||
Once you have the persisted documents available on your GraphQL server or Gateway, you can send a
|
||||
GraphQL request with the persisted document ID following the GraphQL over HTTP specification.
|
||||
|
||||
<Tabs items={["curl", "Apollo Client", "Urql", "Relay"]}>
|
||||
|
||||
<Tabs.Tab>
|
||||
|
||||
```text filename="GraphQL Request with Persisted Document"
|
||||
POST /graphql
|
||||
Content-Type: application/json
|
||||
|
|
@ -339,6 +411,141 @@ curl \
|
|||
http://localhost:4000/graphql
|
||||
```
|
||||
|
||||
</Tabs.Tab>
|
||||
|
||||
<Tabs.Tab>
|
||||
|
||||
The code demonstrates how to send a persisted document request using Apollo Client. Make sure to
|
||||
replace the placeholders with your actual values.
|
||||
|
||||
```typescript filename="Apollo Client Persisted Document Configuration"
|
||||
import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client'
|
||||
import { createPersistedQueryLink } from '@apollo/client/link/persisted-queries'
|
||||
|
||||
// replace <app_name>, <app_version>, and with your values
|
||||
const appVersionPrefix = '<app_name>~<app_version>~'
|
||||
|
||||
const persistedQueriesLink = createPersistedQueryLink({
|
||||
generateHash(document) {
|
||||
// GraphQL Code Generator Client Preset generates
|
||||
// the persisted document ID within the document node.
|
||||
// For other implementations return the hash prefixed with the app version.
|
||||
if (document?.['__metadata__']?.['hash']) {
|
||||
throw Error('Hash not available for document')
|
||||
}
|
||||
return appVersionPrefix + document['__metadata__']['hash']
|
||||
}
|
||||
})
|
||||
|
||||
const httpLink = new HttpLink({
|
||||
uri: '/graphql',
|
||||
fetch(url, init) {
|
||||
const parsedBody = JSON.parse(init!.body as string)
|
||||
return fetch(url, {
|
||||
...init,
|
||||
body: JSON.stringify({
|
||||
variables: parsedBody.variables,
|
||||
documentId: parsedBody.extensions.persistedQuery.sha256Hash,
|
||||
extensions: { ...parsedBody.extensions, persistedQuery: undefined }
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const client = new ApolloClient({
|
||||
cache: new InMemoryCache(),
|
||||
link: persistedQueriesLink.concat(httpLink)
|
||||
})
|
||||
```
|
||||
|
||||
| Parameter | Description |
|
||||
| --------------- | ---------------------------------- |
|
||||
| `<app_name>` | The name of the app deployment. |
|
||||
| `<app_version>` | The version of the app deployment. |
|
||||
|
||||
</Tabs.Tab>
|
||||
|
||||
<Tabs.Tab>
|
||||
|
||||
The code demonstrates how to send a persisted document request using Urql. Make sure to replace the
|
||||
placeholders with your actual values.
|
||||
|
||||
```typescript filename="Urql Persisted Document Configuration"
|
||||
import { createClient, fetchExchange, mapExchange } from 'urql'
|
||||
|
||||
// replace <app_name>, <app_version>, and with your values
|
||||
const appVersionPrefix = '<app_name>~<app_version>~'
|
||||
|
||||
const urqlClient = createClient({
|
||||
url: '/graphql',
|
||||
exchanges: [
|
||||
mapExchange({
|
||||
onOperation(op) {
|
||||
if (op.query?.['__metadata__']?.['hash']) {
|
||||
throw Error('Hash not available for document')
|
||||
}
|
||||
|
||||
return {
|
||||
...op,
|
||||
query: {
|
||||
documentId:
|
||||
// GraphQL Code Generator Client Preset generates
|
||||
// the persisted document ID within the document node.
|
||||
// For other implementations return the hash prefixed with the app version.
|
||||
appVersionPrefix + op.query['__meta__']['hash'],
|
||||
definitions: []
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
fetchExchange
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
| Parameter | Description |
|
||||
| --------------- | ---------------------------------- |
|
||||
| `<app_name>` | The name of the app deployment. |
|
||||
| `<app_version>` | The version of the app deployment. |
|
||||
|
||||
</Tabs.Tab>
|
||||
|
||||
<Tabs.Tab>
|
||||
|
||||
Update your Relay environment configuration to send persisted document requests instead of the
|
||||
document.
|
||||
|
||||
```typescript filename="Relay Persisted Document Configuration"
|
||||
// replace <app_name>, <app_version>, and with your values
|
||||
const appVersionPrefix = '<app_name>~<app_version>~'
|
||||
|
||||
function fetchQuery(operation, variables) {
|
||||
if (!operation.id) {
|
||||
throw new Error('No persisted document hash provided.')
|
||||
}
|
||||
|
||||
return fetch('/graphql', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
documentId: appVersionPrefix + operation.id,
|
||||
variables
|
||||
})
|
||||
}).then(response => response.json())
|
||||
}
|
||||
```
|
||||
|
||||
| Parameter | Description |
|
||||
| --------------- | ---------------------------------- |
|
||||
| `<app_name>` | The name of the app deployment. |
|
||||
| `<app_version>` | The version of the app deployment. |
|
||||
|
||||
</Tabs.Tab>
|
||||
|
||||
</Tabs>
|
||||
|
||||
## Continous Deployment (CD) Integration
|
||||
|
||||
We recommend integrating the app deployment creation and publishing into your CD pipeline for
|
||||
|
|
|
|||
Loading…
Reference in a new issue