# tatabot

> Simple yet powerful json validator

Latest version **1.0.3** (published 2022-08-27) · ISC license · 0 weekly downloads

## Install

```sh
npm install tatabot
pnpm add tatabot
yarn add tatabot
bun add tatabot
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.0.3 |
| Published | 2022-08-27 |
| First published | 2020-09-06 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 1 |
| Unpacked size | 28.8 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 3 |
| Author | Burawi Ben Ammar From Tildah |
| Maintainers | burawi |
| Keywords | json, schema, validation, immutability, modular |

## Links

- npm: https://www.npmjs.com/package/tatabot
- Repository: https://github.com/burawi/tatabot
- Homepage: https://github.com/burawi/tatabot#readme
- Issues: https://github.com/burawi/tatabot/issues
- npm.io page: https://npm.io/package/tatabot

## Dependencies (1)

- [dayjs](https://npm.io/package/dayjs.md) ^1.8.35

## Alternatives

- [@mapbox/jsonlint-lines-primitives](https://npm.io/package/@mapbox/jsonlint-lines-primitives.md) — 5.3M weekly downloads
- [reftools](https://npm.io/package/reftools.md) — 3.5M weekly downloads
- [@hey-api/openapi-ts](https://npm.io/package/@hey-api/openapi-ts.md) — 3.5M weekly downloads
- [@mapbox/geojson-rewind](https://npm.io/package/@mapbox/geojson-rewind.md) — 2.4M weekly downloads
- [turbo-stream](https://npm.io/package/turbo-stream.md) — 1.7M weekly downloads

## Recent versions

- 1.0.3 (latest) — 2022-08-27
- 1.0.2 — 2020-09-07
- 1.0.1 — 2020-09-07
- 1.0.0 — 2020-09-06

## README

# Tatabot
Tatabot, (from Arabic `تثبت` which means `Validation` or `Checking` ),
is a `JSON` schema validator written with ***Immutability*** and ***Modularity***
in mind. And which **does not follow `json-schema.org` standard rules**, because 
we believe that schema syntax can be much simpler than that standard. And that's what we
made in `Tatabot`.
## Example
```javascript
const tatabot = require("tatabot");

const schema = {
  "*name": "string",
  email: "email",
  age: { type: "integer", min: 13 },
  role: { type: "enum", values: ["admin", "follower"] }
}

const user1 = { name: "Bot", email: "tatabot@mm.co", age: "31", role: "admin" };
const user2 = { email: "tatabot", age: 10, role: "guest" }

const validation1 = tatabot.validate(user1, schema);
// validation1: { 
//   isValid: true,
//   errors: [],
//   coersion: { name: "Bot", email: "tatabot@mm.co", age: 31, role: "admin" }
// }

