diff --git a/src/property.ts b/src/property.ts index af448bf..89b75d0 100644 --- a/src/property.ts +++ b/src/property.ts @@ -118,7 +118,7 @@ class Property { * * @returns {*} The current value */ - getValue(): ValueType { + getValue(): Promise { return this.value.get(); } @@ -127,9 +127,9 @@ class Property { * * @param {*} value The value to set */ - setValue(value: ValueType): void { + setValue(value: ValueType): Promise { this.validateValue(value); - this.value.set(value); + return this.value.set(value); } /** diff --git a/src/server.ts b/src/server.ts index 7de2139..d2ddbd4 100644 --- a/src/server.ts +++ b/src/server.ts @@ -225,7 +225,7 @@ class ThingHandler extends BaseHandler { data: Record; }; try { - message = JSON.parse(msg as string); + message = JSON.parse((msg as unknown) as string); } catch (e1) { try { ws.send( @@ -274,7 +274,7 @@ class ThingHandler extends BaseHandler { messageType: 'error', data: { status: '400 Bad Request', - message: e.message, + message: e instanceof Error ? e.message : 'unknown reason', }, }) ); @@ -378,7 +378,14 @@ class PropertyHandler extends BaseHandler { const propertyName = req.params.propertyName; if (thing.hasProperty(propertyName)) { - res.json({ [propertyName]: thing.getProperty(propertyName) }); + thing + .getProperty(propertyName) + .then((value) => { + res.json({ [propertyName]: value }); + }) + .catch((e) => { + res.status(500).end(e.toString()); + }); } else { res.status(404).end(); } @@ -399,19 +406,18 @@ class PropertyHandler extends BaseHandler { const propertyName = req.params.propertyName; if (!req.body.hasOwnProperty(propertyName)) { - res.status(400).end(); + res.status(404).end(); return; } if (thing.hasProperty(propertyName)) { - try { - thing.setProperty(propertyName, req.body[propertyName]); - } catch (e) { - res.status(400).end(); - return; - } - - res.json({ [propertyName]: thing.getProperty(propertyName) }); + thing + .setProperty(propertyName, req.body[propertyName]) + .then(() => thing.getProperty(propertyName)) + .then((value) => res.json({ [propertyName]: value })) + .catch((e) => { + res.status(500).end(e.toString()); + }); } else { res.status(404).end(); } diff --git a/src/thing.ts b/src/thing.ts index 34dad27..831a5a1 100644 --- a/src/thing.ts +++ b/src/thing.ts @@ -337,13 +337,13 @@ class Thing { * * @returns {*} Current property value if found, else null */ - getProperty(propertyName: string): unknown | null { + getProperty(propertyName: string): Promise { const prop = this.findProperty(propertyName); if (prop) { return prop.getValue(); } - return null; + return Promise.reject(); } /** @@ -351,13 +351,18 @@ class Thing { * * Returns an object of propertyName -> value. */ - getProperties(): Record { + getProperties(): Promise> { const props: Record = {}; + const promises: Promise[] = []; for (const name in this.properties) { - props[name] = this.properties[name].getValue(); + promises.push( + this.properties[name].getValue().then((value) => { + props[name] = value; + }) + ); } - return props; + return Promise.all(promises).then(() => props); } /** @@ -377,13 +382,13 @@ class Thing { * @param {String} propertyName Name of the property to set * @param {*} value Value to set */ - setProperty(propertyName: string, value: AnyType): void { + setProperty(propertyName: string, value: AnyType): Promise { const prop = this.findProperty(propertyName); if (!prop) { - return; + return Promise.reject(); } - prop.setValue(value); + return prop.setValue(value); } /** @@ -586,20 +591,22 @@ class Thing { * @param {Object} property The property that changed */ propertyNotify(property: Property): void { - const message = JSON.stringify({ - messageType: 'propertyStatus', - data: { - [property.getName()]: property.getValue(), - }, - }); + property.getValue().then((value) => { + const message = JSON.stringify({ + messageType: 'propertyStatus', + data: { + [property.getName()]: value, + }, + }); - for (const subscriber of this.subscribers) { - try { - subscriber.send(message); - } catch (e) { - // do nothing + for (const subscriber of this.subscribers) { + try { + subscriber.send(message); + } catch (e) { + // do nothing + } } - } + }); } /** diff --git a/src/value.ts b/src/value.ts index a0ba095..70c7b8b 100644 --- a/src/value.ts +++ b/src/value.ts @@ -20,6 +20,8 @@ class Value extends EventEmitter { private valueForwarder: Value.Forwarder | null; + private valueRequestor: Value.Requestor | null; + /** * Initialize the object. * @@ -27,10 +29,15 @@ class Value extends EventEmitter { * @param {function?} valueForwarder The method that updates the actual value * on the thing */ - constructor(initialValue: ValueType, valueForwarder: Value.Forwarder | null = null) { + constructor( + initialValue: ValueType, + valueForwarder: Value.Forwarder | null = null, + valueRequestor: Value.Requestor | null = null + ) { super(); this.lastValue = initialValue; this.valueForwarder = valueForwarder; + this.valueRequestor = valueRequestor; } /** @@ -38,12 +45,10 @@ class Value extends EventEmitter { * * @param {*} value Value to set */ - set(value: ValueType): void { - if (this.valueForwarder) { - this.valueForwarder(value); - } - - this.notifyOfExternalUpdate(value); + set(value: ValueType): Promise { + return Promise.resolve(this.valueForwarder ? this.valueForwarder(value) : undefined).then(() => + this.notifyOfExternalUpdate(value) + ); } /** @@ -51,8 +56,14 @@ class Value extends EventEmitter { * * @returns the value. */ - get(): ValueType { - return this.lastValue; + get(): Promise { + if (this.valueRequestor) { + return Promise.resolve(this.valueRequestor()).then((newValue) => { + this.notifyOfExternalUpdate(newValue); + return newValue; + }); + } + return Promise.resolve(this.lastValue); } /** @@ -69,7 +80,8 @@ class Value extends EventEmitter { } declare namespace Value { - export type Forwarder = (value: T) => void; + export type Forwarder = (value: T) => void | Promise; + export type Requestor = () => T | Promise; } export = Value;