common: eval/monaco boilerplate

This commit is contained in:
Koushik Dutta
2021-09-27 23:06:40 -07:00
parent a4f91f4923
commit b4db0e53cd
3 changed files with 154 additions and 9 deletions

View File

@@ -9,7 +9,8 @@
"version": "1.0.1",
"license": "ISC",
"dependencies": {
"@scrypted/sdk": "file:../sdk"
"@scrypted/sdk": "file:../sdk",
"typescript": "^4.4.3"
},
"devDependencies": {
"@types/node": "^16.9.0"
@@ -17,19 +18,23 @@
},
"../sdk": {
"name": "@scrypted/sdk",
"version": "0.0.69",
"version": "0.0.81",
"license": "ISC",
"dependencies": {
"@babel/core": "^7.2.2",
"@babel/plugin-proposal-class-properties": "^7.4.4",
"@babel/plugin-proposal-optional-chaining": "^7.13.12",
"@babel/plugin-transform-modules-commonjs": "^7.2.0",
"@babel/plugin-transform-typescript": "^7.15.0",
"@babel/polyfill": "^7.2.5",
"@babel/preset-env": "^7.2.3",
"@babel/preset-typescript": "^7.15.0",
"@types/node": "^16.6.1",
"adm-zip": "^0.4.13",
"axios": "^0.21.1",
"axios": "^0.21.4",
"babel-loader": "^8.0.4",
"babel-plugin-const-enum": "^1.1.0",
"babel-plugin-minify-dead-code-elimination": "^0.5.1",
"babel-polyfill": "^6.26.0",
"babel-template": "^6.26.0",
"browserify-buffertools": "^1.0.2",
@@ -60,10 +65,7 @@
"scrypted-webpack": "bin/scrypted-webpack.js"
},
"devDependencies": {
"@babel/plugin-proposal-optional-chaining": "^7.13.12",
"@types/node": "^16.6.1",
"babel-plugin-const-enum": "^1.1.0",
"babel-plugin-minify-dead-code-elimination": "^0.5.1"
"typescript-json-schema": "^0.50.1"
}
},
"node_modules/@scrypted/sdk": {
@@ -75,6 +77,18 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.0.tgz",
"integrity": "sha512-nmP+VR4oT0pJUPFbKE4SXj3Yb4Q/kz3M9dSAO1GGMebRKWHQxLfDNmU/yh3xxCJha3N60nQ/JwXWwOE/ZSEVag==",
"dev": true
},
"node_modules/typescript": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz",
"integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=4.2.0"
}
}
},
"dependencies": {
@@ -91,7 +105,7 @@
"@babel/preset-typescript": "^7.15.0",
"@types/node": "^16.6.1",
"adm-zip": "^0.4.13",
"axios": "^0.21.1",
"axios": "^0.21.4",
"babel-loader": "^8.0.4",
"babel-plugin-const-enum": "^1.1.0",
"babel-plugin-minify-dead-code-elimination": "^0.5.1",
@@ -112,6 +126,7 @@
"ts-loader": "^5.4.5",
"tsconfig-paths-webpack-plugin": "^3.2.0",
"typescript": "^4.3.5",
"typescript-json-schema": "^0.50.1",
"webpack": "^4.28.1",
"webpack-cli": "^3.1.2",
"webpack-inject-plugin": "^1.0.2"
@@ -122,6 +137,11 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.0.tgz",
"integrity": "sha512-nmP+VR4oT0pJUPFbKE4SXj3Yb4Q/kz3M9dSAO1GGMebRKWHQxLfDNmU/yh3xxCJha3N60nQ/JwXWwOE/ZSEVag==",
"dev": true
},
"typescript": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz",
"integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA=="
}
}
}

View File

@@ -9,7 +9,8 @@
"author": "",
"license": "ISC",
"dependencies": {
"@scrypted/sdk": "file:../sdk"
"@scrypted/sdk": "file:../sdk",
"typescript": "^4.4.3"
},
"devDependencies": {
"@types/node": "^16.9.0"

124
common/src/scrypted-eval.ts Normal file
View File

@@ -0,0 +1,124 @@
import ts, { ScriptTarget } from "typescript";
import sdk, { ScryptedDeviceBase } from "@scrypted/sdk";
import vm from "vm";
const { systemManager, deviceManager, mediaManager, endpointManager } = sdk;
function tsCompile(source: string, options: ts.TranspileOptions = null): string {
// Default options -- you could also perform a merge, or use the project tsconfig.json
if (null === options) {
options = {
compilerOptions: {
target: ScriptTarget.ESNext,
module: ts.ModuleKind.CommonJS
}
};
}
return ts.transpileModule(source, options).outputText;
}
export async function scryptedEval(device: ScryptedDeviceBase, script: string, extraLibs: { [lib: string]: string }, params: { [name: string]: any }) {
try {
const libs = Object.assign({
types: require("!!raw-loader!!@scrypted/sdk/types.d.ts"),
}, extraLibs);
const allScripts = Object.values(libs).join('\n').toString() + script;
const compiled = tsCompile(allScripts);
const allParams = Object.assign({}, params, {
systemManager,
deviceManager,
endpointManager,
mediaManager,
log: device.log,
console: device.console,
localStorage: device.storage,
device,
exports: {},
});
try {
const f = vm.compileFunction(compiled, Object.keys(allParams), {
filename: 'script.js',
});
try {
return await f(...Object.values(allParams));
}
catch (e) {
device.log.e('Error running script.');
device.console.error(e);
throw e;
}
}
catch (e) {
device.log.e('Error evaluating script.');
device.console.error(e);
throw e;
}
}
catch (e) {
device.log.e('Error compiling script.');
device.console.error(e);
throw e;
}
}
export function createMonacoEvalDefaults(extraLibs: { [lib: string]: string }) {
const libs = Object.assign({
types: require("!!raw-loader!@scrypted/sdk/types.d.ts"),
sdk: require("!!raw-loader!@scrypted/sdk/index.d.ts"),
}, extraLibs);
function monacoEvalDefaultsFunction(monaco, libs) {
monaco.languages.typescript.typescriptDefaults.setCompilerOptions(
Object.assign(
{},
monaco.languages.typescript.typescriptDefaults.getCompilerOptions(),
{
moduleResolution:
monaco.languages.typescript.ModuleResolutionKind.NodeJs,
}
)
);
const catLibs = Object.values(libs).join('\n');
const catlibsNoExport = Object.keys(libs).filter(lib => lib !== 'sdk')
.map(lib => libs[lib]).map(lib =>
lib.toString().replace(/export /g, '').replace(/import.*?/g, ''))
.join('\n');
monaco.languages.typescript.typescriptDefaults.addExtraLib(`
${catLibs}
declare global {
${catlibsNoExport}
const log: Logger;
const deviceManager: DeviceManager;
const endpointManager: EndpointManager;
const mediaManager: MediaManager;
const systemManager: SystemManager;
const mqtt: MqttClient;
const device: ScryptedDeviceBase & { pathname : string };
}
`,
"node_modules/@types/scrypted__sdk/types.d.ts"
);
monaco.languages.typescript.typescriptDefaults.addExtraLib(
libs['sdk'],
"node_modules/@types/scrypted__sdk/index.d.ts"
);
}
return `(function() {
const libs = ${JSON.stringify(libs)};
return (monaco) => {
(${monacoEvalDefaultsFunction})(monaco, libs);
}
})();
`;
}