diff --git a/src/app/FirebaseResource.ts b/src/app/FirebaseResource.ts new file mode 100644 index 0000000..fd53ef6 --- /dev/null +++ b/src/app/FirebaseResource.ts @@ -0,0 +1,65 @@ +import {Inject, Injectable} from "@extollo/di" +import {Collection, Iterable} from "@extollo/util" +import {FirebaseUnit, RTDBRef} from "./units/FirebaseUnit" +import * as firebase from "firebase-admin" +import {Application} from "@extollo/lib"; + +export interface FirebaseResourceItem { + seqID: number +} + +@Injectable() +export class FirebaseResource extends Iterable { + protected refName!: RTDBRef + + ref(): firebase.database.Reference { + return Application.getApplication().make(FirebaseUnit).ref(this.refName) + } + + async getNextID(): Promise { + return new Promise((res, rej) => { + this.ref().orderByChild('seqID') + .on('value', snapshot => { + res(this.resolveObject(snapshot.val()).reverse()?.[0]?.seqID || 1) + }, rej) + }) + } + + async at(i: number): Promise { + return new Promise((res, rej) => { + this.ref().orderByChild('seqID') + .startAt(i).endAt(i) + .on('value', snapshot => res(this.resolveObject(snapshot.val())[0]), rej) + }) + } + + async range(start: number, end: number): Promise> { + return new Promise>((res, rej) => { + this.ref().orderByChild('seqID') + .startAt(start).endAt(end) + .on('value', snapshot => { + res(new Collection(this.resolveObject(snapshot.val()))) + }, rej) + }) + } + + async count(): Promise { + return new Promise((res, rej) => { + this.ref().orderByChild('seqID') + .on('value', snapshot => { + res(this.resolveObject(snapshot.val()).length) + }, rej) + }) + } + + protected resolveObject(snapshot: object | null | undefined) { + if ( !snapshot ) snapshot = {} + return Object.values(snapshot) + } + + clone(): Iterable { + const inst = new FirebaseResource() + inst.refName = this.refName + return inst + } +} diff --git a/src/app/configs/app.config.ts b/src/app/configs/app.config.ts index d068279..a4a026e 100644 --- a/src/app/configs/app.config.ts +++ b/src/app/configs/app.config.ts @@ -10,6 +10,14 @@ export default { .toString('utf-8') ), - defaultRTDB: env('FIREBASE_DEFAULT_RTDB', 'https://loc-chain-default-rtdb.firebaseio.com'), + api_auth_header: env('FIREBASE_API_AUTH_HEADER', 'X-Auth-Token'), + + rtdb: { + default: env('FIREBASE_DEFAULT_RTDB', 'https://loc-chain-default-rtdb.firebaseio.com'), + refs: { + peers: 'chain/server/peers', + transaction: 'chain/pending/transactions', + }, + }, } } diff --git a/src/app/rtdb/TransactionResource.ts b/src/app/rtdb/TransactionResource.ts new file mode 100644 index 0000000..c172992 --- /dev/null +++ b/src/app/rtdb/TransactionResource.ts @@ -0,0 +1,21 @@ +import {FirebaseResource, FirebaseResourceItem} from "../FirebaseResource" +import {Injectable} from "@extollo/di" +import {RTDBRef} from "../units/FirebaseUnit" +import {AsyncCollection} from "@extollo/util"; + +export interface TransactionResourceItem extends FirebaseResourceItem { + combinedHash: string; + timestamp: number; + encodedGPSLocation: string; + partnerPublicKey: string; + validationSignature: string; +} + +@Injectable() +export class TransactionResource extends FirebaseResource { + public static collect(): AsyncCollection { + return new AsyncCollection(new TransactionResource()) + } + + protected refName: RTDBRef = 'transaction' +} diff --git a/src/app/units/FirebaseUnit.ts b/src/app/units/FirebaseUnit.ts index f7efbf4..dee0e58 100644 --- a/src/app/units/FirebaseUnit.ts +++ b/src/app/units/FirebaseUnit.ts @@ -2,6 +2,8 @@ import {Singleton, Inject} from "@extollo/di" import {Unit, Logging, Config} from "@extollo/lib" import * as firebase from "firebase-admin" +export type RTDBRef = 'peers' | 'transaction' + /** * FirebaseUnit Unit * --------------------------------------- @@ -21,12 +23,18 @@ export class FirebaseUnit extends Unit { return this._firebase } + ref(name: RTDBRef): firebase.database.Reference { + return this._firebase.database().ref( + String(this.config.get(`app.firebase.rtdb.refs.${name}`)) + ) + } + /** Called on app start. */ public async up() { this.logging.info('Initializing Firebase application credentials...') this._firebase.initializeApp({ credential: firebase.credential.cert(this.config.get('app.firebase.credentials')), - databaseURL: this.config.get('app.firebase.defaultRTDB'), + databaseURL: this.config.get('app.firebase.rtdb.default'), }) }