diff --git a/msa/js-executor/api/httpServer.js b/msa/js-executor/api/httpServer.js deleted file mode 100644 index 62bf5807b1..0000000000 --- a/msa/js-executor/api/httpServer.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright © 2016-2022 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -const config = require('config'), - logger = require('../config/logger')._logger('httpServer'), - express = require('express'); - -const httpPort = Number(config.get('http_port')); - -const app = express(); - -app.get('/livenessProbe', async (req, res) => { - const date = new Date(); - const message = { now: date.toISOString() }; - res.send(message); -}) - -app.listen(httpPort, () => logger.info(`Started http endpoint on port ${httpPort}. Please, use /livenessProbe !`)) \ No newline at end of file diff --git a/msa/js-executor/api/httpServer.ts b/msa/js-executor/api/httpServer.ts new file mode 100644 index 0000000000..f3671a1b89 --- /dev/null +++ b/msa/js-executor/api/httpServer.ts @@ -0,0 +1,46 @@ +/// +/// Copyright © 2016-2022 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import express from 'express'; +import { _logger} from '../config/logger'; + +export class HttpServer { + + private logger = _logger('httpServer'); + private app = express(); + private server; + + constructor(httpPort: number) { + this.app.get('/livenessProbe', async (req, res) => { + const message = { + now: new Date().toISOString() + }; + res.send(message); + }) + + this.server = this.app.listen(httpPort, () => { + this.logger.info('Started http endpoint on port %s. Please, use /livenessProbe !', httpPort); + }).on('error', (error) => { + this.logger.error(error); + }); + } + + stop() { + this.server.close(() => { + this.logger.info('Http server stop'); + }); + } +} diff --git a/msa/js-executor/api/jsExecutor.js b/msa/js-executor/api/jsExecutor.js deleted file mode 100644 index 02190406d2..0000000000 --- a/msa/js-executor/api/jsExecutor.js +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright © 2016-2022 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -'use strict'; - -const vm = require('vm'); - -function JsExecutor(useSandbox) { - this.useSandbox = useSandbox; -} - -JsExecutor.prototype.compileScript = function(code) { - if (this.useSandbox) { - return createScript(code); - } else { - return createFunction(code); - } -} - -JsExecutor.prototype.executeScript = function(script, args, timeout) { - if (this.useSandbox) { - return invokeScript(script, args, timeout); - } else { - return invokeFunction(script, args); - } -} - -function createScript(code) { - return new Promise((resolve, reject) => { - try { - code = "("+code+")(...args)"; - var script = new vm.Script(code); - resolve(script); - } catch (err) { - reject(err); - } - }); -} - -function invokeScript(script, args, timeout) { - return new Promise((resolve, reject) => { - try { - var sandbox = Object.create(null); - sandbox.args = args; - var result = script.runInNewContext(sandbox, {timeout: timeout}); - resolve(result); - } catch (err) { - reject(err); - } - }); -} - - -function createFunction(code) { - return new Promise((resolve, reject) => { - try { - code = "return ("+code+")(...args)"; - const parsingContext = vm.createContext({}); - const func = vm.compileFunction(code, ['args'], {parsingContext: parsingContext}); - resolve(func); - } catch (err) { - reject(err); - } - }); -} - -function invokeFunction(func, args) { - return new Promise((resolve, reject) => { - try { - var result = func(args); - resolve(result); - } catch (err) { - reject(err); - } - }); -} - -module.exports = JsExecutor; diff --git a/msa/js-executor/api/jsExecutor.models.ts b/msa/js-executor/api/jsExecutor.models.ts new file mode 100644 index 0000000000..db2ced52c4 --- /dev/null +++ b/msa/js-executor/api/jsExecutor.models.ts @@ -0,0 +1,69 @@ +/// +/// Copyright © 2016-2022 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + + +export interface TbMessage { + scriptIdMSB: string; + scriptIdLSB: string; +} + +export interface RemoteJsRequest { + compileRequest?: JsCompileRequest; + invokeRequest?: JsInvokeRequest; + releaseRequest?: JsReleaseRequest; +} + +export interface JsReleaseRequest extends TbMessage { + functionName: string; +} + +export interface JsInvokeRequest extends TbMessage { + functionName: string; + scriptBody: string; + timeout: number; + args: string[]; +} + +export interface JsCompileRequest extends TbMessage { + functionName: string; + scriptBody: string; +} + + +export interface JsReleaseResponse extends TbMessage { + success: boolean; +} + +export interface JsCompileResponse extends TbMessage { + success: boolean; + errorCode?: number; + errorDetails?: string; +} + +export interface JsInvokeResponse { + success: boolean; + result: string; + errorCode?: number; + errorDetails?: string; +} + +export interface RemoteJsResponse { + requestIdMSB: string; + requestIdLSB: string; + compileResponse?: JsCompileResponse; + invokeResponse?: JsInvokeResponse; + releaseResponse?: JsReleaseResponse; +} diff --git a/msa/js-executor/api/jsExecutor.ts b/msa/js-executor/api/jsExecutor.ts new file mode 100644 index 0000000000..f22f14281b --- /dev/null +++ b/msa/js-executor/api/jsExecutor.ts @@ -0,0 +1,93 @@ +/// +/// Copyright © 2016-2022 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import vm, { Script } from 'vm'; + +export type TbScript = Script | Function; + +export class JsExecutor { + useSandbox: boolean; + + constructor(useSandbox: boolean) { + this.useSandbox = useSandbox; + } + + compileScript(code: string): Promise { + if (this.useSandbox) { + return this.createScript(code); + } else { + return this.createFunction(code); + } + } + + executeScript(script: TbScript, args: string[], timeout?: number): Promise { + if (this.useSandbox) { + return this.invokeScript(script as Script, args, timeout); + } else { + return this.invokeFunction(script as Function, args); + } + } + + private createScript(code: string): Promise