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

class-model

v1.0.1

Published

Class scheme definition by decorator with type-validators and loaders

Downloads

44

Readme

class-model

Class scheme definition by decorator with type-validators and loaders

Example of usage

import * as classModel from "class-model"

//custom validator funciton
function strNotEmptyValidator(prop: string, label: string, model: any) {
    return (model[prop].length > 0)
            ? []
            : ([label + " should be grater then 0"])
}

//model class
class UserAuth {
    @classModel.property("Login", strNotEmptyValidator)
    login: string

    @classModel.property("Password", strNotEmptyValidator)
    pass: string
}

//loading
const user = new UserAuth()
const loadResult = classModel.loadData(user, {login: "asdsa", pass: "c412"})
assert.strictEqual(loadResult, true)
assert.strictEqual(user.login, "asdsa")
assert.strictEqual(user.pass, "c412")

//validation
const validationErrors1 = classModel.validationErrors(user)
assert.strictDeepEqual(validationErrors1, [])

user.password = ""
const validationErrors2 = classModel.validationErrors(user)
assert.strictDeepEqual(validationErrors2, ["Password should be grater then 0"])

//gettingPropertyLabels
assert.deepStrictEqual(classModel.utils.getAllPropertiesLabels(user), {
    login: "Login",
    pass: "Password",
})

Installation

npm i class-model

Usage

1. Set decorator to the property

class UserAuth {
    @classModel.property("Login", 
        classModel.valid.strictEqual("asdsa") //validator
    )
    login: string

    @classModel.property("Password", classModel.valid.stringLength(sl => sl > 8))
    pass: string
}

2. Use load funciton to load structure or object to model using decorated properties

const user = new UserAuth()
const loadResult = classModel.loadData(user, {login: "asdsa", pass: "c412"})
assert.strictEqual(loadResult, true)
assert.strictEqual(user.login, "asdsa")
assert.strictEqual(user.pass, "c412")

3. Use validationErrors function

user.password = ""
const validationErrors2 = classModel.validationErrors(user)
assert.strictDeepEqual(validationErrors2, ["Password should be equals \"c412\""])

//You also may assert model by them
classModel.assert(user) //Error: Password should be equals "c412"

Utils

Package provides utils functions to access metadata of model

//[class-model].utils.dts

import { MakeProperty } from "./make";
import { PropertyValidator } from "./valid";
export declare const __classModelPropertiesKey = "__classModelProperties";
export type PropertyMeta = {
    makeModel: MakeProperty;
    validator: PropertyValidator | null;
    label: string | null;
};
/**
 * Sets property to model
 */
export declare function setProperty(
    model: object, 
    propName: string | symbol, 
    label?: string | null, 
    validator?: PropertyValidator | null, 
    makeModel?: MakeProperty | null
): void;

/**
 * Gets meta-structure with validators and label of property
 */
export declare function getPropertyMeta(
    model: object, 
    propName: string | symbol
): PropertyMeta | null;

/**
 * Get structure kind of {[registeredProperty]: [labelOfProperty]}
 */
export declare function getAllPropertiesLabels(model: object): {};

/**
 * Gets structure kind of {[registeredProperty]: {label: ..., validators: [...]}}
 */
export declare function getAllPropertiesMeta(model: object): Record<string, PropertyMeta>;

/**
 * Get all properties as a string
 */
export declare function getProperties(obj: object): Array<string>;

/**
 * Returns label of property or returns property name
 * if special label had not been registered
 */
export declare function getPropertyLabel(
    model: object, 
    propName: string | symbol
): string;

/**
 * Returns all geristered validators of the property
 */
export declare function getPropertyValidator(
    model: object, 
    propName: string | symbol
): PropertyValidator | null;

/**
 * Returns special constructor of property, is it exists
 */
export declare function getMaybeMakeModelFn(
    model: object, 
    propName: string | symbol
): null | MakeProperty;

/**
 * assert anonimous value by validator
 */
export declare function assertByValidator(
    val: any, 
    validator: (propName: string | symbol, propLabel: string, propVal: any) => string[]
): void;

Special property constructors

If you want to load aggregated data or define special property construction logic on loading, you should define special constructor in property decorator

class SubModel {
    @classModel.property("A")
    a: number = 12
}

class MakeModelTestClass {
    @classModel.property("As", valid.any(), 
        classModel.make.model(() => new SubModel()) /*special property constructor*/)
    public as: SubModel //aggreagated property
}

const obj = new MakeModelTestClass()
const data = {as: {a: 15}}
const loadResult = classModel.loadData(obj, data)
assert.strictEqual(loadResult, true)
assert.strictEqual(obj.as.a, 15)

Special property constructors

We prepared two popular constructors in classModel.make module:

// classModel.make module

export type MakeProperty = (data: any) => any;

/**
 * Load model uses getter
 */
export declare function model(getModel: () => object): MakeProperty;

/**
 * Load array of models uses getter
 */
export declare function modelsArray(getModel: () => object): MakeProperty;

/**
 * Load bigint
 */
export declare function bigInt(printData?: ((v: any) => string) | null): MakeProperty;

/**
 * Constructs Date from loading data
 */
export declare function date(printData?: ((v: any) => string) | null): MakeProperty;

/**
 * Parse data as a Float
 */
export declare function float(printData?: ((v: any) => string) | null): MakeProperty;

/**
 * Parse data as a Float
 */
export declare function int(
    printData?: ((v: any) => string) | null, 
    roundStrategy?: "round" | "floor" | "ceil"
): MakeProperty;

/**
 * Parse data as a boolean
 */
