1
0
silverbullet/packages/plugos/plug.ts

70 lines
1.9 KiB
TypeScript
Raw Normal View History

2022-03-23 14:41:12 +00:00
import { Manifest, RuntimeEnvironment } from "./types";
import { Sandbox } from "./sandbox";
import { System } from "./system";
export class Plug<HookT> {
system: System<HookT>;
sandbox: Sandbox;
public manifest?: Manifest<HookT>;
readonly runtimeEnv: RuntimeEnvironment;
2022-03-25 11:03:06 +00:00
grantedPermissions: string[] = [];
name: string;
version: number;
2022-03-23 14:41:12 +00:00
2022-03-25 11:03:06 +00:00
constructor(
system: System<HookT>,
name: string,
sandboxFactory: (plug: Plug<HookT>) => Sandbox
) {
2022-03-23 14:41:12 +00:00
this.system = system;
2022-03-25 11:03:06 +00:00
this.name = name;
this.sandbox = sandboxFactory(this);
2022-03-23 14:41:12 +00:00
this.runtimeEnv = system.runtimeEnv;
this.version = new Date().getTime();
2022-03-23 14:41:12 +00:00
}
async load(manifest: Manifest<HookT>) {
this.manifest = manifest;
2022-03-25 11:03:06 +00:00
// TODO: These need to be explicitly granted, not just taken
this.grantedPermissions = manifest.requiredPermissions || [];
2022-05-13 12:36:26 +00:00
for (let [dep, code] of Object.entries(manifest.dependencies || {})) {
await this.sandbox.loadDependency(dep, code);
}
2022-03-25 11:03:06 +00:00
}
syscall(name: string, args: any[]): Promise<any> {
return this.system.syscallWithContext({ plug: this }, name, args);
2022-03-23 14:41:12 +00:00
}
canInvoke(name: string) {
if (!this.manifest) {
return false;
}
const funDef = this.manifest.functions[name];
if (!funDef) {
throw new Error(`Function ${name} not found in manifest`);
}
return !funDef.env || funDef.env === this.runtimeEnv;
}
async invoke(name: string, args: Array<any>): Promise<any> {
if (!this.sandbox.isLoaded(name)) {
const funDef = this.manifest!.functions[name];
if (!funDef) {
throw new Error(`Function ${name} not found in manifest`);
}
if (!this.canInvoke(name)) {
throw new Error(
`Function ${name} is not available in ${this.runtimeEnv}`
);
}
await this.sandbox.load(name, funDef.code!);
}
return await this.sandbox.invoke(name, args);
}
async stop() {
this.sandbox.stop();
}
}