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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@carecard/validate

v3.1.27

Published

Validate data

Downloads

3,270

Readme

@carecard/validate

@carecard/validate is a small CommonJS validation package for CareCard services. It exposes individual value validators, a bulk property sanitizer, and a whitelist validator for request-like payloads.

The package returns booleans from the low-level validators, strips unknown or invalid values from validateProperties, and throws CareCard BAD_INPUT errors from validateWhitelistProperties when required or provided whitelist values do not pass validation.

Installation

npm install @carecard/validate

Importing

const { validate, validateProperties, validateWhitelistProperties, isEmailString, isValidUuidString } = require('@carecard/validate');

The validators are available both as top-level exports and under the deprecated validate namespace.

isEmailString('[email protected]'); // true
validate.isEmailString('[email protected]'); // true

Direct Validators

Every direct validator returns true or false. Failure message helpers return a string on failure and null on success.

| Function | Accepted value | | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | isImageUrl(value) | Non-empty string up to 2048 chars using letters, numbers, -, _, ., and /. Intended for safe image/file paths. | | isInteger(value) | JavaScript integer number. String numbers are rejected. | | isValidJsonString(value) | Non-empty string up to 10000 chars that parses to a non-null JSON object or array. JSON primitives are rejected. | | isValidIntegerString(value) | Digit-only string, 1 to 20 chars. No signs or decimals. | | isValidUuidString(value) | Canonical UUID string in 8-4-4-4-12 format, case-insensitive. | | isCharactersString(value) | 1 to 1000 chars containing letters, numbers, spaces, _, or -. | | isStreetString(value) | Non-empty street-like string up to 1000 chars using letters, numbers, spaces, ,, ., /, #, or -, and not starting with ,, _, or -. | | isNameString(value) | 1 to 1000 char string that starts with a letter and uses letters, numbers, spaces, _, -, ., ,, ', (, or ). Leading/trailing spaces are trimmed before pattern validation. | | isSafeSearchString(value) | Trimmed string that starts with a letter and then uses letters, numbers, spaces, _, -, ., ,, ', (, ), or @. | | isEmailString(value) | Email-like string up to 320 chars using the package email regex. | | isJwtString(value) | Non-blank JWT-like string up to 8192 chars that starts with eyJ and contains only letters, numbers, -, _, and .. | | isPasswordString(value) | 6 to 32 chars from letters, numbers, and !@#$%^&*_-, with at least one alphanumeric char and one listed special char. | | isSimplePasswordString(value) | 6 to 32 chars from letters, numbers, and !@#$%^&*_-. | | isPasswordStringFailureMessage(value) | null when isPasswordString passes, otherwise a human-readable failure message. | | isSimplePasswordStringFailureMessage(value) | null when isSimplePasswordString passes, otherwise a human-readable failure message. | | isUsernameString(value) | 1 to 200 alphanumeric chars. | | isPhoneNumber(value) | North American 10-digit phone number with optional parentheses around the area code and optional space, -, or . separators. | | isUrlSafeString(value) | Non-blank string up to 2048 chars using letters, numbers, -, _, and .. | | isString6To24CharacterLong(value) | String with length from 6 to 24. | | isString6To16CharacterLong(value) | String with length from 6 to 16. | | isProvinceString(value) | ON or QC, case-insensitive. | | isBoolValue(value) | Boolean true/false or strings "true"/"false". | | isPostalCodeString(value) | Canadian postal code format, case-insensitive, with optional middle space. | | isSafeString(value) | 1 to 10000 chars using letters, numbers, spaces, -, _, ., ,, #, *, ', (, ), [, ], or :. | | isInStringArray(array, value) | value, after lowercase/trim validation as a name string, is included in the supplied array. | | isCountryCodeString(value) | Country dialing code in +1 to +999 format. | | isValidDomainName(value) | Domain name with at least one dot, valid DNS-like labels, and max total length 253. | | isValidTimestampzString(value) | ISO 8601 timestamp with Z or +/-HH:MM timezone offset. | | isValidTimestampString(value) | ISO 8601 timestamp without timezone offset. | | isValidUrl(value) | Absolute http:// or https:// URL up to 2048 chars. | | isValidArrayOfStrings(value) | Array where every element passes isSafeString. |

validateProperties(obj)

validateProperties accepts an object and returns a new object that contains only recognized keys whose values pass the validator assigned to that key. Unknown keys and invalid values are silently omitted. null, undefined, or no argument returns {}.

const input = {
    first_name: 'Jane',
    email: '[email protected]',
    phone_number: '123',
    unknown_key: 'ignored',
};

validateProperties(input);
// {
//   first_name: 'Jane',
//   email: '[email protected]'
// }

Supported Property Keys

Keys are matched exactly. Both snake_case and camelCase variants are listed where the package supports both.

