Skip to content

Commit b5d3ae2

Browse files
committed
fix: improve context handling
1 parent 82666c0 commit b5d3ae2

File tree

7 files changed

+54
-28
lines changed

7 files changed

+54
-28
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"build": "nuxt-module-build",
3838
"dev": "nuxi dev playground",
3939
"dev:build": "nuxi build playground",
40-
"test": "vitest run --coverage",
40+
"test": "vitest run --coverage --watch false",
4141
"lint": "eslint --ext .js,.ts,.vue .",
4242
"lint:fix": "eslint --fix --ext .js,.ts,.vue .",
4343
"prepare": "nuxt-module-build --stub && nuxi prepare playground"

src/context.ts

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,7 @@ export function prepareContext (ctx: GqlContext, prefix: string) {
2727
const fnExp = (fn: string, typed = false) => {
2828
const name = fnName(fn)
2929

30-
if (!typed) {
31-
const client = ctx?.clients.find(c => ctx?.clientOps?.[c]?.includes(fn))
32-
33-
return `export const ${name} = (...params) => GqlInstance().handle(${client ? `'${client}'` : ''})['${fn}'](...params)`
34-
}
30+
if (!typed) { return `export const ${name} = (...params) => useGql()('${fn}', ...params)` }
3531

3632
return ` export const ${name}: (...params: Parameters<GqlSdkFuncs['${fn}']>) => ReturnType<GqlSdkFuncs['${fn}']>`
3733
}
@@ -40,14 +36,8 @@ export function prepareContext (ctx: GqlContext, prefix: string) {
4036
'import { useGql } from \'#imports\'',
4137
...ctx.clients.map(client => `import { getSdk as ${client}GqlSdk } from '#gql/${client}'`),
4238
'export const GqlSdks = {',
43-
` default: ${ctx.clients.find(c => c === 'default') || ctx.clients[0]}GqlSdk,`,
4439
...ctx.clients.map(client => ` ${client}: ${client}GqlSdk,`),
4540
'}',
46-
'const ctx = { instance: null }',
47-
'export const GqlInstance = () => {',
48-
' if (!ctx?.instance) {ctx.instance = useGql()}',
49-
' return ctx.instance',
50-
'}',
5141
`export const GqlOperations = ${JSON.stringify(ctx.clientOps)}`,
5242
...ctx.fns.map(f => fnExp(f))
5343
].join('\n')
@@ -58,7 +48,9 @@ export function prepareContext (ctx: GqlContext, prefix: string) {
5848
'declare module \'#gql\' {',
5949
` type GqlClients = '${ctx.clients.join("' | '") || 'default'}'`,
6050
' const GqlOperations = {}',
61-
' type GqlSdkValues<T extends GqlClients> = ReturnType<typeof GqlSdks[T]>',
51+
' const GqlSdks = {',
52+
...ctx.clients.map(client => ` ${client}: ${client}GqlSdk,`),
53+
' }',
6254
...ctx.fns.map(f => fnExp(f, true)),
6355
` type GqlSdkFuncs = ${ctx.clients.map(c => `ReturnType<typeof ${c}GqlSdk>`).join(' & ')}`,
6456
'}'

src/runtime/composables/index.ts

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import type { GqlState, GqlConfig, GqlError, OnGqlError } from '../../types'
55
import { deepmerge } from '../utils'
66
// @ts-ignore
77
// eslint-disable-next-line import/named
8-
import { GqlSdks, GqlInstance, GqlOperations } from '#gql'
9-
import type { GqlClients, GqlSdkValues, GqlSdkFuncs } from '#gql'
8+
import { GqlSdks, GqlOperations } from '#gql'
9+
import type { GqlClients, GqlSdkFuncs } from '#gql'
1010
import { useState, useNuxtApp, useAsyncData, useRuntimeConfig } from '#imports'
1111

1212
const useGqlState = (): Ref<GqlState> => {
@@ -204,12 +204,25 @@ export const useGqlCors = (cors: GqlCors) => {
204204
setGqlState({ client, patch: { mode, credentials } })
205205
}
206206

207-
export const useGql = () => {
207+
export const useGql = (): (<
208+
T extends keyof GqlSdkFuncs,
209+
R extends ReturnType<GqlSdkFuncs[T]>,
210+
P extends Parameters<GqlSdkFuncs[T]>['0'],
211+
> (args: { operation: T, variables?: P }) => R) &
212+
(<
213+
T extends keyof GqlSdkFuncs,
214+
R extends ReturnType<GqlSdkFuncs[T]>,
215+
P extends Parameters<GqlSdkFuncs[T]>['0'],
216+
> (operation: T, variables?: P) => R) => {
208217
const state = useGqlState()
209218
const errState = useGqlErrorState()
210219

211-
const handle = <T extends GqlClients> (client?: T) => {
212-
client = client || 'default' as T
220+
return (...args: any[]) => {
221+
const operation = (typeof args?.[0] !== 'string' && 'operation' in args?.[0] ? args[0].operation : args[0]) ?? undefined
222+
const variables = (typeof args?.[0] !== 'string' && 'variables' in args?.[0] ? args[0].variables : args[1]) ?? undefined
223+
224+
const client = Object.keys(GqlOperations).find(k => GqlOperations[k].includes(operation)) ?? 'default'
225+
213226
const { instance } = state.value?.[client]
214227

215228
return GqlSdks[client](instance, async (action, operationName, operationType): Promise<any> => {
@@ -230,10 +243,8 @@ export const useGql = () => {
230243

231244
throw errState.value
232245
}
233-
}) as GqlSdkValues<T>
246+
})[operation](variables)
234247
}
235-
236-
return { handle }
237248
}
238249

239250
/**
@@ -294,7 +305,6 @@ export function useAsyncGql (...args: any[]) {
294305
const operation = (typeof args?.[0] !== 'string' && 'operation' in args?.[0] ? args[0].operation : args[0]) ?? undefined
295306
const variables = (typeof args?.[0] !== 'string' && 'variables' in args?.[0] ? args[0].variables : args[1]) ?? undefined
296307
const options = (typeof args?.[0] !== 'string' && 'options' in args?.[0] ? args[0].options : args[2]) ?? undefined
297-
const client = Object.keys(GqlOperations).find(k => GqlOperations[k].includes(operation)) ?? 'default'
298-
const key = hash({ operation, client, variables })
299-
return useAsyncData(key, () => GqlInstance().handle(client as GqlClients)[operation](variables), options)
308+
const key = hash({ operation, variables })
309+
return useAsyncData(key, () => useGql()(operation, variables), options)
300310
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<template>
2+
<div>
3+
<p>First Episode: {{ data.episode.name || 'Unknown' }}</p>
4+
<p>Name: {{ data?.character?.name || 'John Doe' }}</p>
5+
</div>
6+
</template>
7+
8+
<script lang="ts" setup>
9+
const GqlInstance = useGql()
10+
11+
const { data } = await useAsyncData(async () => {
12+
const { episode } = await GqlInstance('first_episode')
13+
const { character } = await GqlInstance('character')
14+
return { episode, character }
15+
})
16+
</script>

test/fixtures/multi-client/pages/spacex/index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
</template>
44

55
<script lang="ts" setup>
6-
const { data } = await useAsyncGql('launches')
6+
const { data } = await useAsyncData(() => GqlLaunches())
77
</script>

test/fixtures/multi-client/pages/spacex/mission.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@
33
</template>
44

55
<script lang="ts" setup>
6-
const { data } = await useAsyncGql('mission')
6+
const GqlInstance = useGql()
7+
8+
const { data } = await useAsyncData(() => GqlInstance('mission'))
79
</script>

test/multi-client.test.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,16 @@ describe('test multiple clients', () => {
2121
it('renders the character morty', async () => {
2222
const result = await $fetch('/rmorty')
2323
expect(result).toContain('<p>Name: Morty Smith</p>')
24-
}, 15000)
24+
})
2525

2626
it('fetches the name of the first rick and morty episode', async () => {
2727
const result = await $fetch('/rmorty/first-ep')
2828
expect(result).toContain('<p>First Episode: Pilot</p>')
29-
}, 15000)
29+
})
30+
31+
it('fetches the name of the first rick and morty episode', async () => {
32+
const result = await $fetch('/rmorty/chain')
33+
expect(result).toContain('<p>First Episode: Pilot</p>')
34+
expect(result).toContain('<p>Name: Morty Smith</p>')
35+
})
3036
})

0 commit comments

Comments
 (0)