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

@ngserveio/you-good

v9.0.0

Published

A client and backend agnostic validation library created by [NgServe.io](https://ngserve.io).

Downloads

85

Readme

@ngserveio/you-good

A client and backend agnostic validation library created by NgServe.io.

Read More at Angular Tutorial - Sharing Validations Between Angular and NestJs

Running unit tests

Run nx test shared-validator to execute the unit tests via Jest.

Purpose

This library provides the ability to validate models with the consuming service defining validations for the model provided. It is meant to help bridge the gap more easily between back and front end code as models on both sides need validation in a reusable way.

Types

| Name | Returns | Description | | ----------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ValidationErrors | { [validationName: string]: unknown } | The validation type and the values associated with that validation e.g. { required: true } | | PropertyValidationErrors<T> | Record<keyof T, unknown> | Provides a key on property T of unknown type which will be the return validation. e.g. {firstName: { required: true, maxLength: { max: 50, actual: 51 } } | | ValidatorFn<T> | ValidationErrors | A function that returns the validations per the validator on a property | | ValidationField<T> | (item: Partial<T>) => unknown | A delegate method that returns the value to be validated. e.g. (item: { name: string }) => item.name | | PropertyValidators<T> | Record<keyof T, ValidatiorFn<T>>[] | A list of validators of a particular property on T e.g. { firstName: [ required, max(10) ], email: { email, maxLength(50) } } | | Validator<T> | (value: ValidationField<T>) => ValidatorFn<T> | A validator that chooses the value in which to validate per the delegate ValidationField<T>. | | ModelValiatorFn<T> | (item: Partial<T>, partial?: boolean) => PropertyValidationErrors<T> or Null | A validate function that can choose to do partial validations depend on what's the model returns |

Validators

Validation Errors refers to the ValidationErrors return when the validation is executed.

| Validator | Validation Errors | Description | | -------------------------------------------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | | keys<T>(fn: ValidationField<T>): ValidatorFn<T> | {keys: false} | Checks if the item being validated has any keys e.g. Object.keys({name: 'Steve'}).length > 0 | | required<T>(fn: ValidationField<T>): ValidatorFn<T> | { required: true} | Checks the value is not null or undefined and is not empty or white space. | | emptyOrWhiteSpace<T>(fn: ValidationField<T>): ValidatorFn<T> | { emptyOrWhiteSpace: true } | Checks if the provided value is empty or white space | | lessThan(compareValue: number): Validator<T> | { lessThan: { compareValue: number, actual: number } } | Checks if the itemValue is greater than the compareValue supplied in the validation. | | greaterThan(compareValue: number): Validator<T> | { greaterThan: { compareValue: number, actual: number } } | Checks if the itemValue is less than the compareValue supplied in the validation. | | email<T>(fn: ValidationField<T>): ValidationFn<T> | { email: false } | Checks if the provided value is an email address. | | url<T>(fn: ValidationField<T>): ValidatorFn<T> | {url: false} | Checks if the value provided is a URL | | minLength<T>(number): Validator<T> | { minLength: { compareValue: number, actual: number } } | Checks the min length required of the compareValue with itemValue for a property in the validation | | pattern<T>(pattern: string): ValidatorFn<T> | { pattern: { regEx: string, value: StringOrNumber } } | Checks the pattern of the supplied field value. | | maxLength<T>(compareValue: number) | { maxLength: { compreValue: number, actual: number } } | Checks the string value length being supplied isn't over the compareValue |

Validating

One validate<T> method exists to help validate a model.

| Method | Description | | --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | | validate<T>(validatorFns: PropertyValidators<T>): (item: Partial<T>) => ModelValidatorFn<T> | Returns a delegate method for a model to be validated against. Validates partial for patch updates.* | | propertyValidators<T>(fn: ValidationField<T>, fns:(validationField: ValidationField<T>) => ValidatorFn<T>)[]) | A helper method that has the validationField<T> supplied and an array of ValidatorFns<T> |

  • Keep in mind if the object your checking in your validatorFns doesn't contain one of the properties on a partial check this will cause an error, so be careful with partial checks.

How to Use validate

type ModelT = {
  firstName: string;
  email: string;
  url: string;
  jerseyNumber: number | null;
};

const model: ModelT = {
  firstName: 'Steve',
  email: '[email protected]',
  url: 'https://detroitredwings.com',
  jerseyNumber: null,
};

const modelTValidator: (item: T) => PropertyValidationErrors<T> =
  validate<ModelT>({
    firstName: propertyValidators((p) => p.firstName, [required]),
    email: propertyValidators((p) => p.email, [required, email]),
    url: propertyValidators((p) => p.url, [url]),
    jerseyNumber: propertyValidators((p) => p.jerseyNumber, [required]),
  });

modelTValidator(model); // { jerseyNumber: { required: true } }

Sample Validators

Reference below as to how to write a custom validator.

// This is a Validator<T>
export function emptyOrWhiteSpace<T>(
  value: ValidationField<T>
): ValidatorFn<T> {
  return (item: T): ValidationErrors => {
    const itemValue = value(item);

    return isEmptyOrWhiteSpace(itemValue as string)
      ? ({ emptyOrWhiteSpace: true } as Record<string, unknown>)
      : null;
  };
}

// Returns a Validator<T>
export function lessThan<T>(compareValue: number): Validator<T> {
  return (value: ValidationField<T>): ValidatorFn<T> => {
    return (item: T): ValidationErrors => {
      const itemValue = value(item) as number;
      return itemValue > compareValue
        ? ({ lessThan: { compareValue, actual: itemValue } } as Record<
            string,
            unknown
          >)
        : null;
    };
  };
}

FluidValidator

Fluid validations provides an easier way to validate a model in a fluid way. It provides customizations for nested validations for nested properties.

// Sample Types

type ProductAttribute = {
  id: string;
  productId: string;
};

type ProductImage = {
  id: string;
  productId: string;
  altText: string;
};

type Product = {
  id: string;
  name: string;
  attributes: Nullable<ProductAttribute[]>;
  image: ProductImage;
  price: number;
  email: string;
  url: string;
};

const productImageValidator = new FluidValidator<ProductImage>()
  .prop('id') // Maps to a particular property in Product Image
  .maxLength(36) // Standard Validations listed below
  .prop('productId')
  .required();

const productAttributeValidator = new FluidValidator<ProductAttribute>()
  .prop('id')
  .maxLength(36)
  .prop('productId')
  .required();

const productValidator = new FluidValidator<Product>()
  .prop('id')
  .maxLength(36)
  .prop('name')
  .emptyOrWhiteSpace()
  .required()
  .minLength(1)
  .maxLength(50)
  .prop('image')
  .required()
  .custom(({ image }) => {
    // custom validations  using another validator
    return productImageValidator.validate(image);
  })
  .prop('price')
  .greaterThan(0)
  .prop('email')
  .email()
  .prop('url')
  .url()
  .pattern(/^https:\/\//)
  .prop('attributes')
  .required()
  .custom(({ attributes }) => {
    const validationMessages: ValidationErrors = attributes.reduce(
      (errors, attribute, index) => {
        const validationErrors = productAttributeValidator.validate(attribute);
        if (validationErrors) {
          errors[index] = validationErrors;
        }

        return errors;
      },
      {}
    );

    return hasKeys(validationMessages) ? validationMessages : null;
  });

The prop('propertyName') method scopes the validations to the property of the model. The propertyName must be a key of the model being validated.

Methods

| Name | Description | | ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | | prop(propName: string): FluidValidator<T> | Defines the property being validated | | required(): FluidValidator<T> | Defines the property is required. | | maxLength(length: number): FluidValidator<T> | The max length of a string value | | minLength(length: number): FluidValidator<T> | The min length of a string value | | lessThan(compare: number): FluidValidator<T> | Compares the property must be less than the compare value | | greaterThan(compare: number): FluidValidator<T> | Compres the property must be greater than the compare value | | emtpyOrWhiteSpace(): FluidValidator<T> | Checks the value is not empty string or white space. | | email(): FluidValidator<T> | Checks the property is an email address | | url(): FluidValidator<T> | Checks the property is a url | | pattern(regEx: RegExp): FluidValidator<T> | Checks the property is a regular expression | | custom(func: Func<T | Partial<T>, Nullable<ValidationErrors>>, partial: boolean): FluidValidator<T>* | Provides the ability to write a custom validation function or reuse another FluidValidator<T> such as a nested object. | | validate(item:T): Nullable<Partial<PropertyValidationErrors<T>>> | Validates and full object for all the properties defined in the validator | | validatePartial(item: Partial<T>): Nullable<Partial<PropertyValidationErrors<T>>> | Validates a partial object of the properties provided | | extends<T & R>(): FluidValidator<T & R> | Extends the available properties to validate. | | omit<K extends KeyOfType<T>>(keys: K[]): FluidValidator<Omit<T, K>> | Omits certain properties from being validated. | | pick<K extends KeyOfType<T>>(keys: K[]): FluidValidator<Pick<T, K>> | Picks certain properties to be validated. |

* The custom function may provide a Partial<T> so all properties may not be available for validating and you'll want to code if function is a partial check. The assumption is that if you're doing a partial check the object was previously validated in full.

The custom function accepts a partial to determine if the validation is a partial validation. This matters when you want to check multiple multiple and dependent properties of the item.