Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to envelop v3 #1660

Merged
merged 42 commits into from
Oct 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
1ae14fd
update envelop
saihaj Aug 25, 2022
acf0e83
bring error formatter here
saihaj Aug 25, 2022
dac1e50
feat: create a wrapped schema
saihaj Aug 25, 2022
d639419
changeset for now
saihaj Aug 26, 2022
59579f0
useOnResolver envelop plugin proposal
enisdenjo Aug 30, 2022
803cd06
run canary for v3
saihaj Aug 30, 2022
6b7edb0
do not run deps
saihaj Aug 30, 2022
2836f22
fix version
saihaj Aug 30, 2022
dc4c0bd
plz
saihaj Aug 30, 2022
9c9f8f9
remove
saihaj Aug 30, 2022
af234a7
Merge branch 'v3' into saihaj/try-new-envelop
saihaj Sep 20, 2022
452d6ac
update envelop
saihaj Sep 20, 2022
ab91cd1
error masking works
saihaj Sep 20, 2022
a5ab398
Merge branch 'v3' into saihaj/try-new-envelop
saihaj Sep 20, 2022
f57828e
plz build
saihaj Sep 20, 2022
0d68917
Merge branch 'v3' into saihaj/try-new-envelop
saihaj Oct 3, 2022
6991535
update to new envelop
saihaj Oct 4, 2022
f177c5c
Fix tests
saihaj Oct 4, 2022
af8eff5
Merge branch 'v3' into saihaj/try-new-envelop
saihaj Oct 12, 2022
b1ef033
works
saihaj Oct 12, 2022
b221c82
update
saihaj Oct 13, 2022
00e0002
resolve to envelop v3
enisdenjo Oct 13, 2022
a89484f
deno resolve import to envelop/core 3
enisdenjo Oct 13, 2022
53087d1
Merge branch 'v3' into saihaj/try-new-envelop
enisdenjo Oct 13, 2022
b07099e
code review
saihaj Oct 13, 2022
9182edb
update guide
saihaj Oct 13, 2022
034f2a1
unnecessary cast
enisdenjo Oct 14, 2022
be7848a
use own isGraphQL
enisdenjo Oct 14, 2022
6b52b26
dev is when not prod
enisdenjo Oct 14, 2022
10878f6
use http validation context generic
enisdenjo Oct 14, 2022
4e24da6
use yoga types
enisdenjo Oct 14, 2022
11e20cd
plugins need to inherit the context
enisdenjo Oct 14, 2022
039b2b9
patch envelop core
enisdenjo Oct 14, 2022
b36edca
patch envelop response-cache
enisdenjo Oct 14, 2022
9e107f0
partial yoga masked error opts
enisdenjo Oct 14, 2022
20eebf5
appearantly dev env is when dev env
enisdenjo Oct 14, 2022
55a93ec
Merge branch 'v3' into saihaj/try-new-envelop
saihaj Oct 14, 2022
45c9c8b
remove unused
saihaj Oct 14, 2022
3452924
remove more
saihaj Oct 14, 2022
51e14f4
relative imports need .js
saihaj Oct 14, 2022
983a968
Go
ardatan Oct 17, 2022
0fa8eb4
Go
ardatan Oct 17, 2022
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
10 changes: 10 additions & 0 deletions .changeset/strong-peas-exercise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'graphql-yoga': major
---

update to Envelop `useMaskedError` plugin

- Removed handleValidationErrors and handleParseErrors
- Renamed formatError to maskError

