Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

blork

Package Overview
Dependencies
Maintainers
1
Versions
56
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

blork - npm Package Compare versions

Comparing version 7.6.3 to 8.0.0

lib/functions/cause.js

69

lib/classes/Blorker.js

@@ -70,3 +70,3 @@ const ValueError = require("../errors/ValueError");

*/
checker(type) {
Blorker$checker(type) {
// Check args.

@@ -92,3 +92,3 @@ runChecker(this._checkers.string, type, "checker(): type", BlorkError);

*/
assert(assertion, description, prefix, error) {
Blorker$assert(assertion, description, prefix, error) {
// Check args.

@@ -114,3 +114,3 @@ runChecker(this._checkers.string, description, "check(): description", BlorkError);

*/
check(value, type, prefix, error) {
Blorker$check(value, type, prefix, error) {
// Check args.

@@ -135,3 +135,3 @@ if (prefix) runChecker(this._checkers.string, prefix, "check(): prefix", BlorkError);

*/
args(args, types, prefix, error) {
Blorker$args(args, types, prefix, error) {
// Check args.

@@ -144,3 +144,5 @@ runChecker(this._checkers.args, args, "args(): args", BlorkError);

// Recurse into each type.
types.forEach((t, i) => this._check(args[i], t, `${prefix || "arguments"}[${i}]`, error || this._error));
for (let i = 0; i < types.length; i++) {
this._check(args[i], types[i], `${prefix || "arguments"}[${i}]`, error || this._error);
}

@@ -164,3 +166,3 @@ // No excess arguments.

*/
add(name, checker, description, error) {
Blorker$add(name, checker, description, error) {
// Check args.

@@ -186,3 +188,3 @@ runChecker(this._checkers.kebab, name, "add(): name", BlorkError);

*/
throws(error) {
Blorker$throws(error) {
// Check args.

@@ -196,55 +198,2 @@ runChecker(this._checkers.function, error, "throws(): error", BlorkError);

/**
* Define object properties that are locked to their specific Blork types.
*
* The properties are readable, but only writable with values matching the initial type.
* This allows you to define objects with properties of guaranteed types.
*
* @param {object} object The object to define the property on.
* @param {object} props The new locked-down props to define on the property.
* @returns {void}
*/
props(object, props) {
// Check args.
runChecker(this._checkers.objectlike, object, "props(): object", BlorkError);
runChecker(this._checkers.object, props, "props(): props", BlorkError);
// Loop through every property in props.
Object.entries(props).forEach(([key, value]) => {
// Figure out the type from the value.
const type =
value instanceof Object
? // Object types do an 'instanceof' check, so must be an instance of the same object.
Object.getPrototypeOf(value).constructor
: // All other values use typeof value, e.g. "string", "number", "boolean", "symbol".
typeof value;
// Define the property.
Object.defineProperty(object, key, {
configurable: false,
enumerable: true,
// Return the current value.
get: () => value,
// Arrow function so that this refers to the _outer_ this.
set: v => {
// Figure out prefix.
// Either ".myProp" or "MyRandomClass.myProp"
const constructor = Object.getPrototypeOf(object).constructor.name;
const prefix = `${constructor.name}.${key}`;
// Check the value.
this._check(v, type, prefix, this._error);
// Update the value.
value = v;
}
});
});
// Return object (for chaining etc).
return object;
}
/**
* Find the checker corresponding to a string.

@@ -251,0 +200,0 @@ *

const format = require("../functions/format");
const cause = require("../functions/cause");
const { EMPTY } = require("../constants");

@@ -6,3 +7,5 @@

* ValueError
*
* An error type that includes standardised formatting and prefixes.
* ValueError semantically means "there is a problem with a value that has been passed into the current function".
*/

@@ -12,14 +15,34 @@ class ValueError extends TypeError {

* Constructor.
* @param {string} message Message describing what went wrong, e.g. "Must be a string"
* @param {mixed} value A value to debug shown at the end of the message, e.g. "Must be string (received 123)"
* @param {string} prefix=undefined An optional prefix for the message e.g. the function name or the name of the value, e.g. "name: Must be string (received 123)"
* @param {string} message="Invalid value" Message describing what went wrong, e.g. "Must be a string"
* @param {mixed} value=EMPTY A value to debug shown at the end of the message, e.g. "Must be string (received 123)"
* @param {string} prefix="" An optional prefix for the message e.g. the function name or the name of the value, e.g. "name: Must be string (received 123)"
*/
constructor(message = "Invalid value", value = EMPTY, prefix = "") {
// Save message through TypeError.
// We format the `.message` property itself (rather than on the fly in `.toString()`) because Jest and others call it directly.
super(format(message, value, prefix));
constructor(message, value, prefix) {
// Defaults.
if (arguments.length < 3) prefix = "";
if (arguments.length < 2) value = EMPTY;
if (arguments.length < 1) message = "Invalid value";
// Save parts separately.
// Super.
super("******");
// Pin down the cause of the error.
// This looks through the Error.stack and finds where e.g. check() or args() was actually called.
const frame = cause(this.stack);
/* istanbul ignore else */
if (frame) {
// Prepend the caller function name to the prefix, e.g. "name" → "MyClass.myFunc(): name"
/* istanbul ignore else */
if (frame.function) prefix = prefix ? `${frame.function}: ${prefix}` : frame.function;
// Update file, line, column.
this.fileName = frame.file;
this.lineNumber = frame.line;
this.stack = frame.stack;
}
// Save everything.
this.message = format(message, value, prefix);
this.prefix = prefix;
this.reason = message;
this.stack = this.stack.replace("******", this.message);
if (value !== EMPTY) this.value = value;

@@ -26,0 +49,0 @@

@@ -6,2 +6,3 @@ const ValueError = require("./errors/ValueError");

const format = require("./functions/format");
const destack = require("./functions/destack");
const { CLASS, KEYS, VALUES, EMPTY } = require("./constants");

@@ -16,2 +17,3 @@

module.exports.debug = debug;
module.exports.destack = destack;
module.exports.BlorkError = BlorkError;

@@ -18,0 +20,0 @@ module.exports.ValueError = ValueError;

@@ -18,10 +18,9 @@ const Blorker = require("../classes/Blorker");

return {
assert: blorker.assert.bind(blorker),
check: blorker.check.bind(blorker),
args: blorker.args.bind(blorker),
add: blorker.add.bind(blorker),
checker: blorker.checker.bind(blorker),
throws: blorker.throws.bind(blorker),
props: blorker.props.bind(blorker)
assert: blorker.Blorker$assert.bind(blorker),
check: blorker.Blorker$check.bind(blorker),
args: blorker.Blorker$args.bind(blorker),
add: blorker.Blorker$add.bind(blorker),
checker: blorker.Blorker$checker.bind(blorker),
throws: blorker.Blorker$throws.bind(blorker)
};
};

@@ -139,7 +139,7 @@ // Constants.

if (typeof value.name === "string" && value.name.length > 0) {
// Named function, e.g. myFunc()
// Named function, e.g. "myFunc()"
return `${value.name}()`;
} else {
// Unnamed function, e.g. function()
return "anonymous function()";
// Unnamed function, e.g. "function ()"
return "function ()";
}

@@ -146,0 +146,0 @@ }

@@ -13,3 +13,7 @@ const { EMPTY } = require("../constants");

*/
function format(message, value = EMPTY, prefix = "") {
function format(message, value, prefix) {
// Defaults.
if (arguments.length < 3) prefix = "";
if (arguments.length < 2) value = EMPTY;
// e.g. MyPrefix: Must be string (received 123)

@@ -16,0 +20,0 @@ return (

@@ -65,3 +65,3 @@ const BlorkError = require("./errors/BlorkError");

// Loop through and call each checker.
for (const c of ands) if (!c(v)) return false; // Fail.
for (let i = 0; i < ands.length; i++) if (!ands[i](v)) return false; // Fail.
return true; // Otherwise pass.

@@ -95,3 +95,3 @@ };

// Loop through and call each checker.
for (const c of ors) if (c(v)) return true; // Pass.
for (let i = 0; i < ors.length; i++) if (ors[i](v)) return true; // Pass.
return false; // Otherwise fail.

@@ -98,0 +98,0 @@ };

{
"name": "blork",
"description": "Blork! Mini runtime type checking in Javascript",
"version": "7.6.3",
"version": "8.0.0",
"license": "0BSD",

@@ -6,0 +6,0 @@ "author": "Dave Houlbrooke <dave@shax.com>",

@@ -9,3 +9,3 @@ # Blork! Mini runtime type checking in Javascript

Blork is fully unit tested and 100% covered (if you're into that!).
Blork is fully unit tested and 100% covered (if you're into that!). Heaps of love has been put into the _niceness_ and consistency of error messages, so hopefully you'll enjoy that too.

@@ -47,6 +47,6 @@ ## Installation

// Call with invalid args.
myFunc(123); // Throws ValueError "arguments[0]: Must be string (received 123)"
myFunc("abc", "abc"); // Throws ValueError "arguments[1]: Must be number (received "abc")"
myFunc(); // Throws ValueError "arguments[0]: Must be string (received undefined)"
myFunc("abc", 123, true); // Throws ValueError "arguments: Too many arguments (expected 2) (received 3)"
myFunc(123); // Throws ValueError "myFunc(): arguments[0]: Must be string (received 123)"
myFunc("abc", "abc"); // Throws ValueError "myFunc(): arguments[1]: Must be number (received "abc")"
myFunc(); // Throws ValueError "myFunc(): arguments[0]: Must be string (received undefined)"
myFunc("abc", 123, true); // Throws ValueError "myFunc(): arguments: Too many arguments (expected 2) (received 3)"
```

@@ -93,4 +93,10 @@

// Check all the options with a literal type (note that keepAlive is optional).
check(options, { name: "string", required: "boolean", keepAlive: "number?" });
check(options, { name: "string", required: "boolean", keepAlive: "number?" }, "options");
}
// Checks that pass.
myFunc({ name: "Dog", required: true }); // No error.
// Checks that fail.
myFunc({ name: 123, required: false }); // Throws ValueError "myFunc(): options.name: Must be string (received 123)"
```

@@ -249,3 +255,3 @@

// Fails.
myFunc("A dog sits over there"); // Throws ValueError "arguments[1]: Must be string containing "cat" (received "A dog sits over there")"
myFunc("A dog sits over there"); // Throws ValueError "myFunc(): arguments[1]: Must be string containing "cat" (received "A dog sits over there")"
```

@@ -292,46 +298,2 @@

### props(): Define Blork-checked object properties
The `props()` function can define an object properties (like `Object.defineProperties()`) that are readable and writable, BUT the value must always match the type it was initially defined with.
This allows you to create objects with properties that have a guaranteed type. This makes your object more robust and removes the need to check the type of the property before using it.
`props()` accepts two arguments:
1. `object` The object to define the property on
2. `props` A set of properties to define on the object and lock down
```js
import { prop } from "blork";
// Make an object.
const obj = {};
// Define typed properties on the object.
props(obj, {
"name": "Mel",
"coords": { lat: 0, lng: 0 },
"map": new Map()
});
// Setting the value to an allowed type is fine.
obj.name = "John";
obj.coords = { lat: 28.20, lng: 12.00 };
obj.map = new Map();
// Setting the value to a disallowed type is not fine.
obj.name = 123; // Throws TypeError "name: Must be string (received 123)"
obj.coords = 123; // Throws TypeError "coords: Must be plain object (received 123)"
obj.coords = { lat: "abc", lng: 0 }; // Throws TypeError "coords.lat: Must be number (received "abc")"
obj.map = new Set(); // Throws TypeError "map: must be instance of Map (received Set)
```
```js
import { prop } from "blork";
// Make an object.
const obj = {};
```
### debug(): Debug any value as a string.

@@ -795,2 +757,6 @@

- 8.0.0
- Remove `props()` functionality (bloat)
- Prepend function name to `ValueError` errors, e.g. `MyClass.myFunc(): Must be string...`
- Add `destack()` method that parses `Error.stack` across major browsers
- 7.6.0

@@ -797,0 +763,0 @@ - Allow `prefix` and `error` arguments for `check()` and `args()`

@@ -11,4 +11,4 @@ const BlorkError = require("../../lib/errors/BlorkError");

test("Return correct error with message only", () => {
expect(new BlorkError("Message")).toHaveProperty("message", "Message");
expect(new BlorkError("Message")).toHaveProperty("prefix", "");
expect(new BlorkError("Message")).toHaveProperty("message", "Object.test(): Message");
expect(new BlorkError("Message")).toHaveProperty("prefix", "Object.test()");
expect(new BlorkError("Message")).toHaveProperty("reason", "Message");

@@ -18,4 +18,4 @@ expect(new BlorkError("Message")).not.toHaveProperty("value");

test("Return correct error with message and value", () => {
expect(new BlorkError("Message", 123)).toHaveProperty("message", "Message (received 123)");
expect(new BlorkError("Message", 123)).toHaveProperty("prefix", "");
expect(new BlorkError("Message", 123)).toHaveProperty("message", "Object.test(): Message (received 123)");
expect(new BlorkError("Message", 123)).toHaveProperty("prefix", "Object.test()");
expect(new BlorkError("Message", 123)).toHaveProperty("reason", "Message");

@@ -25,4 +25,7 @@ expect(new BlorkError("Message", 123)).toHaveProperty("value", 123);

test("Return correct error with message, value, and prefix", () => {
expect(new BlorkError("Message", 123, "Prefix")).toHaveProperty("message", "Prefix: Message (received 123)");
expect(new BlorkError("Message", 123, "Prefix")).toHaveProperty("prefix", "Prefix");
expect(new BlorkError("Message", 123, "Prefix")).toHaveProperty(
"message",
"Object.test(): Prefix: Message (received 123)"
);
expect(new BlorkError("Message", 123, "Prefix")).toHaveProperty("prefix", "Object.test(): Prefix");
expect(new BlorkError("Message", 123, "Prefix")).toHaveProperty("reason", "Message");

@@ -29,0 +32,0 @@ expect(new BlorkError("Message", 123, "Prefix")).toHaveProperty("value", 123);

@@ -7,4 +7,4 @@ const { ValueError, EMPTY } = require("../../lib/exports");

expect(new ValueError()).toHaveProperty("name", "ValueError");
expect(new ValueError()).toHaveProperty("message", "Invalid value");
expect(new ValueError()).toHaveProperty("prefix", "");
expect(new ValueError()).toHaveProperty("message", "Object.test(): Invalid value");
expect(new ValueError()).toHaveProperty("prefix", "Object.test()");
expect(new ValueError()).toHaveProperty("reason", "Invalid value");

@@ -15,20 +15,47 @@ expect(new ValueError()).not.toHaveProperty("value");

expect(new ValueError("Message")).toHaveProperty("name", "ValueError");
expect(new ValueError("Message")).toHaveProperty("message", "Message");
expect(new ValueError("Message")).toHaveProperty("prefix", "");
expect(new ValueError("Message")).toHaveProperty("message", "Object.test(): Message");
expect(new ValueError("Message")).toHaveProperty("prefix", "Object.test()");
expect(new ValueError("Message")).toHaveProperty("reason", "Message");
expect(new ValueError("Message")).not.toHaveProperty("value");
function abc() {
return new ValueError("Message");
}
expect(abc()).toHaveProperty("name", "ValueError");
expect(abc()).toHaveProperty("message", "abc(): Message");
expect(abc()).toHaveProperty("prefix", "abc()");
expect(abc()).toHaveProperty("reason", "Message");
expect(abc()).not.toHaveProperty("value");
});
test("Return correct error with message and value", () => {
expect(new ValueError("Message", 123)).toHaveProperty("name", "ValueError");
expect(new ValueError("Message", 123)).toHaveProperty("message", "Message (received 123)");
expect(new ValueError("Message", 123)).toHaveProperty("prefix", "");
expect(new ValueError("Message", 123)).toHaveProperty("message", "Object.test(): Message (received 123)");
expect(new ValueError("Message", 123)).toHaveProperty("prefix", "Object.test()");
expect(new ValueError("Message", 123)).toHaveProperty("reason", "Message");
expect(new ValueError("Message", 123)).toHaveProperty("value", 123);
function abc() {
return new ValueError("Message", 123);
}
expect(abc()).toHaveProperty("name", "ValueError");
expect(abc()).toHaveProperty("message", "abc(): Message (received 123)");
expect(abc()).toHaveProperty("prefix", "abc()");
expect(abc()).toHaveProperty("reason", "Message");
expect(abc()).toHaveProperty("value", 123);
});
test("Return correct error with message, value, and prefix", () => {
expect(new ValueError("Message", 123, "Prefix")).toHaveProperty("name", "ValueError");
expect(new ValueError("Message", 123, "Prefix")).toHaveProperty("message", "Prefix: Message (received 123)");
expect(new ValueError("Message", 123, "Prefix")).toHaveProperty("prefix", "Prefix");
expect(new ValueError("Message", 123, "Prefix")).toHaveProperty(
"message",
"Object.test(): Prefix: Message (received 123)"
);
expect(new ValueError("Message", 123, "Prefix")).toHaveProperty("prefix", "Object.test(): Prefix");
expect(new ValueError("Message", 123, "Prefix")).toHaveProperty("reason", "Message");
expect(new ValueError("Message", 123, "Prefix")).toHaveProperty("value", 123);
function abc() {
return new ValueError("Message", 123, "Prefix");
}
expect(abc()).toHaveProperty("name", "ValueError");
expect(abc()).toHaveProperty("message", "abc(): Prefix: Message (received 123)");
expect(abc()).toHaveProperty("prefix", "abc(): Prefix");
expect(abc()).toHaveProperty("reason", "Message");
expect(abc()).toHaveProperty("value", 123);
});

@@ -35,0 +62,0 @@ test("Does not show value in message if value is EMPTY", () => {

@@ -45,9 +45,11 @@ const { args, BlorkError, ValueError } = require("../lib/exports");

const argsObj = { "0": true, "1": true, "2": true, length: 3 };
expect(() => args(argsObj, [Boolean, Boolean])).toThrow(/^arguments/);
expect(() => args(argsObj, [String, String, String])).toThrow(/^arguments/);
// Still includes "expect(): " because we use the stack to calculate the function prefix
expect(() => args(argsObj, [Boolean, Boolean])).toThrow(/^expect\(\): arguments:/);
expect(() => args(argsObj, [String, String, String])).toThrow(/^expect\(\): arguments\[0\]:/);
});
test("Error prefix can be altered by setting prefix argument", () => {
const argsObj = { "0": true, "1": true, "2": true, length: 3 };
expect(() => args(argsObj, [Boolean, Boolean], "myprefix")).toThrow(/^myprefix/);
expect(() => args(argsObj, [String, String, String], "myprefix")).toThrow(/^myprefix/);
// Still includes "expect(): " because we use the stack to calculate the function prefix
expect(() => args(argsObj, [Boolean, Boolean], "myprefix")).toThrow(/^expect\(\): myprefix:/);
expect(() => args(argsObj, [String, String, String], "myprefix")).toThrow(/^expect\(\): myprefix\[0\]:/);
});

@@ -54,0 +56,0 @@ });

@@ -24,6 +24,8 @@ const { assert, BlorkError, ValueError } = require("../lib/exports");

test("Error prefix defaults to no prefix", () => {
expect(() => assert(false, "be assertively true")).toThrow(/^Must/);
// Still includes "expect(): " because we use the stack to calculate the function prefix
expect(() => assert(false, "be assertively true")).toThrow(/^expect\(\): Must/);
});
test("Error prefix can be altered by setting prefix argument", () => {
expect(() => assert(false, "be assertively true", "myprefix")).toThrow(/^myprefix/);
// Still includes "expect(): " because we use the stack to calculate the function prefix
expect(() => assert(false, "be assertively true", "myprefix")).toThrow(/^expect\(\): myprefix/);
});

@@ -30,0 +32,0 @@ });

@@ -181,2 +181,3 @@ const BlorkError = require("../lib/errors/BlorkError");

expect(() => check(1, "string | string & string")).toThrow(/Must be \(string or string\) and string/);
expect(() => check(1, "{ string } | null")).toThrow(/Must be \(plain object containing string\) or null/);
});

@@ -183,0 +184,0 @@ });

@@ -32,6 +32,8 @@ const { check, BlorkError, ValueError } = require("../lib/exports");

test("Error prefix defaults to no prefix", () => {
expect(() => check(123, String)).toThrow(/^Must/);
// Still includes "expect(): " because we use the stack to calculate the function prefix
expect(() => check(123, String)).toThrow(/^expect\(\): Must/);
});
test("Error prefix can be altered by setting prefix argument", () => {
expect(() => check(123, String, "myprefix")).toThrow(/^myprefix/);
// Still includes "expect(): " because we use the stack to calculate the function prefix
expect(() => check(123, String, "myprefix")).toThrow(/^expect\(\): myprefix/);
});

@@ -38,0 +40,0 @@ });

@@ -70,3 +70,3 @@ const { debug } = require("../lib/exports");

test("Return correct debug string for functions", () => {
expect(debug(function() {})).toBe("anonymous function()");
expect(debug(function() {})).toBe("function ()");
expect(debug(function dog() {})).toBe("dog()");

@@ -73,0 +73,0 @@ });

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc