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

payload-guard-filter

v1.8.1

Published

Lightweight, zero-dependency shape-based payload filtering and sanitization for Node.js and browser

Readme

payload-guard

Part of the Professional Node.js Backend Toolkit


🛡️ Workflow

graph LR
    A[Request] --> B(Gatekeeper)
    B --> C{Shape Check}
    C -- Valid --> D[Redact & Clean]
    C -- Invalid --> E[Strict Error / Fail Safe]
    D --> F[Secure Response]
    E --> F
    F --> G((Metrics))

✨ Features

  • Shape-based filtering — Define what you want, auto-remove everything else
  • Sensitive field protectionpassword, token, secret automatically removed
  • Zero dependencies — Pure TypeScript, no external packages
  • Universal — Works in Node.js, Browser, React Native
  • TypeScript-first — Full type inference from shape definitions
  • Blazing fast — Compiled schemas for production performance
  • Never crashes — Graceful failure mode, production-safe

📦 Installation

npm install payload-guard

🚀 Quick Start

Basic Usage

import { guard } from 'payload-guard';

// Define a shape
const userShape = guard.shape({
  id: 'number',
  name: 'string',
  email: 'string',
});

// Filter data
const rawData = {
  id: 1,
  name: 'John Doe',
  email: '[email protected]',
  password: 'secret123',      // ❌ Will be removed
  internalNotes: 'VIP user',  // ❌ Will be removed
};

const safeData = userShape(rawData);
// Result: { id: 1, name: 'John Doe', email: '[email protected]' }

Advanced Validation (v1.4+)

const userShape = guard.shape({
  email: guard.string().email().toLowerCase().trim(),
  age: guard.number().min(18).max(100).default(18),
  tags: guard.array(guard.string().min(2)),
  role: guard.string().validate(v => ['admin', 'user'].includes(v)).default('user'),
  bio: guard.string().max(200).optional(),
});

Nested Object Validation (v1.7+)

Define nested shapes for deep object validation:

const userShape = guard.shape({
  id: 'number',
  profile: {
    name: 'string',
    email: guard.string().email(),
    age: guard.number().min(18),
    address: {
      street: 'string',
      city: 'string',
      zipCode: guard.string().regex(/^\d{5}(-\d{4})?$/),
    },
  },
  posts: guard.array({
    id: 'number',
    title: 'string',
    tags: guard.array('string'),
  }),
});

const input = {
  id: 1,
  profile: {
    name: 'John',
    email: '[email protected]',
    age: 30,
    address: {
      street: '123 Main St',
      city: 'NYC',
      zipCode: '10001',
    },
  },
  posts: [
    { id: 1, title: 'Hello', tags: ['intro'] },
  ],
};

const result = userShape(input);
// Filters all nested levels automatically

Custom Error Messages (v1.7+)

Add per-field custom error messages:

const userShape = guard.shape({
  email: guard
    .string()
    .email()
    .error('Please provide a valid email address'),
  
  username: guard
    .string()
    .min(5)
    .error((value, field) => `${field} must be at least 5 characters`),
  
  age: guard
    .number()
    .min(18)
    .max(100)
    .errorCodes({ min: 'AGE_TOO_YOUNG', max: 'AGE_TOO_OLD' }),
});

// Collect validation errors
const { compile } = require('payload-guard');
const errors = [];
const validator = compile(
  { email: { type: 'string', email: true } },
  { collectErrors: true, _errors: errors }
);

validator({ email: 'invalid' });
// errors: [{ field: 'email', message: '...', code: 'email' }]

📖 API Reference

guard.string()

Creates a string builder with chained constraints:

  • .min(length) — Minimum character length
  • .max(length) — Maximum character length
  • .email() — Basic email validation
  • .regex(pattern) — Regex pattern match
  • .trim() — Auto-trim whitespace (Transformation)
  • .toLowerCase() / .toUpperCase() — Case transformation

guard.number()

  • .min(value) / .max(value) — Range validation
  • .integer() — Ensure number is an integer
  • .positive() — Shortcut for .min(0)

Common Builder Methods

  • .required() / .optional() — Toggle requirement
  • .default(value) — Value to use if field is missing or invalid
  • .transform(fn) — Custom transformation function
  • .validate(fn) — Custom validation function (return false to fail)
  • .error(message) — Custom error message (string or function) (v1.7+)
  • .errorCodes(codes) — Custom error codes for validations (v1.7+)

New in v1.7+

Nested Object Support:

  • Define nested shapes as plain objects: { profile: { name: 'string', email: 'string' } }
  • Arrays with nested objects: guard.array({ id: 'number', name: 'string' })
  • Deep nesting supported at any level

Custom Error Messages:

  • .error('Custom message') — Static error message
  • .error((value, field) => \${field} is invalid`)` — Dynamic error message
  • .errorCodes({ min: 'TOO_SHORT', email: 'BAD_EMAIL' }) — Error codes

Error Collection:

const { compile } = require('payload-guard');
const errors = [];
const validator = compile(shape, { collectErrors: true, _errors: errors });
validator(data);
// errors array populated with { field, message, code, value }

Field Aliasing & Mapping (v1.6+)

Rename fields from your database to match your frontend API:

const userShape = guard.shape({
  id: guard.string().from('_id'), // Map DB _id to id
  workTime: guard.number().from('totalWorkTimeMs').transform(v => v / 1000),
  name: 'string',
});

// Input: { _id: '123', totalWorkTimeMs: 5000, name: 'Sannu' }
// Output: { id: '123', workTime: 5, name: 'Sannu' }

🛡️ "Never Crash" Policy

Payload Guard is designed for mission-critical enterprise environments where uptime is non-negotiable.

  • Circular Reference Safety: Automatically detects and handles circular objects without infinite loops or stack overflows.
  • Hook Isolation: Custom .transform() and .validate() callbacks are wrapped in internal try/catch blocks. If your code fails, the library logs the error and safely continues using fallback values.
  • Middleware Fail-Open: If internal filtering logic hits an unexpected edge case, failOpen: true ensures the original request/response still reaches its destination.

⚡ Performance

| Benchmark | ops/sec | avg (ms) | |-----------|---------|----------| | Small payload (5 fields) | 449,365 | 0.0022ms | | Medium payload (50 posts) | 7,791 | 0.1284ms | | Large payload (1000 users) | 246 | 4.0724ms |

Memory Usage: ~121 MB Heap Used (Stable)


🛡️ Fail-Safe Design

Built for production reliability:

  • Isolation: Monitoring failures never break your API responses. If a storage adapter or plugin crashes, the error is caught and logged, while the user's request continues normally.
  • Async-Only: All processing is non-blocking to ensure zero impact on event loop latency.

⛑️ Maintained actively.

Bug fixes usually within 24–48 hours.


📄 License

MIT