@dronedeploy/rocos-js-sdk 3.0.1-alpha → 3.0.1-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/IRocosSDK.d.ts CHANGED
@@ -1,29 +1,5 @@
1
- import { MapService, SpotProvisioningServiceNode } from './services';
2
- import { AssetStorageService } from './services/AssetStorageService';
3
- import { AuthService } from './services/AuthService';
4
- import { CallerService } from './services/CallerService';
5
- import { CommandService } from './services/CommandService';
6
- import { ConfigGroupService } from './services/ConfigGroupService';
7
- import { ControlService } from './services/ControlService';
8
- import { DashboardService } from './services/DashboardService';
9
- import { EventService } from './services/EventService';
10
- import { FileAccessorService } from './services/FileAccessorService';
11
- import { FunctionService } from './services/FunctionService';
12
- import { IBaseService } from './models/IBaseService';
13
- import { IDebugLevel } from './models/IDebugLevel';
14
- import { IntegrationService } from './services/IntegrationService';
15
- import { ProfileService } from './services/ProfileService';
16
- import { ProjectService } from './services/ProjectService';
17
- import { RobotService } from './services/RobotService';
18
- import { SearchService } from './services/SearchService';
19
- import { ServiceEnum } from './models/ServiceEnum';
20
- import { SpotProvisioningService } from './services/SpotProvisioningService';
21
- import { StreamService } from './services/StreamService';
22
- import { TelemetryService } from './services/TelemetryService';
23
- import { TimeSyncerService } from './services/TimeSyncerService';
24
- import { UserService } from './services/UserService';
25
- import { WebRTCSignallingService } from './services/WebRTCSignallingService';
26
- import { WorkflowService } from './services/WorkflowService';
1
+ import { AssetStorageService, AuthService, CallerService, CommandService, ConfigGroupService, ControlService, DashboardService, EvaluatorService, EventService, FileAccessorService, FunctionService, IntegrationService, MapService, ProfileService, ProjectService, RobotService, SearchService, SpotProvisioningService, SpotProvisioningServiceNode, StreamService, TelemetryService, TimeSyncerService, UserService, WebRTCSignallingService, WorkflowService } from './services';
2
+ import { IBaseService, IDebugLevel, ServiceEnum } from './models';
27
3
  export declare abstract class IRocosSDK {
28
4
  abstract getService<T extends IBaseService>(name: ServiceEnum): T;
29
5
  abstract getAuthService(): AuthService;
@@ -49,6 +25,7 @@ export declare abstract class IRocosSDK {
49
25
  abstract getFileAccessorService(): FileAccessorService;
50
26
  abstract getSpotProvisionerService(): SpotProvisioningService | SpotProvisioningServiceNode;
51
27
  abstract getIntegrationService(): IntegrationService;
28
+ abstract getEvaluatorService(): EvaluatorService;
52
29
  abstract cleanup(): Promise<boolean>;
53
30
  abstract enableDebugMode(on: boolean): void;
54
31
  abstract setDebugLevel(level: IDebugLevel): void;
package/RocosSDK.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { AssetStorageService, AuthService, CallerService, CommandService, ConfigGroupService, ControlService, DashboardService, EventService, FileAccessorService, FunctionService, IntegrationService, MapService, ProfileService, ProjectService, RobotService, ScheduleService, SearchService, SpotProvisioningService, StreamService, TelemetryService, TimeSyncerService, UserService, WebRTCSignallingService, WorkflowService } from './services';
1
+ import { AssetStorageService, AuthService, CallerService, CommandService, ConfigGroupService, ControlService, DashboardService, EvaluatorService, EventService, FileAccessorService, FunctionService, IntegrationService, MapService, ProfileService, ProjectService, RobotService, ScheduleService, SearchService, SpotProvisioningService, StreamService, TelemetryService, TimeSyncerService, UserService, WebRTCSignallingService, WorkflowService } from './services';
2
2
  import { IBaseService, IDebugLevel, IRocosSDKConfig, ServiceEnum } from './models';
3
3
  import { IRocosSDK } from './IRocosSDK';
4
4
  import { Logger } from 'loglevel';
@@ -120,6 +120,11 @@ export declare class RocosSDK implements IRocosSDK {
120
120
  * @returns MapService
121
121
  */
122
122
  getMapService(): MapService;
123
+ /**
124
+ * Gets the evaluator service
125
+ * @returns EvaluatorService
126
+ */
127
+ getEvaluatorService(): EvaluatorService;
123
128
  get platformTimeOffset(): number;
124
129
  get platformTime(): number;
125
130
  /**
package/RocosSDK.js CHANGED
@@ -1,4 +1,4 @@
1
- import { AssetStorageService, AuthService, CallerService, CommandService, ConfigGroupService, ControlService, DashboardService, EventService, FileAccessorService, FunctionService, IntegrationService, MapService, PlatFormTimeService, ProfileService, ProjectService, RobotService, ScheduleService, SearchService, SpotProvisioningService, StreamService, TelemetryService, TimeSyncerService, UserService, WebRTCSignallingService, WorkflowService, } from './services';
1
+ import { AssetStorageService, AuthService, CallerService, CommandService, ConfigGroupService, ControlService, DashboardService, EvaluatorService, EventService, FileAccessorService, FunctionService, IntegrationService, MapService, PlatFormTimeService, ProfileService, ProjectService, RobotService, ScheduleService, SearchService, SpotProvisioningService, StreamService, TelemetryService, TimeSyncerService, UserService, WebRTCSignallingService, WorkflowService, } from './services';
2
2
  import { ServiceEnum } from './models';
3
3
  import { RocosLogger } from './logger/RocosLogger';
4
4
  import { RocosStore } from './store/RocosStore';
@@ -97,6 +97,9 @@ export class RocosSDK {
97
97
  case ServiceEnum.MAP:
98
98
  this.services[name] = new MapService(this.config);
99
99
  break;
100
+ case ServiceEnum.EVALUATOR:
101
+ this.services[name] = new EvaluatorService(this.config);
102
+ break;
100
103
  }
101
104
  }
102
105
  this.logger.debug(`Found service ${name}.`);
@@ -252,6 +255,13 @@ export class RocosSDK {
252
255
  getMapService() {
253
256
  return this.getService(ServiceEnum.MAP);
254
257
  }
258
+ /**
259
+ * Gets the evaluator service
260
+ * @returns EvaluatorService
261
+ */
262
+ getEvaluatorService() {
263
+ return this.getService(ServiceEnum.EVALUATOR);
264
+ }
255
265
  get platformTimeOffset() {
256
266
  return PlatFormTimeService.getInstance(this.getTimeSyncerService())?.platformTimeOffset;
257
267
  }
@@ -31,11 +31,6 @@ export default class Connection<Local extends APIDeclaration<Local>, Remote exte
31
31
  private callbacks;
32
32
  private serviceMethods;
33
33
  constructor(name: string, postMessage: typeof window.postMessage, methods: Local, registerOnMessageListener: (listener: ListenerCallback) => void, options?: Partial<ConnectionOptions>);
34
- /** Update the local methods available to the remote
35
- *
36
- * @param methods - methods to expose to the remote
37
- */
38
- defineMethods(methods: Local): void;
39
34
  /** Call a remote method
40
35
  *
41
36
  * returns a promise that resolves when the remote responds
@@ -21,13 +21,6 @@ export default class Connection {
21
21
  this.postMessageInternal = postMessage;
22
22
  registerOnMessageListener((e) => this.onMessageListener(e));
23
23
  }
24
- /** Update the local methods available to the remote
25
- *
26
- * @param methods - methods to expose to the remote
27
- */
28
- defineMethods(methods) {
29
- this.serviceMethods = new Map(Object.entries(methods));
30
- }
31
24
  /** Call a remote method
32
25
  *
33
26
  * returns a promise that resolves when the remote responds
@@ -1,4 +1,5 @@
1
1
  // Auto-generated file
2
2
  /* eslint-disable */
3
- const source = "(()=>{\"use strict\";var e={880:(e,t)=>{var s;Object.defineProperty(t,\"__esModule\",{value:!0}),function(e){e.RESPONSE=\"response\",e.MESSAGE=\"message\"}(s||(s={}));const r={allowedSenderOrigin:void 0,debugMode:!1};t.default=class{constructor(e,t,s,o,n={}){this.callbacks=new Map,this.serviceMethods=new Map,this.name=e,this.options={...r,...n},this.log(\"Created connection w/ allowedOrigin:\",this.options.allowedSenderOrigin),this.serviceMethods=new Map(Object.entries(s));const[i]=crypto.getRandomValues(new Uint32Array(1));this.incrementalID=i,this.postMessageInternal=t,o((e=>this.onMessageListener(e)))}defineMethods(e){this.serviceMethods=new Map(Object.entries(e))}callRemoteMethod(e,...t){return this.log(\"Calling Remote Method\",{name:e,args:t}),new Promise(((r,o)=>{const n=this.registerCallback(r,o);this.postMessage({callId:n,type:s.MESSAGE,methodName:e,arguments:t})}))}onMessageListener(e){this.log(\"Received message\",e);const{data:t}=e,{allowedSenderOrigin:r}=this.options;switch(r&&e.origin!==r&&console.warn(`Received message from invalid origin: ${e.origin}`),t.type){case s.RESPONSE:return void this.popCallback(t.callId,t.success,t.result);case s.MESSAGE:this.callLocalMethod(t.methodName,t.arguments).then((e=>this.responseOtherSide(t.callId,e))).catch((e=>this.responseOtherSide(t.callId,e,!1)))}}async callLocalMethod(e,t){this.log(\"calling local method\",e,t);const s=this.serviceMethods.get(e);if(!s)throw new Error(`service method ${e} not found`);return s(...t)}responseOtherSide(e,t,r=!0){this.log(\"responding to remote call\",{id:e,result:t,success:r});const o=t=>{this.postMessage({callId:e,type:s.RESPONSE,success:r,result:t})};try{o(t)}catch(e){e instanceof DOMException&&o(JSON.parse(JSON.stringify(t)))}}registerCallback(e,t){const s=(++this.incrementalID).toString();return this.log(\"registering callback for id\",s),this.callbacks.set(s,{success:e,failure:t}),s}popCallback(e,t,s){this.log(\"calling callback for id\",e,{success:t,result:s});const r=this.callbacks.get(e);t?r?.success(s):r?.failure(s),this.callbacks.delete(e)}postMessage(e,t=\"*\"){this.log(\"sending message\",{data:e,targetOrigin:t}),this.postMessageInternal(e,t)}log(...e){this.options.debugMode&&console.debug(`[${this.name}]`,...e)}}},306:function(e,t,s){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,\"__esModule\",{value:!0});const o=r(s(880)),n=r(s(54)),i=new class{constructor(){const e=!!window?.debugMode;this.connection=new o.default(\"FRAME\",window.parent.postMessage.bind(window.parent),{startTask:this.runCode.bind(this)},(e=>{window.addEventListener(\"message\",e)}),{debugMode:e}),this.connection.callRemoteMethod(\"iframeInitialised\"),this.workerManager=new n.default}async runCode(e){return this.workerManager.execute(e)}};t.default=i},54:function(e,t,s){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,\"__esModule\",{value:!0});const o=r(s(420));t.default=o.default},420:function(e,t,s){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,\"__esModule\",{value:!0});const o=r(s(967));t.default=class{constructor(){this.worker=this.createWorker()}async execute(e){const t={...e,contextVariable:e.contextVariable??\"ctx\"},s=this.runTask(t),r=this.timeout(e.timeout??1e3);return Promise.race([s,r]).finally((()=>{this.removeMessageListener()}))}terminate(){this.removeMessageListener(),this.worker.terminate(),this.worker=this.createWorker()}runTask(e){return new Promise(((t,s)=>{const r=r=>{const{data:o}=r;o.id===e.id&&(this.stopTimer(),o.success?t(o.result):s(o.result))};this.worker.addEventListener(\"message\",r),this.removeMessageListener=()=>this.worker.removeEventListener(\"message\",r),this.worker.postMessage(e)}))}timeout(e){return new Promise(((t,s)=>{this.timerId=window.setTimeout((()=>{this.terminate(),s(new Error(\"maximum execution time exceeded\"))}),e)}))}stopTimer(){clearTimeout(this.timerId)}createWorker(){const e=URL.createObjectURL(new Blob([o.default],{type:\"application/javascript\"}));return new Worker(e)}removeMessageListener(){}}},967:(e,t)=>{Object.defineProperty(t,\"__esModule\",{value:!0}),t.default='(()=>{\"use strict\";(()=>{const e=[\"TEMPORARY\",\"PERSISTENT\",\"console\",\"self\",\"onmessage\",\"postMessage\",\"global\",\"allowed\",\"Array\",\"Boolean\",\"Date\",\"Function\",\"Number\",\"Object\",\"RegExp\",\"String\",\"Error\",\"EvalError\",\"RangeError\",\"ReferenceError\",\"SyntaxError\",\"TypeError\",\"URIError\",\"decodeURI\",\"decodeURIComponent\",\"encodeURI\",\"encodeURIComponent\",\"isFinite\",\"isNaN\",\"parseFloat\",\"parseInt\",\"Infinity\",\"JSON\",\"Math\",\"NaN\",\"undefined\"];[...Object.getOwnPropertyNames(self),...Object.getOwnPropertyNames(self.__proto__)].forEach((r=>{e.includes(r)||Object.defineProperty(self,r,{get:()=>{throw new Error(`Security Exception: cannot access ${r}`)},set:()=>{throw new Error(`Security Exception: cannot set ${r}`)},configurable:!1})})),onmessage=e=>{let r,t=!0;try{r=Function(e.data.contextVariable,`\"use strict\";return (${e.data.code});`)(e.data.context)}catch(e){r=e,t=!1}const o={id:e.data.id,result:r,success:t};postMessage(o)}})()})();'}},t={};!function s(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={exports:{}};return e[r].call(n.exports,n,n.exports,s),n.exports}(306)})();";
3
+ import __WORKER_SOURCE__ from './worker/worker.source';
4
+ const source = `(()=>{"use strict";var e={880:(e,t)=>{var s;Object.defineProperty(t,"__esModule",{value:!0}),function(e){e.RESPONSE="response",e.MESSAGE="message"}(s||(s={}));const r={allowedSenderOrigin:void 0,debugMode:!1};t.default=class{constructor(e,t,s,i,o={}){this.callbacks=new Map,this.serviceMethods=new Map,this.name=e,this.options={...r,...o},this.log("Created connection w/ allowedOrigin:",this.options.allowedSenderOrigin),this.serviceMethods=new Map(Object.entries(s));const[n]=crypto.getRandomValues(new Uint32Array(1));this.incrementalID=n,this.postMessageInternal=t,i((e=>this.onMessageListener(e)))}callRemoteMethod(e,...t){return this.log("Calling Remote Method",{name:e,args:t}),new Promise(((r,i)=>{const o=this.registerCallback(r,i);this.postMessage({callId:o,type:s.MESSAGE,methodName:e,arguments:t})}))}onMessageListener(e){this.log("Received message",e);const{data:t}=e,{allowedSenderOrigin:r}=this.options;switch(r&&e.origin!==r&&console.warn(\`Received message from invalid origin: \${e.origin}\`),t.type){case s.RESPONSE:return void this.popCallback(t.callId,t.success,t.result);case s.MESSAGE:this.callLocalMethod(t.methodName,t.arguments).then((e=>this.responseOtherSide(t.callId,e))).catch((e=>this.responseOtherSide(t.callId,e,!1)))}}async callLocalMethod(e,t){this.log("calling local method",e,t);const s=this.serviceMethods.get(e);if(!s)throw new Error(\`service method \${e} not found\`);return s(...t)}responseOtherSide(e,t,r=!0){this.log("responding to remote call",{id:e,result:t,success:r});const i=t=>{this.postMessage({callId:e,type:s.RESPONSE,success:r,result:t})};try{i(t)}catch(e){e instanceof DOMException&&i(JSON.parse(JSON.stringify(t)))}}registerCallback(e,t){const s=(++this.incrementalID).toString();return this.log("registering callback for id",s),this.callbacks.set(s,{success:e,failure:t}),s}popCallback(e,t,s){this.log("calling callback for id",e,{success:t,result:s});const r=this.callbacks.get(e);t?r?.success(s):r?.failure(s),this.callbacks.delete(e)}postMessage(e,t="*"){this.log("sending message",{data:e,targetOrigin:t}),this.postMessageInternal(e,t)}log(...e){this.options.debugMode&&console.debug(\`[\${this.name}]\`,...e)}}},306:function(e,t,s){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const i=r(s(880)),o=r(s(54)),n=new class{constructor(){const e=!!window?.debugMode;this.connection=new i.default("FRAME",window.parent.postMessage.bind(window.parent),{startTask:this.runCode.bind(this)},(e=>{window.addEventListener("message",e)}),{debugMode:e}),this.connection.callRemoteMethod("iframeInitialised"),this.workerManager=new o.default}async runCode(e){return this.workerManager.execute(e)}};t.default=n},54:function(e,t,s){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const i=r(s(420));t.default=i.default},420:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.default=class{constructor(){this.worker=this.createWorker()}async execute(e){const t={...e,contextVariable:e.contextVariable??"ctx"},s=this.runTask(t),r=this.timeout(e.timeout??1e3);return Promise.race([s,r]).finally((()=>{this.removeMessageListener()}))}terminate(){this.removeMessageListener(),this.worker.terminate(),this.worker=this.createWorker()}runTask(e){return new Promise(((t,s)=>{const r=r=>{const{data:i}=r;i.id===e.id&&(this.stopTimer(),i.success?t(i.result):s(i.result))};this.worker.addEventListener("message",r),this.removeMessageListener=()=>this.worker.removeEventListener("message",r),this.worker.postMessage(e)}))}timeout(e){return new Promise(((t,s)=>{this.timerId=window.setTimeout((()=>{this.terminate(),s(new Error("maximum execution time exceeded"))}),e)}))}stopTimer(){clearTimeout(this.timerId)}createWorker(){const e=URL.createObjectURL(new Blob(["${__WORKER_SOURCE__.replace(/(['`"$])/g, '\\$1')}"],{type:"application/javascript"}));return new Worker(e)}removeMessageListener(){}}}},t={};!function s(r){var i=t[r];if(void 0!==i)return i.exports;var o=t[r]={exports:{}};return e[r].call(o.exports,o,o.exports,s),o.exports}(306)})();`;
4
5
  export default source;
@@ -1,4 +1,5 @@
1
- import workerSource from './worker.source';
1
+ // this token (__WORKER_SOURCE__) is replaced by webpack with the source of the worker
2
+ const WORKER_SOURCE = '__WORKER_SOURCE__';
2
3
  export default class Manager {
3
4
  constructor() {
4
5
  this.worker = this.createWorker();
@@ -50,7 +51,7 @@ export default class Manager {
50
51
  clearTimeout(this.timerId);
51
52
  }
52
53
  createWorker() {
53
- const blob = URL.createObjectURL(new Blob([workerSource], { type: 'application/javascript' }));
54
+ const blob = URL.createObjectURL(new Blob([WORKER_SOURCE], { type: 'application/javascript' }));
54
55
  return new Worker(blob);
55
56
  }
56
57
  removeMessageListener() {
@@ -1,4 +1,4 @@
1
1
  // Auto-generated file
2
2
  /* eslint-disable */
3
- const source = "(()=>{\"use strict\";(()=>{const e=[\"TEMPORARY\",\"PERSISTENT\",\"console\",\"self\",\"onmessage\",\"postMessage\",\"global\",\"allowed\",\"Array\",\"Boolean\",\"Date\",\"Function\",\"Number\",\"Object\",\"RegExp\",\"String\",\"Error\",\"EvalError\",\"RangeError\",\"ReferenceError\",\"SyntaxError\",\"TypeError\",\"URIError\",\"decodeURI\",\"decodeURIComponent\",\"encodeURI\",\"encodeURIComponent\",\"isFinite\",\"isNaN\",\"parseFloat\",\"parseInt\",\"Infinity\",\"JSON\",\"Math\",\"NaN\",\"undefined\"];[...Object.getOwnPropertyNames(self),...Object.getOwnPropertyNames(self.__proto__)].forEach((r=>{e.includes(r)||Object.defineProperty(self,r,{get:()=>{throw new Error(`Security Exception: cannot access ${r}`)},set:()=>{throw new Error(`Security Exception: cannot set ${r}`)},configurable:!1})})),onmessage=e=>{let r,t=!0;try{r=Function(e.data.contextVariable,`\"use strict\";return (${e.data.code});`)(e.data.context)}catch(e){r=e,t=!1}const o={id:e.data.id,result:r,success:t};postMessage(o)}})()})();";
3
+ const source = `(()=>{"use strict";(()=>{const e=["TEMPORARY","PERSISTENT","console","self","onmessage","postMessage","global","allowed","Array","Boolean","Date","Function","Number","Object","RegExp","String","Error","EvalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","isFinite","isNaN","parseFloat","parseInt","Infinity","JSON","Math","NaN","undefined"];[...Object.getOwnPropertyNames(self),...Object.getOwnPropertyNames(self.__proto__)].forEach((r=>{e.includes(r)||Object.defineProperty(self,r,{get:()=>{throw new Error(\`Security Exception: cannot access \${r}\`)},set:()=>{throw new Error(\`Security Exception: cannot set \${r}\`)},configurable:!1})})),onmessage=e=>{let r,t=!0;try{r=Function(e.data.contextVariable,\`"use strict";return (\${e.data.code});\`)(e.data.context)}catch(e){r=e,t=!1}const o={id:e.data.id,result:r,success:t};postMessage(o)}})()})();`;
4
4
  export default source;
