UNPKG

routeros-api

Version:

Mikrotik Routerboard RouterOS API for NodeJS

389 lines 21.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RosApiCommands = void 0; const RosApiCrud_1 = require("./RosApiCrud"); const RosApiModel_1 = require("./RosApiModel"); const debug = require("debug"); const info = debug("routeros-client:commands:info"); const error = debug("routeros-client:commands:error"); class RosApiCommands extends RosApiCrud_1.RouterOSAPICrud { /** * Creates a set of operations to do over a menu * * @param rosApi The raw API * @param path The menu path we are doing actions on * @param snakeCase If we should use snake_case */ constructor(rosApi, path, snakeCase) { super(rosApi, path, snakeCase); } /** * Limits the returned fields when printing * * @param fields Fields to return */ select(fields) { let commaFields = "=.proplist="; if (typeof fields === "string") fields = [fields]; for (let i = 0; i < fields.length; i++) { const field = fields[i]; if (/^(id|dead|nextid)$/.test(field)) fields[i] = "." + field; } // Convert array to a string comma separated commaFields += fields; this.proplistVal = commaFields; return this; } /** * Moves a rule ABOVE the destination * * @param from the rule you want to move * @param to the destination where you want to move */ move(from, to) { return super.moveEntry(from, to); } /** * Alias for select() * @param fields Fields to return */ only(fields) { return this.select(fields); } /** * Add an option to the command. As an example: count-only or detail * * @param opts an option or array of options * @param args multiple strings of parameters of options */ options(opts, ...args) { if (typeof opts === "string") opts = [opts]; opts = opts.concat(args || []); const optObj = {}; for (const opt of opts) optObj[opt] = ""; return this.where(optObj, "", false); } /** * Alias for select() * @param fields */ proplist(fields) { return this.select(fields); } /** * Filters the content when printing or define which item * will do actions to when not printing * * @param key a key to a value or an object with keys and values to filter * @param value the value if a string key is passed * @param addQuestionMark if will start the sentence with a question mark (?), else, starts with equal (=) */ where(key, value = "", addQuestionMark = true) { let search = new Object(); if (typeof key === "string") { search[key] = value; } else { search = key; } this.makeQuery(search, addQuestionMark); return this; } /** * Alias to where, but without adding question marks * * @param key a key to a value or an object with keys and values to filter * @param value the value if a string key is passed */ query(key, value) { return this.where(key, value, false); } /** * Alias to where, but without adding question marks * * @param key a key to a value or an object with keys and values to filter * @param value the value if a string key is passed */ filter(key, value) { return this.where(key, value, false); } /** * Raw API syntax to be added to the stack * * @param search array of sentences to send over the api */ whereRaw(search) { this.queryVal = this.queryVal.concat(search); return this; } /** * Adds an OR operator when filtering content * * @param key a key to a value or an object with keys and values to filter * @param value the value if a string key is passed */ orWhere(key, value) { this.where(key, value); this.queryVal.push("?#|"); return this; } /** * Adds a NOT and then OR operator when filtering content * * @param key a key to a value or an object with keys and values to filter * @param value the value if a string key is passed */ orWhereNot(key, value) { this.where(key, value); this.queryVal.push("?#!", "?#|"); return this; } /** * Adds an AND operator when filtering content * * @param key a key to a value or an object with keys and values to filter * @param value the value if a string key is passed */ andWhere(key, value) { this.where(key, value); this.queryVal.push("?#&"); return this; } /** * Adds a NOT and then an AND operator when filtering content * * @param key a key to a value or an object with keys and values to filter * @param value the value if a string key is passed */ andWhereNot(key, value) { this.where(key, value); this.queryVal.push("?#!", "?#&"); return this; } /** * Adds an NOT operator when filtering content * * @param key a key to a value or an object with keys and values to filter * @param value the value if a string key is passed */ whereNot(key, value) { this.where(key, value); this.queryVal.push("?#!"); return this; } /** * Adds a HIGHER THAN (>) operator when filtering content * * @param key a key to a value or an object with keys and values to filter * @param value the value if a string key is passed */ whereHigher(key, value) { this.where(">" + key, value); return this; } /** * Adds a LOWER THAN (<) operator when filtering content * * @param key a key to a value or an object with keys and values to filter * @param value the value if a string key is passed */ whereLower(key, value) { this.where("<" + key, value); return this; } /** * Checks if the parameter or key exists by having a value when filtering * * @param key the parameter to check */ whereExists(key) { return this.whereHigher(key); } /** * Alias to whereExists * * @param key the parameter to check */ whereNotEmpty(key) { return this.whereHigher(key); } /** * Check if the parameter or key doesn't exist or has no value when filtering * * @param key the parameter to check */ whereEmpty(key) { this.where("-" + key); return this; } /** * Alias of whereEmpty * * @param key the parameter to check */ whereNotExists(key) { return this.whereEmpty(key); } /** * Prints the data of the menu * * @param data optional filtering, like what you get when using the where function */ get(data) { if (data) this.makeQuery(data, true); const query = this.fullQuery("/print"); return this.write(query); } /** * Alias of get * * @param data optional filtering, like what you get when using the where function */ getAll(data) { return this.get(data); } /** * Alias of get, but in the process creates a model * of each item returned * * @param data optional filtering, like what you get when using the where function */ getModel(data) { return this.get(data).then((results) => { for (let i = 0; i < results.length; i++) { results[i] = new RosApiModel_1.RosApiModel(this.rosApi, results[i], this.snakeCase); } return Promise.resolve(results); }).catch((err) => { return Promise.reject(err); }); } /** * Alias of get * * @param data optional filtering, like what you get when using the where function */ print(data) { return this.get(data); } /** * Alias of find * * @param data optional filtering, like what you get when using the where function */ first(data) { return this.find(data); } /** * Returns the first item if found, else return null * * @param data optional filtering, like what you get when using the where function */ find(data) { return this.get(data).then((results) => { let result = new Object(); if (results.length > 0) result = results[0]; else result = null; return Promise.resolve(result); }).catch((err) => { return Promise.reject(err); }); } /** * Alias of find * * @param data optional filtering, like what you get when using the where function */ getOne(data) { return this.find(data); } /** * Alias of find * * @param data optional filtering, like what you get when using the where function */ getOnly(data) { return this.find(data); } /** * Remove all entries of the current menu */ purge() { return this.write([ this.pathVal + "/print", "=.proplist=.id" ]).then((results) => { const ids = results.map((result) => { return result[".id"]; }); return this.write([ this.pathVal + "/remove", "=numbers=" + ids ]); }).catch((err) => { return Promise.reject(err); }); } /** * Start a streaming of content and returns a Stream object * so it can be paused, resumed or stopped * * @param action optional action to add when streaming, like "listen" for example * @param callback */ stream(action, callback) { if (typeof action === "function") { callback = action; action = ""; } else if (action && typeof action === "string") { action = "/" + action.replace(/^\//, ""); } const query = this.fullQuery(action); info("Streaming query %o", query); this.queryVal = []; this.proplistVal = ""; if (!callback) { const stream = this.rosApi.stream(query); stream.on("data", (packet) => { if (!Array.isArray(packet)) { packet = this.treatMikrotikProperties([packet])[0]; } else { packet = this.treatMikrotikProperties(packet); } stream.emit("parsed-data", packet); }); stream.on("error", (err) => { err = this.treatMikrotikProperties([err])[0]; stream.emit("parsed-error", err); }); return stream; } return this.rosApi.stream(query, (err, packet, stream) => { if (err) error("When streaming, got error: %o", err); if (typeof callback === "function") { if (packet) { info("Received stream packet: %o", packet); if (!Array.isArray(packet)) { packet = this.treatMikrotikProperties([packet])[0]; } else { packet = this.treatMikrotikProperties(packet); } } callback(err, packet, stream); } }); } } exports.RosApiCommands = RosApiCommands; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUm9zQXBpQ29tbWFuZHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvUm9zQXBpQ29tbWFuZHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EsNkNBQStDO0FBQy9DLCtDQUE0QztBQUU1QywrQkFBK0I7QUFJL0IsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLCtCQUErQixDQUFDLENBQUM7QUFDcEQsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLGdDQUFnQyxDQUFDLENBQUM7QUFFdEQsTUFBYSxjQUFlLFNBQVEsNEJBQWU7SUFFL0M7Ozs7OztPQU1HO0lBQ0gsWUFBWSxNQUFtQixFQUFFLElBQVksRUFBRSxTQUFrQjtRQUM3RCxLQUFLLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztJQUNuQyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLE1BQU0sQ0FBQyxNQUF5QjtRQUNuQyxJQUFJLFdBQVcsR0FBVyxhQUFhLENBQUM7UUFDeEMsSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRO1lBQUUsTUFBTSxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFbEQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDcEMsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3hCLElBQUksb0JBQW9CLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztnQkFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxHQUFHLEtBQUssQ0FBQztTQUNqRTtRQUVELDZDQUE2QztRQUM3QyxXQUFXLElBQUksTUFBTSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO1FBQy9CLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNJLElBQUksQ0FBQyxJQUFjLEVBQUUs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