Ctrl K
ComunidadGuías…

lib/knowledge-db-storage-nedb.js

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

Archivo original ↗Preguntar a KiBot
var fs = require("fs");
var path = require("path");
var Datastore = require("@seald-io/nedb");
var maintenance = require("./knowledge-db-storage-nedb-maintenance");
var STORE_REGISTRY = new Map();

function clone(value) { return JSON.parse(JSON.stringify(value)); }
function error(message, code) { return Object.assign(new Error(message), { code: code }); }
function createKnowledgeDbNedbStorage(options) {
  var projectDir = path.resolve(options.projectDir); var projectReal = null;
  var knowledgeDir = path.join(projectDir, "knowledge"); var dataDir = path.join(knowledgeDir, ".clay-db");
  var filename = path.join(dataDir, "databases.db"); var entry = STORE_REGISTRY.get(filename);
  if (!entry) { entry = { queues: new Map(), database: null, loading: null, ready: false }; STORE_REGISTRY.set(filename, entry); }
  function safeDirectory(target, create) {
    var stat;
    try { stat = fs.lstatSync(target); }
    catch (cause) { if (!create || cause.code !== "ENOENT") throw cause; fs.mkdirSync(target, { recursive: true, mode: 0o700 }); stat = fs.lstatSync(target); }
    if (!stat.isDirectory() || stat.isSymbolicLink()) throw error("Knowledge database path is unsafe.", "UNSAFE_PATH");
    var real = fs.realpathSync(target);
    if (real !== projectReal && !real.startsWith(projectReal + path.sep)) throw error("Knowledge database path escapes the Mate project.", "UNSAFE_PATH");
  }
  function open() {
    if (entry.loading) return entry.loading;
    entry.loading = Promise.resolve().then(function () {
      projectReal = fs.realpathSync(projectDir); safeDirectory(knowledgeDir, true); safeDirectory(dataDir, true);
      var stat; try { stat = fs.lstatSync(filename); } catch (cause) { if (cause.code !== "ENOENT") throw cause; }
      if (stat && (!stat.isFile() || stat.isSymbolicLink())) throw error("Knowledge database file is unsafe.", "UNSAFE_PATH");
      entry.database = new Datastore({ filename: filename }); return entry.database.loadDatabaseAsync();
    }).then(function () { return entry.database.ensureIndexAsync({ fieldName: "_id", unique: true }); })
      .then(function () { entry.ready = true; return entry.database; })
      .catch(function (cause) { invalidate(); throw cause; });
    return entry.loading;
  }
  function invalidate() { entry.database = null; entry.loading = null; entry.ready = false; }
  var io = maintenance.attachKnowledgeDbNedbMaintenance({ entry: entry, filename: filename, open: open, invalidate: invalidate });
  function serialize(scope, work) {
    var previous = entry.queues.get(scope) || Promise.resolve(); var next = previous.catch(function () {}).then(function () { return work(); });
    entry.queues.set(scope, next.catch(function () {})); return next;
  }
  function insert(snapshot) {
    var value = clone(snapshot);
    return io.write(function (store) { return store.insertAsync(value); }, value).then(function () {}, function (cause) {
      if (cause.errorType === "uniqueViolated") throw error("Knowledge storage identity already exists.", "ALREADY_EXISTS");
      throw cause;
    });
  }
  function replaceIfRevision(id, revision, snapshot) {
    var value = clone(snapshot);
    if (value._id !== id) return Promise.reject(error("Knowledge storage replacement identity must match.", "INVALID_STORAGE_ID"));
    return io.write(function (store) { return store.updateAsync({ _id: id, revision: revision }, value, {}); }, value)
      .then(function (result) { return result.numAffected === 1; });
  }
  return {
    contractVersion: 1,
    initialize: function () { return io.read(function () {}); },
    hasStore: function () { try { return fs.lstatSync(filename).isFile(); } catch (cause) { return false; } },
    isReady: function () { return entry.ready === true; },
    get: function (id) { return io.read(function (store) { return store.findOneAsync({ _id: id }); }); },
    list: function () { return io.read(function (store) { return store.findAsync({}); }); },
    getCached: function () { return clone(io.cached()); },
    insert: insert, replaceIfRevision: replaceIfRevision, serialize: serialize,
    diagnostics: function () { return io.readStorageStatus().then(function (status) { return Object.assign({ engine: "nedb", automaticCompaction: false }, status); }); }
  };
}

module.exports = { createKnowledgeDbNedbStorage: createKnowledgeDbNedbStorage };