import type { ScriptServer } from './classes.scriptserver.js'; import * as plugins from './plugins.js'; export type TDenoPermission = | 'all' | 'env' | 'ffi' | 'hrtime' | 'net' | 'read' | 'run' | 'sys' | 'write'; export interface IDenoExecutionOptions { permissions?: TDenoPermission[]; denoBinaryPath?: string; } /** * This class contains logic to execute deno commands in an ephemeral way */ export class DenoExecution { public id: string; public scriptserverRef: ScriptServer; public script: string; public options: IDenoExecutionOptions; constructor(scriptserverRef: ScriptServer, scriptArg: string, options: IDenoExecutionOptions = {}) { this.scriptserverRef = scriptserverRef; this.script = scriptArg; this.options = options; this.id = plugins.smartunique.shortId(); } private buildPermissionFlags(): string { const permissions = this.options.permissions || []; if (permissions.length === 0) { return ''; } if (permissions.includes('all')) { return '-A'; } return permissions.map(p => `--allow-${p}`).join(' '); } public async execute(): Promise<{ exitCode: number; stdout: string; stderr: string }> { this.scriptserverRef.executionMap.add(this); try { const denoBinary = this.options.denoBinaryPath || 'deno'; const permissionFlags = this.buildPermissionFlags(); const port = this.scriptserverRef.getPort(); const scriptUrl = `http://localhost:${port}/getscript/${this.id}`; const command = `${denoBinary} run ${permissionFlags} ${scriptUrl}`.replace(/\s+/g, ' ').trim(); const result = await this.scriptserverRef.smartshellInstance.exec(command); return { exitCode: result.exitCode, stdout: result.stdout, stderr: result.stderr, }; } finally { // Clean up: remove from execution map after execution completes this.scriptserverRef.executionMap.remove(this); } } }