UNPKG

shelfdb

Version:

Node.JS custom database and abstract class library

417 lines (358 loc) 11.2 kB
// Generated by CoffeeScript 2.0.2 var BSON, BSONSerializer, DBSerializable, Database, DatabaseSerializer, GZIP, JSONSerializer, YAML, YAMLSerializer, _serTypes, abstractClass, compjs, compressed, compressions, fs, gzipped, isImplementation, zlib, indexOf = [].indexOf; fs = require('fs'); YAML = require('js-yaml'); BSON = new (require('bson'))(); GZIP = require('pako'); zlib = require('zlib'); ({abstractClass, isImplementation} = require('./abstraction.js')); compjs = require('compressjs'); DatabaseSerializer = (function() { class DatabaseSerializer {}; DatabaseSerializer.prototype.F_serialize = null; DatabaseSerializer.prototype.F_deserialize = null; return DatabaseSerializer; })(); DatabaseSerializer = abstractClass(DatabaseSerializer, function(cls) { return cls.database = function(filename, debug) { return new Database(filename, cls, debug); }; }); JSONSerializer = (function() { class JSONSerializer {}; JSONSerializer.prototype.serialize = JSON.stringify; JSONSerializer.prototype.deserialize = JSON.parse; return JSONSerializer; })(); YAMLSerializer = (function() { class YAMLSerializer { serialize(o) { return YAML.safeDump(o, { indent: 4, lineWidth: 175 }); } }; YAMLSerializer.prototype.deserialize = YAML.safeLoad; return YAMLSerializer; })(); BSONSerializer = (function() { class BSONSerializer {}; BSONSerializer.prototype.serialize = BSON.serialize; BSONSerializer.prototype.deserialize = BSON.deserialize; return BSONSerializer; })(); JSONSerializer = DatabaseSerializer.apply(JSONSerializer); YAMLSerializer = DatabaseSerializer.apply(YAMLSerializer); BSONSerializer = DatabaseSerializer.apply(BSONSerializer); gzipped = function(ser) { // for compatibility purposes var GZipped; GZipped = class GZipped { serialize(o) { return new Buffer(GZIP.deflate(ser.prototype.serialize(o))); } deserialize(o) { return ser.prototype.deserialize(new Buffer(GZIP.inflate(o))); } }; GZipped.name += ser.name; GZipped = DatabaseSerializer.apply(GZipped); return GZipped; }; compressions = { gzip: [zlib.gzipSync, zlib.gunzipSync], inflate: [zlib.deflateSync, zlib.inflateSync], bzip2: [compjs.Bzip2.compressFile, compjs.Bzip2.decompressFile], bwtc: [compjs.BWTC.compressFile, compjs.BWTC.decompressFile], lzp3: [compjs.Lzp3.compressFile, compjs.Lzp3.decompressFile], ppm: [compjs.PPM.compressFile, compjs.PPM.decompressFile] }; compressed = function(ser, compression) { var Compressed; if (compressions[compression = compression.toLowerCase()] == null) { throw new Error("No such compression currently available with shelfdb!"); } Compressed = class Compressed { serialize(o) { return new Buffer(compressions[compression][0](new Buffer(ser.prototype.serialize(o)))); } deserialize(o) { return ser.prototype.deserialize(new Buffer(compressions[compression][1](o))); } }; Compressed.name += ser.name; Compressed = DatabaseSerializer.apply(Compressed); return Compressed; }; // ======================= _serTypes = {}; DBSerializable = (function() { class DBSerializable {}; DBSerializable.prototype.F_toObject = null; DBSerializable.prototype.S_fromObject = null; return DBSerializable; })(); DBSerializable = abstractClass(DBSerializable, function(cls) { return _serTypes[cls.name] = cls; }); // ======================= Database = class Database { constructor(filename1, serializer, debug1) { var err; this.objectFrom = this.objectFrom.bind(this); this.unfreeze = this.unfreeze.bind(this); this._loadFile = this._loadFile.bind(this); this.load = this.load.bind(this); this.save = this.save.bind(this); this.serialize = this.serialize.bind(this); this.put = this.put.bind(this); this.get = this.get.bind(this); this.append = this.append.bind(this); this.filename = filename1; this.serializer = serializer; this.debug = debug1; if (this.debug == null) { this.debug = false; } try { if (fs.statSync(this.filename).isFile()) { this.data = this.serializer.deserialize(fs.readFileSync(this.filename)); } else { throw new Error("If you are seeing this, something is wrong with this control block."); } } catch (error) { err = error; this.data = {}; } if ((typeof this.serializer) === 'function') { this.serializer = new this.serializer(); } } objectFrom(obj, pkey, parent) { var arr, i, k, len, o, ref, ref1, res, v; if (parent == null) { parent = null; } if (pkey == null) { pkey = null; } if (this.debug === 2) { console.log("Attempting to get object from:"); console.log(obj); } res = { spec: { serialization: null, type: null, primitive: false }, obj: null }; if ((obj != null) && isImplementation(obj.constructor, DBSerializable)) { res.spec.type = "DBSerializable"; res.spec.serialization = obj.constructor.name; if (this.debug === 1) { console.log(`Found DBSerializable of type ${obj.constructor.name}${(pkey != null ? ` (and key '${pkey}')` : '')}`); } res.obj = {}; ref = obj.toObject(); for (k in ref) { v = ref[k]; res.obj[k] = this.objectFrom(v, k, obj); } } else if (obj == null) { res.spec.type = "nil"; res.spec.primitive = true; res.obj = obj; } else if ((typeof obj) !== 'object') { if ((ref1 = typeof obj) !== 'string' && ref1 !== 'number' && ref1 !== 'boolean') { throw new Error(`${obj}${(parent != null ? ` (from key '${pkey}' in parent with keys '${Object.keys(parent).join(', ')}')` : "")} must be a primitive, non-instance object, array, or implement the abstract type DBSerializable!`); } else { res.obj = obj; res.spec.type = typeof obj; res.spec.primitive = true; } } else if (Array.isArray(obj)) { arr = []; for (i = 0, len = obj.length; i < len; i++) { o = obj[i]; arr.push(this.objectFrom(o)); } res.obj = arr; res.spec.type = 'array'; res.spec.primitive = false; } else if (obj === null) { // includes undefined res.obj = null; res.spec.primitive = true; } else { if (res.spec.type == null) { res.spec.type = "object"; } res.obj = {}; for (k in obj) { v = obj[k]; res.obj[k] = this.objectFrom(v, k, obj); } } return res; } unfreeze(d) { var e, i, item, k, len, ref, ref1, ref2, ref3, ref4, res, ud, v; try { res = null; if (d.spec.type === "DBSerializable") { ud = {}; ref = d.obj; for (k in ref) { v = ref[k]; ud[k] = this.unfreeze(v); } if ((d.spec.serialization != null) && (ref1 = d.spec.serialization, indexOf.call(Object.keys(_serTypes), ref1) >= 0)) { res = _serTypes[d.spec.serialization].fromObject(ud); } else if (ref2 = d.spec.serialization, indexOf.call(Object.keys(_serTypes), ref2) < 0) { throw new Error(`DBSerializable-based object '${d.obj}' specifies an unsupported serialization type '${d.spec.serialization}'! (try loading the module with the serialization)`); } else { throw new Error(`DBSerializable-based object '${d.obj}' does not specify the serializing class in its spec structure`); } } else if (d.spec.primitive) { res = d.obj; } else if (d.spec.type === "array") { res = []; ref3 = d.obj; for (i = 0, len = ref3.length; i < len; i++) { item = ref3[i]; res.push(this.unfreeze(item)); } } else if (d.spec.type === "object") { res = {}; ref4 = d.obj; for (k in ref4) { v = ref4[k]; res[k] = this.unfreeze(v); } } else { throw new Error(`Object '${d.obj}' does not specify a supported spec structure type ('${d.spec.type}' is a currently unsupported format)`); } return res; } catch (error) { e = error; if (d.spec != null) { if (!d.spec.primitive) { console.log(`Error unfreezing object with keys '${Object.keys(d.obj).join(', ')}' and spec..`); console.log(d.spec); } else { console.log(`Error unfreezing object '${d.obj}' with spec...`); console.log(d.spec); } } else { console.log("Error unfreezing object..."); console.log(d); } throw e; } } _loadFile() { var data, err; try { if (!fs.statSync(this.filename).isFile()) { throw new Error("If you are seeing this, something is wrong with this control block."); } } catch (error) { err = error; return this.data || {}; } data = this.serializer.deserialize(fs.readFileSync(this.filename)); return this.unfreeze(data); } load() { return this.data = this._loadFile(); } save() { return fs.writeFileSync(this.filename, this.serialize(this.data)); } serialize(obj) { return this.serializer.serialize(this.objectFrom(obj)); } parsePath(path, separator) { if ((typeof path) === "string") { path = path.match(new RegExp(`(?:\\\\.|[^\\${separator[0]}])+`, 'g')).map(function(x) { return x.split("\\.").join("."); }); } return path; } put(path, value, separator, obj) { var first; if (separator == null) { separator = '.'; } path = this.parsePath(path, separator); first = false; if (obj == null) { this.load(); first = true; obj = this.data; } if (path.length > 1) { if (obj[path[0]] == null) { obj[path[0]] = {}; } obj[path[0]] = this.put(path.slice(1), value, separator, obj[path[0]]); } else { obj[path[0]] = value; } if (first) { this.data = obj; this.save(); return path.map(function(x) { return x.split('.').join('\\.'); }).join("."); } else { return obj; } } get(path, separator) { var i, len, o, p; if (separator == null) { separator = '.'; } this.load(); path = this.parsePath(path, separator); o = this.data; for (i = 0, len = path.length; i < len; i++) { p = path[i]; if (o[p] == null) { return null; } o = o[p]; } return o; } append(path, value, separator) { var o; o = this.get(path, separator); if (o == null) { o = [value]; } else if (typeof o !== "array") { return null; } else { o.push(value); } return this.put(path, o, separator); } }; module.exports = { DBSerializable: DBSerializable, Database: Database, DatabaseSerializer: DatabaseSerializer, JSONSerializer: JSONSerializer, YAMLSerializer: YAMLSerializer, BSONSerializer: BSONSerializer, gzipped: gzipped, compressed: compressed, compressions: compressions, // entry point inheritance abstractClass: abstractClass, isImplementation: isImplementation };