diff --git a/.eslintrc b/.eslintrc
index 11643ef..f39f317 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,12 +1,11 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
- "plugins": [
- "@typescript-eslint"
- ],
+ "plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
- "plugin:@typescript-eslint/recommended"
+ "plugin:@typescript-eslint/recommended",
+ "prettier"
]
}
diff --git a/.gitattributes b/.gitattributes
index dfe0770..e7c1d93 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,2 +1,2 @@
# Auto detect text files and perform LF normalization
-* text=auto
+* text eol=lf
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 0000000..b91f820
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,11 @@
+{
+ "overrides": [
+ {
+ "files": ["*.*ts?(x)", "*.js?(x)"],
+ "options": {
+ "tabWidth": 4,
+ "singleQuote": true
+ }
+ }
+ ]
+}
diff --git a/README.md b/README.md
index 0d682fc..ca4550f 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
# procedure.js 🔗
+
The simple RPC framework for Node.js.
[](https://npmjs.org/package/@procedure-rpc/procedure.js "View procedure.js on npm") [](https://npmjs.org/package/@procedure-rpc/procedure.js "View procedure.js on npm") [](https://procedure-rpc.github.io/procedure.js "Read the documentation on Github Pages") [](https://codecov.io/gh/procedure-rpc/procedure.js "View code coverage on Codecov") [](https://www.codefactor.io/repository/github/procedure-rpc/procedure.js "View code quality on CodeFactor") [](https://github.com/toebeann/signals/blob/main/LICENSE "View the license on GitHub")
@@ -12,20 +13,21 @@ The simple RPC framework for Node.js.
## Description
+
A lightweight alternative to the boilerplate-heavy gRPC, or spinning up a HTTP server and REST API. Procedure links your independent applications and services with as little code as possible, so that you can just focus on building your app!
```js
// my-app/index.js
// a simple procedure which returns the square of a given number
-const procedure = new Procedure((n) => n ** 2).bind('tcp://*:5000');
+const procedure = new Procedure((n) => n ** 2).bind("tcp://*:5000");
```
```js
// some-other-app/index.js
// calling the procedure to find the square of 8
-let squared = await call('tcp://localhost:5000', 8);
+let squared = await call("tcp://localhost:5000", 8);
console.log(squared); // outputs 64
```
@@ -38,6 +40,7 @@ With [implementations in multiple languages](#language-implementations), applica
-->
## Table of contents
+
- [procedure.js 🔗](#procedurejs-)
- [Description](#description)
- [Table of contents](#table-of-contents)
@@ -67,67 +70,83 @@ With [implementations in multiple languages](#language-implementations), applica
## Install
### [npm](https://www.npmjs.com/package/@procedure-rpc/procedure.js "npm is a package manager for JavaScript")
+
`npm i @procedure-rpc/procedure.js`
## Usage
+
With Procedure, setting up your function to be called from another process (whether remote or local) is remarkably simple:
+
```js
-import Procedure from '@procedure-rpc/procedure.js';
+import Procedure from "@procedure-rpc/procedure.js";
const procedure = new Procedure((n) => n ** 2);
-procedure.bind('tcp://*:5000');
+procedure.bind("tcp://*:5000");
```
And calling it is just as easy:
+
```js
-import { call } from '@procedure-rpc/procedure.js';
+import { call } from "@procedure-rpc/procedure.js";
let x = 8;
-let xSquared = await call('tcp://localhost:5000', x);
+let xSquared = await call("tcp://localhost:5000", x);
console.log(xSquared); // outputs 64
console.log(typeof xSquared); // outputs 'number'
```
### `async`/`await`
+
Asynchronous functions are fully supported:
+
```js
-import { ProcedureExcecutionError } from '@procedure-rpc/procedure.js/errors';
+import { ProcedureExcecutionError } from "@procedure-rpc/procedure.js/errors";
const procedure = new Procedure(async () => {
- const response = await fetch('https://catfact.ninja/fact');
- if (response.ok) {
- return (await response.json()).fact;
- } else {
- throw new ProcedureExecutionError(`${response.status}: ${response.statusText}`);
- }
+ const response = await fetch("https://catfact.ninja/fact");
+ if (response.ok) {
+ return (await response.json()).fact;
+ } else {
+ throw new ProcedureExecutionError(
+ `${response.status}: ${response.statusText}`
+ );
+ }
});
-procedure.bind('tcp://127.0.0.1:8888');
+procedure.bind("tcp://127.0.0.1:8888");
```
### Parameters and return types
+
Parameter and return types can be anything supported by the [msgpack](https://github.com/msgpack/msgpack-javascript) serialization format, which covers much of JavaScript by default, and you can handle unsupported types with [Extension Types](https://github.com/msgpack/msgpack-javascript#extension-types). We generally recommend sticking to [PODs](https://en.wikipedia.org/wiki/Passive_data_structure "plain old data objects"). It is possible to pass more complex types around in many cases - but note that they will be passed by value, [not by reference](#pass-by-reference).
Procedure supports a single parameter, or none. We considered supporting multiple parameters, but this increases the complexity of the design and leads to potentially inconsistent APIs for different language implementations, while multiple parameters can easily be simulated through the use of [PODs](https://en.wikipedia.org/wiki/Passive_data_structure "plain old data objects") (e.g. object literals, property bags) or arrays in virtually any programming language.
If you have existing functions with multiple parameters which you want to expose as procedures, wrapping them is trivial:
+
```js
function myFunction(a, b, c) {
- return a + b * c;
+ return a + b * c;
}
-const procedure = new Procedure(params => myFunction(...params))
- .bind('tcp://*:30666');
+const procedure = new Procedure((params) => myFunction(...params)).bind(
+ "tcp://*:30666"
+);
```
+
Which can then be called like so:
+
```js
-call('tcp://localhost:30666', [1, 2, 3]);
+call("tcp://localhost:30666", [1, 2, 3]);
```
+
For functions where you have optional parameters, it might make more sense to use object literals/property bags instead of arrays.
Functions which accept multiple parameters where only the first is required (or none) will work as is, but you will only be able to pass the first parameter via `call`.
#### A note about `null` and `undefined`
+
##### Optional parameter support
+
In the JavaScript implementation of msgpack, [`undefined` is mapped to `null`](https://github.com/msgpack/msgpack-javascript#messagepack-mapping-table). This means that all `undefined` values will be decoded as `null`, and there is no way to differentiate between the two.
This causes an issue for procedures which accept an optional parameter, as in most implementations of optional parameters in JavaScript, only `undefined` is coerced into a default value.
@@ -137,61 +156,74 @@ It also means that procedures with no return value will evaluate to `null` inste
To handle these inconsistencies, we coerce a msgpack decoded `null` to `undefined`. This does not affect the properties of objects - they will still be evaluated as `null` when they were either `null` or `undefined`.
To disable this behavior, you can [set `optionalParameterSupport` to `false`](https://procedure-rpc.github.io/procedure.js/interfaces/procedure.ProcedureOptions.html#optionalParameterSupport) for either procedure definitions or calls, or both:
+
```js
const procedure = new Procedure(x => { ... }, { optionalParameterSupport: false })
.bind('tcp://*:54321');
```
```js
-await call('tcp://*:54321', x, { optionalParameterSupport: false });
+await call("tcp://*:54321", x, { optionalParameterSupport: false });
```
+
Note that disabling at the definition will not affect the return value, and disabling at the call will not affect the input parameter.
##### `null` and `undefined` properties
+
For objects, we do not coerce `null` properties to `undefined`. Instead, we leave them as is, but properties with the value of `undefined` are ignored, thereby allowing those properties to be evaluated as `undefined` at the other end, while `null` properties remain `null`.
This operation adds some overhead, and any code that relies on the presence of a property to infer meaning may not work as expected, e.g. `if ('prop' in obj)`.
To disable this behavior, you can [set `ignoreUndefinedProperties` to `false`](https://procedure-rpc.github.io/procedure.js/interfaces/procedure.ProcedureOptions.html#ignoreUndefinedProperties) for either procedure definitions or calls, or both:
+
```js
const procedure = new Procedure(x => { ... }, { ignoreUndefinedProperties: false }
.bind('tcp://*:54321');
```
```js
-await call('tcp://*:54321', x, { ignoreUndefinedProperties: false });
+await call("tcp://*:54321", x, { ignoreUndefinedProperties: false });
```
+
Note that disabling at the definition will not affect the return value, and disabling at the call will not affect the input parameter.
#### Pass by reference?
-It is **impossible** to pass by reference with Procedure. All data is encoded and then sent across the wire, similar to what happens when a REST API responds to a request by sending back a JSON string/file. You can parse that JSON into an object and access its data, but you only have a *copy* of the data that lives on the server.
+
+It is **impossible** to pass by reference with Procedure. All data is encoded and then sent across the wire, similar to what happens when a REST API responds to a request by sending back a JSON string/file. You can parse that JSON into an object and access its data, but you only have a _copy_ of the data that lives on the server.
For example, if you were to implement the following procedure:
+
```js
-const procedure = new Procedure(x => x.foo = 'bar')
- .bind('tcp://*:33333');
+const procedure = new Procedure((x) => (x.foo = "bar")).bind("tcp://*:33333");
```
+
And then call it like so:
+
```js
let obj = { foo: 123 };
-await call('tcp://*:33333', obj);
+await call("tcp://*:33333", obj);
console.log(obj); // outputs '{ foo: 123 }'
```
-The `obj` object would remain unchanged, because the procedure is acting on a *clone* of the object, not the object itself. First, the object is encoded for transmission by msgpack, then sent across the wire by nanomsg, and finally decoded by msgpack at the other end into a brand new object.
+
+The `obj` object would remain unchanged, because the procedure is acting on a _clone_ of the object, not the object itself. First, the object is encoded for transmission by msgpack, then sent across the wire by nanomsg, and finally decoded by msgpack at the other end into a brand new object.
### Error handling
+
When unhandled exceptions occur during execution of a procedure, the procedure safely passes an error message back to be thrown at the callsite:
+
```js
const procedure = new Procedure((n) => n ** 2);
-procedure.bind('tcp://*:5000');
+procedure.bind("tcp://*:5000");
```
+
```js
-let x = { foo: 'bar' };
-let xSquared = await call('tcp://localhost:5000', x);
+let x = { foo: "bar" };
+let xSquared = await call("tcp://localhost:5000", x);
// throws ProcedureExecutionError: An unhandled exception was thrown during procedure execution.
```
There are a number of custom ProcedureErrors, all relating to a specific class of error, e.g.
+
- the procedure was not found at the endpoint,
- the request timed out while waiting for a response,
- the request was cancelled by the client,
@@ -199,41 +231,53 @@ There are a number of custom ProcedureErrors, all relating to a specific class o
- etc.
#### Custom error messages
+
In the event that you want to expose more detailed information back to the caller when an error occurs, you can simply throw a ProcedureError yourself:
+
```js
-import { ProcedureExecutionError } from '@procedure-rpc/procedure.js/errors';
-
-const procedure = new Procedure(n => {
- if (typeof n !== 'number') {
- throw new ProcedureExecutionError(`Expected n to be a number, got '${typeof n}'`);
- }
- return n ** 2;
-}).bind('tcp://*:5000');
+import { ProcedureExecutionError } from "@procedure-rpc/procedure.js/errors";
+
+const procedure = new Procedure((n) => {
+ if (typeof n !== "number") {
+ throw new ProcedureExecutionError(
+ `Expected n to be a number, got '${typeof n}'`
+ );
+ }
+ return n ** 2;
+}).bind("tcp://*:5000");
```
+
```js
-let x = { foo: 'bar' };
-let xSquared = await call('tcp://localhost:5000', x);
+let x = { foo: "bar" };
+let xSquared = await call("tcp://localhost:5000", x);
// throws ProcedureExecutionError: Expected n to be a number, got 'object'
```
#### Custom error data
+
You can optionally pass an object into the constructor of a ProcedureError and it will be attached to the `data` property of the thrown error:
+
```js
-import { ProcedureExecutionError } from '@procedure-rpc/procedure.js/errors';
-
-const procedure = new Procedure(n => {
- if (typeof n !== 'number') {
- throw new ProcedureExecutionError(`Expected n to be a number, got '${typeof n}'`, { n });
- }
- return n ** 2;
-}).bind('tcp://*:5000');
+import { ProcedureExecutionError } from "@procedure-rpc/procedure.js/errors";
+
+const procedure = new Procedure((n) => {
+ if (typeof n !== "number") {
+ throw new ProcedureExecutionError(
+ `Expected n to be a number, got '${typeof n}'`,
+ { n }
+ );
+ }
+ return n ** 2;
+}).bind("tcp://*:5000");
```
+
```js
-let x = { foo: 'bar' }, xSquared;
+let x = { foo: "bar" },
+ xSquared;
try {
- xSquared = await call('tcp://localhost:5000', x);
+ xSquared = await call("tcp://localhost:5000", x);
} catch (e) {
- console.error(e?.name, '-', e?.message, e?.data);
+ console.error(e?.name, "-", e?.message, e?.data);
}
// outputs ProcedureExecutionError - Expected n to be a number, got 'object' {
// n: {
@@ -243,9 +287,11 @@ try {
```
## API reference
+
The full API reference for procedure.js is [available on GitHub Pages](https://procedure-rpc.github.io/procedure.js).
### Quick links
+
- [Initializing a procedure](https://procedure-rpc.github.io/procedure.js/classes/index.Procedure.html#constructor)
- [Options](https://procedure-rpc.github.io/procedure.js/interfaces/index.ProcedureDefinitionOptions.html)
- [Binding a procedure to an endpoint](https://procedure-rpc.github.io/procedure.js/classes/index.Procedure.html#bind)
@@ -253,14 +299,19 @@ The full API reference for procedure.js is [available on GitHub Pages](https://p
- [Options](https://procedure-rpc.github.io/procedure.js/interfaces/index.ProcedureCallOptions.html)
## Transports: More than just TCP!
+
The examples in this readme all use TCP to demonstrate the most common use case for RPC. However, Procedure is built on top of [nanomsg](https://nanomsg.org/), which means it supports all of the same transports that nanomsg does:
### INPROC: intraprocess
+
Call functions between threads or modules of the same process.
+
- `inproc://foobar`
### IPC: intra/interprocess
+
Call functions between different processes on the same host.
+
- `ipc://foobar.ipc`
- `ipc:///tmp/test.ipc`
- `ipc://my-app/my-procedure`
@@ -270,32 +321,39 @@ On POSIX compliant systems (ubuntu, macOS, etc.), UNIX domain sockets are used a
On Windows, named pipes are used and IPC addresses are arbitrary case-insensitive strings containing any characters except backslash (`\`).
### TCP: intra/inter-network over TCP/IP
-Call functions between processes across TCP with support for IPv4 and IPv6 addresses and DNS names*.
+
+Call functions between processes across TCP with support for IPv4 and IPv6 addresses and DNS names\*.
+
- `tcp://*:80`
- `tcp://192.168.0.5:5600`
-- `tcp://localhost:33000`*
+- `tcp://localhost:33000`\*
TLS (`tcp+tls://`) is not currently supported.
-_* DNS names are only supported when calling a procedure, not when defining. _
+_\* DNS names are only supported when calling a procedure, not when defining. _
### WS: intra/inter-network over WebSockets
-Call functions between processes across WebSockets over TCP with support for both IPv4 and IPv6 addresses and DNS names*.
+
+Call functions between processes across WebSockets over TCP with support for both IPv4 and IPv6 addresses and DNS names\*.
+
- `ws://*`
- `ws://127.0.0.1:8080`
-- `ws://example.com`*
+- `ws://example.com`\*
TLS (`wss://`) is not currently supported.
-_* DNS names are only supported when calling a procedure, not when defining. _
+_\* DNS names are only supported when calling a procedure, not when defining. _
## Handling breaking changes to your procedures
+
Procedure has no way of knowing what the parameter or return types of the procedure at the other end of the call will be. If you rewrite a procedure to return a different type or to accept a different parameter type, you will only get errors at runtime, not at compile time.
Therefore, if you are developing procedures for public consumption, be mindful of the fact that **breaking changes on the same endpoint will result in unhappy consumers!**
If you do need to make breaking changes to a procedure, it is recommended to either:
+
- implement the breaking changes on a new endpoint, while keeping the original available:
+
```js
myFunction(x) {
return isNaN(x); // return boolean indicating whether x is NaN
@@ -316,10 +374,12 @@ If you do need to make breaking changes to a procedure, it is recommended to eit
```
```js
- const v1Result = await call('tcp://localhost:33000'); // returns false
- const v2Result = await call('tcp://localhost:33001'); // returns undefined
+ const v1Result = await call("tcp://localhost:33000"); // returns false
+ const v2Result = await call("tcp://localhost:33001"); // returns undefined
```
+
- use a parameter or property to specify a version modifier, defaulting to the original when unspecified:
+
```js
myFunction(x) {
return isNaN(x); // return boolean indicating whether x is NaN
@@ -345,13 +405,14 @@ If you do need to make breaking changes to a procedure, it is recommended to eit
```
```js
- const v1Result = await call('tcp://localhost:33000'); // returns false
- const v2Result = await call('tcp://localhost:33000', { version: 2 }); //returns undefined
+ const v1Result = await call("tcp://localhost:33000"); // returns false
+ const v2Result = await call("tcp://localhost:33000", { version: 2 }); //returns undefined
```
You may prefer to use a [semver](https://www.npmjs.com/package/semver) compatible string for versioning.
## Language implementations
+
As Procedure is designed around nanomsg and msgpack, it can be implemented in any language that has both a nanomsg binding and a msgpack implementation.
Presently, the only official implementation of Procedure is procedure.js for Node.js, but a .NET implementation written in C# and a stripped-down browser library for calling procedures via the [WS transport](#ws-intrainter-network-over-websockets) are currently being worked on.
@@ -420,4 +481,5 @@ Procedure is currently implemented in the following languages:
If you would like to contribute a Procedure implementation in another language, please feel free! Create a GitHub repository for the language implementation and open an issue with us once it's ready for review! 💜
## License
+
procedure.js is licensed under [MIT](https://github.com/procedure-rpc/procedure.js/blob/main/LICENSE) © 2022 Tobey Blaber.
diff --git a/jest.config.json b/jest.config.json
index 4053fab..3ac468c 100644
--- a/jest.config.json
+++ b/jest.config.json
@@ -1,13 +1,7 @@
{
"preset": "ts-jest",
"testEnvironment": "node",
- "coverageReporters": [
- "html",
- "text",
- "cobertura",
- "json",
- "lcovonly"
- ],
+ "coverageReporters": ["html", "text", "cobertura", "json", "lcovonly"],
"coverageThreshold": {
"global": {
"statements": 90,
diff --git a/package-lock.json b/package-lock.json
index 923eacd..5952bbd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -31,7 +31,9 @@
"@typescript-eslint/eslint-plugin": "^5.30.6",
"@typescript-eslint/parser": "^5.30.6",
"eslint": "^8.20.0",
+ "eslint-config-prettier": "^8.5.0",
"jest": "^28.1.3",
+ "prettier": "^2.7.1",
"ts-jest": "^28.0.8",
"typed-emitter": "^2.1.0",
"typedoc": "^0.23.10",
@@ -2248,6 +2250,18 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/eslint-config-prettier": {
+ "version": "8.5.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz",
+ "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==",
+ "dev": true,
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
"node_modules/eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
@@ -4114,6 +4128,21 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/prettier": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
+ "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
"node_modules/pretty-format": {
"version": "28.1.3",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz",
@@ -6745,6 +6774,13 @@
}
}
},
+ "eslint-config-prettier": {
+ "version": "8.5.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz",
+ "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==",
+ "dev": true,
+ "requires": {}
+ },
"eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
@@ -8135,6 +8171,12 @@
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true
},
+ "prettier": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
+ "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
+ "dev": true
+ },
"pretty-format": {
"version": "28.1.3",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz",
diff --git a/package.json b/package.json
index 5b061f5..ec243a9 100644
--- a/package.json
+++ b/package.json
@@ -22,9 +22,13 @@
"sideEffects": false,
"scripts": {
"build": "tsc",
- "lint": "eslint . --ext .ts",
+ "prebuild": "npm run format",
+ "format": "prettier -w . --ignore-path .gitignore",
+ "format:check": "prettier -c . --ignore-path .gitignore",
"test": "jest",
- "docs": "typedoc"
+ "posttest": "npm run format:check",
+ "docs": "typedoc",
+ "predocs": "npm run format"
},
"dependencies": {
"@msgpack/msgpack": "^2.7.2",
@@ -40,7 +44,9 @@
"@typescript-eslint/eslint-plugin": "^5.30.6",
"@typescript-eslint/parser": "^5.30.6",
"eslint": "^8.20.0",
+ "eslint-config-prettier": "^8.5.0",
"jest": "^28.1.3",
+ "prettier": "^2.7.1",
"ts-jest": "^28.0.8",
"typed-emitter": "^2.1.0",
"typedoc": "^0.23.10",
diff --git a/src/errors.ts b/src/errors.ts
index f8ba1d6..c88bdd3 100644
--- a/src/errors.ts
+++ b/src/errors.ts
@@ -20,10 +20,10 @@ export enum ProcedureErrorCodes {
/** An unhandled exception was thrown while attempting to handle the procedure. */
INTERNAL_SERVER_ERROR = 200,
/** An unhandled exception was thrown during procedure execution. */
- EXECUTION_ERROR = 201
+ EXECUTION_ERROR = 201,
}
-/**
+/**
* A base abstraction of an error relating to a procedure.
* @internal
* @remarks Intended for internal use; may not be exported in future.
@@ -61,7 +61,10 @@ export class ProcedureUnknownError extends ProcedureError {
* @param {string} [message] A string indicating the cause of the error.
* @param {Record} [data] An optional dictionary of data which will be passed to a procedure's caller when thrown.
*/
- constructor(message = 'An unhandled exception of unknown origin was thrown while handling the request.', data?: Record) {
+ constructor(
+ message = 'An unhandled exception of unknown origin was thrown while handling the request.',
+ data?: Record
+ ) {
super(message, data);
}
}
@@ -75,7 +78,10 @@ export class ProcedureInternalClientError extends ProcedureError {
* @param {string} [message] A string indicating the cause of the error.
* @param {Record} [data] An optional dictionary of data which will be passed to a procedure's caller when thrown.
*/
- constructor(message = 'An unhandled exception was thrown while attempting to call the procedure.', data?: Record) {
+ constructor(
+ message = 'An unhandled exception was thrown while attempting to call the procedure.',
+ data?: Record
+ ) {
super(message, data);
}
}
@@ -89,7 +95,10 @@ export class ProcedureNotFoundError extends ProcedureError {
* @param {string} [message] A string indicating the cause of the error.
* @param {Record} [data] An optional dictionary of data which will be passed to a procedure's caller when thrown.
*/
- constructor(message = 'The procedure could not be found at the stated endpoint.', data?: Record) {
+ constructor(
+ message = 'The procedure could not be found at the stated endpoint.',
+ data?: Record
+ ) {
super(message, data);
}
}
@@ -103,7 +112,10 @@ export class ProcedureCancelledError extends ProcedureError {
* @param {string} [message] A string indicating the cause of the error.
* @param {Record} [data] An optional dictionary of data which will be passed to a procedure's caller when thrown.
*/
- constructor(message = 'The operation was cancelled by the client.', data?: Record) {
+ constructor(
+ message = 'The operation was cancelled by the client.',
+ data?: Record
+ ) {
super(message, data);
}
}
@@ -117,7 +129,10 @@ export class ProcedureTimedOutError extends ProcedureError {
* @param {string} [message] A string indicating the cause of the error.
* @param {Record} [data] An optional dictionary of data which will be passed to a procedure's caller when thrown.
*/
- constructor(message = 'Timed out waiting for the operation to complete.', data?: Record) {
+ constructor(
+ message = 'Timed out waiting for the operation to complete.',
+ data?: Record
+ ) {
super(message, data);
}
}
@@ -131,7 +146,10 @@ export class ProcedureInvalidResponseError extends ProcedureError {
* @param {string} [message] A string indicating the cause of the error.
* @param {Record} [data] An optional dictionary of data which will be passed to a procedure's caller when thrown.
*/
- constructor(message = 'The response from the server was invalid.', data?: Record) {
+ constructor(
+ message = 'The response from the server was invalid.',
+ data?: Record
+ ) {
super(message, data);
}
}
@@ -145,7 +163,10 @@ export class ProcedureInternalServerError extends ProcedureError {
* @param {string} [message] A string indicating the cause of the error.
* @param {Record} [data] An optional dictionary of data which will be passed to a procedure's caller when thrown.
*/
- constructor(message = 'An unhandled exception was thrown while attempting to handle the procedure.', data?: Record) {
+ constructor(
+ message = 'An unhandled exception was thrown while attempting to handle the procedure.',
+ data?: Record
+ ) {
super(message, data);
}
}
@@ -159,7 +180,10 @@ export class ProcedureExecutionError extends ProcedureError {
* @param {string} [message] A string indicating the cause of the error.
* @param {Record} [data] An optional dictionary of data which will be passed to a procedure's caller when thrown.
*/
- constructor(message = 'An unhandled exception was thrown during procedure execution.', data?: Record) {
+ constructor(
+ message = 'An unhandled exception was thrown during procedure execution.',
+ data?: Record
+ ) {
super(message, data);
}
}
@@ -174,7 +198,13 @@ export class ProcedureExecutionError extends ProcedureError {
* @remarks Intended for internal use; may not be exported in future.
*/
export function isError(object: unknown): object is Error {
- return object instanceof Error || (typeof object === 'object' && object !== null && 'name' in object && 'message' in object);
+ return (
+ object instanceof Error ||
+ (typeof object === 'object' &&
+ object !== null &&
+ 'name' in object &&
+ 'message' in object)
+ );
}
/**
@@ -183,7 +213,13 @@ export function isError(object: unknown): object is Error {
* @returns {object is ProcedureError} `true` if the object conforms to the {@link ProcedureError} interface, otherwise `false`.
*/
export function isProcedureError(object: unknown): object is ProcedureError {
- return object instanceof ProcedureError || (isError(object) && object.name.startsWith('Procedure') && object.name.endsWith('Error')
- && 'message' in object
- && 'code' in object && (<{ code: number }>object).code in ProcedureErrorCodes);
+ return (
+ object instanceof ProcedureError ||
+ (isError(object) &&
+ object.name.startsWith('Procedure') &&
+ object.name.endsWith('Error') &&
+ 'message' in object &&
+ 'code' in object &&
+ (<{ code: number }>object).code in ProcedureErrorCodes)
+ );
}
diff --git a/src/index.ts b/src/index.ts
index 03f853a..30c8089 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,12 +1,23 @@
///
import {
- isProcedureError, isError,
- ProcedureCancelledError, ProcedureInvalidResponseError, ProcedureInternalClientError, ProcedureInternalServerError,
- ProcedureExecutionError, ProcedureNotFoundError, ProcedureTimedOutError, ProcedureError
+ isProcedureError,
+ isError,
+ ProcedureCancelledError,
+ ProcedureInvalidResponseError,
+ ProcedureInternalClientError,
+ ProcedureInternalServerError,
+ ProcedureExecutionError,
+ ProcedureNotFoundError,
+ ProcedureTimedOutError,
+ ProcedureError,
} from './errors';
import { AggregateSignal, TimeoutSignal } from '@toebean/signals';
import { createSocket, Socket } from 'nanomsg';
-import { encode as msgpackEncode, decode as msgpackDecode, ExtensionCodec } from '@msgpack/msgpack';
+import {
+ encode as msgpackEncode,
+ decode as msgpackDecode,
+ ExtensionCodec,
+} from '@msgpack/msgpack';
import { once, EventEmitter } from 'events';
import TypedEmitter from 'typed-emitter';
import { v5 as uuidv5 } from 'uuid';
@@ -22,28 +33,43 @@ const uuidNamespace = uuidv5(homepage, uuidv5.URL);
* @template Output Type of output value the procedure returns. Defaults to `undefined`.
* @see [TypedEmitter](https://github.com/andywer/typed-emitter#readme)
*/
-export class Procedure
- extends (EventEmitter as { new (): TypedEmitter> }) implements ProcedureDefinitionOptions {
+export class Procedure<
+ Input extends Nullable = undefined,
+ Output extends Nullable = undefined
+ >
+ extends (EventEmitter as {
+ new (): TypedEmitter>;
+ })
+ implements ProcedureDefinitionOptions
+{
#endpoint?: string;
- /**
+ /**
* The endpoint at which the {@link Procedure}, when {@link bind bound}, can be {@link call called}.
- */
- get endpoint() { return this.#endpoint; }
- protected set endpoint(value) { this.#endpoint = value; }
+ */
+ get endpoint() {
+ return this.#endpoint;
+ }
+ protected set endpoint(value) {
+ this.#endpoint = value;
+ }
#uuid?: string;
- /**
+ /**
* A v5 uuid generated from {@link endpoint}, used to identify ping requests.
*/
- protected get uuid() { return this.#uuid; }
- protected set uuid(value) { this.#uuid = value; }
+ protected get uuid() {
+ return this.#uuid;
+ }
+ protected set uuid(value) {
+ this.#uuid = value;
+ }
- /**
+ /**
* The options in use by the {@link Procedure}, including defaults.
*/
protected options: ProcedureDefinitionOptions;
- /**
+ /**
* The underlying nanomsg sockets used for data transmission.
*/
protected sockets: Socket[] = [];
@@ -51,36 +77,55 @@ export class Procedure , options: Partial = {}) {
+ constructor(
+ protected callback: Callback ,
+ options: Partial = {}
+ ) {
super();
this.options = {
...{
verbose: false,
workers: 1,
optionalParameterSupport: true,
- ignoreUndefinedProperties: true
+ ignoreUndefinedProperties: true,
},
- ...options
+ ...options,
};
this.workers = this.options.workers; // explicitly run setter logic
}
@@ -115,9 +163,14 @@ export class Procedure this.#onRepSocketData(data, socket))
+ .on('data', (data: Buffer) =>
+ this.#onRepSocketData(data, socket)
+ )
.on('error', (error: unknown) => this.#onRepSocketError(error))
.once('close', () => this.#onRepSocketClose())
.bind(endpoint); // bind the socket to the endpoint
@@ -162,12 +215,21 @@ export class Procedure (buffer, this.extensionCodec) };
} catch (e) {
- const error = new ProcedureInternalServerError(undefined, { error: e });
- this.#emitAndLogError('Procedure input data could not be decoded', error);
+ const error = new ProcedureInternalServerError(undefined, {
+ error: e,
+ });
+ this.#emitAndLogError(
+ 'Procedure input data could not be decoded',
+ error
+ );
delete error.data;
return { error };
}
@@ -183,18 +245,26 @@ export class Procedure > {
try {
return {
- output: (await this.callback(input
- ?? (this.optionalParameterSupport
- ? undefined
- : input))) ?? null
+ output:
+ (await this.callback(
+ input ??
+ (
+ (this.optionalParameterSupport
+ ? undefined
+ : input)
+ )
+ )) ?? null,
};
} catch (e) {
- const message = 'Procedure encountered an error while executing callback';
+ const message =
+ 'Procedure encountered an error while executing callback';
if (isProcedureError(e)) {
this.#emitAndLogError(message, e);
return { error: e };
} else {
- const error = new ProcedureExecutionError(undefined, { error: e });
+ const error = new ProcedureExecutionError(undefined, {
+ error: e,
+ });
this.#emitAndLogError(message, error);
delete error.data;
return { error };
@@ -209,15 +279,26 @@ export class Procedure ): Buffer {
try {
- return encode(response, this.ignoreUndefinedProperties, this.extensionCodec);
+ return encode(
+ response,
+ this.ignoreUndefinedProperties,
+ this.extensionCodec
+ );
} catch (e) {
- const error = new ProcedureInternalServerError(undefined, { error: e });
- this.#emitAndLogError('Procedure response could not be encoded for transmission', error);
+ const error = new ProcedureInternalServerError(undefined, {
+ error: e,
+ });
+ this.#emitAndLogError(
+ 'Procedure response could not be encoded for transmission',
+ error
+ );
delete error.data;
- return this.#tryEncodeResponse({ // As the response could not be encoded, encode and return a new response containing the thrown error
- error: 'output' in response
- ? error // output failed to encode
- : undefined // error failed to encode, should break any infinite loops unless msgpack or the extension codec is broken
+ return this.#tryEncodeResponse({
+ // As the response could not be encoded, encode and return a new response containing the thrown error
+ error:
+ 'output' in response
+ ? error // output failed to encode
+ : undefined, // error failed to encode, should break any infinite loops unless msgpack or the extension codec is broken
});
}
}
@@ -233,7 +314,10 @@ export class Procedure {
const decoded = this.#tryDecodeInput(data);
- if (!this.#tryHandlePing(decoded.input, socket)) { // input was not a ping, handle it
+ if (!this.#tryHandlePing(decoded.input, socket)) {
+ // input was not a ping, handle it
if ('input' in decoded) {
this.#emitAndLogData(decoded.input as Input);
}
- const response = 'input' in decoded
- ? await this.#tryGetCallbackResponse(decoded.input as Input)
- : decoded;
+ const response =
+ 'input' in decoded
+ ? await this.#tryGetCallbackResponse(decoded.input as Input)
+ : decoded;
if ('output' in response && this.verbose) {
- console.log(`Generated output data at endpoint: ${this.endpoint}`, response.output);
+ console.log(
+ `Generated output data at endpoint: ${this.endpoint}`,
+ response.output
+ );
}
- if (this.#trySendBuffer(this.#tryEncodeResponse(response), socket) && this.verbose) {
- console.log(`Response sent at endpoint ${this.endpoint}`, response);
+ if (
+ this.#trySendBuffer(
+ this.#tryEncodeResponse(response),
+ socket
+ ) &&
+ this.verbose
+ ) {
+ console.log(
+ `Response sent at endpoint ${this.endpoint}`,
+ response
+ );
}
}
}
@@ -277,7 +375,12 @@ export class Procedure socket.closed)) {
+ if (this.sockets.every((socket) => socket.closed)) {
this.unbind();
this.#emitAndLogUnbind(); // emit the unbind event
}
@@ -316,7 +422,10 @@ export class Procedure 0) { // only emit if there are listeners to prevent unhandled error exceptions
+ if (this.listenerCount('error') > 0) {
+ // only emit if there are listeners to prevent unhandled error exceptions
this.emit('error', error);
}
- if (this.verbose) { // optionally output the error to the console
+ if (this.verbose) {
+ // optionally output the error to the console
console.error(`${message}\r\n`, error);
}
}
@@ -354,7 +465,8 @@ export class Procedure = (input: Input) => Output;
+export type Callback<
+ Input extends Nullable = undefined,
+ Output extends Nullable = undefined
+> = (input: Input) => Output;
/**
* A response from a {@link call Procedure call}.
* If the call returned successfully, the response will be of shape `{ output: Output }`, otherwise `{ error: ProcedureError }`.
*/
-export type Response
- = { output: Output | null | undefined, error?: never, pong?: never }
- | { output?: never, error: ProcedureError | null | undefined, pong?: never }
- | { output?: never, error?: never, pong: string };
+export type Response =
+ | { output: Output | null | undefined; error?: never; pong?: never }
+ | { output?: never; error: ProcedureError | null | undefined; pong?: never }
+ | { output?: never; error?: never; pong: string };
/**
* Options for defining or calling a {@link Procedure}.
@@ -393,7 +508,7 @@ export interface ProcedureOptions {
* Whether or not to enable optional parameter support. Defaults to `true`.
* When `true` on a {@link Procedure}, a `null` input parameter will be coerced to `undefined`.
* When `true` for a {@link call}, a `null` return value will be coerced to `undefined`.
- *
+ *
* @remarks
* The {@link https://procedure-rpc.github.io/procedure.js procedure.js} library uses the {@link https://github.com/msgpack/msgpack-javascript msgpack} serialization
* format for encoding JavaScript objects and values for transmission to and from remote {@link Procedure procedures}.
@@ -403,7 +518,7 @@ export interface ProcedureOptions {
* for the convenience of passing the return value into an optional parameter of another function call.
* {@link optionalParameterSupport} aims to alleviate these issues by mapping `null` to `undefined`
* for the input and output of your {@link Procedure} calls.
- *
+ *
* @see {@link ignoreUndefinedProperties}
* @see {@link https://procedure-rpc.github.io/procedure.js#optional-parameter-support Optional parameter support}
*/
@@ -412,7 +527,7 @@ export interface ProcedureOptions {
* Whether or not to ignore `undefined` properties of objects passed to or from a {@link Procedure}. Defaults to `true`.
* When `true` on a {@link Procedure}, only affects properties of input parameters.
* When `true` on a {@link call}, only affects properties of the return value.
- *
+ *
* @remarks
* The {@link https://procedure-rpc.github.io/procedure.js procedure.js} library uses the {@link https://github.com/msgpack/msgpack-javascript msgpack} serialization
* format for encoding JavaScript objects and values for transmission to and from remote {@link Procedure procedures}.
@@ -423,7 +538,7 @@ export interface ProcedureOptions {
* allowing `undefined` to be evaluated as `undefined` and `null` to be evaluated as `null`.
* This operation incurs some overhead, and means that code relying on the presence of a property to infer meaning
* may not operate as expected.
- *
+ *
* @see {@link https://procedure-rpc.github.io/procedure.js#null-and-undefined-properties null and undefined properties}
*/
ignoreUndefinedProperties: boolean;
@@ -433,7 +548,7 @@ export interface ProcedureOptions {
* Options for defining a {@link Procedure}.
*/
export interface ProcedureDefinitionOptions extends ProcedureOptions {
- /**
+ /**
* The number of workers to spin up for the {@link Procedure}. Useful for procedures which may take a long time to complete.
* Will be clamped between `1` and
* [Number.MAX_SAFE_INTEGER](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER) inclusive.
@@ -449,7 +564,7 @@ export interface ProcedureDefinitionOptions extends ProcedureOptions {
* Options for {@link call calling} a {@link Procedure}.
*/
export interface ProcedureCallOptions extends ProcedureOptions {
- /**
+ /**
* The number of milliseconds after which the {@link call} will automatically be aborted.
* Set to [Infinity](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Infinity)
* or [NaN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN) to never timeout.
@@ -458,7 +573,7 @@ export interface ProcedureCallOptions extends ProcedureOptions {
* Defaults to `1000`.
*/
timeout: number;
- /**
+ /**
* The number of milliseconds to wait for a ping-pong from the endpoint before calling the remote procedure.
* When set, if a ping-pong is not received in the given time, the {@link call} will be aborted.
* [NaN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN) or
@@ -497,7 +612,7 @@ export type ProcedureEvents = {
error: (error: unknown) => void;
/** Signature for the unbind event. */
unbind: () => void;
-}
+};
/**
* A simple interface representing a ping.
@@ -516,7 +631,12 @@ export interface Ping {
* @remarks Intended for internal use; may not be exported in future.
*/
export function isPing(object: unknown): object is Ping {
- return typeof object === 'object' && object !== null && 'ping' in object && typeof (object as { ping: unknown }).ping === 'string';
+ return (
+ typeof object === 'object' &&
+ object !== null &&
+ 'ping' in object &&
+ typeof (object as { ping: unknown }).ping === 'string'
+ );
}
/**
@@ -531,7 +651,11 @@ export function isPing(object: unknown): object is Ping {
* @see {@link Procedure.endpoint}
* @see {@link ping}
*/
-export async function call(endpoint: string, input?: Nullable, options: Partial = {}): Promise {
+export async function call(
+ endpoint: string,
+ input?: Nullable,
+ options: Partial = {}
+): Promise {
try {
// parse options into defaults
const opts: ProcedureCallOptions = {
@@ -541,9 +665,9 @@ export async function call(endpoint: string,
pingCacheLength: 60000,
optionalParameterSupport: true,
ignoreUndefinedProperties: true,
- ipv6: false
+ ipv6: false,
},
- ...options
+ ...options,
};
// first check the endpoint is ready
@@ -551,7 +675,13 @@ export async function call(endpoint: string,
try {
await (opts.pingCacheLength === undefined
? ping(endpoint, opts.ping, opts.ipv6, opts.signal)
- : cachedPing(endpoint, opts.ping, opts.pingCacheLength, opts.ipv6, opts.signal));
+ : cachedPing(
+ endpoint,
+ opts.ping,
+ opts.pingCacheLength,
+ opts.ipv6,
+ opts.signal
+ ));
} catch (error) {
throw error instanceof ProcedureTimedOutError
? new ProcedureNotFoundError() // timeout on ping = not found
@@ -562,11 +692,13 @@ export async function call(endpoint: string,
// call the endpoint and get response
const response = await getResponse(endpoint, input, opts);
- if ('output' in response && !('error' in response)) { // success!
+ if ('output' in response && !('error' in response)) {
+ // success!
return response.output ?? (opts.optionalParameterSupport
- ? undefined // coerce null to undefined
- : response.output);
- } else if (isProcedureError(response.error)) { // response indicates an error happened server-side
+ ? undefined // coerce null to undefined
+ : response.output);
+ } else if (isProcedureError(response.error)) {
+ // response indicates an error happened server-side
throw response.error;
} else {
throw new ProcedureInvalidResponseError();
@@ -596,16 +728,25 @@ export async function call(endpoint: string,
* @returns {Promise} A [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
* which when resolved indicates that the endpoint is available and ready to handle {@link call calls}.
*/
-export async function ping(endpoint: string, timeout = 1000, ipv6 = false, signal?: AbortSignal): Promise {
+export async function ping(
+ endpoint: string,
+ timeout = 1000,
+ ipv6 = false,
+ signal?: AbortSignal
+): Promise {
try {
const ping = uuidv5(endpoint, uuidNamespace);
- const response = await getResponse<{ pong: string }>(endpoint, { ping }, {
- timeout,
- signal,
- ignoreUndefinedProperties: false,
- optionalParameterSupport: false,
- ipv6
- });
+ const response = await getResponse<{ pong: string }>(
+ endpoint,
+ { ping },
+ {
+ timeout,
+ signal,
+ ignoreUndefinedProperties: false,
+ optionalParameterSupport: false,
+ ipv6,
+ }
+ );
if (response?.pong !== ping) {
throw new ProcedureInvalidResponseError();
@@ -629,8 +770,15 @@ export async function ping(endpoint: string, timeout = 1000, ipv6 = false, signa
* @returns {Promise} A [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) which,
* when resolved, indicates that the endpoint is available and ready to handle {@link call calls}.
*/
-async function cachedPing(endpoint: string, timeout: number, cacheLength: number, ipv6: boolean, signal?: AbortSignal): ReturnType {
- if (isNaN(cacheLength) || !isFinite(cacheLength)) { // number is invalid, skip the cache
+async function cachedPing(
+ endpoint: string,
+ timeout: number,
+ cacheLength: number,
+ ipv6: boolean,
+ signal?: AbortSignal
+): ReturnType {
+ if (isNaN(cacheLength) || !isFinite(cacheLength)) {
+ // number is invalid, skip the cache
return ping(endpoint, timeout, ipv6, signal);
}
@@ -642,9 +790,13 @@ async function cachedPing(endpoint: string, timeout: number, cacheLength: number
}
// if a ping for the same endpoint is currently in progress, await on either it or the a new ping to resolve
- cachedPingsByEndpoint[endpoint].resolving = cachedPingsByEndpoint[endpoint].resolving !== undefined
- ? Promise.any([cachedPingsByEndpoint[endpoint].resolving, ping(endpoint, timeout, ipv6, signal)])
- : ping(endpoint, timeout, ipv6, signal);
+ cachedPingsByEndpoint[endpoint].resolving =
+ cachedPingsByEndpoint[endpoint].resolving !== undefined
+ ? Promise.any([
+ cachedPingsByEndpoint[endpoint].resolving,
+ ping(endpoint, timeout, ipv6, signal),
+ ])
+ : ping(endpoint, timeout, ipv6, signal);
await cachedPingsByEndpoint[endpoint].resolving;
@@ -672,7 +824,12 @@ async function cachedPing(endpoint: string, timeout: number, cacheLength: number
* which when resolved indicated whether the endpoint is available and ready to handle {@link call calls}.
* If errors were thrown, resolves to `false` instead of rejecting.
*/
-export async function tryPing(endpoint: string, timeout = 1000, ipv6 = false, signal?: AbortSignal): Promise {
+export async function tryPing(
+ endpoint: string,
+ timeout = 1000,
+ ipv6 = false,
+ signal?: AbortSignal
+): Promise {
try {
await ping(endpoint, timeout, ipv6, signal);
return true;
@@ -691,7 +848,11 @@ export async function tryPing(endpoint: string, timeout = 1000, ipv6 = false, si
* [then](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) handler(s).
* @template Output The type of output value expected to be returned from the {@link Procedure}. Defaults to `unknown`.
*/
-async function getResponse(endpoint: string, input: Nullable, options: ProcedureCallOptions): Promise> {
+async function getResponse(
+ endpoint: string,
+ input: Nullable,
+ options: ProcedureCallOptions
+): Promise> {
let socket: Socket | undefined;
let timeoutSignal: TimeoutSignal | undefined = undefined;
let aggregateSignal: AggregateSignal | undefined = undefined;
@@ -702,14 +863,25 @@ async function getResponse(endpoint: string,
}
timeoutSignal = new TimeoutSignal(options.timeout);
- aggregateSignal = new AggregateSignal(options.signal, timeoutSignal.signal);
+ aggregateSignal = new AggregateSignal(
+ options.signal,
+ timeoutSignal.signal
+ );
const { signal } = aggregateSignal;
socket = createSocket('req', { ipv6: options.ipv6 });
socket.connect(endpoint);
- socket.send(encode(input, options.ignoreUndefinedProperties, options.extensionCodec)); // send the encoded input data to the endpoint
-
- const [buffer]: [Buffer] = await once(socket, 'data', { signal }) as [Buffer]; // await buffered response
+ socket.send(
+ encode(
+ input,
+ options.ignoreUndefinedProperties,
+ options.extensionCodec
+ )
+ ); // send the encoded input data to the endpoint
+
+ const [buffer]: [Buffer] = (await once(socket, 'data', { signal })) as [
+ Buffer
+ ]; // await buffered response
return decode>(buffer, options.extensionCodec); // decode response from buffer
} catch (e) {
if (isProcedureError(e)) {
@@ -734,8 +906,15 @@ async function getResponse(endpoint: string,
* @param {ExtensionCodec} [extensionCodec] The [ExtensionCodec](https://github.com/msgpack/msgpack-javascript#extension-types) to use for encoding.
* @returns {Buffer} A [Buffer](https://nodejs.org/api/buffer.html#buffer) containing the encoded value.
*/
-function encode(value: unknown, ignoreUndefinedProperties: boolean, extensionCodec?: ExtensionCodec): Buffer {
- const encoded = msgpackEncode(value, { extensionCodec, ignoreUndefined: ignoreUndefinedProperties });
+function encode(
+ value: unknown,
+ ignoreUndefinedProperties: boolean,
+ extensionCodec?: ExtensionCodec
+): Buffer {
+ const encoded = msgpackEncode(value, {
+ extensionCodec,
+ ignoreUndefined: ignoreUndefinedProperties,
+ });
return Buffer.from(encoded.buffer, encoded.byteOffset, encoded.byteLength);
}
@@ -746,8 +925,14 @@ function encode(value: unknown, ignoreUndefinedProperties: boolean, extensionCod
* @returns {T} The buffer, decoded and cast to type {@link T}.
* @template T The type the decoded value should be cast to.
*/
-function decode(buffer: Buffer, extensionCodec?: ExtensionCodec): T {
+function decode(
+ buffer: Buffer,
+ extensionCodec?: ExtensionCodec
+): T {
return msgpackDecode(buffer, { extensionCodec }) as T;
}
-const cachedPingsByEndpoint: Record }> = {};
+const cachedPingsByEndpoint: Record<
+ string,
+ { timestamp?: number; resolving?: ReturnType }
+> = {};
diff --git a/test/errors.spec.ts b/test/errors.spec.ts
index 4f29998..5169ecb 100644
--- a/test/errors.spec.ts
+++ b/test/errors.spec.ts
@@ -1,8 +1,16 @@
import {
- ProcedureError, ProcedureUnknownError, ProcedureInternalClientError, ProcedureNotFoundError,
- ProcedureCancelledError, ProcedureTimedOutError, ProcedureInvalidResponseError,
- ProcedureInternalServerError, ProcedureExecutionError,
- isError, isProcedureError, ProcedureErrorCodes
+ ProcedureError,
+ ProcedureUnknownError,
+ ProcedureInternalClientError,
+ ProcedureNotFoundError,
+ ProcedureCancelledError,
+ ProcedureTimedOutError,
+ ProcedureInvalidResponseError,
+ ProcedureInternalServerError,
+ ProcedureExecutionError,
+ isError,
+ isProcedureError,
+ ProcedureErrorCodes,
} from '../src/errors';
describe('ProcedureUnknownError', () => {
@@ -10,75 +18,82 @@ describe('ProcedureUnknownError', () => {
let instance: ProcedureUnknownError;
describe('when no parameters passed', () => {
- beforeEach(() => { instance = new ProcedureUnknownError() });
+ beforeEach(() => {
+ instance = new ProcedureUnknownError();
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureUnknownError',
- () => { expect(instance).toBeInstanceOf(ProcedureUnknownError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureUnknownError', () => {
+ expect(instance).toBeInstanceOf(ProcedureUnknownError);
+ });
describe('message', () =>
- it(
- 'should be: \'An unhandled exception of unknown origin was thrown while handling the request.\'',
- () => { expect(instance.message).toEqual('An unhandled exception of unknown origin was thrown while handling the request.') }
- ));
+ it("should be: 'An unhandled exception of unknown origin was thrown while handling the request.'", () => {
+ expect(instance.message).toEqual(
+ 'An unhandled exception of unknown origin was thrown while handling the request.'
+ );
+ }));
describe('data', () => {
- it('should not be set', () => { expect(instance).not.toHaveProperty('data') })
+ it('should not be set', () => {
+ expect(instance).not.toHaveProperty('data');
+ });
});
});
- describe(
- 'when message: \'Expected n to be typeof number, got object\', data: undefined',
- () => {
- beforeEach(
- () => { instance = new ProcedureUnknownError('Expected n to be typeof number, got object') }
+ describe("when message: 'Expected n to be typeof number, got object', data: undefined", () => {
+ beforeEach(() => {
+ instance = new ProcedureUnknownError(
+ 'Expected n to be typeof number, got object'
);
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureUnknownError',
- () => { expect(instance).toBeInstanceOf(ProcedureUnknownError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureUnknownError', () => {
+ expect(instance).toBeInstanceOf(ProcedureUnknownError);
+ });
- describe('message', () =>
- it('should be: \'Expected n to be typeof number, got object\'', () => {
- expect(instance.message).toEqual('Expected n to be typeof number, got object')
- }));
+ describe('message', () =>
+ it("should be: 'Expected n to be typeof number, got object'", () => {
+ expect(instance.message).toEqual(
+ 'Expected n to be typeof number, got object'
+ );
+ }));
- describe('data', () => {
- it('should not be set', () => { expect(instance).not.toHaveProperty('data') });
+ describe('data', () => {
+ it('should not be set', () => {
+ expect(instance).not.toHaveProperty('data');
});
- }
- );
+ });
+ });
- describe('when message: undefined, data: { foo: \'bar\' }', () => {
- beforeEach(() => { instance = new ProcedureUnknownError(undefined, { foo: 'bar' }) });
+ describe("when message: undefined, data: { foo: 'bar' }", () => {
+ beforeEach(() => {
+ instance = new ProcedureUnknownError(undefined, { foo: 'bar' });
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureUnknownError',
- () => { expect(instance).toBeInstanceOf(ProcedureUnknownError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureUnknownError', () => {
+ expect(instance).toBeInstanceOf(ProcedureUnknownError);
+ });
describe('message', () =>
- it(
- 'should be: \'An unhandled exception of unknown origin was thrown while handling the request.\'',
- () => { expect(instance.message).toEqual('An unhandled exception of unknown origin was thrown while handling the request.') }
- ));
+ it("should be: 'An unhandled exception of unknown origin was thrown while handling the request.'", () => {
+ expect(instance.message).toEqual(
+ 'An unhandled exception of unknown origin was thrown while handling the request.'
+ );
+ }));
describe('data', () => {
- it('should equal: { foo: \'bar\' }', () => { expect(instance.data).toStrictEqual({ foo: 'bar' }) });
+ it("should equal: { foo: 'bar' }", () => {
+ expect(instance.data).toStrictEqual({ foo: 'bar' });
+ });
});
});
});
@@ -89,77 +104,82 @@ describe('ProcedureInternalClientError', () => {
let instance: ProcedureInternalClientError;
describe('when no parameters passed', () => {
- beforeEach(() => instance = new ProcedureInternalClientError());
+ beforeEach(() => (instance = new ProcedureInternalClientError()));
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureInternalClientError',
- () => { expect(instance).toBeInstanceOf(ProcedureInternalClientError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureInternalClientError', () => {
+ expect(instance).toBeInstanceOf(ProcedureInternalClientError);
+ });
describe('message', () =>
- it(
- 'should be: \'An unhandled exception was thrown while attempting to call the procedure.\'',
- () => { expect(instance.message).toEqual('An unhandled exception was thrown while attempting to call the procedure.') }
- ));
+ it("should be: 'An unhandled exception was thrown while attempting to call the procedure.'", () => {
+ expect(instance.message).toEqual(
+ 'An unhandled exception was thrown while attempting to call the procedure.'
+ );
+ }));
describe('data', () => {
- it('should not be set', () => { expect(instance).not.toHaveProperty('data') });
+ it('should not be set', () => {
+ expect(instance).not.toHaveProperty('data');
+ });
});
});
- describe(
- 'when message: \'Expected n to be typeof number, got object\', data: undefined',
- () => {
- beforeEach(
- () => { instance = new ProcedureInternalClientError('Expected n to be typeof number, got object') }
+ describe("when message: 'Expected n to be typeof number, got object', data: undefined", () => {
+ beforeEach(() => {
+ instance = new ProcedureInternalClientError(
+ 'Expected n to be typeof number, got object'
);
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureInternalClientError',
- () => { expect(instance).toBeInstanceOf(ProcedureInternalClientError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureInternalClientError', () => {
+ expect(instance).toBeInstanceOf(ProcedureInternalClientError);
+ });
- describe('message', () =>
- it('should be: \'Expected n to be typeof number, got object\'', () => {
- expect(instance.message).toEqual('Expected n to be typeof number, got object')
- }));
+ describe('message', () =>
+ it("should be: 'Expected n to be typeof number, got object'", () => {
+ expect(instance.message).toEqual(
+ 'Expected n to be typeof number, got object'
+ );
+ }));
- describe('data', () => {
- it('should not be set', () => { expect(instance).not.toHaveProperty('data') });
+ describe('data', () => {
+ it('should not be set', () => {
+ expect(instance).not.toHaveProperty('data');
});
- }
- );
+ });
+ });
- describe('when message: undefined, data: { foo: \'bar\' }', () => {
- beforeEach(
- () => { instance = new ProcedureInternalClientError(undefined, { foo: 'bar' }) }
- );
+ describe("when message: undefined, data: { foo: 'bar' }", () => {
+ beforeEach(() => {
+ instance = new ProcedureInternalClientError(undefined, {
+ foo: 'bar',
+ });
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureInternalClientError',
- () => { expect(instance).toBeInstanceOf(ProcedureInternalClientError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureInternalClientError', () => {
+ expect(instance).toBeInstanceOf(ProcedureInternalClientError);
+ });
describe('message', () =>
- it(
- 'should be: \'An unhandled exception was thrown while attempting to call the procedure.\'',
- () => { expect(instance.message).toEqual('An unhandled exception was thrown while attempting to call the procedure.') }
- ));
+ it("should be: 'An unhandled exception was thrown while attempting to call the procedure.'", () => {
+ expect(instance.message).toEqual(
+ 'An unhandled exception was thrown while attempting to call the procedure.'
+ );
+ }));
describe('data', () => {
- it('should equal: { foo: \'bar\' }', () => { expect(instance.data).toStrictEqual({ foo: 'bar' }) });
+ it("should equal: { foo: 'bar' }", () => {
+ expect(instance.data).toStrictEqual({ foo: 'bar' });
+ });
});
});
});
@@ -170,75 +190,84 @@ describe('ProcedureNotFoundError', () => {
let instance: ProcedureNotFoundError;
describe('when no parameters passed', () => {
- beforeEach(() => { instance = new ProcedureNotFoundError() });
+ beforeEach(() => {
+ instance = new ProcedureNotFoundError();
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureNotFoundError',
- () => { expect(instance).toBeInstanceOf(ProcedureNotFoundError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureNotFoundError', () => {
+ expect(instance).toBeInstanceOf(ProcedureNotFoundError);
+ });
describe('message', () =>
- it(
- 'should be: \'The procedure could not be found at the stated endpoint.\'',
- () => { expect(instance.message).toEqual('The procedure could not be found at the stated endpoint.') }
- ));
+ it("should be: 'The procedure could not be found at the stated endpoint.'", () => {
+ expect(instance.message).toEqual(
+ 'The procedure could not be found at the stated endpoint.'
+ );
+ }));
describe('data', () => {
- it('should not be set', () => { expect(instance).not.toHaveProperty('data') });
+ it('should not be set', () => {
+ expect(instance).not.toHaveProperty('data');
+ });
});
});
- describe(
- 'when message: \'Expected n to be typeof number, got object\', data: undefined',
- () => {
- beforeEach(
- () => { instance = new ProcedureNotFoundError('Expected n to be typeof number, got object') }
+ describe("when message: 'Expected n to be typeof number, got object', data: undefined", () => {
+ beforeEach(() => {
+ instance = new ProcedureNotFoundError(
+ 'Expected n to be typeof number, got object'
);
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureNotFoundError',
- () => { expect(instance).toBeInstanceOf(ProcedureNotFoundError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureNotFoundError', () => {
+ expect(instance).toBeInstanceOf(ProcedureNotFoundError);
+ });
- describe('message', () =>
- it('should be: \'Expected n to be typeof number, got object\'', () => {
- expect(instance.message).toEqual('Expected n to be typeof number, got object')
- }));
+ describe('message', () =>
+ it("should be: 'Expected n to be typeof number, got object'", () => {
+ expect(instance.message).toEqual(
+ 'Expected n to be typeof number, got object'
+ );
+ }));
- describe('data', () => {
- it('should not be set', () => { expect(instance).not.toHaveProperty('data') });
+ describe('data', () => {
+ it('should not be set', () => {
+ expect(instance).not.toHaveProperty('data');
});
- }
- );
+ });
+ });
- describe('when message: undefined, data: { foo: \'bar\' }', () => {
- beforeEach(() => { instance = new ProcedureNotFoundError(undefined, { foo: 'bar' }) });
+ describe("when message: undefined, data: { foo: 'bar' }", () => {
+ beforeEach(() => {
+ instance = new ProcedureNotFoundError(undefined, {
+ foo: 'bar',
+ });
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureNotFoundError',
- () => { expect(instance).toBeInstanceOf(ProcedureNotFoundError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureNotFoundError', () => {
+ expect(instance).toBeInstanceOf(ProcedureNotFoundError);
+ });
describe('message', () =>
- it(
- 'should be: \'The procedure could not be found at the stated endpoint.\'',
- () => { expect(instance.message).toEqual('The procedure could not be found at the stated endpoint.') }
- ));
+ it("should be: 'The procedure could not be found at the stated endpoint.'", () => {
+ expect(instance.message).toEqual(
+ 'The procedure could not be found at the stated endpoint.'
+ );
+ }));
describe('data', () => {
- it('should equal: { foo: \'bar\' }', () => { expect(instance.data).toStrictEqual({ foo: 'bar' }) });
+ it("should equal: { foo: 'bar' }", () => {
+ expect(instance.data).toStrictEqual({ foo: 'bar' });
+ });
});
});
});
@@ -249,73 +278,84 @@ describe('ProcedureCancelledError', () => {
let instance: ProcedureCancelledError;
describe('when no parameters passed', () => {
- beforeEach(() => { instance = new ProcedureCancelledError() });
+ beforeEach(() => {
+ instance = new ProcedureCancelledError();
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureCancelledError',
- () => { expect(instance).toBeInstanceOf(ProcedureCancelledError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureCancelledError', () => {
+ expect(instance).toBeInstanceOf(ProcedureCancelledError);
+ });
describe('message', () =>
- it('should be: \'The operation was cancelled by the client.\'', () => {
- expect(instance.message).toEqual('The operation was cancelled by the client.')
+ it("should be: 'The operation was cancelled by the client.'", () => {
+ expect(instance.message).toEqual(
+ 'The operation was cancelled by the client.'
+ );
}));
describe('data', () => {
- it('should not be set', () => { expect(instance).not.toHaveProperty('data') });
+ it('should not be set', () => {
+ expect(instance).not.toHaveProperty('data');
+ });
});
});
- describe(
- 'when message: \'Expected n to be typeof number, got object\', data: undefined',
- () => {
- beforeEach(
- () => { instance = new ProcedureCancelledError('Expected n to be typeof number, got object') }
+ describe("when message: 'Expected n to be typeof number, got object', data: undefined", () => {
+ beforeEach(() => {
+ instance = new ProcedureCancelledError(
+ 'Expected n to be typeof number, got object'
);
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureCancelledError',
- () => { expect(instance).toBeInstanceOf(ProcedureCancelledError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureCancelledError', () => {
+ expect(instance).toBeInstanceOf(ProcedureCancelledError);
+ });
- describe('message', () =>
- it('should be: \'Expected n to be typeof number, got object\'', () => {
- expect(instance.message).toEqual('Expected n to be typeof number, got object')
- }));
+ describe('message', () =>
+ it("should be: 'Expected n to be typeof number, got object'", () => {
+ expect(instance.message).toEqual(
+ 'Expected n to be typeof number, got object'
+ );
+ }));
- describe('data', () => {
- it('should not be set', () => { expect(instance).not.toHaveProperty('data') });
+ describe('data', () => {
+ it('should not be set', () => {
+ expect(instance).not.toHaveProperty('data');
});
- }
- );
+ });
+ });
- describe('when message: undefined, data: { foo: \'bar\' }', () => {
- beforeEach(() => { instance = new ProcedureCancelledError(undefined, { foo: 'bar' }) });
+ describe("when message: undefined, data: { foo: 'bar' }", () => {
+ beforeEach(() => {
+ instance = new ProcedureCancelledError(undefined, {
+ foo: 'bar',
+ });
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureCancelledError',
- () => { expect(instance).toBeInstanceOf(ProcedureCancelledError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureCancelledError', () => {
+ expect(instance).toBeInstanceOf(ProcedureCancelledError);
+ });
describe('message', () =>
- it('should be: \'The operation was cancelled by the client.\'', () => {
- expect(instance.message).toEqual('The operation was cancelled by the client.')
+ it("should be: 'The operation was cancelled by the client.'", () => {
+ expect(instance.message).toEqual(
+ 'The operation was cancelled by the client.'
+ );
}));
describe('data', () => {
- it('should equal: { foo: \'bar\' }', () => { expect(instance.data).toStrictEqual({ foo: 'bar' }) });
+ it("should equal: { foo: 'bar' }", () => {
+ expect(instance.data).toStrictEqual({ foo: 'bar' });
+ });
});
});
});
@@ -326,73 +366,84 @@ describe('ProcedureTimedOutError', () => {
let instance: ProcedureTimedOutError;
describe('when no parameters passed', () => {
- beforeEach(() => { instance = new ProcedureTimedOutError() });
+ beforeEach(() => {
+ instance = new ProcedureTimedOutError();
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureTimedOutError',
- () => { expect(instance).toBeInstanceOf(ProcedureTimedOutError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureTimedOutError', () => {
+ expect(instance).toBeInstanceOf(ProcedureTimedOutError);
+ });
describe('message', () =>
- it('should be: \'Timed out waiting for the operation to complete.\'', () => {
- expect(instance.message).toEqual('Timed out waiting for the operation to complete.')
+ it("should be: 'Timed out waiting for the operation to complete.'", () => {
+ expect(instance.message).toEqual(
+ 'Timed out waiting for the operation to complete.'
+ );
}));
describe('data', () => {
- it('should not be set', () => { expect(instance).not.toHaveProperty('data') });
+ it('should not be set', () => {
+ expect(instance).not.toHaveProperty('data');
+ });
});
});
- describe(
- 'when message: \'Expected n to be typeof number, got object\', data: undefined',
- () => {
- beforeEach(
- () => { instance = new ProcedureTimedOutError('Expected n to be typeof number, got object') }
+ describe("when message: 'Expected n to be typeof number, got object', data: undefined", () => {
+ beforeEach(() => {
+ instance = new ProcedureTimedOutError(
+ 'Expected n to be typeof number, got object'
);
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureTimedOutError',
- () => { expect(instance).toBeInstanceOf(ProcedureTimedOutError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureTimedOutError', () => {
+ expect(instance).toBeInstanceOf(ProcedureTimedOutError);
+ });
- describe('message', () =>
- it('should be: \'Expected n to be typeof number, got object\'', () => {
- expect(instance.message).toEqual('Expected n to be typeof number, got object')
- }));
+ describe('message', () =>
+ it("should be: 'Expected n to be typeof number, got object'", () => {
+ expect(instance.message).toEqual(
+ 'Expected n to be typeof number, got object'
+ );
+ }));
- describe('data', () => {
- it('should not be set', () => { expect(instance).not.toHaveProperty('data') });
+ describe('data', () => {
+ it('should not be set', () => {
+ expect(instance).not.toHaveProperty('data');
});
- }
- );
+ });
+ });
- describe('when message: undefined, data: { foo: \'bar\' }', () => {
- beforeEach(() => { instance = new ProcedureTimedOutError(undefined, { foo: 'bar' }) });
+ describe("when message: undefined, data: { foo: 'bar' }", () => {
+ beforeEach(() => {
+ instance = new ProcedureTimedOutError(undefined, {
+ foo: 'bar',
+ });
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureTimedOutError',
- () => { expect(instance).toBeInstanceOf(ProcedureTimedOutError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureTimedOutError', () => {
+ expect(instance).toBeInstanceOf(ProcedureTimedOutError);
+ });
describe('message', () =>
- it('should be: \'Timed out waiting for the operation to complete.\'', () => {
- expect(instance.message).toEqual('Timed out waiting for the operation to complete.')
+ it("should be: 'Timed out waiting for the operation to complete.'", () => {
+ expect(instance.message).toEqual(
+ 'Timed out waiting for the operation to complete.'
+ );
}));
describe('data', () => {
- it('should equal: { foo: \'bar\' }', () => { expect(instance.data).toStrictEqual({ foo: 'bar' }) });
+ it("should equal: { foo: 'bar' }", () => {
+ expect(instance.data).toStrictEqual({ foo: 'bar' });
+ });
});
});
});
@@ -403,75 +454,84 @@ describe('ProcedureInvalidResponseError', () => {
let instance: ProcedureInvalidResponseError;
describe('when no parameters passed', () => {
- beforeEach(() => { instance = new ProcedureInvalidResponseError() });
+ beforeEach(() => {
+ instance = new ProcedureInvalidResponseError();
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureInvalidResponseError',
- () => { expect(instance).toBeInstanceOf(ProcedureInvalidResponseError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureInvalidResponseError', () => {
+ expect(instance).toBeInstanceOf(ProcedureInvalidResponseError);
+ });
describe('message', () =>
- it('should be: \'The response from the server was invalid.\'', () => {
- expect(instance.message).toEqual('The response from the server was invalid.')
+ it("should be: 'The response from the server was invalid.'", () => {
+ expect(instance.message).toEqual(
+ 'The response from the server was invalid.'
+ );
}));
describe('data', () => {
- it('should not be set', () => { expect(instance).not.toHaveProperty('data') });
+ it('should not be set', () => {
+ expect(instance).not.toHaveProperty('data');
+ });
});
});
- describe(
- 'when message: \'Expected n to be typeof number, got object\', data: undefined',
- () => {
- beforeEach(
- () => { instance = new ProcedureInvalidResponseError('Expected n to be typeof number, got object') }
+ describe("when message: 'Expected n to be typeof number, got object', data: undefined", () => {
+ beforeEach(() => {
+ instance = new ProcedureInvalidResponseError(
+ 'Expected n to be typeof number, got object'
);
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureInvalidResponseError',
- () => { expect(instance).toBeInstanceOf(ProcedureInvalidResponseError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureInvalidResponseError', () => {
+ expect(instance).toBeInstanceOf(ProcedureInvalidResponseError);
+ });
- describe('message', () =>
- it('should be: \'Expected n to be typeof number, got object\'', () => {
- expect(instance.message).toEqual('Expected n to be typeof number, got object')
- }));
+ describe('message', () =>
+ it("should be: 'Expected n to be typeof number, got object'", () => {
+ expect(instance.message).toEqual(
+ 'Expected n to be typeof number, got object'
+ );
+ }));
- describe('data', () => {
- it('should not be set', () => { expect(instance).not.toHaveProperty('data') });
+ describe('data', () => {
+ it('should not be set', () => {
+ expect(instance).not.toHaveProperty('data');
});
- }
- );
+ });
+ });
- describe('when message: undefined, data: { foo: \'bar\' }', () => {
- beforeEach(
- () => { instance = new ProcedureInvalidResponseError(undefined, { foo: 'bar' }) }
- );
+ describe("when message: undefined, data: { foo: 'bar' }", () => {
+ beforeEach(() => {
+ instance = new ProcedureInvalidResponseError(undefined, {
+ foo: 'bar',
+ });
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureInvalidResponseError',
- () => { expect(instance).toBeInstanceOf(ProcedureInvalidResponseError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureInvalidResponseError', () => {
+ expect(instance).toBeInstanceOf(ProcedureInvalidResponseError);
+ });
describe('message', () =>
- it('should be: \'The response from the server was invalid.\'', () => {
- expect(instance.message).toEqual('The response from the server was invalid.')
+ it("should be: 'The response from the server was invalid.'", () => {
+ expect(instance.message).toEqual(
+ 'The response from the server was invalid.'
+ );
}));
describe('data', () => {
- it('should equal: { foo: \'bar\' }', () => { expect(instance.data).toStrictEqual({ foo: 'bar' }) });
+ it("should equal: { foo: 'bar' }", () => {
+ expect(instance.data).toStrictEqual({ foo: 'bar' });
+ });
});
});
});
@@ -482,80 +542,83 @@ describe('ProcedureInternalServerError', () => {
let instance: ProcedureInternalServerError;
describe('when no parameters passed', () => {
- beforeEach(() => { instance = new ProcedureInternalServerError() });
+ beforeEach(() => {
+ instance = new ProcedureInternalServerError();
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureInternalServerError',
- () => { expect(instance).toBeInstanceOf(ProcedureInternalServerError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureInternalServerError', () => {
+ expect(instance).toBeInstanceOf(ProcedureInternalServerError);
+ });
describe('message', () =>
- it(
- 'should be: \'An unhandled exception was thrown while attempting to handle the procedure.\'',
- () => {
- expect(instance.message).toEqual('An unhandled exception was thrown while attempting to handle the procedure.')
- }
- ));
+ it("should be: 'An unhandled exception was thrown while attempting to handle the procedure.'", () => {
+ expect(instance.message).toEqual(
+ 'An unhandled exception was thrown while attempting to handle the procedure.'
+ );
+ }));
describe('data', () => {
- it('should not be set', () => { expect(instance).not.toHaveProperty('data') });
+ it('should not be set', () => {
+ expect(instance).not.toHaveProperty('data');
+ });
});
});
- describe(
- 'when message: \'Expected n to be typeof number, got object\', data: undefined',
- () => {
- beforeEach(
- () => { instance = new ProcedureInternalServerError('Expected n to be typeof number, got object') }
+ describe("when message: 'Expected n to be typeof number, got object', data: undefined", () => {
+ beforeEach(() => {
+ instance = new ProcedureInternalServerError(
+ 'Expected n to be typeof number, got object'
);
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureInternalServerError',
- () => { expect(instance).toBeInstanceOf(ProcedureInternalServerError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureInternalServerError', () => {
+ expect(instance).toBeInstanceOf(ProcedureInternalServerError);
+ });
- describe('message', () =>
- it('should be: \'Expected n to be typeof number, got object\'', () => {
- expect(instance.message).toEqual('Expected n to be typeof number, got object')
- }));
+ describe('message', () =>
+ it("should be: 'Expected n to be typeof number, got object'", () => {
+ expect(instance.message).toEqual(
+ 'Expected n to be typeof number, got object'
+ );
+ }));
- describe('data', () => {
- it('should not be set', () => { expect(instance).not.toHaveProperty('data') });
+ describe('data', () => {
+ it('should not be set', () => {
+ expect(instance).not.toHaveProperty('data');
});
- }
- );
+ });
+ });
- describe('when message: undefined, data: { foo: \'bar\' }', () => {
- beforeEach(
- () => { instance = new ProcedureInternalServerError(undefined, { foo: 'bar' }) }
- );
+ describe("when message: undefined, data: { foo: 'bar' }", () => {
+ beforeEach(() => {
+ instance = new ProcedureInternalServerError(undefined, {
+ foo: 'bar',
+ });
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureInternalServerError',
- () => { expect(instance).toBeInstanceOf(ProcedureInternalServerError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureInternalServerError', () => {
+ expect(instance).toBeInstanceOf(ProcedureInternalServerError);
+ });
describe('message', () =>
- it(
- 'should be: \'An unhandled exception was thrown while attempting to handle the procedure.\'',
- () => { expect(instance.message).toEqual('An unhandled exception was thrown while attempting to handle the procedure.') }
- ));
+ it("should be: 'An unhandled exception was thrown while attempting to handle the procedure.'", () => {
+ expect(instance.message).toEqual(
+ 'An unhandled exception was thrown while attempting to handle the procedure.'
+ );
+ }));
describe('data', () => {
- it('should equal: { foo: \'bar\' }', () => {
- expect(instance.data).toStrictEqual({ foo: 'bar' })
+ it("should equal: { foo: 'bar' }", () => {
+ expect(instance.data).toStrictEqual({ foo: 'bar' });
});
});
});
@@ -567,76 +630,83 @@ describe('ProcedureExecutionError', () => {
let instance: ProcedureExecutionError;
describe('when no parameters passed', () => {
- beforeEach(() => { instance = new ProcedureExecutionError() });
+ beforeEach(() => {
+ instance = new ProcedureExecutionError();
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureExecutionError',
- () => { expect(instance).toBeInstanceOf(ProcedureExecutionError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureExecutionError', () => {
+ expect(instance).toBeInstanceOf(ProcedureExecutionError);
+ });
describe('message', () =>
- it(
- 'should be: \'An unhandled exception was thrown during procedure execution.\'',
- () => { expect(instance.message).toEqual('An unhandled exception was thrown during procedure execution.') }
- ));
+ it("should be: 'An unhandled exception was thrown during procedure execution.'", () => {
+ expect(instance.message).toEqual(
+ 'An unhandled exception was thrown during procedure execution.'
+ );
+ }));
describe('data', () => {
- it('should not be set', () => { expect(instance).not.toHaveProperty('data') });
+ it('should not be set', () => {
+ expect(instance).not.toHaveProperty('data');
+ });
});
});
- describe(
- 'when message: \'Expected n to be typeof number, got object\', data: undefined',
- () => {
- beforeEach(
- () => { instance = new ProcedureExecutionError('Expected n to be typeof number, got object') }
+ describe("when message: 'Expected n to be typeof number, got object', data: undefined", () => {
+ beforeEach(() => {
+ instance = new ProcedureExecutionError(
+ 'Expected n to be typeof number, got object'
);
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureExecutionError',
- () => { expect(instance).toBeInstanceOf(ProcedureExecutionError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureExecutionError', () => {
+ expect(instance).toBeInstanceOf(ProcedureExecutionError);
+ });
- describe('message', () =>
- it('should be: \'Expected n to be typeof number, got object\'', () => {
- expect(instance.message).toEqual('Expected n to be typeof number, got object')
- }));
+ describe('message', () =>
+ it("should be: 'Expected n to be typeof number, got object'", () => {
+ expect(instance.message).toEqual(
+ 'Expected n to be typeof number, got object'
+ );
+ }));
- describe('data', () => {
- it('should not be set', () => { expect(instance).not.toHaveProperty('data') });
+ describe('data', () => {
+ it('should not be set', () => {
+ expect(instance).not.toHaveProperty('data');
});
- }
- );
+ });
+ });
- describe('when message: undefined, data: { foo: \'bar\' }', () => {
- beforeEach(() => { instance = new ProcedureExecutionError(undefined, { foo: 'bar' }) });
+ describe("when message: undefined, data: { foo: 'bar' }", () => {
+ beforeEach(() => {
+ instance = new ProcedureExecutionError(undefined, {
+ foo: 'bar',
+ });
+ });
- it(
- 'should be: instanceof ProcedureError',
- () => { expect(instance).toBeInstanceOf(ProcedureError) }
- );
- it(
- 'should be: instanceof ProcedureExecutionError',
- () => { expect(instance).toBeInstanceOf(ProcedureExecutionError) }
- );
+ it('should be: instanceof ProcedureError', () => {
+ expect(instance).toBeInstanceOf(ProcedureError);
+ });
+ it('should be: instanceof ProcedureExecutionError', () => {
+ expect(instance).toBeInstanceOf(ProcedureExecutionError);
+ });
describe('message', () =>
- it(
- 'should be: \'An unhandled exception was thrown during procedure execution.\'',
- () => { expect(instance.message).toEqual('An unhandled exception was thrown during procedure execution.') }
- ));
+ it("should be: 'An unhandled exception was thrown during procedure execution.'", () => {
+ expect(instance.message).toEqual(
+ 'An unhandled exception was thrown during procedure execution.'
+ );
+ }));
describe('data', () => {
- it('should equal: { foo: \'bar\' }', () => {
- expect(instance.data).toStrictEqual({ foo: 'bar' })
+ it("should equal: { foo: 'bar' }", () => {
+ expect(instance.data).toStrictEqual({ foo: 'bar' });
});
});
});
@@ -646,88 +716,122 @@ describe('ProcedureExecutionError', () => {
describe('isError(object: unknown): object is Error', () => {
let object: unknown;
describe('when object: instanceof Error', () => {
- beforeEach(() => { object = new Error() });
- it('should return: true', () => { expect(isError(object)).toEqual(true) });
+ beforeEach(() => {
+ object = new Error();
+ });
+ it('should return: true', () => {
+ expect(isError(object)).toEqual(true);
+ });
});
describe('when object: undefined', () => {
- beforeEach(() => object = undefined);
- it('should return: false', () => { expect(isError(object)).toEqual(false) });
+ beforeEach(() => (object = undefined));
+ it('should return: false', () => {
+ expect(isError(object)).toEqual(false);
+ });
});
describe('when object: null', () => {
- beforeEach(() => object = null);
- it('should return: false', () => { expect(isError(object)).toEqual(false) });
+ beforeEach(() => (object = null));
+ it('should return: false', () => {
+ expect(isError(object)).toEqual(false);
+ });
});
describe('when object: instanceof TypeError', () => {
- beforeEach(() => object = new TypeError());
- it('should return: true', () => { expect(isError(object)).toEqual(true) });
+ beforeEach(() => (object = new TypeError()));
+ it('should return: true', () => {
+ expect(isError(object)).toEqual(true);
+ });
});
- describe('when object: { name: \'Foo\', message: \'Bar\' }', () => {
- beforeEach(() => object = { name: 'Foo', message: 'Bar' });
- it('should return: true', () => { expect(isError(object)).toEqual(true) });
+ describe("when object: { name: 'Foo', message: 'Bar' }", () => {
+ beforeEach(() => (object = { name: 'Foo', message: 'Bar' }));
+ it('should return: true', () => {
+ expect(isError(object)).toEqual(true);
+ });
});
- describe('when object: { name: \'Foo\' }', () => {
- beforeEach(() => object = { name: 'Foo' });
- it('should return: false', () => { expect(isError(object)).toEqual(false) });
- })
+ describe("when object: { name: 'Foo' }", () => {
+ beforeEach(() => (object = { name: 'Foo' }));
+ it('should return: false', () => {
+ expect(isError(object)).toEqual(false);
+ });
+ });
});
describe('isProcedureError(object: unknown): object is ProcedureError', () => {
let object: unknown;
describe('when object: instanceof Error', () => {
- beforeEach(() => object = new Error());
- it('should return: false', () => { expect(isProcedureError(object)).toEqual(false) });
+ beforeEach(() => (object = new Error()));
+ it('should return: false', () => {
+ expect(isProcedureError(object)).toEqual(false);
+ });
});
describe('when object: undefined', () => {
- beforeEach(() => object = undefined);
- it('should return: false', () => { expect(isProcedureError(object)).toEqual(false) });
+ beforeEach(() => (object = undefined));
+ it('should return: false', () => {
+ expect(isProcedureError(object)).toEqual(false);
+ });
});
describe('when object: null', () => {
- beforeEach(() => object = null);
- it('should return: false', () => { expect(isProcedureError(object)).toEqual(false) });
+ beforeEach(() => (object = null));
+ it('should return: false', () => {
+ expect(isProcedureError(object)).toEqual(false);
+ });
});
describe('when object: instanceof TypeError', () => {
- beforeEach(() => object = new TypeError());
- it('should return: false', () => { expect(isProcedureError(object)).toEqual(false) });
+ beforeEach(() => (object = new TypeError()));
+ it('should return: false', () => {
+ expect(isProcedureError(object)).toEqual(false);
+ });
});
- describe('when object: { name: \'Foo\', message: \'Bar\' }', () => {
- beforeEach(() => object = { name: 'Foo', message: 'Bar' });
- it('should return: false', () => { expect(isProcedureError(object)).toEqual(false) });
+ describe("when object: { name: 'Foo', message: 'Bar' }", () => {
+ beforeEach(() => (object = { name: 'Foo', message: 'Bar' }));
+ it('should return: false', () => {
+ expect(isProcedureError(object)).toEqual(false);
+ });
});
- describe('when object: { name: \'Foo\' }', () => {
- beforeEach(() => object = { name: 'Foo' });
- it('should return: false', () => { expect(isProcedureError(object)).toEqual(false) });
- })
+ describe("when object: { name: 'Foo' }", () => {
+ beforeEach(() => (object = { name: 'Foo' }));
+ it('should return: false', () => {
+ expect(isProcedureError(object)).toEqual(false);
+ });
+ });
describe('when object: instanceof ProcedureError', () => {
- beforeEach(() => object = new ProcedureUnknownError());
- it('should return: true', () => { expect(isProcedureError(object)).toEqual(true) });
+ beforeEach(() => (object = new ProcedureUnknownError()));
+ it('should return: true', () => {
+ expect(isProcedureError(object)).toEqual(true);
+ });
});
- describe(
- 'when object: { name: \'ProcedureError\', message: \'foo\', code: ProcedureErrorCodes.NOT_FOUND }',
- () => {
- beforeEach(
- () => object = { name: 'ProcedureError', message: 'foo', code: ProcedureErrorCodes.NOT_FOUND }
- );
- it('should return: true', () => { expect(isProcedureError(object)).toEqual(true) });
- }
- );
-
- describe(
- 'when object: { name: \'ProcedureError\', message: \'foo\', code: -1 }',
- () => {
- beforeEach(() => object = { name: 'ProcedureError', message: 'foo', code: -1 });
- it('should return: false', () => { expect(isProcedureError(object)).toEqual(false) });
- }
- );
+ describe("when object: { name: 'ProcedureError', message: 'foo', code: ProcedureErrorCodes.NOT_FOUND }", () => {
+ beforeEach(
+ () =>
+ (object = {
+ name: 'ProcedureError',
+ message: 'foo',
+ code: ProcedureErrorCodes.NOT_FOUND,
+ })
+ );
+ it('should return: true', () => {
+ expect(isProcedureError(object)).toEqual(true);
+ });
+ });
+
+ describe("when object: { name: 'ProcedureError', message: 'foo', code: -1 }", () => {
+ beforeEach(
+ () =>
+ (object = { name: 'ProcedureError', message: 'foo', code: -1 })
+ );
+ it('should return: false', () => {
+ expect(isProcedureError(object)).toEqual(false);
+ });
+ });
});
diff --git a/test/index.spec.ts b/test/index.spec.ts
index 0b634dd..ea27b32 100644
--- a/test/index.spec.ts
+++ b/test/index.spec.ts
@@ -1,182 +1,262 @@
import { ExtensionCodec } from '@msgpack/msgpack';
import Procedure, { call, ping, tryPing, isPing, Callback } from '../src';
-import { ProcedureErrorCodes, ProcedureInternalServerError } from '../src/errors';
+import {
+ ProcedureErrorCodes,
+ ProcedureInternalServerError,
+} from '../src/errors';
describe('Procedure', () => {
describe('constructor(endpoint: string, callback: Callback, options: Partial)', () => {
let instance: Procedure;
describe('when options.verbose: true', () => {
- beforeEach(() => { instance = new Procedure(x => x, { verbose: true }) });
- describe('verbose', () => it('should be: true', () => { expect(instance.verbose).toEqual(true) }));
+ beforeEach(() => {
+ instance = new Procedure((x) => x, { verbose: true });
+ });
+ describe('verbose', () =>
+ it('should be: true', () => {
+ expect(instance.verbose).toEqual(true);
+ }));
});
describe('when options.verbose is false', () => {
- beforeEach(() => { instance = new Procedure(x => x, { verbose: false }) });
- describe('verbose', () => it('should be: false', () => { expect(instance.verbose).toEqual(false) }));
+ beforeEach(() => {
+ instance = new Procedure((x) => x, { verbose: false });
+ });
+ describe('verbose', () =>
+ it('should be: false', () => {
+ expect(instance.verbose).toEqual(false);
+ }));
});
describe('when options.verbose: undefined', () => {
- beforeEach(() => { instance = new Procedure(x => x) });
- describe('verbose', () => it('should be: false', () => { expect(instance.verbose).toEqual(false) }));
+ beforeEach(() => {
+ instance = new Procedure((x) => x);
+ });
+ describe('verbose', () =>
+ it('should be: false', () => {
+ expect(instance.verbose).toEqual(false);
+ }));
});
describe('when options.workers: undefined', () => {
- beforeEach(() => { instance = new Procedure(x => x) });
- describe('workers', () => it('should be: 1', () => { expect(instance.workers).toEqual(1) }));
+ beforeEach(() => {
+ instance = new Procedure((x) => x);
+ });
+ describe('workers', () =>
+ it('should be: 1', () => {
+ expect(instance.workers).toEqual(1);
+ }));
});
describe('when options.workers: NaN', () => {
- beforeEach(() => { instance = new Procedure(x => x, { workers: NaN }) });
- describe('workers', () => it('should be: 1', () => { expect(instance.workers).toEqual(1) }));
+ beforeEach(() => {
+ instance = new Procedure((x) => x, { workers: NaN });
+ });
+ describe('workers', () =>
+ it('should be: 1', () => {
+ expect(instance.workers).toEqual(1);
+ }));
});
describe('when options.workers: Infinity', () => {
- beforeEach(() => { instance = new Procedure(x => x, { workers: Infinity }) });
- describe('workers', () => it('should be: 1', () => { expect(instance.workers).toEqual(1) }));
+ beforeEach(() => {
+ instance = new Procedure((x) => x, { workers: Infinity });
+ });
+ describe('workers', () =>
+ it('should be: 1', () => {
+ expect(instance.workers).toEqual(1);
+ }));
});
describe('when options.workers: < 1', () => {
- beforeEach(() => { instance = new Procedure(x => x, { workers: 0.8 }) });
- describe('workers', () => it('should be: 1', () => { expect(instance.workers).toEqual(1) }));
+ beforeEach(() => {
+ instance = new Procedure((x) => x, { workers: 0.8 });
+ });
+ describe('workers', () =>
+ it('should be: 1', () => {
+ expect(instance.workers).toEqual(1);
+ }));
});
describe('when options.workers: 10', () => {
- beforeEach(() => { instance = new Procedure(x => x, { workers: 10 }) });
- describe('workers', () => it('should be: 10', () => { expect(instance.workers).toEqual(10) }));
+ beforeEach(() => {
+ instance = new Procedure((x) => x, { workers: 10 });
+ });
+ describe('workers', () =>
+ it('should be: 10', () => {
+ expect(instance.workers).toEqual(10);
+ }));
});
describe('when options.extensionCodec: undefined', () => {
- beforeEach(() => { instance = new Procedure(x => x) });
- describe('extensionCodec', () => it(
- 'should be: undefined',
- () => { expect(instance.extensionCodec).toBeUndefined() }
- ));
- })
+ beforeEach(() => {
+ instance = new Procedure((x) => x);
+ });
+ describe('extensionCodec', () =>
+ it('should be: undefined', () => {
+ expect(instance.extensionCodec).toBeUndefined();
+ }));
+ });
describe('when options.extensionCodec: instanceof ExtensionCodec', () => {
- beforeEach(
- () => { instance = new Procedure(x => x, { extensionCodec: new ExtensionCodec() }) }
- );
- describe('extensionCodec', () => it(
- 'should be: instanceof ExtensionCodec',
- () => { expect(instance.extensionCodec).toBeInstanceOf(ExtensionCodec) }
- ));
+ beforeEach(() => {
+ instance = new Procedure((x) => x, {
+ extensionCodec: new ExtensionCodec(),
+ });
+ });
+ describe('extensionCodec', () =>
+ it('should be: instanceof ExtensionCodec', () => {
+ expect(instance.extensionCodec).toBeInstanceOf(
+ ExtensionCodec
+ );
+ }));
});
});
describe('set verbose(value: boolean)', () => {
let instance: Procedure;
- beforeEach(() => { instance = new Procedure(x => x) });
+ beforeEach(() => {
+ instance = new Procedure((x) => x);
+ });
describe('when value: true', () => {
- beforeEach(() => { instance.verbose = true });
- describe('verbose', () => it('should be: true', () => { expect(instance.verbose).toEqual(true) }));
+ beforeEach(() => {
+ instance.verbose = true;
+ });
+ describe('verbose', () =>
+ it('should be: true', () => {
+ expect(instance.verbose).toEqual(true);
+ }));
});
describe('when value: false', () => {
- beforeEach(() => { instance.verbose = false });
- describe('verbose', () => it('should be: false', () => { expect(instance.verbose).toEqual(false) }));
+ beforeEach(() => {
+ instance.verbose = false;
+ });
+ describe('verbose', () =>
+ it('should be: false', () => {
+ expect(instance.verbose).toEqual(false);
+ }));
});
});
describe('set extensionCodec(value: ExtensionCodec | undefined)', () => {
let instance: Procedure;
- beforeEach(() => { instance = new Procedure(x => x) });
+ beforeEach(() => {
+ instance = new Procedure((x) => x);
+ });
describe('when value: undefined', () => {
- beforeEach(() => { instance.extensionCodec = undefined });
- describe('extensionCodec', () => it(
- 'should be: undefined',
- () => { expect(instance.extensionCodec).toBeUndefined() }
- ));
- })
+ beforeEach(() => {
+ instance.extensionCodec = undefined;
+ });
+ describe('extensionCodec', () =>
+ it('should be: undefined', () => {
+ expect(instance.extensionCodec).toBeUndefined();
+ }));
+ });
describe('when value: instanceof ExtensionCodec', () => {
- beforeEach(() => { instance.extensionCodec = new ExtensionCodec() });
- describe('extensionCodec', () => it(
- 'should be: instanceof ExtensionCodec',
- () => { expect(instance.extensionCodec).toBeInstanceOf(ExtensionCodec) }
- ));
+ beforeEach(() => {
+ instance.extensionCodec = new ExtensionCodec();
+ });
+ describe('extensionCodec', () =>
+ it('should be: instanceof ExtensionCodec', () => {
+ expect(instance.extensionCodec).toBeInstanceOf(
+ ExtensionCodec
+ );
+ }));
});
});
describe('set optionalParameterSupport(value: boolean)', () => {
let instance: Procedure;
- beforeEach(() => { instance = new Procedure(x => x) });
+ beforeEach(() => {
+ instance = new Procedure((x) => x);
+ });
describe('when value: true', () => {
- beforeEach(() => { instance.optionalParameterSupport = true });
- describe('verbose', () => it(
- 'should be: true',
- () => { expect(instance.optionalParameterSupport).toEqual(true) }
- ));
+ beforeEach(() => {
+ instance.optionalParameterSupport = true;
+ });
+ describe('verbose', () =>
+ it('should be: true', () => {
+ expect(instance.optionalParameterSupport).toEqual(true);
+ }));
});
describe('when value: false', () => {
- beforeEach(() => instance.optionalParameterSupport = false);
- describe('verbose', () => it(
- 'should be: false',
- () => { expect(instance.optionalParameterSupport).toEqual(false) }
- ));
+ beforeEach(() => (instance.optionalParameterSupport = false));
+ describe('verbose', () =>
+ it('should be: false', () => {
+ expect(instance.optionalParameterSupport).toEqual(false);
+ }));
});
});
describe('set ignoreUndefinedProperties(value: boolean)', () => {
let instance: Procedure;
- beforeEach(() => instance = new Procedure(x => x));
+ beforeEach(() => (instance = new Procedure((x) => x)));
describe('when value: true', () => {
- beforeEach(() => instance.ignoreUndefinedProperties = true);
- describe('verbose', () => it(
- 'should be: true',
- () => { expect(instance.ignoreUndefinedProperties).toEqual(true) }
- ));
+ beforeEach(() => (instance.ignoreUndefinedProperties = true));
+ describe('verbose', () =>
+ it('should be: true', () => {
+ expect(instance.ignoreUndefinedProperties).toEqual(true);
+ }));
});
describe('when value: false', () => {
- beforeEach(() => instance.ignoreUndefinedProperties = false);
- describe('verbose', () => it(
- 'should be: false',
- () => { expect(instance.ignoreUndefinedProperties).toEqual(false) }
- ));
+ beforeEach(() => (instance.ignoreUndefinedProperties = false));
+ describe('verbose', () =>
+ it('should be: false', () => {
+ expect(instance.ignoreUndefinedProperties).toEqual(false);
+ }));
});
});
describe('bind(): this', () => {
let instance: Procedure;
- beforeEach(() => instance = new Procedure(x => x));
- afterEach(() => { instance.unbind().removeAllListeners(); });
+ beforeEach(() => (instance = new Procedure((x) => x)));
+ afterEach(() => {
+ instance.unbind().removeAllListeners();
+ });
- it(
- 'should return: this',
- () => { expect(instance.bind('inproc://foo')).toEqual(instance) }
- );
+ it('should return: this', () => {
+ expect(instance.bind('inproc://foo')).toEqual(instance);
+ });
- describe('when endpoint: \'\'', () => {
- beforeEach(() => instance = new Procedure(x => x));
+ describe("when endpoint: ''", () => {
+ beforeEach(() => (instance = new Procedure((x) => x)));
- describe('instance', () => it('should emit: \'error\'', () => {
- const error = jest.fn((error: unknown) => {
- expect(error).toBeInstanceOf(ProcedureInternalServerError);
- expect(error).toHaveProperty('data');
- expect((error).data).toHaveProperty('error');
- });
- instance.on('error', error).bind('');
- expect(error).toHaveBeenCalledTimes(1);
- }));
+ describe('instance', () =>
+ it("should emit: 'error'", () => {
+ const error = jest.fn((error: unknown) => {
+ expect(error).toBeInstanceOf(
+ ProcedureInternalServerError
+ );
+ expect(error).toHaveProperty('data');
+ expect(
+ (error).data
+ ).toHaveProperty('error');
+ });
+ instance.on('error', error).bind('');
+ expect(error).toHaveBeenCalledTimes(1);
+ }));
describe('when verbose: true', () => {
let error: jest.SpyInstance;
beforeEach(() => {
- instance = new Procedure(x => x);
+ instance = new Procedure((x) => x);
instance.verbose = true;
error = jest.spyOn(console, 'error').mockImplementation();
});
- describe('instance', () => it('should call console.error', () => {
- instance.bind('');
- expect(error).toHaveBeenCalledTimes(1);
- }));
+ describe('instance', () =>
+ it('should call console.error', () => {
+ instance.bind('');
+ expect(error).toHaveBeenCalledTimes(1);
+ }));
afterEach(() => {
instance.verbose = false;
error.mockReset();
@@ -184,41 +264,48 @@ describe('Procedure', () => {
});
});
- describe('when endpoint: \'inproc://Procedure\'', () => {
- beforeEach(() => instance = new Procedure(x => x));
- describe('instance', () => it('should not emit: \'error\'', () => {
- const error = jest.fn();
- instance.on('error', error).bind('inproc://Procedure');
- expect(error).not.toHaveBeenCalled();
- }));
+ describe("when endpoint: 'inproc://Procedure'", () => {
+ beforeEach(() => (instance = new Procedure((x) => x)));
+ describe('instance', () =>
+ it("should not emit: 'error'", () => {
+ const error = jest.fn();
+ instance.on('error', error).bind('inproc://Procedure');
+ expect(error).not.toHaveBeenCalled();
+ }));
describe('when already bound', () => {
beforeEach(() => instance.bind('inproc://Procedure'));
- describe('instance', () => it('should emit: \'unbind\'', () => {
- const unbind = jest.fn();
- instance.on('unbind', unbind).bind('inproc://Procedure');
- expect(unbind).toHaveBeenCalledTimes(1);
- }));
+ describe('instance', () =>
+ it("should emit: 'unbind'", () => {
+ const unbind = jest.fn();
+ instance
+ .on('unbind', unbind)
+ .bind('inproc://Procedure');
+ expect(unbind).toHaveBeenCalledTimes(1);
+ }));
});
});
});
describe('unbind(): this', () => {
let instance: Procedure;
- beforeEach(() => instance = new Procedure(x => x));
+ beforeEach(() => (instance = new Procedure((x) => x)));
- it('should return: this', () => { expect(instance.unbind()).toEqual(instance) });
+ it('should return: this', () => {
+ expect(instance.unbind()).toEqual(instance);
+ });
- describe('when instance bound to endpoint: \'inproc://Procedure\'', () => {
+ describe("when instance bound to endpoint: 'inproc://Procedure'", () => {
beforeEach(() => {
- instance = new Procedure(x => x);
+ instance = new Procedure((x) => x);
instance.bind('inproc://Procedure');
});
- describe('instance', () => it('should emit: \'unbind\'', () => {
- const unbind = jest.fn();
- instance.on('unbind', unbind).unbind();
- expect(unbind).toHaveBeenCalledTimes(1);
- }));
+ describe('instance', () =>
+ it("should emit: 'unbind'", () => {
+ const unbind = jest.fn();
+ instance.on('unbind', unbind).unbind();
+ expect(unbind).toHaveBeenCalledTimes(1);
+ }));
describe('when verbose: true', () => {
let log: jest.SpyInstance;
@@ -227,10 +314,11 @@ describe('Procedure', () => {
instance.verbose = true;
log = jest.spyOn(console, 'log').mockImplementation();
});
- describe('instance', () => it('should call console.log', () => {
- instance.unbind();
- expect(log).toHaveBeenCalledTimes(2);
- }));
+ describe('instance', () =>
+ it('should call console.log', () => {
+ instance.unbind();
+ expect(log).toHaveBeenCalledTimes(2);
+ }));
afterEach(() => {
instance.verbose = false;
log.mockReset();
@@ -248,55 +336,140 @@ describe('call(endpoint: string, input: Input | null, options: Partial {
- describe(
- 'when procedure callback: Callback (simple accumulator function)',
- () => {
- beforeEach(() => {
- let i = 0;
- fn = jest.fn(>((n: number) => {
- if (typeof n !== 'number') {
- throw new TypeError('Expected a number');
- }
+ describe('when procedure callback: Callback (simple accumulator function)', () => {
+ beforeEach(() => {
+ let i = 0;
+ fn = jest.fn(>((n: number) => {
+ if (typeof n !== 'number') {
+ throw new TypeError('Expected a number');
+ }
- return i += n;
- }));
- procedureEndpoint = 'inproc://Procedure/Add';
- procedure = new Procedure(fn, { workers: 3 });
- procedure.bind(procedureEndpoint);
+ return (i += n);
+ }));
+ procedureEndpoint = 'inproc://Procedure/Add';
+ procedure = new Procedure(fn, { workers: 3 });
+ procedure.bind(procedureEndpoint);
+ });
+
+ describe('when endpoint: correct', () => {
+ beforeEach(() => (callEndpoint = procedureEndpoint));
+
+ describe('when input: 0', () => {
+ beforeEach(() => (input = 0));
+
+ it('should emit: data, with parameter: 0', async () => {
+ let x: unknown = undefined;
+ const data = jest.fn((data: unknown) => (x = data));
+ procedure.on('data', data);
+ await call(callEndpoint, input);
+ expect(data).toHaveBeenCalledTimes(1);
+ expect(x).toEqual(0);
+ });
+
+ it('should resolve: 0', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).resolves.toEqual(0);
+ });
+
+ afterEach(() => (input = undefined));
+
+ describe('when verbose: true', () => {
+ let log: jest.SpyInstance;
+ beforeEach(() => {
+ procedure.verbose = true;
+ log = jest
+ .spyOn(console, 'log')
+ .mockImplementation();
+ });
+
+ it('should call console.log', async () => {
+ await call(callEndpoint, input);
+ expect(log).toHaveBeenCalledTimes(3);
+ });
+
+ afterEach(() => {
+ procedure.verbose = false;
+ log.mockReset();
+ });
+ });
+ });
+
+ describe("when input: 'foo'", () => {
+ beforeEach(() => (input = 'foo'));
+
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
+ });
+ });
+
+ afterEach(() => (input = undefined));
+ });
+
+ describe('when input: 1000', () => {
+ beforeEach(() => (input = 1000));
+
+ it('should resolve: 1000', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).resolves.toEqual(input);
+ });
+
+ afterEach(() => (input = undefined));
});
- describe('when endpoint: correct', () => {
- beforeEach(() => callEndpoint = procedureEndpoint);
+ describe('when input: undefined', () => {
+ beforeEach(() => (input = undefined));
+
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
+ });
+ });
+ });
+ describe('when ping: 100', () => {
describe('when input: 0', () => {
- beforeEach(() => input = 0);
+ beforeEach(() => (input = 0));
it('should emit: data, with parameter: 0', async () => {
let x: unknown = undefined;
- const data = jest.fn((data: unknown) => x = data);
+ const data = jest.fn((data: unknown) => (x = data));
procedure.on('data', data);
- await call(callEndpoint, input);
+ await call(callEndpoint, input, {
+ ping: 100,
+ });
expect(data).toHaveBeenCalledTimes(1);
expect(x).toEqual(0);
});
- it(
- 'should resolve: 0',
- async () => { await expect(call(callEndpoint, input)).resolves.toEqual(0) }
- );
+ it('should resolve: 0', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).resolves.toEqual(0);
+ });
- afterEach(() => input = undefined);
+ afterEach(() => (input = undefined));
describe('when verbose: true', () => {
let log: jest.SpyInstance;
beforeEach(() => {
procedure.verbose = true;
- log = jest.spyOn(console, 'log').mockImplementation();
+ log = jest
+ .spyOn(console, 'log')
+ .mockImplementation();
});
it('should call console.log', async () => {
- await call(callEndpoint, input);
- expect(log).toHaveBeenCalledTimes(3);
+ await call(callEndpoint, input, {
+ ping: 100,
+ });
+ expect(log).toHaveBeenCalled();
});
afterEach(() => {
@@ -306,180 +479,186 @@ describe('call(endpoint: string, input: Input | null, options: Partial {
- beforeEach(() => input = 'foo');
+ describe("when input: 'foo'", () => {
+ beforeEach(() => (input = 'foo'));
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
+ });
+ });
- afterEach(() => input = undefined);
+ afterEach(() => (input = undefined));
});
describe('when input: 1000', () => {
- beforeEach(() => input = 1000);
+ beforeEach(() => (input = 1000));
- it(
- 'should resolve: 1000',
- async () => { await expect(call(callEndpoint, input)).resolves.toEqual(input) }
- );
+ it('should resolve: 1000', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).resolves.toEqual(input);
+ });
- afterEach(() => input = undefined);
+ afterEach(() => (input = undefined));
});
describe('when input: undefined', () => {
- beforeEach(() => input = undefined);
-
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
- });
+ beforeEach(() => (input = undefined));
- describe('when ping: 100', () => {
- describe('when input: 0', () => {
- beforeEach(() => input = 0);
-
- it('should emit: data, with parameter: 0', async () => {
- let x: unknown = undefined;
- const data = jest.fn((data: unknown) => x = data);
- procedure.on('data', data);
- await call(callEndpoint, input, { ping: 100 });
- expect(data).toHaveBeenCalledTimes(1);
- expect(x).toEqual(0);
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
});
+ });
+ });
+ });
- it(
- 'should resolve: 0',
- async () => { await expect(call(callEndpoint, input, { ping: 100 })).resolves.toEqual(0) }
- );
+ afterEach(() => (callEndpoint = undefined));
+ });
- afterEach(() => input = undefined);
+ // TODO: when endpoint: incorrect
- describe('when verbose: true', () => {
- let log: jest.SpyInstance;
- beforeEach(() => {
- procedure.verbose = true;
- log = jest.spyOn(console, 'log').mockImplementation();
- });
+ afterEach(() => procedure.unbind());
+ });
- it('should call console.log', async () => {
- await call(callEndpoint, input, { ping: 100 });
- expect(log).toHaveBeenCalled();
- });
+ describe('when procedure callback: Callback (testing nullish returns)', () => {
+ beforeEach(() => {
+ fn = jest.fn(>((n: number) => {
+ if (typeof n !== 'number') {
+ throw new TypeError('Expected a number');
+ }
- afterEach(() => {
- procedure.verbose = false;
- log.mockReset();
- });
- });
- });
+ return null;
+ }));
+ procedureEndpoint = 'inproc://Procedure/ReturnsNull';
+ procedure = new Procedure(fn, { workers: 3 });
+ procedure.bind(procedureEndpoint);
+ });
- describe('when input: \'foo\'', () => {
- beforeEach(() => input = 'foo');
+ describe('when endpoint: correct', () => {
+ beforeEach(() => (callEndpoint = procedureEndpoint));
+
+ describe('when input: 0', () => {
+ beforeEach(() => (input = 0));
+
+ it('should emit: data, with parameter: 0', async () => {
+ let x: unknown = undefined;
+ const data = jest.fn((data: unknown) => (x = data));
+ procedure.on('data', data);
+ await call(callEndpoint, input);
+ expect(data).toHaveBeenCalledTimes(1);
+ expect(x).toEqual(0);
+ });
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ it('should resolve: undefined', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).resolves.toBeUndefined();
+ });
- afterEach(() => input = undefined);
- });
+ afterEach(() => (input = undefined));
- describe('when input: 1000', () => {
- beforeEach(() => input = 1000);
+ describe('when verbose: true', () => {
+ let log: jest.SpyInstance;
+ beforeEach(() => {
+ procedure.verbose = true;
+ log = jest
+ .spyOn(console, 'log')
+ .mockImplementation();
+ });
- it(
- 'should resolve: 1000',
- async () => { await expect(call(callEndpoint, input, { ping: 100 })).resolves.toEqual(input) }
- );
+ it('should call console.log', async () => {
+ await call(callEndpoint, input);
+ expect(log).toHaveBeenCalledTimes(3);
+ });
- afterEach(() => input = undefined);
+ afterEach(() => {
+ procedure.verbose = false;
+ log.mockReset();
});
+ });
+ });
- describe('when input: undefined', () => {
- beforeEach(() => input = undefined);
+ describe("when input: 'foo'", () => {
+ beforeEach(() => (input = 'foo'));
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
});
});
- afterEach(() => callEndpoint = undefined);
+ afterEach(() => (input = undefined));
});
- // TODO: when endpoint: incorrect
-
- afterEach(() => procedure.unbind());
- }
- );
+ describe('when input: 1000', () => {
+ beforeEach(() => (input = 1000));
- describe(
- 'when procedure callback: Callback (testing nullish returns)',
- () => {
- beforeEach(() => {
- fn = jest.fn(>((n: number) => {
- if (typeof n !== 'number') {
- throw new TypeError('Expected a number');
- }
+ it('should resolve: undefined', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).resolves.toBeUndefined();
+ });
- return null;
- }));
- procedureEndpoint = 'inproc://Procedure/ReturnsNull';
- procedure = new Procedure(fn, { workers: 3 });
- procedure.bind(procedureEndpoint);
+ afterEach(() => (input = undefined));
});
- describe('when endpoint: correct', () => {
- beforeEach(() => callEndpoint = procedureEndpoint);
+ describe('when input: undefined', () => {
+ beforeEach(() => (input = undefined));
+
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
+ });
+ });
+ });
+ describe('when ping: 100', () => {
describe('when input: 0', () => {
- beforeEach(() => input = 0);
+ beforeEach(() => (input = 0));
it('should emit: data, with parameter: 0', async () => {
let x: unknown = undefined;
- const data = jest.fn((data: unknown) => x = data);
+ const data = jest.fn((data: unknown) => (x = data));
procedure.on('data', data);
- await call(callEndpoint, input);
+ await call(callEndpoint, input, {
+ ping: 100,
+ });
expect(data).toHaveBeenCalledTimes(1);
expect(x).toEqual(0);
});
- it(
- 'should resolve: undefined',
- async () => {
- await expect(call(callEndpoint, input))
- .resolves.toBeUndefined()
- }
- );
+ it('should resolve: undefined', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).resolves.toBeUndefined();
+ });
- afterEach(() => input = undefined);
+ afterEach(() => (input = undefined));
describe('when verbose: true', () => {
let log: jest.SpyInstance;
beforeEach(() => {
procedure.verbose = true;
- log = jest.spyOn(console, 'log').mockImplementation();
+ log = jest
+ .spyOn(console, 'log')
+ .mockImplementation();
});
it('should call console.log', async () => {
- await call(callEndpoint, input);
- expect(log).toHaveBeenCalledTimes(3);
+ await call(callEndpoint, input, {
+ ping: 100,
+ });
+ expect(log).toHaveBeenCalled();
});
afterEach(() => {
@@ -489,189 +668,186 @@ describe('call(endpoint: string, input: Input | null, options: Partial {
- beforeEach(() => input = 'foo');
+ describe("when input: 'foo'", () => {
+ beforeEach(() => (input = 'foo'));
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
+ });
+ });
- afterEach(() => input = undefined);
+ afterEach(() => (input = undefined));
});
describe('when input: 1000', () => {
- beforeEach(() => input = 1000);
-
- it(
- 'should resolve: undefined',
- async () => {
- await expect(call(callEndpoint, input))
- .resolves.toBeUndefined()
- }
- );
+ beforeEach(() => (input = 1000));
- afterEach(() => input = undefined);
- });
+ it('should resolve: undefined', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).resolves.toBeUndefined();
+ });
- describe('when input: undefined', () => {
- beforeEach(() => input = undefined);
-
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ afterEach(() => (input = undefined));
});
- describe('when ping: 100', () => {
- describe('when input: 0', () => {
- beforeEach(() => input = 0);
+ describe('when input: undefined', () => {
+ beforeEach(() => (input = undefined));
- it('should emit: data, with parameter: 0', async () => {
- let x: unknown = undefined;
- const data = jest.fn((data: unknown) => x = data);
- procedure.on('data', data);
- await call(callEndpoint, input, { ping: 100 });
- expect(data).toHaveBeenCalledTimes(1);
- expect(x).toEqual(0);
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
});
+ });
+ });
+ });
+
+ afterEach(() => (callEndpoint = undefined));
+ });
- it(
- 'should resolve: undefined',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .resolves.toBeUndefined()
- }
- );
+ // TODO: when endpoint: incorrect
- afterEach(() => input = undefined);
+ afterEach(() => procedure.unbind());
+ });
- describe('when verbose: true', () => {
- let log: jest.SpyInstance;
- beforeEach(() => {
- procedure.verbose = true;
- log = jest.spyOn(console, 'log').mockImplementation();
- });
+ describe('when procedure callback: Callback (testing nullish returns)', () => {
+ beforeEach(() => {
+ fn = jest.fn(>((n: number) => {
+ if (typeof n !== 'number') {
+ throw new TypeError('Expected a number');
+ }
- it('should call console.log', async () => {
- await call(callEndpoint, input, { ping: 100 });
- expect(log).toHaveBeenCalled();
- });
+ return;
+ }));
+ procedureEndpoint = 'inproc://Procedure/ReturnsVoid';
+ procedure = new Procedure(fn, { workers: 3 });
+ procedure.bind(procedureEndpoint);
+ });
- afterEach(() => {
- procedure.verbose = false;
- log.mockReset();
- });
- });
- });
+ describe('when endpoint: correct', () => {
+ beforeEach(() => (callEndpoint = procedureEndpoint));
+
+ describe('when input: 0', () => {
+ beforeEach(() => (input = 0));
+
+ it('should emit: data, with parameter: 0', async () => {
+ let x: unknown = undefined;
+ const data = jest.fn((data: unknown) => (x = data));
+ procedure.on('data', data);
+ await call(callEndpoint, input);
+ expect(data).toHaveBeenCalledTimes(1);
+ expect(x).toEqual(0);
+ });
- describe('when input: \'foo\'', () => {
- beforeEach(() => input = 'foo');
+ it('should resolve: undefined', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).resolves.toBeUndefined();
+ });
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ afterEach(() => (input = undefined));
- afterEach(() => input = undefined);
+ describe('when verbose: true', () => {
+ let log: jest.SpyInstance;
+ beforeEach(() => {
+ procedure.verbose = true;
+ log = jest
+ .spyOn(console, 'log')
+ .mockImplementation();
});
- describe('when input: 1000', () => {
- beforeEach(() => input = 1000);
-
- it(
- 'should resolve: undefined',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .resolves.toBeUndefined()
- }
- );
+ it('should call console.log', async () => {
+ await call(callEndpoint, input);
+ expect(log).toHaveBeenCalledTimes(3);
+ });
- afterEach(() => input = undefined);
+ afterEach(() => {
+ procedure.verbose = false;
+ log.mockReset();
});
+ });
+ });
- describe('when input: undefined', () => {
- beforeEach(() => input = undefined);
+ describe("when input: 'foo'", () => {
+ beforeEach(() => (input = 'foo'));
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
});
});
- afterEach(() => callEndpoint = undefined);
+ afterEach(() => (input = undefined));
});
- // TODO: when endpoint: incorrect
-
- afterEach(() => procedure.unbind());
- }
- );
+ describe('when input: 1000', () => {
+ beforeEach(() => (input = 1000));
- describe(
- 'when procedure callback: Callback (testing nullish returns)',
- () => {
- beforeEach(() => {
- fn = jest.fn(>((n: number) => {
- if (typeof n !== 'number') {
- throw new TypeError('Expected a number');
- }
+ it('should resolve: undefined', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).resolves.toBeUndefined();
+ });
- return;
- }));
- procedureEndpoint = 'inproc://Procedure/ReturnsVoid';
- procedure = new Procedure(fn, { workers: 3 });
- procedure.bind(procedureEndpoint);
+ afterEach(() => (input = undefined));
});
- describe('when endpoint: correct', () => {
- beforeEach(() => callEndpoint = procedureEndpoint);
+ describe('when input: undefined', () => {
+ beforeEach(() => (input = undefined));
+
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
+ });
+ });
+ });
+ describe('when ping: 100', () => {
describe('when input: 0', () => {
- beforeEach(() => input = 0);
+ beforeEach(() => (input = 0));
it('should emit: data, with parameter: 0', async () => {
let x: unknown = undefined;
- const data = jest.fn((data: unknown) => x = data);
+ const data = jest.fn((data: unknown) => (x = data));
procedure.on('data', data);
- await call(callEndpoint, input);
+ await call(callEndpoint, input, {
+ ping: 100,
+ });
expect(data).toHaveBeenCalledTimes(1);
expect(x).toEqual(0);
});
- it(
- 'should resolve: undefined',
- async () => {
- await expect(call(callEndpoint, input))
- .resolves.toBeUndefined()
- }
- );
+ it('should resolve: undefined', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).resolves.toBeUndefined();
+ });
- afterEach(() => input = undefined);
+ afterEach(() => (input = undefined));
describe('when verbose: true', () => {
let log: jest.SpyInstance;
beforeEach(() => {
procedure.verbose = true;
- log = jest.spyOn(console, 'log').mockImplementation();
+ log = jest
+ .spyOn(console, 'log')
+ .mockImplementation();
});
it('should call console.log', async () => {
- await call(callEndpoint, input);
- expect(log).toHaveBeenCalledTimes(3);
+ await call(callEndpoint, input, {
+ ping: 100,
+ });
+ expect(log).toHaveBeenCalled();
});
afterEach(() => {
@@ -681,196 +857,196 @@ describe('call(endpoint: string, input: Input | null, options: Partial {
- beforeEach(() => input = 'foo');
+ describe("when input: 'foo'", () => {
+ beforeEach(() => (input = 'foo'));
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
+ });
+ });
- afterEach(() => input = undefined);
+ afterEach(() => (input = undefined));
});
describe('when input: 1000', () => {
- beforeEach(() => input = 1000);
-
- it(
- 'should resolve: undefined',
- async () => {
- await expect(call(callEndpoint, input))
- .resolves.toBeUndefined()
- }
- );
+ beforeEach(() => (input = 1000));
- afterEach(() => input = undefined);
- });
+ it('should resolve: undefined', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).resolves.toBeUndefined();
+ });
- describe('when input: undefined', () => {
- beforeEach(() => input = undefined);
-
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ afterEach(() => (input = undefined));
});
- describe('when ping: 100', () => {
- describe('when input: 0', () => {
- beforeEach(() => input = 0);
+ describe('when input: undefined', () => {
+ beforeEach(() => (input = undefined));
- it('should emit: data, with parameter: 0', async () => {
- let x: unknown = undefined;
- const data = jest.fn((data: unknown) => x = data);
- procedure.on('data', data);
- await call(callEndpoint, input, { ping: 100 });
- expect(data).toHaveBeenCalledTimes(1);
- expect(x).toEqual(0);
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
});
+ });
+ });
+ });
- it(
- 'should resolve: undefined',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .resolves.toBeUndefined()
- }
- );
+ afterEach(() => (callEndpoint = undefined));
+ });
- afterEach(() => input = undefined);
+ // TODO: when endpoint: incorrect
- describe('when verbose: true', () => {
- let log: jest.SpyInstance;
- beforeEach(() => {
- procedure.verbose = true;
- log = jest.spyOn(console, 'log').mockImplementation();
- });
+ afterEach(() => procedure.unbind());
+ });
+ });
- it('should call console.log', async () => {
- await call(callEndpoint, input, { ping: 100 });
- expect(log).toHaveBeenCalled();
- });
+ // TODO: test optionalParameterSupport option works as intended
+ // TODO: test ignoreUndefinedProperties option works as intended
- afterEach(() => {
- procedure.verbose = false;
- log.mockReset();
- });
- });
- });
+ // TODO: when callback asynchronous (completes normally, times out, throws error, infinite timeout, abortion signaled during execution, abortion signaled before execution)
- describe('when input: \'foo\'', () => {
- beforeEach(() => input = 'foo');
+ const winDescribe = process.platform === 'win32' ? describe : describe.skip;
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ winDescribe('IPC tests', () => {
+ describe('when procedure callback: Callback (simple accumulator function)', () => {
+ beforeEach(() => {
+ let i = 0;
+ fn = jest.fn(>((n: number) => {
+ if (typeof n !== 'number') {
+ throw new TypeError('Expected a number');
+ }
- afterEach(() => input = undefined);
- });
+ return (i += n);
+ }));
+ procedureEndpoint = 'ipc://procedure/add';
+ procedure = new Procedure(fn, { workers: 3 });
+ procedure.bind(procedureEndpoint);
+ });
- describe('when input: 1000', () => {
- beforeEach(() => input = 1000);
+ describe('when endpoint: correct', () => {
+ beforeEach(() => (callEndpoint = procedureEndpoint));
+
+ describe('when input: 0', () => {
+ beforeEach(() => (input = 0));
+
+ it('should emit: data, with parameter: 0', async () => {
+ let x: unknown = undefined;
+ const data = jest.fn((data: unknown) => (x = data));
+ procedure.on('data', data);
+ await call(callEndpoint, input);
+ expect(data).toHaveBeenCalledTimes(1);
+ expect(x).toEqual(0);
+ });
+
+ it('should resolve: 0', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).resolves.toEqual(0);
+ });
- it(
- 'should resolve: undefined',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .resolves.toBeUndefined()
- }
- );
+ afterEach(() => (input = undefined));
- afterEach(() => input = undefined);
+ describe('when verbose: true', () => {
+ let log: jest.SpyInstance;
+ beforeEach(() => {
+ procedure.verbose = true;
+ log = jest
+ .spyOn(console, 'log')
+ .mockImplementation();
});
- describe('when input: undefined', () => {
- beforeEach(() => input = undefined);
+ it('should call console.log', async () => {
+ await call(callEndpoint, input);
+ expect(log).toHaveBeenCalledTimes(3);
+ });
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ afterEach(() => {
+ procedure.verbose = false;
+ log.mockReset();
});
});
-
- afterEach(() => callEndpoint = undefined);
});
- // TODO: when endpoint: incorrect
-
- afterEach(() => procedure.unbind());
- }
- );
- });
+ describe("when input: 'foo'", () => {
+ beforeEach(() => (input = 'foo'));
- // TODO: test optionalParameterSupport option works as intended
- // TODO: test ignoreUndefinedProperties option works as intended
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
+ });
+ });
- // TODO: when callback asynchronous (completes normally, times out, throws error, infinite timeout, abortion signaled during execution, abortion signaled before execution)
+ afterEach(() => (input = undefined));
+ });
- const winDescribe = process.platform === 'win32' ? describe : describe.skip;
+ describe('when input: 1000', () => {
+ beforeEach(() => (input = 1000));
- winDescribe('IPC tests', () => {
- describe(
- 'when procedure callback: Callback (simple accumulator function)',
- () => {
- beforeEach(() => {
- let i = 0;
- fn = jest.fn(>((n: number) => {
- if (typeof n !== 'number') {
- throw new TypeError('Expected a number');
- }
+ it('should resolve: 1000', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).resolves.toEqual(input);
+ });
- return i += n;
- }));
- procedureEndpoint = 'ipc://procedure/add';
- procedure = new Procedure(fn, { workers: 3 });
- procedure.bind(procedureEndpoint);
+ afterEach(() => (input = undefined));
});
- describe('when endpoint: correct', () => {
- beforeEach(() => callEndpoint = procedureEndpoint);
+ describe('when input: undefined', () => {
+ beforeEach(() => (input = undefined));
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
+ });
+ });
+ });
+
+ describe('when ping: 100', () => {
describe('when input: 0', () => {
- beforeEach(() => input = 0);
+ beforeEach(() => (input = 0));
it('should emit: data, with parameter: 0', async () => {
let x: unknown = undefined;
- const data = jest.fn((data: unknown) => x = data);
+ const data = jest.fn((data: unknown) => (x = data));
procedure.on('data', data);
- await call(callEndpoint, input);
+ await call(callEndpoint, input, {
+ ping: 100,
+ });
expect(data).toHaveBeenCalledTimes(1);
expect(x).toEqual(0);
});
- it(
- 'should resolve: 0',
- async () => { await expect(call(callEndpoint, input)).resolves.toEqual(0) }
- );
+ it('should resolve: 0', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).resolves.toEqual(0);
+ });
- afterEach(() => input = undefined);
+ afterEach(() => (input = undefined));
describe('when verbose: true', () => {
let log: jest.SpyInstance;
beforeEach(() => {
procedure.verbose = true;
- log = jest.spyOn(console, 'log').mockImplementation();
+ log = jest
+ .spyOn(console, 'log')
+ .mockImplementation();
});
it('should call console.log', async () => {
- await call(callEndpoint, input);
- expect(log).toHaveBeenCalledTimes(3);
+ await call(callEndpoint, input, {
+ ping: 100,
+ });
+ expect(log).toHaveBeenCalled();
});
afterEach(() => {
@@ -880,180 +1056,186 @@ describe('call(endpoint: string, input: Input | null, options: Partial {
- beforeEach(() => input = 'foo');
+ describe("when input: 'foo'", () => {
+ beforeEach(() => (input = 'foo'));
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
+ });
+ });
- afterEach(() => input = undefined);
+ afterEach(() => (input = undefined));
});
describe('when input: 1000', () => {
- beforeEach(() => input = 1000);
+ beforeEach(() => (input = 1000));
- it(
- 'should resolve: 1000',
- async () => { await expect(call(callEndpoint, input)).resolves.toEqual(input) }
- );
+ it('should resolve: 1000', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).resolves.toEqual(input);
+ });
- afterEach(() => input = undefined);
+ afterEach(() => (input = undefined));
});
describe('when input: undefined', () => {
- beforeEach(() => input = undefined);
-
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
- });
+ beforeEach(() => (input = undefined));
- describe('when ping: 100', () => {
- describe('when input: 0', () => {
- beforeEach(() => input = 0);
-
- it('should emit: data, with parameter: 0', async () => {
- let x: unknown = undefined;
- const data = jest.fn((data: unknown) => x = data);
- procedure.on('data', data);
- await call(callEndpoint, input, { ping: 100 });
- expect(data).toHaveBeenCalledTimes(1);
- expect(x).toEqual(0);
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
});
+ });
+ });
+ });
- it(
- 'should resolve: 0',
- async () => { await expect(call(callEndpoint, input, { ping: 100 })).resolves.toEqual(0) }
- );
+ afterEach(() => (callEndpoint = undefined));
+ });
- afterEach(() => input = undefined);
+ // TODO: when endpoint: incorrect
- describe('when verbose: true', () => {
- let log: jest.SpyInstance;
- beforeEach(() => {
- procedure.verbose = true;
- log = jest.spyOn(console, 'log').mockImplementation();
- });
+ afterEach(() => procedure.unbind());
+ });
- it('should call console.log', async () => {
- await call(callEndpoint, input, { ping: 100 });
- expect(log).toHaveBeenCalled();
- });
+ describe('when procedure callback: Callback (testing nullish returns)', () => {
+ beforeEach(() => {
+ fn = jest.fn(>((n: number) => {
+ if (typeof n !== 'number') {
+ throw new TypeError('Expected a number');
+ }
- afterEach(() => {
- procedure.verbose = false;
- log.mockReset();
- });
- });
- });
+ return null;
+ }));
+ procedureEndpoint = 'ipc://procedure/returnsnull';
+ procedure = new Procedure(fn, { workers: 3 });
+ procedure.bind(procedureEndpoint);
+ });
+
+ describe('when endpoint: correct', () => {
+ beforeEach(() => (callEndpoint = procedureEndpoint));
+
+ describe('when input: 0', () => {
+ beforeEach(() => (input = 0));
+
+ it('should emit: data, with parameter: 0', async () => {
+ let x: unknown = undefined;
+ const data = jest.fn((data: unknown) => (x = data));
+ procedure.on('data', data);
+ await call(callEndpoint, input);
+ expect(data).toHaveBeenCalledTimes(1);
+ expect(x).toEqual(0);
+ });
- describe('when input: \'foo\'', () => {
- beforeEach(() => input = 'foo');
+ it('should resolve: undefined', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).resolves.toBeUndefined();
+ });
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ afterEach(() => (input = undefined));
- afterEach(() => input = undefined);
+ describe('when verbose: true', () => {
+ let log: jest.SpyInstance;
+ beforeEach(() => {
+ procedure.verbose = true;
+ log = jest
+ .spyOn(console, 'log')
+ .mockImplementation();
});
- describe('when input: 1000', () => {
- beforeEach(() => input = 1000);
-
- it(
- 'should resolve: 1000',
- async () => { await expect(call(callEndpoint, input, { ping: 100 })).resolves.toEqual(input) }
- );
+ it('should call console.log', async () => {
+ await call(callEndpoint, input);
+ expect(log).toHaveBeenCalledTimes(3);
+ });
- afterEach(() => input = undefined);
+ afterEach(() => {
+ procedure.verbose = false;
+ log.mockReset();
});
+ });
+ });
- describe('when input: undefined', () => {
- beforeEach(() => input = undefined);
+ describe("when input: 'foo'", () => {
+ beforeEach(() => (input = 'foo'));
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
});
});
- afterEach(() => callEndpoint = undefined);
+ afterEach(() => (input = undefined));
});
- // TODO: when endpoint: incorrect
-
- afterEach(() => procedure.unbind());
- }
- );
+ describe('when input: 1000', () => {
+ beforeEach(() => (input = 1000));
- describe(
- 'when procedure callback: Callback (testing nullish returns)',
- () => {
- beforeEach(() => {
- fn = jest.fn(>((n: number) => {
- if (typeof n !== 'number') {
- throw new TypeError('Expected a number');
- }
+ it('should resolve: undefined', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).resolves.toBeUndefined();
+ });
- return null;
- }));
- procedureEndpoint = 'ipc://procedure/returnsnull';
- procedure = new Procedure(fn, { workers: 3 });
- procedure.bind(procedureEndpoint);
+ afterEach(() => (input = undefined));
});
- describe('when endpoint: correct', () => {
- beforeEach(() => callEndpoint = procedureEndpoint);
+ describe('when input: undefined', () => {
+ beforeEach(() => (input = undefined));
+
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
+ });
+ });
+ });
+ describe('when ping: 100', () => {
describe('when input: 0', () => {
- beforeEach(() => input = 0);
+ beforeEach(() => (input = 0));
it('should emit: data, with parameter: 0', async () => {
let x: unknown = undefined;
- const data = jest.fn((data: unknown) => x = data);
+ const data = jest.fn((data: unknown) => (x = data));
procedure.on('data', data);
- await call(callEndpoint, input);
+ await call(callEndpoint, input, {
+ ping: 100,
+ });
expect(data).toHaveBeenCalledTimes(1);
expect(x).toEqual(0);
});
- it(
- 'should resolve: undefined',
- async () => {
- await expect(call(callEndpoint, input))
- .resolves.toBeUndefined()
- }
- );
+ it('should resolve: undefined', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).resolves.toBeUndefined();
+ });
- afterEach(() => input = undefined);
+ afterEach(() => (input = undefined));
describe('when verbose: true', () => {
let log: jest.SpyInstance;
beforeEach(() => {
procedure.verbose = true;
- log = jest.spyOn(console, 'log').mockImplementation();
+ log = jest
+ .spyOn(console, 'log')
+ .mockImplementation();
});
it('should call console.log', async () => {
- await call(callEndpoint, input);
- expect(log).toHaveBeenCalledTimes(3);
+ await call(callEndpoint, input, {
+ ping: 100,
+ });
+ expect(log).toHaveBeenCalled();
});
afterEach(() => {
@@ -1063,189 +1245,186 @@ describe('call(endpoint: string, input: Input | null, options: Partial {
- beforeEach(() => input = 'foo');
+ describe("when input: 'foo'", () => {
+ beforeEach(() => (input = 'foo'));
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
+ });
+ });
- afterEach(() => input = undefined);
+ afterEach(() => (input = undefined));
});
describe('when input: 1000', () => {
- beforeEach(() => input = 1000);
-
- it(
- 'should resolve: undefined',
- async () => {
- await expect(call(callEndpoint, input))
- .resolves.toBeUndefined()
- }
- );
+ beforeEach(() => (input = 1000));
- afterEach(() => input = undefined);
- });
+ it('should resolve: undefined', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).resolves.toBeUndefined();
+ });
- describe('when input: undefined', () => {
- beforeEach(() => input = undefined);
-
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ afterEach(() => (input = undefined));
});
- describe('when ping: 100', () => {
- describe('when input: 0', () => {
- beforeEach(() => input = 0);
+ describe('when input: undefined', () => {
+ beforeEach(() => (input = undefined));
- it('should emit: data, with parameter: 0', async () => {
- let x: unknown = undefined;
- const data = jest.fn((data: unknown) => x = data);
- procedure.on('data', data);
- await call(callEndpoint, input, { ping: 100 });
- expect(data).toHaveBeenCalledTimes(1);
- expect(x).toEqual(0);
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
});
+ });
+ });
+ });
- it(
- 'should resolve: undefined',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .resolves.toBeUndefined()
- }
- );
+ afterEach(() => (callEndpoint = undefined));
+ });
- afterEach(() => input = undefined);
+ // TODO: when endpoint: incorrect
- describe('when verbose: true', () => {
- let log: jest.SpyInstance;
- beforeEach(() => {
- procedure.verbose = true;
- log = jest.spyOn(console, 'log').mockImplementation();
- });
+ afterEach(() => procedure.unbind());
+ });
- it('should call console.log', async () => {
- await call(callEndpoint, input, { ping: 100 });
- expect(log).toHaveBeenCalled();
- });
+ describe('when procedure callback: Callback (testing nullish returns)', () => {
+ beforeEach(() => {
+ fn = jest.fn(>((n: number) => {
+ if (typeof n !== 'number') {
+ throw new TypeError('Expected a number');
+ }
- afterEach(() => {
- procedure.verbose = false;
- log.mockReset();
- });
- });
- });
+ return;
+ }));
+ procedureEndpoint = 'ipc://procedure/returnsvoid';
+ procedure = new Procedure(fn, { workers: 3 });
+ procedure.bind(procedureEndpoint);
+ });
+
+ describe('when endpoint: correct', () => {
+ beforeEach(() => (callEndpoint = procedureEndpoint));
+
+ describe('when input: 0', () => {
+ beforeEach(() => (input = 0));
+
+ it('should emit: data, with parameter: 0', async () => {
+ let x: unknown = undefined;
+ const data = jest.fn((data: unknown) => (x = data));
+ procedure.on('data', data);
+ await call(callEndpoint, input);
+ expect(data).toHaveBeenCalledTimes(1);
+ expect(x).toEqual(0);
+ });
- describe('when input: \'foo\'', () => {
- beforeEach(() => input = 'foo');
+ it('should resolve: undefined', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).resolves.toBeUndefined();
+ });
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ afterEach(() => (input = undefined));
- afterEach(() => input = undefined);
+ describe('when verbose: true', () => {
+ let log: jest.SpyInstance;
+ beforeEach(() => {
+ procedure.verbose = true;
+ log = jest
+ .spyOn(console, 'log')
+ .mockImplementation();
});
- describe('when input: 1000', () => {
- beforeEach(() => input = 1000);
-
- it(
- 'should resolve: undefined',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .resolves.toBeUndefined()
- }
- );
+ it('should call console.log', async () => {
+ await call(callEndpoint, input);
+ expect(log).toHaveBeenCalledTimes(3);
+ });
- afterEach(() => input = undefined);
+ afterEach(() => {
+ procedure.verbose = false;
+ log.mockReset();
});
+ });
+ });
- describe('when input: undefined', () => {
- beforeEach(() => input = undefined);
+ describe("when input: 'foo'", () => {
+ beforeEach(() => (input = 'foo'));
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
});
});
- afterEach(() => callEndpoint = undefined);
+ afterEach(() => (input = undefined));
});
- // TODO: when endpoint: incorrect
-
- afterEach(() => procedure.unbind());
- }
- );
+ describe('when input: 1000', () => {
+ beforeEach(() => (input = 1000));
- describe(
- 'when procedure callback: Callback (testing nullish returns)',
- () => {
- beforeEach(() => {
- fn = jest.fn(>((n: number) => {
- if (typeof n !== 'number') {
- throw new TypeError('Expected a number');
- }
+ it('should resolve: undefined', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).resolves.toBeUndefined();
+ });
- return;
- }));
- procedureEndpoint = 'ipc://procedure/returnsvoid';
- procedure = new Procedure(fn, { workers: 3 });
- procedure.bind(procedureEndpoint);
+ afterEach(() => (input = undefined));
});
- describe('when endpoint: correct', () => {
- beforeEach(() => callEndpoint = procedureEndpoint);
+ describe('when input: undefined', () => {
+ beforeEach(() => (input = undefined));
+
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
+ });
+ });
+ });
+ describe('when ping: 100', () => {
describe('when input: 0', () => {
- beforeEach(() => input = 0);
+ beforeEach(() => (input = 0));
it('should emit: data, with parameter: 0', async () => {
let x: unknown = undefined;
- const data = jest.fn((data: unknown) => x = data);
+ const data = jest.fn((data: unknown) => (x = data));
procedure.on('data', data);
- await call(callEndpoint, input);
+ await call(callEndpoint, input, {
+ ping: 100,
+ });
expect(data).toHaveBeenCalledTimes(1);
expect(x).toEqual(0);
});
- it(
- 'should resolve: undefined',
- async () => {
- await expect(call(callEndpoint, input))
- .resolves.toBeUndefined()
- }
- );
+ it('should resolve: undefined', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).resolves.toBeUndefined();
+ });
- afterEach(() => input = undefined);
+ afterEach(() => (input = undefined));
describe('when verbose: true', () => {
let log: jest.SpyInstance;
beforeEach(() => {
procedure.verbose = true;
- log = jest.spyOn(console, 'log').mockImplementation();
+ log = jest
+ .spyOn(console, 'log')
+ .mockImplementation();
});
it('should call console.log', async () => {
- await call(callEndpoint, input);
- expect(log).toHaveBeenCalledTimes(3);
+ await call(callEndpoint, input, {
+ ping: 100,
+ });
+ expect(log).toHaveBeenCalled();
});
afterEach(() => {
@@ -1255,189 +1434,189 @@ describe('call(endpoint: string, input: Input | null, options: Partial {
- beforeEach(() => input = 'foo');
+ describe("when input: 'foo'", () => {
+ beforeEach(() => (input = 'foo'));
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
+ });
+ });
- afterEach(() => input = undefined);
+ afterEach(() => (input = undefined));
});
describe('when input: 1000', () => {
- beforeEach(() => input = 1000);
-
- it(
- 'should resolve: undefined',
- async () => {
- await expect(call(callEndpoint, input))
- .resolves.toBeUndefined()
- }
- );
+ beforeEach(() => (input = 1000));
- afterEach(() => input = undefined);
- });
+ it('should resolve: undefined', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).resolves.toBeUndefined();
+ });
- describe('when input: undefined', () => {
- beforeEach(() => input = undefined);
-
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ afterEach(() => (input = undefined));
});
- describe('when ping: 100', () => {
- describe('when input: 0', () => {
- beforeEach(() => input = 0);
+ describe('when input: undefined', () => {
+ beforeEach(() => (input = undefined));
- it('should emit: data, with parameter: 0', async () => {
- let x: unknown = undefined;
- const data = jest.fn((data: unknown) => x = data);
- procedure.on('data', data);
- await call(callEndpoint, input, { ping: 100 });
- expect(data).toHaveBeenCalledTimes(1);
- expect(x).toEqual(0);
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input, { ping: 100 })
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
});
+ });
+ });
+ });
- it(
- 'should resolve: undefined',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .resolves.toBeUndefined()
- }
- );
+ afterEach(() => (callEndpoint = undefined));
+ });
- afterEach(() => input = undefined);
+ // TODO: when endpoint: incorrect
- describe('when verbose: true', () => {
- let log: jest.SpyInstance;
- beforeEach(() => {
- procedure.verbose = true;
- log = jest.spyOn(console, 'log').mockImplementation();
- });
+ afterEach(() => procedure.unbind());
+ });
+ });
- it('should call console.log', async () => {
- await call(callEndpoint, input, { ping: 100 });
- expect(log).toHaveBeenCalled();
- });
+ describe('TCP tests', () => {
+ describe('when procedure callback: Callback (simple accumulator function)', () => {
+ beforeEach(() => {
+ let i = 0;
+ fn = jest.fn(>((n: number) => {
+ if (typeof n !== 'number') {
+ throw new TypeError('Expected a number');
+ }
- afterEach(() => {
- procedure.verbose = false;
- log.mockReset();
- });
- });
- });
+ return (i += n);
+ }));
+ procedureEndpoint = 'tcp://127.0.0.1:33333';
+ procedure = new Procedure(fn, { workers: 3 });
+ procedure.bind(procedureEndpoint);
+ });
+
+ describe('when endpoint: correct', () => {
+ beforeEach(() => (callEndpoint = procedureEndpoint));
+
+ describe('when input: 0', () => {
+ beforeEach(() => (input = 0));
+
+ it('should emit: data, with parameter: 0', async () => {
+ let x: unknown = undefined;
+ const data = jest.fn((data: unknown) => (x = data));
+ procedure.on('data', data);
+ await call(callEndpoint, input);
+ expect(data).toHaveBeenCalledTimes(1);
+ expect(x).toEqual(0);
+ });
- describe('when input: \'foo\'', () => {
- beforeEach(() => input = 'foo');
+ it('should resolve: 0', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).resolves.toEqual(0);
+ });
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ afterEach(() => (input = undefined));
- afterEach(() => input = undefined);
+ describe('when verbose: true', () => {
+ let log: jest.SpyInstance;
+ beforeEach(() => {
+ procedure.verbose = true;
+ log = jest
+ .spyOn(console, 'log')
+ .mockImplementation();
});
- describe('when input: 1000', () => {
- beforeEach(() => input = 1000);
-
- it(
- 'should resolve: undefined',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .resolves.toBeUndefined()
- }
- );
+ it('should call console.log', async () => {
+ await call(callEndpoint, input);
+ expect(log).toHaveBeenCalledTimes(3);
+ });
- afterEach(() => input = undefined);
+ afterEach(() => {
+ procedure.verbose = false;
+ log.mockReset();
});
+ });
+ });
- describe('when input: undefined', () => {
- beforeEach(() => input = undefined);
+ describe("when input: 'foo'", () => {
+ beforeEach(() => (input = 'foo'));
- it(
- 'should throw: ProcedureExecutionError',
- async () => {
- await expect(call(callEndpoint, input, { ping: 100 }))
- .rejects.toMatchObject({ code: ProcedureErrorCodes.EXECUTION_ERROR })
- }
- );
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
});
});
- afterEach(() => callEndpoint = undefined);
+ afterEach(() => (input = undefined));
});
- // TODO: when endpoint: incorrect
-
- afterEach(() => procedure.unbind());
- }
- );
- });
+ describe('when input: 1000', () => {
+ beforeEach(() => (input = 1000));
- describe('TCP tests', () => {
- describe(
- 'when procedure callback: Callback (simple accumulator function)',
- () => {
- beforeEach(() => {
- let i = 0;
- fn = jest.fn(>((n: number) => {
- if (typeof n !== 'number') {
- throw new TypeError('Expected a number');
- }
+ it('should resolve: 1000', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).resolves.toEqual(input);
+ });
- return i += n;
- }));
- procedureEndpoint = 'tcp://127.0.0.1:33333';
- procedure = new Procedure(fn, { workers: 3 });
- procedure.bind(procedureEndpoint);
+ afterEach(() => (input = undefined));
});
- describe('when endpoint: correct', () => {
- beforeEach(() => callEndpoint = procedureEndpoint);
+ describe('when input: undefined', () => {
+ beforeEach(() => (input = undefined));
+ it('should throw: ProcedureExecutionError', async () => {
+ await expect(
+ call(callEndpoint, input)
+ ).rejects.toMatchObject({
+ code: ProcedureErrorCodes.EXECUTION_ERROR,
+ });
+ });
+ });
+
+ describe('when ping: 100', () => {
describe('when input: 0', () => {
- beforeEach(() => input = 0);
+ beforeEach(() => (input = 0));
it('should emit: data, with parameter: 0', async () => {
let x: unknown = undefined;
- const data = jest.fn((data: unknown) => x = data);
+ const data = jest.fn((data: unknown) => (x = data));
procedure.on('data', data);
- await call(callEndpoint, input);
+ await call(callEndpoint, input, {
+ ping: 100,
+ });
expect(data).toHaveBeenCalledTimes(1);
expect(x).toEqual(0);
});
- it(
- 'should resolve: 0',
- async () => { await expect(call(