Skip to content
This repository has been archived by the owner on Mar 25, 2024. It is now read-only.

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
aluisiora committed Mar 7, 2018
2 parents eda0334 + 82f3ff6 commit 84605d7
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 106 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "routeros-client",
"version": "0.8.1",
"description": "Easy to use abstraction layer over the node-routeros API",
"version": "0.9.0",
"description": "Abstraction layer over the node-routeros API",
"main": "./dist/index",
"types": "./dist/index",
"directories": {
Expand Down Expand Up @@ -51,6 +51,7 @@
},
"dependencies": {
"debug": "^3.*",
"lodash": "^4.*",
"node-routeros": "^1.*"
}
}
154 changes: 100 additions & 54 deletions src/RosApiCrud.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { RouterOSAPI, RosException } from "node-routeros";
import { flatten } from "lodash";
import * as utils from "./utils";
import * as Types from "./Types";

export abstract class RouterOSAPICrud {
Expand Down Expand Up @@ -48,10 +50,8 @@ export abstract class RouterOSAPICrud {
*/
public add(data: object): Types.SocPromise {
return this.exec("add", data).then((results: any) => {
if (results.length > 0) results = results[0];
return Promise.resolve(results);
}).catch((err: RosException) => {
return Promise.reject(err);
if (results.length === 0) return Promise.resolve(null);
return this.recoverDataFromIdsOfChangedItems(null, results[0].ret);
});
}

Expand All @@ -74,7 +74,10 @@ export abstract class RouterOSAPICrud {
ids = this.stringfySearchQuery(ids);
this.queryVal.push("=numbers=" + ids);
}
return this.exec("disable");
const disabledIds = utils.lookForIdParameterAndReturnItsValue(this.queryVal);
return this.exec("disable").then((response: any[]) => {
return this.recoverDataFromIdsOfChangedItems(response, disabledIds);
});
}

/**
Expand All @@ -83,10 +86,6 @@ export abstract class RouterOSAPICrud {
* @param ids the id(s) or number(s) to delete
*/
public delete(ids?: Types.Id): Types.SocPromise {
if (ids) {
ids = this.stringfySearchQuery(ids);
this.queryVal.push("=numbers=" + ids);
}
return this.remove(ids);
}

Expand All @@ -100,7 +99,10 @@ export abstract class RouterOSAPICrud {
ids = this.stringfySearchQuery(ids);
this.queryVal.push("=numbers=" + ids);
}
return this.exec("enable");
const enabledIds = utils.lookForIdParameterAndReturnItsValue(this.queryVal);
return this.exec("enable").then((response: any[]) => {
return this.recoverDataFromIdsOfChangedItems(response, enabledIds);
});
}

