mercurius-validation
Advanced tools
| # Registration | ||
| The `mercurius-validation` plugin must be registered **after** Mercurius is registered. | ||
| ```js | ||
| 'use strict' | ||
| const Fastify = require('fastify') | ||
| const mercurius = require('mercurius') | ||
| const mercuriusValidation = require('mercurius-validation') | ||
| const app = Fastify() | ||
| const schema = ` | ||
| directive @validation( | ||
| requires: Role = ADMIN, | ||
| ) on OBJECT | FIELD_DEFINITION | ||
| enum Role { | ||
| ADMIN | ||
| REVIEWER | ||
| USER | ||
| UNKNOWN | ||
| } | ||
| type Query { | ||
| add(x: Int, y: Int): Int @validation(requires: USER) | ||
| } | ||
| ` | ||
| const resolvers = { | ||
| Query: { | ||
| add: async (_, { x, y }) => x + y | ||
| } | ||
| } | ||
| app.register(mercurius, { | ||
| schema, | ||
| resolvers | ||
| }) | ||
| // After initial setup, register Mercurius validation | ||
| app.register(mercuriusValidation, { | ||
| validationContext (context) { | ||
| return { | ||
| identity: context.reply.request.headers['x-user'] | ||
| } | ||
| }, | ||
| async applyPolicy (validationDirectiveAST, parent, args, context, info) { | ||
| return context.validation.identity === 'admin' | ||
| }, | ||
| validationDirective: 'validation' | ||
| }) | ||
| app.listen(3000) | ||
| ``` |
@@ -5,2 +5,6 @@ version: 2 | ||
| directory: "/" | ||
| ignore: | ||
| - dependency-name: "actions/*" | ||
| update-types: | ||
| ["version-update:semver-minor", "version-update:semver-patch"] | ||
| schedule: | ||
@@ -7,0 +11,0 @@ interval: daily |
@@ -13,5 +13,5 @@ name: CI workflow | ||
| steps: | ||
| - uses: actions/checkout@v2.3.4 | ||
| - uses: actions/checkout@v2 | ||
| - name: Use Node.js ${{ matrix.node-version }} | ||
| uses: actions/setup-node@v2.4.1 | ||
| uses: actions/setup-node@v2 | ||
| with: | ||
@@ -27,5 +27,8 @@ node-version: ${{ matrix.node-version }} | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| pull-requests: write | ||
| contents: write | ||
| steps: | ||
| - uses: fastify/github-action-merge-dependabot@v2.5.0 | ||
| - uses: fastify/github-action-merge-dependabot@v3 | ||
| with: | ||
| github-token: ${{secrets.GITHUB_TOKEN}} |
+0
-58
| # mercurius-validation | ||
| - [Plugin options](#plugin-options) | ||
| - [Registration](#registration) | ||
| ## Plugin options | ||
| <!-- TODO --> | ||
| **mercurius-validation** supports the following options: | ||
@@ -126,57 +124,1 @@ | ||
| The [JTD](https://jsontypedef.com/docs/) schema definition for the input object type, type field or field argument. | ||
| ## Registration | ||
| The plugin must be registered **after** Mercurius is registered. | ||
| ```js | ||
| 'use strict' | ||
| const Fastify = require('fastify') | ||
| const mercurius = require('mercurius') | ||
| const mercuriusValidation = require('mercurius-validation') | ||
| const app = Fastify() | ||
| const schema = ` | ||
| directive @validation( | ||
| requires: Role = ADMIN, | ||
| ) on OBJECT | FIELD_DEFINITION | ||
| enum Role { | ||
| ADMIN | ||
| REVIEWER | ||
| USER | ||
| UNKNOWN | ||
| } | ||
| type Query { | ||
| add(x: Int, y: Int): Int @validation(requires: USER) | ||
| } | ||
| ` | ||
| const resolvers = { | ||
| Query: { | ||
| add: async (_, { x, y }) => x + y | ||
| } | ||
| } | ||
| app.register(mercurius, { | ||
| schema, | ||
| resolvers | ||
| }) | ||
| app.register(mercuriusValidation, { | ||
| validationContext (context) { | ||
| return { | ||
| identity: context.reply.request.headers['x-user'] | ||
| } | ||
| }, | ||
| async applyPolicy (validationDirectiveAST, parent, args, context, info) { | ||
| return context.validation.identity === 'admin' | ||
| }, | ||
| validationDirective: 'validation' | ||
| }) | ||
| app.listen(3000) | ||
| ``` |
| # Directive validation | ||
| - [Using the GraphQL definitions within your schema](#using-the-graphql-definitions-within-your-schema) | ||
| - [GraphQL argument validation](#graphql-argument-validation) | ||
| - [GraphQL Input Object type field validation](#graphql-input-object-type-field-validation) | ||
| - [GraphQL Input Object type validation](#graphql-input-object-type-validation) | ||
| - [Additional AJV options](#additional-ajv-options) | ||
| - [Turning off directive validation](#turning-off-directive-validation) | ||
| - [Unsupported JSON Schema keywords](#unsupported-json-schema-keywords) | ||
| By default, Mercurius validation supports `@constraint` Directives out of the box. It is defined as follows: | ||
@@ -49,2 +57,47 @@ | ||
| ## Using the GraphQL definitions within your schema | ||
| `mercurius-validation` provides `GraphQLDirective` and type definitions to allow one to use the `@constraint` directive within a GraphQL schema. | ||
| For string-based schema definitions, you can use as follows: | ||
| ```js | ||
| 'use strict' | ||
| const mercuriusValidation = require('mercurius-validation') | ||
| const schema = ` | ||
| ${mercuriusValidation.graphQLTypeDefs} | ||
| type Message { | ||
| id: ID! | ||
| text: String | ||
| } | ||
| input Filters { | ||
| id: ID | ||
| text: String @constraint(minLength: 1) | ||
| } | ||
| type Query { | ||
| message(id: ID @constraint(type: "string", minLength: 1)): Message | ||
| messages(filters: Filters): [Message] | ||
| } | ||
| ` | ||
| ``` | ||
| For executable schema definitions, you can use as follows: | ||
| ```js | ||
| 'use strict' | ||
| const { parse, GraphQLSchema } = require('graphql') | ||
| const mercuriusValidation = require('mercurius-validation') | ||
| // Define your executable schema as normal | ||
| const graphQLSchemaToExtend = new GraphQLSchema({ ... }) | ||
| const schema = extendSchema(graphQLSchemaToExtend, parse(mercuriusValidation.graphQLTypeDefs)) | ||
| ``` | ||
| ## GraphQL argument validation | ||
@@ -286,2 +339,13 @@ | ||
| ## Turning off directive validation | ||
| If you don't want to run directive validation within the plugin, you can turn it off during plugin registration: | ||
| ```js | ||
| app.register(mercuriusValidation, { | ||
| directiveValidation: false | ||
| // Additional options here | ||
| }) | ||
| ``` | ||
| ## Unsupported JSON Schema keywords | ||
@@ -288,0 +352,0 @@ |
| # Function validation | ||
| - [GraphQL argument validation](#graphql-argument-validation) | ||
| You can setup Mercurius validation to run custom functions on arguments when defining in-band validation schemas. It supports the following validation definitions: | ||
@@ -4,0 +6,0 @@ |
| # JSON Schema validation | ||
| - [GraphQL argument validation](#graphql-argument-validation) | ||
| - [GraphQL Input Object type field validation](#graphql-input-object-type-field-validation) | ||
| - [GraphQL Input Object type validation](#graphql-input-object-type-validation) | ||
| - [Additional AJV options](#additional-ajv-options) | ||
| - [Custom errors](#custom-errors) | ||
| - [Type inference](#type-inference) | ||
| - [Caveats](#caveats) | ||
| By default, Mercurius validation runs in JSON Schema mode when defining in-band validation schemas. It supports the following validation definitions: | ||
@@ -4,0 +12,0 @@ |
| # JTD validation | ||
| - [GraphQL argument validation](#graphql-argument-validation) | ||
| - [GraphQL Input Object type field validation](#graphql-input-object-type-field-validation) | ||
| - [GraphQL Input Object type validation](#graphql-input-object-type-validation) | ||
| - [Additional AJV options](#additional-ajv-options) | ||
| You can setup Mercurius validation to run in JTD mode when defining in-band validation schemas. It supports the following validation definitions: | ||
@@ -11,3 +16,3 @@ | ||
| To enable JTD mode, set the following at registration: | ||
| To enable JTD mode, set the `mode` options to `"JTD"` at registration: | ||
@@ -14,0 +19,0 @@ ```js |
+6
-6
| { | ||
| "name": "mercurius-validation", | ||
| "version": "1.0.0", | ||
| "version": "2.0.0", | ||
| "description": "Mercurius Validation Plugin adds configurable Validation support to Mercurius.", | ||
@@ -38,3 +38,3 @@ "main": "index.js", | ||
| "@sinonjs/fake-timers": "^8.0.1", | ||
| "@types/node": "^16.0.0", | ||
| "@types/node": "^17.0.0", | ||
| "@types/ws": "^8.2.0", | ||
@@ -44,5 +44,5 @@ "@typescript-eslint/eslint-plugin": "^4.1.0", | ||
| "autocannon": "^7.0.5", | ||
| "concurrently": "^6.1.0", | ||
| "concurrently": "^7.0.0", | ||
| "fastify": "^3.0.2", | ||
| "mercurius": "^8.0.0", | ||
| "mercurius": "^9.1.0", | ||
| "pre-commit": "^1.2.2", | ||
@@ -52,3 +52,3 @@ "snazzy": "^9.0.0", | ||
| "tap": "^15.0.2", | ||
| "tsd": "^0.17.0", | ||
| "tsd": "^0.19.0", | ||
| "typescript": "^4.0.3", | ||
@@ -63,3 +63,3 @@ "wait-on": "^6.0.0" | ||
| "fastify-plugin": "^3.0.0", | ||
| "graphql": "^15.4.0" | ||
| "graphql": "^16.2.0" | ||
| }, | ||
@@ -66,0 +66,0 @@ "tsd": { |
+77
-0
@@ -23,5 +23,8 @@ # mercurius-validation | ||
| - [Quick Start](#quick-start) | ||
| - [Validation with JSON SChema definitions](#validation-with-json-schema-definitions) | ||
| - [Validation with the GraphQL `@constraint` directive](#validation-with-the-graphql-constraint-directive) | ||
| - [Examples](#examples) | ||
| - [Benchmarks](#benchmarks) | ||
| - [API](docs/api/options.md) | ||
| - [Registration](docs/registration.md) | ||
| - [JSON Schema Validation](docs/json-schema-validation.md) | ||
@@ -40,2 +43,6 @@ - [JTD Validation](docs/jtd-validation.md) | ||
| ### Validation with JSON Schema definitions | ||
| You can setup `mercurius-validation` using a JSON Schema validation definition as follows: | ||
| ```js | ||
@@ -118,2 +125,72 @@ 'use strict' | ||
| ### Validation with the GraphQL `@constraint` directive | ||
| You can setup `mercurius-validation` with the `@constraint` GraphQL directive. `mercurius-validation` provides the type definitions to include this directive definition within your GraphQL schema. | ||
| ```js | ||
| 'use strict' | ||
| const Fastify = require('fastify') | ||
| const mercurius = require('mercurius') | ||
| const mercuriusValidation = require('mercurius-validation') | ||
| const schema = ` | ||
| ${mercuriusValidation.graphQLTypeDefs} | ||
| type Message { | ||
| id: ID! | ||
| text: String | ||
| } | ||
| input Filters { | ||
| id: ID | ||
| text: String @constraint(minLength: 1) | ||
| } | ||
| type Query { | ||
| message(id: ID @constraint(type: "string", minLength: 1)): Message | ||
| messages(filters: Filters): [Message] | ||
| } | ||
| ` | ||
| const messages = [ | ||
| { | ||
| id: 0, | ||
| text: 'Some system message.' | ||
| }, | ||
| { | ||
| id: 1, | ||
| text: 'Hello there' | ||
| }, | ||
| { | ||
| id: 2, | ||
| text: 'Give me a place to stand, a lever long enough and a fulcrum. And I can move the Earth.' | ||
| }, | ||
| { | ||
| id: 3, | ||
| text: '' | ||
| } | ||
| ] | ||
| const resolvers = { | ||
| Query: { | ||
| message: async (_, { id }) => { | ||
| return messages.find(message => message.id === Number(id)) | ||
| }, | ||
| messages: async () => { | ||
| return messages | ||
| } | ||
| } | ||
| } | ||
| const app = Fastify() | ||
| app.register(mercurius, { | ||
| schema, | ||
| resolvers | ||
| }) | ||
| app.register(mercuriusValidation) | ||
| app.listen(3000) | ||
| ``` | ||
| ## Benchmarks | ||
@@ -120,0 +197,0 @@ |
301322
1.53%52
1.96%306
33.62%+ Added
- Removed
Updated