@nahisaho/katashiro-sandbox 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,64 @@
1
+ /**
2
+ * KATASHIRO Sandbox - Local Executor Implementation
3
+ *
4
+ * @fileoverview REQ-007: ローカル環境でのコード実行(開発/テスト用)
5
+ * @module @nahisaho/katashiro-sandbox
6
+ * @since 0.4.0
7
+ */
8
+ import { EventEmitter } from 'events';
9
+ import { type Result } from '@nahisaho/katashiro-core';
10
+ import type { SandboxConfig, ExecutionRequest, ExecutionResult, SupportedLanguage, SandboxEventType, SandboxEventListener } from './types';
11
+ import { SandboxError } from './docker-executor';
12
+ /**
13
+ * Local Executor(開発/テスト用)
14
+ *
15
+ * 注意: このExecutorはホストシステムで直接コードを実行するため、
16
+ * 本番環境では使用しないでください。開発とテスト目的専用です。
17
+ */
18
+ export declare class LocalExecutor extends EventEmitter {
19
+ private readonly config;
20
+ private readonly activeProcesses;
21
+ private readonly tempDir;
22
+ constructor(config?: Partial<SandboxConfig>);
23
+ /**
24
+ * 型安全なイベントリスナー登録
25
+ */
26
+ on(event: SandboxEventType, listener: SandboxEventListener): this;
27
+ /**
28
+ * イベント発火
29
+ */
30
+ private emitEvent;
31
+ /**
32
+ * コードを実行
33
+ */
34
+ execute(code: string, language: SupportedLanguage, options?: Partial<Pick<ExecutionRequest, 'stdin' | 'env' | 'timeout'>>): Promise<Result<ExecutionResult, SandboxError>>;
35
+ /**
36
+ * 言語に対応する拡張子を取得
37
+ */
38
+ private getExtension;
39
+ /**
40
+ * コマンドを構築
41
+ */
42
+ private buildCommand;
43
+ /**
44
+ * プロセスを実行
45
+ */
46
+ private runProcess;
47
+ /**
48
+ * エラーをパース
49
+ */
50
+ private parseError;
51
+ /**
52
+ * 指定した実行をキャンセル
53
+ */
54
+ cancel(requestId: string): boolean;
55
+ /**
56
+ * 全アクティブプロセスをクリーンアップ
57
+ */
58
+ cleanup(): void;
59
+ /**
60
+ * アクティブなプロセス数を取得
61
+ */
62
+ getActiveProcessCount(): number;
63
+ }
64
+ //# sourceMappingURL=local-executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-executor.d.ts","sourceRoot":"","sources":["../src/local-executor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAW,KAAK,MAAM,EAAc,MAAM,0BAA0B,CAAC;AAC5E,OAAO,KAAK,EACV,aAAa,EACb,gBAAgB,EAChB,eAAe,EAEf,iBAAiB,EAEjB,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAMjD;;;;;GAKG;AACH,qBAAa,aAAc,SAAQ,YAAY;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAmC;IACnE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM;IAM/C;;OAEG;IACH,EAAE,CAAC,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,oBAAoB,GAAG,IAAI;IAIjE;;OAEG;IACH,OAAO,CAAC,SAAS;IASjB;;OAEG;IACG,OAAO,CACX,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,GAAE,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC,CAAM,GACzE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;IA8EjD;;OAEG;IACH,OAAO,CAAC,YAAY;IAUpB;;OAEG;IACH,OAAO,CAAC,YAAY;IAqBpB;;OAEG;IACH,OAAO,CAAC,UAAU;IA0DlB;;OAEG;IACH,OAAO,CAAC,UAAU;IAsBlB;;OAEG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IASlC;;OAEG;IACH,OAAO,IAAI,IAAI;IAOf;;OAEG;IACH,qBAAqB,IAAI,MAAM;CAGhC"}
@@ -0,0 +1,242 @@
1
+ "use strict";
2
+ /**
3
+ * KATASHIRO Sandbox - Local Executor Implementation
4
+ *
5
+ * @fileoverview REQ-007: ローカル環境でのコード実行(開発/テスト用)
6
+ * @module @nahisaho/katashiro-sandbox
7
+ * @since 0.4.0
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.LocalExecutor = void 0;
11
+ const child_process_1 = require("child_process");
12
+ const promises_1 = require("fs/promises");
13
+ const path_1 = require("path");
14
+ const os_1 = require("os");
15
+ const events_1 = require("events");
16
+ const katashiro_core_1 = require("@nahisaho/katashiro-core");
17
+ const types_1 = require("./types");
18
+ const docker_executor_1 = require("./docker-executor");
19
+ // =============================================================================
20
+ // Local Executor
21
+ // =============================================================================
22
+ /**
23
+ * Local Executor(開発/テスト用)
24
+ *
25
+ * 注意: このExecutorはホストシステムで直接コードを実行するため、
26
+ * 本番環境では使用しないでください。開発とテスト目的専用です。
27
+ */
28
+ class LocalExecutor extends events_1.EventEmitter {
29
+ config;
30
+ activeProcesses = new Map();
31
+ tempDir;
32
+ constructor(config = {}) {
33
+ super();
34
+ this.config = { ...types_1.DEFAULT_SANDBOX_CONFIG, ...config, runtime: 'local' };
35
+ this.tempDir = (0, path_1.join)((0, os_1.tmpdir)(), 'katashiro-sandbox');
36
+ }
37
+ /**
38
+ * 型安全なイベントリスナー登録
39
+ */
40
+ on(event, listener) {
41
+ return super.on(event, listener);
42
+ }
43
+ /**
44
+ * イベント発火
45
+ */
46
+ emitEvent(type, data) {
47
+ const event = {
48
+ type,
49
+ timestamp: new Date().toISOString(),
50
+ ...data,
51
+ };
52
+ this.emit(type, event);
53
+ }
54
+ /**
55
+ * コードを実行
56
+ */
57
+ async execute(code, language, options = {}) {
58
+ const requestId = (0, katashiro_core_1.generateId)();
59
+ const timeout = options.timeout ?? this.config.timeout;
60
+ const startTime = Date.now();
61
+ this.emitEvent('execution:start', { requestId });
62
+ let tempFile;
63
+ try {
64
+ // 一時ディレクトリ作成
65
+ await (0, promises_1.mkdir)(this.tempDir, { recursive: true });
66
+ // コードを一時ファイルに書き込み
67
+ tempFile = (0, path_1.join)(this.tempDir, `${requestId}${this.getExtension(language)}`);
68
+ await (0, promises_1.writeFile)(tempFile, code, 'utf-8');
69
+ // コマンド構築
70
+ const { command, args } = this.buildCommand(language, tempFile);
71
+ // プロセス起動
72
+ const result = await this.runProcess(requestId, command, args, timeout, options.stdin, options.env);
73
+ const duration = Date.now() - startTime;
74
+ const executionResult = {
75
+ requestId,
76
+ status: result.exitCode === 0 ? 'completed' : 'failed',
77
+ exitCode: result.exitCode,
78
+ stdout: result.stdout,
79
+ stderr: result.stderr,
80
+ duration,
81
+ files: [],
82
+ completedAt: new Date().toISOString(),
83
+ };
84
+ this.emitEvent('execution:complete', { requestId, data: executionResult });
85
+ return (0, katashiro_core_1.ok)(executionResult);
86
+ }
87
+ catch (error) {
88
+ const duration = Date.now() - startTime;
89
+ const execError = this.parseError(error);
90
+ const executionResult = {
91
+ requestId,
92
+ status: execError.code === 'TIMEOUT' ? 'timeout' : 'failed',
93
+ exitCode: -1,
94
+ stdout: '',
95
+ stderr: execError.message,
96
+ duration,
97
+ files: [],
98
+ error: execError,
99
+ completedAt: new Date().toISOString(),
100
+ };
101
+ if (execError.code === 'TIMEOUT') {
102
+ this.emitEvent('execution:timeout', { requestId, data: executionResult });
103
+ }
104
+ else {
105
+ this.emitEvent('execution:error', { requestId, data: executionResult });
106
+ }
107
+ return (0, katashiro_core_1.err)(new docker_executor_1.SandboxError(execError.message, execError.code, { requestId }));
108
+ }
109
+ finally {
110
+ // 一時ファイル削除
111
+ if (tempFile) {
112
+ await (0, promises_1.unlink)(tempFile).catch(() => { });
113
+ }
114
+ this.activeProcesses.delete(requestId);
115
+ }
116
+ }
117
+ /**
118
+ * 言語に対応する拡張子を取得
119
+ */
120
+ getExtension(language) {
121
+ const extensions = {
122
+ bash: '.sh',
123
+ python: '.py',
124
+ javascript: '.js',
125
+ typescript: '.ts',
126
+ };
127
+ return extensions[language];
128
+ }
129
+ /**
130
+ * コマンドを構築
131
+ */
132
+ buildCommand(language, filePath) {
133
+ switch (language) {
134
+ case 'bash':
135
+ return { command: 'bash', args: [filePath] };
136
+ case 'python':
137
+ return { command: 'python3', args: [filePath] };
138
+ case 'javascript':
139
+ return { command: 'node', args: [filePath] };
140
+ case 'typescript':
141
+ return { command: 'npx', args: ['tsx', filePath] };
142
+ default:
143
+ throw new docker_executor_1.SandboxError(`Unsupported language: ${language}`, 'UNSUPPORTED_LANGUAGE');
144
+ }
145
+ }
146
+ /**
147
+ * プロセスを実行
148
+ */
149
+ runProcess(requestId, command, args, timeout, stdin, env) {
150
+ return new Promise((resolve, reject) => {
151
+ const proc = (0, child_process_1.spawn)(command, args, {
152
+ cwd: this.tempDir,
153
+ env: { ...process.env, ...env },
154
+ stdio: ['pipe', 'pipe', 'pipe'],
155
+ });
156
+ this.activeProcesses.set(requestId, proc);
157
+ let stdout = '';
158
+ let stderr = '';
159
+ proc.stdout?.on('data', (data) => {
160
+ stdout += data.toString();
161
+ });
162
+ proc.stderr?.on('data', (data) => {
163
+ stderr += data.toString();
164
+ });
165
+ // stdin送信
166
+ if (stdin && proc.stdin) {
167
+ proc.stdin.write(stdin);
168
+ proc.stdin.end();
169
+ }
170
+ else if (proc.stdin) {
171
+ proc.stdin.end();
172
+ }
173
+ // タイムアウト
174
+ const timeoutId = setTimeout(() => {
175
+ proc.kill('SIGKILL');
176
+ reject(new docker_executor_1.SandboxError('Execution timeout', 'TIMEOUT', { timeout }));
177
+ }, timeout * 1000);
178
+ proc.on('close', (code) => {
179
+ clearTimeout(timeoutId);
180
+ resolve({
181
+ exitCode: code ?? -1,
182
+ stdout,
183
+ stderr,
184
+ });
185
+ });
186
+ proc.on('error', (err) => {
187
+ clearTimeout(timeoutId);
188
+ reject(err);
189
+ });
190
+ });
191
+ }
192
+ /**
193
+ * エラーをパース
194
+ */
195
+ parseError(error) {
196
+ if (error instanceof docker_executor_1.SandboxError) {
197
+ return {
198
+ code: error.code,
199
+ message: error.message,
200
+ };
201
+ }
202
+ if (error instanceof Error) {
203
+ return {
204
+ code: 'EXECUTION_ERROR',
205
+ message: error.message,
206
+ stack: error.stack,
207
+ };
208
+ }
209
+ return {
210
+ code: 'UNKNOWN_ERROR',
211
+ message: String(error),
212
+ };
213
+ }
214
+ /**
215
+ * 指定した実行をキャンセル
216
+ */
217
+ cancel(requestId) {
218
+ const proc = this.activeProcesses.get(requestId);
219
+ if (!proc)
220
+ return false;
221
+ proc.kill('SIGKILL');
222
+ this.activeProcesses.delete(requestId);
223
+ return true;
224
+ }
225
+ /**
226
+ * 全アクティブプロセスをクリーンアップ
227
+ */
228
+ cleanup() {
229
+ for (const [requestId, proc] of this.activeProcesses) {
230
+ proc.kill('SIGKILL');
231
+ this.activeProcesses.delete(requestId);
232
+ }
233
+ }
234
+ /**
235
+ * アクティブなプロセス数を取得
236
+ */
237
+ getActiveProcessCount() {
238
+ return this.activeProcesses.size;
239
+ }
240
+ }
241
+ exports.LocalExecutor = LocalExecutor;
242
+ //# sourceMappingURL=local-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-executor.js","sourceRoot":"","sources":["../src/local-executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * KATASHIRO Sandbox - Unified Sandbox Interface
3
+ *
4
+ * @fileoverview REQ-007: 統一サンドボックスインターフェース
5
+ * @module @nahisaho/katashiro-sandbox
6
+ * @since 0.4.0
7
+ */
8
+ import type { Result } from '@nahisaho/katashiro-core';
9
+ import type { SandboxConfig, SandboxRuntime, ExecutionResult, SupportedLanguage, ExecutionRequest, SandboxEventType, SandboxEventListener } from './types';
10
+ import { SandboxError } from './docker-executor';
11
+ /**
12
+ * サンドボックスインターフェース
13
+ */
14
+ export interface ISandbox {
15
+ /**
16
+ * コードを実行
17
+ */
18
+ execute(code: string, language: SupportedLanguage, options?: Partial<Pick<ExecutionRequest, 'stdin' | 'env' | 'timeout'>>): Promise<Result<ExecutionResult, SandboxError>>;
19
+ /**
20
+ * 指定した実行をキャンセル
21
+ */
22
+ cancel(requestId: string): boolean | Promise<boolean>;
23
+ /**
24
+ * 全アクティブ実行をクリーンアップ
25
+ */
26
+ cleanup(): void | Promise<void>;
27
+ /**
28
+ * イベントリスナー登録
29
+ */
30
+ on(event: SandboxEventType, listener: SandboxEventListener): this;
31
+ }
32
+ /**
33
+ * サンドボックスファクトリ
34
+ *
35
+ * 環境に応じて適切なExecutorを生成します。
36
+ */
37
+ export declare class SandboxFactory {
38
+ /**
39
+ * サンドボックスを作成
40
+ *
41
+ * @param config サンドボックス設定
42
+ * @param runtime ランタイム(省略時はconfig.runtimeを使用)
43
+ */
44
+ static create(config?: Partial<SandboxConfig>, runtime?: SandboxRuntime): ISandbox;
45
+ /**
46
+ * Dockerが利用可能か確認
47
+ */
48
+ static isDockerAvailable(): Promise<boolean>;
49
+ /**
50
+ * 環境に応じて最適なランタイムを自動選択
51
+ */
52
+ static autoDetect(): Promise<SandboxRuntime>;
53
+ /**
54
+ * 自動検出してサンドボックスを作成
55
+ */
56
+ static createAuto(config?: Partial<SandboxConfig>): Promise<ISandbox>;
57
+ }
58
+ /**
59
+ * コードを実行(簡易関数)
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * const result = await executeCode('print("Hello")', 'python');
64
+ * if (result.isOk()) {
65
+ * console.log(result.value.stdout); // "Hello\n"
66
+ * }
67
+ * ```
68
+ */
69
+ export declare function executeCode(code: string, language: SupportedLanguage, options?: {
70
+ runtime?: SandboxRuntime;
71
+ timeout?: number;
72
+ stdin?: string;
73
+ env?: Record<string, string>;
74
+ }): Promise<Result<ExecutionResult, SandboxError>>;
75
+ /**
76
+ * Bashスクリプトを実行
77
+ */
78
+ export declare function executeBash(script: string, options?: {
79
+ timeout?: number;
80
+ env?: Record<string, string>;
81
+ }): Promise<Result<ExecutionResult, SandboxError>>;
82
+ /**
83
+ * Pythonコードを実行
84
+ */
85
+ export declare function executePython(code: string, options?: {
86
+ timeout?: number;
87
+ stdin?: string;
88
+ env?: Record<string, string>;
89
+ }): Promise<Result<ExecutionResult, SandboxError>>;
90
+ /**
91
+ * JavaScriptコードを実行
92
+ */
93
+ export declare function executeJavaScript(code: string, options?: {
94
+ timeout?: number;
95
+ env?: Record<string, string>;
96
+ }): Promise<Result<ExecutionResult, SandboxError>>;
97
+ /**
98
+ * TypeScriptコードを実行
99
+ */
100
+ export declare function executeTypeScript(code: string, options?: {
101
+ timeout?: number;
102
+ env?: Record<string, string>;
103
+ }): Promise<Result<ExecutionResult, SandboxError>>;
104
+ //# sourceMappingURL=sandbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAkB,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAOjE;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB;;OAEG;IACH,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC,CAAC,GACrE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC,CAAC;IAElD;;OAEG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEtD;;OAEG;IACH,OAAO,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhC;;OAEG;IACH,EAAE,CAAC,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;CACnE;AAED;;;;GAIG;AACH,qBAAa,cAAc;IACzB;;;;;OAKG;IACH,MAAM,CAAC,MAAM,CACX,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM,EACnC,OAAO,CAAC,EAAE,cAAc,GACvB,QAAQ;IAqBX;;OAEG;WACU,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC;IAWlD;;OAEG;WACU,UAAU,IAAI,OAAO,CAAC,cAAc,CAAC;IAOlD;;OAEG;WACU,UAAU,CACrB,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM,GAClC,OAAO,CAAC,QAAQ,CAAC;CAIrB;AAMD;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,CAAC,EAAE;IACR,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B,GACA,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC,CAgBhD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAC3D,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC,CAEhD;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAC3E,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC,CAEhD;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAC3D,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC,CAEhD;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAC3D,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC,CAEhD"}
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ /**
3
+ * KATASHIRO Sandbox - Unified Sandbox Interface
4
+ *
5
+ * @fileoverview REQ-007: 統一サンドボックスインターフェース
6
+ * @module @nahisaho/katashiro-sandbox
7
+ * @since 0.4.0
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.SandboxFactory = void 0;
11
+ exports.executeCode = executeCode;
12
+ exports.executeBash = executeBash;
13
+ exports.executePython = executePython;
14
+ exports.executeJavaScript = executeJavaScript;
15
+ exports.executeTypeScript = executeTypeScript;
16
+ const types_1 = require("./types");
17
+ const docker_executor_1 = require("./docker-executor");
18
+ const local_executor_1 = require("./local-executor");
19
+ /**
20
+ * サンドボックスファクトリ
21
+ *
22
+ * 環境に応じて適切なExecutorを生成します。
23
+ */
24
+ class SandboxFactory {
25
+ /**
26
+ * サンドボックスを作成
27
+ *
28
+ * @param config サンドボックス設定
29
+ * @param runtime ランタイム(省略時はconfig.runtimeを使用)
30
+ */
31
+ static create(config = {}, runtime) {
32
+ const resolvedRuntime = runtime ?? config.runtime ?? types_1.DEFAULT_SANDBOX_CONFIG.runtime;
33
+ switch (resolvedRuntime) {
34
+ case 'docker':
35
+ return new docker_executor_1.DockerExecutor(config);
36
+ case 'local':
37
+ return new local_executor_1.LocalExecutor(config);
38
+ case 'wasm':
39
+ throw new docker_executor_1.SandboxError('WASM runtime is not yet implemented', 'NOT_IMPLEMENTED');
40
+ default:
41
+ throw new docker_executor_1.SandboxError(`Unknown runtime: ${resolvedRuntime}`, 'UNKNOWN_RUNTIME');
42
+ }
43
+ }
44
+ /**
45
+ * Dockerが利用可能か確認
46
+ */
47
+ static async isDockerAvailable() {
48
+ try {
49
+ const Docker = (await import('dockerode')).default;
50
+ const docker = new Docker();
51
+ await docker.ping();
52
+ return true;
53
+ }
54
+ catch {
55
+ return false;
56
+ }
57
+ }
58
+ /**
59
+ * 環境に応じて最適なランタイムを自動選択
60
+ */
61
+ static async autoDetect() {
62
+ if (await this.isDockerAvailable()) {
63
+ return 'docker';
64
+ }
65
+ return 'local';
66
+ }
67
+ /**
68
+ * 自動検出してサンドボックスを作成
69
+ */
70
+ static async createAuto(config = {}) {
71
+ const runtime = await this.autoDetect();
72
+ return this.create(config, runtime);
73
+ }
74
+ }
75
+ exports.SandboxFactory = SandboxFactory;
76
+ // =============================================================================
77
+ // Convenience Functions
78
+ // =============================================================================
79
+ /**
80
+ * コードを実行(簡易関数)
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * const result = await executeCode('print("Hello")', 'python');
85
+ * if (result.isOk()) {
86
+ * console.log(result.value.stdout); // "Hello\n"
87
+ * }
88
+ * ```
89
+ */
90
+ async function executeCode(code, language, options) {
91
+ const timeout = options?.timeout ?? types_1.DEFAULT_SANDBOX_CONFIG.timeout;
92
+ const sandbox = SandboxFactory.create({ timeout }, options?.runtime ?? 'local');
93
+ try {
94
+ return await sandbox.execute(code, language, {
95
+ stdin: options?.stdin,
96
+ env: options?.env,
97
+ timeout,
98
+ });
99
+ }
100
+ finally {
101
+ sandbox.cleanup();
102
+ }
103
+ }
104
+ /**
105
+ * Bashスクリプトを実行
106
+ */
107
+ async function executeBash(script, options) {
108
+ return executeCode(script, 'bash', options);
109
+ }
110
+ /**
111
+ * Pythonコードを実行
112
+ */
113
+ async function executePython(code, options) {
114
+ return executeCode(code, 'python', options);
115
+ }
116
+ /**
117
+ * JavaScriptコードを実行
118
+ */
119
+ async function executeJavaScript(code, options) {
120
+ return executeCode(code, 'javascript', options);
121
+ }
122
+ /**
123
+ * TypeScriptコードを実行
124
+ */
125
+ async function executeTypeScript(code, options) {
126
+ return executeCode(code, 'typescript', options);
127
+ }
128
+ //# sourceMappingURL=sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"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"}