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

flow-validator

v0.6.2

Published

object validation with flow types and more

Downloads

51

Readme

npm version Build Status davidDm Dependencies Known Vulnerabilities Coverage Status Inline docs npm downloads Licence Stability: Stable contributions welcome PRs Welcome

flow-validator

Object validation with proper flow types and more.

Installation

npm install flow-validator

Usage

import { arrayOf, string, number, object, instanceOf, Type, Vobject, asyncArrayOf, tuple, takes, match } from 'flow-validator';
import { express } from 'flow-validator/express';

describe("readme code", () => {
  it("works", () => {
    // { name: string, age: ?number, toys: Array<string> }
    const Person = object({
      name: string,
      age: number.optional(),
      toys: arrayOf(string)
    });
    const fred = Person.parse({
      name: "Fred",
      age: 89,
      toys: ["teddy bear", "shotgun"]
    });
    console.log(fred); // eslint-disable-line no-console

    // Array<string> validated asynchronously
    const InventoryObjects = asyncArrayOf(
      string.async().refine(checkInventory)
    );
    const shoppingCart = InventoryObjects.parse(["AK47", "stuffed bunny"]);
    shoppingCart.then(items => console.log(items)); // eslint-disable-line no-console

    async function checkInventory(item: string, error): Promise<string> {
      if (~["AK47", "stuffed bunny"].indexOf(item)) return item;
      return Promise.reject(error("no supplies"));
    }

    // pattern matching -- MORE WORK NEEDED
    // const x = match(1,
    //   number, n => new Date(n*2),
    //   Person, ({ name }) => [name, name]
    // );
    // (x: Date);

    // express middleware example
    const middleware = express.middleware(
      object({ headers: object({ "my-custom-header": string }) }),
      (req, res, next) => next()
    );

    // express endpoint matching middleware (inspired to Spring RequestMapping)
    const requestMap1 = express.requestMapping(
      object({ body: Person }),
      (req, res) => res.json(req.body.age)
    );
    const requestMap2 = express.requestMapping(
      object({ body: object({ username: string, password: string }) }),
      (req, res) => {
        /* authenticate */
      }
    );
    // app.use('/user', requestMap1);
    // app.use('/user', requestMap2);

    const Contact = object({
      name: string,
      birth: string.toDate(),
      email: string.isEmail().optional()
    });
    console.log(
      // eslint-disable-line no-console
      Contact.parse({
        name: "fred",
        birth: String(new Date()),
        email: "[email protected]"
      })
    );

    // ensure functions params, useful on user input functions
    const signUpUser = takes(string.isEmail(), number)(
      (email, secretCoupon) =>
        `user ${email} added with coupon: ${secretCoupon}`
    );
    signUpUser("[email protected]", 666);

    // Don't Repeat Yourself
    // you can use a type of a defined schema, instead of
    // var yogi: { name: string, age: ?number, toys: Array<string> }
    var yogi: typeof Person.type;

    // runtime introspection
    const Name: Type<string> = Person.schema.name;
    const Age: Type<?number> = Person.schema.age;

    // const tup: [string, number, Date] = ...
    const tup = tuple([string, number, instanceOf(Date)]).parse([
      "hello",
      4,
      new Date()
    ]);

    // { a: string, b: number, c: Array<string | number | Date>, d: string, e: Date }
    const Schema = object({
      a: string,
      b: number.optional(),
      c: arrayOf(string.or(number).or(instanceOf(Date))),
      d: string
        .refine((s, error) => {
          // refinements must return the same type
          if (/el/.test(s)) return s;
          throw error(String(/el/)); // this throws proper error
        })
        .revalidate(), // add a revalidate if want to be sure not changed type during refinement
      e: string.to(s => new Date(s)) // with .to() you can convert types
    });

    const toBeValidated = {
      a: "hi",
      c: [1, new Date(), "2017"],
      d: "hello",
      e: "Mon Feb 27 2017 10:00:15 GMT-0800 (PST)"
    };

    // validate input object, returns original object if valid, throws otherwise
    // VType object has .validate() method that returns original object
    // arrayOf, tuple, mapping, object, objectExact ha V prefixed variants,
    // and can't contain validators that change input
    Vobject({ a: string }).validate({ a: "hello" }) === toBeValidated; // = true

    // same as validate, but it make a copy in case of: arrayOf, tuple, mapping, object, objectExact
    // it can be used when using refinemnts that return not the original value
    // and with .to() for conversions
    Schema.parse(toBeValidated) === toBeValidated; // = false
    // deepEqual(Schema.parse(toBeValidated), toBeValidated); // = true

    // shortcuts
    Vobject({ a: string }).isValid({ a: "hello" }); // : boolean
    Vobject({ a: string }).validateResult({ a: "hello" }); // : { value: ... } | { error: ... }
    Schema.parseResult(toBeValidated); // : { value: ... } | { error: ... }

    // you can chain validators, to reuse them or check if your custom type converter works
    string.to(s => new Date(s)).chain(instanceOf(Date));

    // to get JSON serializable error report
    try {
      Schema.parse();
    } catch (e) {
      console.log(e.toJSON()); // eslint-disable-line no-console
    }

    // sometimes flow will not remember types, ex:
    object({ x: number.to(n => new Date(n)) }).parse({ x: 4 }); // unknown type

    // solution
    const x2: Type<Date> = number.to(n => new Date(n));
    object({ x2 }).parse({ x2: 4 }); // : { x: Date }

    // type-safe composition
    const str2num = (s: string) => Number(s);
    const div = (n: number) => n / 2;
    const num2str = (n: number) => String(n);
    const str2arr = (s: string) => s.split("1");
    const nonSense = string
      .compose(str2num)
      .compose(div)
      .compose(num2str)
      .compose(str2arr);
    nonSense.parseResult("1234567890"); // : Array<string>

    // you can convert sync type to async one
    string.async();
  });
});