@@ -24,11 +24,16 @@ export declare const BaseOptions: SandboxOptions;
24
24
  export interface SandboxMethods {
25
25
  iframeInitialised: () => void;
26
26
  }
27
+ /** A sandbox for running untrusted code in an iframe & embedded web worker.
28
+ *
29
+ * This is a wrapper around the iframe and web worker that provides a simple API for running code in the sandbox.
30
+ * It also provides a context object that can be used to pass data into the sandbox.
31
+ */
27
32
  export default class WebSandbox {
28
- private options;
33
+ private readonly options;
29
34
  private frame;
30
35
  private connection?;
31
- initialised: Promise<WebSandbox>;
36
+ private initialised;
32
37
  static new(options?: Partial<SandboxOptions>): Promise<WebSandbox>;
33
38
  private constructor();
34
39
  /** Runs code in the sandbox. Can be either a string or a function */
@@ -39,6 +44,7 @@ export default class WebSandbox {
39
44
  */
40
45
  destroy(): void;
41
46
  private initialise;
47
+ private validateOptions;
42
48
  private destroyAndRebuild;
43
49
  private removeMessageListener;
44
50
  private runFunction;
@@ -6,18 +6,26 @@ export const BaseOptions = {
6
6
  debugMode: false,
7
7
  contextVariable: 'ctx',
8
8
  timeout: {
9
- minimumMs: 500,
10
- maximumMs: 1000,
9
+ minimumMs: 1000,
10
+ maximumMs: 1500,
11
11
  },
12
12
  };
13
+ /** A sandbox for running untrusted code in an iframe & embedded web worker.
14
+ *
15
+ * This is a wrapper around the iframe and web worker that provides a simple API for running code in the sandbox.
16
+ * It also provides a context object that can be used to pass data into the sandbox.
17
+ */
13
18
  export default class WebSandbox {
14
19
  static async new(options = {}) {
15
- return new WebSandbox(options).initialised;
20
+ const sandbox = new WebSandbox(options);
21
+ await sandbox.initialised;
22
+ return sandbox;
16
23
  }
17
24
  constructor(options) {
18
25
  this.options = { ...BaseOptions, ...options };
19
26
  this.frame = this.createFrame();
20
- this.initialised = this.initialise().then(() => this);
27
+ this.validateOptions(this.options);
28
+ this.initialised = this.initialise();
21
29
  }
22
30
  /** Runs code in the sandbox. Can be either a string or a function */
23
31
  async run(code, context, options) {
@@ -50,6 +58,19 @@ export default class WebSandbox {
50
58
  }, { allowedSenderOrigin: 'null', debugMode: this.options.debugMode });
51
59
  });
52
60
  }
