{"id":29287895,"url":"https://github.com/huntergera/yh-validator","last_synced_at":"2025-07-06T02:07:35.132Z","repository":{"id":301615972,"uuid":"1009243351","full_name":"huntergera/yh-validator","owner":"huntergera","description":"A lightweight form validation library with modular functions","archived":false,"fork":false,"pushed_at":"2025-07-05T08:36:41.000Z","size":48,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-07-05T08:43:24.572Z","etag":null,"topics":["email-validation","form-validation","formik","javascript-library","lightweight","modular","npm-package","password-validation","phone-validation","react","react-form","typescript","username-validation","validation-library","validator","yup"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/huntergera.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-26T20:10:41.000Z","updated_at":"2025-07-05T08:36:44.000Z","dependencies_parsed_at":"2025-06-29T03:01:16.408Z","dependency_job_id":null,"html_url":"https://github.com/huntergera/yh-validator","commit_stats":null,"previous_names":["huntergera/yh-validator"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/huntergera/yh-validator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huntergera%2Fyh-validator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huntergera%2Fyh-validator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huntergera%2Fyh-validator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huntergera%2Fyh-validator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/huntergera","download_url":"https://codeload.github.com/huntergera/yh-validator/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huntergera%2Fyh-validator/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263837468,"owners_count":23517952,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["email-validation","form-validation","formik","javascript-library","lightweight","modular","npm-package","password-validation","phone-validation","react","react-form","typescript","username-validation","validation-library","validator","yup"],"created_at":"2025-07-06T02:07:32.768Z","updated_at":"2025-07-06T02:07:35.072Z","avatar_url":"https://github.com/huntergera.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 📦yh-validator\n[![npm version](https://img.shields.io/npm/v/yh-validator.svg)](https://www.npmjs.com/package/yh-validator)\n[![npm downloads](https://img.shields.io/npm/dm/yh-validator.svg)](https://www.npmjs.com/package/yh-validator)\n[![license](https://img.shields.io/npm/l/yh-validator.svg)](https://github.com/huntergera/yh-validator/main/LICENSE)\n\nA lightweight, modular form validation library written in **TypeScript**, designed to be framework-agnostic and easy to use in any JavaScript or TypeScript project.\n\n---\n\n## 🚀 Features\n\n- 📧 Email validation\n- 📞 International phone number validation (with country support)\n- 🔐 Configurable password strength validation\n- 👤 Flexible username validation\n- ↔️ Deep equality comparison for objects and arrays\n- 🛠 Modular structure — import only what you need\n- 📦 Lightweight and dependency-minimized\n- 🔐 TypeScript-first with full type safety\n\n---\n\n## 📦 Installation\n\n```\nnpm install yh-validator\n```\nor\n```\nyarn add yh-validator\n```\n\n## ⚠️ Tree-shaking notice\nTo ensure optimal bundle size, import validators directly from their paths, for example:\n```ts\nimport { isEmail } from \"yh-validator/isEmail\";\nimport { isPhone } from \"yh-validator/isPhone\";\nimport { isStrongPassword } from \"yh-validator/isStrongPassword\";\n```\n\n## ✨ Usage\n### 📧 Validate Email\n```ts\nimport { isEmail } from 'yh-validator/isEmail';\n\nconsole.log(isEmail('test@example.com')); // true\nconsole.log(isEmail('invalid-email'));    // false\n```\n\n### 📞 Validate Phone Number\n```ts\nimport { isPhone } from 'yh-validator/isPhone';\n\n// With international format\nconsole.log(isPhone('+380961234567')); // true\n\n// With country code\nconsole.log(isPhone('0961234567', 'UA')); // true\n\n// Invalid\nconsole.log(isPhone('12345')); // false\n```\n\n### 🔐 Validate Password Strength\nThe `isStrongPassword` function returns an object containing `valid: boolean` and an `errors: string[]` array, providing detailed feedback on why a password might not meet the criteria.\n```ts\nimport { isStrongPassword } from 'yh-validator/isStrongPassword';\n\n// Basic usage with default options (min 8 chars, 1 uppercase, 1 lowercase, 1 number, 1 special char)\nconst result1 = isStrongPassword('StrongP@ss1');\nconsole.log(result1.valid);   // true\nconsole.log(result1.errors);  // []\n\n// Password missing required elements\nconst result2 = isStrongPassword('weakpassword');\nconsole.log(result2.valid);   // false\nconsole.log(result2.errors);  // [\"Password must contain at least 1 uppercase letter(s).\", \"Password must contain at least 1 number(s).\", \"Password must contain at least 1 special character(s).\"]\n\n// Custom options\nconst result3 = isStrongPassword('simple123', {\n  minLength: 6,\n  minUppercase: 0,\n  minLowercase: 0,\n  minNumbers: 1,\n  minSpecialChars: 0,\n});\nconsole.log(result3.valid);   // true\nconsole.log(result3.errors);  // [] (valid based on custom relaxed rules)\n\nconst result4 = isStrongPassword('tooShort', { minLength: 10 });\nconsole.log(result4.valid);   // false\nconsole.log(result4.errors);  // [\"Password must be at least 10 characters long.\"]\n```\n\n### 👤 Validate Username\nThe `isUsername` function provides configurable rules for validating usernames, returning a detailed result object.\n```ts\nimport { isUsername } from 'yh-validator/isUsername';\n\n// Basic usage with default options (min 3, max 30, alphanumeric, dashes, underscores, periods allowed)\nconst result1 = isUsername('john_doe123');\nconsole.log(result1.valid);  // true\nconsole.log(result1.errors); // []\n\n// Username too short\nconst result2 = isUsername('ab');\nconsole.log(result2.valid);  // false\nconsole.log(result2.errors[0]); // [\"Username must be at least 3 characters long.\"]\n\n// Username with disallowed characters (e.g., !)\nconst result3 = isUsername('user!name');\nconsole.log(result3.valid);  // false\nconsole.log(result3.errors[0]); // [\"Username contains disallowed characters.\"]\n\n// Custom options: allow spaces, longer minLength, specific blacklist\nconst result4 = isUsername('My User Name', { \n  minLength: 5, \n  allowSpaces: true, \n  blacklist: ['admin', 'guest'] \n});\nconsole.log(result4.valid);  // true\nconsole.log(result4.errors); // []\n\n// Custom options: check against a specific blacklist\nconst result5 = isUsername('admin', { blacklist: ['admin', 'root'] });\nconsole.log(result5.valid);  // false\nconsole.log(result5.errors); // [\"Username is reserved or not allowed.\"]\n```\n\n### ↔️ Equality Comparison\n```ts\nimport { isEqual } from 'yh-validator/isEqual';\n\nconsole.log(isEqual('hello', 'hello')); // true\n```\n\n## 🧩 Integration with Schema Validation Libraries\nYou can easily integrate `yh-validator` functions with popular schema validation libraries like `Zod`, `Yup` and others using their custom validation methods. These libraries typically allow you to define custom validation rules that return a boolean (valid/invalid) or throw an error with a custom message.\n\n### Integrating with Zod\n(You'll need to install `zod`: `npm install zod`)\n```ts\nimport { z } from 'zod';\nimport { isEmail } from 'yh-validator/isEmail';\nimport { isStrongPassword } from 'yh-validator/isStrongPassword';\n\nexport const registrationSchema = z.object({\n  username: z.string().min(1, { message: \"Username is required\" }),\n  \n  email: z.string()\n    .min(1, 'Email is required')\n    .refine((value) =\u003e isEmail(value), 'Enter a valid email address'),\n  \n  password: z.string()\n    .min(8, { message: \"Password must be at least 8 characters long.\" }) // Base Zod length check\n    .refine((value) =\u003e {\n      // Use isStrongPassword to check complexity\n      const result = isStrongPassword(value);\n      return result.valid; // Zod's .refine expects a boolean\n    }, (value) =\u003e {\n      // If validation fails, Zod calls this function to get the error message.\n      // Re-run isStrongPassword to get the detailed errors to display.\n      const result = isStrongPassword(value); \n      return { message: result.errors[0] || \"Password is not strong enough.\" };\n    }),\n});\n```\n\n### Integrating with Yup\n(You'll need to install `yup`: `npm install yup`)\n```ts\nimport * as yup from 'yup';\nimport { isEmail } from 'yh-validator/isEmail';\nimport { isStrongPassword } from 'yh-validator/isStrongPassword';\n\nexport const userProfileSchema = yup.object().shape({\n  email: yup.string()\n    .required('Email is required.')\n    .test(\n      'is-valid-email', \n      'Please enter a valid email address.', \n      (value) =\u003e value ? isEmail(value) : false\n    ),\n  \n  password: yup.string()\n    .required('Password is required.')\n    .min(8, 'Password must be at least 8 characters long (base check).') // Optional: you can add a base length measurement Yup\n    .test(\n      'is-strong-password', \n      '', // Empty string as message, we will generate dynamic message\n      function (value) {\n        if (!value) return false; // Handle empty/null values if not caught by .required()\n\n        const result = isStrongPassword(value, {\n          minLength: 8, // Ensure this matches or is greater than Yup's .min()\n          minUppercase: 1,\n          minLowercase: 1,\n          minNumbers: 1,\n          minSpecialChars: 1,\n        });\n        \n        if (!result.valid) {\n          // If validation fails, use this.createError to provide detailed message\n          return this.createError({ message: result.errors[0] || \"Password is not strong enough.\" });\n        }\n        return true; // Password is strong\n      }\n    ),\n});\n```\n\n## 📘 API Reference\n`isEmail(email: string): boolean`\n\nValidates whether the string is a well-formed email address.\n\n`isPhone(phoneNumber: string, countryCode?: string): boolean`\n\nValidates international phone numbers. If no `countryCode` is provided, assumes the number starts with `+`.\n\n`phoneNumber` — phone string to validate\n\n`countryCode` — (optional) ISO 2-letter country code (e.g. `\"US\"`, `\"UA\"`)\n\nInternally uses the [`phone`](https://www.npmjs.com/package/phone) library.\n\n`isStrongPassword(password: string, options?: PasswordValidationOptions): PasswordValidationResult`\n\nValidates the strength of a password based on configurable criteria.\n- `password` (string): The password string to validate.\n  - `options` (object, optional): An object to customize validation criteria.\n  - `minLength` (number): Minimum total length of the password (default: 8).\n  - `minUppercase` (number): Minimum number of uppercase letters (default: 1).\n  - `minLowercase` (number): Minimum number of lowercase letters (default: 1).\n  - `minNumbers` (number): Minimum number of digits (default: 1).\n  - `minSpecialChars` (number): Minimum number of special characters (default: 1).\n- Returns: `PasswordValidationResult` - An object `{ valid: boolean; errors: string[] }`.\n  - `valid:` true if the password meets all criteria, false otherwise.\n  - `errors:` An array of strings, each describing a failed validation criterion.\n\n`PasswordValidationOptions` Interface:\n```ts\ninterface PasswordValidationOptions {\n    minLength?: number;       // Default: 8\n    minUppercase?: number;    // Default: 1\n    minLowercase?: number;    // Default: 1\n    minNumbers?: number;      // Default: 1\n    minSpecialChars?: number; // Default: 1\n}\n```\n`PasswordValidationResult` Interface:\n```ts\ninterface PasswordValidationResult {\n    valid: boolean;   // True if all validation rules passed\n    errors: string[]; // Array of error messages if validation failed\n}\n```\n`isUsername(username: string, options?: UsernameValidationOptions): UsernameValidationResult`\nValidates a username based on configurable criteria, including length, allowed characters, and format.\n- `username` (string): The username string to validate.\n- `options` (object, optional): An object to customize validation criteria.\n  - `minLength` (number): Minimum total length of the username `(default: 3)`.\n  - `maxLength` (number): Maximum total length of the username `(default: 30)`.\n  - `allowSpaces` (boolean): Allow spaces within the username `(default: false)`.\n  - `allowDashes` (boolean): Allow hyphens - `(default: true)`.\n  - `allowUnderscores` (boolean): Allow underscores _ `(default: true)`.\n  - `allowPeriods` (boolean): Allow periods . `(default: true)`.\n  - `noLeadingTrailingSpecialChars` (boolean): Disallow special characters or spaces at the start or end `(default: true).\n  - `noConsecutiveSpecialChars` (boolean): Disallow two or more consecutive special characters like -- or __ `(default: true)`.\n  - `blacklist` (string[]): An array of usernames that are explicitly disallowed (case-insensitive) `(default: [])`.\n- Returns: `UserNameValidationResult` - An object `{ valid: boolean; errors: string[] }`.\n  - valid: true if the userName meets all criteria, false otherwise.\n  - errors: An array of strings, each describing a failed validation criterion.\n  \n`UserNameValidationOptions` Interface:\n```ts\ninterface UserNameValidationOptions {\n  minLength?: number;\n  maxLength?: number;\n  allowSpaces?: boolean;\n  allowDashes?: boolean;\n  allowUnderscores?: boolean;\n  allowPeriods?: boolean;\n  noLeadingTrailingSpecialChars?: boolean;\n  noConsecutiveSpecialChars?: boolean;\n  blacklist?: string[];\n}\n```\n`UserNameValidationResult` Interface:\n```ts\ninterface UserNameValidationResult {\n  valid: boolean;\n  errors: string[];\n}\n```\n`isEqual(a: string, b: string): boolean`\n- `a (string)`: The first value to compare.\n- `b (string)`: The second value to compare.\n- Returns: boolean - true if the two values are equal, false otherwise.\n\n## 🧪 Running Tests\n```\nnpm test\n```\nUses Vitest for unit testing.\n\n## 📁 Project Structure\n```\nsrc/\n├── isEmail.ts              # Email validator\n├── isPhone.ts              # Phone validator\n├── isPassworStrong.ts      # Password validator\n├── isUsername.ts           # userName validator\n├── isEqual.ts              # equality comparison\n└── index.ts                # Exports\n\ntests/\n├── email.test.ts\n├── isEqual.test.ts\n├── password.test.ts\n├── phone.test.ts\n└── userName.test.ts\n```\n\n## ❓ Why this exists\nThere are many username validation libraries — but most either:\n- lack of flexibility in character rules,\n- don’t support Formik/Yup integration well,\n- or don’t support things like blacklists or special character positioning.\n\nyh-validator was built to provide strict, customizable username validation with minimal dependencies — usable in modern React forms or plain JavaScript.\n\n## 📄 License\nMIT\nThis project is licensed under the [MIT License](https://github.com/huntergera/yh-validator/blob/master/LICENSE).\n\n## 📫 Contact\nFeel free to reach out if you have suggestions or need help integrating this package.\n\nGitHub: [@huntergera](https://github.com/huntergera)\n\nEmail: [yuriihieorhiu@gmail.com](mailto:yuriihieorhiu@gmail.com)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhuntergera%2Fyh-validator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhuntergera%2Fyh-validator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhuntergera%2Fyh-validator/lists"}