Skip to content

Commit

Permalink
feat: initial setup for mongo #447
Browse files Browse the repository at this point in the history
  • Loading branch information
flauc committed Nov 30, 2022
1 parent 63584a0 commit 75a04bc
Show file tree
Hide file tree
Showing 5 changed files with 447 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {Injectable} from '@angular/core';
import {getDownloadURL, ref, Storage, StorageReference, uploadBytes} from '@angular/fire/storage';
import {StorageService} from '@jaspero/form-builder';

@Injectable()
export class FbStorageService extends StorageService {
constructor(
public storage: Storage
) {
super();
}

upload(path: string, data: any, metadata?: any) {
return uploadBytes(
ref(this.storage, path),
data,
metadata
);
}

getDownloadURL(ref: StorageReference) {
return getDownloadURL(ref);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export enum FirebaseOperator {
Equal = '==',
LargerThen = '>',
SmallerThen = '<',
LargerThenOrEqual = '>=',
SmallerThenOrEqual = '<=',
ArrayContains = 'array-contains'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,331 @@
import {Injectable} from '@angular/core';
import {
collection,
collectionData,
collectionGroup,
deleteDoc,
doc,
docData,
Firestore,
getDoc,
getDocs,
getDocsFromCache,
getDocsFromServer,
limit,
onSnapshot,
orderBy,
query,
setDoc,
startAfter,
where
} from '@angular/fire/firestore';
import {Functions, httpsCallableData} from '@angular/fire/functions';
import {FilterMethod, SHARED_CONFIG} from '@definitions';
import {Parser} from '@jaspero/form-builder';
import {from, Observable} from 'rxjs';
import {map} from 'rxjs/operators';
import {WhereFilter} from '../../src/app/shared/interfaces/where-filter.interface';
import {DbService} from '../../src/app/shared/services/db/db.service';
import {environment} from '../../src/environments/environment';

@Injectable()
export class MongoDatabaseService extends DbService {
constructor(
private firestore: Firestore,
private functions: Functions
) {
super();
}

url(url: string) {

if (environment.origin) {
return [
environment.origin,
environment.firebase.projectId,
SHARED_CONFIG.cloudRegion,
url
]
.join('/');
} else {
return `https://${SHARED_CONFIG.cloudRegion}-${environment.firebase.projectId}.cloudfunctions.net/${url}`;
}
}

getDocuments(
moduleId,
pageSize,
sort?,
cursor?,
filters?,
source?,
collectionGroup?
) {
const sources = {
server: getDocsFromServer,
cache: getDocsFromCache
};
const method = source ? sources[source] : getDocs;

return from(
method(
this.collection(moduleId, pageSize, sort, cursor, filters, collectionGroup)
)
)
.pipe(
map((res: any) =>
res.docs
)
);
}

getStateChanges(
moduleId,
pageSize?,
sort?,
cursor?,
filters?: WhereFilter[],
collectionGroup?
) {
return new Observable(observer =>
onSnapshot(
this.collection(
moduleId,
pageSize,
sort,
cursor,
filters,
collectionGroup
),
snap => {
const docs = snap.docChanges().filter(it => !it.doc.metadata.hasPendingWrites);
if (docs.length) {
observer.next(docs);
}
})
) as Observable<any>;
}

getValueChanges(
moduleId,
pageSize?,
sort?,
cursor?,
filters?: WhereFilter[],
collectionGroup?
) {
return collectionData(
this.collection(
moduleId,
pageSize,
sort,
cursor,
filters,
collectionGroup
),
{
idField: 'id'
}
);
}

getDocument<T = any>(
moduleId,
documentId,
stream = false
): Observable<T> {
if (stream) {
return docData<T>(
doc(
this.firestore,
moduleId,
documentId
) as any,
{idField: 'id'}
);
}

return from(
getDoc(
doc(
this.firestore,
moduleId,
documentId
)
)
)
.pipe(
map(snap => ({
...snap.data(),
id: documentId
} as any))
);

}

getDocumentsSimple(moduleId, sort?, filter?) {
return from(
getDocs(
query(
collection(this.firestore, moduleId),
...[
sort && orderBy(sort, 'asc'),
filter && where(filter.key, filter.operator, filter.value)
]
.filter(it => it)
)
)
)
.pipe(
map(data =>
data.docs.map((it: any) => ({
id: it.id,
...it.data()
}))
)
);
}

getSubdocumentsSimple(moduleId, sort?, filter?) {
return from(
getDocs(
query(
collectionGroup(this.firestore, moduleId),
...[
sort && orderBy(sort.active, sort.direction),
filter && where(filter.key, filter.operator, filter.value)
]
.filter(it => it)
)
)
)
.pipe(
map(data =>
data.docs.map((it: any) => ({
id: it.id,
...it.data()
}))
)
);
}

setDocument(moduleId, documentId, data, options) {
return from(
setDoc(
doc(
this.firestore,
moduleId,
documentId
),
data,
options || {}
)
);
}

removeDocument(moduleId, documentId) {
return from(
deleteDoc(
doc(
this.firestore,
moduleId,
documentId
)
)
);
}

createUserAccount(email: string, password: string) {
return this.callFunction('cms-createUser', {email, password}) as any;
}

removeUserAccount(id: string) {
return this.callFunction('cms-removeUser', {id});
}

callFunction(name: string, data) {
return httpsCallableData(this.functions, name)(data);
}

private collection(
moduleId,
pageSize,
sort,
cursor,
filters?: any[],
cg?
) {

if (Array.isArray(sort)) {
sort = [...sort].map(s => {
s.active = Parser.standardizeKey(s.active);
return s;
})
} else if (sort?.active) {
sort.active = Parser.standardizeKey(sort.active);
}

/**
* In firebase we can't sort by the
* key we filter with.
*/
if (
filters?.length &&
(Array.isArray(sort) || sort?.active) &&
filters.some(it => Array.isArray(sort) ? sort.some(s => s.active === it.key) : it.key === sort.active)
) {
sort = null;
}

const methods = [
...sort ? Array.isArray(sort) ? sort.map(it => orderBy(it.active, it.direction)) : [orderBy(sort.active, sort.direction)] : [],
...this.filterMethod(filters || []),
pageSize && limit(pageSize),
cursor && startAfter(cursor)
]
.filter(it => it);

if (cg) {

return query(
collectionGroup(this.firestore, moduleId),
...methods
);
}

return query(
collection(this.firestore, moduleId),
...methods
);
}

private filterMethod(filters?: WhereFilter[]) {
if (filters) {
return filters.reduce((acc, item) => {
if (
item.value !== undefined &&
item.value !== null &&
!Number.isNaN(item.value) &&
item.value !== '' &&
(
(
item.operator === FilterMethod.ArrayContains ||
item.operator === FilterMethod.ArrayContainsAny ||
item.operator === FilterMethod.In
) && Array.isArray(item.value) ?
item.value.length :
true
)
) {
acc.push(
where(item.key, item.operator, item.value)
);
}

return acc;
}, []);
}

return [];
}
}
Loading

0 comments on commit 75a04bc

Please sign in to comment.