Skip to content

Commit

Permalink
useEngine accepts GraphQL's specifiedRules (#1557)
Browse files Browse the repository at this point in the history
* failing test

* useengine accepts specifiedRules

* changeset

* missed doc updates

* simplify map

* simplify even further
  • Loading branch information
enisdenjo authored Oct 13, 2022
1 parent 50321cd commit 1da52ee
Show file tree
Hide file tree
Showing 63 changed files with 265 additions and 223 deletions.
5 changes: 5 additions & 0 deletions .changeset/weak-lobsters-fetch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@envelop/core': patch
---

useEngine accepts GraphQL's specifiedRules
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ yarn add graphql @envelop/core
Then, create a simple Envelop based on your GraphQL schema:

```ts
import { parse, validate, execute, subscribe } from 'graphql'
import { parse, validate, specifiedRules, execute, subscribe } from 'graphql'
import { envelop, useEngine, useSchema } from '@envelop/core'

const mySchema = buildSchema(/* ... */) // GraphQLSchema

const getEnveloped = envelop({
plugins: [useEngine({ parse, validate, execute, subscribe }), useSchema(mySchema)]
plugins: [useEngine({ parse, validate, specifiedRules, execute, subscribe }), useSchema(mySchema)]
})
```

Expand Down
12 changes: 6 additions & 6 deletions benchmark/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const { useGraphQlJit } = require('../packages/plugins/graphql-jit');
const { useValidationCache } = require('../packages/plugins/validation-cache');
const { fastify } = require('fastify');
const faker = require('faker');
const { parse, validate, subscribe, execute } = require('graphql');
const { parse, validate, specifiedRules, subscribe, execute } = require('graphql');
const { monitorEventLoopDelay } = require('perf_hooks');
const eventLoopMonitor = monitorEventLoopDelay({ resolution: 20 });

Expand Down Expand Up @@ -69,12 +69,12 @@ const createSchema = () =>

