Edits history of script submission #24071 for ' Run DB query (akips)'

  • bunnative
    One script reply has been approved by the moderators
    Ap­pro­ved
    //native
    
    const READ_COMMANDS = [
      "aggregate",
      "calc",
      "check",
      "count",
      "cseries",
      "get",
      "list",
      "mcalc",
      "mget",
      "mgroup",
      "mlist",
      "mtime",
      "mtype",
      "netmask",
      "rget",
      "series",
      "tf",
      "tget",
      "top",
      "tz",
    ]
    
    /**
     * Run DB query
     * Run one read-only AKIPS api-db command (e.g. `mget text * sys /ip.addr/`, `mlist interface swt250 *`) and parse each output line into tokens and, for `... = value` lines, the entity path and value.
     */
    export async function main(auth: RT.Akips, command: string) {
      const cmd = command.trim()
      const verb = cmd.split(/\s+/)[0]
      if (!READ_COMMANDS.includes(verb)) {
        throw new Error(
          `"${verb}" is not a read-only api-db command. Allowed: ${READ_COMMANDS.join(", ")}`
        )
      }
    
      // A line break starts a second api-db command (§4.5.2 data), so inputs must stay on one line.
      if (/[\r\n]/.test(cmd)) throw new Error("api-db command must be a single line")
    
      // Documented form (API guide §4.5.2): password in the URL, commands in the POST body.
      const url = new URL(`${auth.base_url}/api-db`)
      url.searchParams.append("username", auth.username)
      url.searchParams.append("password", auth.password)
      const response = await fetch(url, {
        method: "POST",
        headers: { "Content-Type": "application/x-www-form-urlencoded" },
        body: new URLSearchParams({ cmds: cmd }),
      }).catch((e) => {
        // Network errors quote the full URL: drop the query string, which holds the password.
        throw new Error(String(e).replaceAll(url.search, ""))
      })
      const text = await response.text()
      if (!response.ok || text.startsWith("ERROR:")) {
        throw new Error(`${response.status} ${text}`)
      }
    
      const lines = text.split("\n").filter((line) => line.trim() !== "")
      const rows = lines.map((line) => {
        const eq = line.indexOf(" = ")
        if (eq === -1) {
          return { raw: line, tokens: line.trim().split(/\s+/) }
        }
        const entity = line.slice(0, eq).trim().split(/\s+/)
        return {
          raw: line,
          tokens: entity,
          parent: entity[0],
          child: entity[1],
          attribute: entity[2],
          value: line.slice(eq + 3),
        }
      })
    
      return { command: cmd, count: rows.length, rows }
    }
    

    Submitted by hugo989 6 hours ago