core: add script default export support

This commit is contained in:
Koushik Dutta
2022-06-25 14:17:24 -07:00
parent 9d98059a89
commit cb3591e613
10 changed files with 41 additions and 19 deletions

View File

@@ -1,4 +1,8 @@
export interface ScriptDevice {
/**
* @deprecated Use export default instead.
* @param handler
*/
handle<T>(handler?: T & object): void;
handleTypes(...interfaces: string[]): void;
}

View File

@@ -82,7 +82,7 @@ export async function scryptedEval(device: ScryptedDeviceBase, script: string, e
console: device.console,
localStorage: device.storage,
device,
exports: {},
exports: {} as any,
ScryptedInterface,
ScryptedDeviceType,
});
@@ -102,7 +102,12 @@ export async function scryptedEval(device: ScryptedDeviceBase, script: string, e
}
try {
return await asyncFunction();
const value = await asyncFunction();
const defaultExport = allParams.exports.default;
return {
value,
defaultExport,
};
}
catch (e) {
device.log.e('Error running script.');

View File

@@ -33,4 +33,4 @@ class ChromecastViewCameraExample implements StartStop {
}
}
device.handle(new ChromecastViewCameraExample());
export default ChromecastViewCameraExample;

View File

@@ -17,4 +17,4 @@ class SwitchWebhookExample implements OnOff {
}
}
device.handle(new SwitchWebhookExample());
export default SwitchWebhookExample;

View File

@@ -15,8 +15,9 @@ class WebhookExample implements HttpRequestHandler {
}
}
device.handle(new WebhookExample());
device.handleTypes(ScryptedInterface.MotionSensor);
endpointManager.getInsecurePublicLocalEndpoint(device.nativeId)
.then(endpoint => console.log('motion webhook:', endpoint));
export default WebhookExample;

View File

@@ -9,11 +9,10 @@ class WebhookExample implements HttpRequestHandler {
async onRequest(request: HttpRequest, response: HttpResponse) {
response.send('OK');
// scrpyted uses metric for all units, so this must be celsius
device.temperature = parseFloat(request.body);
device.temperature = parseFloat(request.body!);
}
}
device.handle(new WebhookExample());
device.handleTypes(ScryptedInterface.Thermometer);
endpointManager.getInsecurePublicLocalEndpoint(device.nativeId)
@@ -22,3 +21,5 @@ endpointManager.getInsecurePublicLocalEndpoint(device.nativeId)
console.log('example:');
console.log(' curl -H "Content-Type: text/plain" --data 25 ', endpoint);
});
export default WebhookExample;

View File

@@ -55,7 +55,7 @@ export class Automation extends ScryptedDeviceBase implements OnOff, Settings {
}
async eval(script: string, variables: { [name: string]: any }) {
return scryptedEval(this, script, variables);
return (await scryptedEval(this, script, variables)).value;
}
async turnOff() {

View File

@@ -15,10 +15,10 @@ export class AutomationJavascript {
}
async run(script: string) {
return scryptedEval(this.automation, script, {
return (await scryptedEval(this.automation, script, {
eventDetails: this.eventDetails,
eventData: this.eventData,
eventSource: this.eventSource,
})
})).value;
}
}

View File

@@ -42,7 +42,18 @@ export class Script extends ScryptedDeviceBase implements Scriptable, Program, S
}
}
async postRunScript() {
async postRunScript(defaultExport: any) {
if (defaultExport) {
let deviceInstance = defaultExport;
// support exporting a plugin class, plugin main function,
// or a plugin instance
if (deviceInstance.toString().startsWith('class '))
deviceInstance = new deviceInstance(this.nativeId);
if (typeof deviceInstance === 'function')
deviceInstance = await deviceInstance();
this.handle(deviceInstance);
}
const allInterfaces = this.mergeHandler(this);
if (allInterfaces.length !== 2) {
await deviceManager.onDeviceDiscovered({
@@ -60,7 +71,7 @@ export class Script extends ScryptedDeviceBase implements Scriptable, Program, S
ScryptedInterface.Scriptable,
ScryptedInterface.Program,
]));
}
}
async run(variables?: { [name: string]: any; }): Promise<any> {
this.prepareScript();
@@ -68,12 +79,12 @@ export class Script extends ScryptedDeviceBase implements Scriptable, Program, S
try {
const data = JSON.parse(this.storage.getItem('data'));
const ret = await scryptedEval(this, data['script.ts'], Object.assign({
const { value, defaultExport } = await scryptedEval(this, data['script.ts'], Object.assign({
device: this,
}, variables));
await this.postRunScript();
return ret;
await this.postRunScript(defaultExport);
return value;
}
catch (e) {
this.console.error('error loading script', e);
@@ -84,12 +95,12 @@ export class Script extends ScryptedDeviceBase implements Scriptable, Program, S
async eval(source: ScriptSource, variables: { [name: string]: any }) {
this.prepareScript();
const ret = await scryptedEval(this, source.script, Object.assign({
const { value, defaultExport } = await scryptedEval(this, source.script, Object.assign({
device: this,
}, variables));
await this.postRunScript();
return ret;
await this.postRunScript(defaultExport);
return value;
}
// will be done at runtime

View File

@@ -237,7 +237,7 @@ export default {
this.adjustingTime = setTimeout(() => {
this.adjustingTime = null;
this.streamRecorder(this.startTime);
}, 2500);
}, 10);
},
cleanupConnection() {
console.log("control cleanup");