mirror of
https://github.com/koush/scrypted.git
synced 2026-05-04 21:30:30 +01:00
common: eval/monaco boilerplate
This commit is contained in:
36
common/package-lock.json
generated
36
common/package-lock.json
generated
@@ -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=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
124
common/src/scrypted-eval.ts
Normal 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);
|
||||
}
|
||||
})();
|
||||
`;
|
||||
}
|
||||
Reference in New Issue
Block a user