rosinterface 1.3.0 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/Generate.js +20 -1
- package/dist/cli/Generate.js.map +1 -1
- package/dist/cli/SchemaInferrer.d.ts +9 -0
- package/dist/cli/SchemaInferrer.js +22 -3
- package/dist/cli/SchemaInferrer.js.map +1 -1
- package/dist/client/CommandBuilder.d.ts +337 -2
- package/dist/client/CommandBuilder.js +483 -15
- package/dist/client/CommandBuilder.js.map +1 -1
- package/dist/client/MikrotikClient.d.ts +349 -1
- package/dist/client/MikrotikClient.js +364 -1
- package/dist/client/MikrotikClient.js.map +1 -1
- package/dist/client/MikrotikPool.d.ts +30 -0
- package/dist/client/MikrotikPool.js +31 -1
- package/dist/client/MikrotikPool.js.map +1 -1
- package/dist/client/MikrotikSwarm.d.ts +167 -0
- package/dist/client/MikrotikSwarm.js +178 -1
- package/dist/client/MikrotikSwarm.js.map +1 -1
- package/dist/client/MikrotikTransaction.d.ts +27 -0
- package/dist/client/MikrotikTransaction.js +28 -0
- package/dist/client/MikrotikTransaction.js.map +1 -1
- package/dist/client/ResultParser.d.ts +19 -0
- package/dist/client/ResultParser.js +31 -0
- package/dist/client/ResultParser.js.map +1 -1
- package/dist/client/SnapshotSubscription.d.ts +139 -0
- package/dist/client/SnapshotSubscription.js +169 -0
- package/dist/client/SnapshotSubscription.js.map +1 -1
- package/dist/core/Auth.d.ts +31 -0
- package/dist/core/Auth.js +46 -1
- package/dist/core/Auth.js.map +1 -1
- package/dist/core/CircuitBreaker.d.ts +26 -0
- package/dist/core/CircuitBreaker.js +26 -0
- package/dist/core/CircuitBreaker.js.map +1 -1
- package/dist/core/HttpConstants.d.ts +29 -16
- package/dist/core/HttpConstants.js +23 -7
- package/dist/core/HttpConstants.js.map +1 -1
- package/dist/core/OfflineQueue.d.ts +16 -0
- package/dist/core/OfflineQueue.js +10 -0
- package/dist/core/OfflineQueue.js.map +1 -1
- package/dist/core/RateLimiter.d.ts +24 -0
- package/dist/core/RateLimiter.js +43 -7
- package/dist/core/RateLimiter.js.map +1 -1
- package/dist/core/RestProtocol.d.ts +9 -0
- package/dist/core/RestProtocol.js +16 -1
- package/dist/core/RestProtocol.js.map +1 -1
- package/dist/core/RosError.d.ts +15 -0
- package/dist/core/RosError.js +36 -1
- package/dist/core/RosError.js.map +1 -1
- package/dist/core/RosProtocol.d.ts +21 -0
- package/dist/core/RosProtocol.js +40 -1
- package/dist/core/RosProtocol.js.map +1 -1
- package/dist/core/SchemaMapper.d.ts +41 -0
- package/dist/core/SchemaMapper.js +57 -2
- package/dist/core/SchemaMapper.js.map +1 -1
- package/dist/core/SocketClient.d.ts +34 -0
- package/dist/core/SocketClient.js +51 -3
- package/dist/core/SocketClient.js.map +1 -1
- package/dist/features/FileManager.d.ts +50 -0
- package/dist/features/FileManager.js +72 -6
- package/dist/features/FileManager.js.map +1 -1
- package/dist/features/LiveCollection.d.ts +51 -0
- package/dist/features/LiveCollection.js +69 -0
- package/dist/features/LiveCollection.js.map +1 -1
- package/dist/features/PrometheusExporter.d.ts +18 -1
- package/dist/features/PrometheusExporter.js +21 -1
- package/dist/features/PrometheusExporter.js.map +1 -1
- package/dist/index.d.ts +66 -0
- package/dist/index.js +78 -0
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.js +24 -0
- package/dist/types/index.js.map +1 -1
- package/dist/utils/Helpers.d.ts +16 -0
- package/dist/utils/Helpers.js +17 -1
- package/dist/utils/Helpers.js.map +1 -1
- package/dist/utils/MikrotikCollection.d.ts +85 -0
- package/dist/utils/MikrotikCollection.js +97 -1
- package/dist/utils/MikrotikCollection.js.map +1 -1
- package/package.json +2 -2
|
@@ -49,6 +49,7 @@ class RestProtocol {
|
|
|
49
49
|
const response = await fetch(url, fetchOptions);
|
|
50
50
|
if (!response.ok) {
|
|
51
51
|
const rosError = await RosError_1.RosError.fromResponse(response, cmd);
|
|
52
|
+
// IDEMPOTENCY LOGIC
|
|
52
53
|
if (options?.idempotent && rosError.isDuplicate) {
|
|
53
54
|
const keyField = options.idempotencyKey || 'name';
|
|
54
55
|
if (body && body[keyField]) {
|
|
@@ -57,6 +58,7 @@ class RestProtocol {
|
|
|
57
58
|
}
|
|
58
59
|
throw rosError;
|
|
59
60
|
}
|
|
61
|
+
// Handle 204 No Content (Success but no body, common in DELETE/PUT)
|
|
60
62
|
if (response.status === 204) {
|
|
61
63
|
return null;
|
|
62
64
|
}
|
|
@@ -89,10 +91,20 @@ class RestProtocol {
|
|
|
89
91
|
}
|
|
90
92
|
throw new Error(`Idempotency Failed: Item with ${keyField}='${value}' exists but could not be retrieved.`);
|
|
91
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Translates CLI commands to REST API logic according to Mikrotik v7 Docs.
|
|
96
|
+
* Mappings:
|
|
97
|
+
* - /print -> GET
|
|
98
|
+
* - /add -> PUT (Fixed: Docs say PUT is for Create)
|
|
99
|
+
* - /set -> PATCH
|
|
100
|
+
* - /remove -> DELETE
|
|
101
|
+
* - others -> POST (Universal)
|
|
102
|
+
*/
|
|
92
103
|
translateToRest(cmd, params) {
|
|
93
104
|
let cleanPath = cmd.replace(/\/+$/, '');
|
|
94
|
-
let method = 'POST';
|
|
105
|
+
let method = 'POST'; // Default safe verb
|
|
95
106
|
let body = { ...params };
|
|
107
|
+
// CASE: PRINT (Read)
|
|
96
108
|
if (cleanPath.endsWith('/print')) {
|
|
97
109
|
if (Object.keys(params).length > 0) {
|
|
98
110
|
method = 'POST';
|
|
@@ -117,10 +129,12 @@ class RestProtocol {
|
|
|
117
129
|
body = undefined;
|
|
118
130
|
}
|
|
119
131
|
}
|
|
132
|
+
// CASE: ADD (Create) -> PUT
|
|
120
133
|
else if (cleanPath.endsWith('/add')) {
|
|
121
134
|
method = 'PUT';
|
|
122
135
|
cleanPath = cleanPath.replace(/\/add$/, '');
|
|
123
136
|
}
|
|
137
|
+
// CASE: SET (Update) -> PATCH
|
|
124
138
|
else if (cleanPath.endsWith('/set')) {
|
|
125
139
|
method = 'PATCH';
|
|
126
140
|
cleanPath = cleanPath.replace(/\/set$/, '');
|
|
@@ -132,6 +146,7 @@ class RestProtocol {
|
|
|
132
146
|
throw new Error("RestProtocol: To use 'set' (PATCH), you must provide the '.id' parameter.");
|
|
133
147
|
}
|
|
134
148
|
}
|
|
149
|
+
// CASE: REMOVE (Delete) -> DELETE
|
|
135
150
|
else if (cleanPath.endsWith('/remove')) {
|
|
136
151
|
method = 'DELETE';
|
|
137
152
|
cleanPath = cleanPath.replace(/\/remove$/, '');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RestProtocol.js","sourceRoot":"","sources":["../../src/core/RestProtocol.ts"],"names":[],"mappings":";;;AAAA,yCAAoC;AACpC,mCAA2C;AAgB3C,MAAa,YAAY;IAMrB,YAAY,OAAqB;QAC7B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,GAAG,CAAC;QACjC,IAAI,CAAC,OAAO,GAAG,WAAW,OAAO,CAAC,IAAI,IAAI,IAAI,OAAO,CAAC;QACtD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC;QACxC,IAAI,CAAC,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAE/F,IAAI,CAAC,UAAU,GAAG,IAAI,cAAK,CAAC;YACxB,OAAO,EAAE;gBACL,kBAAkB,EAAE,CAAC,OAAO,CAAC,QAAQ;aACxC;SACJ,CAAC,CAAC;IACP,CAAC;IAEM,KAAK,CAAC,OAAO;QAChB,IAAI,CAAC;YACD,MAAM,IAAI,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;YAC7C,OAAO,IAAI,CAAC;QAChB,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YAClB,IAAI,KAAK,CAAC,UAAU;gBAAE,MAAM,KAAK,CAAC;YAClC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;YACjE,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAE,KAAK,CAAC,KAAa,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;YACjE,MAAM,IAAI,KAAK,CAAC,mCAAmC,MAAM,WAAW,IAAI,WAAW,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACvG,CAAC;IACL,CAAC;IAEM,KAAK;QACR,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;IAC9B,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,GAAW,EAAE,SAA8B,EAAE,EAAE,OAAyB;QACzF,MAAM,EAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAC,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAE9D,MAAM,YAAY,GAAQ;YACtB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACL,eAAe,EAAE,IAAI,CAAC,UAAU;gBAChC,cAAc,EAAE,kBAAkB;aACrC;YACD,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;SAC5C,CAAC;QAEF,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACxC,YAAY,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC7C,CAAC;QAED,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;YAEhD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACf,MAAM,QAAQ,GAAG,MAAM,mBAAQ,CAAC,YAAY,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"RestProtocol.js","sourceRoot":"","sources":["../../src/core/RestProtocol.ts"],"names":[],"mappings":"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"}
|
package/dist/core/RosError.d.ts
CHANGED
|
@@ -6,13 +6,28 @@ export declare class RosError extends Error {
|
|
|
6
6
|
readonly isRosError = true;
|
|
7
7
|
readonly timestamp: Date;
|
|
8
8
|
constructor(status: number, detail: string, command: string, rawResponse?: any | undefined);
|
|
9
|
+
/** Resource missing (404) */
|
|
9
10
|
get isNotFound(): boolean;
|
|
11
|
+
/** Authentication failure (401) */
|
|
10
12
|
get isAuthError(): boolean;
|
|
13
|
+
/** Permissions failure (403) */
|
|
11
14
|
get isPermissionError(): boolean;
|
|
15
|
+
/** * Critical: Detects if the error is due to a duplicate item.
|
|
16
|
+
* Useful for Idempotency logic.
|
|
17
|
+
*/
|
|
12
18
|
get isDuplicate(): boolean;
|
|
19
|
+
/** Rate Limiting hit (429) */
|
|
13
20
|
get isRateLimit(): boolean;
|
|
21
|
+
/** True if the error is likely temporary (503, 429, etc) */
|
|
14
22
|
get isRetryable(): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* static factory to parse a Fetch Response and throw/return a typed RosError.
|
|
25
|
+
* Encapsulates all the "dirty" JSON parsing logic from RouterOS.
|
|
26
|
+
*/
|
|
15
27
|
static fromResponse(response: Response, command: string): Promise<RosError>;
|
|
28
|
+
/**
|
|
29
|
+
* Custom generic JSON representation for logging systems (DataDog, Sentry, etc.)
|
|
30
|
+
*/
|
|
16
31
|
toJSON(): {
|
|
17
32
|
errorType: string;
|
|
18
33
|
status: number;
|
package/dist/core/RosError.js
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RosError = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* core/RosError.ts
|
|
6
|
+
*
|
|
7
|
+
* Sophisticated Error wrapper for RouterOS interactions.
|
|
8
|
+
* Features:
|
|
9
|
+
* - Semantic Getters (isNotFound, isAuthError, etc.)
|
|
10
|
+
* - Static Factory for parsing raw Fetch Responses.
|
|
11
|
+
* - JSON serialization support.
|
|
12
|
+
*/
|
|
4
13
|
const HttpConstants_1 = require("./HttpConstants");
|
|
5
14
|
class RosError extends Error {
|
|
6
|
-
constructor(status, detail, command, rawResponse
|
|
15
|
+
constructor(status, detail, command, rawResponse // Saves the full JSON body for deep debugging
|
|
16
|
+
) {
|
|
17
|
+
// Construct a highly readable log message
|
|
18
|
+
// Format: "RouterOS [404] Not Found (/ip/address/print) -> Item *99 not found"
|
|
7
19
|
const prefix = HttpConstants_1.RosHttpMessages[status] || 'Unknown Error';
|
|
8
20
|
super(`RouterOS [${status}] ${prefix} (${command}) -> ${detail}`);
|
|
9
21
|
this.status = status;
|
|
@@ -13,40 +25,60 @@ class RosError extends Error {
|
|
|
13
25
|
this.isRosError = true;
|
|
14
26
|
this.name = 'RosError';
|
|
15
27
|
this.timestamp = new Date();
|
|
28
|
+
// Fix for extending built-ins in TypeScript/ES6
|
|
16
29
|
Object.setPrototypeOf(this, RosError.prototype);
|
|
17
30
|
}
|
|
31
|
+
// --- 1. Surgical Precision Getters ---
|
|
32
|
+
/** Resource missing (404) */
|
|
18
33
|
get isNotFound() {
|
|
19
34
|
return this.status === HttpConstants_1.RosHttpStatus.NOT_FOUND;
|
|
20
35
|
}
|
|
36
|
+
/** Authentication failure (401) */
|
|
21
37
|
get isAuthError() {
|
|
22
38
|
return this.status === HttpConstants_1.RosHttpStatus.UNAUTHORIZED;
|
|
23
39
|
}
|
|
40
|
+
/** Permissions failure (403) */
|
|
24
41
|
get isPermissionError() {
|
|
25
42
|
return this.status === HttpConstants_1.RosHttpStatus.FORBIDDEN;
|
|
26
43
|
}
|
|
44
|
+
/** * Critical: Detects if the error is due to a duplicate item.
|
|
45
|
+
* Useful for Idempotency logic.
|
|
46
|
+
*/
|
|
27
47
|
get isDuplicate() {
|
|
28
48
|
if (this.status !== HttpConstants_1.RosHttpStatus.BAD_REQUEST)
|
|
29
49
|
return false;
|
|
30
50
|
const msg = this.detail.toLowerCase();
|
|
31
51
|
return msg.includes('already exists') || msg.includes('already have');
|
|
32
52
|
}
|
|
53
|
+
/** Rate Limiting hit (429) */
|
|
33
54
|
get isRateLimit() {
|
|
34
55
|
return this.status === HttpConstants_1.RosHttpStatus.TOO_MANY_REQUESTS;
|
|
35
56
|
}
|
|
57
|
+
/** True if the error is likely temporary (503, 429, etc) */
|
|
36
58
|
get isRetryable() {
|
|
59
|
+
// We import the logic from HttpConstants to keep it DRY
|
|
60
|
+
// (Assuming you exported the helper function, otherwise implement logic here)
|
|
37
61
|
return [429, 503, 504, 502].includes(this.status);
|
|
38
62
|
}
|
|
63
|
+
// --- 2. Factory Method (The Logic Cleaner) ---
|
|
64
|
+
/**
|
|
65
|
+
* static factory to parse a Fetch Response and throw/return a typed RosError.
|
|
66
|
+
* Encapsulates all the "dirty" JSON parsing logic from RouterOS.
|
|
67
|
+
*/
|
|
39
68
|
static async fromResponse(response, command) {
|
|
40
69
|
const status = response.status;
|
|
41
70
|
let detail = response.statusText;
|
|
42
71
|
let rawBody = null;
|
|
43
72
|
try {
|
|
44
73
|
const text = await response.text();
|
|
74
|
+
// Try parsing JSON
|
|
45
75
|
try {
|
|
46
76
|
rawBody = JSON.parse(text);
|
|
77
|
+
// RouterOS usually puts the error in 'detail' or 'message'
|
|
47
78
|
detail = rawBody.detail || rawBody.message || text;
|
|
48
79
|
}
|
|
49
80
|
catch {
|
|
81
|
+
// If not JSON, use the raw text (e.g. HTML from a proxy)
|
|
50
82
|
detail = text || detail;
|
|
51
83
|
}
|
|
52
84
|
}
|
|
@@ -55,6 +87,9 @@ class RosError extends Error {
|
|
|
55
87
|
}
|
|
56
88
|
return new RosError(status, detail, command, rawBody);
|
|
57
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Custom generic JSON representation for logging systems (DataDog, Sentry, etc.)
|
|
92
|
+
*/
|
|
58
93
|
toJSON() {
|
|
59
94
|
return {
|
|
60
95
|
errorType: 'RosError',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RosError.js","sourceRoot":"","sources":["../../src/core/RosError.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"RosError.js","sourceRoot":"","sources":["../../src/core/RosError.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RosProtocol.ts
|
|
3
|
+
* * This module is the "mathematical heart" of the library.
|
|
4
|
+
* It strictly handles the encoding and decoding of packet lengths
|
|
5
|
+
* according to MikroTik's proprietary standard.
|
|
6
|
+
* * Refactored and adapted from:
|
|
7
|
+
* - node-routeros/src/connector/Transmitter.ts
|
|
8
|
+
* - node-routeros/src/connector/Receiver.ts
|
|
9
|
+
*/
|
|
1
10
|
export declare class RosProtocol {
|
|
11
|
+
/**
|
|
12
|
+
* Converts a string (command) into a Buffer ready to be sent over the socket.
|
|
13
|
+
* Includes the variable Length Encoding calculation.
|
|
14
|
+
* * @param str The command or parameter (e.g., "/ip/address/print" or "=disabled=yes")
|
|
15
|
+
*/
|
|
2
16
|
static encodeSentence(str: string): Buffer;
|
|
17
|
+
/**
|
|
18
|
+
* Attempts to read the length of the next packet in the buffer.
|
|
19
|
+
* Refactored from Receiver.ts
|
|
20
|
+
* * @param buffer The raw data buffer received from the socket
|
|
21
|
+
* @returns An object containing the message length and the header byte size,
|
|
22
|
+
* or NULL if there is not enough data yet.
|
|
23
|
+
*/
|
|
3
24
|
static decodeLength(buffer: Buffer): {
|
|
4
25
|
length: number;
|
|
5
26
|
byteLength: number;
|
package/dist/core/RosProtocol.js
CHANGED
|
@@ -1,23 +1,45 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* RosProtocol.ts
|
|
4
|
+
* * This module is the "mathematical heart" of the library.
|
|
5
|
+
* It strictly handles the encoding and decoding of packet lengths
|
|
6
|
+
* according to MikroTik's proprietary standard.
|
|
7
|
+
* * Refactored and adapted from:
|
|
8
|
+
* - node-routeros/src/connector/Transmitter.ts
|
|
9
|
+
* - node-routeros/src/connector/Receiver.ts
|
|
10
|
+
*/
|
|
2
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
12
|
exports.RosProtocol = void 0;
|
|
4
13
|
class RosProtocol {
|
|
14
|
+
/**
|
|
15
|
+
* Converts a string (command) into a Buffer ready to be sent over the socket.
|
|
16
|
+
* Includes the variable Length Encoding calculation.
|
|
17
|
+
* * @param str The command or parameter (e.g., "/ip/address/print" or "=disabled=yes")
|
|
18
|
+
*/
|
|
5
19
|
static encodeSentence(str) {
|
|
20
|
+
// Convert String to Bytes (Native UTF-8)
|
|
21
|
+
// Note: The legacy library used 'win1252' via iconv-lite.
|
|
22
|
+
// In 2025/26 and RouterOS v7, UTF-8 is preferable and requires no external dependencies.
|
|
6
23
|
const encoded = Buffer.from(str, 'utf8');
|
|
7
24
|
const len = encoded.length;
|
|
8
25
|
let offset = 0;
|
|
9
26
|
let header;
|
|
27
|
+
// Calculate how many bytes are needed to specify the length.
|
|
28
|
+
// This logic is adopted directly from Transmitter.ts logic.
|
|
10
29
|
if (len < 0x80) {
|
|
30
|
+
// 1 byte for length
|
|
11
31
|
header = Buffer.alloc(1);
|
|
12
32
|
header[offset++] = len;
|
|
13
33
|
}
|
|
14
34
|
else if (len < 0x4000) {
|
|
35
|
+
// 2 bytes
|
|
15
36
|
header = Buffer.alloc(2);
|
|
16
37
|
const lenBytes = len | 0x8000;
|
|
17
38
|
header[offset++] = (lenBytes >> 8) & 0xff;
|
|
18
39
|
header[offset++] = lenBytes & 0xff;
|
|
19
40
|
}
|
|
20
41
|
else if (len < 0x200000) {
|
|
42
|
+
// 3 bytes
|
|
21
43
|
header = Buffer.alloc(3);
|
|
22
44
|
const lenBytes = len | 0xc00000;
|
|
23
45
|
header[offset++] = (lenBytes >> 16) & 0xff;
|
|
@@ -25,6 +47,7 @@ class RosProtocol {
|
|
|
25
47
|
header[offset++] = lenBytes & 0xff;
|
|
26
48
|
}
|
|
27
49
|
else if (len < 0x10000000) {
|
|
50
|
+
// 4 bytes
|
|
28
51
|
header = Buffer.alloc(4);
|
|
29
52
|
const lenBytes = len | 0xe0000000;
|
|
30
53
|
header[offset++] = (lenBytes >> 24) & 0xff;
|
|
@@ -33,6 +56,7 @@ class RosProtocol {
|
|
|
33
56
|
header[offset++] = lenBytes & 0xff;
|
|
34
57
|
}
|
|
35
58
|
else {
|
|
59
|
+
// 5 bytes (Extreme cases for giant payloads)
|
|
36
60
|
header = Buffer.alloc(5);
|
|
37
61
|
header[offset++] = 0xf0;
|
|
38
62
|
header[offset++] = (len >> 24) & 0xff;
|
|
@@ -40,39 +64,54 @@ class RosProtocol {
|
|
|
40
64
|
header[offset++] = (len >> 8) & 0xff;
|
|
41
65
|
header[offset++] = len & 0xff;
|
|
42
66
|
}
|
|
67
|
+
// 3. Concatenate the header (length) with the body (command)
|
|
43
68
|
return Buffer.concat([header, encoded]);
|
|
44
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Attempts to read the length of the next packet in the buffer.
|
|
72
|
+
* Refactored from Receiver.ts
|
|
73
|
+
* * @param buffer The raw data buffer received from the socket
|
|
74
|
+
* @returns An object containing the message length and the header byte size,
|
|
75
|
+
* or NULL if there is not enough data yet.
|
|
76
|
+
*/
|
|
45
77
|
static decodeLength(buffer) {
|
|
46
78
|
if (buffer.length === 0)
|
|
47
79
|
return null;
|
|
48
80
|
const b = buffer[0];
|
|
81
|
+
// Inverse bitwise logic to detect which length scheme was used
|
|
82
|
+
// Case 1 byte (0xxxxxxx)
|
|
49
83
|
if ((b & 0x80) === 0x00) {
|
|
50
84
|
return { length: b, byteLength: 1 };
|
|
51
85
|
}
|
|
86
|
+
// Case 2 bytes (10xxxxxx ...)
|
|
52
87
|
if ((b & 0xC0) === 0x80) {
|
|
53
88
|
if (buffer.length < 2)
|
|
54
|
-
return null;
|
|
89
|
+
return null; // Missing data
|
|
55
90
|
const len = ((b & 0x3F) << 8) | buffer[1];
|
|
56
91
|
return { length: len, byteLength: 2 };
|
|
57
92
|
}
|
|
93
|
+
// Case 3 bytes (110xxxxx ...)
|
|
58
94
|
if ((b & 0xE0) === 0xC0) {
|
|
59
95
|
if (buffer.length < 3)
|
|
60
96
|
return null;
|
|
61
97
|
const len = ((b & 0x1F) << 16) | (buffer[1] << 8) | buffer[2];
|
|
62
98
|
return { length: len, byteLength: 3 };
|
|
63
99
|
}
|
|
100
|
+
// Case 4 bytes (1110xxxx ...)
|
|
64
101
|
if ((b & 0xF0) === 0xE0) {
|
|
65
102
|
if (buffer.length < 4)
|
|
66
103
|
return null;
|
|
67
104
|
const len = ((b & 0x0F) << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
|
|
68
105
|
return { length: len, byteLength: 4 };
|
|
69
106
|
}
|
|
107
|
+
// Case 5 bytes (11110000 ...)
|
|
70
108
|
if (b === 0xF0) {
|
|
71
109
|
if (buffer.length < 5)
|
|
72
110
|
return null;
|
|
73
111
|
const len = (buffer[1] << 24) | (buffer[2] << 16) | (buffer[3] << 8) | buffer[4];
|
|
74
112
|
return { length: len, byteLength: 5 };
|
|
75
113
|
}
|
|
114
|
+
// If we reach here, the initial byte is invalid according to the protocol
|
|
76
115
|
return null;
|
|
77
116
|
}
|
|
78
117
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RosProtocol.js","sourceRoot":"","sources":["../../src/core/RosProtocol.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"RosProtocol.js","sourceRoot":"","sources":["../../src/core/RosProtocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,55 @@
|
|
|
1
1
|
import { MikrotikClient } from '../client/MikrotikClient';
|
|
2
|
+
/**
|
|
3
|
+
* SchemaMapper
|
|
4
|
+
* * Responsible for the "Auto-Topology Discovery" feature.
|
|
5
|
+
* * It automatically detects the router's capabilities (Version, Architecture, Packages)
|
|
6
|
+
* upon connection and builds a map of "Smart Paths".
|
|
7
|
+
* * This allows the developer to use abstract aliases (like 'wifi') without worrying
|
|
8
|
+
* if the underlying router is running RouterOS v6 (legacy) or v7 (modern).
|
|
9
|
+
*/
|
|
2
10
|
export declare class SchemaMapper {
|
|
11
|
+
/** Full RouterOS version string (e.g., "7.12.1" or "6.49.10") */
|
|
3
12
|
version: string;
|
|
13
|
+
/** The major version number (e.g., 7 or 6). Vital for logic branching. */
|
|
4
14
|
majorVersion: number;
|
|
15
|
+
/** The hardware model name (e.g., "CCR2004-1G-12S+2XS") */
|
|
5
16
|
boardName: string;
|
|
17
|
+
/** The CPU architecture (e.g., "arm64", "mipsbe", "tile") */
|
|
6
18
|
architecture: string;
|
|
19
|
+
/** Flag indicating if the router has wireless capabilities installed */
|
|
7
20
|
hasWireless: boolean;
|
|
21
|
+
/** Internal dictionary to store path translations */
|
|
8
22
|
private pathAliases;
|
|
23
|
+
/**
|
|
24
|
+
* Scans the connected router to determine its specifications and capabilities.
|
|
25
|
+
* This method should be called immediately after a successful login.
|
|
26
|
+
* * @param client The active MikrotikClient instance.
|
|
27
|
+
*/
|
|
9
28
|
load(client: MikrotikClient): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* defines the translation rules for aliases based on the RouterOS version.
|
|
31
|
+
*/
|
|
10
32
|
private buildPathMap;
|
|
33
|
+
/**
|
|
34
|
+
* Resolves an abstract path alias to the concrete RouterOS path.
|
|
35
|
+
* * @example
|
|
36
|
+
* // On RouterOS v7:
|
|
37
|
+
* schema.resolve('wifi') // Returns "/interface/wifi"
|
|
38
|
+
* * // On RouterOS v6:
|
|
39
|
+
* schema.resolve('wifi') // Returns "/interface/wireless"
|
|
40
|
+
* * // Non-aliases are returned as is:
|
|
41
|
+
* schema.resolve('/ip/address') // Returns "/ip/address"
|
|
42
|
+
* * @param path The path alias or full path to resolve.
|
|
43
|
+
* @returns The actual menu path for the connected router.
|
|
44
|
+
*/
|
|
11
45
|
resolve(path: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* Helper to determine if the connected router is running RouterOS v7 or higher.
|
|
48
|
+
* Useful for conditional logic in developer scripts.
|
|
49
|
+
*/
|
|
12
50
|
isV7(): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Helper to check if the router is running on ARM architecture (Performance tuning).
|
|
53
|
+
*/
|
|
13
54
|
isArm(): boolean;
|
|
14
55
|
}
|
|
@@ -1,25 +1,49 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SchemaMapper = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* SchemaMapper
|
|
6
|
+
* * Responsible for the "Auto-Topology Discovery" feature.
|
|
7
|
+
* * It automatically detects the router's capabilities (Version, Architecture, Packages)
|
|
8
|
+
* upon connection and builds a map of "Smart Paths".
|
|
9
|
+
* * This allows the developer to use abstract aliases (like 'wifi') without worrying
|
|
10
|
+
* if the underlying router is running RouterOS v6 (legacy) or v7 (modern).
|
|
11
|
+
*/
|
|
4
12
|
class SchemaMapper {
|
|
5
13
|
constructor() {
|
|
14
|
+
/** Full RouterOS version string (e.g., "7.12.1" or "6.49.10") */
|
|
6
15
|
this.version = '';
|
|
16
|
+
/** The major version number (e.g., 7 or 6). Vital for logic branching. */
|
|
7
17
|
this.majorVersion = 0;
|
|
18
|
+
/** The hardware model name (e.g., "CCR2004-1G-12S+2XS") */
|
|
8
19
|
this.boardName = '';
|
|
20
|
+
/** The CPU architecture (e.g., "arm64", "mipsbe", "tile") */
|
|
9
21
|
this.architecture = '';
|
|
22
|
+
/** Flag indicating if the router has wireless capabilities installed */
|
|
10
23
|
this.hasWireless = false;
|
|
24
|
+
/** Internal dictionary to store path translations */
|
|
11
25
|
this.pathAliases = {};
|
|
12
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Scans the connected router to determine its specifications and capabilities.
|
|
29
|
+
* This method should be called immediately after a successful login.
|
|
30
|
+
* * @param client The active MikrotikClient instance.
|
|
31
|
+
*/
|
|
13
32
|
async load(client) {
|
|
14
33
|
try {
|
|
34
|
+
// 1. Fetch vital system information
|
|
35
|
+
// We use the raw command to avoid circular dependency logic here
|
|
15
36
|
const resourceCollection = await client.command('/system/resource').print();
|
|
16
37
|
const resource = resourceCollection.first();
|
|
17
38
|
if (resource) {
|
|
18
39
|
this.version = resource.version || '0.0.0';
|
|
40
|
+
// Extract the first number from "7.12.1" -> 7
|
|
19
41
|
this.majorVersion = parseInt(this.version.split('.')[0]);
|
|
20
42
|
this.boardName = resource['board-name'] || 'unknown';
|
|
21
43
|
this.architecture = resource['architecture-name'] || 'unknown';
|
|
22
44
|
}
|
|
45
|
+
// 2. Detect installed packages (to determine if WiFi/IoT/Container features exist)
|
|
46
|
+
// Wrapped in try-catch because read-only users might not have permission to view packages.
|
|
23
47
|
try {
|
|
24
48
|
const packages = await client.command('/system/package').print();
|
|
25
49
|
this.hasWireless = packages.filter(p => p.name === 'wireless' || p.name === 'wifiwave2' || p.name === 'wifi').count() > 0;
|
|
@@ -27,36 +51,67 @@ class SchemaMapper {
|
|
|
27
51
|
catch (e) {
|
|
28
52
|
console.warn('[SchemaMapper] Warning: Could not scan packages (Permission denied?). Defaulting features to false.');
|
|
29
53
|
}
|
|
54
|
+
// 3. Build the Smart Path Map based on the detected version
|
|
30
55
|
this.buildPathMap();
|
|
31
56
|
console.log(`Schema Loaded: RouterOS v${this.version} (${this.architecture}) on ${this.boardName}`);
|
|
32
57
|
}
|
|
33
58
|
catch (error) {
|
|
34
59
|
console.error('Schema Discovery Failed:', error);
|
|
60
|
+
// Fallback: Assume v6 if detection fails to prevent crashes
|
|
35
61
|
this.majorVersion = 6;
|
|
36
62
|
this.buildPathMap();
|
|
37
63
|
}
|
|
38
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* defines the translation rules for aliases based on the RouterOS version.
|
|
67
|
+
*/
|
|
39
68
|
buildPathMap() {
|
|
40
69
|
if (this.majorVersion >= 7) {
|
|
70
|
+
// --- MODERN ROUTEROS v7 MAPPINGS ---
|
|
71
|
+
// WiFi: v7 uses the new 'wifi' package (formerly wifiwave2) or legacy wireless
|
|
72
|
+
// We default to the modern interface, but this could be refined further.
|
|
41
73
|
this.pathAliases['wifi'] = '/interface/wifi';
|
|
74
|
+
// Routing protocols structure changed significantly in v7
|
|
42
75
|
this.pathAliases['bgp'] = '/routing/bgp/connection';
|
|
43
76
|
this.pathAliases['ospf'] = '/routing/ospf/instance';
|
|
44
|
-
this.pathAliases['firewall'] = '/ip/firewall/filter';
|
|
77
|
+
this.pathAliases['firewall'] = '/ip/firewall/filter'; // Standard
|
|
45
78
|
}
|
|
46
79
|
else {
|
|
80
|
+
// --- LEGACY ROUTEROS v6 MAPPINGS ---
|
|
47
81
|
this.pathAliases['wifi'] = '/interface/wireless';
|
|
48
82
|
this.pathAliases['bgp'] = '/routing/bgp/peer';
|
|
49
|
-
this.pathAliases['ospf'] = '/routing/ospf/instance';
|
|
83
|
+
this.pathAliases['ospf'] = '/routing/ospf/instance'; // OSPFv2 usually
|
|
50
84
|
this.pathAliases['firewall'] = '/ip/firewall/filter';
|
|
51
85
|
}
|
|
52
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Resolves an abstract path alias to the concrete RouterOS path.
|
|
89
|
+
* * @example
|
|
90
|
+
* // On RouterOS v7:
|
|
91
|
+
* schema.resolve('wifi') // Returns "/interface/wifi"
|
|
92
|
+
* * // On RouterOS v6:
|
|
93
|
+
* schema.resolve('wifi') // Returns "/interface/wireless"
|
|
94
|
+
* * // Non-aliases are returned as is:
|
|
95
|
+
* schema.resolve('/ip/address') // Returns "/ip/address"
|
|
96
|
+
* * @param path The path alias or full path to resolve.
|
|
97
|
+
* @returns The actual menu path for the connected router.
|
|
98
|
+
*/
|
|
53
99
|
resolve(path) {
|
|
100
|
+
// Remove leading slash for dictionary lookup consistency
|
|
54
101
|
const cleanPath = path.startsWith('/') ? path.substring(1) : path;
|
|
102
|
+
// Return the mapped alias if it exists, otherwise return the original path
|
|
55
103
|
return this.pathAliases[cleanPath] || path;
|
|
56
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Helper to determine if the connected router is running RouterOS v7 or higher.
|
|
107
|
+
* Useful for conditional logic in developer scripts.
|
|
108
|
+
*/
|
|
57
109
|
isV7() {
|
|
58
110
|
return this.majorVersion >= 7;
|
|
59
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Helper to check if the router is running on ARM architecture (Performance tuning).
|
|
114
|
+
*/
|
|
60
115
|
isArm() {
|
|
61
116
|
return this.architecture === 'arm' || this.architecture === 'arm64';
|
|
62
117
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SchemaMapper.js","sourceRoot":"","sources":["../../src/core/SchemaMapper.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"SchemaMapper.js","sourceRoot":"","sources":["../../src/core/SchemaMapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,23 +1,57 @@
|
|
|
1
1
|
import { EventEmitter } from 'events';
|
|
2
2
|
import { Buffer } from 'buffer';
|
|
3
|
+
/**
|
|
4
|
+
* Configuration options for the Socket Client.
|
|
5
|
+
*/
|
|
3
6
|
export interface SocketClientOptions {
|
|
7
|
+
/** Target IP address or Hostname */
|
|
4
8
|
host: string;
|
|
9
|
+
/** Target Port (default: 8728 for plain, 8729 for SSL) */
|
|
5
10
|
port: number;
|
|
11
|
+
/** Connection timeout in seconds (default: 10) */
|
|
6
12
|
timeout?: number;
|
|
13
|
+
/** Enable SSL/TLS encryption (default: false) */
|
|
7
14
|
useTLS?: boolean;
|
|
15
|
+
/** If true, allows self-signed certificates (default: false) */
|
|
8
16
|
rejectUnauthorized?: boolean;
|
|
17
|
+
/** Enable TCP Keep-Alive to prevent idle disconnects (default: true) */
|
|
9
18
|
keepAlive?: boolean;
|
|
10
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Low-level TCP/TLS Client.
|
|
22
|
+
* Responsibilities:
|
|
23
|
+
* 1. Transport Layer: Decides between 'net' (Plain) and 'tls' (Secure).
|
|
24
|
+
* 2. Event Handling: Manages socket errors, closures, and timeouts.
|
|
25
|
+
* 3. Framing: Buffers incoming raw bytes and splits them into valid MikroTik words.
|
|
26
|
+
*/
|
|
11
27
|
export declare class SocketClient extends EventEmitter {
|
|
12
28
|
private socket;
|
|
13
29
|
private options;
|
|
14
30
|
connected: boolean;
|
|
15
31
|
private receiveBuffer;
|
|
16
32
|
constructor(options: SocketClientOptions);
|
|
33
|
+
/**
|
|
34
|
+
* Establishes the connection to the router.
|
|
35
|
+
* Supports both Plain TCP and TLS based on configuration.
|
|
36
|
+
* @returns Promise that resolves when the connection is fully established.
|
|
37
|
+
*/
|
|
17
38
|
connect(): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Writes raw bytes to the socket stream.
|
|
41
|
+
*/
|
|
18
42
|
write(data: Buffer): void;
|
|
43
|
+
/**
|
|
44
|
+
* Gracefully closes the connection.
|
|
45
|
+
*/
|
|
19
46
|
close(): void;
|
|
47
|
+
/**
|
|
48
|
+
* Forcefully destroys the connection.
|
|
49
|
+
*/
|
|
20
50
|
destroy(): void;
|
|
21
51
|
private cleanup;
|
|
52
|
+
/**
|
|
53
|
+
* CORE LOGIC: TCP Framing.
|
|
54
|
+
* Extracts valid MikroTik "Words" from the TCP stream.
|
|
55
|
+
*/
|
|
22
56
|
private handleDataChunk;
|
|
23
57
|
}
|