From 1da52eefcf198150b77db35733ad2b31018f9419 Mon Sep 17 00:00:00 2001 From: Denis Badurina Date: Thu, 13 Oct 2022 17:57:39 +0200 Subject: [PATCH] `useEngine` accepts GraphQL's specifiedRules (#1557) * failing test * useengine accepts specifiedRules * changeset * missed doc updates * simplify map * simplify even further --- .changeset/weak-lobsters-fetch.md | 5 +++ README.md | 4 +- benchmark/app.js | 12 +++--- packages/core/docs/use-engine.md | 3 +- packages/core/docs/use-error-handler.md | 4 +- packages/core/docs/use-extend-context.md | 4 +- packages/core/docs/use-logger.md | 4 +- packages/core/docs/use-masked-errors.md | 12 +++--- packages/core/docs/use-payload-formatter.md | 2 +- packages/core/docs/use-schema-by-context.md | 4 +- packages/core/docs/use-schema.md | 4 +- packages/core/src/orchestrator.ts | 3 -- packages/core/src/plugins/use-engine.ts | 4 +- packages/core/test/validate.spec.ts | 30 +++++++++++++- packages/plugins/apollo-datasources/README.md | 4 +- packages/plugins/apollo-federation/README.md | 4 +- .../plugins/apollo-server-errors/README.md | 4 +- packages/plugins/apollo-tracing/README.md | 4 +- packages/plugins/auth0/README.md | 4 +- packages/plugins/dataloader/README.md | 4 +- packages/plugins/depth-limit/README.md | 4 +- .../plugins/disable-introspection/README.md | 4 +- .../execute-subscription-event/README.md | 8 ++-- .../plugins/extended-validation/README.md | 8 ++-- .../plugins/filter-operation-type/README.md | 7 +++- packages/plugins/fragment-arguments/README.md | 4 +- packages/plugins/generic-auth/README.md | 12 +++--- packages/plugins/graphql-jit/README.md | 12 +++--- packages/plugins/graphql-middleware/README.md | 4 +- packages/plugins/graphql-modules/README.md | 4 +- .../plugins/immediate-introspection/README.md | 8 ++-- packages/plugins/live-query/README.md | 4 +- packages/plugins/newrelic/README.md | 12 +++--- packages/plugins/on-resolve/README.md | 8 ++-- packages/plugins/opentelemetry/README.md | 8 ++-- .../operation-field-permissions/README.md | 4 +- packages/plugins/parser-cache/README.md | 4 +- .../plugins/persisted-operations/README.md | 14 +++---- packages/plugins/preload-assets/README.md | 4 +- packages/plugins/prometheus/README.md | 12 +++--- packages/plugins/rate-limiter/README.md | 4 +- .../plugins/resource-limitations/README.md | 4 +- .../plugins/response-cache-redis/README.md | 8 ++-- packages/plugins/response-cache/README.md | 12 +++--- packages/plugins/sentry/README.md | 4 +- packages/plugins/statsd/README.md | 4 +- packages/plugins/validation-cache/README.md | 4 +- packages/testing/src/index.ts | 3 +- website/src/pages/v3/composing-envelop.mdx | 3 +- website/src/pages/v3/core.mdx | 23 ++++++----- website/src/pages/v3/getting-started.mdx | 8 ++-- .../adding-a-graphql-response-cache.mdx | 24 +++++------ .../adding-authentication-with-auth0.mdx | 12 +++--- .../v3/guides/integrating-with-databases.mdx | 8 +++- .../v3/guides/migrating-from-v2-to-v3.mdx | 20 +++++----- .../v3/guides/monitoring-and-tracing.mdx | 12 +++--- ...ubscription-data-loader-caching-issues.mdx | 4 +- .../v3/guides/securing-your-graphql-api.mdx | 40 +++++++++---------- ...using-graphql-features-from-the-future.mdx | 8 ++-- .../src/pages/v3/plugins/custom-plugin.mdx | 8 ++-- website/src/pages/v3/plugins/lifecycle.mdx | 4 +- website/src/pages/v3/plugins/typescript.mdx | 3 +- website/src/pages/v3/tracing.mdx | 4 +- 63 files changed, 265 insertions(+), 223 deletions(-) create mode 100644 .changeset/weak-lobsters-fetch.md diff --git a/.changeset/weak-lobsters-fetch.md b/.changeset/weak-lobsters-fetch.md new file mode 100644 index 000000000..2ac89e719 --- /dev/null +++ b/.changeset/weak-lobsters-fetch.md @@ -0,0 +1,5 @@ +--- +'@envelop/core': patch +--- + +useEngine accepts GraphQL's specifiedRules diff --git a/README.md b/README.md index 5b87c8f5d..249ebd9bc 100644 --- a/README.md +++ b/README.md @@ -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)] }) ``` diff --git a/benchmark/app.js b/benchmark/app.js index 7cb748f1d..ef2994536 100644 --- a/benchmark/app.js +++ b/benchmark/app.js @@ -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 }); @@ -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(), @@ -83,7 +83,7 @@ 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(), @@ -91,7 +91,7 @@ const envelopsMap = { }), 'envelop-cache-jit': envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), useSchema(createSchema()), useGraphQlJit(), useParserCache(), @@ -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(), diff --git a/packages/core/docs/use-engine.md b/packages/core/docs/use-engine.md index 1840a6a24..1f3d7e894 100644 --- a/packages/core/docs/use-engine.md +++ b/packages/core/docs/use-engine.md @@ -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 }) diff --git a/packages/core/docs/use-error-handler.md b/packages/core/docs/use-error-handler.md index 060e24953..acb58c807 100644 --- a/packages/core/docs/use-error-handler.md +++ b/packages/core/docs/use-error-handler.md @@ -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 }) diff --git a/packages/core/docs/use-extend-context.md b/packages/core/docs/use-extend-context.md index 9a8137b8f..a2cb0ab87 100644 --- a/packages/core/docs/use-extend-context.md +++ b/packages/core/docs/use-extend-context.md @@ -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: { diff --git a/packages/core/docs/use-logger.md b/packages/core/docs/use-logger.md index 87a3b6eca..29e6ab366 100644 --- a/packages/core/docs/use-logger.md +++ b/packages/core/docs/use-logger.md @@ -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` diff --git a/packages/core/docs/use-masked-errors.md b/packages/core/docs/use-masked-errors.md index 4579c386b..573faa800 100644 --- a/packages/core/docs/use-masked-errors.md +++ b/packages/core/docs/use-masked-errors.md @@ -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 */ ` @@ -33,7 +33,7 @@ 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()] }) ``` @@ -41,12 +41,12 @@ You may customize the default error message `Unexpected error.` with your own `e ```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.' }) ] @@ -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)) { @@ -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 }) ] diff --git a/packages/core/docs/use-payload-formatter.md b/packages/core/docs/use-payload-formatter.md index afaa1dd11..cd5dbceaa 100644 --- a/packages/core/docs/use-payload-formatter.md +++ b/packages/core/docs/use-payload-formatter.md @@ -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. diff --git a/packages/core/docs/use-schema-by-context.md b/packages/core/docs/use-schema-by-context.md index d7a13890e..a082be7a4 100644 --- a/packages/core/docs/use-schema-by-context.md +++ b/packages/core/docs/use-schema-by-context.md @@ -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) { @@ -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 ... ] diff --git a/packages/core/docs/use-schema.md b/packages/core/docs/use-schema.md index 112a19a06..5b922324e 100644 --- a/packages/core/docs/use-schema.md +++ b/packages/core/docs/use-schema.md @@ -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 ... ] diff --git a/packages/core/src/orchestrator.ts b/packages/core/src/orchestrator.ts index 070600d5b..44980b6c6 100644 --- a/packages/core/src/orchestrator.ts +++ b/packages/core/src/orchestrator.ts @@ -227,9 +227,6 @@ export function createEnvelopOrchestrator 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 = []; } diff --git a/packages/core/src/plugins/use-engine.ts b/packages/core/src/plugins/use-engine.ts index 896ace0f7..242377413 100644 --- a/packages/core/src/plugins/use-engine.ts +++ b/packages/core/src/plugins/use-engine.ts @@ -4,6 +4,7 @@ type UseEngineOptions = { execute?: ExecuteFunction; parse?: ParseFunction; validate?: ValidateFunction; + specifiedRules?: readonly any[]; subscribe?: SubscribeFunction; }; @@ -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) { diff --git a/packages/core/test/validate.spec.ts b/packages/core/test/validate.spec.ts index b5f0a9907..c223d99ac 100644 --- a/packages/core/test/validate.spec.ts +++ b/packages/core/test/validate.spec.ts @@ -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), @@ -51,7 +51,7 @@ describe('validate', () => { expect(replacementFn).toHaveBeenCalledWith( expect.any(GraphQLSchema), expect.any(Object), - undefined, + expect.any(Array), undefined, undefined ); @@ -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".], + ], + } + `); + }); }); diff --git a/packages/plugins/apollo-datasources/README.md b/packages/plugins/apollo-datasources/README.md index 936c91b9a..1716495e5 100644 --- a/packages/plugins/apollo-datasources/README.md +++ b/packages/plugins/apollo-datasources/README.md @@ -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' @@ -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() { diff --git a/packages/plugins/apollo-federation/README.md b/packages/plugins/apollo-federation/README.md index 85b9dbd06..1d5d31202 100644 --- a/packages/plugins/apollo-federation/README.md +++ b/packages/plugins/apollo-federation/README.md @@ -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' @@ -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 }) ] diff --git a/packages/plugins/apollo-server-errors/README.md b/packages/plugins/apollo-server-errors/README.md index 05a3ec159..fb381f8e7 100644 --- a/packages/plugins/apollo-server-errors/README.md +++ b/packages/plugins/apollo-server-errors/README.md @@ -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 diff --git a/packages/plugins/apollo-tracing/README.md b/packages/plugins/apollo-tracing/README.md index ef5adba0e..f9295c445 100644 --- a/packages/plugins/apollo-tracing/README.md +++ b/packages/plugins/apollo-tracing/README.md @@ -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() ] diff --git a/packages/plugins/auth0/README.md b/packages/plugins/auth0/README.md index 2af1b6a5c..6328d0d9e 100644 --- a/packages/plugins/auth0/README.md +++ b/packages/plugins/auth0/README.md @@ -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. diff --git a/packages/plugins/dataloader/README.md b/packages/plugins/dataloader/README.md index 4bf3dc01d..560469566 100644 --- a/packages/plugins/dataloader/README.md +++ b/packages/plugins/dataloader/README.md @@ -11,14 +11,14 @@ yarn add dataloader @envelop/dataloader ## 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 DataLoader from 'dataloader' import { useDataLoader } from '@envelop/dataloader' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useDataLoader('users', context => new DataLoader(keys => myBatchGetUsers(keys))) ] diff --git a/packages/plugins/depth-limit/README.md b/packages/plugins/depth-limit/README.md index ca846df4d..c57f704e2 100644 --- a/packages/plugins/depth-limit/README.md +++ b/packages/plugins/depth-limit/README.md @@ -11,13 +11,13 @@ yarn add @envelop/depth-limit ## 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 { useDepthLimit } from '@envelop/depth-limit' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useDepthLimit({ maxDepth: 10 diff --git a/packages/plugins/disable-introspection/README.md b/packages/plugins/disable-introspection/README.md index dccc4e6b6..e7e363c33 100644 --- a/packages/plugins/disable-introspection/README.md +++ b/packages/plugins/disable-introspection/README.md @@ -11,12 +11,12 @@ yarn add @envelop/disable-introspection ## 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 { useDisableIntrospection } from '@envelop/disable-introspection' const getEnveloped = envelop({ - plugins: [useEngine({ parse, validate, execute, subscribe }), useDisableIntrospection()] + plugins: [useEngine({ parse, validate, specifiedRules, execute, subscribe }), useDisableIntrospection()] }) ``` diff --git a/packages/plugins/execute-subscription-event/README.md b/packages/plugins/execute-subscription-event/README.md index ec1192315..8bc939701 100644 --- a/packages/plugins/execute-subscription-event/README.md +++ b/packages/plugins/execute-subscription-event/README.md @@ -7,14 +7,14 @@ Utilities for hooking into the [ExecuteSubscriptionEvent]( createContext()), useContextValuePerExecuteSubscriptionEvent(() => ({ // Existing context is merged with this context partial @@ -31,14 +31,14 @@ const getEnveloped = envelop({ Alternatively, you can also provide a callback that is invoked after each [`ExecuteSubscriptionEvent`]() phase. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useContextValuePerExecuteSubscriptionEvent } from '@envelop/execute-subscription-event' import { createContext, createDataLoaders } from './context' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), useContext(() => createContext()), useContextValuePerExecuteSubscriptionEvent(({ args }) => ({ onEnd: () => { diff --git a/packages/plugins/extended-validation/README.md b/packages/plugins/extended-validation/README.md index 3630bdcd1..7cd8419ca 100644 --- a/packages/plugins/extended-validation/README.md +++ b/packages/plugins/extended-validation/README.md @@ -17,13 +17,13 @@ yarn add @envelop/extended-validation Then, use the plugin with your validation rules: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useExtendedValidation } from '@envelop/extended-validation' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), useExtendedValidation({ rules: [ /* ... your rules here */ @@ -62,13 +62,13 @@ You can use union inputs either via a the SDL flow, by annotating types and fiel First, make sure to add that rule to your plugin usage: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useExtendedValidation, OneOfInputObjectsRule } from '@envelop/extended-validation' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), useExtendedValidation({ rules: [OneOfInputObjectsRule] }) diff --git a/packages/plugins/filter-operation-type/README.md b/packages/plugins/filter-operation-type/README.md index 3fb5b03ec..12ee0ebc3 100644 --- a/packages/plugins/filter-operation-type/README.md +++ b/packages/plugins/filter-operation-type/README.md @@ -11,12 +11,15 @@ yarn add @envelop/filter-operation-type ## 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 { useFilterAllowedOperations } from '@envelop/filter-operation-type' const getEnveloped = envelop({ // only allow execution of subscription operations - plugins: [useEngine({ parse, validate, execute, subscribe }), useFilterAllowedOperations(['subscription'])] + plugins: [ + useEngine({ parse, validate, specifiedRules, execute, subscribe }), + useFilterAllowedOperations(['subscription']) + ] }) ``` diff --git a/packages/plugins/fragment-arguments/README.md b/packages/plugins/fragment-arguments/README.md index 16af0bb60..ada5c09bb 100644 --- a/packages/plugins/fragment-arguments/README.md +++ b/packages/plugins/fragment-arguments/README.md @@ -15,13 +15,13 @@ yarn add @envelop/fragment-arguments ## 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 { useFragmentArguments } from '@envelop/fragment-arguments' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useFragmentArguments() ] diff --git a/packages/plugins/generic-auth/README.md b/packages/plugins/generic-auth/README.md index ba0855672..c8d0d1533 100644 --- a/packages/plugins/generic-auth/README.md +++ b/packages/plugins/generic-auth/README.md @@ -78,7 +78,7 @@ This mode offers complete protection for the entire API. It protects your entire To setup this mode, use the following config: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useGenericAuth, ResolveUserFn, ValidateUserFn } from '@envelop/generic-auth' @@ -94,7 +94,7 @@ const validateUser: ValidateUserFn = params => { const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useGenericAuth({ resolveUserFn, @@ -149,7 +149,7 @@ const GraphQLQueryType = new GraphQLObjectType({ This mode uses the plugin to inject the authenticated user into the `context`, and later you can verify it in your resolvers. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useGenericAuth, ResolveUserFn, ValidateUserFn } from '@envelop/generic-auth' @@ -165,7 +165,7 @@ const validateUser: ValidateUserFn = async params => { const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useGenericAuth({ resolveUserFn, @@ -196,7 +196,7 @@ const resolvers = { This mode is similar to option #2, but it uses the `@auth` SDL directive or `auth` field extension for protecting specific GraphQL fields. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useGenericAuth, ResolveUserFn, ValidateUserFn } from '@envelop/generic-auth' @@ -212,7 +212,7 @@ const validateUser: ValidateUserFn = params => { const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useGenericAuth({ resolveUserFn, diff --git a/packages/plugins/graphql-jit/README.md b/packages/plugins/graphql-jit/README.md index e6eef37fe..23352da35 100644 --- a/packages/plugins/graphql-jit/README.md +++ b/packages/plugins/graphql-jit/README.md @@ -11,13 +11,13 @@ yarn add @envelop/graphql-jit ## 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 { useGraphQlJit } from '@envelop/graphql-jit' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useGraphQlJit( { @@ -36,13 +36,13 @@ const getEnveloped = envelop({ If you wish to conditionally use the JIT executor based on the incoming request, you can use `enableIf` config flag and return a `boolean` based on the `ExecutionArgs`: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useGraphQlJit } from '@envelop/graphql-jit' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useGraphQlJit( { @@ -61,13 +61,13 @@ const getEnveloped = envelop({ You can configure the JIT cache with the following options: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useGraphQlJit } from '@envelop/graphql-jit' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useGraphQlJit( { diff --git a/packages/plugins/graphql-middleware/README.md b/packages/plugins/graphql-middleware/README.md index 76a3c44ec..f8ac2257d 100644 --- a/packages/plugins/graphql-middleware/README.md +++ b/packages/plugins/graphql-middleware/README.md @@ -15,7 +15,7 @@ yarn add graphql-middleware @envelop/graphql-middleware You can use any type of middleware defined for `graphql-middleware`, here's an example for doing that with [`graphql-shield`](https://github.com/maticzav/graphql-shield): ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useGraphQLMiddleware } from '@envelop/graphql-middleware' import { rule, shield, and, or, not } from 'graphql-shield' @@ -37,7 +37,7 @@ const permissions = shield({ const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useSchema(mySchema), useGraphQLMiddleware([permissions]) diff --git a/packages/plugins/graphql-modules/README.md b/packages/plugins/graphql-modules/README.md index 584a12a90..6e1fae912 100644 --- a/packages/plugins/graphql-modules/README.md +++ b/packages/plugins/graphql-modules/README.md @@ -13,7 +13,7 @@ yarn add @envelop/graphql-modules ## 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 { createApplication } from 'graphql-modules' import { useGraphQLModules } from '@envelop/graphql-modules' @@ -26,7 +26,7 @@ const myApp = createApplication({ const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useGraphQLModules(myApp) ] diff --git a/packages/plugins/immediate-introspection/README.md b/packages/plugins/immediate-introspection/README.md index 38b0223e2..5acdbb204 100644 --- a/packages/plugins/immediate-introspection/README.md +++ b/packages/plugins/immediate-introspection/README.md @@ -14,13 +14,13 @@ For simple GraphQL operations that only select introspection fields building a c The `useImmediateIntrospection` can be used to short circuit any further context building if a GraphQL operation selection set only includes introspection fields within the selection set. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useImmediateIntrospection, useEngine } from '@envelop/core' import { schema } from './schema' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), useSchema(schema), useImmediateIntrospection() // additional plugins @@ -31,14 +31,14 @@ const getEnveloped = envelop({ In case you want to authorize that an user is authenticated before allowing introspection the plugin must be placed in front of the `useImmediateIntrospection()` call. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useImmediateIntrospection, useEngine } from '@envelop/core' import { schema } from './schema' import { useAuthorization } from './useAuthorization' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), useSchema(schema), useAuthorization(), // place this before useImmediateIntrospection() diff --git a/packages/plugins/live-query/README.md b/packages/plugins/live-query/README.md index 5cb239f71..f7e8cbfdd 100644 --- a/packages/plugins/live-query/README.md +++ b/packages/plugins/live-query/README.md @@ -27,7 +27,7 @@ yarn add @envelop/live-query @n1ru4l/in-memory-live-query-store ### `makeExecutableSchema` from `graphql-tools` ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useSchema, useExtendContext, useEngine } from '@envelop/core' import { useLiveQuery } from '@envelop/live-query' import { InMemoryLiveQueryStore } from '@n1ru4l/in-memory-live-query-store' @@ -61,7 +61,7 @@ setInterval(() => { const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), useSchema(schema), useLiveQuery({ liveQueryStore }), useExtendContext(() => ({ greetings })) diff --git a/packages/plugins/newrelic/README.md b/packages/plugins/newrelic/README.md index a5ba910ef..0100e8549 100644 --- a/packages/plugins/newrelic/README.md +++ b/packages/plugins/newrelic/README.md @@ -1,6 +1,6 @@ ## `@envelop/newrelic` -Instrument your GraphQL application with New Relic reporting. +Instrument your GraphQL application with New Relic reporting. Take advantage of Distributed tracing to monitor performance and errors whilst ultimately getting to the root cause of issues. Below are some screenshots to show how tracking looks like in New Relic, in these examples all plugin options were set to `true`. @@ -31,13 +31,13 @@ yarn add newrelic @envelop/newrelic ## Basic 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 { useNewRelic } from '@envelop/newrelic' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useNewRelic({ includeOperationDocument: true, // default `false`. When set to `true`, includes the GraphQL document defining the operations and fragments @@ -59,10 +59,10 @@ const getEnveloped = envelop({ ## Advanced usage -The plugin allows you to keep control over the variables and arguments that are tracked in New Relic. +The plugin allows you to keep control over the variables and arguments that are tracked in New Relic. In addition to the basic `true/false` boolean value, `includeExecuteVariables` and `includeResolverArgs` also accept a RegEx pattern. This allows you to implement white and black listing of properties to be tracked in New Relic. -This is particularly useful if you have properties coming through variables and arguments that are useful for debugging, but you don't want to leak users' data (such as PII). +This is particularly useful if you have properties coming through variables and arguments that are useful for debugging, but you don't want to leak users' data (such as PII). Below is a quick example of how you can use RegEx to set up white/black listing functionalities. ```ts @@ -88,7 +88,7 @@ The main methods to configure the New Relic Agent is through: If you choose to use the newrelic.js file, then you need this file located in the root of your application. You can look [here](https://github.com/newrelic/node-newrelic/blob/main/newrelic.js) for a basic example of what this file can look like. -If you choose to configure the New Relic Agent through environment variables, then you can follow your preferred strategy to make sure the variables are set and available when your application starts. +If you choose to configure the New Relic Agent through environment variables, then you can follow your preferred strategy to make sure the variables are set and available when your application starts. The variables are the same you can set in newrelic.js file, you just need to know that they need to start with `NEW_RELIC_`, obviously, the variables name must be fully uppercase. The two variables that are always required are: diff --git a/packages/plugins/on-resolve/README.md b/packages/plugins/on-resolve/README.md index dd271e1c0..c00834ee4 100644 --- a/packages/plugins/on-resolve/README.md +++ b/packages/plugins/on-resolve/README.md @@ -15,14 +15,14 @@ yarn add @envelop/on-resolve ### Custom field resolutions ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useOnResolve } from '@envelop/on-resolve' import { specialResolver } from './my-resolvers' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useOnResolve(async function onResolve({ context, root, args, info, replaceResolver }) { // replace special field's resolver @@ -44,7 +44,7 @@ const getEnveloped = envelop({ ### Tracing ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine, Plugin } from '@envelop/core' import { useOnResolve } from '@envelop/on-resolve' @@ -94,7 +94,7 @@ function useFieldTracing() { const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useSpecialResolve() ] diff --git a/packages/plugins/opentelemetry/README.md b/packages/plugins/opentelemetry/README.md index d4f1ebd47..d585e80ed 100644 --- a/packages/plugins/opentelemetry/README.md +++ b/packages/plugins/opentelemetry/README.md @@ -15,13 +15,13 @@ yarn add @envelop/opentelemetry By default, this plugin prints the collected telemetry to the console: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useOpenTelemetry } from '@envelop/opentelemetry' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useOpenTelemetry({ resolvers: true, // Tracks resolvers calls, and tracks resolvers thrown errors @@ -35,7 +35,7 @@ const getEnveloped = envelop({ If you wish to use custom tracer/exporter, create it and pass it. This example integrates Jaeger tracer: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useOpenTelemetry } from '@envelop/opentelemetry' import { JaegerExporter } from '@opentelemetry/exporter-jaeger' @@ -51,7 +51,7 @@ provider.register() const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useOpenTelemetry( { diff --git a/packages/plugins/operation-field-permissions/README.md b/packages/plugins/operation-field-permissions/README.md index 81d21ec1d..f0bd02640 100644 --- a/packages/plugins/operation-field-permissions/README.md +++ b/packages/plugins/operation-field-permissions/README.md @@ -13,13 +13,13 @@ yarn add @envelop/operation-field-permissions ## Usage Example ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useSchema, useEngine } from '@envelop/core' import { useOperationFieldPermissions } from '@envelop/operation-field-permissions' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), useSchema(schema), useOperationFieldPermissions({ // we can access graphql context here diff --git a/packages/plugins/parser-cache/README.md b/packages/plugins/parser-cache/README.md index 624121de9..c83a93ae0 100644 --- a/packages/plugins/parser-cache/README.md +++ b/packages/plugins/parser-cache/README.md @@ -13,13 +13,13 @@ yarn add @envelop/parser-cache ## 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 { useParserCache } from '@envelop/parser-cache' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useParserCache({ // options goes here diff --git a/packages/plugins/persisted-operations/README.md b/packages/plugins/persisted-operations/README.md index 042f7d861..28414b759 100644 --- a/packages/plugins/persisted-operations/README.md +++ b/packages/plugins/persisted-operations/README.md @@ -15,7 +15,7 @@ yarn add @envelop/persisted-operations The most basic implementation can use an in-memory JS `Map` wrapper with a `Store` object: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { usePersistedOperations, InMemoryStore } from '@envelop/persisted-operations' @@ -30,7 +30,7 @@ const store = new InMemoryStore({ const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... usePersistedOperations({ store: myStore @@ -60,7 +60,7 @@ usePersistedOperations({ ## Usage Example with built-in JsonFileStore ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { usePersistedOperations, JsonFileStore } from '@envelop/persisted-operations' @@ -75,7 +75,7 @@ await persistedOperationsStore.loadFromFile(filePath) // load and parse persiste const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... usePersistedOperations({ store: persistedOperationsStore @@ -89,12 +89,12 @@ const getEnveloped = envelop({ The `store` parameter accepts both a `Store` instance, or a function. If you need to support multiple stores (based on incoming GraphQL operation/HTTP request), you can provide a function to toggle between the stores, based on your needs: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... usePersistedOperations({ store: context => { @@ -120,7 +120,7 @@ You can pass `onlyPersisted: true` when you want to allow persisted operations o ### onMissingMatch -You might want to perform some actions, such as logging custom events, when your operation Id is not matched in your store/s; in this case you can use the `onMissingMatch` callback function. +You might want to perform some actions, such as logging custom events, when your operation Id is not matched in your store/s; in this case you can use the `onMissingMatch` callback function. The function receives the context and operationId as arguments, so you can use it like so: ```js diff --git a/packages/plugins/preload-assets/README.md b/packages/plugins/preload-assets/README.md index 43bfed6a9..9c5c1dc21 100644 --- a/packages/plugins/preload-assets/README.md +++ b/packages/plugins/preload-assets/README.md @@ -12,7 +12,7 @@ yarn add @envelop/preload-assets ``` ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { usePreloadAssets } from '@envelop/preload-asset' import { makeExecutableSchema } from 'graphql' @@ -35,7 +35,7 @@ const schema = makeExecutableSchema({ }) const getEnveloped = envelop({ - plugins: [useEngine({ parse, validate, execute, subscribe }), usePreloadAssets()] + plugins: [useEngine({ parse, validate, specifiedRules, execute, subscribe }), usePreloadAssets()] }) ``` diff --git a/packages/plugins/prometheus/README.md b/packages/plugins/prometheus/README.md index e2f01c526..d68ad2c70 100644 --- a/packages/plugins/prometheus/README.md +++ b/packages/plugins/prometheus/README.md @@ -26,13 +26,13 @@ yarn add prom-client @envelop/prometheus ## 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 { usePrometheus } from '@envelop/prometheus' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... usePrometheus({ // all optional, and by default, all set to false, please opt-in to the metrics you wish to get @@ -59,7 +59,7 @@ const getEnveloped = envelop({ You can customize the `prom-client` `Registry` object if you are using a custom one, by passing it along with the configuration object: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { Registry } from 'prom-client' @@ -67,7 +67,7 @@ const myRegistry = new Registry() const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... usePrometheus({ // ... config ... @@ -88,14 +88,14 @@ If you wish to disable introspection logging, you can use `skipIntrospection: tr Each tracing field supports custom `prom-client` objects, and custom `labels` a metadata, you can create a custom extraction function for every `Histogram` / `Summary` / `Counter`: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { Histogram } from 'prom-client' import { envelop, useEngine } from '@envelop/core' import { createHistogram, usePrometheus } from '@envelop/prometheus' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... usePrometheus({ // all optional, and by default, all set to false, please opt-in to the metrics you wish to get diff --git a/packages/plugins/rate-limiter/README.md b/packages/plugins/rate-limiter/README.md index bcd66b293..906e93c0a 100644 --- a/packages/plugins/rate-limiter/README.md +++ b/packages/plugins/rate-limiter/README.md @@ -11,7 +11,7 @@ yarn add @envelop/rate-limiter ## 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 { useRateLimiter, IdentifyFn } from '@envelop/rate-limiter' @@ -21,7 +21,7 @@ const identifyFn: IdentifyFn = async context => { const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useRateLimiter({ identifyFn diff --git a/packages/plugins/resource-limitations/README.md b/packages/plugins/resource-limitations/README.md index c1c418c9c..91b994f08 100644 --- a/packages/plugins/resource-limitations/README.md +++ b/packages/plugins/resource-limitations/README.md @@ -11,13 +11,13 @@ yarn add @envelop/resource-limitations ## 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 { useResourceLimitations } from '@envelop/resource-limitations' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useResourceLimitations({ nodeCostLimit: 500000, // optional, default to 500000 diff --git a/packages/plugins/response-cache-redis/README.md b/packages/plugins/response-cache-redis/README.md index af284623f..47b4b5939 100644 --- a/packages/plugins/response-cache-redis/README.md +++ b/packages/plugins/response-cache-redis/README.md @@ -22,7 +22,7 @@ In order to use the Redis cache, you need to: - Create an instance of the Redis Cache and set to the `useResponseCache` plugin options ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useResponseCache } from '@envelop/response-cache' import { createRedisCache } from '@envelop/response-cache-redis' @@ -46,7 +46,7 @@ const cache = createRedisCache({ redis }) const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useResponseCache({ cache }) ] @@ -56,7 +56,7 @@ const getEnveloped = envelop({ ### Invalidate Cache based on custom logic ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useResponseCache } from '@envelop/response-cache' import { createRedisCache } from '@envelop/response-cache-redis' @@ -70,7 +70,7 @@ const cache = createRedisCache({ redis }) const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useResponseCache({ ttl: 2000, diff --git a/packages/plugins/response-cache/README.md b/packages/plugins/response-cache/README.md index d738adbc3..e63ee6ee7 100644 --- a/packages/plugins/response-cache/README.md +++ b/packages/plugins/response-cache/README.md @@ -38,13 +38,13 @@ When configuring the `useResponseCache`, you can choose the type of cache: The in-memory LRU cache is used by default. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useResponseCache } from '@envelop/response-cache' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useResponseCache({ // use global cache for all operations @@ -57,7 +57,7 @@ const getEnveloped = envelop({ Or, you may create the in-memory LRU cache explicitly. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useResponseCache, createInMemoryCache } from '@envelop/response-cache' @@ -65,7 +65,7 @@ const cache = createInMemoryCache() const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useResponseCache({ cache, @@ -80,13 +80,13 @@ const getEnveloped = envelop({ ### Cache based on session/user ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useResponseCache } from '@envelop/response-cache' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useResponseCache({ ttl: 2000, diff --git a/packages/plugins/sentry/README.md b/packages/plugins/sentry/README.md index cb6f8c3e0..57a5a181c 100644 --- a/packages/plugins/sentry/README.md +++ b/packages/plugins/sentry/README.md @@ -30,7 +30,7 @@ yarn add @sentry/node @sentry/tracing @envelop/sentry ## 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 { useSentry } from '@envelop/sentry' // do this only once in you entry file. @@ -38,7 +38,7 @@ import '@sentry/tracing' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useSentry({ includeRawResult: false, // set to `true` in order to include the execution result in the metadata collected diff --git a/packages/plugins/statsd/README.md b/packages/plugins/statsd/README.md index 056b2f40e..0d6c6ab97 100644 --- a/packages/plugins/statsd/README.md +++ b/packages/plugins/statsd/README.md @@ -25,7 +25,7 @@ yarn add hot-shots @envelop/stats ## 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 { useStatsD } from '@envelop/statsd' import StatsD from 'hot-shots' @@ -37,7 +37,7 @@ const client = new StatsD({ const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useStatsD({ client, diff --git a/packages/plugins/validation-cache/README.md b/packages/plugins/validation-cache/README.md index 42d37dd20..a10b00c56 100644 --- a/packages/plugins/validation-cache/README.md +++ b/packages/plugins/validation-cache/README.md @@ -13,13 +13,13 @@ yarn add @envelop/validation-cache ## 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 { useValidationCache } from '@envelop/validation-cache' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useValidationCache({ // options goes here diff --git a/packages/testing/src/index.ts b/packages/testing/src/index.ts index ee1d9b3d8..7b80686d8 100644 --- a/packages/testing/src/index.ts +++ b/packages/testing/src/index.ts @@ -9,13 +9,14 @@ import { parse, subscribe, validate, + specifiedRules, } from 'graphql'; import { useSchema, envelop, isAsyncIterable, useEngine } from '@envelop/core'; import { GetEnvelopedFn, Plugin } from '@envelop/types'; import { mapSchema as cloneSchema, isDocumentNode } from '@graphql-tools/utils'; export const useGraphQLJSEngine = () => { - return useEngine({ parse, validate, execute, subscribe }); + return useEngine({ parse, validate, specifiedRules, execute, subscribe }); }; export type ModifyPluginsFn = (plugins: Plugin[]) => Plugin[]; diff --git a/website/src/pages/v3/composing-envelop.mdx b/website/src/pages/v3/composing-envelop.mdx index 0faedacff..a34904e42 100644 --- a/website/src/pages/v3/composing-envelop.mdx +++ b/website/src/pages/v3/composing-envelop.mdx @@ -8,7 +8,7 @@ This allows writing shareable pieces that can be used. Here's a small example for sharing envelops: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEnvelop, useSchema, useEngine } from '@envelop/core' // Somewhere where you wish to create the basics of what you wish to share @@ -24,6 +24,7 @@ const myEnvelop = envelop({ useEngine({ parse, validate, + specifiedRules, execute, subscribe }), diff --git a/website/src/pages/v3/core.mdx b/website/src/pages/v3/core.mdx index 92d13095f..01457dce1 100644 --- a/website/src/pages/v3/core.mdx +++ b/website/src/pages/v3/core.mdx @@ -12,13 +12,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 ] @@ -31,11 +31,11 @@ This plugin invokes a custom function every time execution encounters an error. ```ts import { envelop, useErrorHandler, 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, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), useErrorHandler(error => { // This callback is called per each GraphQLError emitted during the execution phase }) @@ -55,11 +55,11 @@ Easily extends the context with custom fields. ```ts import { envelop, useExtendContext, 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, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), useExtendContext(async contextSoFar => { return { myCustomField: { @@ -78,11 +78,11 @@ Logs parameters and information about the execution phases. You can easily plug ```ts import { envelop, useLogger, 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, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), useLogger({ logFn(eventName, args) { // Event could be `execute-start` / `execute-end` / `subscribe-start` / `subscribe-end` @@ -102,11 +102,11 @@ The second argument `executionArgs` provides additional information for your for ```ts import { envelop, usePayloadFormatter, 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, 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. @@ -122,7 +122,7 @@ 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' import { parser } from 'my-custom-graphql-parser' const getEnveloped = envelop({ @@ -130,6 +130,7 @@ const getEnveloped = envelop({ useEngine({ parse, validate, + specifiedRules, execute, subscribe }) diff --git a/website/src/pages/v3/getting-started.mdx b/website/src/pages/v3/getting-started.mdx index 48b68aaa2..d3a80c08a 100644 --- a/website/src/pages/v3/getting-started.mdx +++ b/website/src/pages/v3/getting-started.mdx @@ -20,7 +20,7 @@ Start by adding the core of `envelop` and `graphql` to your codebase. After installing the `@envelop/core` package, you can use the `envelop` function for creating your `getEnveloped` function. We use a simple GraphQL schema that we build with the `buildSchema` function from `graphql`. ```ts -import { parse, validate, execute, subcribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subcribe } from 'graphql' import { envelop, useSchema, useEngine } from '@envelop/core' import { buildSchema } from 'graphql' @@ -31,7 +31,7 @@ const schema = buildSchema(/* GraphQL */ ` `) export const getEnveloped = envelop({ - plugins: [useEngine({ parse, validate, execute, subscribe }), useSchema(schema)] + plugins: [useEngine({ parse, validate, specifiedRules, execute, subscribe }), useSchema(schema)] }) ``` @@ -62,7 +62,7 @@ Let's add a parser and validation cache, so sending the same operation string se ```ts -import { parse, validate, execute, subcribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subcribe } from 'graphql' import { envelop, useSchema, useEngine } from '@envelop/core' import { buildSchema } from 'graphql' import { useParserCache } from '@envelop/parser-cache' @@ -76,7 +76,7 @@ const schema = buildSchema(/* GraphQL */ ` const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // all enabled plugins useSchema(schema), useParserCache(), diff --git a/website/src/pages/v3/guides/adding-a-graphql-response-cache.mdx b/website/src/pages/v3/guides/adding-a-graphql-response-cache.mdx index 5dc6afda5..9e18c8a35 100644 --- a/website/src/pages/v3/guides/adding-a-graphql-response-cache.mdx +++ b/website/src/pages/v3/guides/adding-a-graphql-response-cache.mdx @@ -190,13 +190,13 @@ The goal of the response cache plugin is to educate how such mechanisms are impl Adding a response cache to an existing envelop GraphQL server setup is as easy as adding the plugin: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useResponseCache } from '@envelop/response-cache' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useResponseCache() ] @@ -206,7 +206,7 @@ const getEnveloped = envelop({ If you need to imperatively invalidate you can do that by providing the cache to the plugin: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useResponseCache, createInMemoryCache } from '@envelop/response-cache' import { emitter } from './event-emitter' @@ -224,7 +224,7 @@ emitter.on('invalidate', entity => { const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useResponseCache({ cache }) ] @@ -234,13 +234,13 @@ const getEnveloped = envelop({ The caching behavior can be fully customized. A TTL can be provided as global or more granular per type or schema coordinate. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useResponseCache } from '@envelop/response-cache' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useResponseCache({ // cache operations for 1 hour by default @@ -263,13 +263,13 @@ const getEnveloped = envelop({ Need to cache based on the user? No problem. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useResponseCache } from '@envelop/response-cache' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useResponseCache({ // context is the GraphQL context that would be used for execution @@ -284,13 +284,13 @@ const getEnveloped = envelop({ Don't want to automatically invalidate based on mutations? Also configurable! ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useResponseCache } from '@envelop/response-cache' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useResponseCache({ // some might prefer invalidating only based on a database write log @@ -313,7 +313,7 @@ Once you have that, gather up the necessary connection settings (e.g., `host`, ` Then, with that instance of the Redis Cache setup, provide it to the `useResponseCache` plugin options, and you're done. Here's an example: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useResponseCache } from '@envelop/response-cache' import { createRedisCache } from '@envelop/response-cache-redis' @@ -331,7 +331,7 @@ const cache = createRedisCache({ redis }) const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useResponseCache({ cache }) ] diff --git a/website/src/pages/v3/guides/adding-authentication-with-auth0.mdx b/website/src/pages/v3/guides/adding-authentication-with-auth0.mdx index 1003cbf59..d95b85f3e 100644 --- a/website/src/pages/v3/guides/adding-authentication-with-auth0.mdx +++ b/website/src/pages/v3/guides/adding-authentication-with-auth0.mdx @@ -21,13 +21,13 @@ We start by installing the package into our envelop setup with your favorite Pac ```ts import { engine, useSchema, useEngine } from '@envelop/core' import { useAuth0 } from '@envelop/auth0' -import { parse, execute, subcribe, validate } from 'graphql' +import { parse, execute, subcribe, validate, specifiedRules } from 'graphql' // ... other imports and code const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), useSchema(schema), useAuth0({ domain: 'TODO', @@ -85,14 +85,14 @@ Let's quickly add this information to our envelop setup. ```ts import { envelop, useEngine, useSchema } from '@envelop/core' -import { parse, execute, subcribe, validate } from 'graphql' +import { parse, execute, subcribe, validate, specifiedRules } from 'graphql' import { useAuth0 } from '@envelop/auth0' // ... other imports and code const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), useSchema(schema), useAuth0({ domain: '{account_name}.{region}.auth0.com', @@ -270,13 +270,13 @@ In the GraphQL schema of this guide, we only re-expose the auth0 authentication A full user object could be loaded when building the context via the [`useExtendContext` plugin](/plugins/use-extend-context). ```ts -import { parse, execute, subcribe, validate } from 'graphql' +import { parse, execute, subcribe, validate, specifiedRules } from 'graphql' import { envelop, useEngine, useSchema, useExtendContext } from '@envelop/core' import { useAuth0 } from '@envelop/auth0' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), useSchema(schema), useAuth0(auth0Config), useExtendContext(async context => { diff --git a/website/src/pages/v3/guides/integrating-with-databases.mdx b/website/src/pages/v3/guides/integrating-with-databases.mdx index ba0202eb5..7fa4c2528 100644 --- a/website/src/pages/v3/guides/integrating-with-databases.mdx +++ b/website/src/pages/v3/guides/integrating-with-databases.mdx @@ -40,7 +40,7 @@ The better way to avoid this is to open only one client per request. With Envelo a plugin that adds a client to the context add releases it at the end of the request execution. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { isAsyncIterable, useEngine } from '@envelop/core' import { useSchema } from './use-schema' @@ -68,7 +68,11 @@ const resolvers = { } const getEnvelop = envelop({ - plugins: [useEngine({ parse, validate, execute, subscribe }), useSchema(/*...*/), databaseClientPlugin] + plugins: [ + useEngine({ parse, validate, specifiedRules, execute, subscribe }), + useSchema(/*...*/), + databaseClientPlugin + ] }) ``` diff --git a/website/src/pages/v3/guides/migrating-from-v2-to-v3.mdx b/website/src/pages/v3/guides/migrating-from-v2-to-v3.mdx index 48a994b11..48b7719d2 100644 --- a/website/src/pages/v3/guides/migrating-from-v2-to-v3.mdx +++ b/website/src/pages/v3/guides/migrating-from-v2-to-v3.mdx @@ -9,10 +9,10 @@ We have designed the new `envelop` to be engine agnostic. This means that `graph ```diff - import { envelop } from '@envelop/core'; + import { envelop, useEngine } from '@envelop/core'; -+ import { parse, validate, execute, subscribe } from 'graphql'; ++ import { parse, validate, specifiedRules, execute, subscribe } from 'graphql'; - const getEnveloped = envelop([ ... ]) -+ const getEnveloped = envelop({ plugins: [ useEngine({ parse, validate, execute, subscribe }), ... ] }) ++ const getEnveloped = envelop({ plugins: [ useEngine({ parse, validate, specifiedRules, execute, subscribe }), ... ] }) ``` ## 2. Removed orchestrator tracing @@ -24,7 +24,7 @@ We have designed the new `envelop` to be engine agnostic. This means that `graph We decided to drop `onResolverCalled` hook and instead [provide a new plugin](https://github.com/n1ru4l/envelop/pull/1500) that will let you hook into this phase. ```diff -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules,execute, subscribe } from 'graphql' import { envelop, Plugin, useEngine } from '@envelop/core' + import { useOnResolve } from '@envelop/on-resolve' @@ -41,7 +41,7 @@ function useResolve(): Plugin { const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate,specifiedRules, execute, subscribe }), // ... other plugins ... useResolve(), ], @@ -88,13 +88,13 @@ You should first load your schema and then create the envelop instance and pass ```ts import { envelop, useSchema, useEngine } from '@envelop/core' -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' // This assumes you are using Node v14.8+ where top-level await is supported const schema = await loadSchema() const getEnveloped = envelop({ - plugins: [useEngine({ parse, validate, execute, subscribe }), useSchema(schema)] + plugins: [useEngine({ parse, validate, specifiedRules, execute, subscribe }), useSchema(schema)] }) ``` @@ -109,13 +109,13 @@ This utility was used to enable plugins conditionally. For a better developer ex ```diff - import { envelop, useMaskedErrors, enableIf } from '@envelop/core' + import { envelop, useMaskedErrors, useEngine } from '@envelop/core' -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules,execute, subscribe } from 'graphql' const isProd = process.env.NODE_ENV === 'production' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // This plugin is enabled only in production - enableIf(isProd, useMaskedErrors()) + isProd && useMaskedErrors() @@ -130,7 +130,7 @@ const getEnveloped = envelop({ ```diff import { envelop, useMaskedErrors, useEngine, isGraphQLError } from '@envelop/core' -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' export const customFormatError: MaskError = err => { if (isGraphQLError(err)) { @@ -141,7 +141,7 @@ export const customFormatError: MaskError = err => { const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), - useMaskedErrors({ formatError: customFormatError }) + useMaskedErrors({ maskError: customFormatError }) ] diff --git a/website/src/pages/v3/guides/monitoring-and-tracing.mdx b/website/src/pages/v3/guides/monitoring-and-tracing.mdx index 77aef0686..c6d88c4fd 100644 --- a/website/src/pages/v3/guides/monitoring-and-tracing.mdx +++ b/website/src/pages/v3/guides/monitoring-and-tracing.mdx @@ -11,13 +11,13 @@ Sentry is the biggest player regarding error tracking within JavaScript land. Wi As with any other envelop plugin, the setup is straight forward! ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useSentry } from '@envelop/sentry' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useSentry() ] @@ -49,13 +49,13 @@ If you wish to integrate NewRelic for tracing, monitoring and error reporting, y As with any other envelop plugin the setup is straight forward! ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useNewRelic } from '@envelop/newrelic' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useNewRelic({ // ... @@ -71,13 +71,13 @@ const getEnveloped = envelop({ Apollo introduced the apollo-tracing specification and implemented it in apollo-server. With envelop it is possible to use apollo-tracing for tracking down slow resolvers with any server. ```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() ] diff --git a/website/src/pages/v3/guides/resolving-subscription-data-loader-caching-issues.mdx b/website/src/pages/v3/guides/resolving-subscription-data-loader-caching-issues.mdx index ff1cd299b..5cfc876ed 100644 --- a/website/src/pages/v3/guides/resolving-subscription-data-loader-caching-issues.mdx +++ b/website/src/pages/v3/guides/resolving-subscription-data-loader-caching-issues.mdx @@ -45,14 +45,14 @@ const GraphQLSubscriptionType = new GraphQLObjectType({ As your project scales this, however, can become a tedious task. With the `useContextValuePerExecuteSubscriptionEvent` plugin we abstracted this away by having a generic solution for extending the original context with a new part before the subscription event is being executed. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useContextValuePerExecuteSubscriptionEvent } from '@envelop/execute-subscription-event' import { createContext, createDataLoaders } from './context' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useContext(() => createContext()), useContextValuePerExecuteSubscriptionEvent(() => ({ diff --git a/website/src/pages/v3/guides/securing-your-graphql-api.mdx b/website/src/pages/v3/guides/securing-your-graphql-api.mdx index 3dbd1399a..6143753ed 100644 --- a/website/src/pages/v3/guides/securing-your-graphql-api.mdx +++ b/website/src/pages/v3/guides/securing-your-graphql-api.mdx @@ -68,7 +68,7 @@ Instead of allowing any arbitrary GraphQL operation in production usage, we coul With the [`usePersistedOperations`](/plugins/use-persisted-operations) plugin such an extracted map can easily be used for allow-listing such operations. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { usePersistedOperations, PersistedOperationsStore } from '@envelop/persisted-operations' import persistedOperations from './codegen-artifact' @@ -80,7 +80,7 @@ const store: PersistedOperationsStore = { const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... usePersistedOperations({ store: myStore, @@ -125,13 +125,13 @@ Learn more about `graphql-inspector audit` [here](https://the-guild.dev/graphql/ You can limit the amount of allowed tokens per operation and automatically abort any further processing of a GraphQL operation document that exceeds the limit with the `maxTokensPlugin`. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { maxTokensPlugin } from '@escape.tech/graphql-armor-max-tokens' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... maxTokensPlugin({ maxTokenCount: 1000 // Number of tokens allowed in a document @@ -148,13 +148,13 @@ protection. The [`maxDepthPlugin`](/plugins/graphql-armor-max-depth) allows a maximum nesting level an operation is allowed to have. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { maxDepthPlugin } from '@escape.tech/graphql-armor-max-depth' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... maxDepthPlugin({ n: 10 // Number of depth allowed @@ -176,13 +176,13 @@ Rate-limiting is a common practice with APIs, and with GraphQL it gets more comp The [`useRateLimiter`](/plugins/use-rate-limiter) to limit access to resources, by a field level. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useRateLimiter } from '@envelop/rate-limiter' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useRateLimiter({ // ... @@ -215,13 +215,13 @@ With the `@envelop/auth0` plugin, you can simply bootstrap the authorization pro ```tsx import { envelop, useExtendContext, useSchema, useEngine } from '@envelop/core' -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { useAuth0 } from '@envelop/auth0' import { schema } from './schema' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), useSchema(schema), useAuth0({ domain: 'YOUR_AUTH0_DOMAIN_HERE', @@ -273,13 +273,13 @@ With the `useSchemaByContext` plugin it is possible to dynamically select a sche Libraries such as [`graphql-public-schema-filter`](https://github.com/n1ru4l/graphql-public-schema-filter) can be used for generating a schema with only access to a sub part of the original schema using either SDL directives or schema field extensions. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useSchemaByContext, useEngine } from '@envelop/core' import { privateSchema, publicSchema } from './schema' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins (e.g. useAuth0) useSchemaByContext(context => (context.isPrivateApiUser ? privateSchema : publicSchema)) ] @@ -293,14 +293,14 @@ With the `useOperationFieldPermissions` plugin you can automatically reject Grap This plugin is perfect for use-cases where you want the whole schema being introspectable, but restrict access to a certain part of the Graph only to specific users. E.g. in a payment subscription model, where API users should only have access to the data that is included within the plan. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useSchema, useEngine } from '@envelop/core' import { useOperationFieldPermissions } from '@envelop/operation-field-permissions' import { schema } from './schema' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins (e.g. useAuth0) useSchema(schema), useOperationFieldPermissions({ @@ -346,7 +346,7 @@ In most GraphQL servers any thrown error or rejected promise will result in the ```tsx import { envelop, useSchema, useMaskedErrors, EnvelopError, useEngine } from '@envelop/core' -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { makeExecutableSchema } from '@graphql-tools/schema' const schema = makeExecutableSchema({ @@ -376,7 +376,7 @@ 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()] }) ``` @@ -388,11 +388,11 @@ If your schema includes sensitive information that you want to hide from the out ```ts import { envelop, useEngine } from '@envelop/core' -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { useDisableIntrospection } from '@envelop/disable-introspection' const getEnveloped = envelop({ - plugins: [useEngine({ parse, validate, execute, subscribe }), useDisableIntrospection()] + plugins: [useEngine({ parse, validate, specifiedRules, execute, subscribe }), useDisableIntrospection()] }) ``` @@ -406,11 +406,11 @@ If you disabled schema introspection, you should also disable field suggestions ```ts import { envelop, useEngine } from '@envelop/core' -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { useRateLimiter } from '@envelop/rate-limiter' import { blockFieldSuggestions } from '@escape.tech/graphql-armor-block-field-suggestions' const getEnveloped = envelop({ - plugins: [useEngine({ parse, validate, execute, subscribe }), blockFieldSuggestions()] + plugins: [useEngine({ parse, validate, specifiedRules, execute, subscribe }), blockFieldSuggestions()] }) ``` diff --git a/website/src/pages/v3/guides/using-graphql-features-from-the-future.mdx b/website/src/pages/v3/guides/using-graphql-features-from-the-future.mdx index c89bb603d..d5cff0161 100644 --- a/website/src/pages/v3/guides/using-graphql-features-from-the-future.mdx +++ b/website/src/pages/v3/guides/using-graphql-features-from-the-future.mdx @@ -140,13 +140,13 @@ While the following input would be invalid and not pass the validation phase: Adding support to the existing envelop setup is straight-forward: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useExtendedValidation, OneOfInputObjectsRule } from '@envelop/extended-validation' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins useExtendedValidation({ rules: [OneOfInputObjectsRule] @@ -287,13 +287,13 @@ Frameworks such as relay allow doing similar via directives today. It is time th Envelop already allows using fragment arguments by extending the GraphQL parser. We don't recommend using this for production usage! Please only use it for research or learning purposes! ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' import { useFragmentArguments } from '@envelop/fragment-arguments' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), // ... other plugins ... useFragmentArguments() ] diff --git a/website/src/pages/v3/plugins/custom-plugin.mdx b/website/src/pages/v3/plugins/custom-plugin.mdx index f1a3e446b..0ea5aae67 100644 --- a/website/src/pages/v3/plugins/custom-plugin.mdx +++ b/website/src/pages/v3/plugins/custom-plugin.mdx @@ -19,7 +19,7 @@ https://github.com/n1ru4l/envelop/blob/main/packages/types/src/plugin.ts Here's a simple example that allows you to print the execution and parsing parameters. ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { useEngine } from '@envelop/core' import type { Plugin } from '@envelop/core' @@ -44,7 +44,7 @@ const myPlugin: Plugin = { const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), /// ... other plugins ..., myPlugin ] @@ -57,7 +57,7 @@ Often plugins require additional configuration. A common pattern for doing this ```ts import { envelop, useEngine } from '@envelop/core' -import { parse, validate, subscribe, execute } from 'graphql' +import { parse, validate, specifiedRules, subscribe, execute } from 'graphql' const myPlugin = (shouldPrintResult: boolean): Plugin => { return { @@ -77,7 +77,7 @@ const myPlugin = (shouldPrintResult: boolean): Plugin => { const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }), + useEngine({ parse, validate, specifiedRules, execute, subscribe }), /// ... other plugins ..., myPlugin(true) ] diff --git a/website/src/pages/v3/plugins/lifecycle.mdx b/website/src/pages/v3/plugins/lifecycle.mdx index 532f55d1e..765d857ea 100644 --- a/website/src/pages/v3/plugins/lifecycle.mdx +++ b/website/src/pages/v3/plugins/lifecycle.mdx @@ -35,11 +35,11 @@ In most cases, you'll pass the incoming HTTP request (or, just the relevant part ```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, execute, subscribe }) + useEngine({ parse, validate, specifiedRules, execute, subscribe }) /* ... plugins ... */ ] }) diff --git a/website/src/pages/v3/plugins/typescript.mdx b/website/src/pages/v3/plugins/typescript.mdx index 94351a441..cc6669f43 100644 --- a/website/src/pages/v3/plugins/typescript.mdx +++ b/website/src/pages/v3/plugins/typescript.mdx @@ -24,7 +24,7 @@ export const useMyPlugin = (): Plugin<{ myContext: string }> => { As a user of a plugin, you get type-inference based on the plugins that you use, for example: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' // At this point, the context known to envelop is `{ pluginA: string, pluginB: string }` @@ -33,6 +33,7 @@ const getEnveloped = envelop({ useEngine({ parse, validate, + specifiedRules, execute, subscribe }), diff --git a/website/src/pages/v3/tracing.mdx b/website/src/pages/v3/tracing.mdx index f5c6b6237..58ed54335 100644 --- a/website/src/pages/v3/tracing.mdx +++ b/website/src/pages/v3/tracing.mdx @@ -7,12 +7,12 @@ import { Callout } from '@theguild/components' If you wish to enable it, pass `enableInternalTracing: true` to your envelop instance: ```ts -import { parse, validate, execute, subscribe } from 'graphql' +import { parse, validate, specifiedRules, execute, subscribe } from 'graphql' import { envelop, useEngine } from '@envelop/core' const getEnveloped = envelop({ plugins: [ - useEngine({ parse, validate, execute, subscribe }) + useEngine({ parse, validate, specifiedRules, execute, subscribe }) // ... ], enableInternalTracing: true