UNPKG

@cowwoc/requirements

Version:

A fluent API for enforcing design contracts with automatic message generation.

194 lines (146 loc) 7.73 kB
[![npm version](https://badge.fury.io/js/%40cowwoc%2Frequirements.svg)](https://badge.fury.io/js/%40cowwoc%2Frequirements) [![build-status](https://github.com/cowwoc/requirements.js/workflows/Build/badge.svg)](https://github.com/cowwoc/requirements.js/actions?query=workflow%3ABuild) # <img src="https://raw.githubusercontent.com/cowwoc/requirements.js/release-4.0.11/docs/checklist.svg?sanitize=true" width=64 height=64 alt="checklist"> Requirements API [![API](https://img.shields.io/badge/api_docs-5B45D5.svg)](https://cowwoc.github.io/requirements.js/4.0.11/) [![Changelog](https://img.shields.io/badge/changelog-A345D5.svg)](docs/Changelog.md) [![java](https://img.shields.io/badge/other%20languages-java-457FD5.svg)](../../../requirements.java) A [fluent API](https://en.m.wikipedia.org/docs/Fluent_interface) for enforcing [design contracts](https://en.wikipedia.org/docs/Design_by_contract) with [automatic message generation](docs/Features.md#automatic-message-generation): ✔️ Easy to use ✔️ Fast ✔️ Production-ready To get started, add this dependency: ```shell npm install --save @cowwoc/requirements@4.0.11 ``` or [pnpm](https://pnpm.io/): ```shell pnpm add @cowwoc/requirements@4.0.11 ``` ## Usage Example ```typescript import {requireThatString} from "@cowwoc/requirements"; class Cake { private bitesTaken = 0; private piecesLeft; public constructor(piecesLeft: number) { requireThat(piecesLeft, "piecesLeft").isPositive(); this.piecesLeft = piecesLeft; } public eat(): number { ++bitesTaken; assertThat(bitesTaken, "bitesTaken").isNotNegative().elseThrow(); piecesLeft -= ThreadLocalRandom.current().nextInt(5); assertThat(piecesLeft, "piecesLeft").isNotNegative().elseThrow(); return piecesLeft; } public getFailures(): String[] { return checkIf(bitesTaken, "bitesTaken").isNotNegative(). and(checkIf(piecesLeft, "piecesLeft").isGreaterThan(3)). elseGetMessages(); } } ``` If you violate a **precondition**: ```typescript const cake = new Cake(-1000); ``` You'll get: ``` RangeError: "piecesLeft" must be positive. actual: -1000 ``` If you violate a **class invariant**: ```typescript const cake = new Cake(1_000_000); while (true) cake.eat(); ``` You'll get: ``` lang.AssertionError: "bitesTaken" may not be negative. actual: -128 ``` If you violate a **postcondition**: ```typescript const cake = new Cake(100); while (true) cake.eat(); ``` You'll get: ``` AssertionError: "piecesLeft" may not be negative. actual: -4 ``` If you violate **multiple** conditions at once: ```typescript const cake = new Cake(1); cake.bitesTaken = -1; cake.piecesLeft = 2; const failures = []; for (const failure of cake.getFailures()) failures.add(failure); console.log(failures.join("\n\n")); ``` You'll get: ``` "bitesTaken" may not be negative. actual: -1 "piecesLeft" must be greater than 3. actual: 2 ``` ## Features This library offers the following features: * [Automatic message generation](docs/Features.md#automatic-message-generation) for validation failures * [Diffs provided whenever possible](docs/Features.md#diffs-provided-whenever-possible) to highlight the differences between expected and actual values * [Zero overhead when assertions are disabled](docs/Features.md#assertion-support) for better performance * [Multiple validation failures](docs/Features.md#multiple-validation-failures) that report all the errors at once * [Nested validations](docs/Features.md#nested-validations) that allow you to validate complex objects * [String diff](docs/Features.md#string-diff) that shows the differences between two strings ## Entry Points Designed for discovery using your favorite IDE's auto-complete feature. The main entry points are: * `requireThat(value, name)` for method preconditions. * [requireThat(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.requireThat.html) * [requireThatArray(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.requireThatArray.html) * [requireThatBoolean(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.requireThatBoolean.html) * [requireThatMap(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.requireThatMap.html) * [requireThatNumber(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.requireThatNumber.html) * [requireThatSet(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.requireThatSet.html) * [requireThatString(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.requireThatString.html) * `assertThat(value, name)` for [class invariants, method postconditions and private methods](docs/Features.md#assertion-support). * [assertThat(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.assertThat.html) * [assertThatArray(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.assertThatArray.html) * [assertThatBoolean(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.assertThatBoolean.html) * [assertThatMap(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.assertThatMap.html) * [assertThatNumber(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.assertThatNumber.html) * [assertThatSet(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.assertThatSet.html) * [assertThatString(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.assertThatString.html) * `checkIf(value, name)` for multiple failures and customized error handling. * [checkIf(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.checkIf.html) * [checkIfArray(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.checkIfArray.html) * [checkIfBoolean(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.checkIfBoolean.html) * [checkIfMap(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.checkIfMap.html) * [checkIfNumber(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.checkIfNumber.html) * [checkIfSet(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.checkIfSet.html) * [checkIfString(value, name)](https://cowwoc.github.io/requirements.js/4.0.11/functions/DefaultJavascriptValidators.checkIfString.html) See the [API documentation](https://cowwoc.github.io/requirements.js/4.0.11/) for more details. ## Best practices * Use `checkIf().elseGetMessages()` to return failure messages without throwing an exception. This is the fastest validation approach, ideal for web services. * To enhance the clarity of failure messages, you should provide parameter names, even when they are optional. In other words, favor `assert that(value, name)` over `assert that(value)`. ## Related Projects * http://chaijs.com/ * https://github.com/dsheiko/bycontract * https://github.com/muroc/offensive.js ## License Code licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 Icons made by Flat Icons from www.flaticon.com is licensed by CC 3.0 BY