strimertul/frontend/src/lib/extensions/workers/extensionHost.ts

104 lines
2.6 KiB
TypeScript

import Kilovolt from '@strimertul/kilovolt-client';
import ts from 'typescript';
import { type ExtensionHostCommand, type ExtensionHostMessage, ExtensionStatus } from '../types';
import { type SourceMapMappings, parseSourceMap } from '../sourceMap';
const sendMessage = (message: ExtensionHostMessage, transfer?: Transferable[]) =>
postMessage(message, transfer);
async function ExtensionFunction(_kv: Kilovolt) {}
let extFn: typeof ExtensionFunction = null;
let kv: Kilovolt;
let name: string;
let extensionStatus = ExtensionStatus.GettingReady;
function setStatus(status: ExtensionStatus) {
extensionStatus = status;
sendMessage({
kind: 'status-change',
status,
});
}
function log(level: string, _sourceMap: SourceMapMappings) {
// eslint-disable-next-line func-names
return (...args: { toString(): string }[]) => {
const message = args.join(' ');
void kv.putJSON('strimertul/@log', {
level,
message,
data: {
extension: name,
},
});
};
}
function start() {
if (!extFn || !kv || extensionStatus !== ExtensionStatus.Ready) {
throw new Error('extension not ready');
}
void extFn(kv)
.then(() => {
setStatus(ExtensionStatus.Finished);
})
.catch((error: Error) => {
sendMessage({
kind: 'error',
error,
});
});
setStatus(ExtensionStatus.Running);
}
addEventListener('message', async (ev: MessageEvent<ExtensionHostCommand>) => {
const cmd = ev.data;
switch (cmd.kind) {
case 'arguments': {
name = cmd.name;
// Create Kilovolt instance
kv = new Kilovolt(cmd.dependencies.kilovolt.address, {
password: cmd.dependencies.kilovolt.password,
});
await kv.connect();
try {
// Transpile TS into JS
const out = ts.transpileModule(cmd.source, {
compilerOptions: {
module: ts.ModuleKind.ES2022,
sourceMap: true,
},
});
const sourceMap = parseSourceMap(out.sourceMapText);
// Replace console.* methods with something that logs to UI
console.log = log('info', sourceMap);
console.info = log('info', sourceMap);
console.warn = log('warn', sourceMap);
console.error = log('error', sourceMap);
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
extFn = ExtensionFunction.constructor('kv', out.outputText);
setStatus(ExtensionStatus.Ready);
} catch (error: unknown) {
sendMessage({
kind: 'error',
error,
});
}
start();
break;
}
case 'start':
start();
break;
}
});