Skip to content

10.2.0

Choose a tag to compare

@peterver peterver released this 23 Mar 15:13
· 45 commits to main since this release

Added

  • feat: Added a new validation rule literal which is used to tell validator that a provided value is a fixed/literal value. From a typing perspective this rule will be inferred as being of the provided param value.
const v = Validator.create({
    type: 'literal:act_send',
    message: 'string_ne',
    target: 'email',
});

/* Get type */
type vType = typeof v.schema;

/* Type will be the following */
type vType = {
    type: 'act_send',
    message: string;
    target: Email;
}

This of course can be used in conditional groups as well:

const v = Validator.create({
    userId: 'guid',
    action: [
        {
            type: 'literal:sent',
            message: 'string_ne',
            target: ['email', 'phone']
        }, {
            type: 'literal:received',
            message: 'string_ne',
            from: ['email', 'phone']
        }
    ],
});

/* Get type */
type vType = typeof v.schema;

/* Type will be the following */
type vType = {
    userId: GUID;
    action: {
        type: 'sent';
        message: string;
        target: Email | Phone
    } | {
        type: 'received';
        message: string;
        from: Email | Phone
    }
}
  • feat: Added support to pass multiple schemas to Validator.create, if multiple schemas are passed they will be treated as an OR group and if one of them passes it will be seen as valid.
const v = Validator.create([
    {
        type: 'literal:sent',
        message: 'string_ne',
        target: ['email', 'phone']
    }, {
        type: 'literal:received',
        message: 'string_ne',
        from: ['email', 'phone']
    },
]);

type vType = typeof v.schema;

/* Type will be the following */
type vType = {
    type: 'sent';
    message: string;
    target: Email | Phone
} | {
    type: 'received';
    message: string;
    from: Email | Phone
}

This can lead to some very powerful scripting simply based on the behind-the-scenes type inferrence, for example:

const v = Validator.create([
    {type: 'literal:sent', message: 'string_ne', target: ['email', 'phone']},
    {type: 'literal:received', message: 'string_ne', from: ['email', 'phone']},
]);

function someFunction (data:Record<string, unknown>) {
    if (!v.check(data)) return false;

    /* Typescript will automatically infer data.type as 'sent' | 'received' thanks to the type guard on v.check */
    switch (data.type) {
        case 'sent':
            console.log('Sent a message');
            break;
        case 'received':
            console.log('Received a message');
            break;
        case 'bla': /* Typescript will complain here as there's no possible branch called 'bla' */
            console.log('Something unknown');
            break;
    }
}

Going one step further, you could also externally define those validators and create an or-based validator from the external validators:

import {vSent, onSent} from './onSentHandler'; /* vSent is a Validator instance here */
import {vReceived, onReceived} from './onReceivedHandler'; /* vReceived is a Validator instance here */

const v = Validator.create([vSent, vReceived]);

function someFunction (data:Record<string, unknown>) {
    if (!v.check(data)) return false;

    switch (data.type) {
        case 'sent': onSent(data); break;
        case 'received': onReceived(data); break;
        case 'bla' /* Typescript will complain here as there's no bla in the union */
    }
};

Improved

  • perf: Minor performance improvement in extended enum/regex/schema rules thanks to eliminating an internal retrieval step
  • deps: Upgrade @types/node to 22.13.11
  • deps: Upgrade @valkyriestudios/utils to 12.35.0
  • deps: Upgrade eslint to 9.23.0
  • deps: Upgrade typescript-eslint to 8.27.0