{"id":19299673,"url":"https://github.com/supendi/ts-validity","last_synced_at":"2025-02-24T01:22:09.458Z","repository":{"id":233078313,"uuid":"775318410","full_name":"supendi/ts-validity","owner":"supendi","description":null,"archived":false,"fork":false,"pushed_at":"2024-04-13T00:41:27.000Z","size":363,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-05T22:54:57.313Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/supendi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2024-03-21T06:52:55.000Z","updated_at":"2024-04-13T01:12:57.000Z","dependencies_parsed_at":"2024-04-13T14:02:49.680Z","dependency_job_id":"4d628cd9-9617-43f0-b93f-224557c14a73","html_url":"https://github.com/supendi/ts-validity","commit_stats":null,"previous_names":["supendi/ts-validity"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supendi%2Fts-validity","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supendi%2Fts-validity/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supendi%2Fts-validity/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supendi%2Fts-validity/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/supendi","download_url":"https://codeload.github.com/supendi/ts-validity/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240400919,"owners_count":19795444,"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":[],"created_at":"2024-11-09T23:12:22.068Z","updated_at":"2025-02-24T01:22:09.403Z","avatar_url":"https://github.com/supendi.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ts-validity\n\n## Installation\n```\nnpm install ts-validity       # npm\nyarn add ts-validity          # yarn\n```\n\n## Usage\n### Let's start with simple validation\nGiven interface\n```typescript\ninterface Account {\n    name: string,\n    age: number,\n    email: string\n}\n```\n\nCreate the validation rule and validate the object\n```typescript\nimport { objectValidator, ValidationRule, minNumber, required, emailAddress } from \"ts-validity\";\n\nconst validationRule: ValidationRule\u003cAccount\u003e = {\n    name: [required(\"Account name is required.\")],\n    age: [required(), minNumber(17, \"Should be at least 17 years old.\")],\n    email: [required(), emailAddress(\"Invalid email address\")]\n}\n\nconst account: Account = {\n    name: \"\",\n    age: 0,\n    email: \"\"\n}\n\nconst validationResult = objectValidator.validate(account, validationRule)\n\n// The above validationResult value:\n// {\n//     message: \"One or more validation errors occurred.\",\n//     isValid: false,\n//     errors: {\n//         name: [\"Account name is required.\"],\n//         age: [\"This field is required.\", \"Should be at least 17 years old.\"],\n//         email: [\"This field is required.\", \"Invalid email address\"],\n//     }\n// }\n\nNotice that the validationResult.errors property, has the same property names as the account object, but its dataype is array of string. \n```\n\n### Nested object validation\n```typescript\nimport { objectValidator, ValidationRule, minNumber, required, emailAddress } from \"ts-validity\";\n\ninterface Person {\n    name: string,\n    age: number,\n    child?: Person\n    address?: {\n        street: string,\n        city: {\n            name: string\n            country: {\n                name: string\n                continent: {\n                    name: string\n                }\n            }\n        }\n    }\n}\n\nconst rule: ValidationRule\u003cPerson\u003e = {\n    name: [required()],\n    age: [minNumber(20)],\n    address: {\n        street: [required()],\n        city: {\n            name: [required()],\n            country: {\n                name: [required()],\n                continent: {\n                    name: [required()],\n                }\n            }\n        }\n    },\n    child: {\n        name: [required()]\n    }\n}\n\nconst john: Person = {\n    name: \"\",\n    age: 0,\n    address: {\n        street: \"\",\n        city: {\n            name: \"\",\n            country: {\n                name: \"\",\n                continent: {\n                    name: \"\"\n                }\n            }\n        }\n    },\n    child: {\n        name: \"\",\n        age: 0,\n    }\n}\n\nconst validationResult = objectValidator.validate(john, rule)\n\n// validationResult = {\n//     message: defaultMessage.errorMessage,\n//     isValid: false,\n//     errors: {\n//         name: [\"This field is required.\"],\n//         age: [\"The minimum value for this field is 20.\"],\n//         address: {\n//             street: [\"This field is required.\"],\n//             city: {\n//                 name: [\"This field is required.\"],\n//                 country: {\n//                     name: [\"This field is required.\"],\n//                     continent: {\n//                         name: [\"This field is required.\"],\n//                     }\n//                 }\n//             }\n//         },\n//         child: {\n//             name: [\"This field is required.\"],\n//         }\n//     }\n// }\n```\n\n### Validate array property\n```typescript\nimport { objectValidator, ValidationRule, minNumber, required, emailAddress, arrayMinLen } from \"ts-validity\";\n\ninterface Product {\n    name?: string\n    units?: Unit[]\n}\n\ninterface Unit {\n    name: string,\n    conversion: number,\n}\n\nconst validationRule: ValidationRule\u003cProduct\u003e = {\n    name: [required()],\n    units: {\n        validators: [arrayMinLen(3, \"Product uom has to be at least 3 units.\")],\n        validationRule: {\n            name: [required()],\n            conversion: [minNumber(1)]\n        }\n    }\n}\n\nconst ironStick: Product = {\n    name: \"\",\n    units: [\n        {\n            name: \"\",\n            conversion: 0\n        },\n        {\n            name: \"cm\",\n            conversion: 0\n        }\n    ]\n}\n\nconst validationResult = objectValidator.validate(ironStick, validationRule)\n\n// validationResult = {\n//     message: defaultMessage.errorMessage,\n//     isValid: false,\n//     errors: {\n//         name: [\"This field is required.\"],\n//         units: {\n//             errors: [\"Product uom has to be at least 3 units.\"],\n//             errorsEach: [\n//                 {\n//                     index: 0,\n//                     errors: {\n//                         name: [\"This field is required.\"],\n//                         conversion: [\"The minimum value for this field is 1.\"]\n//                     },\n//                     validatedObject: {\n//                         name: \"\",\n//                         conversion: 0\n//                     }\n//                 },\n//                 {\n//                     index: 1,\n//                     errors: {\n//                         conversion: [\"The minimum value for this field is 1.\"]\n//                     },\n//                     validatedObject: {\n//                         name: \"cm\",\n//                         conversion: 0\n//                     }\n//                 }\n//             ]\n//         }\n//     }\n// }\n```\n\n## Custom Property Validator\nTo use your own validator, you can use the propertyValidator function.\nThe following is the signature of **propertyValidator** function:\n```typescript\nexport declare const propertyValidator: \u003cTValue, TObject\u003e(func: ValidateFunc\u003cTValue, TObject\u003e, errorMessage: string, validatorDescription?: string) =\u003e PropertyValidator\u003cTValue, TObject\u003e;\n```\n\nThe existing built-in property validators, including the propertyValidator actually is a closure that returns a validate function, which is called by the objectValidator. The following is the signature of the **ValidateFunc**:\n```typescript\nexport type ValidateFunc\u003cTValue, TObject\u003e = (value: TValue, objRef?: TObject) =\u003e boolean\n```\n\nAnd this is the **PropertyValidator** type:\n```typescript\nexport type PropertyValidator\u003cTValue, TObject\u003e = {\n    description: string;\n    validate: ValidateFunc\u003cTValue, TObject\u003e;\n    returningErrorMessage: string;\n};\n```\n\n### Usage\n```typescript\nimport { objectValidator, ValidationRule, propertyValidator } from \"ts-validity\";\n\ninterface Account {\n    name: string,\n}\n\nconst validationRule: ValidationRule\u003cAccount\u003e = {\n    name: [\n        // Name length minimum is 5 char\n        propertyValidator((value, object) =\u003e {\n            return value.length \u003e= 5\n        }, \"Name length minimum is 5 chars.\"),\n\n        // Must contain A letter\n        propertyValidator((value, object) =\u003e {\n            return value.toLocaleLowerCase().includes(\"a\")\n        }, \"Name must contain 'A' letter.\"),\n    ],\n}\n\nconst account: Account = {\n    name: \"John\",\n}\n\nconst validationResult = objectValidator.validate(account, validationRule)\n\n// validationResult = {\n//     message: \"One or more validation errors occurred.\",\n//     isValid: false,\n//     errors: {\n//         name: [\"Name length minimum is 5 chars.\", \"Name must contain 'A' letter.\"]\n//     }\n// }\n```\n\n## Use existing npm validator package as custom validator\n\nWe can use and combine the existing popular validator from npm. In this example I use the validator package (https://www.npmjs.com/package/validator).\n\n### Installation\n```typescript\nnpm install validator\nnpm install -D @types/validator // if typescript\n```\n\n### Usage\n```typescript\nimport { objectValidator, ValidationRule, propertyValidator } from \"ts-validity\";\nimport validator from 'validator';\n\ninterface Account {\n    name: string,\n    email: string,\n    phone: string,\n    password: string\n}\n\nconst validationRule: ValidationRule\u003cAccount\u003e = {\n    name: [required()],\n    // Combine the built-in validator and the 'validator' package\n    email: [\n        required(),\n        propertyValidator((value, object) =\u003e {\n            return validator.isEmail(value) // the 'validator' package\n        }, \"Not a valid email.\"),\n    ],\n    phone: [\n        required(),\n        propertyValidator((value, object) =\u003e {\n            return validator.isMobilePhone(value, \"en-AU\") // the 'validator' package\n        }, \"Should be an AU mobile phone number format\"),\n    ],\n    password: [\n        required(),\n        propertyValidator((value, object) =\u003e {\n            // the 'validator' package\n            return validator.isStrongPassword(value, {\n                minLength: 8,\n                minUppercase: 2\n            })\n        }, \"Password should be 8 chars minimum, and has to contain at least 2 upper case.\"),\n    ],\n}\n\nconst account: Account = {\n    name: \"John\",\n    email: \"valid@@email.com\",\n    phone: \"123123123\",\n    password: \"strongpassword\"\n}\n\nconst validationResult = objectValidator.validate(account, validationRule)\n\n// validationResult = {\n//     message: \"One or more validation errors occurred.\",\n//     isValid: false,\n//     errors: {\n//         email: [\"Not a valid email.\"],\n//         phone: [\"Should be an AU mobile phone number format\"],\n//         password: [\"Password should be 8 chars minimum, and has to contain at least 2 upper case.\"]\n//     }\n// }\n```\n\n## Available Built-in Property Validators\n```typescript\nexport {\n    alphabetOnly,\n    arrayMaxLen,\n    arrayMinLen,\n    elementOf,\n    emailAddress,\n    equalToPropertyValue,\n    maxNumber,\n    minNumber,\n    maxSumOf,\n    minSumOf,\n    propertyValidator,\n    regularExpression,\n    required,\n    stringMaxLen,\n    stringMinLen,\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsupendi%2Fts-validity","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsupendi%2Fts-validity","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsupendi%2Fts-validity/lists"}