Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/AmmarHalees/onsubmit
Typescript utilities for input validation, with emphasis on security
https://github.com/AmmarHalees/onsubmit
form-validation forms javascript schema typescript
Last synced: 3 months ago
JSON representation
Typescript utilities for input validation, with emphasis on security
- Host: GitHub
- URL: https://github.com/AmmarHalees/onsubmit
- Owner: AmmarHalees
- License: other
- Created: 2023-12-13T23:15:52.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2024-01-03T12:11:14.000Z (about 1 year ago)
- Last Synced: 2024-06-22T19:04:51.301Z (7 months ago)
- Topics: form-validation, forms, javascript, schema, typescript
- Language: TypeScript
- Homepage: https://on-submit-website.vercel.app/
- Size: 169 KB
- Stars: 19
- Watchers: 4
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
Awesome Lists containing this project
- awesome-jordan - onSubmit - Typescript utilities for input validation, with emphasis on security. (Frontend)
README
Quickstart |
API |
Examples |
Codesandbox |
Demo## Description
`onsubmit` is the simplest, least set-up needing way to validate an input or a form. On the client or on the server.
### Features
- Light-weight. (~1KB gzipped)
- Simple API.
- Zero dependencies.### Install
```sh
npm i onsubmit
```### Quickstart
```Typescript
import { validateField } from 'onsubmit';const firstNameRules = {
required: { criterion: true, message: 'First Name is required' },
minLength: { criterion: 3, message: 'Minimum length is 3' },
maxLength: { criterion: 10, message: 'Maximum length is 10' },
};// recieve an array of errors
const errors = validateField('Ammar', 'firstName', firstNameRules);```
### API
#### Methods
| Function | Description | Parameters | Returns |
|-----------------|-------------------------------------------------------|-------------------------------------------------------------------|--------------------|
| `validateField` | Validates a single form field against specified rules.| `value`: The string value of the field.
`name`: Name of the field.
`rules`: Object containing validation rules. | Array of `FieldError` objects, each containing the `name` of the field and the error `message`. |
| `validateForm` | Validates an entire form. | `values`: A key-value pair object of field names and values.
`rules`: A key-value object which maps field names to their rules . | Array of `FieldError` objects for the entire form. |#### Validation Rules
| Rule | Description | Expected Value |
|------------|----------------------------------------------|--------------------|
| `minLength` | Minimum length of the field's value. | Number (length) |
| `maxLength` | Maximum length of the field's value. | Number (length) |
| `pattern` | Regex pattern the field's value should match.| RegExp |
| `custom` | Custom validation logic. | Function |
| `required` | Whether the field is required. | Boolean |### Examples
#### Validate a single field
```Typescript
import { validateField, regex } from 'onsubmit';const emailRules = {
required: { criterion: true, message: 'Email is required' },
pattern: {
criterion: regex.email,
mesaage: 'Invalid email',
},
};const errors = validateField('[email protected]' , 'email', emailRules);
```
#### Custom validation logic
```Typescript
import { validateField } from 'onsubmit';
const rulesObject = {
custom: {
criterion: (value) => value === password,
message: 'Passwords do not match',
}
};const errors = validateField(passwordRepeat, 'passwordRepeat', rulesObject);
```#### Validate some data
```Typescript
import { validateForm } from 'onsubmit';const rulesObject = {
firstName: {
required: {
criterion: true,
message: "First name is required",
},
minLength: {
criterion: 5,
message: "First name must be at least 5 characters",
},
maxLength: {
criterion: 20,
message: "First name must be at most 20 characters",
},
pattern: {
criterion: /^[a-zA-Z0-9_ ]*$/,
message: "First name must be a valid name",
},
},
lastName: {
required: {
criterion: true,
message: "Last name is required",
},
minLength: {
criterion: 5,
message: "Last name must be at least 5 characters",
},
maxLength: {
criterion: 20,
message: "Last name must be at most 20 characters",
},
},
email: {
required: {
criterion: true,
message: "Email is required",
},
minLength: {
criterion: 5,
message: "Email must be at least 5 characters",
},pattern: {
criterion: /^\S+@\S+\.\S+$/,
message: "Email must be a valid email",
},
},
};const data = {
firstName: 'Ammar',
lastName: 'Halees',
email: '[email protected]',
};const errors = validateForm(data, rulesObject);
```#### Validate a form
```Typescript
import { validateForm } from 'onsubmit';const handleOnsubmit = (e) => {
e.preventDefault();const formData = new FormData(e.currentTarget);
const data = Object.fromEntries(formData);
const errors = validateForm(data, RulesMap);
};
```### Utils and patterns
#### utils
`onsubmit` provides a set of utility functions and patterns to help you build your forms.
| Function Name | Type Signature | Description |
|-------------------|----------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|
| `isDateObject` | `(value: unknown) => value is Date` | Checks if the given value is a valid `Date` object. |
| `isString` | `(value: unknown) => value is string` | Determines if the provided value is a string. This includes both string literals and `String` objects. |
| `isNumber` | `(value: unknown) => value is number` | Verifies if the value is a number and is finite. |
| `isNullOrUndefined` | `(value: unknown) => value is null \| undefined` | Checks if the value is either `null` or `undefined`. |
| `isObject` | `(value: unknown) => value is T` | Determines if a value is an object. This excludes `null`, arrays, and `Date` objects. |
| `isFile` | `(element: HTMLInputElement) => element is HTMLInputElement` | Checks if an HTML input element is of type `file`. |#### _patterns
1. `email`
2. `uri`
3. `alphanumeric`
4. `cuid`
5. `kebabCase`
6. `arabic`
## FAQ
### Which rule object has precedence?
The `required` rule has the highest precedence. The remaining rules are evaluated in the order they are specified in the `rulesObject`.
## Types
```Typescripttype Criterion = string | number | CustomFunction | boolean | RegExp;
interface Rule {
criterion: Criterion;
message: string;
}type FormDataShape = KeyValuePair | { [k: string]: FormDataEntryValue };
interface RulesObject {
required?: Rule;
minLength?: Rule;
maxLength?: Rule;
pattern?: Rule;
custom?: Rule;
}```
### TODO
- `onlySecure` opt-out rule.
- `minDate` rule.
- `maxDate` rule.
- `minTime` rule.rule
- `maxTime` rule
- `file` rule: { minSize, maxSize, type, name }
- `cardNumber` pattern.
- `cardCompany` utility.
- Benchmarking
- Allow for multiple patterns