UNPKG

@fibercom/routeros-api

Version:

Robust MikroTik RouterOS API client for Node.js and TypeScript

144 lines 9.91 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Channel = void 0; const events_1 = require("events"); const RosException_1 = require("./RosException"); const debug = require("debug"); const info = debug("routeros-api:channel:info"); const error = debug("routeros-api:channel:error"); /** * Channel class is responsible for issuing commands with a unique tag, * and receiving corresponding replies via the RouterOS API. It listens for * specific reply types such as !re, !done, and !trap. */ class Channel extends events_1.EventEmitter { constructor(connector) { super(); this.data = []; this.trapped = false; this.streaming = false; this.closed = false; this.id = Math.random().toString(36).substring(3); this.connector = connector; this.once("unknown", this.onUnknown.bind(this)); } /** * Get the unique ID assigned to this channel. */ get Id() { return this.id; } /** * Get the underlying connector used by this channel. */ get Connector() { return this.connector; } /** Whether this channel has completed cleanup and stopped reading its tag. */ get Closed() { return this.closed; } /** * Write a command to the RouterOS device with this channel's tag. * Always returns a promise that resolves/rejects on done/trap. */ write(params, isStream = false, returnPromise = true) { this.streaming = isStream; const taggedParams = [...params, ".tag=" + this.id]; if (!returnPromise) { this.readAndWrite(taggedParams); return Promise.resolve([]); } this.data = []; // clear any old data this.on("data", (packet) => this.data.push(packet)); return new Promise((resolve, reject) => { this.once("done", (data) => resolve(data)); this.once("trap", (data) => { const msg = (data === null || data === void 0 ? void 0 : data.message) || "Unknown error"; reject(new RosException_1.RosException("TRAP", { message: msg })); }); this.readAndWrite(taggedParams); }); } /** * Close the channel and stop reading its tag. * Optionally force cleanup of event listeners. */ close(force = false) { if (this.closed) return; this.closed = true; this.emit("close"); if (!this.streaming || force) { this.removeAllListeners(); } this.connector.stopRead(this.id); } /** * Bind a tag reader and issue the command. */ readAndWrite(params) { this.connector.read(this.id, (packet) => this.processPacket(packet)); this.connector.write(params); } /** * Parse incoming replies and emit appropriate events. */ processPacket(packet) { const reply = packet.shift(); info("Processing reply %s with data %o", reply, packet); if (reply === "!empty") { info("Received !empty — interpreted as empty [] response"); // Explicitly clear data this.data = []; return; } const parsed = this.parsePacket(packet); if (reply === "!trap") { this.trapped = true; this.emit("trap", parsed); return; } if (packet.length > 0 && !this.streaming) { this.emit("data", parsed); } switch (reply) { case "!re": if (this.streaming) this.emit("stream", parsed); break; case "!done": if (!this.trapped) this.emit("done", this.data); this.close(); break; default: this.emit("unknown", reply); this.close(); break; } } /** * Convert an array of lines like '=key=value' into an object. */ parsePacket(packet) { const obj = {}; for (const line of packet) { const linePair = line.split("="); linePair.shift(); // Remove leading empty element const key = linePair.shift(); if (key !== undefined) obj[key] = linePair.join("="); } info("Parsed line, got %o as result", obj); return obj; } /** * Handler for unexpected replies—emits and throws an error. */ onUnknown(reply) { throw new RosException_1.RosException("UNKNOWNREPLY", { reply }); } } exports.Channel = Channel; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2hhbm5lbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9DaGFubmVsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLG1DQUFzQztBQUV0QyxpREFBOEM7QUFDOUMsK0JBQWdDO0FBR2hDLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO0FBQ2hELE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO0FBRWxEOzs7O0dBSUc7QUFDSCxNQUFhLE9BQVEsU0FBUSxxQkFBWTtJQVF2QyxZQUFZLFNBQW9CO1FBQzlCLEtBQUssRUFBRSxDQUFDO1FBTkYsU0FBSSxHQUFVLEVBQUUsQ0FBQztRQUNqQixZQUFPLEdBQVksS0FBSyxDQUFDO1FBQ3pCLGNBQVMsR0FBWSxLQUFLLENBQUM7UUFDM0IsV0FBTSxHQUFZLEtBQUssQ0FBQztRQUk5QixJQUFJLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xELElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1FBQzNCLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbEQsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBSSxFQUFFO1FBQ0osT0FBTyxJQUFJLENBQUMsRUFBRSxDQUFDO0lBQ2pCLENBQUM7SUFFRDs7T0FFRztJQUNILElBQUksU0FBUztRQUNYLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQztJQUN4QixDQUFDO0lBRUQsOEVBQThFO0lBQzlFLElBQUksTUFBTTtRQUNSLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNyQixDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksS0FBSyxDQUNWLE1BQWdCLEVBQ2hCLFFB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