diff --git a/README.md b/README.md index b53620b6956fcda4fdb6e960c4311be0d87b68fe..71dcaddd9e5e441a383fff6897fd84c004f3ec4d 100644 --- a/README.md +++ b/README.md @@ -227,6 +227,17 @@ const clear = usp.on(/NOTIFY.*/, (data, msg) => console.log({ data, msg })); Options allows extending commands with additional functionality. + Props: + timeout -> timeout after given ms (throws error) + preCall -> called before each command, provides command name and arguments + postCall -> called after each command, provides command name, arguments and result/error + ```javascript -await usp.options({ timeout: 1000 }).get("Device.DeviceInfo.SerialNumber"); +await usp + .options({ + timeout: 1000, + preCall: (name, args) => console.log(name, args), + postCall: (name, args, result) => console.log(name, args, result), + }) + .get("Device.DeviceInfo.SerialNumber"); ``` diff --git a/src/index.ts b/src/index.ts index 61216465f43b20a07f70cc5b11f3cb34a2e51fe2..952ad6e6f23bb1816406e888c2e482f3d4e2dc4f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,7 @@ import { Options, USP, Command, + PostCallCallback, } from "./types"; import { makeCallbackRouter, makeRouter } from "./util"; @@ -41,8 +42,8 @@ const wait = (ms: number) => }, ms); }); -const timeoutWrapper = (promise: Promise<any>, ms: number) => - Promise.race([promise, wait(ms)]); +const timeoutWrapper = (promise: () => Promise<any>, ms?: number) => + ms && ms > 0 ? Promise.race([promise(), wait(ms)]) : promise(); const wrap = <T extends (...args: any[]) => any>( opts: Options, @@ -50,12 +51,20 @@ const wrap = <T extends (...args: any[]) => any>( cmd: T ): T => { return <T>((...args: any[]) => { - if (opts.logMessage) opts.logMessage(cmdName, args); - if (opts.timeout && opts.timeout > 0) { - return timeoutWrapper(cmd(...args), opts.timeout); - } - - return cmd(...args); + // Promise.resolve added to handle non-promise commands + const cmdCall = () => Promise.resolve(cmd(...args)); + const finalCall = () => + timeoutWrapper(cmdCall, opts.timeout) + .then((res) => { + opts.postCall && opts.postCall(cmdName, args, res); + return res; + }) + .catch((err) => { + opts.postCall && opts.postCall(cmdName, args, err); + throw err; + }); + if (opts.preCall) opts.preCall(cmdName, args); + return finalCall(); }); }; @@ -67,7 +76,7 @@ const addOptions = (usp: Partial<USP>, opts: Options): USP => { }), {} as any ) as USP; - mainUSP.options = wrap(opts, "options", (opts) => addOptions(mainUSP, opts)); + mainUSP.options = (opts) => addOptions(mainUSP, opts); return mainUSP; }; diff --git a/src/types.ts b/src/types.ts index e73e478bad25b1a23349457e7cc370c427cdd2d4..0ab49c9a52fc42ea628bf01207ce94aa6ba251c4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -174,14 +174,17 @@ export type ResolveRecipe = ( level?: number ) => Promise<GetReturn>; -export type LogMessageCallback = (name: string, args: any[]) => void; +export type PreCallCallback = (name: string, args: any[]) => void; +export type PostCallCallback = (name: string, args: any[], result: any) => void; /** Options that allow extending command funcitonality */ export type Options = { /** Timeout command after given number of milliseconds (throws an error for handling with catch) */ timeout?: number; - /** Log outgoing calls to the console */ - logMessage?: LogMessageCallback; + /** Call function before command */ + preCall?: PreCallCallback; + /** Call after before command */ + postCall?: PostCallCallback; }; /** Device API */ diff --git a/tests/integration/config.json b/tests/integration/config.json index 8f98c81a8b7c0536e0dc7517e38ad7960d11b11f..8926a5dcf23263efde87e75c1d939451b8987d94 100644 --- a/tests/integration/config.json +++ b/tests/integration/config.json @@ -10,12 +10,5 @@ "url": "ws://192.168.1.1:9001", "username": "admin", "password": "admin" - }, - "bulut": { - "url": "wss://bulut.iopsys.eu:443", - "fromId": "proto::usp-cloud-controller", - "toId": "os::002207-+105318+2031000004", - "username": "admin", - "password": "admin" } } diff --git a/tests/integration/index.test.ts b/tests/integration/index.test.ts index 07f111c0f5b1cd346d927a825e0bf6e41872521c..f5fa962fff57d023ff7de96ab8cf05ce948aeddd 100644 --- a/tests/integration/index.test.ts +++ b/tests/integration/index.test.ts @@ -7,7 +7,7 @@ describe("Test general API", () => { let device: any = null; before(async () => { - device = await connect(config.bulut as ConnectionOptions); + device = await connect(config.ws as ConnectionOptions); }); // GET @@ -189,7 +189,7 @@ describe("Test general API", () => { it("get with double options setup returns without error", async () => { await device .options({ timeout: -1 }) - .options({ logMessage: () => null }) + .options({ preCall: () => null }) .get("Device.DeviceInfo.SerialNumber") .then((msg) => assert.strictEqual(typeof msg, "string")) .catch((err) => { @@ -197,6 +197,15 @@ describe("Test general API", () => { }); }); + it("get with pre and post call executes without error", async () => { + await device + .options({ + preCall: (name) => assert.strictEqual(name, "get"), + postCall: (name) => assert.strictEqual(name, "get"), + }) + .get("Device.DeviceInfo.SerialNumber"); + }); + after(async () => { await device.disconnect(); });