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

gruber-validate

v0.2.1

Published

Validator wrapper to use on front & back end of boilerplate

Downloads

4

Readme

Validate

This package is designed to solve one problem in one situation.

The situation: Node / Express JS API with an Angular front end. You may be able to use it with something other than Express and Angular, but it wasn't designed for such uses. Currently Angular 2 is in beta, I'm not sure how it will handle Angular 2.

The problem: my form validation and API validation wasn't DRY. I was keeping two sets of validators. This can be extremely dangerous if your backend accepts invalid or insecure data.

The package is a bit complicated This package is more of a boilerplate. you should perform a git clone and update the source/validations.js file with your own validations. Then publish your package to NPM. I set it up as a boilerplate because I keep my backend and front end projects seperate. I use Node's package manager to keep my validations the same in both projects.

Usage

Express

This has a pretty simple middleware function you can use. The middleware performs the following tasks:

  • Checks each field to verify it's valid.
    • if a field isn't valid, the middleware will stop the route return a status of 400 to the client.
  • Removes any field that is not in the validator (this is on by default but can be disabled)
  • Sets req.validatorType to the validatorType (in case you want it later in the route pipeline)

If any fields are invalid it will string together the errors and call:

res.status(400).json({errors: errors});

The client should be able to expose the errors (just in case), but in reality the client should never see them (because the front end is using the same validation)

The Express middleware parameters

  1. validatorType: {string} (Required) - the name of the validator that will be used. The validatorTypes are defined in the source/validations.js file. You should add your own and delete the one's you don't use. The names of the validatorTypes should correspond with a RESTful route and the front end form.
  2. strict: {boolean} (optional: defaults true) - when set to true the middleware will delete any parameters found in req.body. This ensures the user can only update the fields you validate. If there are extra fields in the req.body, they will be deleted but not cause the validation to fail. This way, if you have an authentication token in the request body, they won't cause your validation to fail. But you need to use the parameters prior to validation, or they will be deleted.

Expects json parameters in req.body (that means something like body-parser is required).Expects a validatorType parameter (the name of the form). Returns JSON 400 on failure. if validation succeeds it will move to the next middleware. Lastly it will set req.validatorType = validatorType;

Requirements

  • The middleware expects json parameters in the req.body, which means body-parser or its equivalent is required.

Example

var express     = require('express');
var bodyParser  = require('body-parser');
var validate    = require('gruber-validate');

var app = express();
app.use(bodyParser.json());

express_app.get('/api/register', validate('register'), function (req, res) {
  // if I get here the parameters validated successfully.
});

Client

Copy client.js into public location.

window.validateField = function(model, fieldName, data) ...

call window.validateField with the proper attributes to validate the field.

I bundle into Angular using the following

The angular bundle will add the validation error to the form. That way you can check if the form is invalid. This package has an issue where the input type cannot be email. There is something about the validation that happens automatically. You can add ng-options to the field but i just use type="text" instead.

// Directive
app.directive('validator', function() {
  return {
    require: ['^form', 'ngModel'],
    scope: {ngModel:'=', modelType:'@', fieldName:'@'},
    templateUrl: 'ValidatorTemplate.html',
    link: function(scope, elm, attrs, ctrls) {
      var ngModelCtrl = ctrls[1];
      scope.form = ctrls[0];
      scope.field = scope.form[scope.fieldName];

      ngModelCtrl.$validators.wb = function(modelValue, viewValue) {
        scope.errors = window.validate_field(scope.modelType, scope.fieldName, viewValue);
        if (scope.errors) return false;
        return true;
      };
    }
  };
});
<!-- template -->
<div ng-show="form.$submitted || field.$touched">
  <p class="text-danger" ng-show="errors">{{errors}}</p>
</div>
<!-- Example Usage -->
<form name="login_form" novalidate ng-submit="login()">
    <input type="text" ng-model="email" name="email" class="form-control" placeholder="Email" required>
    <validator ng-model='email' model-type='login' field-name='email'></validator>
    <div>
      <button type="submit" class="btn btn-primary">Log in</button>
    </div>
</form>
// Controller Example
app.controller('LoginCtrl', ['$scope', function($scope) {
  $scope.login = function() {
    if ($scope.login_form.$valid) {
      // Will only get here if there are no errors on the input
    }
  };
}]);

