RYP / src /components /Compiler /useCompiler.js
Soumya79's picture
Upload 1361 files
f91a684 verified
import { useCallback, useState, useRef } from 'react';
export const LANGUAGE_OPTIONS = [
{ value: 'python', label: 'Python', monacoLanguage: 'python', extension: 'py', pistonLang: 'python', pistonVersion: '3.10.0' },
{ value: 'python3', label: 'Python 3', monacoLanguage: 'python', extension: 'py', pistonLang: 'python3', pistonVersion: '3.10.0' },
{ value: 'javascript', label: 'JavaScript', monacoLanguage: 'javascript', extension: 'js', pistonLang: 'javascript', pistonVersion: '18.15.0' },
{ value: 'java', label: 'Java', monacoLanguage: 'java', extension: 'java', pistonLang: 'java', pistonVersion: '15.0.2' },
{ value: 'c', label: 'C', monacoLanguage: 'c', extension: 'c', pistonLang: 'c', pistonVersion: '10.2.0' },
{ value: 'cpp', label: 'C++', monacoLanguage: 'cpp', extension: 'cpp', pistonLang: 'c++', pistonVersion: '10.2.0' },
];
export const DEFAULT_CODE_BY_LANGUAGE = {
python: `# Type your input in the terminal box below after clicking RUN
name = input("Enter your name: ")
print(f"Hello, {name}!")
`,
python3: `# Type your input in the terminal box below after clicking RUN
name = input("Enter your name: ")
print(f"Hello, {name}!")
`,
javascript: `const fs = require("fs");
const input = fs.readFileSync(0, "utf8").trim();
console.log(\`Hello, \${input}!\`);
`,
java: `import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String name = scanner.next();
System.out.println("Hello, " + name + "!");
}
}
`,
c: `#include <stdio.h>
int main() {
char name[100];
scanf("%99s", name);
printf("Hello, %s!\\n", name);
return 0;
}
`,
cpp: `#include <iostream>
using namespace std;
int main() {
string name;
cin >> name;
cout << "Hello, " << name << "!" << endl;
return 0;
}
`,
};
function compilerApiUrl() {
const base = (import.meta.env.VITE_COMPILER_API_BASE ?? '').trim().replace(/\/$/, '');
return `${base}/api/compile`;
}
async function parseResponse(response) {
const text = await response.text();
if (!text) return {};
try {
return JSON.parse(text);
} catch {
return { error: text };
}
}
export default function useCompiler(initialLanguage = 'python') {
const [language, setLanguage] = useState(initialLanguage);
const [code, setCode] = useState(DEFAULT_CODE_BY_LANGUAGE[initialLanguage]);
const [input, setInput] = useState('');
const [output, setOutput] = useState('');
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const [executionTime, setExecutionTime] = useState(null);
const [status, setStatus] = useState('idle'); // idle | running | success | error | compile_error
const [compileOutput, setCompileOutput] = useState('');
const [analysis, setAnalysis] = useState(null);
const [executionId, setExecutionId] = useState(null);
const eventSourceRef = useRef(null);
const handleRunInteractive = useCallback(
async (overrides = {}) => {
const runCode = overrides.code ?? code;
const runLanguage = overrides.language ?? language;
const onStdout = overrides.onStdout ?? (() => {});
const onStderr = overrides.onStderr ?? (() => {});
const onDone = overrides.onDone ?? (() => {});
if (!runCode.trim()) {
onStderr('Code is required.');
onDone('error', 0);
return;
}
setLoading(true);
setOutput('');
setError('');
setExecutionTime(null);
setStatus('running');
setCompileOutput('');
setAnalysis(null);
setExecutionId(null);
if (eventSourceRef.current) {
eventSourceRef.current.close();
eventSourceRef.current = null;
}
try {
const base = (import.meta.env.VITE_COMPILER_API_BASE ?? '').trim().replace(/\/$/, '');
const startRes = await fetch(`${base}/api/compile/start`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code: runCode, language: runLanguage }),
});
const startData = await parseResponse(startRes);
if (!startRes.ok || !startData.executionId) {
throw new Error(startData.error || 'Failed to start execution');
}
const id = startData.executionId;
setExecutionId(id);
const es = new EventSource(`${base}/api/compile/stream/${id}`);
eventSourceRef.current = es;
es.addEventListener('stdout', (e) => {
try {
const text = JSON.parse(e.data);
setOutput(prev => prev + text);
onStdout(text);
} catch(err) {}
});
es.addEventListener('stderr', (e) => {
try {
const text = JSON.parse(e.data);
setError(prev => prev + text);
onStderr(text);
} catch(err) {}
});
es.addEventListener('done', (e) => {
try {
const data = JSON.parse(e.data);
setStatus(data.status);
setExecutionTime(data.executionTime);
onDone(data.status, data.executionTime);
} catch(err) {}
setLoading(false);
es.close();
eventSourceRef.current = null;
});
es.onerror = () => {
if (es.readyState === EventSource.CLOSED) return;
const msg = '\n[Connection lost — is the compiler server running?]';
setError(prev => prev + msg);
onStderr(msg);
onDone('error', 0);
setStatus('error');
setLoading(false);
es.close();
eventSourceRef.current = null;
};
} catch (err) {
const msg = err.message;
setError(msg);
onStderr(msg);
onDone('error', 0);
setStatus('error');
setLoading(false);
}
},
[code, language],
);
const sendInput = useCallback(async (text) => {
if (!executionId || status !== 'running') return;
try {
const base = (import.meta.env.VITE_COMPILER_API_BASE ?? '').trim().replace(/\/$/, '');
await fetch(`${base}/api/compile/input/${executionId}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ input: text + '\n' }),
});
} catch (err) {
console.error('Failed to send input', err);
}
}, [executionId, status]);
const resetResult = useCallback(() => {
if (eventSourceRef.current) {
eventSourceRef.current.close();
eventSourceRef.current = null;
}
setOutput('');
setError('');
setExecutionTime(null);
setStatus('idle');
setCompileOutput('');
setAnalysis(null);
setExecutionId(null);
}, []);
return {
code,
setCode,
language,
setLanguage,
input,
setInput,
output,
setOutput,
error,
setError,
loading,
executionTime,
status,
compileOutput,
analysis,
handleRunInteractive,
sendInput,
resetResult,
};
}