Skip to content

Commit

Permalink
feat: Refinements (#48)
Browse files Browse the repository at this point in the history
* wip

* Tests

* Getting close

* Tests pass

* Implementation almost ready

* v0.6.1-0

* All migrated

* Tests

* v0.6.1-1

* Update stringify

* v0.6.1-2

* Add sourcemaps

* Cleanup

* Docs wip

* feat(refinements): Add nextValid and nextNotValid

BREAKING CHANGE: `next` was renamed to `nextValid`.

* chore: Update deps

* docs: Fix link

* docs: Update readme with new benchmarks
  • Loading branch information
typeofweb authored Mar 22, 2021
1 parent 17a8165 commit 7b2d7e4
Show file tree
Hide file tree
Showing 53 changed files with 1,371 additions and 1,064 deletions.
32 changes: 17 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
`@typeofweb/schema` is a lightweight and extensible library for data validation with full TypeScript support!

<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->

[![All Contributors](https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square)](#contributors-)

<!-- ALL-CONTRIBUTORS-BADGE:END -->

[![codecov](https://codecov.io/gh/typeofweb/schema/branch/main/graph/badge.svg?token=6DNCIHEEUO)](https://codecov.io/gh/typeofweb/schema)
Expand Down Expand Up @@ -51,7 +53,7 @@ const personSchema = object({
name: string(),
age: number(),
email: optional(string()),
});
})();

const mark = {
name: 'Mark',
Expand All @@ -71,24 +73,24 @@ Early benchmarks show some really promising performance of `@typeofweb/schema` w
```
Platform info:
==============
Darwin 20.2.0 x64
Node.JS: 14.15.2
V8: 8.4.371.19-node.17
Darwin 20.3.0 x64
Node.JS: 14.16.0
V8: 8.4.371.19-node.18
Intel(R) Core(TM) i7-6920HQ CPU @ 2.90GHz × 8
```

| library | relative speed | operations per second | avg. operation time |
| --------------------- | -------------: | --------------------: | ------------------: |
| **@typeofweb/schema** | ref | **(2,812,709 rps)** | **(avg: 0.355μs)** |
| [email protected] | -27.82% | (2,030,076 rps) | (avg: 0.492μs) |
| [email protected] | -79.15% | (586,537 rps) | (avg: 1μs) |
| [email protected] | -83.22% | (471,847 rps) | (avg: 2μs) |
| [email protected] | -91.62% | (235,741 rps) | (avg: 4μs) |
| [email protected] | -94.08% | (166,599 rps) | (avg: 6μs) |
| [email protected] | -95.52% | (125,992 rps) | (avg: 7μs) |
| [email protected] | -97.17% | (79,536 rps) | (avg: 12μs) |
| [email protected] | -97.66% | (65,748 rps) | (avg: 15μs) |
| [email protected] | -99.17% | (23,308 rps) | (avg: 42μs) |
| [email protected] | -99.36% | (18,126 rps) | (avg: 55μs) |
| **@typeofweb/schema** | **ref** | **(1,934,098 rps)** | **(avg: 0.517μs)** |
| [email protected] | -7.21% | (1,794,594 rps) | (avg: 0.557μs) |
| [email protected] | -69.8% | (584,151 rps) | (avg: 1μs) |
| [email protected] | -76.16% | (461,088 rps) | (avg: 2μs) |
| [email protected] | -89.02% | (212,408 rps) | (avg: 4μs) |
| [email protected] | -92.2% | (150,791 rps) | (avg: 6μs) |
| [email protected] | -93.25% | (130,541 rps) | (avg: 7μs) |
| [email protected] | -96.99% | (58,197 rps) | (avg: 17μs) |
| [email protected] | -97.09% | (56,243 rps) | (avg: 17μs) |
| [email protected] | -98.99% | (19,492 rps) | (avg: 51μs) |
| [email protected] | -99.03% | (18,827 rps) | (avg: 53μs) |

### 👉 [schema.typeofweb.com](https://schema.typeofweb.com/) 👈
22 changes: 11 additions & 11 deletions __tests__/bench.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
'use strict';
exports.__esModule = true;
const src_1 = require('../dist/index.common.js');
const { object, minStringLength, string, number, validate } = require('../dist/index.common.js');
function run(i) {
const schema = src_1.object({
name: src_1.minLength(4)(src_1.string()),
email: src_1.string(),
firstName: src_1.nonEmpty(src_1.string()),
phone: src_1.nonEmpty(src_1.string()),
age: src_1.oneOf([i]),
});
const validator = src_1.validate(schema);
const schema = object({
name: minStringLength(4)(string()),
email: string(),
firstName: minStringLength(0)(string()),
phone: string(),
// age: number(),
})();
const validator = validate(schema);
const obj = {
name: 'John Doe',
email: '[email protected]',
firstName: 'John',
phone: '123-4567',
age: i,
// age: i,
};
return validator(obj);
}
for (let i = 0; i < 2000000; ++i) {
for (let i = 0; i < 4000000; ++i) {
run(i);
}
46 changes: 23 additions & 23 deletions __tests__/index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import {
nullable,
optional,
nil,
minLength,
nonEmpty,
minArrayLength,
minStringLength,
unknown,
} from '../src';

Expand All @@ -27,19 +27,19 @@ expectType<number>(validate(validator2)(''));
const validator3 = date();
expectType<Date>(validate(validator3)(''));

const validator4 = oneOf(['a', 'b']);
const validator4 = oneOf(['a', 'b'])();
expectType<'a' | 'b'>(validate(validator4)('a'));

const validator41 = validate(oneOf([number(), false]))('');
const validator41 = validate(oneOf([number(), false])())('');
expectType<number | false>(validator41);

const validator5 = nullable(string());
expectType<string | null>(validate(validator5)(''));

const validator6 = nullable(oneOf(['a']));
const validator6 = nullable(oneOf(['a'])());
expectType<'a' | null>(validate(validator6)(''));

const validator7 = optional(nullable(oneOf(['a'])));
const validator7 = optional(nullable(oneOf(['a'])()));
expectType<'a' | null | undefined>(validate(validator7)(''));

const validator8 = optional(nullable(boolean()));
Expand All @@ -49,33 +49,33 @@ const validator9 = nil(boolean());
expectType<boolean | null | undefined>(validate(validator9)(false));

// nested
const nested1 = object({});
const nested1 = object({})();
expectType<{}>(validate(nested1)({}));

const nested2 = object({
a: string(),
b: object({
c: number(),
}),
});
})(),
})();
expectType<{ readonly a: string; readonly b: { readonly c: number } }>(validate(nested2)({}));

