ProvenPin Install

validator.js input cleaning: working versions (tested 2026-10-15)

Validate and sanitize form input with validator.js: isEmail, isURL with protocol options, isUUID, isStrongPassword scoring, plus normalizeEmail, escape and trim sanitizers offline.

passed6 passed · 0 failed2026-10-15 22:58 UTC
Status
passed
Last passed
2026-10-15 22:58 UTC
Tests
6 / 6
Language
TypeScript
Runtime
node v22.23.3
pinned versions4
validator@13.15.35@types/validator@13.15.10@types/node@26.6.5tsx@4.23.15
run it
npm install --no-audit --no-fund --ignore-scripts=false
npm test
test environment
node v22.23.3
linux 6.17.0-1022-azure
x64
runner: github-actions 38820570375

The code

Exactly the files that passed. Your agent can pull them with get_recipe("validator-js-sanitize") (install), or see them on GitHub.

package.json
{
  "name": "validator-js-sanitize",
  "private": true,
  "type": "module",
  "scripts": {
    "test": "node --import tsx --test test/*.test.ts"
  },
  "dependencies": {
    "validator": "13.15.35"
  },
  "devDependencies": {
    "@types/validator": "13.15.10",
    "@types/node": "26.6.5",
    "tsx": "4.23.15"
  }
}
src/sanitize.ts
import validator from "validator";

// validator is CommonJS: use the default export, named ESM imports fail at runtime.
const {
  escape,
  isEmail,
  isStrongPassword,
  isURL,
  isUUID,
  normalizeEmail,
  trim,
} = validator;

export type RawInput = {
  email?: unknown;
  website?: unknown;
  userId?: unknown;
  password?: unknown;
  note?: unknown;
};

export type CleanInput = {
  email: string;
  emailValid: boolean;
  website: string;
  websiteValid: boolean;
  userId: string;
  userIdValid: boolean;
  passwordScore: number;
  passwordStrong: boolean;
  note: string;
};

function str(value: unknown): string {
  return typeof value === "string" ? value : "";
}

export function scorePassword(password: string): number {
  return isStrongPassword(password, { returnScore: true }) as unknown as number;
}

export function cleanInput(input: RawInput): CleanInput {
  const email = trim(str(input.email));
  const website = trim(str(input.website));
  const userId = trim(str(input.userId)).toLowerCase();
  const password = str(input.password);
  const note = escape(trim(str(input.note)));

  return {
    email: normalizeEmail(email) || email,
    emailValid: isEmail(email),
    website,
    websiteValid: isURL(website, {
      require_protocol: true,
      protocols: ["http", "https"],
    }),
    userId,
    userIdValid: isUUID(userId, "4"),
    passwordScore: scorePassword(password),
    passwordStrong: isStrongPassword(password),
    note,
  };
}
test/sanitize.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { cleanInput, scorePassword } from "../src/sanitize.ts";

test("validates and normalizes an email", () => {
  const result = cleanInput({ email: "  [email protected]  " });
  assert.equal(result.emailValid, true);
  assert.equal(result.email, "[email protected]");
});

test("flags malformed emails", () => {
  const result = cleanInput({ email: "not-an-email" });
  assert.equal(result.emailValid, false);
});

test("validates URLs with protocol options", () => {
  assert.equal(cleanInput({ website: "https://example.com" }).websiteValid, true);
  assert.equal(cleanInput({ website: "ftp://example.com" }).websiteValid, false);
});

test("validates UUID v4 values", () => {
  assert.equal(
    cleanInput({ userId: "F47AC10B-58CC-4372-A567-0E02B2C3D479" }).userIdValid,
    true,
  );
  assert.equal(cleanInput({ userId: "nope" }).userIdValid, false);
});

test("scores strong passwords higher than weak ones", () => {
  const weak = scorePassword("password");
  const strong = scorePassword("Str0ng!Passw0rd");
  assert.equal(cleanInput({ password: "password" }).passwordStrong, false);
  assert.equal(cleanInput({ password: "Str0ng!Passw0rd" }).passwordStrong, true);
  assert.ok(strong > weak);
});

test("escapes and trims notes with sanitizers", () => {
  const result = cleanInput({ note: "  <b>hi & bye  " });
  assert.equal(result.note, "&lt;b&gt;hi &amp; bye");
});

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.