From ee6d31ab65cc7e425cc2b960f5938668d7abb24a Mon Sep 17 00:00:00 2001 From: Florian Hotze Date: Sun, 4 Dec 2022 13:56:25 +0100 Subject: [PATCH] [actions] Add Transformation Actions as a class & Add arg type checking lib (#180) * README: Add Transformation Actions * [actions] Explicitely add Transformation This adds a Transformation class to explicitely allow access to the Transformation Actions, which were dynamically exported before. * Add `typeof-arguments` to dependencies * Update type defs * Update CHANGELOG Signed-off-by: Florian Hotze --- CHANGELOG.md | 1 + README.md | 12 +++++++++++ actions.js | 49 ++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 29 ++++++++++++++++++++++++- package.json | 3 ++- types/actions.d.ts | 32 +++++++++++++++++++++++++++ types/actions.d.ts.map | 2 +- 7 files changed, 125 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5a2c30c2..dfdc35fda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ |-------------|-----------|---------------------------------------------------------------------|--------------------------------------------------------|----------| | Enhancement | `items` | ItemHistory: Change return types of min/max between/since to number | [#175](https://github.com/openhab/openhab-js/pull/175) | Yes | | Cleanup | `rules` | Remove unused rule providers | [#183](https://github.com/openhab/openhab-js/pull/183) | Yes | +| Enhancement | `actions` | Add Transformation actions as a class with arg type checking | [#180](https://github.com/openhab/openhab-js/pull/180) | No | Also see the [Release Milestone](https://github.com/openhab/openhab-js/milestone/8). diff --git a/README.md b/README.md index 37b4cb2ca..2c114af2e 100644 --- a/README.md +++ b/README.md @@ -627,6 +627,18 @@ It is possible to get the actions for a Thing using `actions.Things.getActions(b See [openhab-js : actions.Things](https://openhab.github.io/openhab-js/actions.html#.Things) for complete documentation. +#### Transformation Actions + +openHAB provides various [data transformation services](https://www.openhab.org/addons/#transform) which can translate between technical and human-readable values. +Usually, they are used directly on Items, but it is also possible to access them from scripts. + +```javascript +console.log(actions.Transformation.transform('MAP', 'en.map', 'OPEN')); // open +console.log(actions.Transformation.transform('MAP', 'de.map', 'OPEN')); // offen +``` + +See [openhab-js : actions.Transformation](https://openhab.github.io/openhab-js/actions.Transformation.html) for complete documentation. + #### Voice Actions See [openhab-js : actions.Voice](https://openhab.github.io/openhab-js/actions.html#.Voice) for complete documentation. diff --git a/actions.js b/actions.js index 363839bb6..129e5b0cf 100644 --- a/actions.js +++ b/actions.js @@ -14,6 +14,7 @@ * actions.NotificationAction.sendBroadcastNotification("Hello World!") */ +const typeOfArguments = require('typeof-arguments'); const osgi = require('./osgi'); // See https://github.com/openhab/openhab-core/blob/main/bundles/org.openhab.core.automation.module.script/src/main/java/org/openhab/core/automation/module/script/internal/defaultscope/ScriptThingActionsImpl.java const { actions } = require('@runtime/Defaults'); @@ -21,7 +22,9 @@ const log = require('./log')('actions'); const Things = Java.type('org.openhab.core.model.script.actions.Things'); const actionServices = osgi.findServices('org.openhab.core.model.script.engine.action.ActionService', null) || []; + const JavaScriptExecution = Java.type('org.openhab.core.model.script.actions.ScriptExecution'); +const JavaTransformation = Java.type('org.openhab.core.transform.actions.Transformation'); // Dynamically export all found actions const dynamicExports = {}; @@ -299,6 +302,51 @@ const Semantics = Java.type('org.openhab.core.model.script.actions.Semantics'); */ const ThingsAction = Java.type('org.openhab.core.model.script.actions.Things'); +/** + * {@link https://www.openhab.org/javadoc/latest/org/openhab/core/transform/actions/transformation Transformation} Actions + * + * The static methods of this class allow rules to execute transformations using one of the various {@link https://www.openhab.org/addons/#transform data transformation services}. + * + * @example + * actions.Transformation.transform('MAP', 'en.map', 'OPEN'); // returns "open" + * actions.Transformation.transform('MAP', 'de.map', 'OPEN'); // returns "offen" + * @memberof actions + * @hideconstructor + */ +class Transformation { + /** + * Applies a transformation of a given type with some function to a value. + * + * @param {string} type the transformation type, e.g. REGEX or MAP + * @param {string} fn the function to call, this value depends on the transformation type + * @param {string} value the value to apply the transformation to + * @returns {string} the transformed value or the original one, if there was no service registered for the given type or a transformation exception occurred + */ + static transform (type, fn, value) { + typeOfArguments(arguments, ['string', 'string', 'string']); + return JavaTransformation.transform(type, fn, value).toString(); + } + + /** + * Applies a transformation of a given type with some function to a value. + * + * @param {string} type the transformation type, e.g. REGEX or MAP + * @param {string} fn the function to call, this value depends on the transformation type + * @param {string} value the value to apply the transformation to + * @returns {string} the transformed value + * @throws Java {@link https://www.openhab.org/javadoc/latest/org/openhab/core/transform/TransformationException.html TransformationException} + */ + static transformRaw (type, fn, value) { + typeOfArguments(arguments, ['string', 'string', 'string']); + // Wrap exception to enable JS stack traces + try { + return JavaTransformation.transformRaw(type, fn, value).toString(); + } catch (error) { + throw new Error(error); + } + } +} + /** * {@link https://www.openhab.org/javadoc/latest/org/openhab/core/model/script/actions/Voice.html Voice} Actions * @@ -354,6 +402,7 @@ module.exports = Object.assign(dynamicExports, { ScriptExecution, Semantics, Things: ThingsAction, + Transformation, Voice, NotificationAction, /** diff --git a/package-lock.json b/package-lock.json index fb61717f9..bbdc6682b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,8 @@ "dependencies": { "@js-joda/core": "^4.3.1", "@js-joda/timezone": "^2.11.1", - "parse-duration": "^0.1.1" + "parse-duration": "^0.1.1", + "typeof-arguments": "^5.1.3" }, "devDependencies": { "@types/jest": "^28.1.8", @@ -7241,6 +7242,11 @@ "node": ">= 0.4" } }, + "node_modules/of-type": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/of-type/-/of-type-3.0.4.tgz", + "integrity": "sha512-xPRrHy1QYTHnGaNDYIHvaVS2J5pimc3OAcjYamYJ6YbE4dirt2elfI+r5888AQj+M+gqmBIH3+x6tlnYeJMvHw==" + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -9055,6 +9061,14 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "node_modules/typeof-arguments": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/typeof-arguments/-/typeof-arguments-5.1.3.tgz", + "integrity": "sha512-7whUbYkiTfdYYtx8v4e/9MhTTynsIkF3ICIG0rZlNrnt3Y8/716zABl3k/HifNjwUq8WljuDCWqGkrAwocNIKQ==", + "dependencies": { + "of-type": "^3.0.3" + } + }, "node_modules/typescript": { "version": "4.7.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz", @@ -15700,6 +15714,11 @@ "es-abstract": "^1.19.1" } }, + "of-type": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/of-type/-/of-type-3.0.4.tgz", + "integrity": "sha512-xPRrHy1QYTHnGaNDYIHvaVS2J5pimc3OAcjYamYJ6YbE4dirt2elfI+r5888AQj+M+gqmBIH3+x6tlnYeJMvHw==" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -17200,6 +17219,14 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "typeof-arguments": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/typeof-arguments/-/typeof-arguments-5.1.3.tgz", + "integrity": "sha512-7whUbYkiTfdYYtx8v4e/9MhTTynsIkF3ICIG0rZlNrnt3Y8/716zABl3k/HifNjwUq8WljuDCWqGkrAwocNIKQ==", + "requires": { + "of-type": "^3.0.3" + } + }, "typescript": { "version": "4.7.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz", diff --git a/package.json b/package.json index 5b9bf5ef8..cc71e57b8 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "dependencies": { "@js-joda/core": "^4.3.1", "@js-joda/timezone": "^2.11.1", - "parse-duration": "^0.1.1" + "parse-duration": "^0.1.1", + "typeof-arguments": "^5.1.3" }, "scripts": { "test:mocha": "mocha test/**/*.test.js", diff --git a/types/actions.d.ts b/types/actions.d.ts index 183ea2e05..5a8cb7196 100644 --- a/types/actions.d.ts +++ b/types/actions.d.ts @@ -223,6 +223,38 @@ export const Semantics: any; * @memberof actions */ declare const ThingsAction: any; +/** + * {@link https://www.openhab.org/javadoc/latest/org/openhab/core/transform/actions/transformation Transformation} Actions + * + * The static methods of this class allow rules to execute transformations using one of the various {@link https://www.openhab.org/addons/#transform data transformation services}. + * + * @example + * actions.Transformation.transform('MAP', 'en.map', 'OPEN'); // returns "open" + * actions.Transformation.transform('MAP', 'de.map', 'OPEN'); // returns "offen" + * @memberof actions + * @hideconstructor + */ +export class Transformation { + /** + * Applies a transformation of a given type with some function to a value. + * + * @param {string} type the transformation type, e.g. REGEX or MAP + * @param {string} fn the function to call, this value depends on the transformation type + * @param {string} value the value to apply the transformation to + * @returns {string} the transformed value or the original one, if there was no service registered for the given type or a transformation exception occurred + */ + static transform(type: string, fn: string, value: string, ...args: any[]): string; + /** + * Applies a transformation of a given type with some function to a value. + * + * @param {string} type the transformation type, e.g. REGEX or MAP + * @param {string} fn the function to call, this value depends on the transformation type + * @param {string} value the value to apply the transformation to + * @returns {string} the transformed value + * @throws Java {@link https://www.openhab.org/javadoc/latest/org/openhab/core/transform/TransformationException.html TransformationException} + */ + static transformRaw(type: string, fn: string, value: string, ...args: any[]): string; +} /** * {@link https://www.openhab.org/javadoc/latest/org/openhab/core/model/script/actions/Voice.html Voice} Actions * diff --git a/types/actions.d.ts.map b/types/actions.d.ts.map index 2168b5516..bee9e0c00 100644 --- a/types/actions.d.ts.map +++ b/types/actions.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../actions.js"],"names":[],"mappings":"AAqCA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAuE;AAEvE;;;;;;;;;;;;;;;;;;GAkBG;AACH,2BAA6E;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,4BAA+E;AAE/E;;;;;;;;;;;GAWG;AACH,uBAAqE;AAErE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,uBAAqE;AAErE;;;;;;;;;;;;;GAaG;AACH,6BAAyE;AAEzE;;;;;;;;;;GAUG;AACH,uBAAqE;AAErE;;;;;;;;;;;;GAYG;AACH;IACE;;;;OAIG;IACH,8BAFW,MAAM,QAIhB;IAED;;;;;;;OAOG;IACH,gCALW,MAAM,kDAsBhB;IAED;;;;;;;;;OASG;IACH,2GAQC;CACF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,4BAA+E;AAE/E;;;;;;;;;;;GAWG;AACH,gCAA+E;AAE/E;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAuE;AAEvE;;;;;;;;;;;;;;;GAeG;AACH,mCAAuB;AA6BhB,sEAAyD;AAUhD,+EAA+D"} \ No newline at end of file +{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../actions.js"],"names":[],"mappings":"AAwCA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAuE;AAEvE;;;;;;;;;;;;;;;;;;GAkBG;AACH,2BAA6E;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,4BAA+E;AAE/E;;;;;;;;;;;GAWG;AACH,uBAAqE;AAErE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,uBAAqE;AAErE;;;;;;;;;;;;;GAaG;AACH,6BAAyE;AAEzE;;;;;;;;;;GAUG;AACH,uBAAqE;AAErE;;;;;;;;;;;;GAYG;AACH;IACE;;;;OAIG;IACH,8BAFW,MAAM,QAIhB;IAED;;;;;;;OAOG;IACH,gCALW,MAAM,kDAsBhB;IAED;;;;;;;;;OASG;IACH,2GAQC;CACF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,4BAA+E;AAE/E;;;;;;;;;;;GAWG;AACH,gCAA+E;AAE/E;;;;;;;;;;GAUG;AACH;IACE;;;;;;;OAOG;IACH,uBALW,MAAM,MACN,MAAM,SACN,MAAM,mBACJ,MAAM,CAKlB;IAED;;;;;;;;OAQG;IACH,0BANW,MAAM,MACN,MAAM,SACN,MAAM,mBACJ,MAAM,CAWlB;CACF;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAuE;AAEvE;;;;;;;;;;;;;;;GAeG;AACH,mCAAuB;AA8BhB,sEAAyD;AAUhD,+EAA+D"} \ No newline at end of file