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 🙏

© 2025 – Pkg Stats / Ryan Hefner

valipass

v1.0.0

Published

Collection of password validation actions for Valibot schemas

Downloads

79

Readme

🎟️ Valipass

npm version CI status

Collection of password validation actions for Valibot schemas


📦 Installation

[!Note]

This library is distributed only as an ESM module.

$ npm install valipass

or:

$ yarn add valipass

🔧 Usage

Example usage with Valibot:

import * as v from "valibot";
import { password } from "valipass";

const loginSchema = v.object({
  username: v.pipe(v.string(), v.email()),
  password: password()
});

const result = v.safeParse(loginSchema, {
  username: "[email protected]",
  password: "secret"
});

Will yield the following result with issues:

{
  typed: true,
  success: false,
  output: { username: '[email protected]', password: 'secret' },
  issues: [
    {
      kind: 'validation',
      type: 'min_length',
      input: 'secret',
      expected: '>=8',
      received: '6',
      message: 'Invalid length: Expected >=8 but received 6',
      requirement: 8,
      path: [
        {
          type: 'object',
          origin: 'value',
          input: {...},
          key: 'password',
          value: 'secret'
        }
      ],
      issues: undefined,
      lang: undefined,
      abortEarly: undefined,
      abortPipeEarly: undefined
    },
    {
      kind: 'validation',
      type: 'min_uppercase',
      input: 'secret',
      expected: '>=1',
      received: '6',
      message: 'Invalid count: Expected >=1 but received 6',
      requirement: 1,
      path: [
        {
          type: 'object',
          origin: 'value',
          input: {...},
          key: 'password',
          value: 'secret'
        }
      ],
      issues: undefined,
      lang: undefined,
      abortEarly: undefined,
      abortPipeEarly: undefined
    },
    {
      kind: 'validation',
      type: 'min_numbers',
      input: 'secret',
      expected: '>=1',
      received: '6',
      message: 'Invalid count: Expected >=1 but received 6',
      requirement: 1,
      path: [
        {
          type: 'object',
          origin: 'value',
          input: {...},
          key: 'password',
          value: 'secret'
        }
      ],
      issues: undefined,
      lang: undefined,
      abortEarly: undefined,
      abortPipeEarly: undefined
    },
    {
      kind: 'validation',
      type: 'min_symbols',
      input: 'secret',
      expected: '>=1',
      received: '6',
      message: 'Invalid count: Expected >=1 but received 6',
      requirement: 1,
      path: [
        {
          type: 'object',
          origin: 'value',
          input: {...},
          key: 'password',
          value: 'secret'
        }
      ],
      issues: undefined,
      lang: undefined,
      abortEarly: undefined,
      abortPipeEarly: undefined
    }
  ]
}

Override the default rules:

import * as v from "valibot";
import { password } from "valipass";

const loginSchema = v.object({
  username: v.pipe(v.string(), v.email()),
  // by default, a password is expected to be between 8 and 250 characters
  // here, we set that to between 16 and 32 characters, and add a
  // space-separated "words" requirement
  password: v.pipe(password({ min: 16, max: 32 }), v.minWords(`en`, 5))
});

const result = v.safeParse(loginSchema, {
  username: "[email protected]",
  password: "Min word requirement 1!"
});

Will yield the following result with a minimum words issue:

{
  typed: true,
  success: false,
  output: {
    username: '[email protected]',
    password: 'Min word requirement 1!'
  },
  issues: [
    {
      kind: 'validation',
      type: 'min_words',
      input: 'Min word requirement 1!',
      expected: '>=5',
      received: '4',
      message: 'Invalid words: Expected >=5 but received 4',
      requirement: 5,
      path: [
        {
          type: 'object',
          origin: 'value',
          input: {...},
          key: 'password',
          value: 'Min word requirement 1!'
        }
      ],
      issues: undefined,
      lang: undefined,
      abortEarly: undefined,
      abortPipeEarly: undefined
    }
  ]
}

