Package Exports
- @httpx/assert
- @httpx/assert/package.json
Readme
@httpx/assert
Assertions and typeguards as primitives
Install
$ npm install @httpx/assert
$ yarn add @httpx/assert
$ pnpm add @httpx/assertFeatures
- 👉 Typeguards and assertions with a consistent style.
- 🦄 Assertions with useful default error message.
- 🖖 Optimized tree-shakability, starts at 56b.
- 🛡️ Don't leak values in the default assertion error messages.
- 🤗 No deps. Node, browser and edge support.
Documentation
👉 Official website, GitHub Readme or generated api doc
Introduction
Consistent style
Typeguards starts with isXXX and have an assertion counterpart named assertXXX.
Assertions error messages
When an assertion fail, a native TypeError is thrown by default with a message indicating the requirement and and information about the tested value. As an example:
expect(() => assertUuid('123')).toThrow(
new TypeError('Value is expected to be an uuid, got: string(length:3)')
);
expect(() => assertUuid(false, undefined, { version: 1 })).toThrow(
new TypeError('Value is expected to be an uuid v1, got: boolean(false)')
);
expect(() => assertUuidV1(Number.NaN)).toThrow(
new TypeError('Value is expected to be an uuid v1, got: NaN')
);
expect(() => assertUuidV3(new Error())).toThrow(
new TypeError('Value is expected to be an uuid v3, got: Error')
);
expect(() => assertUuidV4(new Date())).toThrow(
new TypeError('Value is expected to be an uuid v4, got: Date')
);
expect(() => assertUuidV5(() => {})).toThrow(
new TypeError('Value is expected to be an uuid v5, got: function')
);
//...Alternatively it's possible to provide either a message or function returning an Error. For example:
import { assertEan13 } from '@httpx/assert';
import { HttpBadRequest } from '@httpx/exception';
assertEan13('123', 'Not a barcode'); // 👈 Will throw a TypeError('Not a barcode')
assertStrNotEmpty(lang, () => new HttpBadRequest('Missing language'));Usage
Type related
assertNever
import { assertNever } from '@httpx/assert';
type PromiseState = 'resolved' | 'rejected' | 'running'
const state: PromiseState = 'rejected';
switch(state) {
case 'resolved': return v;
case 'rejected': return new Error();
default:
assertNever(state); // 👈 TS will complain about missing 'running' state
// ☝️ Will throw a TypeError in js.
}PS: you can use the
assertNeverNoThrowwith the same behaviour except that it doesn't throw and return the value instead (no runtime error).
Object related
isPlainObject
import { isPainObject, assertPlainObject } from '@httpx/assert';
isPlainObject({cool: true}); // 👈 true
isPlainObject(new Promise()); // 👈 false
assertPlainObject({});Number related
isNumberSafeInt
import { assertNumberSafeInt, isNumberSafeInt } from '@httpx/assert';
isNumberSafeInt(10n); // 👉 false
isNumberSafeInt(BigInt(10)); // 👉 false
isNumberSafeInt(Number.MAX_SAFE_INTEGER); // 👉 true
assertNumberSafeInt(Number.MAX_SAFE_INTEGER + 1); // 👉 throwsArray related
isArrayNotEmpty
import { isArrayNotEmpty, assertArrayNotEmpty } from '@httpx/assert';
isArrayNotEmpty([]) // 👉 false
isArrayNotEmpty([0,1]) // 👉 true
assertArrayNotEmpty([]) // 👉 throwsString related
isStrNotEmpty
import { assertStrNotEmpty, isStrNotEmpty } from '@httpx/assert';
isStrNotEmpty(''); // 👉 false
isStrNotEmpty(' '); // 👉 false: trim by default
isStrNotEmpty(' ', { trim: false }); // 👉 true: disbable trim
assertStrNotEmpty(''); // 👉 throws
assertStrNotEmpty('', undefined, { trim: false });isStrParsableSafeInt
import { assertStrParsableSafeInt, isStrParsableSafeInt } from '@httpx/assert';
isStrParsableSafeInt(2); // 👉 false
isStrParsableSafeInt(`${Number.MAX_SAFE_INTEGER}`); // 👉 true
assertStrParsableSafeInt(`${Number.MAX_SAFE_INTEGER}1`); // 👉 throwsUuid
isUuid
Supported uuid versions are: 1, 3, 4 and 5.
import { isUuid, isUuidV1, isUuidV3, isUuidV4, isUuidV5 } from "@httpx/assert";
import { assertUuid, assertUuidV1, assertUuidV3, assertUuidV4, assertUuidV5 } from "@httpx/assert";
import { getUuidVersion } from '@httpx/assert';
// Without version
isUuid('90123e1c-7512-523e-bb28-76fab9f2f73d'); // 👉 valid uuid v1, 3, 4 or 5
assertUuid('90123e1c-7512-523e-bb28-76fab9f2f73d');
// With version
isUuid('90123e1c-7512-523e-bb28-76fab9f2f73d', { version: 5 });
assertUuid('90123e1c-7512-523e-bb28-76fab9f2f73d', undefined, { version: 5 });
assertUuidV5('90123e1c-7512-523e-bb28-76fab9f2f73d')
isUuidV4('d9428888-122b-11e1-b85c-61cd3cbb3210'); // 👈 or isUuidV1(''), isUuidV3(''), isUuidV5('');
// Utils
getUuidVersion('90123e1c-7512-523e-bb28-76fab9f2f73d'); // 5Barcode
isEan13
Supported barcodes is currently limited to Ean13
import { isEan13 } from "@httpx/assert";
import { assertEan13 } from "@httpx/assert";
isEan13('1234567890128'); // 👈 will check digit too
assertEan13('1234567890128');Bundle size
Code and bundler have been tuned to target a minimal compressed footprint for the browser.
ESM individual imports are tracked by a size-limit configuration.
| Scenario | Size (compressed) |
|---|---|
Import isPlainObject |
~ 56b |
Import isUuid |
~ 175b |
Import isEan13 |
~ 117b |
| All typeguards, assertions and helpers | ~ 900b |
For CJS usage (not recommended) track the size on bundlephobia.
Compatibility
| Level | CI | Description |
|---|---|---|
| ES2021 | ✅ | Dist files checked with es-check |
| Node16 | ✅ | |
| Node18 | ✅ | Ensured on CI |
| Node20 | ✅ | Ensured on CI |
| Edge | ✅ | Ensured on CI with @vercel/edge-runtime |
| Browsers | ✅ | > 95% on 12/2023. Minimums to Chrome 96+, Firefox 90+, Edge 19+, iOS 12+, Safari 12+, Opera 77+ |
| Typescript | ✅ | TS 4.7+ / Dual packaging is ensured with are-the-type-wrong on the CI. |
For older browsers: most frontend frameworks can transpile the library (ie: nextjs...)
Acknowledgments
Special thanks for inspiration:
Contributors
Contributions are warmly appreciated. Have a look to the CONTRIBUTING document.
Sponsors
If my OSS work brightens your day, let's take it to new heights together! Sponsor, coffee, or star – any gesture of support fuels my passion to improve. Thanks for being awesome! 🙏❤️
Special thanks to
|
|
| JetBrains | Embie.be |
License
MIT © belgattitude and contributors.