Ctrl K
ComunidadGuías…

lib/knowledge-db-import-validation.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
var crypto = require("crypto");
var validation = require("./knowledge-db-validation");
var MAX_BATCH_ROWS = 100;
var MAX_BATCH_BYTES = 256 * 1024;

function fail(message, code) { throw Object.assign(new Error(message), { code: code || "INVALID" }); }
function json(value, depth) {
  if (depth > 32) fail("Import JSON exceeds 32 nesting levels.");
  if (value === null || typeof value === "string" || typeof value === "boolean") return;
  if (typeof value === "number" && Number.isFinite(value)) return;
  if (typeof value !== "object" || !value) fail("Import payload must contain finite JSON values.");
  if (!Array.isArray(value)) validation.plainObject(value, "Import payload");
  Object.keys(value).forEach(function (key) { json(value[key], depth + 1); });
}
function canonical(value) {
  if (Array.isArray(value)) return value.map(canonical);
  if (!value || typeof value !== "object") return value;
  var out = {}; Object.keys(value).sort().forEach(function (key) { out[key] = canonical(value[key]); }); return out;
}
function identity(namespace, key) { return JSON.stringify([namespace, key]); }
function sourceText(value, label, max) {
  var clean = validation.text(value, label, max, false);
  if (clean !== value) fail(label + " must not have surrounding whitespace.");
  return clean;
}
function batch(args) {
  validation.plainObject(args, "Import request");
  var namespace = sourceText(args.sourceNamespace, "Source namespace", 120);
  if (!Array.isArray(args.rows) || !args.rows.length || args.rows.length > MAX_BATCH_ROWS) fail("Import batch must contain between 1 and " + MAX_BATCH_ROWS + " rows.", "IMPORT_BATCH_LIMIT");
  json(args.rows, 0);
  if (Buffer.byteLength(JSON.stringify(args.rows), "utf8") > MAX_BATCH_BYTES) fail("Import rows exceed the " + MAX_BATCH_BYTES + " byte input limit.", "IMPORT_BYTES_LIMIT");
  var seen = new Set();
  var rows = args.rows.map(function (row) {
    validation.plainObject(row, "Import row");
    var key = sourceText(row.sourceKey, "Source row key", 200);
    if (seen.has(key)) fail("Import batch contains duplicate source row keys.");
    seen.add(key);
    if (!Object.prototype.hasOwnProperty.call(row, "sourcePayload")) fail("Each import row needs an immutable sourcePayload.");
    validation.plainObject(row.values, "Import values");
    var fingerprint = crypto.createHash("sha256").update(JSON.stringify(canonical({ sourcePayload: row.sourcePayload, values: row.values }))).digest("hex");
    return { sourceKey: key, fingerprint: fingerprint, values: row.values };
  });
  return { sourceNamespace: namespace, rows: rows };
}

module.exports = { batch: batch, identity: identity, sourceText: sourceText, MAX_BATCH_ROWS: MAX_BATCH_ROWS, MAX_BATCH_BYTES: MAX_BATCH_BYTES };