/**
Expand All @@ -115,6 +117,8 @@ export abstract class RouterOSAPICrud {
return this.translateQueryIntoId(query).then((consultedQuery) => {
return this.write(consultedQuery);
}).then((results) => {
// Only runs when using the place-after feature
// otherwise it will return the response immediately
return this.prepareToPlaceAfter(results);
});
}
Expand All @@ -133,7 +137,10 @@ export abstract class RouterOSAPICrud {
to = this.stringfySearchQuery(to);
this.queryVal.push("=destination=" + to);
}
return this.exec("move");
const movedIds = utils.lookForIdParameterAndReturnItsValue(this.queryVal);
return this.exec("move").then((response: any[]) => {
return this.recoverDataFromIdsOfChangedItems(response, movedIds);
});
}

/**
Expand All @@ -148,7 +155,10 @@ export abstract class RouterOSAPICrud {
this.queryVal.push("=numbers=" + ids);
}
this.makeQuery(data);
return this.exec("set");
const updatedIds = utils.lookForIdParameterAndReturnItsValue(this.queryVal);
return this.exec("set").then((response: any[]) => {
return this.recoverDataFromIdsOfChangedItems(response, updatedIds);
});
}

/**
Expand All @@ -164,14 +174,41 @@ export abstract class RouterOSAPICrud {
}
if (typeof properties === "string") properties = [properties];
const $q: Types.SocPromise[] = [];

// Saving current queryVal for reuse, since running exec will reset it
const curQueryVal = this.queryVal.slice();
const updatedIds = utils.lookForIdParameterAndReturnItsValue(this.queryVal);

// Cleaning current queryVal to prevent duplication
this.queryVal = [];
properties.forEach((property) => {
// Putting back queryVal after a cleanup
this.queryVal = curQueryVal.slice();
this.queryVal.push("=value-name=" + this.camelCaseOrSnakeCaseToDashedCase(property));
this.queryVal.push("=value-name=" + utils.camelCaseOrSnakeCaseToDashedCase(property));
$q.push(this.exec("unset"));
});
return Promise.all($q);
return Promise.all($q).then((data: any[]) => {
data = flatten(data);
return Promise.resolve(data);
}).then((response: any[]) => {
if (!response || !updatedIds) return Promise.resolve(response);
const promises = [];
const ids = updatedIds.split(",");
for (const id of ids) {
const promise = this.rosApi.write([
this.pathVal + "/print",
"?.id=" + id
]);
promises.push(promise);
}
return Promise.all(promises);
}).then((data) => {
if (!data) return Promise.resolve(data);
data = flatten(data);
data = this.treatMikrotikProperties(data);
if (!updatedIds.includes(",")) return Promise.resolve(data[0]);
return Promise.resolve(data);
});
}

/**
Expand All @@ -184,7 +221,31 @@ export abstract class RouterOSAPICrud {
ids = this.stringfySearchQuery(ids);
this.queryVal.push("=numbers=" + ids);
}
return this.exec("remove");
const idsForRemoval = utils.lookForIdParameterAndReturnItsValue(this.queryVal);
if (!idsForRemoval) return this.exec("remove");

const promises = [];
const foundIds = idsForRemoval.split(",");
for (const id of foundIds) {
const promise = this.rosApi.write([
this.pathVal + "/print",
"?.id=" + id
]);
promises.push(promise);
}
let responseData;
return Promise.all(promises).then((data: any) => {
if (!data) return Promise.resolve(data);
data = flatten(data);
data = this.treatMikrotikProperties(data);
if (!idsForRemoval.includes(",")) return Promise.resolve(data[0]);
return Promise.resolve(data);
}).then((data: any) => {
responseData = data;
return this.exec("remove");
}).then(() => {
return Promise.resolve(responseData);
});
}

/**
Expand Down Expand Up @@ -286,7 +347,7 @@ export abstract class RouterOSAPICrud {

tmpKey = (addQuestionMark ? "?" : "=") + tmpKey;

tmpKey = this.camelCaseOrSnakeCaseToDashedCase(tmpKey);
tmpKey = utils.camelCaseOrSnakeCaseToDashedCase(tmpKey);

tmpQuery.push(tmpKey + "=" + tmpVal);
}
Expand Down Expand Up @@ -395,8 +456,8 @@ export abstract class RouterOSAPICrud {
if (result.hasOwnProperty(key)) {
const tmpVal = result[key];
let tmpKey = this.snakeCase
? this.dashedCaseToSnakeCase(key)
: this.dashedCaseToCamelCase(key);
? utils.dashedCaseToSnakeCase(key)
: utils.dashedCaseToCamelCase(key);
tmpKey = tmpKey.replace(/^\./, "");
tmpItem[tmpKey] = tmpVal;
if (tmpVal === "true" || tmpVal === "false") {
Expand Down Expand Up @@ -434,45 +495,30 @@ export abstract class RouterOSAPICrud {
}

/**
* Transform camelCase or snake_case to dashed-case,
* so the routerboard can understand the parameters used
* on this wrapper
*
* @param val to string to transform
*/
private camelCaseOrSnakeCaseToDashedCase(val: string): string {
// Clean any empty space left
return val.replace(/ /g, "")
// Convert camelCase to dashed
.replace(/([a-z][A-Z])/g, (g, w) => {
return g[0] + "-" + g[1].toLowerCase();
})
// Replace any underline to hiphen if used
.replace(/_/g, "-");
}

