Skip to content

Commit

Permalink
fix: no GET on mutations (#663)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonkuhrt authored Feb 3, 2024
1 parent 8f926b8 commit a169969
Show file tree
Hide file tree
Showing 10 changed files with 203 additions and 104 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
"happy-dom": "^13.3.1",
"json-bigint": "^1.0.0",
"prettier": "^3.2.4",
"tsx": "^4.7.0",
"type-fest": "^4.10.1",
"typescript": "^5.3.3",
"vitest": "^1.2.1",
Expand Down
24 changes: 24 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 11 additions & 10 deletions src/classes/GraphQLClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { BatchRequestDocument, BatchRequestsOptions, BatchResult } from '..
import { parseBatchRequestArgs } from '../functions/batchRequests.js'
import { parseRawRequestArgs } from '../functions/rawRequest.js'
import { parseRequestArgs } from '../functions/request.js'
import { resolveRequestDocument } from '../helpers/resolveRequestDocument.js'
import { analyzeDocument } from '../helpers/analyzeDocument.js'
import { runRequest } from '../helpers/runRequest.js'
import type { RequestDocument, RequestOptions, VariablesAndRequestHeadersArgs } from '../helpers/types.js'
import {
Expand Down Expand Up @@ -45,14 +45,13 @@ export class GraphQLClient {
fetchOptions.signal = rawRequestOptions.signal
}

const { operationName } = resolveRequestDocument(rawRequestOptions.query, excludeOperationName)
const document = analyzeDocument(rawRequestOptions.query, excludeOperationName)

const response = await runRequest({
url,
request: {
_tag: `Single`,
operationName,
query: rawRequestOptions.query,
document,
variables: rawRequestOptions.variables,
},
headers: {
Expand Down Expand Up @@ -105,14 +104,13 @@ export class GraphQLClient {
fetchOptions.signal = requestOptions.signal
}

const { query, operationName } = resolveRequestDocument(requestOptions.document, excludeOperationName)
const analyzedDocument = analyzeDocument(requestOptions.document, excludeOperationName)

const response = await runRequest({
url,
request: {
operationName,
_tag: `Single`,
query,
document: analyzedDocument,
variables: requestOptions.variables,
},
headers: {
Expand Down Expand Up @@ -152,17 +150,20 @@ export class GraphQLClient {
fetchOptions.signal = batchRequestOptions.signal
}

const queries = batchRequestOptions.documents.map(
({ document }) => resolveRequestDocument(document, excludeOperationName).query
const analyzedDocuments = batchRequestOptions.documents.map(
({ document }) => analyzeDocument(document, excludeOperationName)
)
const expressions = analyzedDocuments.map(({ expression }) => expression)
const hasMutations = analyzedDocuments.some(({ isMutation }) => isMutation)
const variables = batchRequestOptions.documents.map(({ variables }) => variables)

const response= await runRequest({
url: this.url,
request: {
_tag:`Batch`,
operationName: undefined,
query: queries,
query: expressions,
hasMutations,
variables,
},
headers: {
Expand Down
2 changes: 1 addition & 1 deletion src/entrypoints/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export { GraphQLClient } from '../classes/GraphQLClient.js'
export { batchRequests } from '../functions/batchRequests.js'
export { gql } from '../functions/gql.js'
export { rawRequest } from '../functions/rawRequest.js'
export { resolveRequestDocument } from '../helpers/resolveRequestDocument.js'
export { analyzeDocument } from '../helpers/analyzeDocument.js'
export { GraphQLWebSocketClient } from '../lib/graphql-ws.js'
export {
BatchRequestDocument,
Expand Down
63 changes: 63 additions & 0 deletions src/helpers/analyzeDocument.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { isOperationDefinitionNode } from '../lib/graphql.js'
import { tryCatch } from '../lib/prelude.js'
import type { RequestDocument } from './types.js'
/**
* Refactored imports from `graphql` to be more specific, this helps import only the required files (100KiB)
* instead of the entire package (greater than 500KiB) where tree-shaking is not supported.
* @see https://github.com/jasonkuhrt/graphql-request/pull/543
*/
import { type DocumentNode, OperationTypeNode } from 'graphql/language/ast.js'
import { parse } from 'graphql/language/parser.js'
import { print } from 'graphql/language/printer.js'

/**
* helpers
*/

const extractOperationName = (document: DocumentNode): string | undefined => {
let operationName = undefined

const defs = document.definitions.filter(isOperationDefinitionNode)

if (defs.length === 1) {
operationName = defs[0]!.name?.value
}

return operationName
}

const extractIsMutation = (document: DocumentNode): boolean => {
let isMutation = false

const defs = document.definitions.filter(isOperationDefinitionNode)

if (defs.length === 1) {
isMutation = defs[0]!.operation === OperationTypeNode.MUTATION
}

return isMutation
}

export const analyzeDocument = (
document: RequestDocument,
excludeOperationName?: boolean,
): { expression: string; operationName: string | undefined; isMutation: boolean } => {
const expression = typeof document === `string` ? document : print(document)

let isMutation = false
let operationName = undefined

if (excludeOperationName) {
return { expression, isMutation, operationName }
}

const docNode = tryCatch(() => (typeof document === `string` ? parse(document) : document))
if (docNode instanceof Error) {
return { expression, isMutation, operationName }
}

operationName = extractOperationName(docNode)
isMutation = extractIsMutation(docNode)

return { expression, operationName, isMutation }
}
56 changes: 0 additions & 56 deletions src/helpers/resolveRequestDocument.ts

This file was deleted.

Loading

0 comments on commit a169969

Please sign in to comment.