@ocap/statedb-fs
Version:
OCAP statedb adapter that uses fs as backend
108 lines (106 loc) • 3.39 kB
JavaScript
import { name } from "../package.mjs";
import { StateDBTable } from "@ocap/statedb";
import path from "node:path";
import omit from "lodash/omit.js";
import Lokijs from "lokijs";
import FsAdapter from "lokijs/src/loki-fs-structured-adapter.js";
import Debug from "debug";
//#region src/table/base.ts
const debug = Debug(name);
/**
* 文件系统表基类
* 使用 LokiJS + FSAdapter 作为底层存储
*/
var FsTable = class FsTable extends StateDBTable {
constructor({ name: name$1, dataDir, uniqIndex, balanceTable, syncBalance = false }) {
super(uniqIndex);
this.name = name$1;
this.dataDir = dataDir;
this.collection = null;
this.balanceTable = balanceTable;
this.syncBalance = syncBalance;
if (this.syncBalance && !this.balanceTable) throw new Error("balanceTable is required when syncBalance is true");
const adapter = new FsAdapter();
const db = new Lokijs(path.join(dataDir, `${name$1}.db`), {
adapter,
autoload: true,
autosave: true,
autosaveInterval: 1e3,
autoloadCallback: () => {
this.collection = db.getCollection(name$1);
if (this.collection === null) this.collection = db.addCollection(name$1, {
unique: [this.primaryKey],
clone: true
});
this.markReady();
}
});
}
async _create(key, attrs = {}, _context) {
const id = this.generatePrimaryKey(key);
if (await FsTable.prototype._get.call(this, id)) throw new Error(`${this.name} already exists: ${key}`);
debug(`insert ${this.name}`, attrs);
const insertAttrs = { ...attrs };
if (this.syncBalance) delete insertAttrs.tokens;
const result = await this.collection.insert({
[this.primaryKey]: id,
...insertAttrs
});
if (this.syncBalance && attrs.tokens) {
debug(`update balance for ${this.name}`, attrs);
result.tokens = await this.balanceTable.updateBalance({
address: attrs.address,
tokens: attrs.tokens,
context: attrs.context
});
}
return result;
}
async _get(key, _context) {
if (!key) return null;
const id = this.generatePrimaryKey(key);
const result = await this.collection.by(this.primaryKey, id);
if (result && this.syncBalance) {
const balance = await this.balanceTable.getBalance(result.address);
result.tokens = {
...result.tokens || {},
...balance
};
}
return result;
}
_history(_key, _context) {
return [];
}
async _update(key, updates, _context) {
const id = this.generatePrimaryKey(key);
const doc = await FsTable.prototype._get.call(this, id);
if (!doc) throw new Error(`${this.name} does not exists: ${key}`);
Object.assign(doc, updates);
const updateAttrs = { ...doc };
if (this.syncBalance) delete updateAttrs.tokens;
await this.collection.update(updateAttrs);
if (this.syncBalance && doc.tokens) {
debug(`update balance for ${this.name}`, doc);
doc.tokens = await this.balanceTable.updateBalance({
address: doc.address,
tokens: doc.tokens,
context: doc.context
});
}
return doc;
}
updateOrCreate(exist, state, ctx) {
const id = this.generatePrimaryKey(state);
const attrs = omit(state, this.primaryKey);
if (!id) throw new Error("Cannot update or create without uniq index");
if (exist) return this.update(id, attrs, ctx);
return this.create(id, attrs, ctx);
}
_reset(_context) {
this.collection.removeWhere({});
}
};
var base_default = FsTable;
//#endregion
export { base_default as default };