const envelopsMap = {
'graphql-js': envelop({
plugins: [useEngine({ parse, validate, execute, subscribe }), useSchema(createSchema())],
plugins: [useEngine({ parse, validate, specifiedRules, execute, subscribe }), useSchema(createSchema())],
enableInternalTracing: true,
}),
'envelop-just-cache': envelop({
plugins: [
useEngine({ parse, validate, execute, subscribe }),
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
useSchema(createSchema()),
useParserCache(),
useValidationCache(),
Expand All @@ -83,15 +83,15 @@ const envelopsMap = {
}),
'envelop-cache-and-no-internal-tracing': envelop({
plugins: [
useEngine({ parse, validate, execute, subscribe }),
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
useSchema(createSchema()),
useParserCache(),
useValidationCache(),
],
}),
'envelop-cache-jit': envelop({
plugins: [
useEngine({ parse, validate, execute, subscribe }),
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
useSchema(createSchema()),
useGraphQlJit(),
useParserCache(),
Expand All @@ -101,7 +101,7 @@ const envelopsMap = {
}),
'prom-tracing': envelop({
plugins: [
useEngine({ parse, validate, execute, subscribe }),
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
useSchema(createSchema()),
useParserCache(),
useValidationCache(),
Expand Down
3 changes: 2 additions & 1 deletion packages/core/docs/use-engine.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ This plugin can be used to customize the GraphQL Engine.

```ts
import { envelop, useEngine } from '@envelop/core'
import { parse, validate, execute, subscribe } from 'graphql'
import { parse, validate, specifiedRules, execute, subscribe } from 'graphql'

const getEnveloped = envelop({
plugins: [
useEngine({
parse,
validate,
specifiedRules,
execute,
subscribe
})
Expand Down
4 changes: 2 additions & 2 deletions packages/core/docs/use-error-handler.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ This plugin triggers a custom function when execution encounters an error.

```ts
import { envelop, useEngine, useErrorHandler } from '@envelop/core'
import { parse, validate, execute, subscribe } from 'graphql'
import { parse, validate, specifiedRules, execute, subscribe } from 'graphql'

const getEnveloped = envelop({
plugins: [
useEngine({ parse, validate, execute, subscribe }),
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
useErrorHandler((errors, args) => {
// This callback is called once, containing all GraphQLError emitted during execution phase
})
Expand Down
4 changes: 2 additions & 2 deletions packages/core/docs/use-extend-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ Easily extends the context with custom fields.

```ts
import { envelop, useEngine, useExtendContext } from '@envelop/core'
import { parse, validate, execute, subscribe } from 'graphql'
import { parse, validate, specifiedRules, execute, subscribe } from 'graphql'

const getEnveloped = envelop({
plugins: [
useEngine({ parse, validate, execute, subscribe }),
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
useExtendContext(async contextSoFar => {
return {
myCustomField: {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/docs/use-logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
Logs parameters and information about the execution phases. You can easily plug your custom logger.

```ts
import { envelop, useEngine, useLogger } from '@envelop/core'
import { envelop, useEngine, specifiedRules, useLogger } from '@envelop/core'
import { parse, validate, execute, subscribe } from 'graphql'

const getEnveloped = envelop({
plugins: [
useEngine({ parse, validate, execute, subscribe }),
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
useLogger({
logFn: (eventName, args) => {
// Event could be `execute-start` / `execute-end` / `subscribe-start` / `subscribe-end`
Expand Down
12 changes: 6 additions & 6 deletions packages/core/docs/use-masked-errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Prevent unexpected error messages from leaking to the GraphQL clients.

```ts
import { envelop, useSchema, useMaskedErrors, useEngine } from '@envelop/core'
import { makeExecutableSchema, GraphQLError, parse, validate, execute, subscribe } from 'graphql'
import { makeExecutableSchema, GraphQLError, parse, validate, specifiedRules, execute, subscribe } from 'graphql'

const schema = makeExecutableSchema({
typeDefs: /* GraphQL */ `
Expand Down Expand Up @@ -33,20 +33,20 @@ const schema = makeExecutableSchema({
})

const getEnveloped = envelop({
plugins: [useEngine({ parse, validate, execute, subscribe }), useSchema(schema), useMaskedErrors()]
plugins: [useEngine({ parse, validate, specifiedRules, execute, subscribe }), useSchema(schema), useMaskedErrors()]
})
```

You may customize the default error message `Unexpected error.` with your own `errorMessage`:

```ts
import { envelop, useSchema, useMaskedErrors, useEngine } from '@envelop/core'
import { parse, validate, execute, subscribe } from 'graphql'
import { parse, validate, specifiedRules, execute, subscribe } from 'graphql'
import { schema } from './schema'

const getEnveloped = envelop({
plugins: [
useEngine({ parse, validate, execute, subscribe }),
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
useSchema(schema),
useMaskedErrors({ errorMessage: 'Something went wrong.' })
]
Expand All @@ -57,7 +57,7 @@ Or provide a custom formatter when masking the output:

```ts
import { isGraphQLError, MaskError, useEngine } from '@envelop/core'
import { parse, validate, execute, subscribe, GraphQLError } from 'graphql'
import { parse, validate, specifiedRules, execute, subscribe, GraphQLError } from 'graphql'

export const customFormatError: MaskError = err => {
if (isGraphQLError(err)) {
Expand All @@ -69,7 +69,7 @@ export const customFormatError: MaskError = err => {

const getEnveloped = envelop({
plugins: [
useEngine({ parse, validate, execute, subscribe }),
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
useSchema(schema),
useMaskedErrors({ maskErrorFn: customFormatError })
]
Expand Down
2 changes: 1 addition & 1 deletion packages/core/docs/use-payload-formatter.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { parse, validate, execute, subscribe } from 'graphql'

const getEnveloped = envelop({
plugins: [
useEngine({ parse, validate, execute, subscribe }),
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
usePayloadFormatter((result, executionArgs) => {
// Return a modified result here,
// Or `false`y value to keep it as-is.
Expand Down
4 changes: 2 additions & 2 deletions packages/core/docs/use-schema-by-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This plugin is the simplest plugin for specifying your GraphQL schema. You can s

```ts
import { envelop, useSchemaByContext, useEngine } from '@envelop/core'
import { parse, validate, execute, subscribe } from 'graphql'
import { parse, validate, specifiedRules, execute, subscribe } from 'graphql'

async function getSchema({ req }): GraphQLSchema {
if (req.isAdmin) {
Expand All @@ -16,7 +16,7 @@ async function getSchema({ req }): GraphQLSchema {

const getEnveloped = envelop({
plugins: [
useEngine({ parse, validate, execute, subscribe }),
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
useSchemaByContext(getSchema)
// ... other plugins ...
]
Expand Down
4 changes: 2 additions & 2 deletions packages/core/docs/use-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ This plugin is the simplest plugin for specifying your GraphQL schema. You can s

```ts
import { envelop, useSchema, useEngine } from '@envelop/core'
import { parse, validate, execute, subscribe } from 'graphql'
import { parse, validate, specifiedRules, execute, subscribe } from 'graphql'

const mySchema = buildSchema(/* ... */)

const getEnveloped = envelop({
plugins: [
useEngine({ parse, validate, execute, subscribe }),
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
useSchema(mySchema)
// ... other plugins ...
]
Expand Down
3 changes: 0 additions & 3 deletions packages/core/src/orchestrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,6 @@ export function createEnvelopOrchestrator<PluginsContext extends DefaultContext>
validateFn,
addValidationRule: rule => {
if (!actualRules) {
// Ideally we should provide default validation rules here.
// eslint-disable-next-line no-console
console.warn('No default validation rules provided.');
actualRules = [];
}

Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/plugins/use-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ type UseEngineOptions = {
execute?: ExecuteFunction;
parse?: ParseFunction;
validate?: ValidateFunction;
specifiedRules?: readonly any[];
subscribe?: SubscribeFunction;
};

Expand All @@ -19,10 +20,11 @@ export const useEngine = (engine: UseEngineOptions): Plugin => {
setParseFn(engine.parse);
}
},
onValidate: ({ setValidationFn }) => {
onValidate: ({ setValidationFn, addValidationRule }) => {
if (engine.validate) {
setValidationFn(engine.validate);
}
engine.specifiedRules?.map(addValidationRule);
},
onSubscribe: ({ setSubscribeFn }) => {
if (engine.subscribe) {
Expand Down
30 changes: 28 additions & 2 deletions packages/core/test/validate.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('validate', () => {
schema: expect.any(GraphQLSchema),
documentAST: expect.any(Object),
options: undefined,
rules: undefined,
rules: expect.any(Array),
typeInfo: undefined,
},
addValidationRule: expect.any(Function),
Expand Down Expand Up @@ -51,7 +51,7 @@ describe('validate', () => {
expect(replacementFn).toHaveBeenCalledWith(
expect.any(GraphQLSchema),
expect.any(Object),
undefined,
expect.any(Array),
undefined,
undefined
);
Expand Down Expand Up @@ -147,4 +147,30 @@ describe('validate', () => {
expect(r.errors!.length).toBe(1);
expect(r.errors![0].message).toBe('Invalid!');
});

it('Should not replace default rules when adding new ones', async () => {
const teskit = createTestkit(
[
{
onValidate: ({ addValidationRule }) => {
addValidationRule(
() => ({}) // noop
);
},
},
],
schema
);

const r = await teskit.execute('{ woah }');
assertSingleExecutionValue(r);

expect(r).toMatchInlineSnapshot(`
Object {
"errors": Array [
[GraphQLError: Cannot query field "woah" on type "Query".],
],
}
`);
});
});
4 changes: 2 additions & 2 deletions packages/plugins/apollo-datasources/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ yarn add @envelop/apollo-datasources
## Usage Example

```ts
import { parse, validate, execute, subscribe } from 'graphql'
import { parse, validate, specifiedRules, execute, subscribe } from 'graphql'
import { envelop, useEngine } from '@envelop/core'
import { useApolloDataSources } from '@envelop/apollo-datasources'
import { RESTDataSource } from 'apollo-datasource-rest'
Expand All @@ -37,7 +37,7 @@ class MoviesAPI extends RESTDataSource {

const getEnveloped = envelop({
plugins: [
useEngine({ parse, validate, execute, subscribe }),
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
// ... other plugins ...
useApolloDataSources({
dataSources() {
Expand Down
4 changes: 2 additions & 2 deletions packages/plugins/apollo-federation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ yarn add @envelop/apollo-federation

```ts
import { envelop, useEngine } from '@envelop/core'
import { parse, validate, execute, subscribe } from 'graphql'
import { parse, validate, specifiedRules, execute, subscribe } from 'graphql'
import { ApolloGateway } from '@apollo/gateway'
import { useApolloFederation } from '@envelop/apollo-federation'

Expand All @@ -31,7 +31,7 @@ await gateway.load()
// Then pass it to the plugin configuration
const getEnveloped = envelop({
plugins: [
useEngine({ parse, validate, execute, subscribe }),
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
// ... other plugins ...
useApolloFederation({ gateway })
]
Expand Down
4 changes: 2 additions & 2 deletions packages/plugins/apollo-server-errors/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ yarn add @envelop/apollo-server-errors
## Usage Example

```ts
import { parse, validate, execute, subscribe } from 'graphql'
import { parse, validate, specifiedRules, execute, subscribe } from 'graphql'
import { envelop, useEngine } from '@envelop/core'
import { useApolloServerErrors } from '@envelop/apollo-server-errors'

const getEnveloped = envelop({
plugins: [
useEngine({ parse, validate, execute, subscribe }),
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
// ... other plugins ...
useApolloServerErrors({
// All fields are optional, and should match what you pass today to ApolloServer
Expand Down
4 changes: 2 additions & 2 deletions packages/plugins/apollo-tracing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ yarn add @envelop/apollo-tracing
## Usage Example

```ts
import { parse, validate, execute, subscribe } from 'graphql'
import { parse, validate, specifiedRules, execute, subscribe } from 'graphql'
import { envelop, useEngine } from '@envelop/core'
import { useApolloTracing } from '@envelop/apollo-tracing'

const getEnveloped = envelop({
plugins: [
useEngine({ parse, validate, execute, subscribe }),
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
// ... other plugins ...
useApolloTracing()
]
Expand Down
4 changes: 2 additions & 2 deletions packages/plugins/auth0/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ We recommend using the [Adding Authentication with Auth0 guide](https://www.enve
4. Setup Envelop with that plugin:

```ts
import { parse, validate, execute, subscribe } from 'graphql'
import { parse, validate, specifiedRules, execute, subscribe } from 'graphql'
import { envelop, useEngine } from '@envelop/core'
import { useAuth0 } from '@envelop/auth0'

const getEnveloped = envelop({
plugins: [
useEngine({ parse, validate, execute, subscribe }),
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
// ... other plugins ...
useAuth0({
onError: e => {}, // In case of an error, you can override it and customize the error your client will get.
Expand Down
Loading

0 comments on commit 1da52ee

Please sign in to comment.