Pick and choose your password rules:

import * as v from "valibot";
import { minLowercase, minUppercase, minNumbers, minSymbols, maxRepeating } from "valipass";

const passwordSchema = v.pipe(
  v.string(),
  // has a minimum length of 8 characters
  v.minLength(8),
  // has a maximum length of 32 characters
  v.maxLength(32),
  // must contain a lowercase character
  minLowercase(1),
  // must contain an uppercase character
  minUppercase(1),
  // must use at least one number
  minNumbers(1),
  // must use at least one symbol
  minSymbols(1),
  // don't allow more than 2 repeated characters in a row
  maxRepeating(2)
);

const loginSchema = v.pipe(
  v.object({
    username: v.pipe(v.string(), v.email()),
    password1: passwordSchema,
    password2: v.string()
  }),
  v.forward(
    v.partialCheck(
      [["password1"], ["password2"]],
      (input) => input.password1 === input.password2,
      "The two passwords do not match."
    ),
    ["password2"]
  )
);

const result = v.safeParse(loginSchema, {
  username: "[email protected]",
  password1: "val!dPassw0rd",
  password2: "invalidPassword"
});

Will yield the following result with a partial_check issue:

{
  typed: true,
  success: false,
  output: {
    username: '[email protected]',
    password1: 'val!dPassw0rd',
    password2: 'invalidPassword'
  },
  issues: [
    {
      kind: 'validation',
      type: 'partial_check',
      input: {
        username: '[email protected]',
        password1: 'val!dPassw0rd',
        password2: 'invalidPassword'
      },
      expected: null,
      received: 'Object',
      message: 'The two passwords do not match.',
      path: [
        {
          type: 'unknown',
          origin: 'value',
          input: {...},
          key: 'password2',
          value: 'invalidPassword'
        }
      ],
      issues: undefined,
      lang: undefined,
      abortEarly: undefined,
      abortPipeEarly: undefined,
      requirement: λ
    }
  ]
}

🧰 API

password()

A Password schema with some sensible defaults which can be overriden when providing an optional configuration object.

By default, a password must meet these requirements:

  • must be a string
  • contain at least 8 characters
  • contain at most 250 characters
  • contain at least 1 lowercase letter
  • contain at least 1 uppercase letter
  • contain at least 1 number
  • contain at least 1 symbol

Options:

interface PasswordOptions {
  /** Minumum number of characters */
  min?: number;
  /** Maxmimum number of characters */
  max?: number;
  /** Minimum number of lowercase letters */
  lowercase?: number;
  /** Minimum number of uppercase letters */
  uppercase?: number;
  /** Minimum number of number characters */
  numbers?: number;
  /** Minimum number of symbols */
  symbols?: number;
}

Override Example:

const customPasswordSchema = password({ min: 6, max: 16 });

minLowercase(requirement: number = 1, message?: string)

Creates a min lowercase validation action.

const schema = v.pipe(v.string(), minLowercase(3, "More lowercase characters required!"));

minUppercase(requirement: number = 1, message?: string)

Creates a min uppercase validation action.

const schema = v.pipe(v.string(), minUppercase(3, "More uppercase characters required!"));

minNumbers(requirement: number = 1, message?: string)

Creates a min numbers validation action.

const schema = v.pipe(v.string(), minNumbers(3, "More number characters required!"));

minSymbols(requirement: number = 1, message?: string)

Creates a min symbols validation action.

const schema = v.pipe(v.string(), minSymbols(3, "More symbol characters required!"));

maxRepeating(requirement: number = 2, message?: string)

Creates a max repeating validation action.

const schema = v.pipe(v.string(), maxRepeating(3, "Too many repeated characters in a row!"));

📣 Acknowledgements

Valipass' implementation is based on yup-password

🥂 License

Released under the MIT license © Drake Costa.