@nano-sql/adapter-leveldb
Version:
Easily Run LevelDB in NodeJS with nanoSQL 2!
398 lines • 15.5 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var utilities_1 = require("@nano-sql/core/lib/utilities");
var memoryIndex_1 = require("@nano-sql/core/lib/adapters/memoryIndex");
var wasm = require("./wasm-index");
var levelup = require("levelup");
var encode = require("encoding-down");
var lexint = require("lexicographic-integer-encoding");
var fs = require("fs");
var path = require("path");
var leveldown = require("leveldown");
var encoding = lexint("hex", { strict: true });
exports.rimraf = function (dir_path) {
if (fs.existsSync(dir_path)) {
fs.readdirSync(dir_path).forEach(function (entry) {
var entry_path = path.join(dir_path, entry);
if (fs.lstatSync(entry_path).isDirectory()) {
exports.rimraf(entry_path);
}
else {
fs.unlinkSync(entry_path);
}
});
fs.rmdirSync(dir_path);
}
};
var LevelDB = /** @class */ (function (_super) {
__extends(LevelDB, _super);
function LevelDB(dbPath, indexCache) {
var _this = _super.call(this, false, false) || this;
_this.dbPath = dbPath;
_this.indexCache = indexCache;
_this.plugin = {
name: "LevelDB Adapter",
version: 2.05
};
_this._indexNum = {};
_this._levelDBs = {};
_this._ai = {};
_this._tableConfigs = {};
if (typeof _this.dbPath === "string" || typeof _this.dbPath === "undefined") {
_this._lvlDown = (function (dbId, tableName, tableData) {
var basePath = path.join(_this.dbPath || ".", "db_" + dbId);
if (!fs.existsSync(basePath)) {
fs.mkdirSync(basePath);
}
return {
lvld: leveldown(path.join(basePath, tableName)),
args: {
cacheSize: 64 * 1024 * 1024,
writeBufferSize: 64 * 1024 * 1024
}
};
});
}
else {
_this._lvlDown = _this.dbPath;
}
return _this;
}
LevelDB.prototype.connect = function (id, complete, error) {
var _this = this;
this._id = id;
var tableName = "_ai_store_";
var lvlDownAI = this._lvlDown(this._id, tableName, __assign({}, utilities_1.blankTableDefinition, { pkType: "string" }));
var keyEncoding = "binary";
levelup(encode(lvlDownAI.lvld, { valueEncoding: "json", keyEncoding: keyEncoding }), lvlDownAI.args, function (err, db) {
if (err) {
error(err);
return;
}
if (_this.indexCache) {
var checkWasm_1 = function () {
if (wasm.loaded) {
_this._levelDBs[tableName] = db;
complete();
}
else {
setTimeout(checkWasm_1, 10);
}
};
checkWasm_1();
}
else {
_this._levelDBs[tableName] = db;
complete();
}
});
};
LevelDB.prototype.createTable = function (tableName, tableData, complete, error) {
var _this = this;
if (this._levelDBs[tableName]) {
error(new Error("Table " + tableName + " already exists and is open!"));
return;
}
this._tableConfigs[tableName] = tableData;
var keyEncoding = {
"int": encoding
}[tableData.pkType] || "binary";
var lvlDown = this._lvlDown(this._id, tableName, tableData);
levelup(encode(lvlDown.lvld, { valueEncoding: "json", keyEncoding: keyEncoding }), lvlDown.args, function (err, db) {
if (err) {
error(err);
return;
}
_this._levelDBs[tableName] = db;
_this._indexNum[tableName] = tableData.isPkNum ? wasm.new_index() : wasm.new_index_str();
_this._levelDBs["_ai_store_"].get(Buffer.from(tableName, "utf-8"), function (err, value) {
_this._ai[tableName] = value ? value.ai || 0 : 0;
if (_this.indexCache && tableData) {
_this._levelDBs[tableName]
.createKeyStream()
.on("data", function (data) {
if (tableData.isPkNum) {
wasm.add_to_index(_this._indexNum[tableName], isNaN(data) ? 0 : parseFloat(data));
}
else {
wasm.add_to_index_str(_this._indexNum[tableName], String(data || ""));
}
})
.on("end", function () {
complete();
})
.on("error", error);
}
else {
complete();
}
});
});
};
LevelDB.prototype.dropTable = function (table, complete, error) {
var _this = this;
this._levelDBs["_ai_store_"].del(Buffer.from(table, "utf-8")).then(function () {
_this._levelDBs[table].close(function (err) {
try {
exports.rimraf(path.join((_this.dbPath || "."), "db_" + _this._id, table));
}
catch (e) {
error(e);
return;
}
if (_this.indexCache && _this._tableConfigs[table]) {
if (_this._tableConfigs[table].isPkNum) {
wasm.empty_index(_this._indexNum[table]);
}
else {
wasm.empty_index_str(_this._indexNum[table]);
}
}
delete _this._levelDBs[table];
complete();
}, error);
}).catch(error);
};
LevelDB.prototype.disconnect = function (complete, error) {
var _this = this;
utilities_1.allAsync(Object.keys(this._levelDBs), function (table, i, next, error) {
if (_this.indexCache && _this._tableConfigs[table]) {
_this._tableConfigs[table].isPkNum ? wasm.empty_index(_this._indexNum[table]) : wasm.empty_index_str(_this._indexNum[table]);
}
_this._levelDBs[table].close(function (err) {
if (err) {
error(err);
return;
}
delete _this._tableConfigs[table];
next(null);
});
}).then(complete).catch(error);
};
LevelDB.prototype.write = function (table, pk, row, complete, error) {
var _this = this;
pk = pk || utilities_1.generateID(this._tableConfigs[table].pkType, this._ai[table] + 1);
if (typeof pk === "undefined") {
error(new Error("Can't add a row without a primary key!"));
return;
}
if (this._tableConfigs[table].ai) {
this._ai[table] = Math.max(pk, this._ai[table]);
}
utilities_1.deepSet(this._tableConfigs[table].pkCol, row, pk);
if (this.indexCache) {
if (this._tableConfigs[table].isPkNum) {
wasm.add_to_index(this._indexNum[table], isNaN(pk) ? 0 : parseFloat(pk));
}
else {
wasm.add_to_index_str(this._indexNum[table], String(pk || ""));
}
}
this._levelDBs[table].put(this._encodePk(table, pk), row, function (err) {
if (err) {
error(err);
}
else {
if (_this._tableConfigs[table].ai) {
_this._levelDBs["_ai_store_"].put(Buffer.from(table, "utf-8"), { ai: _this._ai[table] }).then(function () {
complete(pk);
}).catch(error);
}
else {
complete(pk);
}
}
});
};
LevelDB.prototype.read = function (table, pk, complete, error) {
this._levelDBs[table].get(this._encodePk(table, pk), function (err, row) {
if (err) {
complete(undefined);
}
else {
complete(row);
}
});
};
LevelDB.prototype.readMulti = function (table, type, offsetOrLow, limitOrHigh, reverse, onRow, complete, error) {
var _this = this;
if (this.indexCache && type === "offset") {
var ptrFn = this._tableConfigs[table].isPkNum ? wasm.read_index_offset : wasm.read_index_offset_str;
var nextFn_1 = this._tableConfigs[table].isPkNum ? wasm.read_index_offset_next : wasm.read_index_offset_str_next;
var it_1 = ptrFn(this._indexNum[table], reverse ? 1 : 0, reverse ? offsetOrLow + 2 : offsetOrLow + 1);
if (it_1 === 0) {
complete();
return;
}
var nextKey_1 = 0;
var count_1 = 0;
var nextRow_1 = function () {
nextKey_1 = nextFn_1(_this._indexNum[table], it_1, reverse ? 1 : 0, limitOrHigh, count_1);
if (count_1 < limitOrHigh) {
_this.read(table, nextKey_1, function (row) {
if (row) {
onRow(row, count_1);
}
if (count_1 % 500 === 0) {
setTimeout(nextRow_1, 0);
}
else {
nextRow_1();
}
}, error);
}
else {
complete();
}
count_1++;
};
nextRow_1();
return;
}
var i = 0;
this._levelDBs[table]
.createValueStream(type === "range" ? {
gte: type === "range" ? this._encodePk(table, offsetOrLow) : undefined,
lte: type === "range" ? this._encodePk(table, limitOrHigh) : undefined,
reverse: reverse
} : type === "offset" ? {
reverse: reverse,
limit: type === "offset" ? (offsetOrLow + limitOrHigh + (reverse ? 1 : 0)) : undefined
} : {
reverse: reverse,
})
.on("data", function (data) {
if (type === "offset" && (reverse ? i < offsetOrLow + 1 : i < offsetOrLow)) {
i++;
return;
}
onRow(data, i);
i++;
})
.on("end", function () {
complete();
})
.on("error", error);
};
LevelDB.prototype._writeNumberBuffer = function (table, num) {
switch (this._tableConfigs[table].pkType) {
case "int":
return num;
// case "float":
// case "number":
default:
return Buffer.from(String(num), "utf-8");
}
};
LevelDB.prototype._readNumberBuffer = function (table, buff) {
switch (this._tableConfigs[table].pkType) {
case "int":
return buff;
// case "float":
// case "number":
default:
var buffer = new Buffer(buff);
return parseFloat(buffer.toString("utf-8"));
}
};
LevelDB.prototype._encodePk = function (table, pk) {
return this._tableConfigs[table].isPkNum ? this._writeNumberBuffer(table, pk) : Buffer.from(pk, "utf-8");
};
LevelDB.prototype._decodePK = function (table, pk) {
return this._tableConfigs[table].isPkNum ? this._readNumberBuffer(table, pk) : new Buffer(pk).toString("utf-8");
};
LevelDB.prototype.delete = function (table, pk, complete, error) {
var _this = this;
this._levelDBs[table].del(this._encodePk(table, pk), function (err) {
if (err) {
throw Error(err);
}
else {
if (_this.indexCache && _this._tableConfigs[table]) {
if (_this._tableConfigs[table].isPkNum) {
wasm.del_key(_this._indexNum[table], isNaN(pk) ? 0 : parseFloat(pk));
}
else {
wasm.del_key_str(_this._indexNum[table], String(pk || ""));
}
}
complete();
}
});
};
LevelDB.prototype.getTableIndex = function (table, complete, error) {
var _this = this;
if (this.indexCache && this._tableConfigs[table]) {
var ptrFn = this._tableConfigs[table].isPkNum ? wasm.read_index : wasm.read_index_str;
var nextFn = this._tableConfigs[table].isPkNum ? wasm.read_index_next : wasm.read_index_str_next;
var it_2 = ptrFn(this._indexNum[table], 0);
if (!it_2) {
complete([]);
return;
}
it_2 = it_2.split(",").map(function (s) { return parseInt(s); });
var nextKey = 0;
var count = 0;
var keys = [];
while (count < it_2[1]) {
nextKey = nextFn(this._indexNum[table], it_2[0], 0, count);
count++;
keys.push(nextKey);
}
complete(keys);
return;
}
var index = [];
this._levelDBs[table]
.createKeyStream()
.on("data", function (pk) {
index.push(_this._decodePK(table, pk));
})
.on("end", function () {
complete(index);
})
.on("error", error);
};
LevelDB.prototype.getTableIndexLength = function (table, complete, error) {
if (this.indexCache && this._tableConfigs[table]) {
complete(this._tableConfigs[table].isPkNum ? wasm.get_total(this._indexNum[table]) : wasm.get_total_str(this._indexNum[table]));
return;
}
var count = 0;
this._levelDBs[table]
.createKeyStream()
.on("data", function (pk) {
count++;
})
.on("end", function () {
complete(count);
})
.on("error", error);
};
return LevelDB;
}(memoryIndex_1.nanoSQLMemoryIndex));
exports.LevelDB = LevelDB;
//# sourceMappingURL=index.js.map