Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions packages/awesome-graphql-client/src/AwesomeGraphQLClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export class AwesomeGraphQLClient<
private FormData: any
private onError?: (error: GraphQLRequestError | Error) => void
private isFileUpload: (value: unknown) => boolean
private getOperationName?: (query: TQuery) => string | null | undefined

constructor(config: {
/** GraphQL endpoint */
Expand All @@ -37,6 +38,8 @@ export class AwesomeGraphQLClient<
onError?: (error: GraphQLRequestError | Error) => void
/** Custom predicate function for checking if value is a file */
isFileUpload?: (value: unknown) => boolean
/** Custom operation name getter */
getOperationName?: (query: TQuery) => string | null | undefined
}) {
assert(config.endpoint !== undefined, 'endpoint is required')

Expand Down Expand Up @@ -74,14 +77,16 @@ export class AwesomeGraphQLClient<
this.formatQuery = config.formatQuery
this.onError = config.onError
this.isFileUpload = config.isFileUpload || isFileUpload
this.getOperationName = config.getOperationName
}

private createRequestBody(
query: string,
variables?: Record<string, unknown>,
operationName?: string,
): string | FormData {
const { clone, files } = extractFiles(
{ query, variables },
{ query, variables, operationName },
'',
this.isFileUpload as (value: unknown) => value is FileUpload,
)
Expand Down Expand Up @@ -112,6 +117,10 @@ export class AwesomeGraphQLClient<
form.append(`${++i}`, file)
}

if (operationName !== undefined) {
form.append('operationName', operationName)
}

// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return form
}
Expand Down Expand Up @@ -181,6 +190,7 @@ export class AwesomeGraphQLClient<
| { ok: false; error: GraphQLRequestError<TRequestResult> | Error }
> {
try {
const operationName = this.getOperationName?.(query as TQuery) ?? undefined
const queryAsString = this.formatQuery ? this.formatQuery(query as TQuery) : query

assert(
Expand Down Expand Up @@ -210,7 +220,7 @@ export class AwesomeGraphQLClient<
})
response = await this.fetch(url, options)
} else {
const body = this.createRequestBody(queryAsString, variables)
const body = this.createRequestBody(queryAsString, variables, operationName)

response = await this.fetch(this.endpoint, {
...options,
Expand Down
67 changes: 66 additions & 1 deletion packages/awesome-graphql-client/test/browser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import { IncomingHttpHeaders } from 'node:http'

import { TypedDocumentNode } from '@graphql-typed-document-node/core'
import { print, DocumentNode } from 'graphql'
import { print, DocumentNode, Kind } from 'graphql'
import graphqlTag from 'graphql-tag'
import { GraphQLUpload, FileUpload } from 'graphql-upload'
import mercurius from 'mercurius'
Expand Down Expand Up @@ -693,3 +693,68 @@ it('uses provided `isFileUpload` implementation', async () => {

expect(data).toEqual({ uploadFile: true })
})

it('supports custom operationName', async () => {
type GetUserQuery = {
user: { id: number; login: string } | null
}

type GetUserQueryVariables = { id: number }

const user = { id: 10, login: 'admin' }

let parsedOperationName: string | undefined
let receivedOperationName: string | undefined

server = await createServer(
`
type Query {
user(id: Int!): User
}
type User {
id: Int!
login: String!
}
`,
{
Query: {
user: (_, args, cxt, operation) => {
receivedOperationName = operation.operation.name?.value
return user
},
},
},
)

const client = new AwesomeGraphQLClient({
endpoint: server.endpoint,
formatQuery: (query: TypedDocumentNode) => print(query),
getOperationName: (query: DocumentNode): string | undefined => {
for (const node of query.definitions) {
if (node.kind === Kind.OPERATION_DEFINITION) {
parsedOperationName = node.name ? node.name.value : undefined
return parsedOperationName
}
}
},
})

const GetUserDocument: TypedDocumentNode<
GetUserQuery,
GetUserQueryVariables
> = graphqlTag`
query GetUser($id: Int!) {
user(id: $id) {
id
login
}
}
`

const data = await client.request(GetUserDocument, { id: 123 })

expect(parsedOperationName).toBe('GetUser')
expect(receivedOperationName).toBe('GetUser')

expect(data).toEqual({ user })
})