Merge pull request #3 from Nez27/feat/add-common-service-and-class

Add common service and base class
This commit is contained in:
Loi Phan
2023-09-29 09:02:59 +07:00
committed by GitHub
17 changed files with 493 additions and 291 deletions
-288
View File
@@ -3168,15 +3168,6 @@
"safe-buffer": "^5.0.1"
}
},
"node_modules/big-integer": {
"version": "1.6.51",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
"integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==",
"dev": true,
"engines": {
"node": ">=0.6"
}
},
"node_modules/binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
@@ -3255,21 +3246,6 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
"node_modules/bundle-name": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz",
"integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==",
"dev": true,
"dependencies": {
"run-applescript": "^5.0.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/call-bind": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
@@ -4482,12 +4458,6 @@
"is-callable": "^1.1.3"
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"dev": true
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
@@ -4944,18 +4914,6 @@
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
},
"node_modules/is-bigint": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
"integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
"dev": true,
"dependencies": {
"has-bigints": "^1.0.1"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
@@ -4968,22 +4926,6 @@
"node": ">=8"
}
},
"node_modules/is-boolean-object": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
"integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
@@ -5108,21 +5050,6 @@
"node": ">=0.12.0"
}
},
"node_modules/is-number-object": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
"integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
"dev": true,
"dependencies": {
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-path-inside": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
@@ -5160,18 +5087,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
"integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
"dev": true,
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-string": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
@@ -5256,18 +5171,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/isarray": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
"dev": true
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -5628,12 +5531,6 @@
"optional": true,
"peer": true
},
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
"dev": true
},
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -5655,18 +5552,6 @@
"node": ">=8.6"
}
},
"node_modules/mimic-fn": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
"integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -5788,33 +5673,6 @@
"node": ">=0.10.0"
}
},
"node_modules/npm-run-path": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
"integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
"dev": true,
"dependencies": {
"path-key": "^4.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/npm-run-path/node_modules/path-key": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
"integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/nth-check": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
@@ -5927,30 +5785,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dev": true,
"dependencies": {
"wrappy": "1"
}
},
"node_modules/onetime": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
"integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
"dev": true,
"dependencies": {
"mimic-fn": "^4.0.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/open": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz",
@@ -6089,15 +5923,6 @@
"node": ">=8"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -6380,110 +6205,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/run-applescript": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz",
"integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==",
"dev": true,
"dependencies": {
"execa": "^5.0.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/run-applescript/node_modules/execa": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
"integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
"dev": true,
"dependencies": {
"cross-spawn": "^7.0.3",
"get-stream": "^6.0.0",
"human-signals": "^2.1.0",
"is-stream": "^2.0.0",
"merge-stream": "^2.0.0",
"npm-run-path": "^4.0.1",
"onetime": "^5.1.2",
"signal-exit": "^3.0.3",
"strip-final-newline": "^2.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
"node_modules/run-applescript/node_modules/human-signals": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
"dev": true,
"engines": {
"node": ">=10.17.0"
}
},
"node_modules/run-applescript/node_modules/is-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
"dev": true,
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/run-applescript/node_modules/mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/run-applescript/node_modules/npm-run-path": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
"integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
"dev": true,
"dependencies": {
"path-key": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/run-applescript/node_modules/onetime": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
"dev": true,
"dependencies": {
"mimic-fn": "^2.1.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/run-applescript/node_modules/strip-final-newline": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -7060,15 +6781,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/untildify": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
"integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/update-browserslist-db": {
"version": "1.0.13",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
+1 -1
View File
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
+1 -1
View File
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
+1 -1
View File
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
@@ -0,0 +1,28 @@
export const DATABASE_URL =
'https://javascript-training-81f7a-default-rtdb.asia-southeast1.firebasedatabase.app';
export const TIME_OUT_SEC = 3;
export const BTN_CONTENT = {
GOT_IT: 'Got it!',
OK: 'Ok',
};
export const LOCAL_STORAGE = {
ACCESS_TOKEN: 'accessToken',
};
export enum TYPE_TOAST {
success = 'success',
error = 'error',
}
export enum MARK_ICON {
success = 'check',
error = 'error',
}
export const REGEX = {
PASSWORD:
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/,
EMAIL:
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|.(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
};
@@ -0,0 +1,17 @@
export const ERROR_MESSAGE_DEFAULT = ['Something went wrong!'];
export const TIME_OUT_ERROR = 'Connection time out! Please try again!';
export const DEFAULT_TITLE_ERROR_TOAST = 'Error';
export const USER_EXIST_ERROR = 'User is exists! Please try another email!';
export const ADD_WALLET_SUCCESS = 'Add wallet success!';
export const DEFAULT_MESSAGE = 'Press OK to continue!';
export const ADD_TRANSACTION_SUCCESS = 'Add success!';
export const UPDATE_TRANSACTION_SUCCESS = 'Update success!';
export const REGISTER_SUCCESS = 'Register Success';
@@ -0,0 +1,13 @@
export const PASSWORD_NOT_MATCH = 'Password not match!';
export const PASSWORD_NOT_STRONG =
'Password must at least one uppercase, one lowercase letter, one number and one special character!';
export const ERROR_CREDENTIAL = {
title: 'Error Credential',
message: 'Email or password not match! Please try again!',
};
export const INVALID_EMAIL_FORMAT = `The email is not correct!`;
export const REQUIRED_MESSAGE = (field: string) => `The ${field} is required!`;
@@ -0,0 +1,15 @@
export interface IDataObject<T> {
id: string;
data: T;
}
export class DataObject<T> {
public id: string;
public data: T;
constructor(dataObject: IDataObject<T>) {
this.id = dataObject?.id ?? null;
this.data = dataObject.data as T;
}
}
@@ -0,0 +1,33 @@
import { TIME_OUT_ERROR } from '../constants/messages/dialog';
import { TIME_OUT_SEC } from '../constants/config';
import FirebaseService from '../services/firebaseService';
/**
* A waiting function with s second
* @param {number} s The time will be waiting
* @returns {Promise} A Promise will be only reject after s second
*/
export const timeout = (s: number): Promise<string> => {
return new Promise((_, reject) => {
setTimeout(() => {
FirebaseService.disconnect();
reject(TIME_OUT_ERROR);
}, s * 1000);
});
};
/**
* A function waiting the action need to be perform and throw error after s second.
* @param {Function} action The action need to be perform.
* @returns { Object || Error } Return the any object from Firebase or Error
*/
export const timeOutConnect = async <T>(
action: Promise<T>,
): Promise<string | T> => {
const result: T | string = await Promise.race([
action,
timeout(TIME_OUT_SEC),
]);
return result;
};
@@ -0,0 +1,19 @@
import { DataObject } from '../global/types';
export const createIdUser = (): number => {
return new Date().getTime();
};
export const convertDataObjectToModel = <T>(dataObj: DataObject<T>): T => {
const { id } = dataObj;
return { id, ...dataObj.data } as T;
};
export const convertModelToDataObject = <T extends DataObject<T>>(
model: T,
): T => {
const { id, ...data } = model;
return { id, data } as T;
};
@@ -0,0 +1,4 @@
// eslint-disable-next-line import/prefer-default-export
export const redirectToLoginPage = (): void => {
window.location.replace('/login');
};
@@ -0,0 +1,30 @@
import { REGEX } from '../constants/config';
import { REQUIRED_MESSAGE } from '../constants/messages/form';
/**
* Validate password
* @param {string} password Password input
* @returns {boolean} Return true if validate password success, otherwise return false
*/
export const isValidPassword = (password: string): boolean => {
return REGEX.PASSWORD.test(password);
};
export const isValidateEmail = (email: string): RegExpMatchArray | null => {
return String(email).toLowerCase().match(REGEX.EMAIL);
};
export const compare2Password = (
password: string,
passwordConfirm: string,
): boolean => {
return password === passwordConfirm;
};
export const renderRequiredText = (field: string, element: Element): void => {
const markup: string = `
<p class="error-text">${REQUIRED_MESSAGE(field)}</p>
`;
element.insertAdjacentHTML('afterend', markup);
};
+18
View File
@@ -0,0 +1,18 @@
import { createIdUser } from '../helpers/data';
export default class User {
private id: number;
private email: string;
private password: string;
private accessToken: string;
constructor(email: string, password: string, accessToken: string) {
this.id = createIdUser();
this.email = email;
this.password = password;
this.accessToken = accessToken;
}
}
@@ -0,0 +1,109 @@
import { timeOutConnect } from '../helpers/connect';
import {
convertDataObjectToModel,
convertModelToDataObject,
} from '../helpers/data';
import { DataObject } from '../global/types';
import FirebaseService from './firebaseService';
export default class CommonService<T extends DataObject<T>> {
private defaultPath: string = '/';
private firebaseService = FirebaseService;
/**
* Connect to Firebase Database
*/
connectToDb() {
this.firebaseService.reconnect();
}
/**
* Save data on database
* @param {*} data The data wants to save on database
* @param {string} path The path of database
*/
async save(model: T): Promise<void> {
this.connectToDb();
const results: T = convertModelToDataObject(model);
const saveData = this.firebaseService.save(
results.data,
this.defaultPath + results.id,
);
await timeOutConnect(saveData);
}
/**
*
* @param {string} id The string of data object
* @param {string} path The path of database
* @returns {Object || null} Return the object if has, otherwise return null
*/
async getDataFromId(
id: string,
path: string = this.defaultPath,
): Promise<object | null> {
this.connectToDb();
const data = await timeOutConnect(
this.firebaseService.getDataFromId(id, path),
);
if (typeof data === 'object') return data;
return null;
}
async getAllDataFromPath(path = this.defaultPath): Promise<object[] | null> {
this.connectToDb();
const results = await timeOutConnect(
this.firebaseService.getAllDataFromPath(path),
);
if (typeof results === 'object') {
// Convert format object
return results.map((data) => {
const tempData = data as DataObject<T>;
return convertDataObjectToModel(tempData);
});
}
return null;
}
async getListDataFromProp(
property: string,
value: object,
path: string = this.defaultPath,
): Promise<object[] | null> {
this.connectToDb();
const results = await timeOutConnect(
this.firebaseService.getListDataFromProp(path, property, value),
);
if (results && typeof results === 'object') {
// Convert format object
return results.map((data) => {
const tempData = data as DataObject<T>;
return convertDataObjectToModel(tempData);
});
}
return null;
}
async deleteData(
id: string,
path = this.defaultPath,
): Promise<string | void> {
this.connectToDb();
await timeOutConnect(this.firebaseService.delete(id, path));
}
}
@@ -0,0 +1,178 @@
import { FirebaseApp, initializeApp } from 'firebase/app';
import {
getDatabase,
ref,
set,
goOffline,
goOnline,
onValue,
remove,
Database,
} from 'firebase/database';
import { DATABASE_URL } from '../constants/config';
class FirebaseService {
private app: FirebaseApp;
private db: Database;
constructor() {
const firebaseConfig = {
databaseURL: DATABASE_URL,
};
this.app = initializeApp(firebaseConfig);
this.db = getDatabase(this.app);
}
/**
* Save data in database
* @param {Object} data The object need to save into database
* @param {string} path The path of database need to be save
* @returns {Promise} Return the resolves when write to database completed
*/
save(data: object, path: string): Promise<void> {
return set(ref(this.db, path), data);
}
delete(id: string, path: string): Promise<void> {
return remove(ref(this.db, path + id));
}
/**
* Disconnect to database
*/
disconnect(): void {
goOffline(this.db);
}
/**
* Reconnect to database
*/
reconnect(): void {
goOnline(this.db);
}
/**
* Find id of value by property in database
* @param {string} path The path of database to be found
* @param {string} property The property of the value need to be found
* @param {value} value The value to compare in database
* @returns {Promise} Return the resolve when find completed
*/
getDataFromProp(
path: string,
property: string,
value: object,
): Promise<object | null> {
return new Promise((resolve) => {
onValue(
ref(this.db, path),
(snapshot) => {
let id: string | null = null;
let data: object | null = null;
let result: object | null = null;
// snapshot is a type of data by Firebase define
snapshot.forEach((childSnapshot) => {
const dataTemp = childSnapshot.val();
if (dataTemp[property] === value) {
id = childSnapshot.key;
data = dataTemp;
}
});
if (id && data) {
result = { id, data };
}
resolve(result);
},
{
onlyOnce: true,
},
);
});
}
/**
* Get data object from Id
* @param {string} id The id of data object
* @param {string} path The path of data save in database
* @returns {Promise} Return new Promise
*/
getDataFromId(id: string, path: string): Promise<object> {
return new Promise((resolve) => {
onValue(
ref(this.db, path + id),
(snapshot) => {
resolve(snapshot.val());
},
{
onlyOnce: true,
},
);
});
}
getAllDataFromPath(path: string): Promise<object[]> {
return new Promise((resolve) => {
onValue(
ref(this.db, path),
(snapshot) => {
let listData: object[] = [];
// snapshot is a type of data by Firebase define
snapshot.forEach((childSnapshot) => {
let id: string | null = null;
let data: object | null = null;
id = childSnapshot.key;
data = childSnapshot.val();
listData.push({ id, data });
});
resolve(listData);
},
{
onlyOnce: true,
},
);
});
}
getListDataFromProp(
path: string,
property: string,
value: object,
): Promise<object[]> {
return new Promise((resolve) => {
onValue(
ref(this.db, path),
(snapshot) => {
let id: string;
let data: object;
const listData: object[] = [];
// snapshot is a type of data by Firebase define
snapshot.forEach((childSnapshot) => {
const dataTemp = childSnapshot.val();
if (dataTemp[property] === value) {
id = childSnapshot.key;
data = dataTemp;
listData.push({ id, data });
}
});
resolve(listData);
},
{
onlyOnce: true,
},
);
});
}
}
export default new FirebaseService();
@@ -0,0 +1 @@
export default class Service {}
@@ -0,0 +1,25 @@
class LocalStorageService {
private localStorage: Storage;
constructor() {
this.localStorage = localStorage;
}
add(key: string, value: string): void {
this.localStorage.setItem(key, value);
}
get(key: string): string | null {
return this.localStorage.getItem(key);
}
remove(key: string): void {
this.localStorage.removeItem(key);
}
clear(): void {
this.localStorage.clear();
}
}
export default new LocalStorageService();