61
+ validateOptions(options) {
62
+ const minimumTimeout = options.timeout.minimumMs;
63
+ const maximumTimeout = options.timeout.maximumMs;
64
+ if (maximumTimeout < minimumTimeout) {
65
+ throw new Error(`maximum timeout (${maximumTimeout}ms) must be greater than or equal to minimum timeout (${minimumTimeout}ms)`);
66
+ }
67
+ if (minimumTimeout <= 0 || maximumTimeout <= 0) {
68
+ throw new Error('timeout values must be greater than 0');
69
+ }
70
+ if (maximumTimeout > 5000) {
71
+ throw new Error('maximum timeout must be less than or equal to 5000ms');
72
+ }
73
+ }
53
74
  async destroyAndRebuild() {
54
75
  this.destroy();
55
76
  this.frame = this.createFrame();
@@ -65,9 +86,13 @@ export default class WebSandbox {
65
86
  if (!this.connection) {
66
87
  throw new Error('sandbox not initialised');
67
88
  }
89
+ this.validateOptions({
90
+ ...this.options,
91
+ ...options,
92
+ });
68
93
  let timerId;
69
94
  const timeout = new Promise((_, reject) => {
70
- setTimeout(() => {
95
+ timerId = setTimeout(() => {
71
96
  this.destroyAndRebuild().finally(() => reject(new Error('sandbox timed out')));
72
97
  }, options?.timeout?.maximumMs ?? this.options.timeout.maximumMs);
73
98
  });
@@ -90,7 +115,12 @@ export default class WebSandbox {
90
115
  throw new Error('unable to find container for sandbox');
91
116
  }
92
117
  const iframe = document.createElement('iframe');
93
- iframe.sandbox.add('allow-scripts');
118
+ if (iframe.sandbox) {
119
+ iframe.sandbox.add('allow-scripts');
120
+ }
121
+ else {
122
+ iframe.setAttribute('sandbox', 'allow-scripts');
123
+ }
94
124
  iframe.srcdoc = this.prepareFrameContent();
95
125
  iframe.style.display = 'none';
96
126
  container.appendChild(iframe);
@@ -22,6 +22,7 @@ export declare const errorCodes: {
22
22
  SCHEDULE_SERVICE_ERROR: string;
23
23
  INTEGRATIONS_SERVICE_ERROR: string;
24
24
  MAPS_SERVICE_ERROR: string;
25
+ EVALUATOR_SERVICE_ERROR: string;
25
26
  };
26
27
  export declare class RocosError extends Error {
27
28
  code?: string;
@@ -22,6 +22,7 @@ export const errorCodes = {
22
22
  SCHEDULE_SERVICE_ERROR: 'SCHEDULE_SERVICE_ERROR',
23
23
  INTEGRATIONS_SERVICE_ERROR: 'INTEGRATIONS_SERVICE_ERROR',
24
24
  MAPS_SERVICE_ERROR: 'MAPS_SERVICE_ERROR',
25
+ EVALUATOR_SERVICE_ERROR: 'EVALUATOR_SERVICE_ERROR',
25
26
  };
26
27
  export class RocosError extends Error {
27
28
  constructor(err, code, statusCode) {
@@ -22,5 +22,6 @@ export declare enum ServiceEnum {
22
22
  SCHEDULE = "schedule",
23
23
  SPOT_PROVISIONER = "spot_provisioner",
24
24
  INTEGRATION = "integration",
25
- MAP = "map"
25
+ MAP = "map",
26
+ EVALUATOR = "evaluator"
26
27
  }
@@ -24,4 +24,5 @@ export var ServiceEnum;
24
24
  ServiceEnum["SPOT_PROVISIONER"] = "spot_provisioner";
25
25
  ServiceEnum["INTEGRATION"] = "integration";
26
26
  ServiceEnum["MAP"] = "map";
27
+ ServiceEnum["EVALUATOR"] = "evaluator";
27
28
  })(ServiceEnum || (ServiceEnum = {}));
@@ -1,4 +1,4 @@
1
- import { ScheduleService } from '../services';
1
+ import { EvaluatorService, ScheduleService } from '../services';
2
2
  import { CallerServiceNode } from '../services/CallerServiceNode';
3
3
  import { CommandServiceNode } from '../services/CommandServiceNode';
4
4
  import { ControlServiceNode } from '../services/ControlServiceNode';
@@ -39,4 +39,9 @@ export declare class RocosSDKNode extends RocosSDK {
39
39
  * @returns FileAccessorServiceNode
40
40
  */
41
41
  getFileAccessorService(): FileAccessorServiceNode;
42
+ /**
43
+ * Gets the evaluator service
44
+ * @returns EvaluatorServiceNode
45
+ */
46
+ getEvaluatorService(): EvaluatorService;
42
47
  }
@@ -140,4 +140,11 @@ export class RocosSDKNode extends RocosSDK {
140
140
  getFileAccessorService() {
141
141
  return this.getService(ServiceEnum.FILE_ACCESSOR);
142
142
  }
143
+ /**
144
+ * Gets the evaluator service
145
+ * @returns EvaluatorServiceNode
146
+ */
147
+ getEvaluatorService() {
148
+ throw new Error('Evaluator service is not supported in NodeJS');
149
+ }
143
150
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dronedeploy/rocos-js-sdk",
3
- "version": "3.0.1-alpha",
3
+ "version": "3.0.1-alpha.1",
4
4
  "description": "Javascript SDK for rocos",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -0,0 +1,11 @@
1
+ import { IBaseService, IRocosSDKConfig, RocosError } from '../models';
2
+ import { BaseServiceAbstract } from './BaseServiceAbstract';
3
+ import { RunCodeOptions } from '../helpers/websandbox/sandbox';
4
+ export declare class EvaluatorService extends BaseServiceAbstract implements IBaseService {
5
+ private readonly sandbox;
6
+ constructor(config: IRocosSDKConfig);
7
+ protected getError(e: Error): RocosError;
8
+ getStatus(): boolean;
9
+ teardown(): Promise<void>;
10
+ execute<T = unknown>(code: string | (() => T), context?: unknown, options?: RunCodeOptions): Promise<T>;
11
+ }
@@ -0,0 +1,28 @@
1
+ import { RocosError, errorCodes } from '../models';
2
+ import { BaseServiceAbstract } from './BaseServiceAbstract';
3
+ import { RocosLogger } from '../logger/RocosLogger';
4
+ import { WebSandbox } from '../helpers';
5
+ export class EvaluatorService extends BaseServiceAbstract {
6
+ constructor(config) {
7
+ super(config);
8
+ this.logger = RocosLogger.getInstance(`EvaluatorService(${this.config.url})`);
9
+ this.sandbox = WebSandbox.new().catch((e) => {
10
+ this.logger.error('Failed to create WebSandbox', e);
11
+ throw e;
12
+ });
13
+ }
14
+ getError(e) {
15
+ return new RocosError(e, errorCodes.EVALUATOR_SERVICE_ERROR);
16
+ }
17
+ getStatus() {
18
+ return true;
19
+ }
20
+ async teardown() {
21
+ const sandbox = await this.sandbox;
22
+ sandbox.destroy();
23
+ }
24
+ async execute(code, context, options) {
25
+ const sandbox = await this.sandbox;
26
+ return sandbox.run(code, context, options);
27
+ }
28
+ }
@@ -102,6 +102,7 @@ export declare class MapService extends BaseServiceAbstract implements IBaseServ
102
102
  *
103
103
  * @param projectId Project ID
104
104
  * @param mapId Map ID
105
+ * @param frameId Frame ID (optional)
105
106
  */
106
- getGeoJSON(projectId: string, mapId: string): Promise<unknown>;
107
+ getGeoJSON(projectId: string, mapId: string, frameId?: string): Promise<unknown>;
107
108
  }
@@ -138,12 +138,14 @@ export class MapService extends BaseServiceAbstract {
138
138
  *
139
139
  * @param projectId Project ID
140
140
  * @param mapId Map ID
141
+ * @param frameId Frame ID (optional)
141
142
  */
142
- async getGeoJSON(projectId, mapId) {
143
- return this.callGet(formatServiceUrl(API_MAPS_GEOJSON_URL, {
143
+ async getGeoJSON(projectId, mapId, frameId) {
144
+ const params = {
144
145
  url: this.config.url,
145
146
  projectId,
146
147
  mapId,
147
- }, this.config.insecure), 'Failed to get map GeoJSON.');
148
+ };
149
+ return this.callGet(formatServiceUrl(API_MAPS_GEOJSON_URL, params, this.config.insecure), 'Failed to get map GeoJSON.', frameId ? { frameID: frameId } : undefined);
148
150
  }
149
151
  }
@@ -24,3 +24,4 @@ export * from './PlatformTimeService';
24
24
  export * from './SpotProvisioningService';
25
25
  export * from './SpotProvisioningServiceNode';
26
26
  export * from './MapService';
27
+ export * from './EvaluatorService';
package/services/index.js CHANGED
@@ -24,3 +24,4 @@ export * from './PlatformTimeService';
24
24
  export * from './SpotProvisioningService';
25
25
  export * from './SpotProvisioningServiceNode';
26
26
  export * from './MapService';
27
+ export * from './EvaluatorService';