Next.js 16, React 19, Monaco editor, Anthropic SDK, multi-provider AI, Wandbox Python execution, iframe HTML preview, SQLite auth + session persistence. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
52 lines
1.4 KiB
TypeScript
52 lines
1.4 KiB
TypeScript
import type { Dispatch } from 'react';
|
|
import type { AppAction, SupportedLanguage } from '@/types';
|
|
|
|
const MAX_CODE_LENGTH = 10_000;
|
|
|
|
export function useCodeExecution(dispatch: Dispatch<AppAction>) {
|
|
async function execute(language: SupportedLanguage, code: string): Promise<void> {
|
|
if (code.trim().length === 0) return;
|
|
|
|
if (code.length > MAX_CODE_LENGTH) {
|
|
dispatch({ type: 'SET_ERROR', payload: 'Code exceeds the 10,000 character limit.' });
|
|
return;
|
|
}
|
|
|
|
// HTML is handled by HtmlPreview client-side
|
|
if (language === 'html') {
|
|
return;
|
|
}
|
|
|
|
dispatch({ type: 'EXECUTE_START' });
|
|
|
|
try {
|
|
const res = await fetch('/api/execute', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ language, code }),
|
|
});
|
|
|
|
if (!res.ok) {
|
|
const data = await res.json().catch(() => ({}));
|
|
throw new Error(data.error ?? `Server error ${res.status}`);
|
|
}
|
|
|
|
const result = await res.json();
|
|
dispatch({ type: 'EXECUTE_DONE', payload: result });
|
|
} catch (err) {
|
|
dispatch({
|
|
type: 'EXECUTE_DONE',
|
|
payload: {
|
|
stdout: '',
|
|
stderr: '',
|
|
exitCode: -1,
|
|
timedOut: false,
|
|
error: err instanceof Error ? err.message : 'Execution failed',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
return { execute };
|
|
}
|