@stencila/jesta
Version:
Stencila plugin for executable documents using JavaScript
121 lines (120 loc) • 3.92 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.serve = void 0;
const readline_1 = __importDefault(require("readline"));
const errors_1 = require("./util/errors");
/**
* Serve the plugin.
*/
async function serve() {
var _a;
// Turn on the default signal handler so that an errant SIGINT does
// not stop the server
defaultSigIntHandler();
const reader = readline_1.default.createInterface({
input: process.stdin,
terminal: false,
});
for await (const line of reader) {
let id;
let response;
try {
const request = JSON.parse(line);
const { id: id_, method, params } = request;
if (id_ === undefined || method === undefined)
throw new errors_1.InvalidRequestError();
id = id_;
// If the method is interruptible then it has it's own SIGINT handling,
// so turn off this module's SIGINT handling. Otherwise, add a handler that provides
// a notification that this request is not interruptible
// TODO Get interruptible from method schema this[method as Method].schema
const { interruptible = false } = {};
if (interruptible)
noSigIntHandler();
else
uninterruptibleSigIntHandler(id, method);
const result = await this.dispatch(method, params !== null && params !== void 0 ? params : {});
// Turn back on the default SIGINT handling
defaultSigIntHandler();
response = {
id,
result,
};
}
catch (err) {
const error = err instanceof errors_1.JsonRpcError
? err
: err instanceof SyntaxError
? new errors_1.ParseError(err.message)
: err instanceof Error
? new errors_1.ServerError((_a = err.stack) !== null && _a !== void 0 ? _a : err.message)
: new errors_1.ServerError('Unknown error');
const { code, message, data } = error;
response = {
id,
error: { code, message, data },
};
}
sendMessage(response);
}
}
exports.serve = serve;
/**
* On SIGINT, send a JSON-RPC notification that there is no
* request currently being processed.
*/
function defaultSigIntHandler() {
process.removeAllListeners('SIGINT');
process.addListener('SIGINT', () => {
sendMessage({
method: 'warn',
params: {
message: 'No request is currently being processed; interrupt ignored.',
},
});
});
}
/**
* Remove all SIGINT handlers
*/
function noSigIntHandler() {
process.removeAllListeners('SIGINT');
}
/**
* On SIGINT, send a JSON-RPC notification that the current request
* is uninterruptible.
*
* @param id Id of the current request
* @param method Method of the current request
*/
function uninterruptibleSigIntHandler(id, method) {
process.removeAllListeners('SIGINT');
process.addListener('SIGINT', () => {
sendMessage({
method: 'warn',
params: {
request: {
id,
method,
},
message: 'Request is uninterruptible',
},
});
});
}
/**
* Send a JSON-RPC message (response or notification) to the client.
*
* This sends the message with,
* transport: stdio
* framing: nld
* serialization: json
*
* @param message The JSON-RPC response or notification
*/
function sendMessage(message) {
process.stdout.write(JSON.stringify(message) + '\n');
}