Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

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

Awesome Lists containing this project

README

        



onsubmit library logo

# onSubmit


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

```Typescript

type 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