rosinterface 1.1.0 → 1.2.0
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/README.md +269 -1
- package/dist/cli/SchemaInferrer.d.ts +4 -0
- package/dist/cli/SchemaInferrer.js +42 -0
- package/dist/cli/SchemaInferrer.js.map +1 -0
- package/dist/cli/generate.d.ts +1 -0
- package/dist/cli/generate.js +139 -0
- package/dist/cli/generate.js.map +1 -0
- package/dist/client/CommandBuilder.js.map +1 -1
- package/dist/client/MikrotikClient.d.ts +7 -2
- package/dist/client/MikrotikClient.js +16 -1
- package/dist/client/MikrotikClient.js.map +1 -1
- package/dist/client/MikrotikTransaction.d.ts +12 -0
- package/dist/client/MikrotikTransaction.js +52 -0
- package/dist/client/MikrotikTransaction.js.map +1 -0
- package/dist/client/SnapshotSubscription.d.ts +35 -0
- package/dist/client/SnapshotSubscription.js +143 -0
- package/dist/client/SnapshotSubscription.js.map +1 -0
- package/dist/features/LiveCollection.d.ts +6 -5
- package/dist/features/LiveCollection.js +21 -14
- package/dist/features/LiveCollection.js.map +1 -1
- package/dist/features/PrometheusExporter.js +1 -1
- package/dist/features/PrometheusExporter.js.map +1 -1
- package/dist/generated/ISecret.d.ts +14 -0
- package/dist/generated/ISecret.js +3 -0
- package/dist/generated/ISecret.js.map +1 -0
- package/dist/test_library.js +15 -11
- package/dist/test_library.js.map +1 -1
- package/dist/utils/MikrotikCollection.d.ts +7 -2
- package/dist/utils/MikrotikCollection.js +37 -6
- package/dist/utils/MikrotikCollection.js.map +1 -1
- package/package.json +11 -6
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# RosInterface
|
|
1
|
+
# RosInterface v1.2
|
|
2
2
|
|
|
3
3
|
> **High-Performance RouterOS Automation A modern TypeScript and JavasScript Library for MikroTik interactions.**
|
|
4
4
|
> Built with Reactive Streaming (onSnapshot), Circuit Breakers for fault tolerance, and an Offline Queue system.
|
|
@@ -53,6 +53,15 @@ It focuses on **connection stability**, **router hardware protection**, and **ef
|
|
|
53
53
|
- **Fluent API**
|
|
54
54
|
Chainable, expressive syntax for clean and maintainable automation code.
|
|
55
55
|
|
|
56
|
+
- **CLI Code Generator**
|
|
57
|
+
Auto-generate TypeScript interfaces from your live router. No more guessing field names.
|
|
58
|
+
|
|
59
|
+
- **Differential Updates (onDiff)**
|
|
60
|
+
Receive atomic added, modified, and removed events instead of full arrays. Optimized for high-performance UIs.
|
|
61
|
+
|
|
62
|
+
- **Intelligent Throttling**
|
|
63
|
+
Control the flow of real-time data with "Leading + Trailing Edge" strategies.
|
|
64
|
+
|
|
56
65
|
---
|
|
57
66
|
|
|
58
67
|
|
|
@@ -239,6 +248,123 @@ const result = await client.getMetrics('/interface', metricsDef);
|
|
|
239
248
|
console.log(result);
|
|
240
249
|
```
|
|
241
250
|
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
#### 8. Type-Safe Realtime Stream (onDiff)
|
|
254
|
+
|
|
255
|
+
```ts
|
|
256
|
+
client.collection('/ppp/secret')
|
|
257
|
+
.onSnapshot((data) => {
|
|
258
|
+
// Check if we are in Diff Mode
|
|
259
|
+
if ('added' in data) {
|
|
260
|
+
// TypeScript automatically infers that 'data' is a SnapshotDiff!
|
|
261
|
+
|
|
262
|
+
// Added items
|
|
263
|
+
data.added.forEach(secret => console.log('New:', secret.name));
|
|
264
|
+
|
|
265
|
+
// Modified items
|
|
266
|
+
data.modified.forEach(secret => console.log('Modified:', secret.name));
|
|
267
|
+
|
|
268
|
+
// Removed items
|
|
269
|
+
data.removed.forEach(secret => console.log('Removed:', secret.name));
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
// If execution reaches here, .onDiff() was NOT used, so 'data' is a standard Array
|
|
273
|
+
console.log('Full list size:', data.length);
|
|
274
|
+
}
|
|
275
|
+
}).onDiff();
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
#### 9. Data Transformers With Print
|
|
280
|
+
|
|
281
|
+
```ts
|
|
282
|
+
// EXAMPLE 1: Using .toMap() for O(1) Lookup
|
|
283
|
+
// Scenario: Quickly finding a specific user by name without looping through an array.
|
|
284
|
+
client.command('/ppp/secret').print().then(result => {
|
|
285
|
+
// Transform the array into a Dictionary (Map) indexed by 'name'
|
|
286
|
+
const usersMap = result.toMap('name');
|
|
287
|
+
|
|
288
|
+
// Instant access! No .find() required.
|
|
289
|
+
const john = usersMap['john_doe'];
|
|
290
|
+
if (john) {
|
|
291
|
+
console.log(`User Found: ${john.profile}`);
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
// EXAMPLE 2: Using .toGrouped() for Reporting
|
|
296
|
+
// Scenario: Grouping active connections by their service profile (e.g. 10mb, 50mb plans).
|
|
297
|
+
client.command('/ppp/active').print().then(result => {
|
|
298
|
+
// Group users by the 'profile' property
|
|
299
|
+
const byProfile = result.toGrouped('profile');
|
|
300
|
+
|
|
301
|
+
console.log('--- Connected Users Summary ---');
|
|
302
|
+
Object.keys(byProfile).forEach(profile => {
|
|
303
|
+
console.log(`Plan ${profile}: ${byProfile[profile].length} users`);
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// EXAMPLE 3: Using .toPages() for Pagination
|
|
308
|
+
// Scenario: Displaying a large list of logs in a frontend table, page by page.
|
|
309
|
+
const PAGE_SIZE = 50;
|
|
310
|
+
const CURRENT_PAGE = 1;
|
|
311
|
+
|
|
312
|
+
client.command('/log').print().then(result => {
|
|
313
|
+
// Get only the items for the first page
|
|
314
|
+
const pageData = result.toPages(CURRENT_PAGE, PAGE_SIZE);
|
|
315
|
+
|
|
316
|
+
console.log(`Showing ${pageData.length} logs (Page ${CURRENT_PAGE})`);
|
|
317
|
+
pageData.forEach(log => console.log(`[${log.time}] ${log.message}`));
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
#### 10. CLI Codegen - Automatic Type Generation
|
|
324
|
+
|
|
325
|
+
> **OPTION A: Using .env file (Recommended for Security)**
|
|
326
|
+
> Create a .env file with MIKROTIK_HOST, MIKROTIK_USER, MIKROTIK_PASS
|
|
327
|
+
> Run the command:
|
|
328
|
+
> > npm run codegen -- -p /ppp/secret -n ISecret
|
|
329
|
+
>
|
|
330
|
+
> OPTION B: Manual Configuration (Quick Testing / CI)
|
|
331
|
+
> Pass connection details directly via flags. Use double quotes for passwords with special chars.
|
|
332
|
+
> >npm run codegen -- -p /ppp/secret -n ISecret --host ROUTER_IP --user admin --pass "secret123" --port 8728
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
```ts
|
|
336
|
+
// Usage A: Type-Safe Reading (Auto-complete for properties)
|
|
337
|
+
// Pass the interface <ISecret> to .collection() or .command()
|
|
338
|
+
client.collection<ISecret>('/ppp/secret').onSnapshot((diff) => {
|
|
339
|
+
if ('added' in diff) {
|
|
340
|
+
diff.added.forEach(secret => {
|
|
341
|
+
// TypeScript knows 'profile' and 'service' exist!
|
|
342
|
+
// If you type "secret.", your IDE will show all available fields.
|
|
343
|
+
console.log(`New User: ${secret.name} (Plan: ${secret.profile})`);
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
// Usage B: Type-Safe Writing (Validation for .add)
|
|
349
|
+
async function createSecureUser() {
|
|
350
|
+
const api = client.command<ISecret>('/ppp/secret');
|
|
351
|
+
|
|
352
|
+
// TypeScript ensures you only pass valid fields defined in ISecret.
|
|
353
|
+
// It prevents typos like 'passwrod' or using invalid profile names if unions were generated.
|
|
354
|
+
await api.add({
|
|
355
|
+
name: 'vip_user',
|
|
356
|
+
password: 'secure_password',
|
|
357
|
+
profile: 'default',
|
|
358
|
+
service: 'pppoe',
|
|
359
|
+
disabled: false
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
|
|
242
368
|
---
|
|
243
369
|
|
|
244
370
|
## Documentación en Español
|
|
@@ -277,6 +403,18 @@ Su objetivo es garantizar **estabilidad de conexión**, **protección del hardwa
|
|
|
277
403
|
- **API Fluida**
|
|
278
404
|
Sintaxis encadenable y clara.
|
|
279
405
|
|
|
406
|
+
- **Generador de código CLI**
|
|
407
|
+
|
|
408
|
+
Genere automáticamente interfaces TypeScript desde su enrutador en vivo. Olvídese de adivinar los nombres de los campos.
|
|
409
|
+
|
|
410
|
+
- **Actualizaciones diferenciales (onDiff)**
|
|
411
|
+
|
|
412
|
+
Reciba eventos atómicos de adición, modificación y eliminación en lugar de matrices completas. Optimizado para interfaces de usuario de alto rendimiento.
|
|
413
|
+
|
|
414
|
+
- **Limitación inteligente**
|
|
415
|
+
|
|
416
|
+
Controle el flujo de datos en tiempo real con estrategias de vanguardia y vanguardia.
|
|
417
|
+
|
|
280
418
|
---
|
|
281
419
|
|
|
282
420
|
### ✨ Consideraciones Importantes
|
|
@@ -458,7 +596,137 @@ const resultado = await client.getMetrics('/interface', metricasDef);
|
|
|
458
596
|
console.log(resultado);
|
|
459
597
|
```
|
|
460
598
|
|
|
599
|
+
#### 8. Transmisión en tiempo real con seguridad de tipos (onDiff)
|
|
600
|
+
|
|
601
|
+
```ts
|
|
602
|
+
client.collection('/ppp/secret') // Sin <T>, se asume Record<string, any>
|
|
603
|
+
.onSnapshot((data) => {
|
|
604
|
+
// Verificar si estamos en modo Diff
|
|
605
|
+
if ('added' in data) {
|
|
606
|
+
// TypeScript infiere automáticamente que 'data' es un SnapshotDiff
|
|
607
|
+
|
|
608
|
+
// Elementos Agregados
|
|
609
|
+
data.added.forEach(secret => console.log('Nuevo:', secret.name));
|
|
610
|
+
|
|
611
|
+
// Elementos Modificados
|
|
612
|
+
data.modified.forEach(secret => console.log('Editado:', secret.name));
|
|
613
|
+
|
|
614
|
+
// Elementos Eliminados
|
|
615
|
+
data.removed.forEach(secret => console.log('Borrado:', secret.name));
|
|
616
|
+
}
|
|
617
|
+
else {
|
|
618
|
+
// Si entra aquí, es que NO se usó .onDiff() y es un Array normal
|
|
619
|
+
console.log('Tamaño lista completa:', data.length);
|
|
620
|
+
}
|
|
621
|
+
})
|
|
622
|
+
.onDiff(); // <--- IMPORTANTE: Activa el modo diferencial
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
#### 9. Tranformadores de tipo de datos con Print
|
|
627
|
+
|
|
628
|
+
```ts
|
|
629
|
+
// EJEMPLO 1: Usando .toMap() para Búsqueda Instantánea O(1)
|
|
630
|
+
// Escenario: Encontrar rápidamente un usuario específico por nombre sin recorrer un array.
|
|
631
|
+
client.command('/ppp/secret').print().then(result => {
|
|
632
|
+
// Transformar el array en un Diccionario (Map) indexado por 'name'
|
|
633
|
+
const usersMap = result.toMap('name');
|
|
634
|
+
|
|
635
|
+
// ¡Acceso instantáneo! No se requiere .find().
|
|
636
|
+
const john = usersMap['john_doe'];
|
|
637
|
+
if (john) {
|
|
638
|
+
console.log(`Usuario Encontrado: ${john.profile}`);
|
|
639
|
+
}
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
// EJEMPLO 2: Usando .toGrouped() para Reportes
|
|
644
|
+
// Escenario: Agrupar conexiones activas por su perfil de servicio (ej. planes de 10mb, 50mb).
|
|
645
|
+
client.command('/ppp/active').print().then(result => {
|
|
646
|
+
// Agrupar usuarios por la propiedad 'profile'
|
|
647
|
+
const byProfile = result.toGrouped('profile');
|
|
648
|
+
|
|
649
|
+
console.log('--- Resumen de Usuarios Conectados ---');
|
|
650
|
+
Object.keys(byProfile).forEach(profile => {
|
|
651
|
+
console.log(`Plan ${profile}: ${byProfile[profile].length} usuarios`);
|
|
652
|
+
});
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
// EJEMPLO 3: Usando .toPages() para Paginación
|
|
657
|
+
// Escenario: Mostrar una lista grande de logs en una tabla frontend, página por página.
|
|
658
|
+
const PAGE_SIZE = 50;
|
|
659
|
+
const CURRENT_PAGE = 1;
|
|
660
|
+
|
|
661
|
+
client.command('/log').print().then(result => {
|
|
662
|
+
// Obtener solo los elementos para la primera página
|
|
663
|
+
const pageData = result.toPages(CURRENT_PAGE, PAGE_SIZE);
|
|
664
|
+
|
|
665
|
+
console.log(`Mostrando ${pageData.length} logs (Página ${CURRENT_PAGE})`);
|
|
666
|
+
pageData.forEach(log => console.log(`[${log.time}] ${log.message}`));
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
|
|
672
|
+
#### 10. CLI Codegen - Generación Automática de Tipos
|
|
673
|
+
|
|
674
|
+
> **OPCIÓN A: Usando archivo .env (Recomendado por Seguridad)**
|
|
675
|
+
> Crea un archivo .env con MIKROTIK_HOST, MIKROTIK_USER, MIKROTIK_PASS
|
|
676
|
+
> Ejecuta el comando:
|
|
677
|
+
> > npm run codegen -- -p /ppp/secret -n ISecret
|
|
678
|
+
>
|
|
679
|
+
> OPCIÓN B: Configuración Manual (Pruebas Rápidas / CI)
|
|
680
|
+
> PPasa los detalles de conexión directamente mediante banderas. Usa comillas dobles para contraseñas con caracteres especiales.
|
|
681
|
+
> >npm run codegen -- -p /ppp/secret -n ISecret --host ROUTER_IP --user admin --pass "secret123" --port 8728
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
```ts
|
|
685
|
+
// Uso A: Lectura con Tipado Seguro (Auto-completado para propiedades)
|
|
686
|
+
// Pasar la interfaz <ISecret> a .collection() o .command()
|
|
687
|
+
client.collection<ISecret>('/ppp/secret').onSnapshot((diff) => {
|
|
688
|
+
if ('added' in diff) {
|
|
689
|
+
diff.added.forEach(secret => {
|
|
690
|
+
// ¡TypeScript sabe que 'profile' y 'service' existen!
|
|
691
|
+
// Si escribes "secret.", tu IDE mostrará todos los campos disponibles.
|
|
692
|
+
console.log(`Nuevo Usuario: ${secret.name} (Plan: ${secret.profile})`);
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
// Uso B: Escritura con Tipado Seguro (Validación para .add)
|
|
698
|
+
async function createSecureUser() {
|
|
699
|
+
const api = client.command<ISecret>('/ppp/secret');
|
|
700
|
+
|
|
701
|
+
// TypeScript asegura que solo pases campos válidos definidos en ISecret.
|
|
702
|
+
// Previene errores tipográficos como 'passwrod' o usar nombres de perfil inválidos si se generaron uniones.
|
|
703
|
+
await api.add({
|
|
704
|
+
name: 'vip_user',
|
|
705
|
+
password: 'secure_password',
|
|
706
|
+
profile: 'default',
|
|
707
|
+
service: 'pppoe',
|
|
708
|
+
disabled: false
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
|
|
715
|
+
---
|
|
716
|
+
|
|
717
|
+
## Author's Note / Nota del Autor
|
|
718
|
+
|
|
719
|
+
**English**
|
|
720
|
+
>Thank you for choosing RosInterface for your automation needs. I built this library to solve the real-world challenges of managing MikroTik networks at scale. I hope it helps you build your systems.
|
|
721
|
+
|
|
722
|
+
Happy Coding!
|
|
723
|
+
— **McBlockier**
|
|
724
|
+
|
|
725
|
+
**Español**
|
|
726
|
+
> Gracias por elegir **RosInterface** para tus necesidades de automatización. Construí esta librería para resolver los desafíos reales de administrar redes MikroTik a escala. Espero te ayude mucho a construir tus sistemas .
|
|
461
727
|
|
|
728
|
+
¡Feliz Código!
|
|
729
|
+
— **McBlockier**
|
|
462
730
|
|
|
463
731
|
|
|
464
732
|
---
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SchemaInferrer = void 0;
|
|
4
|
+
class SchemaInferrer {
|
|
5
|
+
static generateInterface(interfaceName, dataSample) {
|
|
6
|
+
const fieldStats = {};
|
|
7
|
+
dataSample.forEach(item => {
|
|
8
|
+
Object.keys(item).forEach(key => {
|
|
9
|
+
if (!fieldStats[key])
|
|
10
|
+
fieldStats[key] = new Set();
|
|
11
|
+
fieldStats[key].add(String(item[key]));
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
const lines = [];
|
|
15
|
+
lines.push(`export interface ${interfaceName} {`);
|
|
16
|
+
Object.keys(fieldStats).sort().forEach(key => {
|
|
17
|
+
const values = Array.from(fieldStats[key]);
|
|
18
|
+
const type = this.inferType(key, values);
|
|
19
|
+
const isOptional = true;
|
|
20
|
+
const propName = key.includes('-') ? `'${key}'` : key;
|
|
21
|
+
lines.push(` /** Sample values: ${values.slice(0, 3).join(', ')}... */`);
|
|
22
|
+
lines.push(` ${propName}${isOptional ? '?' : ''}: ${type};`);
|
|
23
|
+
});
|
|
24
|
+
lines.push(`}`);
|
|
25
|
+
return lines.join('\n');
|
|
26
|
+
}
|
|
27
|
+
static inferType(key, values) {
|
|
28
|
+
const isBoolean = values.every(v => ['true', 'false', 'yes', 'no'].includes(v.toLowerCase()));
|
|
29
|
+
if (isBoolean)
|
|
30
|
+
return 'boolean | string';
|
|
31
|
+
const isNumber = values.every(v => v === '' || !isNaN(Number(v)));
|
|
32
|
+
if (isNumber && values.length > 0)
|
|
33
|
+
return 'number | string';
|
|
34
|
+
if (values.length > 0 && values.length < 10 && !isNumber) {
|
|
35
|
+
const union = values.map(v => `'${v}'`).join(' | ');
|
|
36
|
+
return `${union} | string`;
|
|
37
|
+
}
|
|
38
|
+
return 'string';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.SchemaInferrer = SchemaInferrer;
|
|
42
|
+
//# sourceMappingURL=SchemaInferrer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaInferrer.js","sourceRoot":"","sources":["../../src/cli/SchemaInferrer.ts"],"names":[],"mappings":";;;AAGA,MAAa,cAAc;IAKhB,MAAM,CAAC,iBAAiB,CAAC,aAAqB,EAAE,UAAiC;QACpF,MAAM,UAAU,GAAgC,EAAE,CAAC;QAGnD,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YACtB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;gBAC5B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;oBAAE,UAAU,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;gBAClD,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC3C,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAGH,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,oBAAoB,aAAa,IAAI,CAAC,CAAC;QAElD,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YACzC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;YAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAGzC,MAAM,UAAU,GAAG,IAAI,CAAC;YACxB,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;YAEtD,KAAK,CAAC,IAAI,CAAC,0BAA0B,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC5E,KAAK,CAAC,IAAI,CAAC,OAAO,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,GAAG,CAAC,CAAC;QACpE,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAKO,MAAM,CAAC,SAAS,CAAC,GAAW,EAAE,MAAgB;QAElD,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QAC9F,IAAI,SAAS;YAAE,OAAO,kBAAkB,CAAC;QAIzC,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClE,IAAI,QAAQ,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,iBAAiB,CAAC;QAK5D,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACvD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACpD,OAAO,GAAG,KAAK,WAAW,CAAC;QAC/B,CAAC;QAGD,OAAO,QAAQ,CAAC;IACpB,CAAC;CACJ;AA5DD,wCA4DC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const commander_1 = require("commander");
|
|
40
|
+
const MikrotikClient_1 = require("../client/MikrotikClient");
|
|
41
|
+
const SchemaInferrer_1 = require("./SchemaInferrer");
|
|
42
|
+
const fs = __importStar(require("fs-extra"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
45
|
+
const ora_1 = __importDefault(require("ora"));
|
|
46
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
47
|
+
dotenv_1.default.config();
|
|
48
|
+
const program = new commander_1.Command();
|
|
49
|
+
program
|
|
50
|
+
.name('ros-codegen')
|
|
51
|
+
.description('Generates TypeScript interfaces from your live MikroTik router')
|
|
52
|
+
.version('1.2.0')
|
|
53
|
+
.requiredOption('-p, --path <menu>', 'MikroTik Menu Path (e.g. /ppp/secret)')
|
|
54
|
+
.requiredOption('-n, --name <interface>', 'Name of the output Interface (e.g. PPPSecret)')
|
|
55
|
+
.option('-o, --output <dir>', 'Output directory', './src/generated')
|
|
56
|
+
.option('--host <host>', 'Router Host/IP')
|
|
57
|
+
.option('--user <user>', 'Router Username')
|
|
58
|
+
.option('--pass <password>', 'Router Password')
|
|
59
|
+
.option('--port <port>', 'Router API Port')
|
|
60
|
+
.option('--tls', 'Use TLS (SSL) connection', false)
|
|
61
|
+
.action(async (options) => {
|
|
62
|
+
const host = options.host || process.env.MIKROTIK_HOST;
|
|
63
|
+
const user = options.user || process.env.MIKROTIK_USER;
|
|
64
|
+
const password = options.pass || process.env.MIKROTIK_PASS;
|
|
65
|
+
const useTLS = options.tls || process.env.MIKROTIK_USE_TLS === 'true';
|
|
66
|
+
let port;
|
|
67
|
+
if (options.port) {
|
|
68
|
+
port = parseInt(options.port, 10);
|
|
69
|
+
}
|
|
70
|
+
else if (process.env.MIKROTIK_PORT) {
|
|
71
|
+
port = parseInt(process.env.MIKROTIK_PORT, 10);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
port = useTLS ? 8729 : 8728;
|
|
75
|
+
}
|
|
76
|
+
if (!host || !user || !password) {
|
|
77
|
+
console.error(chalk_1.default.red('Error: Missing credentials.'));
|
|
78
|
+
console.error(chalk_1.default.yellow('You must provide credentials via .env file OR CLI flags.'));
|
|
79
|
+
console.log(chalk_1.default.gray(`
|
|
80
|
+
Usage Example:
|
|
81
|
+
$ npm run codegen -- -p /ppp/secret -n ISecret --host 192.168.88.1 --user admin --pass admin
|
|
82
|
+
`));
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
const spinner = (0, ora_1.default)(`Connecting to ${host}:${port}...`).start();
|
|
86
|
+
const client = new MikrotikClient_1.MikrotikClient({
|
|
87
|
+
host: host,
|
|
88
|
+
user: user,
|
|
89
|
+
password: password,
|
|
90
|
+
port: port,
|
|
91
|
+
useTLS: useTLS,
|
|
92
|
+
allowInsecureConfig: true
|
|
93
|
+
});
|
|
94
|
+
try {
|
|
95
|
+
await client.connect();
|
|
96
|
+
spinner.text = `Fetching schema from ${options.path}...`;
|
|
97
|
+
const data = await client.write(`${options.path}/print`);
|
|
98
|
+
if (data.length === 0) {
|
|
99
|
+
spinner.warn(chalk_1.default.yellow(' Warning: No data found in this menu. Generated interface will be empty or generic.'));
|
|
100
|
+
}
|
|
101
|
+
spinner.text = 'Inferring Types & Generating Code...';
|
|
102
|
+
const tsCode = SchemaInferrer_1.SchemaInferrer.generateInterface(options.name, data);
|
|
103
|
+
const fileContent = `
|
|
104
|
+
/**
|
|
105
|
+
* AUTO-GENERATED FILE - DO NOT EDIT MANUALLY
|
|
106
|
+
* Generated by rosinterface-cli v1.2.0
|
|
107
|
+
* Source: ${options.path}
|
|
108
|
+
* Date: ${new Date().toISOString()}
|
|
109
|
+
*/
|
|
110
|
+
|
|
111
|
+
${tsCode}
|
|
112
|
+
`;
|
|
113
|
+
const outputDir = path.resolve(options.output);
|
|
114
|
+
await fs.ensureDir(outputDir);
|
|
115
|
+
const filePath = path.join(outputDir, `${options.name}.ts`);
|
|
116
|
+
await fs.writeFile(filePath, fileContent);
|
|
117
|
+
spinner.succeed(chalk_1.default.green(`Successfully generated ${options.name}.ts in ${options.output}`));
|
|
118
|
+
console.log(chalk_1.default.gray('\nPreview:'));
|
|
119
|
+
console.log(chalk_1.default.cyan(tsCode.split('\n').slice(0, 15).join('\n') + '\n...'));
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
spinner.fail(chalk_1.default.red('Generation Failed'));
|
|
123
|
+
if (error.code === 'ECONNREFUSED') {
|
|
124
|
+
console.error(chalk_1.default.red(`Could not connect to ${host}:${port}. Check IP/Port.`));
|
|
125
|
+
}
|
|
126
|
+
else if (error.message && error.message.includes('login')) {
|
|
127
|
+
console.error(chalk_1.default.red(`Authentication failed for user ${user}. Check password.`));
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
console.error(chalk_1.default.red(error.message));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
finally {
|
|
134
|
+
client.close();
|
|
135
|
+
process.exit(0);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
program.parse(process.argv);
|
|
139
|
+
//# sourceMappingURL=generate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/cli/generate.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommandBuilder.js","sourceRoot":"","sources":["../../src/client/CommandBuilder.ts"],"names":[],"mappings":";;;AACA,8CAAgD;AAChD,oEAAiE;AACjE,uDAAoD;AAgBpD,MAAa,cAAc;IAqBvB,YAAY,MAAsB,EAAE,QAAgB;QAhB5C,gBAAW,GAA2B,EAAE,CAAC;QACzC,aAAQ,GAAa,EAAE,CAAC;QAGxB,wBAAmB,GAAY,KAAK,CAAC;QAazC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAErB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,QAAQ,CAAC;QACrE,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1D,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC;IACL,CAAC;
|
|
1
|
+
{"version":3,"file":"CommandBuilder.js","sourceRoot":"","sources":["../../src/client/CommandBuilder.ts"],"names":[],"mappings":";;;AACA,8CAAgD;AAChD,oEAAiE;AACjE,uDAAoD;AAgBpD,MAAa,cAAc;IAqBvB,YAAY,MAAsB,EAAE,QAAgB;QAhB5C,gBAAW,GAA2B,EAAE,CAAC;QACzC,aAAQ,GAAa,EAAE,CAAC;QAGxB,wBAAmB,GAAY,KAAK,CAAC;QAazC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAErB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,QAAQ,CAAC;QACrE,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1D,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC;IACL,CAAC;IAmCM,KAAK,CAAC,GAAW,EAAE,KAAgC;QACtD,MAAM,QAAQ,GAAG,IAAA,sBAAY,EAAC,GAAG,CAAC,CAAC;QACnC,MAAM,cAAc,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC/C,IAAI,CAAC,WAAW,CAAC,IAAI,QAAQ,EAAE,CAAC,GAAG,cAAc,CAAC;QAClD,OAAO,IAAI,CAAC;IAChB,CAAC;IAmBM,WAAW,CAAC,GAAW;QAC1B,MAAM,QAAQ,GAAG,IAAA,sBAAY,EAAC,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,WAAW,CAAC,IAAI,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC;IAChB,CAAC;IAuBM,MAAM,CAAC,MAAgB;QAC1B,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAA,sBAAY,EAAC,CAAC,CAAC,CAAC,CAAC;QACrD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IAChB,CAAC;IAsBM,UAAU;QACb,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;QAChC,OAAO,IAAI,CAAC;IAChB,CAAC;IAwBM,KAAK,CAAC,MAAM,CAAC,QAAoB;QAEpC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClD,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,KAAY,CAAC,CAAC;QAClC,CAAC;QAED,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAgBM,KAAK,CAAC,OAAO,CAAC,QAAoB;QACrC,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC/C,OAAO,UAAU,CAAC,KAAK,EAAE,CAAC;IAC9B,CAAC;IAmDM,KAAK,CAAC,KAAK,CAAC,WAAiC;QAChD,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QACtC,MAAM,WAAW,GAAG,EAAE,GAAG,YAAY,EAAE,GAAG,WAAW,EAAE,CAAC;QAIxD,MAAM,IAAI,GAAI,IAAI,CAAC,MAAc,CAAC,OAAO,EAAE,IAAI,IAAI,SAAS,CAAC;QAC7D,MAAM,QAAQ,GAAG,GAAG,IAAI,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC;QAG3E,MAAM,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACvD,IAAI,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;YACxC,OAAO,IAAI,uCAAkB,CAAI,MAAM,CAAC,IAAI,CAAC,CAAC;QAClD,CAAC;QAGD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,QAAQ,EAAE,WAAW,CAAC,CAAC;QAG/E,cAAc,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE;YACpC,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc,CAAC,YAAY;SACpD,CAAC,CAAC;QAGH,IAAI,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI;YAAE,IAAI,CAAC,UAAU,EAAE,CAAC;QAE5C,OAAO,IAAI,uCAAkB,CAAI,OAAO,CAAC,CAAC;IAC9C,CAAC;IAKO,UAAU;QACd,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,cAAc,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC;YAC3D,IAAI,GAAG,GAAG,GAAG,CAAC,OAAO;gBAAE,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,CAAC;IACL,CAAC;IAaM,KAAK,CAAC,KAAK;QACd,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACtC,OAAO,UAAU,CAAC,KAAK,EAAE,CAAC;IAC9B,CAAC;IA+BM,KAAK,CAAC,GAAG,CAAC,IAAgB;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAGxC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACrB,2BAAY,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YAC7E,OAAO,gBAAgB,CAAC;QAC5B,CAAC;QAGD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,MAAM,EAAE,MAAM,CAAC,CAAC;QAGzE,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAG3B,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YACvE,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,EAAE,CAAC;IACd,CAAC;IAsBM,KAAK,CAAC,GAAG,CAAC,EAAU,EAAE,IAAgB;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAEnB,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACrB,2BAAY,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YAC7E,OAAO;QACX,CAAC;QAED,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,MAAM,EAAE,MAAM,CAAC,CAAC;QACxD,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC/B,CAAC;IAuBM,KAAK,CAAC,MAAM,CAAC,EAAqB;QACrC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAClD,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;QAE9B,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACrB,2BAAY,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YAChF,OAAO;QACX,CAAC;QAED,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,SAAS,EAAE,MAAM,CAAC,CAAC;QAC3D,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC/B,CAAC;IAiCM,MAAM,CAAC,QAA2B;QAErC,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,QAAQ,CAAC,CAAC;QAGzC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAGhC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAChD,IAAI,QAAQ,GAAG,GAAG,CAAC;YAGnB,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC3B,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACrC,CAAC;YAED,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;gBAE3B,KAAK,CAAC,IAAI,CAAC,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC,CAAC;YACxC,CAAC;iBAAM,CAAC;gBAEJ,KAAK,CAAC,IAAI,CAAC,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC,CAAC;YACxC,CAAC;QACL,CAAC;QAGD,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAGvB,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC1D,CAAC;IAwBM,aAAa,CAAC,QAA2B;QAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QACnC,MAAM,YAAY,GAA2B,EAAE,CAAC;QAGhD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YACnD,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YAC9D,YAAY,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC;QACnC,CAAC;QAED,IAAI,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7D,GAAG,GAAG,GAAG,GAAG,kBAAkB,CAAC;QACnC,CAAC;QAED,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;IAC3D,CAAC;IASO,mBAAmB;QACvB,MAAM,IAAI,GAAI,IAAI,CAAC,MAAc,CAAC,OAAO,EAAE,IAAI,IAAI,SAAS,CAAC;QAC7D,MAAM,MAAM,GAAG,GAAG,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAE1C,KAAK,MAAM,GAAG,IAAI,cAAc,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC;YACjD,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzB,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC1C,CAAC;QACL,CAAC;IACL,CAAC;IAEO,WAAW;QACf,IAAI,CAAC,IAAI,CAAC,mBAAmB;YAAE,OAAO,KAAK,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;IACrC,CAAC;IAEO,iBAAiB;QAErB,MAAM,MAAM,GAAI,IAAI,CAAC,MAAc,CAAC,QAAQ,CAAC,CAAC;QAC9C,OAAO,MAAM,IAAI,MAAM,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IAClD,CAAC;IAKO,SAAS;QACb,MAAM,MAAM,GAA2B,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAG/D,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAE3B,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAEO,WAAW,CAAC,KAAgC;QAChD,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;YAC7B,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;QAChC,CAAC;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IAEO,aAAa,CAAC,IAAS;QAC3B,MAAM,MAAM,GAAwB,EAAE,CAAC;QACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9C,MAAM,QAAQ,GAAG,IAAA,sBAAY,EAAC,GAAG,CAAC,CAAC;YACnC,MAAM,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,KAAY,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;;AAlkBL,wCAmkBC;AAjjBkB,yBAAU,GAAG,IAAI,GAAG,EAAsB,AAAhC,CAAiC;AAClC,2BAAY,GAAG,IAAI,AAAP,CAAQ"}
|
|
@@ -5,6 +5,8 @@ import { CircuitBreakerOptions } from '../core/CircuitBreaker';
|
|
|
5
5
|
import { FileManager } from '../features/FileManager';
|
|
6
6
|
import { MetricDefinition } from '../features/PrometheusExporter';
|
|
7
7
|
import { SnapshotCallback } from "../features/LiveCollection";
|
|
8
|
+
import { SnapshotSubscription } from "./SnapshotSubscription";
|
|
9
|
+
import { MikrotikTransaction } from "./MikrotikTransaction";
|
|
8
10
|
export interface MikrotikOptions extends SocketClientOptions {
|
|
9
11
|
user?: string;
|
|
10
12
|
password?: string;
|
|
@@ -19,6 +21,7 @@ export declare class MikrotikClient {
|
|
|
19
21
|
private socket;
|
|
20
22
|
private readonly options;
|
|
21
23
|
private readonly isConfigFromEnv;
|
|
24
|
+
private activeLiveCollections;
|
|
22
25
|
readonly files: FileManager;
|
|
23
26
|
readonly schema: SchemaMapper;
|
|
24
27
|
private rateLimiter;
|
|
@@ -30,9 +33,11 @@ export declare class MikrotikClient {
|
|
|
30
33
|
private printSeriousWarning;
|
|
31
34
|
close(): void;
|
|
32
35
|
command<T extends Record<string, any> = any>(path: string): CommandBuilder<T>;
|
|
33
|
-
|
|
36
|
+
transaction(): MikrotikTransaction;
|
|
37
|
+
collection<T extends Record<string, any> = Record<string, any>>(path: string): {
|
|
34
38
|
where: (key: string, value: string | number | boolean) => any;
|
|
35
|
-
|
|
39
|
+
print: () => Promise<import("..").MikrotikCollection<T>>;
|
|
40
|
+
onSnapshot: (callback: SnapshotCallback<T>) => SnapshotSubscription<T>;
|
|
36
41
|
};
|
|
37
42
|
getMetrics(path: string, metrics: MetricDefinition[], params?: Record<string, any>): Promise<string>;
|
|
38
43
|
write(command: string, parameters?: Record<string, string | boolean | number>): Promise<any[]>;
|
|
@@ -46,10 +46,12 @@ const CircuitBreaker_1 = require("../core/CircuitBreaker");
|
|
|
46
46
|
const FileManager_1 = require("../features/FileManager");
|
|
47
47
|
const PrometheusExporter_1 = require("../features/PrometheusExporter");
|
|
48
48
|
const LiveCollection_1 = require("../features/LiveCollection");
|
|
49
|
+
const MikrotikTransaction_1 = require("./MikrotikTransaction");
|
|
49
50
|
dotenv.config();
|
|
50
51
|
class MikrotikClient {
|
|
51
52
|
constructor(options) {
|
|
52
53
|
this.isConfigFromEnv = false;
|
|
54
|
+
this.activeLiveCollections = new Map();
|
|
53
55
|
this.schema = new SchemaMapper_1.SchemaMapper();
|
|
54
56
|
this.pendingCommands = new Map();
|
|
55
57
|
this.currentSentence = {};
|
|
@@ -104,6 +106,9 @@ class MikrotikClient {
|
|
|
104
106
|
const realPath = this.schema.resolve(path);
|
|
105
107
|
return new CommandBuilder_1.CommandBuilder(this, realPath);
|
|
106
108
|
}
|
|
109
|
+
transaction() {
|
|
110
|
+
return new MikrotikTransaction_1.MikrotikTransaction(this);
|
|
111
|
+
}
|
|
107
112
|
collection(path) {
|
|
108
113
|
const query = {};
|
|
109
114
|
const builder = {
|
|
@@ -111,8 +116,18 @@ class MikrotikClient {
|
|
|
111
116
|
query[key] = value;
|
|
112
117
|
return builder;
|
|
113
118
|
},
|
|
119
|
+
print: async () => {
|
|
120
|
+
const cmd = new CommandBuilder_1.CommandBuilder(this, path);
|
|
121
|
+
Object.keys(query).forEach(k => cmd.where(k, query[k]));
|
|
122
|
+
return cmd.print();
|
|
123
|
+
},
|
|
114
124
|
onSnapshot: (callback) => {
|
|
115
|
-
const
|
|
125
|
+
const cacheKey = `${path}:${JSON.stringify(query)}`;
|
|
126
|
+
let liveCol = this.activeLiveCollections.get(cacheKey);
|
|
127
|
+
if (!liveCol) {
|
|
128
|
+
liveCol = new LiveCollection_1.LiveCollection(this, path, query);
|
|
129
|
+
this.activeLiveCollections.set(cacheKey, liveCol);
|
|
130
|
+
}
|
|
116
131
|
return liveCol.onSnapshot(callback);
|
|
117
132
|
}
|
|
118
133
|
};
|