From d8b6379b9a4c4a4c40269da362e7349136528fcb Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sat, 16 Jan 2021 13:14:17 +0100 Subject: [PATCH] Add CLI written in Node --- api/src/execute.js | 48 ----------- api/src/index.js | 15 +++- api/src/languages.js | 116 +------------------------ cli/execute | 3 + cli/package.json | 12 +++ cli/src/index.js | 30 +++++++ lxc/test_all_lxc | 52 +++++------ shared/execute.js | 43 ++++++++++ shared/languages.json | 194 ++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 321 insertions(+), 192 deletions(-) delete mode 100644 api/src/execute.js create mode 100755 cli/execute create mode 100644 cli/package.json create mode 100644 cli/src/index.js create mode 100644 shared/execute.js create mode 100644 shared/languages.json diff --git a/api/src/execute.js b/api/src/execute.js deleted file mode 100644 index 1409a7b..0000000 --- a/api/src/execute.js +++ /dev/null @@ -1,48 +0,0 @@ -const { writeFile } = require('fs/promises'); -const { spawn } = require('child_process'); - -async function execute(res, language, body) { - const stamp = new Date().getTime(); - const sourceFile = `/tmp/${stamp}.code`; - - await writeFile(sourceFile, body.source); - - const process = spawn(__dirname + '/../../lxc/execute', [ - language.name, - sourceFile, - body.args?.join('\n') ?? '', - ]); - - const result = { - ran: true, - language: language.name, - stderr: '', - stdout: '', - output: '', - }; - - if (language.version) - result.version = language.version; - - process.stderr.on('data', chunk => { - result.stderr += chunk; - result.output += chunk; - }); - - process.stdout.on('data', chunk => { - result.stdout += chunk; - result.output += chunk; - }); - - process.on('exit', () => { - result.stderr = result.stderr.trim().substring(0, 65535); - result.stdout = result.stdout.trim().substring(0, 65535); - result.output = result.output.trim().substring(0, 65535); - - res.json(result); - }); -} - -module.exports = { - execute, -}; diff --git a/api/src/index.js b/api/src/index.js index c29a461..cd658c5 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -1,5 +1,5 @@ const express = require('express'); -const { execute } = require('./execute'); +const { execute } = require('../../shared/execute'); const { languages } = require('./languages'); const { checkSchema, validationResult } = require('express-validator'); @@ -41,7 +41,7 @@ app.post( }, } }), - (req, res) => { + async (req, res) => { const errors = validationResult(req).array(); if (errors.length === 0) { @@ -49,7 +49,16 @@ app.post( language.aliases.includes(req.body.language.toLowerCase()) ); - execute(res, language, req.body); + const { stdout, stderr, output } = await execute(language, req.body.source, req.body.args); + + res.status(200).json({ + ran: true, + language: language.name, + version: language.version, + stdout, + stderr, + output, + }); } else { res.status(400).json({ message: errors[0].msg, diff --git a/api/src/languages.js b/api/src/languages.js index 9fda547..23e352a 100644 --- a/api/src/languages.js +++ b/api/src/languages.js @@ -1,119 +1,5 @@ const { spawn } = require('child_process'); - -const languages = [ - { - name: 'nasm', - aliases: ['asm', 'nasm'], - }, - { - name: 'nasm64', - aliases: ['asm64', 'nasm64'], - }, - { - name: 'awk', - aliases: ['awk'], - }, - { - name: 'bash', - aliases: ['bash'], - }, - { - name: 'brainfuck', - aliases: ['bf', 'brainfuck'], - }, - { - name: 'c', - aliases: ['c'], - }, - { - name: 'csharp', - aliases: ['c#', 'cs', 'csharp'], - }, - { - name: 'cpp', - aliases: ['c++', 'cpp'], - }, - { - name: 'deno', - aliases: ['deno', 'denojs', 'denots'], - }, - { - name: 'ruby', - aliases: ['duby', 'rb', 'ruby'], - }, - { - name: 'emacs', - aliases: ['el', 'elisp', 'emacs'], - }, - { - name: 'elixir', - aliases: ['elixir'], - }, - { - name: 'haskell', - aliases: ['haskell', 'hs'], - }, - { - name: 'go', - aliases: ['go'], - }, - { - name: 'java', - aliases: ['java'], - }, - { - name: 'node', - aliases: ['javascript', 'js', 'node'], - }, - { - name: 'jelly', - aliases: ['jelly'], - }, - { - name: 'julia', - aliases: ['jl', 'julia'], - }, - { - name: 'kotlin', - aliases: ['kotlin'], - }, - { - name: 'lua', - aliases: ['lua'], - }, - { - name: 'paradoc', - aliases: ['paradoc'], - }, - { - name: 'perl', - aliases: ['perl'], - }, - { - name: 'php', - aliases: ['php', 'php3', 'php4', 'php5'], - }, - { - name: 'python3', - aliases: ['py', 'py3', 'python', 'python3'], - }, - { - name: 'python2', - aliases: ['python2'], - }, - { - name: 'rust', - aliases: ['rs', 'rust'], - }, - { - name: 'swift', - aliases: ['swift'], - }, - { - name: 'typescript', - aliases: ['ts', 'typescript'], - }, -]; +const languages = require('../../shared/languages.json'); { const process = spawn(__dirname + '/../../lxc/versions'); diff --git a/cli/execute b/cli/execute new file mode 100755 index 0000000..37a6b35 --- /dev/null +++ b/cli/execute @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +node src $* diff --git a/cli/package.json b/cli/package.json new file mode 100644 index 0000000..0166712 --- /dev/null +++ b/cli/package.json @@ -0,0 +1,12 @@ +{ + "name": "cli", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/cli/src/index.js b/cli/src/index.js new file mode 100644 index 0000000..c53d132 --- /dev/null +++ b/cli/src/index.js @@ -0,0 +1,30 @@ +const { execute } = require('../../shared/execute'); +const { readFileSync } = require('fs'); +const languages = require('../../shared/languages.json'); + +const [languageName, sourceFile, ...args] = process.argv.slice(2); + +(async () => { + if (!languageName) { + console.error('Provide a language name'); + return; + } + + if (!sourceFile) { + console.error('Provide a source file'); + return; + } + + const source = readFileSync(sourceFile); + + const language = languages.find(language => language.name === languageName); + + if (!language) { + console.error(`${languageName} is not supported by Piston`); + return; + } + + const { output } = await execute(language, source, args); + + console.log(output); +})(); diff --git a/lxc/test_all_lxc b/lxc/test_all_lxc index 873c840..493c4b5 100755 --- a/lxc/test_all_lxc +++ b/lxc/test_all_lxc @@ -2,54 +2,54 @@ cd tests echo 'testing awk' -../execute awk test.awk +../../cli/execute awk test.awk echo 'testing c' -../execute c test.c +../../cli/execute c test.c echo 'testing cpp' -../execute cpp test.cpp +../../cli/execute cpp test.cpp echo 'testing cs' -../execute cs test.cs +../../cli/execute cs test.cs echo 'testing deno' -../execute deno testdeno.ts +../../cli/execute deno testdeno.ts echo 'testing elisp' -../execute elisp test.el +../../cli/execute elisp test.el echo 'testing elixir' -../execute exs test.exs +../../cli/execute exs test.exs echo 'testing go' -../execute go test.go +../../cli/execute go test.go echo 'testing haskell' -../execute haskell test.hs +../../cli/execute haskell test.hs echo 'testing java' -../execute java test.java +../../cli/execute java test.java echo 'testing jelly' -../execute jelly test.jelly +../../cli/execute jelly test.jelly echo 'testing jl' -../execute jl test.jl +../../cli/execute jl test.jl echo 'testing js' -../execute js test.js +../../cli/execute js test.js echo 'testing kotlin' -../execute kotlin test.kt +../../cli/execute kotlin test.kt echo 'testing asm 32 bit' -../execute asm test.nasm +../../cli/execute asm test.nasm echo 'testing asm 64 bit' -../execute asm64 test64.nasm +../../cli/execute asm64 test64.nasm echo 'testing php' -../execute php test.php +../../cli/execute php test.php echo 'testing perl' -../execute perl test.pl +../../cli/execute perl test.pl echo 'testing ruby' -../execute ruby test.rb +../../cli/execute ruby test.rb echo 'testing rust' -../execute rust test.rs +../../cli/execute rust test.rs echo 'testing bash' -../execute bash test.sh +../../cli/execute bash test.sh echo 'testing swift' -../execute swift test.swift +../../cli/execute swift test.swift echo 'testing typescript' -../execute typescript test.ts +../../cli/execute typescript test.ts echo 'testing python2' -../execute python2 test2.py +../../cli/execute python2 test2.py echo 'testing python3' -../execute python3 test3.py +../../cli/execute python3 test3.py echo 'testing paradoc' -../execute python3 test_paradoc.py +../../cli/execute python3 test_paradoc.py diff --git a/shared/execute.js b/shared/execute.js new file mode 100644 index 0000000..22c6dad --- /dev/null +++ b/shared/execute.js @@ -0,0 +1,43 @@ +const { writeFile } = require('fs/promises'); +const { spawn } = require('child_process'); + +function execute(language, source, args) { + return new Promise(async resolve => { + const stamp = new Date().getTime(); + const sourceFile = `/tmp/${stamp}.code`; + + await writeFile(sourceFile, source); + + const process = spawn(__dirname + '/../lxc/execute', [ + language.name, + sourceFile, + args?.join('\n') ?? '', + ]); + + let stdout = ''; + let stderr = ''; + let output = ''; + + process.stderr.on('data', chunk => { + stderr += chunk; + output += chunk; + }); + + process.stdout.on('data', chunk => { + stdout += chunk; + output += chunk; + }); + + process.on('exit', () => { + stderr = stderr.trim().substring(0, 65535); + stdout = stdout.trim().substring(0, 65535); + output = output.trim().substring(0, 65535); + + resolve({ stdout, stderr, output }); + }); + }); +} + +module.exports = { + execute, +}; diff --git a/shared/languages.json b/shared/languages.json new file mode 100644 index 0000000..ba04153 --- /dev/null +++ b/shared/languages.json @@ -0,0 +1,194 @@ +[ + { + "name": "nasm", + "aliases": [ + "asm", + "nasm" + ] + }, + { + "name": "nasm64", + "aliases": [ + "asm64", + "nasm64" + ] + }, + { + "name": "awk", + "aliases": [ + "awk" + ] + }, + { + "name": "bash", + "aliases": [ + "bash" + ] + }, + { + "name": "brainfuck", + "aliases": [ + "bf", + "brainfuck" + ] + }, + { + "name": "c", + "aliases": [ + "c" + ] + }, + { + "name": "csharp", + "aliases": [ + "c#", + "cs", + "csharp" + ] + }, + { + "name": "cpp", + "aliases": [ + "c++", + "cpp" + ] + }, + { + "name": "deno", + "aliases": [ + "deno", + "denojs", + "denots" + ] + }, + { + "name": "ruby", + "aliases": [ + "duby", + "rb", + "ruby" + ] + }, + { + "name": "emacs", + "aliases": [ + "el", + "elisp", + "emacs" + ] + }, + { + "name": "elixir", + "aliases": [ + "elixir" + ] + }, + { + "name": "haskell", + "aliases": [ + "haskell", + "hs" + ] + }, + { + "name": "go", + "aliases": [ + "go" + ] + }, + { + "name": "java", + "aliases": [ + "java" + ] + }, + { + "name": "node", + "aliases": [ + "javascript", + "js", + "node" + ] + }, + { + "name": "jelly", + "aliases": [ + "jelly" + ] + }, + { + "name": "julia", + "aliases": [ + "jl", + "julia" + ] + }, + { + "name": "kotlin", + "aliases": [ + "kotlin" + ] + }, + { + "name": "lua", + "aliases": [ + "lua" + ] + }, + { + "name": "paradoc", + "aliases": [ + "paradoc" + ] + }, + { + "name": "perl", + "aliases": [ + "perl" + ] + }, + { + "name": "php", + "aliases": [ + "php", + "php3", + "php4", + "php5" + ] + }, + { + "name": "python3", + "aliases": [ + "py", + "py3", + "python", + "python3" + ] + }, + { + "name": "python2", + "aliases": [ + "python2" + ] + }, + { + "name": "rust", + "aliases": [ + "rs", + "rust" + ] + }, + { + "name": "swift", + "aliases": [ + "swift" + ] + }, + { + "name": "typescript", + "aliases": [ + "ts", + "typescript" + ] + } +]