These can be copied from the angular folder...

How it works

Before you can even setup and start using this package you'll need to know how it works.

Some guy named Chriso made Validator (https://github.com/chriso/validator.js). A tool that can be used to validate your data on the front end as well as the back end. You'll need to check it out. The validator has most of the validations you'll be using, things like isEmail, etc.

File Summary

  • Chriso's validator is our little worker bee, he handles all the validations.
  • source/validate.js is our distribution hub.
  • source/validations.js is our definitions.
  • source/extenders.js has extensions for our validator (https://github.com/chriso/validator.js#extensions)
  • source/client.js is our client's gateway. You can define more functionality for the client here. (this isn't used on the client directly, it needs to be bundled and browserfied first)
  • express.js is our Node gateway (express middleware). He will be our apps starting place that way you can call him directly from Node.
  • angular/ has my predefined directive I use in Angular.
  • client.js is our browser ready validation tool.

source/validations.js

This is the confusing part. You'll be defining everything you need here.

validations {object}

variable in source/validations.js The validations variable will be an object. source/validate.js will pull the definitions for validating from here. We're going to create this using the todo example.

var validations = {};
validationType {object}

property in Validations object Each property on the validations variable will be a different ValidationType. These should correspond to the client forms and the backend APIs. For example: if your front end has a Todo form that has a corresponding API on the back end. You will add a validationType of todo. Each validationType will be an object of their own.

var validations = {
  todo: {}
};
field {object}

property in validationType Each property on the validationType will be a field/parameter. These will correspond to parameters on your api and fields (such as input's) on your frontend. To keep with the same example: the todo validationType will have two properties: completed & title. Each field will also be an object.

var validations = {
  todo: {
    completed: {},
    title: {}
  }
};
validations {object | boolean}

property in field Each property in the field will be a validation. This is where you'll define a fields validations. So the completed field will have a isBoolean validation. The isBoolean validation doesn't have any options, so you can set it as true.

var validations = {
  todo: {
    completed: {isBoolean: true},
    title: {}
  }
};

The title field will need two validations:

  • required: This is an extension to Christo's validator package. You can find it located in the source/extenders.js file. It simply verifies the existence of the field. Set the required validator to true.
  • minLength: This is also an extension to Christo's validator package. The minLength validation won't do much if it doesn't know how long the minimum length is. So instead of setting minLength to true, set it to an object: {options: 6}. The options value tells our tool to make sure our string is longer than 6 characters.
var validations = {
  todo: {
    completed: {isBoolean: true},
    title: {required: true, minLength: {options: 6}}
  }
};

Ok. Now let's say you have two forms for todo. One for Create and one for put. And now you need to use a different validator for put. Here's how we add it:

var todoTitleMinLength = 6; // DRY ALL UP IN THIS BEAST

var validations = {
  todo: {
    completed: {isBoolean: true},
    title: {required: true, minLength: {options: todoTitleMinLength}}
  }
};

validations.todoUpdate = {
  completed: validations.todo.completed, // Because I made this definition after defining validations I can call myself.
  title: {minLength: {options: todoTitleMinLength}} // this sucker isn't required anymore
};

THREE CHEERS FOR DRYNESS!!!

How do you know the names of the validations? Chriso has many predefined in his application. You can see them here: https://github.com/chriso/validator.js#validators

I've had to add 3 I needed, you'll find them in source/extenders.js. You can also define your own using: https://github.com/chriso/validator.js#extensions. They should be placed in the source/extenders.js.

DEFAULT_ERROR_MESSAGES {object}

variable in source/validations.js This is the other variable you'll need to define. The validate tool generates error messages automatically, most of which are from here. Each property on the object should have the same name as the validations (the properties you defined on the fields above). Each error message will be a simple string.

Example:

var DEFAULT_ERROR_MESSAGES = {
  isEmail: 'is not an email address.',
  required: 'is required.',
  isAlpha: 'must only contain letters (a-zA-Z).',
  minLength: 'must be atleast ${options} characters long.',
  maxLength: 'must be shorter than ${options} characters.'
};

This is as far as I got before I got bored. I can't believe you're even reading this. I designed this project for myself. I just made it public because I'm cheap.

Browse the code and review the tests for a better understanding.

Setup

Remember how I said it's more of a boilerplate?