npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

graphql-yup-middleware

v1.0.0

Published

GraphQL middleware to validate mutations arguments using yup

Downloads

104

Readme

GraphQL Mutations Validation Yup Middleware

npm CircleCI (all branches)

  1. What is this?
  2. Install
  3. Usage

I have no plans to add new features to this library - It's on mainteance-only mode. When building the schema for any new GraphQL server, my recommendation is to use nexus, which has native support for plugins - I have a few plugins available in JCMais/nexus-plugins, including one for Yup validation.

What is this?

It's a middleware to be used with graphql-middleware to add validations to mutations arguments using yup.

It originated from this post: https://medium.com/@jonathancardoso/graphql-mutation-arguments-validation-with-yup-using-graphql-middleware-645822fb748

Install

yarn add graphql-yup-middleware

Keep in mind that you also need to have graphql (>= 15), graphql-middleware (>= 6) and yup as dependencies of your project.

Options

The yupMutationMiddleware function exported by this package should always be called when adding it as middleware. Do not add it without calling first.

It accepts the following options, all are optional:

type YupMiddlewareOptions = {
  // In case of errors, this function is going to be used to build the response. More on this below.
  errorPayloadBuilder?: (
    error: ValidationError,
    errorContext: YupMiddlewareErrorContext,
  ) => Object;
  // if the values returned by yup should be merged into the args passed to the mutation resolver
  shouldTransformArgs?: boolean;
  // any options that are accepted by yup validate method
  yupOptions?: ValidateOptions;
};

The defaults are:

{
  shouldTransformArgs: true,
  yupOptions: {
    abortEarly: false,
  },
}

The default errorPayloadBuilder makes the following assumptions about your mutation response fields:

  1. It's an object with nested fields, that is, your mutation does not return a scalar value
  2. One of those is named error.
  3. error field is of type String or MutationValidationError.

And it's going to create a payload based on the error type:

  1. String: return error.message on it.
  2. MutationValidationError: return an error object matching the following definition:
type FieldValidationError {
  field: String!
  errors: [String!]!
}

type MutationValidationError {
  message: String!
  details: [FieldValidationError!]!
}

MutationValidationError and FieldValidationError are both exported as SDL, so you can add them to your typeDefs:

import {
  MutationValidationError,
  FieldValidationError,
} from 'graphql-yup-middleware';

// ...

const typeDefs = [
  MutationValidationError,
  FieldValidationError,
  /* ...your other types */
  ,
];

// ...

And they are also exported as GraphQLObjectType, in case you are building your schema manually, just append Type to their name.

import {
  MutationValidationErrorType,
  FieldValidationErrorType,
} from 'graphql-yup-middleware';

Usage

For using it with other servers, like apollo, express, koa, etc, you are going to need to install graphql-middleware too:

yarn add graphql-middleware

Then you can apply the middleware to your schema:

import { applyMiddleware } from 'graphql-middleware';
import { yupMutationMiddleware } from 'graphql-yup-middleware';

// ... use makeExecutableSchema from apollo-tools, or build your schema yourself

const schemaWithMiddleware = applyMiddleware(schema, yupMiddleware());

Setting the Validation Schema of each Mutation

For each mutation that you want to validate the args, you must define the validation schema on the definition of the mutation. This is done using the extensions field:

const resolvers = {
  // ...
  Mutation: {
    AddUser: {
      extensions: {
        yupMiddleware: {
          validationSchema: yupSchemaHere,
        },
      },
      resolve: async (root, args, context, info) => {
        // ...
      },
    },
  },
};

You can also pass another property named validationOptions to pass other options that should only be used for this mutation.

graphql-relay

If using the helper mutationWithClientMutationId from graphql-relay, you need to store the resulting mutation configuration to a variable, since if you try to add the validationSchema directly, it's not going to work (graphql-relay does not forward extra properties). See this issue for more details: https://github.com/graphql/graphql-relay-js/issues/244

This will not work:

export default mutationWithClientMutationId({
  name: 'MyMutation',
  validationSchema: yup.object().shape({
    input: yup.object().shape({
      // ...
    }),
  }),
  mutateAndGetPayload: async (args) => {
    // ...
  },
  outputFields: {
    // ...
  },
});

This will:

const mutation = mutationWithClientMutationId({
  name: 'MyMutation',
  mutateAndGetPayload: async (args) => {
    // ...
  },
  outputFields: {
    // ...
  },
});

export default {
  ...mutation,
  extensions: {
    ...mutation.extensions,
    yupMiddleware: {
      validationSchema: yup.object().shape({
        input: yup.object().shape({
          // ...
        }),
      }),
    },
  },
};