if you do not want import the entire library, you can find single validators in import { object } from 'flow-validator/sync/object'; or import { asyncArrayOf } from 'flow-validator/async/asyncArrayOf';

Implemented types / combinators

| Type | Flow syntax | Runtime type | |------|-------|-------------| | string | string | string | | number | number | number | | boolean | boolean | boolean | | generic object | Object | objectType | | generic function | Function | Function | | instance of C | C | instanceOf(C) | | class of C | Class<C> | classOf(C) | | array | Array<A> | arrayOf(A) | | intersection | A & B | intersection(A, B) | | union | A | B | union(A, B) | | literal | 's' | literal('s') | | optional | ?A | optional(A) | | map | { [key: A]: B } | mapping(A, B) | | refinement | ✘ | number.refine(n => { if (n > 10) return n; throw new Error(); }) | | object | { name: string } | object({ name: string }) | | exact object | {| name: string |} | objectExact({ name: string }) | | null | null | isNull | | undefined | void | isUndefined | | not checked | any | isAny | | all types | mixed | isMixed | | function | (a: A) => B | takes(A)(returns(B)(...)) |

Included refinements

| Type | Refinements | Transformations | |------|-------------|-----------------| | string | .isEmail() .isValidDate() .minLength() .maxLength() .regexp() | .toDate()

Technical documentation

for older versions:

git clone https://github.com/freddi301/flow-validator.git
cd flow-validator
yarn
npm run doc:serve

Feature Requests Wanted

(open issue, include examples or links)

Inspiration

flow-io (checkout io-ts too for typescript)

Alternatives

Other Alternatives - not flow typed

Planned Features

  • [ ] 0.7.0
    • [ ] include https://github.com/hapijs/joi/blob/master/API.md features see TODO.md
    • [ ] extend()
    • [ ] typescript support
  • [ ] 0.8.0
    • [ ] generate documentation from types (md, html, jsonschema, blueprint, mson, graphql-schema)
    • [ ] generate flow-validator validators from flow annotations, jsonschema and graphql-schema (cli, runtime, compiletime, startuptime)
    • [ ] json schema validation
  • [ ] 0.9.0
    • [ ] refactor validators to contain metadata
    • [ ] refactor errors to contain metadata
    • [ ] write visitors for validators and errors
    • [ ] write default interpreters for errors json and optionally localized text
  • [ ] 1.0.0
    • [ ] test 100%
    • [ ] doc examples for all validators
    • [ ] better flow coverage where possible
    • [ ] readme += new type example
  • [ ] 2.0.0
    • [ ] doc 100%
    • [ ] performance comparison (compete with https://github.com/ebdrup/json-schema-benchmark)
    • [ ] optimize, use lodash, cache optional() singleton and frequently used types

Experimental

  • [ ] readme += alternate use: json graphql alternative
  • [ ] rewrite match
  • [ ] Vmatch asyncMatch asyncVmatch
  • [ ] overloading
  • [ ] monad do notation using row polymorphism
  • [ ] auto row currying (aka builder)
  • [ ] literal values

Other

  • move documentation to surge.sh

Code Climate Test Coverage Issue Count

bitHound Overall Score bitHound Code bitHound Dependencies bitHound Dev Dependencies

NSP Status repo size

NPM