export declare function boolean(): MakeProperty;

/**
 * Parse data as a string
 */
export declare function string(): MakeProperty;

/**
 * Parse data as array
 */
 export function arrayOf(make: MakeProperty|null = null): MakeProperty

Validators

Validator is function kind of:

type PropertyValidator = (propName: string, propLabel: string, propVal: any) => string[]

Some popular validators are also prepared for you, and keeps in classModel.valid module.

Validator pakcage

You may use validators from validator pakage in property decorator using classModel.valid.lambda validator

import {isHexColor} form "validator"

class LambdaCheckClass {
    @property("A", valid.lambda(isHexColor))
    public a: any
}

const obj = new LambdaCheckClass()
obj.a = "#763820"
const validErrors = validationErrors(obj)
assert.deepStrictEqual(validErrors, [])

This package is not depends of validator package. Its needs to be installed, before using.

List of validators:

//classModel.valid module

export type PropertyValidator = (
    propName: string | symbol, 
    propLabel: string, propVal: any
) => string[];

export type ValuePrinter = (v: any) => string;

/**
 * Strict not deep equals to scalar val
 */
export declare function strictEqual(
    val: string | bigint | number | boolean | null | undefined | symbol, 
    printValue?: ValuePrinter | null
): PropertyValidator;

/**
 * Deep strict equals validator
 */
export declare function strictDeepEqual(
    val: any, 
    printValue?: ValuePrinter | null
): PropertyValidator;

/**
 * Value satisfies operator !!val
 */
export declare function required(): PropertyValidator;

/**
 * Value satisfies operator !val
 */
export declare function empty(): PropertyValidator;

/**
 * Value satisfies filter function
 */
export declare function filterFn(filterFn: (v: any) => boolean): PropertyValidator;

/**
 * Deep strict equals validator
 */
export declare function oneOf(
    vals: Array<string | symbol | number | boolean | null | undefined | bigint>, 
    printValue?: ValuePrinter | null = null
): PropertyValidator;

/**
 * Validator allows anything
 */
export declare function any(): PropertyValidator;

/**
 * Validator allows nothing
 */
export declare function never(): PropertyValidator;

/**
 * Checks is value type of bigint, symbol, number, string,
 * boolean or undefined
 */
export declare function scalar(): PropertyValidator;

/**
 * Checks is property value is array of X
 */
export declare function arrayOf(
    itemValidator?: PropertyValidator | null
): PropertyValidator;

/**
 * Checks is property value is array have n of X values
 */
export declare function arrayDeepStrictUnique(
    printVal?: ValuePrinter | null
): PropertyValidator;

/**
 * Checks array count by function
 */
export declare function arrayCount(
    countCheckFn?: ((n: number) => boolean) | null
): PropertyValidator;

/**
 * Checks property is a tuple match tuple of validators
 */
export declare function arrayTuple(
    valids?: PropertyValidator[] | null
): PropertyValidator;

/**
 * Return errors if one of validators are return errors
 */
export declare function and(valids: PropertyValidator[]): PropertyValidator;

/**
 * Return errors if everyone of validators are return errors
 */
export declare function or(valids: PropertyValidator[]): PropertyValidator;

/**
 * Return errors if everyone of validators are return errors
 */
export declare function not(valid: PropertyValidator): PropertyValidator;

/**
 * Date validation by lambda
 */
export declare function date(
    valid?: ((d: Date) => string[] | boolean) | null
): PropertyValidator;

/**
 * Validate number by lambda
 */
export declare function number(
    valid?: ((n: number) => string[] | boolean) | null
): PropertyValidator;

/**
 * Checks object is instance of X
 */
export declare function objInstance(construct?: Function | null): PropertyValidator;

/**
 * Checks object is valid as a Model
 */
export declare function objValidModel(construct: Function|null = null): PropertyValidator;

/**
 * Checks object has keys
 */
export declare function objHasKeys(keys: (string | symbol)[]): PropertyValidator;

/**
 * Checks object values by structure of validators
 */
export declare function objProps(
    propValidators: Record<string | symbol, PropertyValidator>
): PropertyValidator;

/**
 * Validate string by lambda
 */
export declare function string(
    valid?: ((s: string) => string[] | boolean) | null
): PropertyValidator;

/**
 * Validate string by lambda
 */
export declare function stringLength(
    valid?: ((s: number) => string[] | boolean) | null
): PropertyValidator;

/**
 * Validate string by lambda
 */
export declare function stringRegMatch(regex: RegExp | string): PropertyValidator;

/**
 * Validate string by lambda
 */
export declare function stringUuid(): PropertyValidator;

/**
 * Validate boolean value
 */
export declare function boolean(
    valid?: ((s: boolean) => string[] | boolean) | null
): PropertyValidator;

/**
 * validate Symbol value
 */
export declare function symbol(
    valid?: ((s: symbol) => string[] | boolean) | null
): PropertyValidator;

/**
 * Validate value is Null
 */
export declare function isNull(): PropertyValidator;

/**
 * Validate value is Undefined
 */
export declare function isUndefined(): PropertyValidator;

/**
 * Validate value is function
 */
export declare function func(
    valid?: ((s: Function) => string[] | boolean) | null
): PropertyValidator;

/**
 * Validate value by lambda
 * (You may use it with `validator` package)
 */
export declare function lambda(valid: (a: any) => boolean | string[]): PropertyValidator;

/**
 * Modify any validator. Allows falsable values
 */
export function maybe(valid: PropertyValidator): PropertyValidator

Author

Anatoly Starodubtsev [email protected]

License

MIT