2023-08-04 16:56:55 +00:00
|
|
|
import { Manifest } from "./types.ts";
|
2022-10-10 12:50:21 +00:00
|
|
|
import { Sandbox } from "./sandbox.ts";
|
|
|
|
import { System } from "./system.ts";
|
2022-10-13 13:16:18 +00:00
|
|
|
import { AssetBundle, AssetJson } from "./asset_bundle/bundle.ts";
|
2022-03-23 14:41:12 +00:00
|
|
|
|
|
|
|
export class Plug<HookT> {
|
2023-08-04 16:56:55 +00:00
|
|
|
readonly runtimeEnv?: string;
|
2023-05-23 18:53:53 +00:00
|
|
|
|
|
|
|
public grantedPermissions: string[] = [];
|
|
|
|
public sandbox: Sandbox<HookT>;
|
|
|
|
|
|
|
|
// Resolves once the worker has been loaded
|
|
|
|
ready: Promise<void>;
|
|
|
|
|
|
|
|
// Only available after ready resolves
|
2022-03-23 14:41:12 +00:00
|
|
|
public manifest?: Manifest<HookT>;
|
2022-10-13 13:16:18 +00:00
|
|
|
public assets?: AssetBundle;
|
2022-03-23 14:41:12 +00:00
|
|
|
|
2022-03-25 11:03:06 +00:00
|
|
|
constructor(
|
2023-05-23 18:53:53 +00:00
|
|
|
private system: System<HookT>,
|
|
|
|
public workerUrl: URL,
|
|
|
|
private sandboxFactory: (plug: Plug<HookT>) => Sandbox<HookT>,
|
2022-03-25 11:03:06 +00:00
|
|
|
) {
|
2023-01-08 11:24:12 +00:00
|
|
|
this.runtimeEnv = system.env;
|
2022-03-23 14:41:12 +00:00
|
|
|
|
2023-05-23 18:53:53 +00:00
|
|
|
// Kick off worker
|
|
|
|
this.sandbox = this.sandboxFactory(this);
|
|
|
|
this.ready = this.sandbox.ready.then(() => {
|
|
|
|
this.manifest = this.sandbox.manifest!;
|
|
|
|
this.assets = new AssetBundle(
|
|
|
|
this.manifest.assets ? this.manifest.assets as AssetJson : {},
|
|
|
|
);
|
|
|
|
// TODO: These need to be explicitly granted, not just taken
|
|
|
|
this.grantedPermissions = this.manifest.requiredPermissions || [];
|
2022-11-01 14:00:59 +00:00
|
|
|
});
|
2022-11-01 08:57:20 +00:00
|
|
|
}
|
|
|
|
|
2023-05-23 18:53:53 +00:00
|
|
|
get name(): string | undefined {
|
|
|
|
return this.manifest?.name;
|
2022-03-25 11:03:06 +00:00
|
|
|
}
|
|
|
|
|
2023-05-23 18:53:53 +00:00
|
|
|
// Invoke a syscall
|
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
|
|
|
}
|
|
|
|
|
2023-05-23 18:53:53 +00:00
|
|
|
// Checks if a function can be invoked (it may be restricted on its execution environment)
|
|
|
|
async canInvoke(name: string) {
|
|
|
|
await this.ready;
|
|
|
|
const funDef = this.manifest!.functions[name];
|
2022-03-23 14:41:12 +00:00
|
|
|
if (!funDef) {
|
|
|
|
throw new Error(`Function ${name} not found in manifest`);
|
|
|
|
}
|
2023-01-08 11:24:12 +00:00
|
|
|
return !funDef.env || !this.runtimeEnv || funDef.env === this.runtimeEnv;
|
2022-03-23 14:41:12 +00:00
|
|
|
}
|
|
|
|
|
2023-05-23 18:53:53 +00:00
|
|
|
// Invoke a function
|
2022-10-28 14:17:40 +00:00
|
|
|
async invoke(name: string, args: any[]): Promise<any> {
|
2023-05-23 18:53:53 +00:00
|
|
|
// Ensure the worker is fully up and running
|
|
|
|
await this.ready;
|
|
|
|
|
|
|
|
// Before we access the manifest
|
2022-10-28 14:17:40 +00:00
|
|
|
const funDef = this.manifest!.functions[name];
|
|
|
|
if (!funDef) {
|
|
|
|
throw new Error(`Function ${name} not found in manifest`);
|
|
|
|
}
|
2022-11-01 08:57:20 +00:00
|
|
|
const sandbox = this.sandbox!;
|
2022-10-28 14:17:40 +00:00
|
|
|
if (funDef.redirect) {
|
|
|
|
// Function redirect, look up
|
|
|
|
// deno-lint-ignore no-this-alias
|
|
|
|
let plug: Plug<HookT> | undefined = this;
|
|
|
|
if (funDef.redirect.indexOf(".") !== -1) {
|
|
|
|
const [plugName, functionName] = funDef.redirect.split(".");
|
|
|
|
plug = this.system.loadedPlugs.get(plugName);
|
|
|
|
if (!plug) {
|
|
|
|
throw Error(`Plug ${plugName} redirected to not found`);
|
|
|
|
}
|
|
|
|
name = functionName;
|
|
|
|
} else {
|
|
|
|
name = funDef.redirect;
|
2022-03-23 14:41:12 +00:00
|
|
|
}
|
2022-10-28 14:17:40 +00:00
|
|
|
return plug.invoke(name, args);
|
|
|
|
}
|
2023-05-23 18:53:53 +00:00
|
|
|
if (!await this.canInvoke(name)) {
|
|
|
|
throw new Error(
|
|
|
|
`Function ${name} is not available in ${this.runtimeEnv}`,
|
|
|
|
);
|
2022-03-23 14:41:12 +00:00
|
|
|
}
|
2022-11-01 08:57:20 +00:00
|
|
|
return await sandbox.invoke(name, args);
|
2022-03-23 14:41:12 +00:00
|
|
|
}
|
|
|
|
|
2022-10-15 17:02:56 +00:00
|
|
|
stop() {
|
2022-11-01 08:57:20 +00:00
|
|
|
if (this.sandbox) {
|
|
|
|
this.sandbox.stop();
|
|
|
|
}
|
2022-03-23 14:41:12 +00:00
|
|
|
}
|
|
|
|
}
|