| Validator | Keys | | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | isNameString | first_name, firstName, last_name, lastName, username, new_status, newStatus, description, comment, status, name, title, brand, short_description, shortDescription, college_name, collegeName, campus_name, campusName, role, role_id, roleId, campus, institution_name, institutionName, program_name, programName, role_name, roleName, document_type, documentType, reason, entity_type, entityType, action_type, actionType, city, state, country, type | | isStreetString | street | | isCharactersString | postal_code, postalCode, period | | isBoolValue | is_primary, isPrimary, active | | isSafeSearchString | search_string, searchString | | isString6To16CharacterLong and isSimplePasswordString | password, new_password, newPassword | | isString6To16CharacterLong and isPasswordString | strong_password, strongPassword | | isEmailString | email | | isPhoneNumber | phone_number, phoneNumber | | isCountryCodeString | country_code, countryCode | | isUrlSafeString | token, email_confirm_token, emailConfirmToken, verification_token, verificationToken | | isValidUuidString | uuid, item_id, itemId, user_id, userId, address_id, addressId, image_id, imageId, order_id, orderId, category_id, categoryId, parent_id, parentId, college_id, collegeId, campus_id, campusId, program_id, programId, id, institution_id, institutionId, role_assignment_id, roleAssignmentId, user_role_id, userRoleId, phone_number_id, phoneNumberId, entity_id, entityId, changed_by, changedBy, request_id, requestId | | isValidIntegerString | offset_number, offsetNumber, number_of_orders, numberOfOrders, price, from, number, limit, offset | | isValidJsonString on the raw value | about | | isValidJsonString(JSON.stringify(value)) | weight, dimensions, permission, scope_data, scopeData, meta_data, metaData | | isValidArrayOfStrings | aliases | | isImageUrl or isValidUrl | image_url, imageUrl, website, file_url, fileUrl | | isValidDomainName | domain_name, domainName, domain, email_domain, emailDomain, email_domain_name, emailDomainName | | isValidTimestampzString or isValidTimestampString | expires_at, expiresAt, start_time, startTime, end_time, endTime |

validateWhitelistProperties(inputObject, requiredProperties, options)

validateWhitelistProperties extracts only the required and optional property paths you provide, validates each leaf through validateProperties, and returns a Promise<ValidatePropertiesResult> with the sanitized output.

const body = {
    first_name: 'Jane',
    email: '[email protected]',
    role: 'Admin',
    extra: '<script>',
};

const out = await validateWhitelistProperties(body, ['first_name', 'email'], {
    optionalProperties: ['role'],
});

// {
//   first_name: 'Jane',
//   email: '[email protected]',
//   role: 'Admin'
// }

Defaults

When omitted, requiredProperties defaults to [] and options defaults to:

{
    optionalProperties: [],
    convertToSnakeCase: false,
    flattenOutput: false,
    flattenKeyStyle: 'path',
}

The default output preserves the nested shape described by whitelisted dot paths. flattenKeyStyle only changes output when flattenOutput is true.

const input = {
    user: {
        first_name: 'Jane',
        contact: { email: '[email protected]' },
    },
};

await validateWhitelistProperties(input, ['user.first_name', 'user.contact.email']);
// {
//   user: {
//     first_name: 'Jane',
//     contact: { email: '[email protected]' }
//   }
// }

Options

| Option | Default | Behavior | | -------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | optionalProperties | [] | Additional property paths that may be present. Absent optional paths are ignored. Present optional paths must be valid. | | convertToSnakeCase | false | When true, converts returned keys, including nested keys, to snake_case using @carecard/common-util. Conversion happens before flattening. | | flattenOutput | false | When true, removes nested objects from the returned value so every validated leaf becomes a top-level key. | | flattenKeyStyle | 'path' | Controls flattened key naming when flattenOutput is true. Use 'path' for full dot-notation keys or 'leaf' for direct leaf names. Invalid values throw a BAD_INPUT error. |

Example with only the default options:

await validateWhitelistProperties({ first_name: 'Jane', email: '[email protected]', ignored: 'x' }, ['first_name']);
// { first_name: 'Jane' }

Example with optional properties:

await validateWhitelistProperties({ first_name: 'Jane', phone_number: '4165551234' }, ['first_name'], {
    optionalProperties: ['phone_number'],
});
// { first_name: 'Jane', phone_number: '4165551234' }

Required And Optional Values

Required paths must exist and pass validation. Missing or invalid required paths throw a CareCard bad input error.

await validateWhitelistProperties({ email: 'bad' }, ['email']);
// throws/rejects with:
// {
//   code: 'BAD_INPUT',
//   message: 'Bad_Input',
//   userMessage: 'Missing or invalid property: email'
// }