Checkout envelop docs for more details https://www.the-guild.dev/graphql/envelop/v3/guides/migrating-from-v2-to-v3#8-update-options-for-usemaskederrors-plugin
2 changes: 1 addition & 1 deletion examples/apollo-federation/gateway/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"dependencies": {
"@apollo/gateway": "^0.52.0",
"@envelop/apollo-federation": "^2.5.0",
"@envelop/apollo-federation": "3.0.1",
"graphql-yoga": "3.0.0-next.4",
"graphql": "^16.5.0"
}
Expand Down
2 changes: 1 addition & 1 deletion examples/fastify-modules/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"check": "tsc --pretty --noEmit"
},
"dependencies": {
"@envelop/graphql-modules": "3.6.0",
"@envelop/graphql-modules": "4.0.1",
"@graphql-tools/load-files": "6.6.1",
"graphql-yoga": "3.0.0-next.4",
"fastify": "4.7.0",
Expand Down
2 changes: 1 addition & 1 deletion examples/generic-auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"typescript": "4.8.4"
},
"dependencies": {
"@envelop/generic-auth": "4.6.0",
"@envelop/generic-auth": "5.0.1",
"graphql-yoga": "3.0.0-next.4",
"graphql": "16.6.0"
}
Expand Down
2 changes: 1 addition & 1 deletion examples/live-query/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"typescript": "4.8.4"
},
"dependencies": {
"@envelop/live-query": "4.2.0",
"@envelop/live-query": "5.0.1",
"@n1ru4l/in-memory-live-query-store": "0.10.0",
"graphql-yoga": "3.0.0-next.4",
"graphql": "16.6.0"
Expand Down
2 changes: 1 addition & 1 deletion examples/sveltekit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"vite": "3.1.6"
},
"dependencies": {
"@envelop/graphql-jit": "4.6.0",
"@envelop/graphql-jit": "5.0.1",
"graphql-yoga": "3.0.0-next.4",
"graphql": "16.6.0"
},
Expand Down
2 changes: 1 addition & 1 deletion import-map.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"@graphql-tools/utils": "npm:@graphql-tools/utils",
"graphql": "npm:graphql",
"dset": "npm:dset",
"@envelop/core": "npm:@envelop/core@2",
"@envelop/core": "npm:@envelop/core@3",
"@envelop/parser-cache": "npm:@envelop/parser-cache",
"@envelop/validation-cache": "npm:@envelop/validation-cache",
"@whatwg-node/fetch": "npm:@whatwg-node/fetch",
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
"weak-napi": "2.0.2"
},
"resolutions": {
"graphql": "16.6.0"
"graphql": "16.6.0",
"@envelop/core": "3.0.2"
}
}
5 changes: 0 additions & 5 deletions packages/graphql-yoga/__tests__/context.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ describe('Context', () => {
const onContextBuildingFn = jest.fn(
(() => {}) as Plugin['onContextBuilding'],
)
const onResolverCalledFn = jest.fn((() => {}) as Plugin['onResolverCalled'])

const yoga = createYoga({
schema,
Expand All @@ -131,7 +130,6 @@ describe('Context', () => {
onParse: onParseFn,
onValidate: onValidateFn,
onContextBuilding: onContextBuildingFn,
onResolverCalled: onResolverCalledFn,
},
],
})
Expand All @@ -157,8 +155,5 @@ describe('Context', () => {

expect(onContextBuildingFn.mock.lastCall[0].context.params).toEqual(params)
expect(onContextBuildingFn.mock.lastCall[0].context.request).toBeDefined()

expect(onResolverCalledFn.mock.lastCall[0].context.params).toEqual(params)
expect(onResolverCalledFn.mock.lastCall[0].context.request).toBeDefined()
})
})
10 changes: 5 additions & 5 deletions packages/graphql-yoga/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@
},
"dependencies": {
"@graphql-tools/utils": "8.12.0",
"@envelop/core": "^2.5.0",
"@envelop/parser-cache": "^4.6.0",
"@envelop/validation-cache": "^4.6.0",
"@envelop/core": "3.0.2",
"@envelop/parser-cache": "5.0.1",
"@envelop/validation-cache": "5.0.1",
"@graphql-typed-document-node/core": "^3.1.1",
"@graphql-tools/schema": "^9.0.0",
"@graphql-yoga/subscription": "^3.0.0-next.0",
Expand All @@ -63,8 +63,8 @@
"devDependencies": {
"@types/node": "16.11.64",
"html-minifier-terser": "7.0.0",
"@envelop/disable-introspection": "^3.5.0",
"@envelop/live-query": "^4.1.0",
"@envelop/disable-introspection": "4.0.1",
"@envelop/live-query": "5.0.1",
"graphql": "^16.0.1",
"graphql-scalars": "1.18.0",
"graphql-http": "^1.6.0",
Expand Down
28 changes: 19 additions & 9 deletions packages/graphql-yoga/src/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,16 @@ function hasToString(obj: any): obj is { toString(): string } {
return obj != null && typeof obj.toString === 'function'
}

export function isOriginalGraphQLError(error: Error): boolean {
if (error instanceof GraphQLError) {
if (error.originalError != null) {
return isOriginalGraphQLError(error.originalError)
export function isGraphQLError(val: unknown): val is GraphQLError {
return val instanceof GraphQLError
}

export function isOriginalGraphQLError(
val: unknown,
): val is GraphQLError & { originalError: GraphQLError } {
if (val instanceof GraphQLError) {
if (val.originalError != null) {
return isOriginalGraphQLError(val.originalError)
}
return true
}
Expand All @@ -44,13 +50,18 @@ export function handleError(
}
}
} else if (maskedErrorsOpts) {
const maskedError = maskedErrorsOpts.formatError(
const maskedError = maskedErrorsOpts.maskError(
error,
maskedErrorsOpts.errorMessage,
maskedErrorsOpts.isDev,
)
errors.add(maskedError)
} else if (error instanceof GraphQLError) {
errors.add(
isGraphQLError(maskedError)
? maskedError
: createGraphQLError(maskedError.message, {
originalError: maskedError,
}),
)
} else if (isGraphQLError(error)) {
errors.add(error)
} else if (error instanceof Error) {
errors.add(
Expand Down Expand Up @@ -91,7 +102,6 @@ export function handleError(
}
return Array.from(errors)
}

export function getResponseInitByRespectingErrors(
result: ResultProcessorInput,
headers: Record<string, string> = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ export function getAggregateErrorFromErrors(
throw new AggregateError(errors)
}

export function useHTTPValidationError(): Plugin {
export function useHTTPValidationError<
PluginContext extends Record<string, any> = {},
>(): Plugin<PluginContext> {
return {
onValidate() {
return ({ valid, result }) => {
if (!valid) {
throw getAggregateErrorFromErrors(result)
// Typecasting since Envelop is Agnostic to GraphQL.js
throw getAggregateErrorFromErrors(result as GraphQLError[])
}
}
},
Expand Down
34 changes: 25 additions & 9 deletions packages/graphql-yoga/src/server.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import { print, ExecutionResult } from 'graphql'
import {
print,
ExecutionResult,
execute,
parse,
validate,
subscribe,
specifiedRules,
} from 'graphql'
import {
GetEnvelopedFn,
envelop,
useMaskedErrors,
UseMaskedErrorsOpts,
useEngine,
useExtendContext,
useLogger,
PromiseOrValue,
useMaskedErrors,
} from '@envelop/core'
import { useValidationCache, ValidationCache } from '@envelop/validation-cache'
import { ParserCacheOptions, useParserCache } from '@envelop/parser-cache'
Expand Down Expand Up @@ -96,7 +104,7 @@ export type YogaServerOptions<
*
* @default true
*/
maskedErrors?: boolean | UseMaskedErrorsOpts
maskedErrors?: boolean | Partial<YogaMaskedErrorOpts>
/**
* Context
*/
Expand Down Expand Up @@ -239,9 +247,13 @@ export class YogaServer<
options?.maskedErrors === false
? null
: {
formatError: yogaDefaultFormatError,
maskError: (error, message) =>
yogaDefaultFormatError({
error,
message,
isDev: this.maskedErrorsOpts?.isDev ?? false,
}),
errorMessage: 'Unexpected error.',
isDev: globalThis.process?.env?.NODE_ENV === 'development',
...(typeof options?.maskedErrors === 'object'
? options.maskedErrors
: {}),
Expand All @@ -263,6 +275,7 @@ export class YogaServer<
const graphqlEndpoint = this.graphqlEndpoint

this.plugins = [
useEngine({ parse, validate, execute, subscribe, specifiedRules }),
// Use the schema provided by the user
!!options?.schema && useSchema(options.schema),

Expand Down Expand Up @@ -311,13 +324,14 @@ export class YogaServer<
},
}),
options?.context != null &&
useExtendContext(async (initialContext) => {
useExtendContext((initialContext) => {
if (options?.context) {
if (typeof options.context === 'function') {
return (options.context as Function)(initialContext)
return options.context(initialContext)
}
return options.context
}
return {}
}),
// Middlewares before processing the incoming HTTP request
useHealthCheck({
Expand Down Expand Up @@ -395,7 +409,9 @@ export class YogaServer<

this.getEnveloped = envelop({
plugins: this.plugins,
}) as GetEnvelopedFn<TUserContext & TServerContext & YogaInitialContext>
}) as unknown as GetEnvelopedFn<
TUserContext & TServerContext & YogaInitialContext
>
enisdenjo marked this conversation as resolved.
Show resolved Hide resolved

this.onRequestHooks = []
this.onRequestParseHooks = []
Expand Down
8 changes: 4 additions & 4 deletions packages/graphql-yoga/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { DocumentNode, GraphQLError } from 'graphql'
import type { GraphQLError } from 'graphql'
import type { TypedDocumentNode } from '@graphql-typed-document-node/core'
import type { FormatErrorHandler, PromiseOrValue } from '@envelop/core'
import type { MaskError, PromiseOrValue } from '@envelop/core'
import type { createFetch } from '@whatwg-node/fetch'
import type { GraphQLSchema } from 'graphql'

Expand Down Expand Up @@ -83,9 +83,9 @@ export interface FetchEvent extends Event {
}

export type YogaMaskedErrorOpts = {
formatError: FormatErrorHandler
maskError: MaskError
saihaj marked this conversation as resolved.
Show resolved Hide resolved
errorMessage: string
isDev: boolean
isDev?: boolean
}

export type MaybeArray<T> = T | T[]
53 changes: 34 additions & 19 deletions packages/graphql-yoga/src/utils/yogaDefaultFormatError.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,61 @@
import { FormatErrorHandler } from '@envelop/core'
import { createGraphQLError } from '@graphql-tools/utils'
import { GraphQLError, GraphQLErrorExtensions } from 'graphql'
import { GraphQLErrorExtensions } from 'graphql'
import { isGraphQLError } from '../error.js'

export const yogaDefaultFormatError: FormatErrorHandler = (
err,
export const yogaDefaultFormatError = ({
error,
message,
isDev,
) => {
if (err instanceof GraphQLError) {
if (err.originalError) {
if (err.originalError.name === 'GraphQLError') {
return err
}: {
error: unknown
message: string
isDev?: boolean
}) => {
const dev = isDev || globalThis.process?.env?.NODE_ENV === 'development'

if (isGraphQLError(error)) {
if (error.originalError) {
if (error.originalError.name === 'GraphQLError') {
return error
}
// Original error should be removed
const extensions: GraphQLErrorExtensions = {
...err.extensions,
...error.extensions,
http: {
status: 500,
...err.extensions?.http,
...error.extensions?.http,
},
}
if (isDev) {
if (dev) {
extensions.originalError = {
message: err.originalError.message,
stack: err.originalError.stack,
message: error.originalError.message,
stack: error.originalError.stack,
}
}
return createGraphQLError(message, {
nodes: err.nodes,
source: err.source,
positions: err.positions,
path: err.path,
nodes: error.nodes,
source: error.source,
positions: error.positions,
path: error.path,
extensions,
})
}
return err
return error
}

return createGraphQLError(message, {
extensions: {
http: {
status: 500,
},
originalError: dev
? error instanceof Error
? {
message: error.message,
stack: error.stack,
}
: error
: undefined,
},
})
}
9 changes: 9 additions & 0 deletions packages/node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@
"graphql-yoga": "3.0.0-next.4",
"tslib": "^2.3.1"
},
"devDependencies": {
"@envelop/disable-introspection": "4.0.1",
"@envelop/live-query": "5.0.1",
"@types/eventsource": "1.1.9",
"@types/node": "16.11.63",
"graphql": "^16.6.0",
"graphql-scalars": "1.18.0",
"puppeteer": "18.0.5"
},
"peerDependencies": {
"graphql": "^15.2.0 || ^16.0.0"
},
Expand Down
Loading