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

averyfy

v0.1.1-1

Published

Avery is a schema first and type-safe validation library. The purpose of this library is to show that you can build a type-safe validation library without using TypeScript's advanced type features. In addition to that, it is to show that you can build a v

Downloads

199

Readme

Avery

Avery is a schema first and type-safe validation library. The purpose of this library is to show that you can build a type-safe validation library without using TypeScript's advanced type features. In addition to that, it is to show that you can build a validation library in purely functional programming style.

Read the docs

Usage

import { avery as a } from 'avery';

const schema = a.array(
  a.array(
    a.object({
      name: a.string(),
      age: a.number(),
    })
  )
);

const result = schema.validate([
  [
    {
      name: 'John',
      age: 10,
    },
    {
      name: 'Jane',
      age: 20,
    },
  ],
]);

const data = result.unwrap();
console.log(data);

This example runs as-is, and will validate the data. If the data is invalid, it will throw an error with a detailed message of where it errors out. For example, the example will produce the data itself.

How It Works

Avery works by first defining all the check functions. This check function will only do one thing, but it will be chained with other check functions to build out the whole schema validator. It is done in a structure Validator. This validator will contain the check function, and is completely immutable.

Naively, it can be represented in Typescript like this:

type Validator<T> = {
  check: (data: unknown) => Result<T>;
};

A validator may have additional properties to modify its check function as well. Such as NumberValidator will have gt, lt, int, etc. These properties will return a new validator with the check function modified in a way that will wrap the previous check function. Overall, it will make use of the idea of Higher Order Function to build out the schema.

Here is an example of how the NumberValidator is represented:

type NumberValidator = Validator<number> & {
  gt: (value: number) => NumberValidator;
  lt: (value: number) => NumberValidator;
  int: () => NumberValidator;
};

As you can see, the NumberValidator is a Validator with additional properties. These properties will return a new NumberValidator with the check function modified according to the method used. This ensures that a validator will not have any side effects, and is completely immutable. Not only that, we can chain these methods to build out the schema and ensure that each check only does one thing, adhering to the Single Responsibility Principle.

Here is an example of how chaining works:

const schema = a.number().gt(10).lt(20);

This will create a NumberValidator with the check function that checks if the data is greater than 10 and less than 20. This is done by chaining the methods gt and lt to the NumberValidator.

When you call validate on the schema, it will run the check function on the data. If it fails, it will throw an error with a detailed message of where it fails. If it passes, it will return a Result object. This Result object will contain the data that has been validated.

Type Inference

You may be able to inference the type based on the schema you have built, just like zod!

import { InferSchema, avery as a } from 'avery';

const schema = a.object({
  name: a.string(),
  age: a.number(),
});

type Data = InferSchema<typeof schema>;
// The type will be:
// {
//   name: string;
//   age: number;
// }

Validators

String

Constructor: a.string()

Methods:

  • minLength(min: number) - Minimum length of the string
  • maxLength(max: number) - Maximum length of the string
const schema = a.string().minLength(3).maxLength(10);
schema.validate('Hello!');

Number

Constructor: a.number()

Methods:

  • eq(value: number) - Equal to the value
  • gt(value: number) - Greater than the value
  • gte(value: number) - Greater than or equal to the value
  • lt(value: number) - Less than the value
  • lte(value: number) - Less than or equal to the value
  • int() - Must be an integer
  • finite() - Must be a finite number
const schema = a.number().gt(10).lt(20);
schema.validate(15);

Boolean

Constructor: a.boolean()

Methods:

  • eq(value: boolean) - Equal to the value
const schema = a.boolean();
schema.validate(true);

Array

Constructor: a.array(item: Validator)

const schema = a.array(a.number());
schema.validate([1, 2, 3]);

Object

Constructor: a.object(schema: Record<string, Validator>)

const schema = a.object({
  name: a.string(),
  age: a.number(),
});

schema.validate({
  name: 'John',
  age: 20,
});