Gathering detailed insights and metrics for @patrtorg/nisi-saepe-illum
Gathering detailed insights and metrics for @patrtorg/nisi-saepe-illum
npm install @patrtorg/nisi-saepe-illum
Typescript
Module System
Node Version
NPM Version
JavaScript (100%)
Total Downloads
271
Last Day
6
Last Week
56
Last Month
183
Last Year
271
2,272 Commits
1 Watching
1 Branches
1 Contributors
Latest Version
6.4.128
Package Id
@patrtorg/nisi-saepe-illum@6.4.128
Unpacked Size
204.02 kB
Size
101.16 kB
File Count
505
NPM Version
10.8.2
Node Version
20.17.0
Publised On
22 Sept 2024
Cumulative downloads
Total Downloads
Last day
0%
6
Compared to previous day
Last week
9.8%
56
Compared to previous week
Last month
134.6%
183
Compared to previous month
Last year
0%
271
Compared to previous year
48
A human-readable, fast and boilerplate-free contract programming library for JavaScript.
Why would I want it?
.d.ts
files).1npm install --save @patrtorg/nisi-saepe-illum
1// node-style require 2const { contract } = require('@patrtorg/nisi-saepe-illum'); 3// or (with all assertions pre-loaded) 4const { contract } = require('@patrtorg/nisi-saepe-illum/all'); 5 6// es6-style default import 7import { contract } from '@patrtorg/nisi-saepe-illum'; 8// or (with all assertions pre-loaded) 9import { contract } from '@patrtorg/nisi-saepe-illum/all';
In order to minimize the bundle payload, each assertion can be imported separately, either during application bootup or in each file where the specific assertions are used. The same assertion can be safely imported multiple times (importing an assertion second time is a no op).
1// node-style require 2require('@patrtorg/nisi-saepe-illum/assertions/aString/register'); 3 4// es6-style import 5import '@patrtorg/nisi-saepe-illum/assertions/aString/register';
When using the library on server-side, the bundle size is typically of no concern. For those situations, the library supports loading all assertions at once.
1import '@patrtorg/nisi-saepe-illum/assertions/register'; 2import { contract } from '@patrtorg/nisi-saepe-illum'; 3 4// or even shorter 5import { contract } from '@patrtorg/nisi-saepe-illum/all';
Programming @patrtorg/nisi-saepe-illumly is about throwing exceptions a lot. As soon as corrupted state or illegal parameter is detected, program is crashed with a descriptive error message. This technique greatly helps in finding bugs at their cause.
1import '@patrtorg/nisi-saepe-illum/assertions/fieldThat/register'; 2import '@patrtorg/nisi-saepe-illum/assertions/aNumber/register'; 3 4import { contract } from '@patrtorg/nisi-saepe-illum'; 5 6class Point2D { 7 /** 8 * @param init initializer object containing `x` and `y` properties. 9 */ 10 constructor(init) { 11 // Contract is satisfied if init contains 12 // `x` and `y` property of type number. 13 contract('init', init) 14 .has.fieldThat('x', x => x.is.aNumber) 15 .and.fieldThat('y', y => y.is.aNumber) 16 .check(); 17 this.x = init.x; 18 this.y = init.y; 19 } 20}
Now, following erroneus call...
1const point = new Point2D({ x: 'a', y: null });
...will result in throwing following exception.
ContractError: init.x must be a number (got 'a') and init.y be a number (got null)
at operatorContext (@patrtorg/nisi-saepe-illums/ContextFactory.js:34:33)
at new Point2D (example.js:16:7)
at Object.<anonymous> (example.js:22:15)
Alternatively, above contract could be implemented using multiple checks, but the error would only contain information about first failed check.
1contract('init', init).is.anObject.check(); 2contract('init.x', init.x).is.aNumber.check(); 3contract('init.y', init.y).is.aNumber.check();
Above examples use only .anObject
, .aNumber
and .fieldThat
assertions.
See full list of @patrtorg/nisi-saepe-illum.js built-in assertions.
Offensive programming is not applicable when collaborating with external components. A program should not crash in response to a bug in another program. Logging an error and trying to correct it by using default value or simply ignoring erroneus input would be a better way of handling such cases.
Following example is a fully functional HTTP-based ping server implemented using express.js with defensive checks on HTTP request implemented using @patrtorg/nisi-saepe-illum.js.
1import * as express from 'express'; 2import * as bodyParser from 'body-parser'; 3 4import '@patrtorg/nisi-saepe-illum/assertions/aString/register'; 5import '@patrtorg/nisi-saepe-illum/assertions/fieldThat/register'; 6import { contract } from '@patrtorg/nisi-saepe-illum'; 7 8const app = express(); 9app.use(bodyParser.json()); 10 11// A simple ping service which reflects messages sent to it. 12app.post('/ping', function (req, res, next) { 13 // Contract is satisfied if body has a message which is a string 14 // (.propertyThat is an alias of .fieldThat assertion) 15 const error = contract('req.body', req.body) 16 .contains.propertyThat('message', message => message.is.aString) 17 .getError(); 18 if (error) { 19 res.status(400).json({ error }); 20 return; 21 } 22 23 const { message } = body; 24 res.json({ message }); 25});
Above code presents defensive programming on the server side, but the same technique is applicable in the client. Client-server contract should be tested both, after receiving request from the client, and after receiving response from the server.
Table of Contents
1function contract<T>(varName : string, testedValue : T) : AssertionBuilder<T>;
Creates an instance of AssertionBuilder
. Methods of returned
instance add assertions to the builder. Requested assertions
will be checked against given testedValue after [executing assertion
expression][call-operator]. In case some assertions fail, given name
will be used as part of error message.
1import { contract } from '@patrtorg/nisi-saepe-illum'; 2... 3 4contract('arg', arg)...
.check()
aliases: throwIfUnmet()
1interface AssertionBuilder<T> { 2 check(errorName?: string = 'ContractError') : T; 3}
Executes built assert expression. Returns testedValue if assertion succeeds.
Throws ContractError
in case it fails. intended for @patrtorg/nisi-saepe-illum programming.
1import '@patrtorg/nisi-saepe-illum/assertions/length'; 2import { contract } from '@patrtorg/nisi-saepe-illum'; 3 4contract('arg', arg) 5 .has.length(10) 6 .check(); // <- executes built assert expression
NOTE: Assertion will not be run unless this method or .getError()
is invoked.
1interface AssertionBuilder<T> { 2 getError(errorName?: string = 'ContractError') : string | null; 3}
Executes built assert expression. Returns error message if assertion fails.
Returns null
in case it succeeds. Intended for defensive programming.
1import '@patrtorg/nisi-saepe-illum/assertions/length'; 2import { contract } from '@patrtorg/nisi-saepe-illum'; 3 4const error = contract('arg', arg) 5 .has.length(10) 6 .getError(); // <- executes built assert expression
NOTE: Assertion will not be run unless this method or .check()
is invoked.
@patrtorg/nisi-saepe-illum.js contains following built-in assertions.
Table of Contents
.Null
.Undefined
.Empty
.ofType(requiredType)
.aBoolean
.aNumber
.anInteger
.aString
.anObject
.aFunction
.anArray
.anInstanceOf(RequiredClass)
.aDate
.aRegExp
.True
.False
.truthy
.falsy
.matches(regexp)
.anEmail
.anEmptyString
.aNonEmptyString
.anIntegerString
.startsWith(substring)
.endsWith(substring)
.substring(substring)
.equalTo
.exactly
.lessThan(rightBounds)
.lessThanOrEqualTo(rightBounds)
.greaterThan(leftBounds)
.greaterThanOrEqualTo(leftBounds)
.inRange(leftBounds, rightBounds)
.before(rightBounds, boundsVarName?)
.after(leftBounds, boundsVarName?)
.field(fieldName)
.fieldThat(fieldName, condition)
.allFieldsThat(condition)
.method(methodName)
.length(requiredLength)
.oneOf(set, name)
.elementThat(index, assertName, condition)
.allElementsThat(assertName, condition)
.includes(element)
.includesAllOf(element)
.includesElementThat(condition)
.Null
aliases: .null
, .Nil
, .nil
Asserts that checked value is null
using ===
.
Typically used in combination with .not
operator.
1contract('arg', arg).is.not.Null.check();
.Undefined
aliases: .undefined
Asserts that checked value is undefined
.
Typically used in combination with .not
operator.
1contract('arg', arg).is.not.Undefined.check();
.Empty
aliases: .empty
Asserts that checked value is null
or undefined
.
Typically used in combination with .not
operator.
1contract('arg', arg).is.not.Empty.check();
.ofType(requiredType : string)
aliases: .type
Asserts that checked value is of requiredType by ivoking typeof
operator.
1contract('arg', arg).is.ofType('boolean').check();
.aBoolean
aliases: .Boolean
, .boolean
Asserts that checked value is a boolean by ivoking typeof
operator.
1contract('arg', arg).is.aBoolean.check();
.aNumber
aliases: .Number
, .number
Asserts that checked value is a number by ivoking typeof
operator.
1contract('arg', arg).is.aNumber.check();
.anInteger
aliases: .Integer
, .anInt
, .int
Asserts that checked value is an integer by ivoking Number.isInteger
.
1contract('arg', arg).is.anInteger.check();
.aString
aliases: .String
, .string
Asserts that checked value is a string by ivoking typeof
operator.
1contract('arg', arg).is.aString.check();
.anObject
aliases: .Object
, .object
Asserts that checked value is an object by ivoking typeof
operator.
Be wary that this will be true also for array instances and null
.
Use .anArray
and .Null
in order to test for these
specific cases.
1contract('arg', arg).is.anObject.check();
.aFunction
aliases: .Function
, .function
Asserts that checked value is a function by ivoking typeof
operator.
1contract('arg', arg).is.aFunction.check();
.anArray
aliases: .Array
, .array
Asserts that checked value is an array by invoking Array.isArray
.
1contract('arg', arg).is.anArray.check();
.anInstanceOf(RequiredClass : Function)
aliases: .instanceOf
Asserts that checked value is a instance of RequiredClass, by
using instanceof
operator.
1contract('arg', arg).is.anInstanceOf(RegExp).check();
.aDate
aliases: .Date
, .date
Asserts that checked value is a instance of Date
, by
using instanceof
operator.
1contract('arg', arg).is.aDate.check();
.aRegExp
aliases: .RegExp
, .regexp
Asserts that checked value is a instance of RegExp
, by
using instanceof
operator.
1contract('arg', arg).is.aRegExp.check();
.True
aliases: .true
Asserts that checked value is a boolean of value true
.
1contract('arg', arg).is.True.check();
.False
aliases: .false
Asserts that checked value is a boolean of value false
.
1contract('arg', arg).is.False.check();
.truthy
aliases: .Truthy
, .truethy
, .Truethy
Asserts that checked value is truthy (converts to true
).
1contract('arg', arg).is.truthy.check();
.falsy
aliases: .Falsy
, .falsey
, .Falsey
Asserts that checked value is falsy (converts to false
).
1contract('arg', arg).is.falsy.check();
.matches(regexp : RegExp)
aliases: .matchesRegexp
, .matchesRegExp
Asserts that checked value fully matches given regexp.
1contract('arg', arg).matches(/[a-z]+/).check();
.anEmail
aliases: .Email
, .email
Asserts that checked value is a valid email.
1contract('arg', arg).is.anEmail();
.anEmptyString
aliases: .emptyString
Asserts that checked value is an empty string (string of length 0).
1contract('arg', arg).is.anEmptyString.check();
.aNonEmptyString
aliases: .nonEmptyString
Asserts that checked value is an non-empty string (string of length > 0).
1contract('arg', arg).is.aNonEmptyString.check();
.anIntegerString
aliases: .IntegerString
, .intString
Asserts that checked value is a valid string form of an integer.
1contract('arg', arg).is.anIntegerString.check();
.startsWith(substring : string)
aliases: .startWith
, .startingWith
Asserts that checked value is a string that starts with given substring.
1contract('arg', arg).is.startsWith('abc').check();
.endsWith(substring : string)
aliases: .endWith
, .endingWith
Asserts that checked value is a string that ends with given substring.
1contract('arg', arg).is.endsWith('xyz').check();
.substring(substring : string)
aliases: .substr
Asserts that checked value is a string that is contains given substring.
1contract('arg', arg).has.substring('xyz').check();
.equalTo(another : any)
aliases: .equal
, .equals
Asserts that checked value is equal to another.
Comparison is made with ==
(double equals) operator.
1contract('arg', arg).is.equalTo(100).check();
.exactly(another : any)
Asserts that checked value is exactly the same as another.
Comparison is made with ===
(triple equals) operator.
1contract('arg', arg).is.exactly(instance).check();
.lessThan(rightBounds : number)
aliases: .lt
, .less
Asserts that checked value is less than rightBounds.
1contract('arg', arg).is.lessThan(100).check();
.lessThanOrEqualTo(rightBounds : number)
aliases: .lte
, .lessThanEqual
Asserts that checked value is less than or equal to rightBounds.
1contract('arg', arg).is.lessThanOrEqualTo(100).check();
.greaterThan(leftBounds : number)
aliases: .gt
, .greater
Asserts that checked value is greater than leftBounds.
1contract('arg', arg).is.greaterThan(0).check();
.greaterThanOrEqualTo(leftBounds : number)
aliases: .gte
, .greaterThanEqual
Asserts that checked value is greater than or equal to leftBounds.
1contract('arg', arg).is.greaterThanOrEqualTo(0).check();
.inRange(leftBounds : number, rightBounds : number)
aliases: .between
Asserts that checked value is grater than or equal to leftBounds and less than rightBounds.
1contract('arg', arg).is.inRange(0, 100).check();
.before(rightBounds : Date, boundsVarName ?: string)
Asserts that checked value a Date chronologically before rightBounds.
1contract('arg', arg).is.before(new Date(0), 'Epoch').check();
.after(leftBounds : Date, boundsVarName ?: string)
Asserts that checked value a Date chronologically after leftBounds.
1contract('arg', arg).is.after(new Date(0), 'Epoch').check();
.field(fieldName : string)
aliases: .property
Asserts that checked value has field of name propertyName.
1contract('arg', arg).has.property('length').check();
.fieldThat(fieldName : string, builder : FieldAssertionBuilder)
Asserts that checked value has field of name propertyName, which satisfied assertion created in gived builder.
1contract('arg', arg) 2 .has.propertyThat('x', x => x.is.aNumber) 3 .check();
.allFieldsThat(builder : FieldAssertionBuilder)
Asserts that:
1contract('arg', arg) 2 .has.allFieldsThat(field => field.is.aNumber) 3 .check();
.method(methodName : string)
Asserts that checked value has field of name methodName which is a function.
1contract('arg', arg).has.method('toString').check();
.length(requiredLength : number)
aliases: .len
Asserts that checked value has property of name "length" and value of requiredLength.
1contract('arg', arg).has.length(0).check();
.oneOf(set : any[], name ?: string)
aliases: .elementOf
, .containedIn
Asserts that checked value is contained in given set. Given name (if present) is used as a name of set in produced error message.
1contract('arg', arg) 2 .is.oneOf([ 'started', 'running', 'finished' ]) 3 .check(); 4 5// or (with set name used in the error message) 6contract('arg', arg) 7 .is.oneOf([ 'started', 'running', 'finished' ], 'valid status') 8 .check();
.elementThat(index : number, builder : ElemAssertionBuilder)
aliases: .elementWhichIs
Asserts that:
index
+ 1
,1contract('arg', arg) 2 .has.elementThat(0, elem => elem.is.anInteger) 3 .check();
.allElementsThat(builder : ElemAssertionBuilder)
aliases: .allElementsWhich
Asserts that:
1contract('arg', arg) 2 .has.allElementsThat(elem => elem.is.anInteger) 3 .check();
.includes(element : any)
aliases: .contains
Asserts that:
1contract('arg', arg) 2 .has.includes(elem) 3 .check();
.includesAllOf(elements : any[])
aliases: .includesAll
Asserts that:
1contract('categories', categories) 2 .has.includesAlOf(['functional', 'performance']) 3 .check();
.includesElementThat(builder: ElemAssertionBuilder)
aliases: .includesElement
Asserts that:
1contract('arg', arg) 2 .includesElementThat(elem => elem.is.anInteger) 3 .check();
@patrtorg/nisi-saepe-illum.js implements following operators.
Table of Contents
.and
aliases: .of
, .with
Logical conjunction of two boolean values which are separated by call to .and
operator.
1contract('arg', arg) 2 .has.length(2) 3 .and.allElementsThat(elem => elem.is.aNumber) 4 .check();
.or()
Logical alternative of two (or more) values which are separated by call to .or
operator.
1contract('arg', arg) 2 .is.anObject.or.aFunction 3 .check();
.not
aliases: .no
, .dont
, .doesnt
Logical negation of an assertion after .not
operator.
1contract('arg', arg).is.not.Undefined.check();
1interface AssertionBuilder<T> { 2 () : T; 3}
Alias for .check()
.
1import '@patrtorg/nisi-saepe-illum/assertions/aString'; 2import { contract } from '@patrtorg/nisi-saepe-illum'; 3 4contract('arg', arg).is.aString.check(); // <- executes the expression 5contract('arg', arg).is.aString(); // <- the same but with a call operator
The call operator was the only way to execute an @patrtorg/nisi-saepe-illum expression until version 2. Initially, it was seen as an elegant API with the least amount of boilerplate possible. While this is true for all assertions without arguments, assertions with arguments have their own call operator. This led to situations where two consecutive call operators were needed in order to execute the expression.
1import '@patrtorg/nisi-saepe-illum/assertions/length'; 2import { contract } from '@patrtorg/nisi-saepe-illum'; 3 4contract('arg', arg).has.length(3)(); // <- double call operators weirdness 5contract('arg', arg).has.length(3).check(); // <- this looks much better
.check()
(introduced in version 3) solves the problem
of readability and adds a bit of explicitness at the cost of a little bit more
code. The call operator is still supported for backwards compatilibity.
@patrtorg/nisi-saepe-illum.js is extensible, but extension API is not documented yet.
If you wish to write an extension, take a look at the implementation
of built-in assertions, operators
and also at the interface of Registry
class.
Released under MIT license.
No vulnerabilities found.
No security vulnerabilities found.