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.
Files changed (78) hide show
  1. package/dist/cli/Generate.js +20 -1
  2. package/dist/cli/Generate.js.map +1 -1
  3. package/dist/cli/SchemaInferrer.d.ts +9 -0
  4. package/dist/cli/SchemaInferrer.js +22 -3
  5. package/dist/cli/SchemaInferrer.js.map +1 -1
  6. package/dist/client/CommandBuilder.d.ts +337 -2
  7. package/dist/client/CommandBuilder.js +483 -15
  8. package/dist/client/CommandBuilder.js.map +1 -1
  9. package/dist/client/MikrotikClient.d.ts +349 -1
  10. package/dist/client/MikrotikClient.js +364 -1
  11. package/dist/client/MikrotikClient.js.map +1 -1
  12. package/dist/client/MikrotikPool.d.ts +30 -0
  13. package/dist/client/MikrotikPool.js +31 -1
  14. package/dist/client/MikrotikPool.js.map +1 -1
  15. package/dist/client/MikrotikSwarm.d.ts +167 -0
  16. package/dist/client/MikrotikSwarm.js +178 -1
  17. package/dist/client/MikrotikSwarm.js.map +1 -1
  18. package/dist/client/MikrotikTransaction.d.ts +27 -0
  19. package/dist/client/MikrotikTransaction.js +28 -0
  20. package/dist/client/MikrotikTransaction.js.map +1 -1
  21. package/dist/client/ResultParser.d.ts +19 -0
  22. package/dist/client/ResultParser.js +31 -0
  23. package/dist/client/ResultParser.js.map +1 -1
  24. package/dist/client/SnapshotSubscription.d.ts +139 -0
  25. package/dist/client/SnapshotSubscription.js +169 -0
  26. package/dist/client/SnapshotSubscription.js.map +1 -1
  27. package/dist/core/Auth.d.ts +31 -0
  28. package/dist/core/Auth.js +46 -1
  29. package/dist/core/Auth.js.map +1 -1
  30. package/dist/core/CircuitBreaker.d.ts +26 -0
  31. package/dist/core/CircuitBreaker.js +26 -0
  32. package/dist/core/CircuitBreaker.js.map +1 -1
  33. package/dist/core/HttpConstants.d.ts +29 -16
  34. package/dist/core/HttpConstants.js +23 -7
  35. package/dist/core/HttpConstants.js.map +1 -1
  36. package/dist/core/OfflineQueue.d.ts +16 -0
  37. package/dist/core/OfflineQueue.js +10 -0
  38. package/dist/core/OfflineQueue.js.map +1 -1
  39. package/dist/core/RateLimiter.d.ts +24 -0
  40. package/dist/core/RateLimiter.js +43 -7
  41. package/dist/core/RateLimiter.js.map +1 -1
  42. package/dist/core/RestProtocol.d.ts +9 -0
  43. package/dist/core/RestProtocol.js +16 -1
  44. package/dist/core/RestProtocol.js.map +1 -1
  45. package/dist/core/RosError.d.ts +15 -0
  46. package/dist/core/RosError.js +36 -1
  47. package/dist/core/RosError.js.map +1 -1
  48. package/dist/core/RosProtocol.d.ts +21 -0
  49. package/dist/core/RosProtocol.js +40 -1
  50. package/dist/core/RosProtocol.js.map +1 -1
  51. package/dist/core/SchemaMapper.d.ts +41 -0
  52. package/dist/core/SchemaMapper.js +57 -2
  53. package/dist/core/SchemaMapper.js.map +1 -1
  54. package/dist/core/SocketClient.d.ts +34 -0
  55. package/dist/core/SocketClient.js +51 -3
  56. package/dist/core/SocketClient.js.map +1 -1
  57. package/dist/features/FileManager.d.ts +50 -0
  58. package/dist/features/FileManager.js +72 -6
  59. package/dist/features/FileManager.js.map +1 -1
  60. package/dist/features/LiveCollection.d.ts +51 -0
  61. package/dist/features/LiveCollection.js +69 -0
  62. package/dist/features/LiveCollection.js.map +1 -1
  63. package/dist/features/PrometheusExporter.d.ts +18 -1
  64. package/dist/features/PrometheusExporter.js +21 -1
  65. package/dist/features/PrometheusExporter.js.map +1 -1
  66. package/dist/index.d.ts +66 -0
  67. package/dist/index.js +78 -0
  68. package/dist/index.js.map +1 -1
  69. package/dist/types/index.d.ts +4 -0
  70. package/dist/types/index.js +24 -0
  71. package/dist/types/index.js.map +1 -1
  72. package/dist/utils/Helpers.d.ts +16 -0
  73. package/dist/utils/Helpers.js +17 -1
  74. package/dist/utils/Helpers.js.map +1 -1
  75. package/dist/utils/MikrotikCollection.d.ts +85 -0
  76. package/dist/utils/MikrotikCollection.js +97 -1
  77. package/dist/utils/MikrotikCollection.js.map +1 -1
  78. package/package.json +2 -2