/**
* Transform routerboard's dashed-case to camelCase
* so we can use objects properties without having to wrap
* around quotes
* Clean data print of provided ids, used only when
* creating, editting or unsetting properties
*
* @param val the string to transform
* @param data
* @param ids
*/
private dashedCaseToCamelCase(val: string): string {
return val.replace(/-([a-z])/g, (g) => {
return g[1].toUpperCase();
private recoverDataFromIdsOfChangedItems(data: any[], ids?: string): Promise<any | any[]> {
if (!ids) return Promise.resolve(data);
const promises = [];
const splittedIds = ids.split(",");
for (const id of splittedIds) {
const promise = this.rosApi.write([
this.pathVal + "/print",
"?.id=" + id
]);
promises.push(promise);
}
return Promise.all(promises).then((data) => {
if (!data) return Promise.resolve(data);
data = flatten(data);
data = this.treatMikrotikProperties(data);
if (!ids.includes(",")) return Promise.resolve(data[0]);
return Promise.resolve(data);
});
}

/**
* Transform routerboard's dashed-case to snake_case
* so we can use objects properties without having to wrap
* around quotes
*
* @param val the string to transform
*/
private dashedCaseToSnakeCase(val: string): string {
return val.replace(/-/g, "_");
}

}
41 changes: 15 additions & 26 deletions src/RosApiModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ export class RosApiModel extends RouterOSAPICrud {
* Disable itself
*/
public disable(): Types.SocPromise {
return super.disable(this.originalItem.id).then(() => {
return this.refreshData();
return super.disable(this.originalItem.id).then((response) => {
return this.refreshData(response);
}).catch((err: RosException) => {
return Promise.reject(err);
});
Expand All @@ -45,8 +45,8 @@ export class RosApiModel extends RouterOSAPICrud {
* Enable itself
*/
public enable(): Types.SocPromise {
return super.enable(this.originalItem.id).then(() => {
return this.refreshData();
return super.enable(this.originalItem.id).then((response) => {
return this.refreshData(response);
}).catch((err: RosException) => {
return Promise.reject(err);
});
Expand All @@ -58,8 +58,8 @@ export class RosApiModel extends RouterOSAPICrud {
* @param to where to move to
*/
public move(to?: string | number): Types.SocPromise {
return super.move(this.originalItem.id, to).then(() => {
return this.refreshData();
return super.move(this.originalItem.id, to).then((response) => {
return this.refreshData(response);
}).catch((err: RosException) => {
return Promise.reject(err);
});
Expand All @@ -70,8 +70,8 @@ export class RosApiModel extends RouterOSAPICrud {
* @param properties properties to unset
*/
public unset(properties: string | string[]): Types.SocPromise {
return super.unset(properties, this.originalItem.id).then(() => {
return this.refreshData();
return super.unset(properties, this.originalItem.id).then((response) => {
return this.refreshData(response);
}).catch((err: RosException) => {
return Promise.reject(err);
});
Expand All @@ -83,8 +83,8 @@ export class RosApiModel extends RouterOSAPICrud {
* @param data new data to update to
*/
public update(data: object): Types.SocPromise {
return super.update(data, this.originalItem.id).then(() => {
return this.refreshData();
return super.update(data, this.originalItem.id).then((response) => {
return this.refreshData(response);
}).catch((err: RosException) => {
return Promise.reject(err);
});
Expand Down Expand Up @@ -134,22 +134,11 @@ export class RosApiModel extends RouterOSAPICrud {
* Refresh this object with new data of the item
* after printing it again
*/
private refreshData(): Types.SocPromise {
const originalQueryVal = this.queryVal.slice();
const originalProplistVal = this.proplistVal;
return this.write([
this.originalItem.$$path + "/print",
"?.id=" + this.originalItem.id
]).then((response: any[]) => {
this.cleanDissolvedProperties();
this.originalItem = response[0];
this.dissolveProperties();
this.queryVal = originalQueryVal;
this.proplistVal = originalProplistVal;
return Promise.resolve(this);
}).catch((err: RosException) => {
return Promise.reject(err);
});
private refreshData(response: any): Types.SocPromise {
this.cleanDissolvedProperties();
this.originalItem = response;
this.dissolveProperties();
return Promise.resolve(this);
}

}
Loading

0 comments on commit 84605d7

Please sign in to comment.