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

@fantasy42/vallo

v0.1.1

Published

Lightweight validation engine for dynamic strings and reserved identifiers.

Downloads

176

Readme

Vallo

npm version License: MIT TypeScript Zero Dependencies Tree Shakeable

A lightweight, zero-dependency validation engine for dynamic strings and reserved identifiers in TypeScript. Perfect for validating routes, usernames, and custom identifiers with built-in security checks.

✨ Features

  • 🚀 Zero Dependencies - No external libraries, just pure TypeScript
  • 📦 Tree Shakeable - Only bundle what you use
  • 🔒 Security First - Blocks reserved system words and impersonation terms
  • 🎯 Type Safe - Full TypeScript support with strict typing
  • Fast - Optimized for performance with minimal overhead
  • 🛠️ Customizable - Extend with your own reserved lists and validation rules
  • 📱 ESM & CommonJS - Supports both module systems

📦 Installation

npm install @fantasy42/vallo

or

yarn add @fantasy42/vallo

or

pnpm add @fantasy42/vallo

🚀 Quick Start

import { vallo } from '@fantasy42/vallo';

// Validate a route
if (vallo.route('my-profile')) {
  console.log('Route is available!');
} else {
  console.log('Route is reserved or invalid');
}

// Validate a username
if (vallo.username('john.doe')) {
  console.log('Username is valid!');
}

📚 API Reference

Core Validators

vallo.route(segment: unknown): boolean

Validates route segments against reserved system routes and brand terms.

vallo.route('admin'); // false - reserved
vallo.route('my-route'); // true - valid

vallo.username(segment: unknown): boolean

Validates usernames with alphanumeric characters, dots, and underscores.

vallo.username('root'); // false - reserved
vallo.username('user-name'); // false - dashes not allowed
vallo.username('username123'); // true

Custom Validators

Create your own validators with custom rules by extending the core validators:

import { createUsernameValidator } from '@fantasy42/vallo';

// Custom username validator for a social platform
const socialUsernameValidator = createUsernameValidator({
  extensions: ['blocked-name-1', 'blocked-name-2'],
  caseSensitive: false, // Default: case-insensitive
  maxLength: 25,
  minLength: 3,
  pattern: /^[a-zA-Z0-9._-]+$/ // Alphanumeric, dots, underscores, dashes
});

// Usage examples
console.log(socialUsernameValidator('john.doe')); // true
console.log(socialUsernameValidator('blocked-name-1')); // false (in extensions)
console.log(socialUsernameValidator('user_name')); // true
console.log(socialUsernameValidator('user@name')); // false (special chars not allowed)

Extended Validators

For advanced use cases, import from the extended module:

import { createExtendedRouteValidator } from '@fantasy42/vallo/extended';

Integration with Frameworks

Important: Always validate and sanitize user inputs before processing. Use libraries like Zod for robust input validation to prevent injection attacks and ensure data integrity.

Express.js Route Validation

import express from 'express';
import { z } from 'zod';
import { vallo } from '@fantasy42/vallo';

const app = express();
app.use(express.json());

// Input validation schema
const routeSchema = z
  .string()
  .min(1)
  .max(50)
  .trim()

app.get('/:route', (req, res) => {
  // Validate input first
  const validation = routeSchema.safeParse(req.params.route);
  if (!validation.success) {
    return res.status(400).json({ error: 'Invalid route format' });
  }

  const route = validation.data;

  // Then check against reserved words
  if (!vallo.route(route)) {
    return res.status(400).json({ error: 'Route is reserved or invalid' });
  }

  res.json({ message: `Route ${route} is valid and available` });
});

React Form Validation

import React, { useState } from 'react';
import { z } from 'zod';
import { vallo } from '@fantasy42/vallo';

// Input validation schema
const usernameSchema = z
  .string()
  .min(3)
  .max(30)
  .trim()

function UsernameForm() {
  const [username, setUsername] = useState('');
  const [error, setError] = useState('');

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();

    // Validate input format first
    const validation = usernameSchema.safeParse(username);
    if (!validation.success) {
      setError(validation.error.errors[0].message);
      return;
    }

    const cleanUsername = validation.data;

    // Then check against reserved words and patterns
    if (!vallo.username(cleanUsername)) {
      setError('Username is reserved or invalid.');
      return;
    }

    // Submit form
    console.log('Username is valid:', cleanUsername);
    setError('');
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
        placeholder="Enter username"
      />
      {error && <p style={{ color: 'red' }}>{error}</p>}
      <button type="submit">Submit</button>
    </form>
  );
}

🔧 Configuration Options

All validators support the following options:

| Option | Type | Default | Description | |--------|------|---------|-------------| | extensions | ReservedList | undefined | Additional reserved words to block | | caseSensitive | boolean | false | Whether validation is case-sensitive | | maxLength | number | 50 | Maximum allowed length | | minLength | number | 3 | Minimum allowed length | | pattern | RegExp \| null | null | Custom regex pattern to match against |

🏗️ TypeScript Support

Vallo is written in TypeScript and provides full type safety:

import type { Validator, ValidatorOptions } from '@fantasy42/vallo';

// Types are exported for advanced usage
const options: ValidatorOptions = {
  extensions: ['forbidden'],
  caseSensitive: true
};

const validator: Validator = createRouteValidator(options);

🤝 Contributing

We welcome contributions!

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • Built with ❤️ using TypeScript
  • Inspired by the need for secure, type-safe validation in modern web apps

Made with ❤️ by Fantasy