@@ -44,25 +44,37 @@ const path = __importStar(require("path"));
44
44
  const chalk_1 = __importDefault(require("chalk"));
45
45
  const ora_1 = __importDefault(require("ora"));
46
46
  const dotenv_1 = __importDefault(require("dotenv"));
47
+ // Load .env (if available)
47
48
  dotenv_1.default.config();
48
49
  const program = new commander_1.Command();
49
50
  program
50
51
  .name('ros-codegen')
51
52
  .description('Generates TypeScript interfaces from your live MikroTik router')
52
53
  .version('1.2.0')
54
+ // Mandatory Generation Params
53
55
  .requiredOption('-p, --path <menu>', 'MikroTik Menu Path (e.g. /ppp/secret)')
54
56
  .requiredOption('-n, --name <interface>', 'Name of the output Interface (e.g. PPPSecret)')
55
57
  .option('-o, --output <dir>', 'Output directory', './src/generated')
58
+ // Optional Connection Params (Overrides .env if provided)
56
59
  .option('--host <host>', 'Router Host/IP')
57
60
  .option('--user <user>', 'Router Username')
58
61
  .option('--pass <password>', 'Router Password')
59
62
  .option('--port <port>', 'Router API Port')
60
63
  .option('--tls', 'Use TLS (SSL) connection', false)
