feat: allow providing multiple apolloClients outside of setup/vue context in vue-apollo-composable (#1340)
* allow providing multiple apolloClients outside of setup/vue context * add docs Co-authored-by: Rico Schmidt <schmidt@joshmartin.ch>
This commit is contained in:
@@ -82,3 +82,27 @@ provide(ApolloClients, {
|
||||
```
|
||||
|
||||
You can then select which one to use in functions we will cover next (such as `useQuery`, `useMutation` and `useSubscription`) with the `clientId` option.
|
||||
|
||||
## Usage outside of setup
|
||||
|
||||
When using e.g. `useQuery` outside of vue contexts, the clients cannot be injected using vue's provide/inject mechanism. `@vue/apollo-composable` can manage their own apollo clients
|
||||
|
||||
Use `provideApolloClient` for a single default client:
|
||||
|
||||
```js
|
||||
import { provideApolloClient } from "@vue/apollo-composable";
|
||||
|
||||
provideApolloClient(apolloClient)
|
||||
```
|
||||
|
||||
Use `provideApolloClients` for multiple clients:
|
||||
|
||||
```js
|
||||
import { provideApolloClients } from "@vue/apollo-composable";
|
||||
|
||||
provideApolloClients({
|
||||
default: apolloClient,
|
||||
clientA: apolloClientA,
|
||||
clientB: apolloClientB,
|
||||
})
|
||||
```
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<script lang="ts">
|
||||
import { apolloClient } from '@/apollo'
|
||||
import gql from 'graphql-tag'
|
||||
import { useQuery, useResult, provideApolloClients } from '@vue/apollo-composable'
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
// Global query
|
||||
|
||||
const query = provideApolloClients({ myCustomClientId: apolloClient })(() =>
|
||||
useQuery(
|
||||
gql`
|
||||
query hello {
|
||||
hello
|
||||
}
|
||||
`,
|
||||
{},
|
||||
{ clientId: 'myCustomClientId' },
|
||||
),
|
||||
)
|
||||
const hello = useResult(query.result, [])
|
||||
|
||||
export default defineComponent({
|
||||
setup () {
|
||||
return {
|
||||
hello,
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="no-setup-query">
|
||||
{{ hello }}
|
||||
</div>
|
||||
</template>
|
||||
@@ -18,6 +18,10 @@ export const router = createRouter({
|
||||
path: '/no-setup-query',
|
||||
component: () => import('./components/NoSetupQuery.vue'),
|
||||
},
|
||||
{
|
||||
path: '/no-setup-query-multi-client',
|
||||
component: () => import('./components/NoSetupQueryMultiClient.vue'),
|
||||
},
|
||||
{
|
||||
path: '/lazy-query',
|
||||
component: () => import('./components/LazyQuery.vue'),
|
||||
|
||||
@@ -81,6 +81,11 @@ describe('Vue 3 + Apollo Composable', () => {
|
||||
cy.contains('.no-setup-query', 'Hello world!')
|
||||
})
|
||||
|
||||
it('supports queries outside of setup with multiple clients', () => {
|
||||
cy.visit('/no-setup-query-multi-client')
|
||||
cy.contains('.no-setup-query', 'Hello world!')
|
||||
})
|
||||
|
||||
it('useLazyQuery', () => {
|
||||
cy.visit('/lazy-query')
|
||||
cy.get('.list-disc').should('have.length', 0)
|
||||
|
||||
@@ -43,4 +43,5 @@ export {
|
||||
useApolloClient,
|
||||
UseApolloClientReturn,
|
||||
provideApolloClient,
|
||||
provideApolloClients,
|
||||
} from './useApolloClient'
|
||||
|
||||
@@ -33,28 +33,43 @@ export function useApolloClient<TCacheShape = any> (clientId?: ClientId): UseApo
|
||||
let resolveImpl: ResolveClient<TCacheShape, NullableApolloClient<TCacheShape>>
|
||||
|
||||
// Save current client in current closure scope
|
||||
const savedCurrentClient = currentApolloClient
|
||||
const savedCurrentClients = currentApolloClients
|
||||
|
||||
if (!getCurrentInstance()) {
|
||||
resolveImpl = () => savedCurrentClient
|
||||
resolveImpl = (id?: ClientId) => {
|
||||
if (id) {
|
||||
return resolveClientWithId(savedCurrentClients, id)
|
||||
}
|
||||
return resolveDefaultClient(savedCurrentClients, savedCurrentClients.default)
|
||||
}
|
||||
} else {
|
||||
const providedApolloClients: ClientDict<TCacheShape> | null = inject(ApolloClients, null)
|
||||
const providedApolloClient: ApolloClient<TCacheShape> | null = inject(DefaultApolloClient, null)
|
||||
|
||||
resolveImpl = (id?: ClientId) => {
|
||||
if (savedCurrentClient) {
|
||||
return savedCurrentClient
|
||||
} else if (id) {
|
||||
return resolveClientWithId(providedApolloClients, id)
|
||||
if (id) {
|
||||
const client = resolveClientWithId(providedApolloClients, id)
|
||||
if (client) {
|
||||
return client
|
||||
}
|
||||
return resolveClientWithId(savedCurrentClients, id)
|
||||
}
|
||||
return resolveDefaultClient(providedApolloClients, providedApolloClient)
|
||||
const client = resolveDefaultClient(providedApolloClients, providedApolloClient)
|
||||
if (client) {
|
||||
return client
|
||||
}
|
||||
return resolveDefaultClient(savedCurrentClients, savedCurrentClients.default)
|
||||
}
|
||||
}
|
||||
|
||||
function resolveClient (id: ClientId | undefined = clientId) {
|
||||
const client = resolveImpl(id)
|
||||
if (!client) {
|
||||
throw new Error(`Apollo client with id ${id ?? 'default'} not found. Use provideApolloClient() if you are outside of a component setup.`)
|
||||
throw new Error(
|
||||
`Apollo client with id ${
|
||||
id ?? 'default'
|
||||
} not found. Use provideApolloClient() if you are outside of a component setup.`,
|
||||
)
|
||||
}
|
||||
return client
|
||||
}
|
||||
@@ -67,13 +82,24 @@ export function useApolloClient<TCacheShape = any> (clientId?: ClientId): UseApo
|
||||
}
|
||||
}
|
||||
|
||||
let currentApolloClient: NullableApolloClient<any>
|
||||
let currentApolloClients: ClientDict<any> = {}
|
||||
|
||||
export function provideApolloClient<TCacheShape = any> (client: ApolloClient<TCacheShape>) {
|
||||
currentApolloClient = client
|
||||
currentApolloClients = {
|
||||
default: client,
|
||||
}
|
||||
return function <TFnResult = any> (fn: () => TFnResult) {
|
||||
const result = fn()
|
||||
currentApolloClient = undefined
|
||||
currentApolloClients = {}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
export function provideApolloClients<TCacheShape = any> (clients: ClientDict<TCacheShape>) {
|
||||
currentApolloClients = clients
|
||||
return function <TFnResult = any> (fn: () => TFnResult) {
|
||||
const result = fn()
|
||||
currentApolloClients = {}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user