castelog
Version:
Programación JavaScript en castellano.
302 lines (283 loc) • 16.9 kB
JavaScript
/*lib:simplest-db@1.0.3 + modifications*/
(function (root, factory) {
const scope = (typeof window !== 'undefined') ? window : global;
if("SimplestDB" in scope) return scope.SimplestDB;
const output = factory();
if(typeof module === 'object' && typeof module.exports === 'object')
module.exports = output;
if(typeof define === 'function' && define.amd)
define([], factory);
if(typeof exports === 'object')
exports["SimplestDB"] = output;
scope["SimplestDB"] = output;
})(this, function() {
class SimplestDB {
static create(...args) {
return new this(...args);
}
static getFS() {
if(this.$fs) {
return this.$fs;
}
this.$fs = new SimplestDB({
schema: "system",
tables: {
"fs": {
columns: {
"path": { is_type: "string" },
"contents": { is_type: "string" },
"metadata": { is_type: "object" },
}
}
}
});
return this.$fs;
}
static getCache() {
if(this.$cache) {
return this.$cache;
}
this.$cache = new SimplestDB({
schema: "system",
tables: {
"cache": {
columns: {
"key": { is_type: "string" },
"value": { is_type: "string" },
}
}
}
});
return this.$cache;
}
constructor(schema = {}, noValidate = false) {
if(typeof schema !== "object") throw new Error("Required «schema» to be an object, found «" + typeof(schema) + "» [0301]");
if(typeof schema.schema !== "string") schema.schema = "system";
if(!("attributes" in schema)) {Object.assign(schema, {attributes:{}})}
if(!("tables" in schema)) {Object.assign(schema, {tables:{}})}
this.schema = this.validateSchema(schema);
this.noValidate = noValidate;
this.baseDir = (typeof schema.baseDir === "string" ? schema.baseDir.replace(/^\/+/g, "").replace(/\/+$/g, "") : "./sdb_modules") + "/";
if(typeof global === "object") {
const fs = require("fs");
const hasBaseDir = fs.existsSync(this.baseDir) && fs.lstatSync(this.baseDir).isDirectory();
if(!hasBaseDir) {
fs.mkdirSync(this.baseDir);
}
}
}
validateTable(tableId) {
if(typeof tableId !== "string") throw new Error("Required parameter table «" + tableId + "» to be a string, found «" + typeof(tableId) + "» [0101]");
if(this.noValidate) return this.schema.tables[tableId];
if(!(tableId in this.schema.tables)) throw new Error("Required parameter table «" + tableId + "» to exist as table in schema, only accepted: «" + Object.keys(this.schema.tables).join("», «") + "» [0402]");
return this.schema.tables[tableId];
}
validateRow(tableId, value) {
if(typeof tableId !== "string") throw new Error("Required parameter table «" + tableId + "» to be a string, found «" + typeof(tableId) + "» [0801]");
if(this.noValidate) return this.schema.tables[tableId];
if(!(tableId in this.schema.tables)) throw new Error("Required parameter table «" + tableId + "» to exist as table in schema, only accepted: «" + Object.keys(this.schema.tables).join("», «") + "» [0802]");
return true;
}
validateSchema(schema) {
if(typeof schema !== "object") throw new Error("Required «schema» to be an object, found «" + typeof(schema) + "» [0301]");
if(typeof schema.schema !== "string") throw new Error("Required «schema.schema» to be a string, found «" + typeof(schema) + "» [0302]");
if(typeof schema.attributes === "undefined") schema.attributes = {};
if(typeof schema.attributes !== "object") throw new Error("Required «schema.attributes» to be an object, found «" + typeof(attributes) + "» [0303]");
if(typeof schema.tables === "undefined") schema.tables = {};
if(typeof schema.tables !== "object") throw new Error("Required «schema.tables» to be an object, found «" + typeof(tables) + "» [0304]");
const tableIds = Object.keys(schema.tables);
for(let indexTable = 0; indexTable < tableIds.length; indexTable++) {
const tableId = tableIds[indexTable];
if(typeof schema.tables[tableId] !== "object") throw new Error("Required «schema.tables[" + JSON.stringify(tableId) + "]» to be an object, found «" + typeof(schema.tables[tableId]) + "» [0305]");
if(typeof schema.tables[tableId].attributes === "undefined") schema.tables[tableId].attributes = {};
if(typeof schema.tables[tableId].attributes !== "object") throw new Error("Required «schema.tables[" + JSON.stringify(tableId) + "].attributes» to be an object, found «" + typeof(attributes) + "» [0306]");
if(typeof schema.tables[tableId].columns === "undefined") schema.tables[tableId].columns = {};
if(typeof schema.tables[tableId].columns !== "object") throw new Error("Required «schema.tables[" + JSON.stringify(tableId) + "].columns» to be an object, found «" + typeof(columns) + "» [0307]");
const tableData = schema.tables[tableId];
const columnIds = Object.keys(tableData.columns);
for(let indexColumn = 0; indexColumn < columnIds.length; indexColumn++) {
const columnId = columnIds[indexColumn];
const columnData = tableData.columns[columnId];
if(typeof columnData !== "object") throw new Error("Required «schema.tables[" + JSON.stringify(tableId) + "].columns[" + JSON.stringify(columnId) + "]»")
if(typeof columnData.attributes === "undefined") columnData.attributes = {};
if(typeof columnData.attributes !== "object") throw new Error("Required «schema.tables[" + JSON.stringify(tableId) + "].columns[" + JSON.stringify(columnId) + "].attributes»")
if(typeof columnData.is_type !== "string") throw new Error("Required «schema.tables[" + JSON.stringify(tableId) + "].columns[" + JSON.stringify(columnId) + "].is_type»")
}
}
return schema;
}
setSchema(schema) {
this.schema = this.validateSchema(schema);
}
consumeIdOf(tableId) {
if(typeof tableId !== "string") throw new Error("Required «tableId» to be an object, found «" + typeof(tableId) + "» [0901]");
this.validateTable(tableId);
if(typeof window === "object") {
const storageId = "SDB_STORAGE_FOR_" + this.schema.schema;
if(!(storageId in localStorage)) {
localStorage[storageId] = JSON.stringify({$KEYS:{[tableId]:1},[tableId]:{}});
return 1;
}
const storageJson = localStorage[storageId];
const storageData = JSON.parse(storageJson);
const tableLastId = storageData.$KEYS[tableId]++;
localStorage[storageId] = JSON.stringify(storageData);
return tableLastId;
} else if(typeof global === "object") {
const storageId = this.baseDir + this.schema.schema + ".data.json";
const fs = require("fs");
if(!fs.existsSync(storageId)) {
fs.writeFileSync(storageId, JSON.stringify({$KEYS:{[tableId]:1},[tableId]:{}}));
return 1;
}
const storageJson = fs.readFileSync(storageId).toString();
const storageData = JSON.parse(storageJson);
const tableLastId = storageData.$KEYS[tableId]++;
fs.writeFileSync(storageId, JSON.stringify(storageData), "utf8");
return tableLastId;
}
}
getData(tableId) {
if(typeof tableId !== "string") throw new Error("Required «tableId» to be an object, found «" + typeof(tableId) + "» [0401]");
this.validateTable(tableId);
if(typeof window === "object") {
const storageId = "SDB_STORAGE_FOR_" + this.schema.schema;
if(!(storageId in localStorage)) {
localStorage[storageId] = JSON.stringify({$KEYS:{}});
}
const storageJson = localStorage[storageId];
const storageData = JSON.parse(storageJson);
if(!(tableId in storageData)) {
return {};
throw new Error("Required model «" + tableId + "» to exist in database and not only in schema «" + this.schema.schema + "» [0402]");
}
return storageData[tableId];
} else if(typeof global === "object") {
const storageId = this.baseDir + this.schema.schema + ".data.json";
const fs = require("fs");
if(!fs.existsSync(storageId)) {
fs.writeFileSync(storageId, JSON.stringify({$KEYS:{}}), "utf8");
}
const storageJson = fs.readFileSync(storageId).toString();
const storageData = JSON.parse(storageJson);
if(!(tableId in storageData)) {
return {};
throw new Error("Required model «" + tableId + "» to exist in database and not only in schema «" + this.schema.schema + "» [0403]");
}
return Object.assign({}, storageData[tableId]);
}
}
setData(tableId, modelId, data) {
if(typeof window === "object") {
if(typeof tableId !== "string") throw new Error("Required «tableId» to be a string, found «" + typeof(tableId) + "» [0501]");
if(typeof modelId !== "number") throw new Error("Required «modelId» to be an number, found «" + typeof(modelId) + "» [0502]");
if(typeof data === "undefined") {}
else if(typeof data !== "object") throw new Error("Required «data» to be an object, found «" + typeof(data) + "» [0503]");
this.validateTable(tableId);
const storageId = "SDB_STORAGE_FOR_" + this.schema.schema;
if(!(storageId in localStorage)) {
localStorage[storageId] = JSON.stringify({$KEYS:{}});
}
const storageJson = localStorage[storageId];
const storageData = JSON.parse(storageJson);
if(!(tableId in storageData)) {
storageData[tableId] = {};
storageData.$KEYS[tableId] = 1;
}
let operation = "update";
let selectedId = (modelId === 0) ? storageData.$KEYS[tableId]++ : modelId;
if(!(selectedId in storageData[tableId])) {
if(modelId !== 0) {
throw new Error("Required parameter modelId «" + modelId + "» to be 0 or to exist as id in table «" + storageId + ":" + tableId + "» [0504]")
} else operation = "insert";
}
if(typeof data === "undefined") {
delete storageData[tableId][selectedId];
} else {
if(operation === "insert") {
data.id = selectedId;
}
storageData[tableId][selectedId] = Object.assign({}, storageData[tableId][selectedId] || {}, data);
}
const json = JSON.stringify(storageData);
localStorage[storageId] = json;
return selectedId;
} else if(typeof global === "object") {
if(typeof tableId !== "string") throw new Error("Required «tableId» to be a string, found «" + typeof(tableId) + "» [1101]");
if(typeof modelId !== "number") throw new Error("Required «modelId» to be an number, found «" + typeof(modelId) + "» [1102]");
if(typeof data === "undefined") {}
else if(typeof data !== "object") throw new Error("Required «data» to be an object, found «" + typeof(data) + "» [1103]");
this.validateTable(tableId);
const fs = require("fs");
const storageId = this.baseDir + this.schema.schema + ".data.json";
if(!fs.existsSync(storageId)) {
fs.writeFileSync(storageId, JSON.stringify({[tableId]:{},$KEYS:{[tableId]:1}}), "utf8");
}
const storageJson0 = fs.readFileSync(storageId).toString();
const storageData = JSON.parse(storageJson0);
if(!(tableId in storageData)) {
storageData[tableId] = {};
storageData.$KEYS[tableId] = 1;
}
let operation = "update";
let selectedId = modelId === 0 ? storageData.$KEYS[tableId]++ : modelId;
if(!(selectedId in storageData[tableId])) {
if(modelId !== 0) {
throw new Error("Required id «" + modelId + "» to be 0 (insert) or to exist as id in table «" + storageId + ":" + tableId + "#" + modelId + "» [1104]")
} else operation = "insert";
}
if(typeof data === "undefined") {
delete storageData[tableId][selectedId];
} else {
if(operation === "insert") {
data.id = selectedId;
}
storageData[tableId][selectedId] = Object.assign({}, storageData[tableId][selectedId] || {}, data);
}
const json = JSON.stringify(storageData);
fs.writeFileSync(storageId, json, "utf8");
return selectedId;
}
}
select(tableId, filter) {
if(typeof tableId !== "string") throw new Error("Required «tableId» to be a string, found «" + typeof(tableId) + "» [0601]");
this.validateTable(tableId);
const data = this.getData(tableId);
if(typeof filter === "function") {
return Object.values(data).filter(filter).reduce((output, item) => {
try {
output[item.id] = item;
return output;
} catch (error) {
return false;
}
}, {});
} else if(typeof filter === "undefined") {
return data;
} else {
throw new Error("Required «filter» to be a valid, found «" + typeof(filter) + "» type [0602]");
}
}
insert(tableId, value) {
if(typeof tableId !== "string") throw new Error("Required «tableId» to be a string, found «" + typeof(tableId) + "» [0701]");
if(typeof value !== "object") throw new Error("Required «value» to be an object, found «" + typeof(value) + "» [0702]");
this.validateRow(tableId, value);
return this.setData(tableId, 0, value);
}
update(tableId, instanceId, value) {
if(typeof tableId !== "string") throw new Error("Required «tableId» to be a string, found «" + typeof(tableId) + "» [1201]");
if(typeof instanceId !== "number") throw new Error("Required «instanceId» to be an number, found «" + typeof(instanceId) + "» [1202]");
if(typeof value !== "object") throw new Error("Required «value» to be an object, found «" + typeof(value) + "» [1203]");
this.validateRow(tableId, value);
return this.setData(tableId, instanceId, value);
}
delete(tableId, instanceId) {
if(typeof tableId !== "string") throw new Error("Required «tableId» to be a string, found «" + typeof(tableId) + "» [1401]");
if(typeof instanceId !== "number") throw new Error("Required «instanceId» to be an number, found «" + typeof(instanceId) + "» [1402]");
this.validateTable(tableId);
return this.setData(tableId, instanceId, undefined);
}
}
SimplestDB.default = SimplestDB;
return SimplestDB;
}, this);