61
64
  .action(async (options) => {
65
+ // ==========================================
66
+ // 1. CREDENTIALS RESOLUTION STRATEGY
67
+ // Priority: CLI Flag > Environment Variable
68
+ // ==========================================
62
69
  const host = options.host || process.env.MIKROTIK_HOST;
63
70
  const user = options.user || process.env.MIKROTIK_USER;
64
71
  const password = options.pass || process.env.MIKROTIK_PASS;
72
+ // TLS Logic: Flag OR Env Var string 'true'
65
73
  const useTLS = options.tls || process.env.MIKROTIK_USE_TLS === 'true';
74
+ // Port Logic:
75
+ // 1. CLI Flag
76
+ // 2. Env Var
77
+ // 3. Default based on TLS (8729 vs 8728)
66
78
  let port;
67
79
  if (options.port) {
68
80
  port = parseInt(options.port, 10);
@@ -73,6 +85,7 @@ program
73
85
  else {
74
86
  port = useTLS ? 8729 : 8728;
75
87
  }
88
+ // Pre-flight Validation
76
89
  if (!host || !user || !password) {
77
90
  console.error(chalk_1.default.red('Error: Missing credentials.'));
78
91
  console.error(chalk_1.default.yellow('You must provide credentials via .env file OR CLI flags.'));
@@ -83,23 +96,27 @@ Usage Example:
83
96
  process.exit(1);
84
97
  }
85
98
  const spinner = (0, ora_1.default)(`Connecting to ${host}:${port}...`).start();
99
+ // Initialize Client
86
100
  const client = new MikrotikClient_1.MikrotikClient({
87
101
  host: host,
88
102
  user: user,
89
103
  password: password,
90
104
  port: port,
91
105
  useTLS: useTLS,
92
- allowInsecureConfig: true
106
+ allowInsecureConfig: true // Suppress warnings for CLI tool since hardcoding is expected here
93
107
  });
94
108
  try {
95
109
  await client.connect();
96
110
  spinner.text = `Fetching schema from ${options.path}...`;
111
+ // Fetch Real Data (The "Truth")
97
112
  const data = await client.write(`${options.path}/print`);
98
113
  if (data.length === 0) {
99
114
  spinner.warn(chalk_1.default.yellow(' Warning: No data found in this menu. Generated interface will be empty or generic.'));
100
115
  }
116
+ // Infer Schema
101
117
  spinner.text = 'Inferring Types & Generating Code...';
102
118
  const tsCode = SchemaInferrer_1.SchemaInferrer.generateInterface(options.name, data);
119
+ // Add File Header
103
120
  const fileContent = `
104
121
  /**
105
122
  * AUTO-GENERATED FILE - DO NOT EDIT MANUALLY
@@ -110,11 +127,13 @@ Usage Example:
110
127
 
111
128
  ${tsCode}
112
129
  `;
130
+ // Write to File
113
131
  const outputDir = path.resolve(options.output);
114
132
  await fs.ensureDir(outputDir);
115
133
  const filePath = path.join(outputDir, `${options.name}.ts`);
116
134
  await fs.writeFile(filePath, fileContent);
117
135
  spinner.succeed(chalk_1.default.green(`Successfully generated ${options.name}.ts in ${options.output}`));
136
+ // Show Preview
118
137
  console.log(chalk_1.default.gray('\nPreview:'));
119
138
  console.log(chalk_1.default.cyan(tsCode.split('\n').slice(0, 15).join('\n') + '\n...'));
120
139
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Generate.js","sourceRoot":"","sources":["../../src/cli/Generate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Generate.js","sourceRoot":"","sources":["../../src/cli/Generate.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,13 @@
1
+ /**
2
+ * Analyzes raw MikroTik data and infers TypeScript types.
3
+ */
1
4
  export declare class SchemaInferrer {
5
+ /**
6
+ * Main entry point: Generates the Interface string from raw data items.
7
+ */
2
8
  static generateInterface(interfaceName: string, dataSample: Record<string, any>[]): string;
9
+ /**
10
+ * Heuristic Engine to determine the best TypeScript type.
11
+ */
3
12
  private static inferType;
4
13
  }
@@ -1,9 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SchemaInferrer = void 0;
4
+ /**
5
+ * Analyzes raw MikroTik data and infers TypeScript types.
6
+ */
4
7
  class SchemaInferrer {
8
+ /**
9
+ * Main entry point: Generates the Interface string from raw data items.
10
+ */
5
11
  static generateInterface(interfaceName, dataSample) {
6
12
  const fieldStats = {};
13
+ // Collect all possible values for each field across the sample
7
14
  dataSample.forEach(item => {
8
15
  Object.keys(item).forEach(key => {
9
16
  if (!fieldStats[key])
@@ -11,30 +18,42 @@ class SchemaInferrer {
11
18
  fieldStats[key].add(String(item[key]));
12
19
  });
13
20
  });
21
+ // Build the Interface lines
14
22
  const lines = [];
15
23
  lines.push(`export interface ${interfaceName} {`);
16
24
  Object.keys(fieldStats).sort().forEach(key => {
17
25
  const values = Array.from(fieldStats[key]);
18
26
  const type = this.inferType(key, values);
27
+ // MikroTik fields are mostly optional as they depend on configuration
19
28
  const isOptional = true;
20
- const propName = key.includes('-') ? `'${key}'` : key;
29
+ const propName = key.includes('-') ? `'${key}'` : key; // Quote kebab-case
21
30
  lines.push(` /** Sample values: ${values.slice(0, 3).join(', ')}... */`);
22
31
  lines.push(` ${propName}${isOptional ? '?' : ''}: ${type};`);
23
32
  });
24
33
  lines.push(`}`);
25
34
  return lines.join('\n');
26
35
  }
36
+ /**
37
+ * Heuristic Engine to determine the best TypeScript type.
38
+ */
27
39
  static inferType(key, values) {
40
+ // Boolean Detection (true/false/yes/no)
28
41
  const isBoolean = values.every(v => ['true', 'false', 'yes', 'no'].includes(v.toLowerCase()));
29
42
  if (isBoolean)
30
- return 'boolean | string';
43
+ return 'boolean | string'; // string fallback for safety
44
+ // Number Detection
45
+ // Checks if all values look like numbers (ignoring empty strings)
31
46
  const isNumber = values.every(v => v === '' || !isNaN(Number(v)));
32
47
  if (isNumber && values.length > 0)
33
48
  return 'number | string';
49
+ // Enum / Union Type Detection
50
+ // If we see very few unique values (e.g. 'running' | 'stopped'), create a Union.
51
+ // Limit: Max 10 unique values to consider it an Enum.
34
52
  if (values.length > 0 && values.length < 10 && !isNumber) {
35
53
  const union = values.map(v => `'${v}'`).join(' | ');
36
- return `${union} | string`;
54
+ return `${union} | string`; // Append string to allow future values
37
55
  }
56
+ // Default
38
57
  return 'string';
39
58
  }
40
59
  }
@@ -1 +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"}
1
+ {"version":3,"file":"SchemaInferrer.js","sourceRoot":"","sources":["../../src/cli/SchemaInferrer.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,12 @@
1
1
  import { MikrotikClient, Subscription } from './MikrotikClient';
2
2
  import { MikrotikCollection } from '../utils/MikrotikCollection';
3
+ /**
4
+ * CommandBuilder.ts
5
+ * * The Fluent Interface Engine with Offline-First Capabilities.
6
+ * * Provides syntax sugar for constructing MikroTik commands.
7
+ * * Supports Real-Time Streaming, Persistent Queueing, Smart Caching,
8
+ * * and Enterprise REST Features (Idempotency, Projections).
9
+ */
3
10
  export declare class CommandBuilder<T extends Record<string, any>> {
4
11
  private readonly client;
5
12
  private readonly menuPath;
@@ -8,28 +15,356 @@ export declare class CommandBuilder<T extends Record<string, any>> {
8
15
  private propList;
9
16
  private _idempotent;
10
17
  private isPersistentRequest;
18
+ /**
19
+ * Short-lived cache to prevent read-spamming the router.
20
+ * TTL: 5 Seconds.
21
+ */
11
22
  private static queryCache;
12
23
  private static readonly CACHE_TTL_MS;
13
24
  constructor(client: MikrotikClient, menuPath: string);
25
+ /**
26
+ * Adds a **Query Filter** (Equal Match) to the command.
27
+ *
28
+ * This method appends a filter parameter (`?key=value`) to the API request.
29
+ * Only items matching this condition will be returned or affected.
30
+ *
31
+ * **Feature: Auto-Kebab Case**
32
+ * You can use standard JavaScript camelCase keys. They are automatically converted
33
+ * to MikroTik's kebab-case format.
34
+ * - Input: `macAddress` -> Output: `?mac-address=...`
35
+ * - Input: `rxByte` -> Output: `?rx-byte=...`
36
+ *
37
+ * @param key The field name to filter by (e.g., 'name', 'disabled', 'macAddress').
38
+ * @param value The value to match. Booleans are converted to 'true'/'false' strings.
39
+ * @returns The current builder instance for chaining.
40
+ *
41
+ * @example
42
+ * // Find a specific user by name
43
+ * client.command('/ppp/secret')
44
+ * .where('name', 'john_doe')
45
+ * .print();
46
+ *
47
+ * @example
48
+ * // Find all disabled interfaces (camelCase supported)
49
+ * client.command('/interface')
50
+ * .where('disabled', true) // Sends ?disabled=true
51
+ * .print();
52
+ */
14
53
  where(key: string, value: string | number | boolean): this;
54
+ /**
55
+ * Adds an **Existence Filter** to the command.
56
+ *
57
+ * Matches items where the specified key exists (is defined), regardless of its value.
58
+ * This is useful for finding items that have optional properties set.
59
+ * Corresponds to the MikroTik API syntax `?key=`.
60
+ *
61
+ * @param key The field name to check for existence.
62
+ * @returns The current builder instance for chaining.
63
+ *
64
+ * @example
65
+ * // Find all firewall rules that have a comment
66
+ * client.command('/ip/firewall/filter')
67
+ * .whereExists('comment')
68
+ * .print();
69
+ */
15
70
  whereExists(key: string): this;
71
+ /**
72
+ * **Field Projection (.select)**
73
+ *
74
+ * Restricts the fields returned by the router to a specific list.
75
+ * Using this method significantly reduces CPU load on the router and network bandwidth,
76
+ * especially when querying large tables like the routing table or logs.
77
+ * Corresponds to the MikroTik API argument `.proplist`.
78
+ *
79
+ * **Feature: Auto-Kebab Case**
80
+ * Inputs like `rxByte` are automatically converted to `rx-byte`.
81
+ *
82
+ * **Usage Levels:**
83
+ * * 1. **Novice:** Simple array of strings. `['name', 'address']`
84
+ * * 2. **Advanced (Surgical):** Type-safe list of keys ensuring they exist in interface T.
85
+ *
86
+ * @param fields An array of field names to retrieve (can be type-safe keys).
87
+ * @returns The current builder instance for chaining.
88
+ *
89
+ * @example
90
+ * // Get only the name and uptime of active users (ignoring traffic stats)
91
+ * const users = await client.command<PPPActive>('/ppp/active')
92
+ * .select(['name', 'uptime']) // optimized request
93
+ * .print();
94
+ */
16
95
  select(fields: (keyof T | string)[]): this;
96
+ /**
97
+ * **Enable Idempotency (.idempotent)**
98
+ *
99
+ * Flags the next operation to be **"Safe from Duplicates"**.
100
+ *
101
+ * * **Effect:** If you call `.add()` and the item already exists (based on a unique key like 'name'),
102
+ * the library will NOT throw an error. Instead, it will gracefully fetch and return the existing item.
103
+ * * **Requirement:** This is primarily supported in REST mode (v7+). In Socket mode, behavior depends on driver support.
104
+ *
105
+ * @returns The current builder instance for chaining.
106
+ * @example
107
+ * // Safe Create: Won't fail if 'vlan10' exists
108
+ * client.command('/interface/vlan')
109
+ * .idempotent()
110
+ * .add({ name: 'vlan10', 'vlan-id': 10 });
111
+ */
17
112
  idempotent(keyField?: string): this;
113
+ /**
114
+ * **Offline Tolerance Strategy**
115
+ *
116
+ * Marks the current command as **Persistent**.
117
+ * Normally, if the router is disconnected, a command fails immediately.
118
+ * With `.persistent()`, the command is added to an internal retry queue
119
+ * and will be executed automatically as soon as the connection is restored.
120
+ *
121
+ * **Use Case:** Critical background tasks (e.g., scheduled billing cuts) that
122
+ * must eventually run, even if the network is currently unstable.
123
+ *
124
+ * @returns The current builder instance.
125
+ * @example
126
+ * // Even if the router is down, this will run when it comes back up.
127
+ * client.command('/system/reboot').persistent().send();
128
+ */
18
129
  persistent(): this;
130
+ /**
131
+ * **Server-Side Search (Multi-Item)**
132
+ *
133
+ * Executes a search directly on the RouterOS CPU.
134
+ * Unlike client-side filtering, this method instructs the router to filter
135
+ * the data *before* sending it over the network.
136
+ *
137
+ * **Performance Note:**
138
+ * extremely efficient for large tables (like thousands of PPPoE secrets),
139
+ * as only the matching rows travel over the wire.
140
+ *
141
+ * @param criteria An object with key-value pairs to match (e.g., `{ disabled: 'true', profile: 'default' }`).
142
+ * @returns A `MikrotikCollection` containing only the matching items.
143
+ *
144
+ * @example
145
+ * // Fetch all users in the 'default' profile
146
+ * const users = await client.command('/ppp/secret').findBy({ profile: 'default' });
147
+ */
19
148
  findBy(criteria: Partial<T>): Promise<MikrotikCollection<T>>;
149
+ /**
150
+ * **Server-Side Search (Single-Item)**
151
+ *
152
+ * The most efficient way to retrieve a single specific resource.
153
+ * It applies the filters, executes the query, and returns the first result.
154
+ *
155
+ * @param criteria Unique identifiers (e.g., `{ name: 'admin' }` or `{ macAddress: '00:...' }`).
156
+ * @returns The found item object, or `null` if no match was found.
157
+ *
158
+ * @example
159
+ * // Find a specific interface by name
160
+ * const ether1 = await client.command('/interface').findOne({ name: 'ether1' });
161
+ * if (ether1) console.log(ether1.mac_address);
162
+ */
20
163
  findOne(criteria: Partial<T>): Promise<T | null>;
164
+ /**
165
+ * **Execution Terminator: Print with Caching**
166
+ *
167
+ * Finalizes the builder chain and sends the `print` command to the router.
168
+ *
169
+ * **Feature: Smart Caching (TTL 5s)**
170
+ * To prevent flooding the router with redundant read requests (e.g., multiple UI components
171
+ * asking for the same data), this method implements a **Read-Through Cache**.
172
+ * 1. **Cache Hit:** If the exact same query was made < 5 seconds ago, returns local data immediately.
173
+ * 2. **Cache Miss:** Fetches from the router, stores the result, and returns it.
174
+ *
175
+ * **Feature: Garbage Collection**
176
+ * Includes a probabilistic strategy (5% chance) to prune expired cache entries
177
+ * on every call to keep memory footprint low.
178
+ *
179
+ * @param extraParams Optional explicit parameters (e.g., `{ 'count-only': 'true' }`).
180
+ * @returns A `MikrotikCollection` (v1.2.0) equipped with pagination and transformation tools.
181
+ *
182
+ * @example
183
+ * // EXAMPLE 1: Standard Fetch (Basic Array)
184
+ * // Get all active PPPoE users as a simple array
185
+ * const users = await client.command('/ppp/active').print().then(c => c.toArray());
186
+ *
187
+ * @example
188
+ * // EXAMPLE 2: Pagination (Frontend Tables)
189
+ * // Get Page 2 of secrets, 25 items per page
190
+ * const page2 = await client.command('/ppp/secret')
191
+ * .where('disabled', 'false')
192
+ * .print()
193
+ * .then(c => c.toPages(2, 25));
194
+ *
195
+ * @example
196
+ * // EXAMPLE 3: High-Performance Lookup (O(1) Map)
197
+ * // Index users by name for instant access without looping
198
+ * const userMap = await client.command('/ppp/secret')
199
+ * .print()
200
+ * .then(c => c.toMap('name'));
201
+ *
202
+ * console.log(userMap['juan_perez']?.password); // Instant access!
203
+ *
204
+ * @example
205
+ * // EXAMPLE 4: Reporting (Grouping)
206
+ * // Group active connections by Service Type (pppoe vs ovpn)
207
+ * const report = await client.command('/ppp/active')
208
+ * .print()
209
+ * .then(c => c.toGrouped('service'));
210
+ *
211
+ * console.log(`PPPoE Users: ${report['pppoe']?.length || 0}`);
212
+ */
21
213
  print(extraParams?: Record<string, any>): Promise<MikrotikCollection<T>>;
214
+ /**
215
+ * Helper to clean expired cache entries to prevent memory leaks.
216
+ */
22
217
  private pruneCache;
218
+ /**
219
+ * **Execution Terminator: First Result**
220
+ *
221
+ * Syntactic sugar for fetching a list and retrieving only the first item.
222
+ * Useful when you know the query will return a single result or you only care about the top record.
223
+ *
224
+ * @returns The first item of type `T`, or `null` if the collection is empty.
225
+ * @example
226
+ * // Get the first active admin user
227
+ * const admin = await client.command('/user').where('group', 'full').first();
228
+ */
23
229
  first(): Promise<T | null>;
230
+ /**
231
+ * **Execution Terminator: Create Resource (ADD)**
232
+ *
233
+ * Sends an `/add` command to the router to create a new item.
234
+ *
235
+ * **Feature: Automatic Cache Invalidation**
236
+ * Upon success, this method automatically invalidates the local cache for this menu path.
237
+ * This guarantees that the next `.print()` call will fetch fresh data from the router,
238
+ * including the item you just created.
239
+ *
240
+ * **Feature: Offline Queueing**
241
+ * If the router is unreachable and `.persistent()` was used (or global offline mode is on),
242
+ * the command is saved to the `OfflineQueue` for later execution.
243
+ *
244
+ * **Feature: Idempotency**
245
+ * If `.idempotent()` was called, passes the flag to the client to safely handle duplicates.
246
+ *
247
+ * @param data The object containing the properties for the new item.
248
+ * @returns The MikroTik internal ID (e.g., `*1A`) of the created item, or `'QUEUED_OFFLINE'`.
249
+ *
250
+ * @example
251
+ * // Add a new firewall address list entry
252
+ * const id = await client.command('/ip/firewall/address-list').add({
253
+ * list: 'allowed_users',
254
+ * address: '192.168.88.50',
255
+ * comment: 'Added via API'
256
+ * });
257
+ */
24
258
  add(data: Partial<T>): Promise<string | T>;
259
+ /**
260
+ * **Get or Create (Syntactic Sugar)**
261
+ * * A shorthand method that enables idempotency and executes the add.
262
+ * * Semantically clearer for business logic "Ensure this exists".
263
+ * * @param data The data to ensure exists.
264
+ * @returns The Single item created or recovered.
265
+ */
25
266
  getOrCreate(data: Partial<T>): Promise<T>;
26
- set(id: string, data: Partial<T>): Promise<void>;
27
- remove(id: string | string[]): Promise<void>;
267
+ /**
268
+ * **Execution Terminator: Update Resource (SET)**
269
+ *
270
+ * Sends a `/set` command to modify an existing item.
271
+ *
272
+ * **Feature: Idempotency & Cache**
273
+ * Like `.add()`, this triggers cache invalidation. It also handles the tricky
274
+ * `.id` parameter requirement of MikroTik automatically.
275
+ *
276
+ * @param id The internal ID of the item (e.g., `*14`) or a unique name if supported by the menu.
277
+ * @param data An object containing ONLY the fields you want to change (Partial update).
278
+ *
279
+ * @example
280
+ * // Update a PPPoE secret's password
281
+ * await client.command('/ppp/secret').set('*1F', {
282
+ * password: 'new_secure_password',
283
+ * comment: 'Password changed on ' + new Date().toISOString()
284
+ * });
285
+ */
286
+ set(id: string, data: Partial<T>): Promise<T>;
287
+ /**
288
+ * **Execution Terminator: Delete Resource (REMOVE)**
289
+ *
290
+ * Sends a `/remove` command to delete one or more items.
291
+ *
292
+ * **Feature: Batch Deletion**
293
+ * You can pass an array of IDs to delete multiple items in a single API call,
294
+ * which is significantly faster than a loop of delete calls.
295
+ *
296
+ * @param id A single ID string (e.g., `*1A`) or an array of IDs.
297
+ *
298
+ * @example
299
+ * // Remove a single item
300
+ * await client.command('/queue/simple').remove('*A1');
301
+ *
302
+ * @example
303
+ * // Batch remove (Kick multiple active connections)
304
+ * const idsToKick = ['*8001', '*8002', '*8003'];
305
+ * await client.command('/ppp/active').remove(idsToKick);
306
+ */
307
+ remove(id: string | string[]): Promise<string[]>;
308
+ /**
309
+ * **Streaming Terminator: Data Watcher**
310
+ *
311
+ * Initiates a standard real-time stream using the RouterOS `=follow=` protocol.
312
+ * Used for monitoring **changes in configuration or state** (e.g., "Tell me when a new log appears"
313
+ * or "Notify me when a user connects").
314
+ *
315
+ * **Protocol Internals:**
316
+ * This method automatically constructs the complex packet structure required by RouterOS:
317
+ * - Filters are sent as Queries (`?name=...`).
318
+ * - Properties are sent as Attributes (`=.proplist=...`).
319
+ * - The Streaming Flag (`=follow=`) is appended at the end.
320
+ *
321
+ * @param callback Function to execute whenever a new data packet arrives.
322
+ * @returns A `Subscription` object with a `.stop()` method to cancel the stream.
323
+ *
324
+ * @example
325
+ * // Monitor the System Log in real-time
326
+ * const logStream = client.command('/log')
327
+ * .where('topics', 'error') // Only listen for errors
328
+ * .listen((entry) => {
329
+ * console.log(`NEW ERROR: ${entry.message}`);
330
+ * });
331
+ *
332
+ * // Stop after 1 minute
333
+ * setTimeout(() => logStream.stop(), 60000);
334
+ */
28
335
  listen(callback: (item: T) => void): Subscription;
336
+ /**
337
+ * **Streaming Terminator: Traffic & Torch**
338
+ *
339
+ * A specialized listener designed for commands that stream data but **do not** support
340
+ * the standard `/print` syntax, specifically `/interface/monitor-traffic` and `/tool/torch`.
341
+ *
342
+ * **Difference from .listen():**
343
+ * Standard listeners use Query parameters (`?key=value`). Monitor commands require
344
+ * Action parameters (`=key=value`). This method automatically converts your `.where()`
345
+ * filters into the correct format for these tools.
346
+ *
347
+ * @param callback Function to execute with the live metric data.
348
+ * @returns A `Subscription` object.
349
+ *
350
+ * @example
351
+ * // Monitor Bandwidth on Ether1
352
+ * client.command('/interface') // or '/interface/monitor-traffic'
353
+ * .where('interface', 'ether1')
354
+ * .listenMonitor((stats) => {
355
+ * console.log(`RX: ${stats['rx-bits-per-second']} bps`);
356
+ * });
357
+ */
29
358
  listenMonitor(callback: (item: T) => void): Subscription;
359
+ /**
360
+ * Clears cache entries related to the current menu path.
361
+ */
30
362
  private invalidatePathCache;
31
363
  private shouldDefer;
32
364
  private isClientConnected;
365
+ /**
366
+ * Merges query params (filters) and property list (selects).
367
+ */
33
368
  private getParams;
34
369
  private formatValue;
35
370
  private prepareParams;