Nasal-Interpreter/nasal-web-app/server.js

97 lines
2.9 KiB
JavaScript

const express = require('express');
const path = require('path');
const yargs = require('yargs/yargs');
const { hideBin } = require('yargs/helpers');
const koffi = require('koffi');
require('expose-gc');
// Parse command line arguments
const argv = yargs(hideBin(process.argv))
.usage('Usage: $0 [options]')
.option('verbose', {
alias: 'v',
type: 'boolean',
description: 'Run with verbose logging'
})
.option('port', {
alias: 'p',
type: 'number',
description: 'Port to run the server on',
default: 3000
})
.option('host', {
type: 'string',
description: 'Host to run the server on',
default: 'localhost'
})
.help()
.alias('help', 'h')
.version()
.argv;
const app = express();
app.use(express.json());
app.use(express.static('public'));
let nasalLib;
try {
// First load the library
const lib = koffi.load(path.join(__dirname, '../module/libnasal-web.dylib'));
// Then declare the functions explicitly
nasalLib = {
nasal_init: lib.func('nasal_init', 'void*', []),
nasal_cleanup: lib.func('nasal_cleanup', 'void', ['void*']),
nasal_eval: lib.func('nasal_eval', 'const char*', ['void*', 'const char*', 'int']),
nasal_get_error: lib.func('nasal_get_error', 'const char*', ['void*'])
};
} catch (err) {
console.error('Failed to load nasal library:', err);
process.exit(1);
}
app.post('/eval', (req, res) => {
const { code, showTime = false } = req.body;
if (!code) {
return res.status(400).json({ error: 'No code provided' });
}
if (argv.verbose) {
console.log('Received code evaluation request:', code);
console.log('Show time:', showTime);
}
const ctx = nasalLib.nasal_init();
try {
const result = nasalLib.nasal_eval(ctx, code, showTime ? 1 : 0);
const error = nasalLib.nasal_get_error(ctx);
if (error && error !== 'null') {
if (argv.verbose) console.log('Nasal error:', error);
res.json({ error: error });
} else if (result && result.trim() !== '') {
if (argv.verbose) console.log('Nasal output:', result);
res.json({ result: result });
} else {
if (argv.verbose) console.log('No output or error returned');
res.json({ error: 'No output or error returned' });
}
} catch (err) {
if (argv.verbose) console.error('Server error:', err);
res.status(500).json({ error: err.message });
} finally {
if (argv.verbose) console.log('Cleaning up Nasal context');
nasalLib.nasal_cleanup(ctx);
global.gc()
}
});
const PORT = argv.port || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
console.log(`Visit http://localhost:${PORT} to use the Nasal interpreter`);
if (argv.verbose) console.log('Verbose logging enabled');
});