Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The Validator

The SDK exports a Validator class you can use in your own bot code to validate user input before acting on it. The same validator is used internally by every API method in the SDK, so you already know it works the way you expect.

Creating a validator

const { Validator } = require('highrise.bot');

const validate = new Validator();

How it works

Every method on the validator throws an Error if the value does not pass the check. This means you wrap your validation calls in a try/catch block and handle the error in one place instead of writing if/else checks everywhere:

bot.on('Chat', async (user, message) => {
    if (message.command() === '!mute') {
        const target = message.args(0);
        const duration = Number(message.args(1));

        try {
            validate
                .required(target, 'target')
                .string(target, 'target')
                .required(duration, 'duration')
                .positive(duration, 'duration')
        } catch (error) {
            await bot.message.send(`Invalid input: ${error.message}`);
            return;
        }

        // safe to use target and duration here
        const found = await bot.room.users.find(target);
        if (!found) {
            await bot.message.send(`${target} is not in the room.`);
            return;
        }

        await bot.room.moderation.mute(found.user.id, duration);
        await bot.message.send(`${target} has been muted for ${duration} seconds.`);
    }
});

Method chaining

Every method returns the Validator instance so you can chain multiple checks together in one block:

validate
    .required(username, 'username')
    .string(username, 'username')
    .minLength(username, 3, 'username')
    .match(username, /^[a-z0-9]+$/, 'username');

The chain stops at the first method that fails. If string() throws, minLength() and match() never run.

All methods

Highrise specific

These two methods validate Highrise-specific data structures in a single call so you do not have to validate each coordinate or anchor property individually:

MethodWhat it checks
.isCoordinates(x, y, z, facing)All four position values including a valid facing direction
.isAnchor(entity_id, anchor_ix)An anchor entity ID and its seat index

facing must be one of "FrontRight", "FrontLeft", "BackRight", or "BackLeft". Anything else throws.

Type and existence

MethodWhat it checks
.required(val, field)Value is not null or undefined
.string(val, field)Value is a non-empty string
.number(val, field)Value is a valid number and not NaN
.boolean(val, field)Value is true or false
.array(val, field)Value is an array
.object(val, field)Value is a plain object, not an array, not null

Numbers

MethodWhat it checks
.integer(val, field)Value is a whole number with no decimal
.positive(val, field)Value is greater than zero
.nonNegative(val, field)Value is zero or greater
.range(val, min, max, field)Value falls between min and max inclusive

Strings

MethodWhat it checks
.minLength(val, min, field)String is at least min characters long
.maxLength(val, max, field)String is no longer than max characters
.match(val, regex, field)String matches the regular expression

Arrays

MethodWhat it checks
.nonEmptyArray(val, field)Value is an array with at least one item
.oneOf(val, options, field)Value exists in the provided array of options

The field name

Every method takes a field argument as its last parameter. This is the name that appears in the error message when the check fails. Always use a name that makes sense to whoever reads the error:

validate.string(userId, 'userId');
// throws: "userId must be a non-empty string"

validate.positive(amount, 'amount');
// throws: "amount must be a positive number"

validate.range(page, 1, 100, 'page number');
// throws: "page number must be between 1 and 100"

Use descriptive field names. 'userId' is better than 'id'. 'tip amount' is better than 'val'. The clearer the field name, the more useful the error message is to whoever reads it, next page we will explain each event and what it gives you to work with.