Skip to content

Commit 6c5e0fb

Browse files
Shell (#23)
1 parent 3c8dcf2 commit 6c5e0fb

3 files changed

Lines changed: 153 additions & 6 deletions

File tree

bin/cli.js

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/usr/bin/env node
2+
3+
import fs from 'fs';
4+
import path from 'path';
5+
import axios from 'axios';
6+
import { program } from 'commander';
7+
import dotenv from 'dotenv';
8+
import { languageOptions } from '../src/utils/constant.js';
9+
10+
dotenv.config();
11+
12+
program
13+
.name('tech-run')
14+
.description('Execute code files via Tech Compiler API')
15+
.version('1.0.0')
16+
.argument('<file>', 'File to execute')
17+
.option('-l, --language <lang>', 'Programming language (e.g., python, javascript, cpp)')
18+
.action(async (file, options) => {
19+
try {
20+
const filePath = path.resolve(file);
21+
if (!fs.existsSync(filePath)) {
22+
console.error(`Error: File not found at ${filePath}`);
23+
process.exit(1);
24+
}
25+
26+
const sourceCode = fs.readFileSync(filePath, 'utf-8');
27+
28+
const ext = path.extname(file).replace('.', '');
29+
const langKey = options.language || mapExtensionToLanguage(ext);
30+
31+
const selectedLanguage = languageOptions[langKey];
32+
if (!selectedLanguage) {
33+
console.error(`Error: Unsupported language "${langKey}". Use -l to specify.`);
34+
process.exit(1);
35+
}
36+
37+
console.log(`Running ${file} (${selectedLanguage.name})...`);
38+
await runCode(selectedLanguage.id, sourceCode);
39+
40+
} catch (err) {
41+
console.error('CLI Error:', err.message);
42+
}
43+
});
44+
45+
function mapExtensionToLanguage(ext) {
46+
const map = {
47+
'js': 'javascript',
48+
'py': 'python',
49+
'cpp': 'cpp',
50+
'c': 'c',
51+
'java': 'java',
52+
'rb': 'ruby',
53+
'go': 'go'
54+
};
55+
return map[ext] || null;
56+
}
57+
58+
async function runCode(languageId, code) {
59+
const apiKey = process.env.VITE_API_TOKENS
60+
? JSON.parse(process.env.VITE_API_TOKENS)[0]
61+
: "YOUR_FALLBACK_KEY";
62+
63+
const host = process.env.VITE_RAP_API_HOST || "judge0-ce.p.rapidapi.com";
64+
const url = process.env.VITE_RAPID_API_URL || "https://judge0-ce.p.rapidapi.com/submissions";
65+
66+
try {
67+
const response = await axios.post(url, {
68+
language_id: languageId,
69+
source_code: Buffer.from(code).toString('base64'),
70+
}, {
71+
params: { base64_encoded: "true", fields: "*" },
72+
headers: {
73+
"content-type": "application/json",
74+
"X-RapidAPI-Host": host,
75+
"X-RapidAPI-Key": apiKey,
76+
}
77+
});
78+
79+
const token = response.data.token;
80+
81+
let result = null;
82+
while (!result) {
83+
const statusRes = await axios.get(`${url}/${token}`, {
84+
params: { base64_encoded: "true", fields: "*" },
85+
headers: { "X-RapidAPI-Host": host, "X-RapidAPI-Key": apiKey }
86+
});
87+
88+
const statusId = statusRes.data.status?.id;
89+
if (statusId > 2) {
90+
result = statusRes.data;
91+
} else {
92+
await new Promise(res => setTimeout(res, 1000));
93+
}
94+
}
95+
96+
if (result.stdout) console.log(Buffer.from(result.stdout, 'base64').toString());
97+
if (result.stderr) console.error('Error:', Buffer.from(result.stderr, 'base64').toString());
98+
if (result.compile_output) console.error('Compile Error:', Buffer.from(result.compile_output, 'base64').toString());
99+
100+
} catch (error) {
101+
console.error('Execution Failed:', error.response?.data?.message || error.message);
102+
}
103+
}
104+
105+
program.parse();

package-lock.json

Lines changed: 42 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
"private": true,
44
"version": "0.0.0",
55
"type": "module",
6+
"bin": {
7+
"tech-run": "./bin/cli.js"
8+
},
69
"scripts": {
710
"dev": "vite",
811
"build": "vite build",
@@ -23,7 +26,9 @@
2326
"react-icons": "^5.5.0",
2427
"react-markdown": "^10.1.0",
2528
"react-router-dom": "^7.12.0",
26-
"react-syntax-highlighter": "^16.1.0"
29+
"react-syntax-highlighter": "^16.1.0",
30+
"dotenv": "^16.4.7",
31+
"commander": "^12.1.0"
2732
},
2833
"devDependencies": {
2934
"@eslint/js": "^9.21.0",

0 commit comments

Comments
 (0)