const nested3 = array();
expectType<readonly never[]>(validate(nested3)([]));
expectType<readonly never[]>(validate(nested3())([]));

const nested4 = array(string());
expectType<readonly string[]>(validate(nested4)([]));
expectType<readonly string[]>(validate(nested4())([]));

const nested5 = array(string(), optional(number()));
expectType<readonly (string | number | undefined)[]>(validate(nested5)([]));
expectType<readonly (string | number | undefined)[]>(validate(nested5())([]));

const nested6 = optional(array(string(), number()));
const nested6 = optional(array(string(), number())());
expectType<readonly (string | number)[] | undefined>(validate(nested6)([]));

const nested7 = optional(
object({
arr: optional(array(string(), number())),
}),
arr: optional(array(string(), number())()),
})(),
);
expectType<
| {
Expand All @@ -94,14 +94,14 @@ expectType<string>(validate(parsed2)(new Date(0)));
const parsed3 = date();
expectType<Date>(validate(parsed3)('1970-01-01T00:00:00.000Z'));

// minLength and nonEmpty
const len1 = minLength(1)(array(string()));
// minArrayLength and minStringLength
const len1 = minArrayLength(1)(array(string())());
const resLen1 = validate(len1)([]);
expectType<readonly [string, ...(readonly string[])]>(resLen1);
expectType<string>(resLen1[0]);
expectType<string | undefined>(resLen1[1]);

const len10 = minLength(10)(array(string()));
const len10 = minArrayLength(10)(array(string())());
const resLen10 = validate(len10)([]);
expectType<
readonly [
Expand Down Expand Up @@ -131,20 +131,20 @@ expectType<string>(resLen10[9]);
expectType<string | undefined>(resLen10[10]);
expectType<string | undefined>(resLen10[11]);

const nonEmptyArr = validate(nonEmpty(array(string())))('');
const nonEmptyArr = validate(minArrayLength(1)(array(string())()))('');
expectType<readonly [string, ...(readonly string[])]>(nonEmptyArr);

const nonEmptyStr1 = validate(nonEmpty(string()))('');
const nonEmptyStr1 = validate(minStringLength(1)(string()))('');
expectType<string>(nonEmptyStr1);

const nonEmptyStr2 = validate(minLength(10)(string()))('');
const nonEmptyStr2 = validate(minStringLength(10)(string()))('');
expectType<string>(nonEmptyStr2);

const personSchema = object({
name: string(),
age: number(),
email: optional(string()),
});
})();

expectType<{
readonly name: string;
Expand All @@ -165,6 +165,6 @@ expectType<{ readonly a: number; readonly b: string; readonly c?: unknown }>(
a: number(),
b: string(),
c: unknown(),
}),
})(),
)('dsdas'),
);
Loading

1 comment on commit 7b2d7e4

@vercel
Copy link

@vercel vercel bot commented on 7b2d7e4 Mar 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.