Comparing version 2.0.1 to 3.0.0
@@ -5,9 +5,11 @@ # Blork: Contributing | ||
## Pull requests | ||
This tooling workflow exists to catch simple code mistakes that we all make and raise overall code quality. Once you learn to code against these tools, programming becomes a lot more fun! | ||
Please follow these (obvious) guidelines: | ||
## Pull request rules | ||
1. Code should be fully linted with TSLint (or the PR will be automatically rejected by Travis CI) | ||
Please follow these (pretty obvious) guidelines: | ||
1. Code should be fully linted with ESLint (or the PR will be automatically rejected by Travis CI) | ||
2. Test suite must pass (or the PR will be automatically rejected by Travis CI) | ||
3. New features should include corresponding unit tests | ||
3. New features should include corresponding unit tests (code coverage must be 100%) | ||
4. New features should include new documentation in README.md | ||
@@ -17,19 +19,19 @@ | ||
Blork is written in Typescript, uses TSLint for linting, and Jest for unit testing. Blork is deployed to NPM through Travis CI whenever a new release is made on GitHub, which also automatically checks rejects any pull requests that fail their tests. | ||
Blork is written in Javascript, uses ESLint for linting, Prettier for code style, and Jest for unit testing. Blork is deployed to NPM through Travis CI whenever a new tagged release is created on GitHub. TravisCI automatically checks (and rejects) pull requests that fail the unit tests or are improperly linted. | ||
### Install (npm) | ||
### 1. Clone and install (Git and npm) | ||
Clone the repo from GitHub and install dependencies with NPM. | ||
```sh | ||
git clone https://github.com/dhoulb/blork.git | ||
cd blork | ||
npm install | ||
``` | ||
### Code (you!) | ||
Clone the repo from GitHub and install dependencies with NPM. | ||
Write any code you like. Don't worry too much about style as TSLint will find and correct most issues, but try to stick to what's already there where possible. Ensure all exported functions (the outer-facing edges of the module) validate their input arguments (e.g. with Blork) so the module is hardened against mistakes/misuse. | ||
### 2. Code | ||
### Lint (TSLint) | ||
Write any code you like. Don't worry too much about style as Prettier will standardise it. Ensure all exported functions (the outer-facing edges of the module) validate their input arguments (e.g. with Blork) so the module is hardened against mistakes/misuse. | ||
Blork is linted using TSLint (which is configured to be pretty strict). TSLint will fix as many issues as it can, but any leftover linting issues must be fixed before you can build. | ||
### 2. Lint and style (ESLint and Prettier) | ||
@@ -40,20 +42,24 @@ ```sh | ||
### Build (Typescript) | ||
Blork is linted using ESLint and code formatting is done with Prettier. ESLint will fix as many issues as it can, but any leftover linting should be fixed. Configuring your editor to report linting issues as-you-type and automatically run `eslint --fix` or `npm run fix` on save makes this all a lot easier! | ||
Blork is written in Typescript (in the `src/` directory) and is compiled into Javascript (in the `lib/` directory) using the `build` script. _The build script will run TSLint before it builds so any linting errors must be fixed first._ | ||
All code is reformatted using Prettier, so write using whatever style you like leave Prettier to fix it. | ||
### 3. Unit tests (Jest) | ||
```sh | ||
npm run build | ||
npm test | ||
``` | ||
### Test (Jest) | ||
Tests are written in Jest and are in the `test/` directory. Run the test suite using `npm test` on the command line, which will lint, style, and test the code. | ||
Tests are written in Jest and are in the `test/` directory. Tests are run against the compiled Javascript code so you won't be able to test your code if you have Typescript compiler errors. Run the test suite using the `test` script, which will attempt to lint and build before it runs. | ||
Code coverage must be 100% or `npm test` will also fail (this means every file, function, and branch of your code must be covered by a unit test.) | ||
### Commit (Git) | ||
```sh | ||
npm test | ||
git add . | ||
git commit -m "My changes" | ||
git push origin | ||
``` | ||
### Commit (Git) | ||
Jest unit tests are configured as a precommit hook (using [Husky](https://www.npmjs.com/package/husky)) so Git commits and pushes will fail if code isn't linted, won't build, or fails tests. This helps catch mistakes early (any of these failing would cause your PR to be rejected by Travis CI anyway!) | ||
Jest unit tests, ESLint, and Prettier run as a precommit hook (using [Husky](https://www.npmjs.com/package/husky)) so any Git commit you try to do will fail if code isn't linted correctly or fails tests. |
153
lib/blork.js
@@ -1,41 +0,112 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const internal_1 = require("./internal"); | ||
const checkers_1 = require("./checkers"); | ||
const helpers_1 = require("./helpers"); | ||
const errors_1 = require("./errors"); | ||
let errorConstructor = TypeError; | ||
function check(value, type, prefix = '') { | ||
internal_1.internalCheck(prefix, 'string', 'arguments[2]', errors_1.BlorkError); | ||
return internal_1.internalCheck(value, type, prefix, errorConstructor); | ||
} | ||
exports.check = check; | ||
function args(argsObj, types) { | ||
internal_1.internalCheckString(argsObj, 'args', 'arguments[0]', errors_1.BlorkError); | ||
internal_1.internalCheckString(types, 'array', 'arguments[1]', errors_1.BlorkError); | ||
const l = types.length; | ||
let pass = 0; | ||
for (let i = 0; i < l; i++) | ||
if (internal_1.internalCheck(argsObj[i], types[i], `arguments[${i}]`, errorConstructor)) | ||
pass++; | ||
if (argsObj.length > l) { | ||
throw new errorConstructor(helpers_1.format(`Too many arguments (expected ${l})`, argsObj.length, 'arguments')); | ||
} | ||
return pass; | ||
} | ||
exports.args = args; | ||
function add(name, checker) { | ||
internal_1.internalCheckString(name, 'lower+', 'arguments[0]', errors_1.BlorkError); | ||
internal_1.internalCheckString(checker, 'function', 'arguments[1]', errors_1.BlorkError); | ||
if (checkers_1.checkers[name]) { | ||
throw new errors_1.BlorkError(`Blork type '${name}' already exists`); | ||
} | ||
checkers_1.checkers[name] = checker; | ||
} | ||
exports.add = add; | ||
function throws(err) { | ||
internal_1.internalCheckString(err, 'function', 'arguments[0]', errors_1.BlorkError); | ||
errorConstructor = err; | ||
} | ||
exports.throws = throws; | ||
//# sourceMappingURL=blork.js.map | ||
const internalCheck = require("./check"); | ||
const checkers = require("./checkers"); | ||
const format = require("./format"); | ||
const BlorkError = require("./BlorkError"); | ||
/** | ||
* Create a new instance of Blork. | ||
* | ||
* Allows new instances of args() and check() to exist. | ||
* Separate instances have their own independent throws() error class and list of additional checkers. | ||
* | ||
* @returns {object} An object that can be destructured into { check, args, add, throws } functions. | ||
*/ | ||
module.exports = function blork() { | ||
// Vars. | ||
const instanceCheckers = {}; | ||
let instanceError = TypeError; | ||
// Copy checkers to instanceCheckers. | ||
for (const i in checkers) instanceCheckers[i] = checkers[i]; | ||
/** | ||
* Check values against types. | ||
* Throws an error if a value doesn't match a specified type. | ||
* | ||
* @param {mixed} value A single value (or object/array with multiple values) to check against the type(s). | ||
* @param {string|Function|Array|Object} type A single stringy type reference (e.g. 'str'), functional shorthand type reference (e.g. `String`), or an object/array with list of types (e.g. `{name:'str'}` or `['str', 'num']`). | ||
* @param {string} prefix='' Prefix for error messages, to assist debugging. | ||
* | ||
* @return {integer} Returns the number of values that passed their checks. | ||
* @throws An error describing what went wrong (usually an error object). | ||
*/ | ||
function check(value, type, prefix = "") { | ||
// Check args. | ||
if (typeof prefix !== "string") internalCheck(prefix, "str", "arguments[2]", BlorkError, checkers); | ||
// Check the value against the type. | ||
return internalCheck(value, type, prefix, instanceError, instanceCheckers); | ||
} | ||
/** | ||
* Check function arguments against types. | ||
* Same as check() but slightly friendlier and easier to use. | ||
* | ||
* @param {object} argsobj The entire arguments object from the function call. Must have a .length property. | ||
* @param {array} types A set of types corresponding to the argument. | ||
* | ||
* @return {integer} Returns the number of values that passed their checks. | ||
* @throws An error describing what went wrong (usually an error object). | ||
*/ | ||
function args(argsobj, types) { | ||
// Check args. | ||
// Checked manually first for minor speed improvement. | ||
if (checkers.args(argsobj) !== true) internalCheck(argsobj, "args", "arguments[0]", BlorkError, checkers); | ||
if (!(types instanceof Array)) internalCheck(types, "array", "arguments[1]", BlorkError, checkers); | ||
// Vars. | ||
const l = types.length; | ||
let pass = 0; | ||
// Recurse into each type. | ||
for (let i = 0; i < l; i++) { | ||
if (internalCheck(argsobj[i], types[i], `arguments[${i}]`, instanceError, instanceCheckers)) pass++; | ||
} | ||
// No excess arguments. | ||
if (argsobj.length > l) { | ||
throw new instanceError(format(`Too many arguments (expected ${l})`, argsobj.length, "arguments")); | ||
} | ||
// Success. | ||
return pass; | ||
} | ||
/** | ||
* Add a new custom checker. | ||
* | ||
* Checker function should take in a value, check it and return either `true` (success) or a string error (e.g. `Must be a whole number`). | ||
* This format is chosen because it allows buttery constructions like `check.add(const str = v => (typeof v === 'string' || 'must be string'); | ||
* | ||
* @param {string} name The type reference for the checker. | ||
* @param {function} checker A checker function: Takes a single argument (value), tests it, and returns either true (success) or an error message string in the 'Must be X' format. | ||
* @return {void} | ||
*/ | ||
function add(name, checker) { | ||
// Check args. | ||
internalCheck(name, "lower+", "arguments[0]", BlorkError, instanceCheckers); | ||
internalCheck(checker, "function", "arguments[1]", BlorkError, instanceCheckers); | ||
// Don't double up. | ||
if (instanceCheckers[name]) throw new BlorkError(`Blork type '${name}' already exists`); | ||
// Save the checker. | ||
instanceCheckers[name] = checker; | ||
} | ||
/** | ||
* Set the error any failed checks should throw. | ||
* @param {Error} err The error constructor to use for | ||
* @return {void} | ||
*/ | ||
function throws(err) { | ||
// Check args. | ||
internalCheck(err, "function", "arguments[0]", BlorkError, instanceCheckers); | ||
// Save instanceError. | ||
instanceError = err; | ||
} | ||
// Returns. | ||
return { check, args, add, throws }; | ||
}; |
@@ -1,68 +0,77 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.checkers = { | ||
'null': (v) => v === null || 'Must be null', | ||
'undefined': (v) => v === undefined || 'Must be undefined', | ||
'defined': (v) => v !== undefined || 'Must be defined', | ||
'boolean': (v) => v === true || v === false || 'Must be true or false', | ||
'true': (v) => v === true || 'Must be true', | ||
'false': (v) => v === false || 'Must be false', | ||
'truthy': (v) => !!v || 'Must be truthy', | ||
'falsy': (v) => !v || 'Must be falsy', | ||
'number': (v) => typeof v === 'number' && Number.isFinite(v) || 'Must be a finite number', | ||
'number+': (v) => (typeof v === 'number' && Number.isFinite(v) && v >= 0) || 'Must be a positive finite number', | ||
'number-': (v) => (typeof v === 'number' && Number.isFinite(v) && v <= 0) || 'Must be a negative finite number', | ||
'integer': (v) => (typeof v === 'number' && Number.isInteger(v) && v >= Number.MIN_SAFE_INTEGER && v <= Number.MAX_SAFE_INTEGER) || 'Must be an integer', | ||
'integer+': (v) => (typeof v === 'number' && Number.isInteger(v) && v >= 0 && v <= Number.MAX_SAFE_INTEGER) || 'Must be a positive integer', | ||
'integer-': (v) => (typeof v === 'number' && Number.isInteger(v) && v >= Number.MIN_SAFE_INTEGER && v <= 0) || 'Must be a negative integer', | ||
'string': (v) => typeof v === 'string' || 'Must be a string', | ||
'string+': (v) => (typeof v === 'string' && v.length > 0) || 'Must be a non-empty string', | ||
'lowercase': (v) => (typeof v === 'string' && v === v.toLowerCase()) || 'Must be a lowercase string', | ||
'lowercase+': (v) => (typeof v === 'string' && v.length > 0 && v === v.toLowerCase()) || 'Must be a non-empty lowercase string', | ||
'uppercase': (v) => (typeof v === 'string' && v === v.toUpperCase()) || 'Must be an uppercase string', | ||
'uppercase+': (v) => (typeof v === 'string' && v.length > 0 && v === v.toUpperCase()) || 'Must be a non-empty uppercase string', | ||
'function': (v) => v instanceof Function || 'Must be a function', | ||
'object': (v) => (typeof v === 'object' && v !== null && v.constructor === Object) || 'Must be a plain object', | ||
'object+': (v) => (typeof v === 'object' && v !== null && v.constructor === Object && Object.keys(v).length > 0) || 'Must be a plain object with one or more enumerable properties', | ||
'objectlike': (v) => (typeof v === 'object' && v !== null) || 'Must be an object', | ||
'iterable': (v) => (typeof v === 'object' && v !== null && typeof v[Symbol.iterator] === 'function') || 'Must be an iterable object', | ||
'array': (v) => (v instanceof Array && v.constructor === Array) || 'Must be a plain array', | ||
'array+': (v) => (v instanceof Array && v.constructor === Array && v.length > 0) || 'Must be a plain non-empty array', | ||
'arraylike': (v) => (typeof v === 'object' && v !== null && v.hasOwnProperty('length') && typeof v.length === 'number' && v.length > 0 && v.length <= Number.MAX_SAFE_INTEGER) || 'Must be a plain array', | ||
'map': (v) => (v instanceof Map && v.constructor === Map) || 'Must be a map', | ||
'map+': (v) => (v instanceof Map && v.constructor === Map && v.size > 0) || 'Must be a map', | ||
'weakmap': (v) => (v instanceof WeakMap && v.constructor === WeakMap) || 'Must be a weak map', | ||
'set': (v) => (v instanceof Set && v.constructor === Set) || 'Must be a set', | ||
'set+': (v) => (v instanceof Set && v.constructor === Set && v.size > 0) || 'Must be a non-empty set', | ||
'weakset': (v) => (v instanceof WeakSet && v.constructor === WeakSet) || 'Must be a weak set', | ||
'promise': (v) => v instanceof Promise || 'Must be a promise', | ||
'date': (v) => v instanceof Date || 'Must be a date', | ||
'date+': (v) => (v instanceof Date && v.getTime() > Date.now()) || 'Must be a date in the future', | ||
'date-': (v) => (v instanceof Date && v.getTime() < Date.now()) || 'Must be a date in the past', | ||
}; | ||
exports.checkers.void = exports.checkers.undefined; | ||
exports.checkers.undef = exports.checkers.undefined; | ||
exports.checkers.def = exports.checkers.defined; | ||
exports.checkers.bool = exports.checkers.boolean; | ||
exports.checkers.num = exports.checkers.number; | ||
exports.checkers['num+'] = exports.checkers['number+']; | ||
exports.checkers['num-'] = exports.checkers['number-']; | ||
exports.checkers.int = exports.checkers.integer; | ||
exports.checkers['int+'] = exports.checkers['integer+']; | ||
exports.checkers['int-'] = exports.checkers['integer-']; | ||
exports.checkers.str = exports.checkers.string; | ||
exports.checkers['str+'] = exports.checkers['string+']; | ||
exports.checkers.lower = exports.checkers.lowercase; | ||
exports.checkers['lower+'] = exports.checkers['lowercase+']; | ||
exports.checkers.upper = exports.checkers.uppercase; | ||
exports.checkers['upper+'] = exports.checkers['uppercase+']; | ||
exports.checkers.func = exports.checkers.function; | ||
exports.checkers.obj = exports.checkers.object; | ||
exports.checkers['obj+'] = exports.checkers['object+']; | ||
exports.checkers.arr = exports.checkers.array; | ||
exports.checkers['arr+'] = exports.checkers['array+']; | ||
exports.checkers.arguments = exports.checkers.arraylike; | ||
exports.checkers.args = exports.checkers.arraylike; | ||
exports.checkers.future = exports.checkers['date+']; | ||
exports.checkers.past = exports.checkers['date-']; | ||
//# sourceMappingURL=checkers.js.map | ||
// Primatives. | ||
exports["null"] = v => v === null || "Must be null"; | ||
exports["undefined"] = exports["void"] = exports["undef"] = v => v === undefined || "Must be undefined"; | ||
exports["defined"] = exports["def"] = v => v !== undefined || "Must be defined"; | ||
exports["boolean"] = exports["bool"] = v => v === true || v === false || "Must be true or false"; | ||
exports["true"] = v => v === true || "Must be true"; | ||
exports["false"] = v => v === false || "Must be false"; | ||
exports["truthy"] = v => !!v || "Must be truthy"; | ||
exports["falsy"] = v => !v || "Must be falsy"; | ||
// Numbers. | ||
exports["number"] = exports["num"] = v => (typeof v === "number" && Number.isFinite(v)) || "Must be a finite number"; | ||
exports["number+"] = exports["num+"] = v => | ||
(typeof v === "number" && Number.isFinite(v) && v >= 0) || "Must be a positive finite number"; | ||
exports["number-"] = exports["num-"] = v => | ||
(typeof v === "number" && Number.isFinite(v) && v <= 0) || "Must be a negative finite number"; | ||
exports["integer"] = exports["int"] = v => | ||
(typeof v === "number" && Number.isInteger(v) && v >= Number.MIN_SAFE_INTEGER && v <= Number.MAX_SAFE_INTEGER) || | ||
"Must be an integer"; | ||
exports["integer+"] = exports["int+"] = v => | ||
(typeof v === "number" && Number.isInteger(v) && v >= 0 && v <= Number.MAX_SAFE_INTEGER) || | ||
"Must be a positive integer"; | ||
exports["integer-"] = exports["int-"] = v => | ||
(typeof v === "number" && Number.isInteger(v) && v >= Number.MIN_SAFE_INTEGER && v <= 0) || | ||
"Must be a negative integer"; | ||
// Strings. | ||
exports["string"] = exports["str"] = v => typeof v === "string" || "Must be a string"; | ||
exports["string+"] = exports["str+"] = v => (typeof v === "string" && v.length > 0) || "Must be a non-empty string"; | ||
exports["lowercase"] = exports["lower"] = v => | ||
(typeof v === "string" && v === v.toLowerCase()) || "Must be a lowercase string"; | ||
exports["lowercase+"] = exports["lower+"] = v => | ||
(typeof v === "string" && v.length > 0 && v === v.toLowerCase()) || "Must be a non-empty lowercase string"; | ||
exports["uppercase"] = exports["upper"] = v => | ||
(typeof v === "string" && v === v.toUpperCase()) || "Must be an uppercase string"; | ||
exports["uppercase+"] = exports["upper+"] = v => | ||
(typeof v === "string" && v.length > 0 && v === v.toUpperCase()) || "Must be a non-empty uppercase string"; | ||
// Functions. | ||
exports["function"] = exports["func"] = v => v instanceof Function || "Must be a function"; | ||
// Objects. | ||
exports["object"] = exports["obj"] = v => (v instanceof Object && v.constructor === Object) || "Must be a plain object"; | ||
exports["object+"] = exports["obj+"] = v => | ||
(v instanceof Object && v.constructor === Object && Object.keys(v).length > 0) || | ||
"Must be a plain object with one or more enumerable properties"; | ||
exports["objectlike"] = v => v instanceof Object || "Must be an object"; | ||
exports["iterable"] = v => | ||
(v instanceof Object && typeof v[Symbol.iterator] === "function") || "Must be an iterable object"; | ||
// Arrays. | ||
exports["array"] = exports["arr"] = v => (v instanceof Array && v.constructor === Array) || "Must be a plain array"; | ||
exports["array+"] = exports["arr+"] = v => | ||
(v instanceof Array && v.constructor === Array && v.length > 0) || "Must be a plain non-empty array"; | ||
exports["arraylike"] = exports["arguments"] = exports["args"] = v => | ||
(v instanceof Object && | ||
v.hasOwnProperty("length") && | ||
typeof v.length === "number" && | ||
v.length > 0 && | ||
v.length <= Number.MAX_SAFE_INTEGER) || | ||
"Must be an arraylike object with a numeric length property"; | ||
// Dates. | ||
exports["date"] = v => v instanceof Date || "Must be a date"; | ||
exports["date+"] = exports["future"] = v => | ||
(v instanceof Date && v.getTime() > Date.now()) || "Must be a date in the future"; | ||
exports["date-"] = exports["past"] = v => | ||
(v instanceof Date && v.getTime() < Date.now()) || "Must be a date in the past"; | ||
// Other. | ||
exports["map"] = v => (v instanceof Map && v.constructor === Map) || "Must be a map"; | ||
exports["map+"] = v => (v instanceof Map && v.constructor === Map && v.size > 0) || "Must be a map"; | ||
exports["weakmap"] = v => (v instanceof WeakMap && v.constructor === WeakMap) || "Must be a weak map"; | ||
exports["set"] = v => (v instanceof Set && v.constructor === Set) || "Must be a set"; | ||
exports["set+"] = v => (v instanceof Set && v.constructor === Set && v.size > 0) || "Must be a non-empty set"; | ||
exports["weakset"] = v => (v instanceof WeakSet && v.constructor === WeakSet) || "Must be a weak set"; | ||
exports["promise"] = v => v instanceof Promise || "Must be a promise"; |
{ | ||
"name": "blork", | ||
"description": "Blork! Mini runtime type checking in Javascript", | ||
"version": "2.0.1", | ||
"version": "3.0.0", | ||
"license": "0BSD", | ||
"author": "Dave Houlbrooke <dave@shax.com>", | ||
"main": "lib/blork.js", | ||
"types": "lib/blork.d.ts", | ||
"main": "lib/exports.js", | ||
"engineStrict": true, | ||
"engines": { | ||
"node": ">=6.0.0" | ||
"engines": { "node": ">=8.0.0" }, | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/dhoulb/blork.git" | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"husky": "latest", | ||
"typescript": "latest", | ||
"@types/node": "latest", | ||
"tslint": "latest", | ||
"jest": "latest" | ||
"eslint": "^4.17.0", | ||
"eslint-config-prettier": "^2.9.0", | ||
"eslint-plugin-prettier": "^2.6.0", | ||
"husky": "^0.14.3", | ||
"jest": "^22.1.4", | ||
"prettier": "^1.10.2" | ||
}, | ||
"scripts": { | ||
"fix": "tslint -p tsconfig.json --fix", | ||
"prebuild": "npm run fix", | ||
"build": "rm -rf lib && mkdir lib && tsc -p tsconfig.json", | ||
"pretest": "npm run build", | ||
"test": "jest --coverage", | ||
"watch": "jest --watchAll", | ||
"prepush": "npm run test" | ||
"lint": "eslint ./", | ||
"fix": "eslint --fix ./", | ||
"pretest": "npm run lint", | ||
"precommit": "npm run test" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/dhoulb/blork.git" | ||
"eslintConfig": { | ||
"parserOptions": { | ||
"sourceType": "module", | ||
"ecmaVersion": 2017, | ||
"experimentalObjectRestSpread": true | ||
}, | ||
"extends": [ | ||
"eslint:recommended", | ||
"plugin:prettier/recommended" | ||
], | ||
"env": { | ||
"es6": true, | ||
"node": true, | ||
"jest": true | ||
}, | ||
"rules": { | ||
"eqeqeq": 2, | ||
"global-require": 2, | ||
"no-alert": 2, | ||
"no-caller": 2, | ||
"no-console": 2, | ||
"no-eval": 2, | ||
"no-extend-native": 2, | ||
"no-floating-decimal": 2, | ||
"no-implicit-globals": 2, | ||
"no-labels": 2, | ||
"no-loop-func": 2, | ||
"no-new-require": 2, | ||
"no-path-concat": 2, | ||
"no-useless-rename": 2, | ||
"no-var": 2, | ||
"no-shadow": 2, | ||
"prefer-const": 2, | ||
"prefer-spread": 2, | ||
"strict": 2, | ||
"valid-jsdoc": 2 | ||
} | ||
}, | ||
"prettier": { | ||
"tabWidth": 4, | ||
"useTabs": true, | ||
"printWidth": 120, | ||
"parser": "flow", | ||
"proseWrap": "never" | ||
}, | ||
"jest": { | ||
"coverageReporters": [ | ||
"text" | ||
], | ||
"collectCoverage": true, | ||
"coverageThreshold": { | ||
@@ -39,0 +78,0 @@ "global": { |
# Blork! Mini runtime type checking in Javascript | ||
[![Build Status](https://travis-ci.org/dhoulb/blork.svg?branch=master)](https://travis-ci.org/dhoulb/blork) | ||
[![Prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier) | ||
[![npm](https://img.shields.io/npm/dm/blork.svg)](https://www.npmjs.com/package/blork) | ||
A mini type checker for locking down the external edges of your code. Mainly for use in modules when you don't know who'll be using the code. Minimal boilerplate code keeps your functions hyper readable and lets them be their beautiful minimal best selves (...or something?) | ||
Everything is unit tested and everything has TypeScript types (if you're into that!). | ||
Blork is fully unit tested and 100% covered (if you're into that!). | ||
@@ -194,2 +196,24 @@ ## Installation | ||
### blork(): Create an independent instance of Blork | ||
To create an instance of Blork with an independent set of checkers (added with `add()`) and an independently set `throws()` error object, use the `blork()` function. | ||
This functionality is provided so you can ensure multiple versions of Blork in submodules of the same project don't interfere with each other, even if they have been (possibly purposefully) deduped in npm. | ||
```js | ||
import { blork } from 'blork'; | ||
// Create a new set of functions from Blork. | ||
const { check, add, throws } = blork(); | ||
// Set a new custom error on the new instance. | ||
throws(class CustomError extends TypeError); | ||
// Add a custom checker on the new instance. | ||
add("mychecker", v => v === "abc" || "Must be 'abc'"); | ||
// Try to use the custom checker. | ||
check("123", "mychecker"); // Throws CustomChecker("Must be 'abc' (received '123')") | ||
``` | ||
## Types | ||
@@ -196,0 +220,0 @@ |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
368
60362
6
21
878
1