UNPKG

@stoqey/firestore

Version:

NodeJS Firebase Firestore CRUD library

562 lines 25.8 kB
"use strict"; 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); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseFireStore = void 0; var isEmpty_1 = __importDefault(require("lodash/isEmpty")); var _utils_1 = require("./_utils"); /** * This is the Base class to fetch and store data to Firestore */ var BaseFireStore = /** @class */ (function () { function BaseFireStore(db, options) { this.db = db; this.collection = 'test'; this.storageRef = 'images'; this.options = options; // debug flag } BaseFireStore.prototype.logger = function (event) { // @ts-ignore var defaultLogger = function () { return console.log(event && event.message, event); }; if (this.options && this.options.debug) { return this.options.logger ? this.options.logger(event) : defaultLogger(); } return null; }; /** * Return the collection */ BaseFireStore.prototype.getRef = function () { return this.db.collection(this.collection); }; /** * @param {String} path * @return {arrayObject} deployedApps by user */ BaseFireStore.prototype.autoPagination = function (query) { return __awaiter(this, void 0, void 0, function () { var limit, page, fields, data_1, startAt, total, nextData_1, error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: limit = query.limit ? query.limit : 10; page = query.page ? query.page : 1; fields = query.whereAll; _a.label = 1; case 1: _a.trys.push([1, 4, , 5]); data_1 = this.getRef(); // Add all fields conditions, fields.forEach(function (field) { data_1 = data_1.where(field.name, field.operator, field.value); }); return [4 /*yield*/, data_1.get().then(function (snapshot) { var docsAt = (page - 1) * limit; var startAt = snapshot.docs[docsAt]; var total = snapshot.docs.length; return { startAt: startAt, total: total }; })]; case 2: data_1 = _a.sent(); startAt = data_1.startAt, total = data_1.total; // if null return if (total <= 0) { return [2 /*return*/, { data: [], total: 0 }]; } nextData_1 = this.getRef(); // Add all fields conditions, fields.forEach(function (field) { nextData_1 = nextData_1.where(field.name, field.operator, field.value); }); return [4 /*yield*/, nextData_1 .limit(Number(limit)) .startAt(startAt) .get().then(function (docSnapshot) { var docData = docSnapshot.docs.map(function (doc) { return __assign(__assign({}, doc.data()), { id: doc.id }); }); return docData; })]; case 3: nextData_1 = _a.sent(); return [2 /*return*/, { data: nextData_1, total: total }]; case 4: error_1 = _a.sent(); console.log('Error', error_1); return [2 /*return*/, { data: [], total: 0 }]; case 5: return [2 /*return*/]; } }); }); }; /** * Return all data from a collection with pagination support. * @param {Object} query */ BaseFireStore.prototype.all = function (query) { if (query === void 0) { query = {}; } return __awaiter(this, void 0, void 0, function () { var limit, page, data, startAt, totalPosts, nextData, error_2; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: limit = query.limit ? query.limit : 1000; page = query.page ? query.page : 1; _a.label = 1; case 1: _a.trys.push([1, 4, , 5]); return [4 /*yield*/, this.getRef() .get() .then(function (snapshot) { return __awaiter(_this, void 0, void 0, function () { var docsAt, startAt, totalPosts; return __generator(this, function (_a) { docsAt = (page - 1) * limit; startAt = snapshot.docs[docsAt]; totalPosts = snapshot.docs.length; return [2 /*return*/, { startAt: startAt, totalPosts: totalPosts }]; }); }); })]; case 2: data = _a.sent(); startAt = data.startAt, totalPosts = data.totalPosts; return [4 /*yield*/, this.getRef() // .orderBy('createdAt', 'desc') .limit(Number(limit)) .startAt(startAt) .get() .then(function (docSnapshot) { var data = docSnapshot.docs.map(function (doc) { return __assign(__assign({}, doc.data()), { id: doc.id }); }); return data; })]; case 3: nextData = _a.sent(); return [2 /*return*/, { data: nextData, total: totalPosts }]; case 4: error_2 = _a.sent(); this.logger(error_2); return [2 /*return*/, Promise.reject(error_2)]; case 5: return [2 /*return*/]; } }); }); }; /** * Fetch collection with where conditions * @param {Object} query */ BaseFireStore.prototype.where = function (query) { if (query === void 0) { query = {}; } return __awaiter(this, void 0, void 0, function () { var limit, field, operator, value, multiple, data, error_3; return __generator(this, function (_a) { switch (_a.label) { case 0: limit = query.limit ? query.limit : 1000; field = query.field ? query.field : null; operator = query.operator ? query.operator : '=='; value = query.value ? query.value : null; multiple = query.multiple ? query.multiple : false; data = []; _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, this.getRef() .limit(Number(limit)) .where(field, operator, value) .get() .then(function (snapshot) { snapshot.docs.map(function (doc) { data.push(__assign(__assign({}, doc.data()), { id: doc.id })); }); })]; case 2: _a.sent(); if (multiple) { return [2 /*return*/, data]; } else { return [2 /*return*/, data[0] ? data[0] : null]; } return [3 /*break*/, 4]; case 3: error_3 = _a.sent(); this.logger(error_3); return [2 /*return*/, Promise.reject(error_3)]; case 4: return [2 /*return*/]; } }); }); }; /** * Fetch collection with where conditions * @param {Object} query */ BaseFireStore.prototype.whereAll = function (query) { return __awaiter(this, void 0, void 0, function () { var fields, sort, _a, multiple, _b, limit, _c, snapshot, data, findQuery_1, error_4; return __generator(this, function (_d) { switch (_d.label) { case 0: fields = query.fields, sort = query.sort, _a = query.multiple, multiple = _a === void 0 ? false : _a, _b = query.limit, limit = _b === void 0 ? 1000 : _b, _c = query.snapshot, snapshot = _c === void 0 ? false : _c; data = []; _d.label = 1; case 1: _d.trys.push([1, 3, , 4]); findQuery_1 = this.getRef(); // Add all fields conditions, fields.forEach(function (field) { findQuery_1 = findQuery_1.where(field.name, field.operator, field.value); }); if (sort && !isEmpty_1.default(sort)) { // Add all sorts sort.forEach(function (field) { findQuery_1 = findQuery_1.orderBy(field.name, field.direction); }); } return [4 /*yield*/, findQuery_1.limit(Number(limit)).get() .then(function (snapshotData) { if (snapshot) { return snapshotData; } // do parse data snapshotData.docs.map(function (doc) { data.push(__assign(__assign({}, doc.data()), { id: doc.id })); }); })]; case 2: _d.sent(); if (isEmpty_1.default(data)) { return [2 /*return*/, null]; } if (multiple) { return [2 /*return*/, data]; } else { // Return one item only return [2 /*return*/, data[0]]; } return [3 /*break*/, 4]; case 3: error_4 = _d.sent(); this.logger(error_4); return [2 /*return*/, Promise.reject(error_4)]; case 4: return [2 /*return*/]; } }); }); }; /** * Fetch documents which falls between two range * @param {Object} query */ BaseFireStore.prototype.range = function (query) { if (query === void 0) { query = {}; } return __awaiter(this, void 0, void 0, function () { var field, min, max, posts, data, error_5; return __generator(this, function (_a) { switch (_a.label) { case 0: field = query.field, min = query.min, max = query.max; posts = []; _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, this.getRef() .where(field, '>=', min) .where(field, '<=', max) .get() .then(function (snapshot) { snapshot.docs.map(function (doc) { posts.push(__assign(__assign({}, doc.data()), { id: doc.id })); }); return posts; })]; case 2: data = _a.sent(); return [2 /*return*/, data]; case 3: error_5 = _a.sent(); this.logger(error_5); return [2 /*return*/, Promise.reject(error_5)]; case 4: return [2 /*return*/]; } }); }); }; /** * Fetch a document by its ID * @param id */ BaseFireStore.prototype.byId = function (id) { return __awaiter(this, void 0, void 0, function () { var error_6; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); return [4 /*yield*/, this.getRef() .doc(id) .get() .then(function (item) { return __assign(__assign({}, item.data()), { id: id }); })]; case 1: return [2 /*return*/, _a.sent()]; case 2: error_6 = _a.sent(); this.logger(error_6); return [2 /*return*/, Promise.reject(error_6)]; case 3: return [2 /*return*/]; } }); }); }; /** * Delete a document by its ID * @param id */ BaseFireStore.prototype.delete = function (id) { if (id === void 0) { id = null; } return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { try { return [2 /*return*/, this.getRef() .doc(id) .delete() // Deleting a document does not delete its subcollections! .then(function () { return { id: id }; })]; } catch (error) { this.logger(error); return [2 /*return*/, Promise.reject(error)]; } return [2 /*return*/]; }); }); }; BaseFireStore.prototype.byName = function (name) { return __awaiter(this, void 0, void 0, function () { var error_7; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); return [4 /*yield*/, this.getRef() .where('name', '==', name) .get() .then(function (snapshot) { var docs = snapshot.docs.map(function (doc) { return (__assign(__assign({}, doc.data()), { id: doc.id })); }); return docs[0]; // first item })]; case 1: return [2 /*return*/, _a.sent()]; case 2: error_7 = _a.sent(); this.logger(error_7); return [2 /*return*/, Promise.reject(error_7)]; case 3: return [2 /*return*/]; } }); }); }; /** * Push a new document under a specific collection check if name exists, else update it * @param {Object} query * @checkName is @true by `default` */ BaseFireStore.prototype.add = function (data, options) { return __awaiter(this, void 0, void 0, function () { var checkName, cleanDocument, oldByName, error_8; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: data = __assign(__assign({}, data), { createdAt: new Date() }); _a.label = 1; case 1: _a.trys.push([1, 4, , 5]); checkName = options && options.checkName || true; cleanDocument = data; if (!(checkName && data.name)) return [3 /*break*/, 3]; return [4 /*yield*/, this.byName(data.name)]; case 2: oldByName = _a.sent(); if (oldByName) { // We have the old by name update it now return [2 /*return*/, this.update({ id: oldByName.id, data: cleanDocument, })]; } _a.label = 3; case 3: // Default add document return [2 /*return*/, this.getRef() .add(cleanDocument) .then(function (doc) { return _this.byId(doc.id); })]; case 4: error_8 = _a.sent(); this.logger(error_8); return [2 /*return*/, Promise.reject(error_8)]; case 5: return [2 /*return*/]; } }); }); }; // if you are not sure weather to add or update BaseFireStore.prototype.set = function (query) { if (query === void 0) { query = {}; } return __awaiter(this, void 0, void 0, function () { var id, data, post, error_9; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: id = query.id ? query.id : null; data = query.data ? query.data : {}; data = __assign(__assign({}, data), { updatedAt: _utils_1.getTimeStamp() }); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, this.getRef() .doc(id) .set(data, { merge: true }) .then(function () { return _this.byId(id); })]; case 2: post = _a.sent(); return [2 /*return*/, post]; case 3: error_9 = _a.sent(); this.logger(error_9); return [2 /*return*/, Promise.reject(error_9)]; case 4: return [2 /*return*/]; } }); }); }; /** * Update a document by ID and new data * @param {Object} query */ BaseFireStore.prototype.update = function (query) { if (query === void 0) { query = {}; } return __awaiter(this, void 0, void 0, function () { var id, data, post, error_10; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: id = query.id ? query.id : null; data = query.data ? query.data : {}; data = __assign(__assign({}, data), { updatedAt: _utils_1.getTimeStamp() }); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, this.getRef() .doc(id) .update(data) .then(function () { return _this.byId(id); })]; case 2: post = _a.sent(); return [2 /*return*/, post]; case 3: error_10 = _a.sent(); this.logger(error_10); return [2 /*return*/, Promise.reject(error_10)]; case 4: return [2 /*return*/]; } }); }); }; /** * timelinePagination * Pagination using createdAt from newest time to older -> * Alway DESC * use start and order to pull chunk from a specific time range */ BaseFireStore.prototype.timelinePagination = function (args) { return __awaiter(this, void 0, void 0, function () { var db, order, _a, limit, startAt; return __generator(this, function (_b) { switch (_b.label) { case 0: db = this; order = args.order, _a = args.limit, limit = _a === void 0 ? 10 : _a; startAt = new Date(args.start || new Date()); return [4 /*yield*/, db.whereAll({ fields: [ { name: 'createdAt', operator: order === 'new' ? '>' : '<', value: startAt } ], sort: [ { name: 'createdAt', direction: 'desc' } ], multiple: true, limit: limit, })]; case 1: return [2 /*return*/, _b.sent()]; } }); }); }; return BaseFireStore; }()); exports.BaseFireStore = BaseFireStore; exports.default = BaseFireStore; //# sourceMappingURL=base.js.map