-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #550 from shimataro/develop
version 3.1.0
- Loading branch information
Showing
101 changed files
with
3,539 additions
and
2,419 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ | |
[![Deno version][image-deno]][link-deno] | ||
[![License][image-license]][link-license] | ||
|
||
simple, easy-to-use, and declarative schema validator | ||
simple, easy-to-use, and declarative input validator | ||
|
||
supports [Node.js](https://nodejs.org/), [TypeScript](https://www.typescriptlang.org/), and [Deno](https://deno.land/) | ||
|
||
|
@@ -28,6 +28,7 @@ supports [Node.js](https://nodejs.org/), [TypeScript](https://www.typescriptlang | |
* [string](#string) | ||
* [numeric string](#numeric-string) | ||
* [email](#email) | ||
* [enumeration](#enumeration) | ||
* [array](#array) | ||
* [object](#object) | ||
* [Changelog](#changelog) | ||
|
@@ -196,10 +197,12 @@ $ node --experimental-modules foo.mjs | |
|
||
### [Deno](https://deno.land/) | ||
|
||
Deno has been supported as of v3.0.0-rc.4. | ||
Deno has been supported as of v3. | ||
|
||
```typescript | ||
import vs from "https://deno.land/x/value_schema/mod.ts"; | ||
import vs from "https://deno.land/x/value_schema/mod.ts"; // latest version | ||
import vs from "https://deno.land/x/value_schema@3/mod.ts"; // latest version of v3 | ||
import vs from "https://deno.land/x/[email protected]/mod.ts"; // v3.0.0 | ||
``` | ||
|
||
**CAUTION**: specify `value_schema` (underscore) NOT `value-schema` (hyphen) because [deno.land](https://deno.land/) module database does not support name with hyphen! | ||
|
@@ -467,25 +470,7 @@ const actual = vs.applySchemaObject(schemaObject, input); | |
assert.deepStrictEqual(actual, expected); | ||
``` | ||
|
||
In TypeScript, use "Generics" for type-safe. | ||
|
||
```typescript | ||
interface Parameters { | ||
foo: number | ||
bar: string | ||
} | ||
|
||
const schemaObject = { | ||
foo: vs.number(), | ||
bar: vs.string(), | ||
}; | ||
const input = { | ||
foo: "12345", | ||
bar: "abcde", | ||
}; | ||
|
||
const actual = vs.applySchemaObject<Parameters>(schemaObject, input); | ||
``` | ||
In TypeScript, type inference and auto-completion work perfectly! | ||
|
||
###### error handling 1 | ||
|
||
|
@@ -1840,6 +1825,198 @@ assert.throws( | |
{name: "ValueSchemaError", cause: vs.CAUSE.PATTERN}); | ||
``` | ||
|
||
### enumeration | ||
|
||
Return type of `applyTo()` can be limited to enum-like type; `enum` and union. | ||
**This is useful for TypeScript**. | ||
|
||
#### ambient declarations | ||
|
||
```typescript | ||
export function enumeration<E = never>(options: OptionsForEnumeration): EnumerationSchema<E>; | ||
|
||
type OptionsForEnumeration = { | ||
ifUndefined?: string | null; | ||
ifEmptyString?: string | null; | ||
ifNull?: string | null; | ||
|
||
only: E[]; // this is NOT an optional. | ||
} | ||
type ErrorHandler = (err: ValueSchemaError) => E | null | never; | ||
interface EnumerationSchema { | ||
applyTo(value: unknown, onError?: ErrorHandler): E | null | ||
} | ||
``` | ||
|
||
#### `applyTo(value[, onError])` | ||
|
||
Applies schema to `value`. | ||
|
||
If an error occurs, this method calls `onError` (if specified) or throw `ValueSchemaError` (otherwise). | ||
|
||
See example of `only`. | ||
|
||
#### options | ||
|
||
##### `only` | ||
|
||
Accepts only particular values. | ||
This is NOT an optional. | ||
|
||
```typescript | ||
// enum version | ||
enum NumberEnum | ||
{ | ||
zero, | ||
one, | ||
} | ||
enum StringEnum | ||
{ | ||
a = "a", | ||
b = "b", | ||
} | ||
|
||
// should be OK | ||
{ | ||
// pattern 1: enum that contains number elements | ||
const val: NumberEnum = vs.enumeration({only: [NumberEnum.zero, NumberEnum.one]}).applyTo(1); | ||
assert.strictEqual(val, 1); | ||
} | ||
{ | ||
// pattern 2: enum that contains only string elements | ||
const val: StringEnum = vs.enumeration({only: Object.values(StringEnum)}).applyTo("a"); | ||
assert.strictEqual(val, "a"); | ||
} | ||
|
||
// should cause error | ||
assert.throws( | ||
() => vs.enumeration({only: Object.values(StringEnum)}).applyTo("c"), | ||
{name: "ValueSchemaError", cause: vs.CAUSE.ONLY}); | ||
``` | ||
|
||
```typescript | ||
// union version | ||
type NumberUnion = 0 | 1; | ||
type StringUnion = "a" | "b"; | ||
|
||
// should be OK | ||
{ | ||
// you can use "as const" for union type | ||
const val: NumberUnion = vs.enumeration({only: [0, 1] as const}).applyTo(1); | ||
assert.strictEqual(val, 1); | ||
} | ||
{ | ||
// you can also use "<Type>" | ||
const val: StringEnum = vs.enumeration<StringUnion>({only: ["a", "b"]}).applyTo("a"); | ||
assert.strictEqual(val, "a"); | ||
} | ||
|
||
// should cause error | ||
assert.throws( | ||
() => vs.enumeratino({only: ["a", "b"] as const}).applyTo("c"), | ||
{name: "ValueSchemaError", cause: vs.CAUSE.ONLY}); | ||
``` | ||
|
||
CAUTION: In union version, `only` must be "array of literal union types", "const-asserted array", or "array literal with generics". | ||
|
||
```typescript | ||
type NumberUnion = 0 | 1; | ||
|
||
// OK | ||
{ | ||
// array of literal union types | ||
const val: NumberUnion = vs.enumeration({only: [0, 1] as NumberUnion[]}).applyTo(1); | ||
} | ||
{ | ||
// const-asserted array | ||
const val: NumberUnion = vs.enumeration({only: [0, 1] as const}).applyTo(1); | ||
} | ||
{ | ||
// array literal with generics | ||
const val: NumberUnion = vs.enumeration<NumberUnion>({only: [0, 1]}).applyTo(1); | ||
} | ||
|
||
// NG (compile error) | ||
{ | ||
// TS2322: Type 'number' is not assignable to type 'NumberUnion'. | ||
const val: NumberUnion = vs.enumeration({only: [0, 1]}).applyTo(1); // number | ||
} | ||
{ | ||
const only = [0, 1]; // number[] | ||
const val: NumberUnion = vs.enumeration({only: only}).applyTo(1); | ||
} | ||
{ | ||
const only = [0, 1]; // number[] | ||
const val: NumberUnion = vs.enumeration<NumberUnion>({only: only}).applyTo(1); | ||
} | ||
``` | ||
|
||
##### `ifUndefined` | ||
|
||
Specifies return value when input value is `undefined`. | ||
|
||
```typescript | ||
enum StringEnum | ||
{ | ||
a = "a", | ||
b = "b", | ||
} | ||
|
||
// should be adjusted | ||
assert.strictEqual( | ||
vs.enumeration({ifUndefined: StringEnum.a, only: Object.values(StringEnum)}).applyTo(undefined), | ||
"a"); | ||
|
||
// should cause error | ||
assert.throws( | ||
() => vs.enumeration({only: Object.values(StringEnum)}).applyTo(undefined), | ||
{name: "ValueSchemaError", cause: vs.CAUSE.UNDEFINED}); | ||
``` | ||
|
||
##### `ifNull` | ||
|
||
Specifies return value when input value is `null`. | ||
|
||
```typescript | ||
enum StringEnum | ||
{ | ||
a = "a", | ||
b = "b", | ||
} | ||
|
||
// should be adjusted | ||
assert.strictEqual( | ||
vs.enumeration({ifNull: StringEnum.a, only: Object.values(StringEnum)}).applyTo(null), | ||
"a"); | ||
|
||
// should cause error | ||
assert.throws( | ||
() => vs.enumeration({only: Object.values(StringEnum)}).applyTo(null), | ||
{name: "ValueSchemaError", cause: vs.CAUSE.NULL}); | ||
``` | ||
|
||
##### `ifEmptyString` | ||
|
||
Specifies return value when input value is `""`. | ||
|
||
```typescript | ||
enum StringEnum | ||
{ | ||
a = "a", | ||
b = "b", | ||
} | ||
|
||
// should be adjusted | ||
assert.strictEqual( | ||
vs.enumeration({ifEmptyString: StringEnum.a, only: Object.values(StringEnum)}).applyTo(""), | ||
"a"); | ||
|
||
// should cause error | ||
assert.throws( | ||
() => vs.enumeration({only: Object.values(StringEnum)}).applyTo(""), | ||
{name: "ValueSchemaError", cause: vs.CAUSE.EMPTY_STRING}); | ||
``` | ||
|
||
### array | ||
|
||
#### ambient declarations | ||
|
Oops, something went wrong.