const validation2 = tatabot.validate(user2, schema);
// validation2: { 
//   isValid: false,
//   errors: [ "name is required", "email is not valid email", "age should be greater than 13" ],
//   coersion: { email: "tatabot", age: 10 }
// }
```
## Immutability
As you can see, `Tatabot` never changes the original object you passed to validation.
Instead it returns a coerced object.

This, makes your code much more predictable, thus less buggy.

## Modularity
The modularity of `Tatabot` makes customization possible, so you can add your own custom
types and their validation.

## Installation
```
npm i --save tatabot
```
## Core Concept
The main function of `Tatabot` is `validate`. It takes 3 arguments and returns 3 values.

It takes the object to be validated, the schema, and some additional validation options.
And it returns a `boolean` that set to `true` if the object is valid, a flat array containing all validation errors and an object with coerced values.

See [the example above](#example)

In addition to object and schema `validate` function takes a third argument, containing
validation settings:
* `keepAdditional`: true|false, if set to `true`, additional properties in object that are 
    not mentioned in schema, will not be removed.
* `noRequired`: true|false, if set to `true`, `required` type will not be handled, this is
    useful when you are validating an object intended for update purpose and which does not
    need to include all properties.

## Setting types
Each property must have at least one type, this type (or those types), can be set in
different ways. 
* Direct string
    The shortest form is this one. Just put the type as string value. Eg:
    ```javascript
    {
      age: "integer"
    }
    ```
* Direct array
    Thanks to its modularity, `Tatabot` allows property to have multiple types.
    In order to set multiple types you must put those types in array. The most common case
    is `required` type. (Yes required is considered as a type in `Tatabot`).
    ```javascript
    {
      age: ["required", "integer"]
    }
    ```
* type property
    The ways of doing shown above are very convenient when you just want to set types, but
    in many cases, you'll find yourself wanting to set some other options to the prop.
    In those cases, you have to set types in the long format, using `type` property. Eg:
    ```javascript
    {
      age: { type: "integer", min: 10 }
    }
    ```
    And of course, you can also set multiple types in array. Eg:
    ```javascript
    {
      age: { type: ["required","integer"], min: 10 }
    }
    ```
## Setting required
As we saw earlier, `required` is a type. So if you want a property to be required, just
give it the `required` type. Eg:
```javascript
{
  name: ["required","string"] 
}
```
### InKey required
As an alternative, you can add `*` in the begining of the property name, to set it
as required. Eg:
```javascript
{
  "*name": "string" 
}
```
## Types
This is the list of predefined types in `Tatabot` and their options.
### `string`
**options:**
* minLength: mininmum length of string
* maxLength: maximum length of string

Eg:
```javascript
{
  name: {type: "string", minLength: 3, maxLength: 6}
}
```
### `uppercase`
This takes the exact same options as `string` type. The only difference is that this type
coerces the value to upper case.
### `lowercase`
Same `uppercase` for lower case.
### `email`
Checks if value is a valid email.
### `url`
Checks if value is a valid url.
### `integer`
Checks if `parseInt` of value is not NaN.

**options:**
* min: mininmum value
* max: maximum value
* blockFloat: true|false, wether to block floats or to parse them to int. Default false.
### `float`
Checks if `parseFloat` of value is not NaN.

**options:**
* min: mininmum value
* max: maximum value
### `enum`
Checks if value is listed among `values` option.

**options:**
* values: list of allowed values

Eg:
```javascript
{
  role: {type: "enum", values: ["admin", "follower"]}
}
```

### `date`
Check if value is a valid date. and coerces it to date object.

`Tatabot` uses [`dayjs`](https://day.js.org/) for date validation and parsing.

**options**
* format: the format of given date. see [`dayjs Doc`](https://day.js.org/docs/en/parse/string-format)
* before: a function that should return a date (or `dayjs` instance). to check wether or not the given date is before it.
* after: a function similar to `before`, but for after checking.

Eg:
```javascript
const schema = { createdAt: {
  type: "date",
  format: "DD-MM-YYYY",
  after: () => dayjs("20-20-2020", "DD-MM-YYYY")
}};
const item = { createdAt: "20-06-2018" }
const {isValid, coersion, errors} = tatabot.validate(item, schema);
// isValid: false 
// errors: ["createdAt should be after 20-20-2020"]
```

### `object`
Handles the value as plain object, according to its `schema` option.

**options:**
* schema: schema of object

Eg:
```javascript
{
  pet: {type: "object", schema: {
    name: "string",
    species: {type: "enum", values: ["dog", "cat"]}
  }}
}
```
### `array`
Checks the validity of the array.

**options:**
* minItems: minimum length of array
* maxItems: maximum length of array
* itemOptions: schema of item

Eg:
```javascript
{
  children: {type: "array", maxItems: 10, itemOptions: "string"}
}
// Here, you'll have an array of strings that accepts 10 items as maximum
```

Or:
```javascript
{
  children: {type: "array", maxItems: 10, itemOptions: {
    type: "object",
    schema: {name: "string", age: "integer"}
  }}
}
// Here, you'll have an array of objects that accepts 10 items as maximum
```
## Custom Types
As we said, the modularity of `Tatabot` allows you to set your own custom types.
Use `addType` function to add a custom type this takes 2 arguments, the *type name* and
the *processors*.

Processors is an object that should contain 2 functions, `coerce` and `validate`.

`coerce` returns the coerced value.

`validate` returns an array of errors. This array should be empty if the value is valid.

These two processors take the same 2 arguments:
* value: the value to be processed
* options: an object containing the following properties:
    * key: the property name that is being processed
    * propOptions: the property options in the schema (`minLength`, `max`...) 
    * settings: the settings passed to `validate` function

Let's say you want to add `password` type, that accepts only strings longer than 6 and 
coerces all chars to `*` (miming crypting).

You'll write that code:
```javascript
tatabot.addType("password", {
  coerce: (value, options) => value.split("").map(() => "*").join(""),
  validate: (value) => value.length < 6 ? ["password too short"] : [],
})
```

---
_Source: https://npm.io/package/tatabot · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
