fix(terminal): показывать последние записи журнала RouterOS

This commit is contained in:
Denozordec committed 2026-10-11 11:26:59 +07:00
1 parent 1e4d3b4678
commit bd023b8aaa
15 files changed
+321 -16

No files matched your search

@@ -0,0 +1,44 @@
import assert from "node:assert/strict"
import { createServer } from "node:http"
import { test } from "node:test"
import { MikrotikClient } from "./mikrotik.js"
test("REST logs use the default buffer and return the latest bounded entries", async () => {
const history = Array.from({ length: 1000 }, (_, i) => ({
".id": `*${i.toString(16)}`, time: `time-${i}`, topics: "system,info", message: `entry-${i}`,
}))
let rows = history, denied = false, requests = 0
const server = createServer((req, res) => {
requests++
const url = new URL(req.url!, "http://127.0.0.1")
assert.equal(req.method, "GET")
assert.equal(url.pathname, "/rest/log")
assert.equal(url.searchParams.get("buffer"), "memory")
assert.equal(url.searchParams.get(".proplist"), ".id,time,topics,message")
assert.equal(url.searchParams.has("limit"), false)
res.writeHead(denied ? 401 : 200, { "content-type": "application/json" })
res.end(JSON.stringify(denied ? { message: "Unauthorized" } : rows))
})
await new Promise<void>(resolve => server.listen(0, "127.0.0.1", resolve))
const address = server.address()
assert.ok(address && typeof address !== "string")
const client = new MikrotikClient({ host: "127.0.0.1", port: address.port, useSsl: false, verifySsl: false, username: "fixture", password: "fixture" })
try {
assert.deepEqual(await client.getLogs(3), history.slice(-3))
assert.deepEqual(await client.getLogs(), history.slice(-50))
assert.deepEqual(await client.getLogs(500), history.slice(-200))
rows = history.slice(0, 2)
assert.deepEqual(await client.getLogs(3), rows)
rows = []
assert.deepEqual(await client.getLogs(3), [])
const before = requests
for (const limit of [0, -1, 1.5, NaN, Infinity, Number.MAX_SAFE_INTEGER + 1]) {
await assert.rejects(client.getLogs(limit), RangeError)
}
assert.equal(requests, before, "Invalid limits must not poll RouterOS")
denied = true
await assert.rejects(client.getLogs(3), /401.*Unauthorized/)
} finally {
await new Promise<void>((resolve, reject) => server.close(error => error ? reject(error) : resolve()))
}
})
+7 -1
View File
@@ -696,7 +696,13 @@ export class MikrotikClient {
}
async getLogs(limit = 50): Promise<RosLogEntry[]> {
return this.get<RosLogEntry[]>(`/log?limit=${limit}`)
if (!Number.isSafeInteger(limit) || limit < 1) {
throw new RangeError("limit должен быть положительным целым числом.")
}
// REST query parameters filter properties; limit is not a print row limit.
// Read only the default buffer and retain its latest entries in native order.
const entries = await this.get<RosLogEntry[]>("/log?buffer=memory&.proplist=.id,time,topics,message")
return entries.slice(-Math.min(limit, 200))
}
async ping(