From e4450c8417624b71d779cb4f41692538f9165e10 Mon Sep 17 00:00:00 2001 From: sowgro Date: Sat, 2 Sep 2023 19:12:47 -0400 Subject: first commit --- node_modules/@sapphire/shapeshift/README.md | 934 ++++++++++++++++++++++++++++ 1 file changed, 934 insertions(+) create mode 100644 node_modules/@sapphire/shapeshift/README.md (limited to 'node_modules/@sapphire/shapeshift/README.md') diff --git a/node_modules/@sapphire/shapeshift/README.md b/node_modules/@sapphire/shapeshift/README.md new file mode 100644 index 0000000..c9f113f --- /dev/null +++ b/node_modules/@sapphire/shapeshift/README.md @@ -0,0 +1,934 @@ +
+ +![Sapphire Logo](https://raw.githubusercontent.com/sapphiredev/assets/main/banners/SapphireCommunity.png) + +# @sapphire/shapeshift + +**Shapeshift** + +Blazing fast input validation and transformation ⚡ + +[![GitHub](https://img.shields.io/github/license/sapphiredev/shapeshift)](https://github.com/sapphiredev/shapeshift/blob/main/LICENSE.md) +[![codecov](https://codecov.io/gh/sapphiredev/shapeshift/branch/main/graph/badge.svg?token=RF4mMKx6lL)](https://codecov.io/gh/sapphiredev/shapeshift) +[![npm](https://img.shields.io/npm/v/@sapphire/shapeshift?color=crimson&logo=npm&style=flat-square)](https://www.npmjs.com/package/@sapphire/shapeshift) + +
+ +## Table of Contents + +- [@sapphire/shapeshift](#sapphireshapeshift) + - [Table of Contents](#table-of-contents) + - [Description](#description) + - [Features](#features) + - [Usage](#usage) + - [Basic usage](#basic-usage) + - [Defining validations](#defining-validations) + - [Primitives](#primitives) + - [Literals](#literals) + - [Strings](#strings) + - [Numbers](#numbers) + - [BigInts](#bigints) + - [Booleans](#booleans) + - [Arrays](#arrays) + - [Tuples](#tuples) + - [Unions](#unions) + - [Enums](#enums) + - [Maps](#maps) + - [Sets](#sets) + - [Instances](#instances) + - [Records](#records) + - [Functions // TODO](#functions--todo) + - [TypedArray](#typedarray) + - [Defining schemas (objects)](#defining-schemas-objects) + - [Utility types for TypeScript](#utility-types-for-typescript) + - [Extracting an interface from a schema](#extracting-an-interface-from-a-schema) + - [Defining the structure of a schema through an interface](#defining-the-structure-of-a-schema-through-an-interface) + - [`.extend`:](#extend) + - [`.pick` / `.omit`:](#pick--omit) + - [`.partial`](#partial) + - [`.required`](#required) + - [Handling unrecognized keys](#handling-unrecognized-keys) + - [`.strict`](#strict) + - [`.ignore`](#ignore) + - [`.passthrough`](#passthrough) + - [BaseValidator: methods and properties](#basevalidator-methods-and-properties) + - [`.run`](#rundata-unknown-resultt-error-given-a-validation-you-can-call-this-method-to-check-whether-or-not-the) + - [`.parse`](#parsedata-unknown-t-given-a-validations-you-can-call-this-method-to-check-whether-or-not-the-input-is-valid) + - [`.transform`](#transformrvalue-t--r-nopvalidatorr-adds-a-constraint-that-modifies-the-input) + - [`.reshape`](#reshapervalue-t--resultr-error--iconstraint-nopvalidatorr-adds-a-constraint-able-to-both-validate) + - [`.default`](#defaultvalue-t----t-transform-undefined-into-the-given-value-or-the-callbacks-returned-value) + - [`.optional`](#optional-a-convenience-method-that-returns-a-union-of-the-type-with-sundefined) + - [`.nullable`](#nullable-a-convenience-method-that-returns-a-union-of-the-type-with-snullable) + - [`.nullish`](#nullish-a-convenience-method-that-returns-a-union-of-the-type-with-snullish) + - [`.array`](#array-a-convenience-method-that-returns-an-arrayvalidator-with-the-type) + - [`.or`](#or-a-convenience-method-that-returns-an-unionvalidator-with-the-type-this-method-is-also-overridden-in) + - [`.when`](#when-adjust-the-schema-based-on-a-sibling-or-sinbling-children-fields) + - [Available options for providing `is`](#available-options-for-providing-is) + - [Resolving of the `key` (first) parameter](#resolving-of-the-key-first-parameter) + - [Examples](#examples) + - [Enabling and disabling validation](#enabling-and-disabling-validation) + - [Buy us some doughnuts](#buy-us-some-doughnuts) + - [Contributors](#contributors) + +## Description + +[Back to top][toc] + +A very fast and lightweight input validation and transformation library for JavaScript. + +> **Note**: Shapeshift requires Node.js v14.0.0 or higher to work. + +## Features + +[Back to top][toc] + +- TypeScript friendly +- Offers CJS, ESM and UMD builds +- API similar to [`zod`] +- Faster than ⚡ + +## Usage + +[Back to top][toc] + +**_For complete usages, please dive into our [documentation]_** + +### Basic usage + +[Back to top][toc] + +Creating a simple string validation + +```typescript +import { s } from '@sapphire/shapeshift'; + +const myStringValidation = s.string; + +// Parse +myStringValidation.parse('sapphire'); // => returns 'sapphire' +myStringValidation.parse(12); // throws ValidationError +``` + +Creating an object schema + +```typescript +import { s } from '@sapphire/shapeshift'; + +const user = s.object({ + username: s.string +}); + +user.parse({ username: 'Sapphire' }); +``` + +### Defining validations + +[Back to top][toc] + +#### Primitives + +[Back to top][toc] + +```typescript +import { s } from '@sapphire/shapeshift'; + +// Primitives +s.string; +s.number; +s.bigint; +s.boolean; +s.date; + +// Empty Types +s.undefined; +s.null; +s.nullish; // Accepts undefined | null + +// Catch-all Types +s.any; +s.unknown; + +// Never Type +s.never; +``` + +#### Literals + +[Back to top][toc] + +```typescript +s.literal('sapphire'); +s.literal(12); +s.literal(420n); +s.literal(true); +s.literal(new Date(1639278160000)); // s.date.equal(1639278160000); +``` + +#### Strings + +[Back to top][toc] + +Shapeshift includes a handful of string-specific validations: + +```typescript +s.string.lengthLessThan(5); +s.string.lengthLessThanOrEqual(5); +s.string.lengthGreaterThan(5); +s.string.lengthGreaterThanOrEqual(5); +s.string.lengthEqual(5); +s.string.lengthNotEqual(5); +s.string.email; +s.string.url(); +s.string.uuid(); +s.string.regex(regex); +s.string.ip(); +s.string.ipv4; +s.string.ipv6; +s.string.phone(); +``` + +#### Numbers + +[Back to top][toc] + +Shapeshift includes a handful of number-specific validations: + +```typescript +s.number.greaterThan(5); // > 5 +s.number.greaterThanOrEqual(5); // >= 5 +s.number.lessThan(5); // < 5 +s.number.lessThanOrEqual(5); // <= 5 +s.number.equal(5); // === 5 +s.number.notEqual(5); // !== 5 + +s.number.equal(NaN); // special case: Number.isNaN +s.number.notEqual(NaN); // special case: !Number.isNaN + +s.number.int; // value must be an integer +s.number.safeInt; // value must be a safe integer +s.number.finite; // value must be finite + +s.number.positive; // .greaterThanOrEqual(0) +s.number.negative; // .lessThan(0) + +s.number.divisibleBy(5); // Divisible by 5 +``` + +And transformations: + +```typescript +s.number.abs; // Transforms the number to an absolute number +s.number.sign; // Gets the number's sign + +s.number.trunc; // Transforms the number to the result of `Math.trunc` +s.number.floor; // Transforms the number to the result of `Math.floor` +s.number.fround; // Transforms the number to the result of `Math.fround` +s.number.round; // Transforms the number to the result of `Math.round` +s.number.ceil; // Transforms the number to the result of `Math.ceil` +``` + +#### BigInts + +[Back to top][toc] + +Shapeshift includes a handful of number-specific validations: + +```typescript +s.bigint.greaterThan(5n); // > 5n +s.bigint.greaterThanOrEqual(5n); // >= 5n +s.bigint.lessThan(5n); // < 5n +s.bigint.lessThanOrEqual(5n); // <= 5n +s.bigint.equal(5n); // === 5n +s.bigint.notEqual(5n); // !== 5n + +s.bigint.positive; // .greaterThanOrEqual(0n) +s.bigint.negative; // .lessThan(0n) + +s.bigint.divisibleBy(5n); // Divisible by 5n +``` + +And transformations: + +```typescript +s.bigint.abs; // Transforms the bigint to an absolute bigint + +s.bigint.intN(5); // Clamps to a bigint to a signed bigint with 5 digits, see BigInt.asIntN +s.bigint.uintN(5); // Clamps to a bigint to an unsigned bigint with 5 digits, see BigInt.asUintN +``` + +#### Booleans + +[Back to top][toc] + +Shapeshift includes a few boolean-specific validations: + +```typescript +s.boolean.true; // value must be true +s.boolean.false; // value must be false + +s.boolean.equal(true); // s.boolean.true +s.boolean.equal(false); // s.boolean.false + +s.boolean.notEqual(true); // s.boolean.false +s.boolean.notEqual(false); // s.boolean.true +``` + +#### Arrays + +[Back to top][toc] + +```typescript +const stringArray = s.array(s.string); +const stringArray = s.string.array; +``` + +Shapeshift includes a handful of array-specific validations: + +```typescript +s.string.array.lengthLessThan(5); // Must have less than 5 elements +s.string.array.lengthLessThanOrEqual(5); // Must have 5 or less elements +s.string.array.lengthGreaterThan(5); // Must have more than 5 elements +s.string.array.lengthGreaterThanOrEqual(5); // Must have 5 or more elements +s.string.array.lengthEqual(5); // Must have exactly 5 elements +s.string.array.lengthNotEqual(5); // Must not have exactly 5 elements +s.string.array.lengthRange(0, 4); // Must have at least 0 elements and less than 4 elements (in math, that is [0, 4)) +s.string.array.lengthRangeInclusive(0, 4); // Must have at least 0 elements and at most 4 elements (in math, that is [0, 4]) +s.string.array.lengthRangeExclusive(0, 4); // Must have more than 0 element and less than 4 elements (in math, that is (0, 4)) +s.string.array.unique; // All elements must be unique. Deep equality is used to check for uniqueness. +``` + +> **Note**: All `.length` methods define tuple types with the given amount of elements. For example, +> `s.string.array.lengthGreaterThanOrEqual(2)`'s inferred type is `[string, string, ...string[]]` + +#### Tuples + +[Back to top][toc] + +Unlike arrays, tuples have a fixed number of elements and each element can have a different type: + +```typescript +const dish = s.tuple([ + s.string, // Dish's name + s.number.int, // Table's number + s.date // Date the dish was ready for delivery +]); + +dish.parse(['Iberian ham', 10, new Date()]); +``` + +#### Unions + +[Back to top][toc] + +Shapeshift includes a built-in method for composing OR types: + +```typescript +const stringOrNumber = s.union(s.string, s.number); + +stringOrNumber.parse('Sapphire'); // => 'Sapphire' +stringOrNumber.parse(42); // => 42 +stringOrNumber.parse({}); // => throws CombinedError +``` + +#### Enums + +[Back to top][toc] + +Enums are a convenience method that aliases `s.union(s.literal(a), s.literal(b), ...)`: + +```typescript +s.enum('Red', 'Green', 'Blue'); +// s.union(s.literal('Red'), s.literal('Green'), s.literal('Blue')); +``` + +#### Maps + +[Back to top][toc] + +```typescript +const map = s.map(s.string, s.number); +// Map +``` + +#### Sets + +[Back to top][toc] + +```typescript +const set = s.set(s.number); +// Set +``` + +#### Instances + +[Back to top][toc] + +You can use `s.instance(Class)` to check that the input is an instance of a class. This is useful to validate inputs +against classes: + +```typescript +class User { + public constructor(public name: string) {} +} + +const userInstanceValidation = s.instance(User); +userInstanceValidation.parse(new User('Sapphire')); // => User { name: 'Sapphire' } +userInstanceValidation.parse('oops'); // => throws ValidatorError +``` + +#### Records + +[Back to top][toc] + +Record validations are similar to objects, but validate `Record` types. Keep in mind this does not check for +the keys, and cannot support validation for specific ones: + +```typescript +const tags = s.record(s.string); + +tags.parse({ foo: 'bar', hello: 'world' }); // => { foo: 'bar', hello: 'world' } +tags.parse({ foo: 42 }); // => throws CombinedError +tags.parse('Hello'); // => throws ValidateError +``` + +--- + +_**Function validation is not yet implemented and will be made available starting v2.1.0**_ + +#### Functions // TODO + +[Back to top][toc] + +You can define function validations. This checks for whether or not an input is a function: + +```typescript +s.function; // () => unknown +``` + +You can define arguments by passing an array as the first argument, as well as the return type as the second: + +```typescript +s.function([s.string]); // (arg0: string) => unknown +s.function([s.string, s.number], s.string); // (arg0: string, arg1: number) => string +``` + +> **Note**: Shapeshift will transform the given function into one with validation on arguments and output. You can +> access the `.raw` property of the function to get the unchecked function. + +--- + +#### TypedArray + +[Back to top][toc] + +```ts +const typedArray = s.typedArray(); +const int16Array = s.int16Array; +const uint16Array = s.uint16Array; +const uint8ClampedArray = s.uint8ClampedArray; +const int16Array = s.int16Array; +const uint16Array = s.uint16Array; +const int32Array = s.int32Array; +const uint32Array = s.uint32Array; +const float32Array = s.float32Array; +const float64Array = s.float64Array; +const bigInt64Array = s.bigInt64Array; +const bigUint64Array = s.bigUint64Array; +``` + +Shapeshift includes a handful of validations specific to typed arrays. + +```typescript +s.typedArray().lengthLessThan(5); // Length must be less than 5 +s.typedArray().lengthLessThanOrEqual(5); // Length must be 5 or less +s.typedArray().lengthGreaterThan(5); // Length must be more than 5 +s.typedArray().lengthGreaterThanOrEqual(5); // Length must be 5 or more +s.typedArray().lengthEqual(5); // Length must be exactly 5 +s.typedArray().lengthNotEqual(5); // Length must not be 5 +s.typedArray().lengthRange(0, 4); // Length L must satisfy 0 <= L < 4 +s.typedArray().lengthRangeInclusive(0, 4); // Length L must satisfy 0 <= L <= 4 +s.typedArray().lengthRangeExclusive(0, 4); // Length L must satisfy 0 < L < 4 +``` + +Note that all of these methods have analogous methods for working with the typed array's byte length, +`s.typedArray().byteLengthX()` - for instance, `s.typedArray().byteLengthLessThan(5)` is the same as +`s.typedArray().lengthLessThan(5)` but for the array's byte length. + +--- + +### Defining schemas (objects) + +[Back to top][toc] + +```typescript +// Properties are required by default: +const animal = s.object({ + name: s.string, + age: s.number +}); +``` + +#### Utility types for TypeScript + +[Back to top][toc] + +For object validation Shapeshift exports 2 utility types that can be used to extract interfaces from schemas and define +the structure of a schema as an interface beforehand respectively. + +##### Extracting an interface from a schema + +[Back to top][toc] + +You can use the `InferType` type to extract the interface from a schema, for example: + +```typescript +import { InferType, s } from '@sapphire/shapeshift'; + +const schema = s.object({ + foo: s.string, + bar: s.number, + baz: s.boolean, + qux: s.bigint, + quux: s.date +}); + +type Inferredtype = InferType; + +// Expected type: +type Inferredtype = { + foo: string; + bar: number; + baz: boolean; + qux: bigint; + quux: Date; +}; +``` + +##### Defining the structure of a schema through an interface + +[Back to top][toc] + +You can use the `SchemaOf` type to define the structure of a schema before defining the actual schema, for example: + +```typescript +import { s, SchemaOf } from '@sapphire/shapeshift'; + +interface IIngredient { + ingredientId: string | undefined; + name: string | undefined; +} + +interface IInstruction { + instructionId: string | undefined; + message: string | undefined; +} + +interface IRecipe { + recipeId: string | undefined; + title: string; + description: string; + instructions: IInstruction[]; + ingredients: IIngredient[]; +} + +type InstructionSchemaType = SchemaOf; +// Expected Type: ObjectValidator + +type IngredientSchemaType = SchemaOf; +// Expected Type: ObjectValidator + +type RecipeSchemaType = SchemaOf; +// Expected Type: ObjectValidator + +const instructionSchema: InstructionSchemaType = s.object({ + instructionId: s.string.optional, + message: s.string +}); + +const ingredientSchema: IngredientSchemaType = s.object({ + ingredientId: s.string.optional, + name: s.string +}); + +const recipeSchema: RecipeSchemaType = s.object({ + recipeId: s.string.optional, + title: s.string, + description: s.string, + instructions: s.array(instructionSchema), + ingredients: s.array(ingredientSchema) +}); +``` + +#### `.extend`: + +[Back to top][toc] + +You can add additional fields using either an object or an ObjectValidator, in this case, you will get a new object +validator with the merged properties: + +```typescript +const animal = s.object({ + name: s.string.optional, + age: s.number +}); + +const pet = animal.extend({ + owner: s.string.nullish +}); + +const pet = animal.extend( + s.object({ + owner: s.string.nullish + }) +); +``` + +> If both schemas share keys, an error will be thrown. Please use `.omit` on the first object if you desire this +> behaviour. + +#### `.pick` / `.omit`: + +[Back to top][toc] + +Inspired by TypeScript's built-in `Pick` and `Omit` utility types, all object schemas have the aforementioned methods +that return a modifier version: + +```typescript +const pkg = s.object({ + name: s.string, + description: s.string, + dependencies: s.string.array +}); + +const justTheName = pkg.pick(['name']); +// s.object({ name: s.string }); + +const noDependencies = pkg.omit(['dependencies']); +// s.object({ name: s.string, description: s.string }); +``` + +#### `.partial` + +[Back to top][toc] + +Inspired by TypeScript's built-in `Partial` utility type, all object schemas have the aforementioned method that makes +all properties optional: + +```typescript +const user = s.object({ + username: s.string, + password: s.string +}).partial; +``` + +Which is the same as doing: + +```typescript +const user = s.object({ + username: s.string.optional, + password: s.string.optional +}); +``` + +--- + +#### `.required` + +[Back to top][toc] + +Inspired by TypeScript's built-in `Required` utility type, all object schemas have the aforementioned method that makes +all properties required: + +```typescript +const user = s.object({ + username: s.string.optional, + password: s.string.optional +}).required; +``` + +Which is the same as doing: + +```typescript +const user = s.object({ + username: s.string, + password: s.string +}); +``` + +--- + +### Handling unrecognized keys + +[Back to top][toc] + +By default, Shapeshift will not include keys that are not defined by the schema during parsing: + +```typescript +const person = s.object({ + framework: s.string +}); + +person.parse({ + framework: 'Sapphire', + awesome: true +}); +// => { name: 'Sapphire' } +``` + +#### `.strict` + +[Back to top][toc] + +You can disallow unknown keys with `.strict`. If the input includes any unknown keys, an error will be thrown. + +```typescript +const person = s.object({ + framework: s.string +}).strict; + +person.parse({ + framework: 'Sapphire', + awesome: true +}); +// => throws ValidationError +``` + +#### `.ignore` + +[Back to top][toc] + +You can use the `.ignore` getter to reset an object schema to the default behaviour (ignoring unrecognized keys). + +#### `.passthrough` + +[Back to top][toc] + +You can use the `.passthrough` getter to make the validator add the unrecognized properties the shape does not have, +from the input. + +--- + +### BaseValidator: methods and properties + +[Back to top][toc] + +All validations in Shapeshift contain certain methods. + +- #### `.run(data: unknown): Result`: given a validation, you can call this method to check whether or not the + + input is valid. If it is, a `Result` with `success: true` and a deep-cloned value will be returned with the given + constraints and transformations. Otherwise, a `Result` with `success: false` and an error is returned. + +- #### `.parse(data: unknown): T`: given a validations, you can call this method to check whether or not the input is valid. + + If it is, a deep-cloned value will be returned with the given constraints and transformations. Otherwise, an error is + thrown. + +- #### `.transform((value: T) => R): NopValidator`: adds a constraint that modifies the input: + +```typescript +import { s } from '@sapphire/shapeshift'; + +const getLength = s.string.transform((value) => value.length); +getLength.parse('Hello There'); // => 11 +``` + +> :warning: `.transform`'s functions **must not throw**. If a validation error is desired to be thrown, `.reshape` +> instead. + +- #### `.reshape((value: T) => Result | IConstraint): NopValidator`: adds a constraint able to both validate + and modify the input: + +```typescript +import { s, Result } from '@sapphire/shapeshift'; + +const getLength = s.string.reshape((value) => Result.ok(value.length)); +getLength.parse('Hello There'); // => 11 +``` + +> :warning: `.reshape`'s functions **must not throw**. If a validation error is desired to be thrown, use +> `Result.err(error)` instead. + +- #### `.default(value: T | (() => T))`: transform `undefined` into the given value or the callback's returned value: + +```typescript +const name = s.string.default('Sapphire'); +name.parse('Hello'); // => 'Hello' +name.parse(undefined); // => 'Sapphire' +``` + +```typescript +const number = s.number.default(Math.random); +number.parse(12); // => 12 +number.parse(undefined); // => 0.989911985608602 +number.parse(undefined); // => 0.3224350185068794 +``` + +> :warning: The default values are not validated. + +- #### `.optional`: a convenience method that returns a union of the type with `s.undefined`. + +```typescript +s.string.optional; // s.union(s.string, s.undefined) +``` + +- #### `.nullable`: a convenience method that returns a union of the type with `s.nullable`. + +```typescript +s.string.nullable; // s.union(s.string, s.nullable) +``` + +- #### `.nullish`: a convenience method that returns a union of the type with `s.nullish`. + +```typescript +s.string.nullish; // s.union(s.string, s.nullish) +``` + +- #### `.array`: a convenience method that returns an ArrayValidator with the type. + +```typescript +s.string.array; // s.array(s.string) +``` + +- #### `.or`: a convenience method that returns an UnionValidator with the type. This method is also overridden in + UnionValidator to just append one more entry. + +```typescript +s.string.or(s.number); +// => s.union(s.string, s.number) + +s.object({ name: s.string }).or(s.string, s.number); +// => s.union(s.object({ name: s.string }), s.string, s.number) +``` + +- #### `.when`: Adjust the schema based on a sibling or sinbling children fields. + +For using when you provide an object literal where the key `is` is undefined, a value, or a matcher function; `then` +provides the schema when `is` resolves truthy, and `otherwise` provides the schema when `is` resolves falsey. + +##### Available options for providing `is` + +When `is` is not provided (`=== undefined`) it is strictly resolved as `Boolean(value)` wherein `value` is the current +value of the referenced sibling. Note that if multiple siblings are referenced then all the values of the array need to +resolve truthy for the `is` to resolve truthy. + +When `is` is a primitive literal it is strictly compared (`===`) to the current value. + +If you want to use a different form of equality you can provide a function like: `is: (value) => value === true`. + +##### Resolving of the `key` (first) parameter + +For resolving the `key` parameter to its respective value we use [lodash/get](https://lodash.com/docs#get). This means +that every way that Lodash supports resolving a key to its respective value is also supported by Shapeshift. This +includes: + +- Simply providing a string or number like `'name'` or `1`. +- Providing a string or number with a dot notation like `'name.first'` (representative of a nested object structure of + `{ 'name': { 'first': 'Sapphire' } }` => resolves to `Sapphire`). +- Providing a string or number with a bracket notation like `'name[0]'` (representative of an array structure of + `{ 'name': ['Sapphire', 'Framework'] }` => resolves to `Sapphire`). +- Providing a string or number with a dot and bracket notation like `'name[1].first'` (representative of a nested object + structure of `{ 'name': [{ 'first': 'Sapphire' }, { 'first': 'Framework' }] }` => resolves to `Framework`). + +##### Examples + +Let's start with a basic example: + +```typescript +const whenPredicate = s.object({ + booleanLike: s.boolean, + numberLike: s.number.when('booleanLike', { + then: (schema) => schema.greaterThanOrEqual(5), + otherwise: (schema) => schema.lessThanOrEqual(5) + }) +}); + +whenPredicate.parse({ booleanLike: true, numberLike: 6 }); +// => { booleanLike: true, numberLike: 6 } + +whenPredicate.parse({ booleanLike: true, numberLike: 4 }); +// => ExpectedConstraintError('s.number.greaterThanOrEqual', 'Invalid number value', 4, 'expected >= 5') + +whenPredicate.parse({ booleanLike: false, numberLike: 4 }); +// => { booleanLike: false, numberLike: 4 } +``` + +The provided key can also be an array of sibling children: + +```typescript +const whenPredicate = s.object({ + booleanLike: s.boolean, + stringLike: s.string, + numberLike: s.number.when(['booleanLike', 'stringLike'], { + is: ([booleanLikeValue, stringLikeValue]) => booleanLikeValue === true && stringLikeValue === 'foobar', + then: (schema) => schema.greaterThanOrEqual(5), + otherwise: (schema) => schema.lessThanOrEqual(5) + }) +}); + +whenPredicate.parse({ booleanLike: true, stringLike: 'foobar', numberLike: 6 }); +// => { booleanLike: true, numberLike: 6 } + +whenPredicate.parse({ booleanLike: true, stringLike: 'barfoo', numberLike: 4 }); +// => ExpectedConstraintError('s.number.greaterThanOrEqual', 'Invalid number value', 4, 'expected >= 5') + +whenPredicate.parse({ booleanLike: false, stringLike: 'foobar' numberLike: 4 }); +// => ExpectedConstraintError('s.number.greaterThanOrEqual', 'Invalid number value', 4, 'expected >= 5') +``` + +### Enabling and disabling validation + +[Back to top][toc] + +At times, you might want to have a consistent code base with validation, but would like to keep validation to the strict +necessities instead of the in-depth constraints available in shapeshift. By calling `setGlobalValidationEnabled` you can +disable validation at a global level, and by calling `setValidationEnabled` you can disable validation on a +per-validator level. + +> When setting the validation enabled status per-validator, you can also set it to `null` to use the global setting. + +```typescript +import { setGlobalValidationEnabled } from '@sapphire/shapeshift'; + +setGlobalValidationEnabled(false); +``` + +```typescript +import { s } from '@sapphire/shapeshift'; + +const predicate = s.string.lengthGreaterThan(5).setValidationEnabled(false); +``` + +## Buy us some doughnuts + +[Back to top][toc] + +Sapphire Community is and always will be open source, even if we don't get donations. That being said, we know there are +amazing people who may still want to donate just to show their appreciation. Thank you very much in advance! + +We accept donations through Open Collective, Ko-fi, Paypal, Patreon and GitHub Sponsorships. You can use the buttons +below to donate through your method of choice. + +| Donate With | Address | +| :-------------: | :-------------------------------------------------: | +| Open Collective | [Click Here](https://sapphirejs.dev/opencollective) | +| Ko-fi | [Click Here](https://sapphirejs.dev/kofi) | +| Patreon | [Click Here](https://sapphirejs.dev/patreon) | +| PayPal | [Click Here](https://sapphirejs.dev/paypal) | + +## Contributors + +[Back to top][toc] + +Please make sure to read the [Contributing Guide][contributing] before making a pull request. + +Thank you to all the people who already contributed to Sapphire! + + + + + +[contributing]: https://github.com/sapphiredev/.github/blob/main/.github/CONTRIBUTING.md +[`zod`]: https://github.com/colinhacks/zod +[documentation]: https://www.sapphirejs.dev/docs/Documentation/api-shapeshift/ +[toc]: #table-of-contents -- cgit v1.2.3