Skip to content

Commit

Permalink
feat: expose gql client to nitro (#258)
Browse files Browse the repository at this point in the history
  • Loading branch information
Diizzayy committed Nov 25, 2022
1 parent e457505 commit c7fe0e0
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 17 deletions.
60 changes: 43 additions & 17 deletions src/module.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { existsSync, statSync, readFileSync } from 'fs'
import { existsSync, statSync } from 'fs'
import { defu } from 'defu'
import { parse } from 'graphql'
import { upperFirst } from 'scule'
import { useLogger, addPlugin, addImportsDir, addTemplate, resolveFiles, createResolver, defineNuxtModule, extendViteConfig } from '@nuxt/kit'
import type { NameNode, DefinitionNode } from 'graphql'
import { name, version } from '../package.json'
import generate from './generate'
import { mapDocsToClients } from './utils'
import type { GqlConfig, GqlClient, TokenOpts, GqlCodegen, TokenStorageOpts } from './types'
import { mapDocsToClients, extractGqlOperations } from './utils'
import type { GqlConfig, GqlClient, GqlCodegen, TokenStorageOpts } from './types'
import { prepareContext, mockTemplate } from './context'
import type { GqlContext } from './context'

Expand Down Expand Up @@ -190,20 +189,9 @@ export default defineNuxtModule<GqlConfig>({
...(typeof config.codegen !== 'boolean' && config.codegen)
}).then(output => output.reduce<Record<string, string>>((acc, c) => ({ ...acc, [c.filename.split('.ts')[0]]: c.content }), {}))
: ctx.clients!.reduce<Record<string, string>>((acc, k) => {
const entries: Record<string, string> = {}

if (!clientDocs?.[k]?.length) { return acc }

for (const doc of clientDocs?.[k] || []) {
const definitions = parse(readFileSync(doc, 'utf-8'))?.definitions as (DefinitionNode & { name: NameNode })[]

for (const op of definitions) {
const name: string = op?.name?.value
const operation = op.loc?.source.body.slice(op.loc.start, op.loc.end) || undefined

if (name && operation) { entries[name] = operation }
}
}
const entries = extractGqlOperations(ctx?.clientDocs?.[k] || [])

return { ...acc, [k]: mockTemplate(entries) }
}, {})
Expand Down Expand Up @@ -244,6 +232,44 @@ export default defineNuxtModule<GqlConfig>({
addImportsDir(resolver.resolve('runtime/composables'))
}

nuxt.hook('nitro:config', (nitro) => {
if (nitro.imports === false) { return }

nitro.externals = nitro.externals || {}
nitro.externals.inline = nitro.externals.inline || []
nitro.externals.inline.push(resolver.resolve('runtime'))

const clientSdks = Object.entries(ctx.clientDocs || {}).reduce<string[]>((acc, [client, docs]) => {
const entries = extractGqlOperations(docs)

return [...acc, `${client}: ` + mockTemplate(entries).replace('export ', '')]
}, [])

nitro.virtual = nitro.virtual || {}
nitro.virtual['#gql-nitro'] = [
'const clientSdks = {' + clientSdks + '}',
'const config = ' + JSON.stringify(config.clients),
'const ops = ' + JSON.stringify(ctx.clientOps),
'const clients = {}',
'const useGql = (op, variables = undefined) => {',
' const client = Object.keys(ops).find(k => ops[k].includes(op))',
' return clientSdks[client](clients?.[client])[op](variables)',
'}',
ctx.fns?.map(fn => `export const ${config.functionPrefix + upperFirst(fn)} = (...params) => useGql('${fn}', ...params)`).join('\n'),
'export default { clients, config }'
].join('\n')

nitro.imports = defu(nitro.imports, {
presets: [{
from: '#gql-nitro',
imports: ctx.fns?.map(fn => config.functionPrefix + upperFirst(fn))
}]
})

nitro.plugins = nitro.plugins || []
nitro.plugins.push(resolver.resolve('runtime/nitro'))
})

const allowDocument = (f: string) => {
const isSchema = f.match(/([^/]+)\.(gql|graphql)$/)?.[0]?.toLowerCase().includes('schema')

Expand Down
27 changes: 27 additions & 0 deletions src/runtime/nitro.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { GraphQLClient } from 'graphql-request'
import type { GqlConfig } from '../../types'
// @ts-ignore
import { defineNitroPlugin } from '#internal/nitro'
// @ts-ignore
import GqlNitro from '#gql-nitro'

export default defineNitroPlugin(() => {
const GqlConfig: GqlConfig['clients'] = GqlNitro!.config

for (const [client, conf] of Object.entries(GqlConfig!)) {
const serverHeaders = (typeof conf?.headers?.serverOnly === 'object' && conf?.headers?.serverOnly) || undefined
if (conf?.headers?.serverOnly) { delete conf.headers.serverOnly }

const tokenName = conf!.token!.name!
const tokenType = conf.token!.type!
const authToken = !tokenType ? conf?.token?.value : `${tokenType} ${conf?.token?.value}`

const headers = {
...conf?.headers,
...serverHeaders,
...(conf?.token?.value && { [tokenName]: authToken })
}

GqlNitro.clients[client] = new GraphQLClient(conf.host, { headers })
}
})
21 changes: 21 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { readFileSync } from 'fs'
import { parse } from 'graphql'
import type { DefinitionNode, NameNode } from 'graphql'

export const mapDocsToClients = (documents: string[], clients: string[]) => {
const mappedDocs = new Set()

Expand Down Expand Up @@ -27,3 +31,20 @@ export const mapDocsToClients = (documents: string[], clients: string[]) => {
return acc
}, {} as Record<string, string[]>)
}

export const extractGqlOperations = (docs: string[]): Record<string, string> => {
const entries: Record<string, string> = {}

for (const doc of docs) {
const definitions = parse(readFileSync(doc, 'utf-8'))?.definitions as (DefinitionNode & { name: NameNode })[]

for (const op of definitions) {
const name: string = op?.name?.value
const operation = op.loc?.source.body.slice(op.loc.start, op.loc.end) || undefined

if (name && operation) { entries[name] = operation }
}
}

return entries
}

0 comments on commit c7fe0e0

Please sign in to comment.