Node.js · API

Lint

El módulo donly/lint valida un documento contra un objeto de reglas y devuelve los problemas encontrados. Los ejemplos usan este app.donly:

name "my-app"
port 8080
enabled true

server {
  host "example.com"
  route GET /home {
    respond 200
  }
  route POST /api/user
}

lint(text, rules)

Recibe el texto del documento y las reglas. Devuelve un arreglo de LintIssue, vacío si todo es válido. lint es también el nombre corto de lintSchema.

import { lint, renderReport } from "donly/lint";

const rules = {
  "/port": { "[1]": { type: "number", gte: 1, lte: 65535 } },
};

lint(text, rules); // []  (el documento cumple las reglas)
type LintSeverity = "error" | "warning" | "info";

interface LintIssue {
  message: string;
  severity: LintSeverity;
  trace?: string;
  loc?: { start: Token; end: Token };
}

Forma de las reglas

Cada clave es un camino de directiva (/server, /server/route). Dentro, otras claves /hijo bajan un nivel y las claves [N] restringen el argumento en la posición N (desde 1). También existe la forma fusionada "/port[1]".

const rules = {
  // posición del argumento: [N] (desde 1) o "/ruta[N]"
  "/port": { "[1]": { type: "number", gte: 1, lte: 65535 } },
  "/server": {
    "/route[1]": { enum: ["GET", "POST"] },
    "/host[1]": { type: "string", pattern: "^[a-z.]+$" },
  },
  "/enabled": { "[1]": { or: [{ type: "boolean" }, { type: "number" }] } },
  "/name": { "[1]": { not: { enum: ["admin"] } } },
};

Ocurrencias

required, min y max controlan cuántas veces aparece una directiva.

lint(text, { "/database": { required: true } });
// error: required directive is missing

lint(text, { "/server": { "/route": { max: 1 } } });
// error: too many occurrences (max 1)

lint(text, { "/server": { "/route": { min: 3 } } });
// error: too few occurrences (min 3)

Mensaje y severidad

message reemplaza el texto del problema y severity lo cambia a "error", "warning" o "info".

lint(text, {
  "/database": {
    required: true,
    message: "falta database",
    severity: "warning",
  },
});
// [ { severity: 'warning', message: 'falta database' } ]

Lógica propia

evaluation es una vía de escape: recibe la directiva (o el argumento y su posición) y devuelve los problemas que quieras reportar.

lint(text, {
  "/name": {
    evaluation: (directive) => [
      { message: "revisado: " + directive.args[0], severity: "info" },
    ],
  },
});
// [ { severity: 'info', message: 'revisado: my-app' } ]

Reglas en un archivo .donly

Las reglas también pueden escribirse en sintaxis DON. parseLintRulesDonly las convierte en el mismo objeto de reglas.

/port {
  [1] {
    type "string"
  }
}
import { lint, parseLintRulesDonly } from "donly/lint";

const rules = parseLintRulesDonly(`
/port {
  [1] {
    type "number"
    gte 1
    lte 1000
  }
}
`);

JSON.stringify(rules);
// {"/port":{"[1]":{"type":"number","gte":1,"lte":1000}}}

Reportes

renderReport(issues, { filePath, asciiColor? }) produce un texto legible, con línea y columna desde 1. Con asciiColor agrega colores ANSI. renderJSONReport devuelve el mismo reporte en JSON; line y column son null si el problema no tiene ubicación (por ejemplo, una directiva requerida que falta).

import { renderJSONReport } from "donly/lint";

renderJSONReport(issues, { filePath: "app.donly" });
// {
//   "filePath": "app.donly",
//   "issues": [
//     { "line": 2, "column": 6, "severity": "error",
//       "message": "argument at position 1 must be of type string" }
//   ],
//   "summary": { "errors": 1, "warnings": 0, "info": 0 }
// }

CLI

npx donly lint usa esta misma API. Acepta reglas en .json o .donly, y termina con código 1 si hay errores.

$ npx donly lint --rules rules.donly app.donly
app.donly
  2:6  error  argument at position 1 must be of type string

1 error 0 warnings 0 info

$ npx donly lint --rules rules.donly -o json app.donly   # salida JSON