import { DenoDownloader } from './classes.denodownloader.js'; import * as plugins from './plugins.js'; import * as paths from './paths.js'; import { ScriptServer } from './classes.scriptserver.js'; import { DenoExecution, type TDenoPermission } from './classes.denoexecution.js'; export interface ISmartDenoOptions { /** * Force downloading a local copy of Deno even if it's available in PATH */ forceLocalDeno?: boolean; /** * Port for the internal script server (default: 3210) */ port?: number; } export interface IExecuteScriptOptions { /** * Deno permissions to grant to the script */ permissions?: TDenoPermission[]; } export class SmartDeno { private denoDownloader = new DenoDownloader(); private scriptServer: ScriptServer; private denoBinaryPath: string | null = null; private isStarted = false; constructor() { this.scriptServer = new ScriptServer(); } /** * Starts the SmartDeno instance * @param optionsArg Configuration options */ public async start(optionsArg: ISmartDenoOptions = {}): Promise { if (this.isStarted) { return; } // Create script server with configured port this.scriptServer = new ScriptServer({ port: optionsArg.port }); const denoAlreadyInPath = await plugins.smartshell.which('deno', { nothrow: true }); if (!denoAlreadyInPath || optionsArg.forceLocalDeno) { this.denoBinaryPath = await this.denoDownloader.download( plugins.path.join(paths.nogitDir, 'deno.zip') ); } else { this.denoBinaryPath = 'deno'; } await this.scriptServer.start(); this.isStarted = true; } /** * Stops the SmartDeno instance and cleans up resources */ public async stop(): Promise { if (!this.isStarted) { return; } await this.scriptServer.stop(); this.isStarted = false; } /** * Check if the SmartDeno instance is running */ public isRunning(): boolean { return this.isStarted; } /** * Execute a Deno script * @param scriptArg The script content to execute * @param options Execution options including permissions * @returns Execution result with exitCode, stdout, and stderr */ public async executeScript( scriptArg: string, options: IExecuteScriptOptions = {} ): Promise<{ exitCode: number; stdout: string; stderr: string }> { if (!this.isStarted) { throw new Error('SmartDeno is not started. Call start() first.'); } const denoExecution = new DenoExecution(this.scriptServer, scriptArg, { permissions: options.permissions, denoBinaryPath: this.denoBinaryPath || undefined, }); return denoExecution.execute(); } }