multi-db-orm
Version:
CRUD , Backup , Restore and Migration library for multiple databases
228 lines (202 loc) • 6.36 kB
JavaScript
const { MultiDbORM } = require("./multidb");
function replaceUndefinedWithNull(obj) {
try {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === "object" && obj[key] !== null) {
replaceUndefinedWithNull(obj[key]);
} else if (typeof obj[key] === "undefined") {
obj[key] = null;
}
}
}
} catch (e) {
console.log(
"Error in sanitizing object before insert/update ! ",
e.message
);
}
}
class FireStoreDB extends MultiDbORM {
admin;
serviceAccount;
constructor(serviceAccount, appname) {
super();
var admin = require("firebase-admin");
this.serviceAccount = serviceAccount;
if (appname) {
admin = admin.initializeApp(
{
credential: admin.credential.cert(this.serviceAccount),
databaseURL: `https://${this.serviceAccount.project_id}.firebaseio.com`,
},
appname
);
} else
admin = admin.initializeApp({
credential: admin.credential.cert(this.serviceAccount),
databaseURL: `https://${this.serviceAccount.project_id}.firebaseio.com`,
});
const db = admin.firestore();
this.db = db;
this.admin = admin;
console.log("Firestore Initialized");
this.dbType = "firestore";
}
async run(query) {
if (this.loglevel > 3)
console.log("RUN : Not Supported in DB Type", this.dbType);
}
attachOptions(modelref, options) {
if (options.apply) {
if (options.apply.ineq) {
modelref = modelref.where(
options.apply.field,
options.apply.ineq.op,
options.apply.ineq.value
);
}
if (options.apply.sort) {
modelref = modelref.orderBy(options.apply.field, options.apply.sort);
}
} else if (options.sort) {
options.sort.forEach((srt) => {
modelref = modelref.orderBy(srt.field, srt.order);
});
}
if (options.limit) {
modelref = modelref.limit(options.limit);
}
if (options.offset) {
modelref = modelref.offset(options.offset);
}
return modelref;
}
async _get(modelname, filter, options) {
const modelref = this.getdb().collection(modelname);
var where = modelref;
for (var key in filter) {
where = where.where(key, "==", filter[key]);
}
if (options) {
where = this.attachOptions(where, options);
}
const snapshot = await where.get();
if (snapshot.empty) {
return;
}
return snapshot;
}
async get(modelname, filter, options) {
var result = [];
var snapshot = await this._get(modelname, filter, options);
if (snapshot == undefined) return [];
this.metrics.get(modelname, filter, options);
let that = this;
snapshot.forEach((doc) => {
that.metrics.getOne(modelname, filter, options);
result.push(doc.data());
});
if (this.loglevel > 2) console.log("Retrieved ", result);
return result;
}
async getOne(modelname, filter, id, options) {
var idx = id || filter.id;
if (idx) {
this.metrics.getOne(modelname, filter, options);
const modelref = this.getdb().collection(modelname).doc(idx);
const doc = await modelref.get();
if (this.loglevel > 2) console.log("Retrieved ", doc.data());
return doc.data();
} else {
var rows = await this.get(modelname, filter, options);
if (rows != undefined) {
if (this.loglevel > 2) console.log("Retrieved ", rows[0]);
return rows[0];
} else {
return undefined;
}
}
}
async create(modelname, sampleObject) {
this.sync.create(modelname, sampleObject);
this.metrics.create(modelname, sampleObject);
if (this.loglevel > 3)
console.log("CREATE : Not required in DB Type", this.dbType);
}
async insert(modelname, object, id) {
replaceUndefinedWithNull(object);
this.sync.insert(modelname, object, id);
this.metrics.insert(modelname, object, id);
var db = this.getdb();
var idx = id || object.id || Date.now();
const docref = db.collection(modelname).doc("" + idx);
try {
replaceUndefinedWithNull(object);
return await docref.set(object);
} catch (e) {
if (
e.message.indexOf(
"Firestore doesn't support JavaScript objects with custom prototypes"
) > -1
) {
return await docref.set(JSON.parse(JSON.stringify(object)));
} else {
throw e;
}
}
}
async update(modelname, filter, object, id) {
this.sync.update(modelname, filter, object, id);
var idx = id || filter.id || object.id;
try {
replaceUndefinedWithNull(object);
if (idx) {
this.metrics.update(modelname, filter, object, id);
await this.getdb().collection(modelname).doc(idx).update(object);
} else {
var snaps = (await this._get(modelname, filter)) || [];
let that = this;
snaps.forEach(async function (element) {
that.metrics.getOne(modelname, filter, id);
that.metrics.update(modelname, filter, object, id);
await element.ref.update(object);
});
}
} catch (e) {
if (
e.message.indexOf(
"Firestore doesn't support JavaScript objects with custom prototypes"
) > -1
) {
return await this.update(
modelname,
filter,
JSON.parse(JSON.stringify(object)),
id
);
} else {
throw e;
}
}
}
async delete(modelname, filter, id) {
this.sync.delete(modelname, filter, id);
var idx = id || filter.id;
if (idx) {
this.metrics.delete(modelname, filter, id);
await this.getdb().collection(modelname).doc(idx).delete();
} else {
var snaps = (await this._get(modelname, filter)) || [];
let that = this;
snaps.forEach(async function (element) {
that.metrics.getOne(modelname, filter, id);
that.metrics.delete(modelname, filter, id);
await element.ref.delete();
});
}
}
}
module.exports = {
FireStoreDB,
};