Optional paths are ignored when absent, but invalid when present.

await validateWhitelistProperties({ first_name: 'Jane', email: 'bad' }, ['first_name'], {
    optionalProperties: ['email'],
});
// userMessage: 'Invalid property value: email'

Nested Paths

Use dot notation for nested objects. The leaf key decides which validator is used.

const out = await validateWhitelistProperties(
    {
        user: {
            first_name: 'Jane',
            contact: { email: '[email protected]', ignored: 'x' },
        },
    },
    ['user.first_name', 'user.contact.email'],
);

// {
//   user: {
//     first_name: 'Jane',
//     contact: { email: '[email protected]' }
//   }
// }

Nested paths support up to 5 segments. The combined count of required and optional paths must be 5000 or fewer.

Arrays

If a whitelisted leaf value is an array, each element is validated as if it were the scalar value for that same leaf key. The array is accepted only when every element passes. Empty arrays are accepted.

await validateWhitelistProperties({ email: ['[email protected]', '[email protected]'] }, ['email']);
// { email: ['[email protected]', '[email protected]'] }

This array behavior is intended for repeated scalar fields such as email or name.

Case Conversion And Flattening

const out = await validateWhitelistProperties({ userInfo: { firstName: 'Jane', phoneNumber: '4165551234' } }, ['userInfo.firstName'], {
    optionalProperties: ['userInfo.phoneNumber'],
    convertToSnakeCase: true,
    flattenOutput: true,
});

// {
//   'user_info.first_name': 'Jane',
//   'user_info.phone_number': '4165551234'
// }

With flattenOutput: false or no flattenOutput option, nested paths keep the nested output shape:

const input = { a: { b: { c: { d: { email: '[email protected]' } } } } };
await validateWhitelistProperties(input, ['a.b.c.d.email']);
// { a: { b: { c: { d: { email: '[email protected]' } } } } }

With flattenOutput: true, keys are full dot paths by default:

const input = { a: { b: { c: { d: { email: '[email protected]', name: 'Jane' } } } } };
await validateWhitelistProperties(input, ['a.b.c.d.email', 'a.b.c.d.name'], {
    flattenOutput: true,
});
// { 'a.b.c.d.email': '[email protected]', 'a.b.c.d.name': 'Jane' }

Use flattenKeyStyle: 'leaf' to return top-level leaf keys instead:

const input = { a: { b: { c: { d: { email: '[email protected]', name: 'Jane' } } } } };
await validateWhitelistProperties(input, ['a.b.c.d.email', 'a.b.c.d.name'], {
    flattenOutput: true,
    flattenKeyStyle: 'leaf',
});
// { email: '[email protected]', name: 'Jane' }

When flattenKeyStyle: 'leaf' produces duplicate keys at different nesting levels, the higher-level value is kept and the lower-level duplicate is discarded. Duplicate leaf keys at the same nesting depth keep the first value encountered:

const input = {
    name: 'Top Level Name',
    user: { name: 'Nested Name', email: '[email protected]' },
};

await validateWhitelistProperties(input, ['name', 'user.name', 'user.email'], {
    flattenOutput: true,
    flattenKeyStyle: 'leaf',
});
// { name: 'Top Level Name', email: '[email protected]' }

TypeScript

The package ships index.d.ts and declares types for the CommonJS exports.

import { validateWhitelistProperties, isEmailString, ValidatePropertiesResult } from '@carecard/validate';

const valid: boolean = isEmailString('[email protected]');
const output: ValidatePropertiesResult = await validateWhitelistProperties({ first_name: 'Jane' }, ['first_name']);
const maxDepth: 5 = validateWhitelistProperties.MAX_NESTING_DEPTH;

Project Layout

index.js                         CommonJS public entry point
index.d.ts                       TypeScript declarations
lib/validate.js                  Direct value validators
lib/validateProperties.js        Key-to-validator sanitizer
lib/validateWhitelistProperties.js Required/optional whitelist validator
test/*.test.js                   Mocha runtime tests
test/types.test.ts               TypeScript declaration tests

Development

npm ci
npm run test
npm run test:types
npm run test:All
npm run lint
npm run format:check

CI runs on Node.js 25 and executes npm run test:All. Publishing to npm happens from main through the Publish to npm GitHub workflow.

Auth Boundary

Validation protects request shape, not authorization. ms-auth owns its auth-table RLS contract: normal users are self-row only, JWT roles: ["ad"] is the auth super-admin signal, and public auth flows use narrow system contexts. Do not use validators as a replacement for service RLS or database context checks.

Docs that mention ms-auth controller internals should use concise action names such as loginUser, registerUser, getUserDetail, and renewJwt. Access level is conveyed by route middleware and endpoint placement, not by public/protected/admin/Handler suffixes.