-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Derek Burgman
committed
Jan 26, 2022
1 parent
ba41615
commit 62a3586
Showing
13 changed files
with
432 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { writeBatch, DocumentReference, DocumentSnapshot, UpdateData, WithFieldValue, WriteBatch } from "@angular/fire/firestore"; | ||
import { getDoc } from "@firebase/firestore"; | ||
import { from, Observable } from "rxjs"; | ||
import { FirestoreDocumentDatabaseAccessor, FirestoreDocumentDatabaseAccessorFactory, FirestoreDocumentDatabaseAccessorStreamState } from "./accessor"; | ||
|
||
/** | ||
* FirestoreDocumentDatabaseAccessor implementation for a batch. | ||
*/ | ||
export class WriteBatchFirestoreDocumentDatabaseAccessor<T> implements FirestoreDocumentDatabaseAccessor<T> { | ||
|
||
constructor(readonly batch: WriteBatch, readonly documentRef: DocumentReference<T>) { } | ||
|
||
stream(): Observable<FirestoreDocumentDatabaseAccessorStreamState<T>> { | ||
return from(this.get().then(snapshot => ({ snapshot, isActiveStream: false }))); | ||
} | ||
|
||
get(): Promise<DocumentSnapshot<T>> { | ||
return getDoc(this.documentRef); | ||
} | ||
|
||
delete(): Promise<void> { | ||
this.batch.delete(this.documentRef); | ||
return Promise.resolve(); | ||
} | ||
|
||
set(data: WithFieldValue<T>): Promise<void> { | ||
this.batch.set(this.documentRef, data); | ||
return Promise.resolve(); | ||
} | ||
|
||
update(data: UpdateData<T>): Promise<void> { | ||
this.batch.update(this.documentRef, data); | ||
return Promise.resolve(); | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Creates a new FirestoreDocumentDatabaseAccessorFactory for a Batch. | ||
* | ||
* @param batch | ||
* @returns | ||
*/ | ||
export function writeBatchAccessorFactory<T>(writeBatch: WriteBatch): FirestoreDocumentDatabaseAccessorFactory<T> { | ||
return { | ||
accessorFor: (ref: DocumentReference<T>) => new WriteBatchFirestoreDocumentDatabaseAccessor(writeBatch, ref) | ||
}; | ||
} |
47 changes: 47 additions & 0 deletions
47
packages/dbx-firebase/src/lib/firestore/accessor.default.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { DocumentReference, DocumentSnapshot, UpdateData, WithFieldValue, docSnapshots, setDoc } from "@angular/fire/firestore"; | ||
import { deleteDoc, getDoc, updateDoc } from "@firebase/firestore"; | ||
import { map, Observable } from "rxjs"; | ||
import { FirestoreDocumentDatabaseAccessor, FirestoreDocumentDatabaseAccessorFactory, FirestoreDocumentDatabaseAccessorStreamState } from "./accessor"; | ||
|
||
/** | ||
* FirestoreDocumentDatabaseAccessor implementation for a batch. | ||
*/ | ||
export class DefaultFirestoreDocumentDatabaseAccessor<T> implements FirestoreDocumentDatabaseAccessor<T> { | ||
|
||
constructor(readonly documentRef: DocumentReference<T>) { } | ||
|
||
stream(): Observable<FirestoreDocumentDatabaseAccessorStreamState<T>> { | ||
return docSnapshots(this.documentRef).pipe( | ||
map(snapshot => ({ snapshot, isActiveStream: true })) | ||
); | ||
} | ||
|
||
get(): Promise<DocumentSnapshot<T>> { | ||
return getDoc(this.documentRef); | ||
} | ||
|
||
delete(): Promise<void> { | ||
return deleteDoc(this.documentRef); | ||
} | ||
|
||
set(data: WithFieldValue<T>): Promise<void> { | ||
return setDoc(this.documentRef, data); | ||
} | ||
|
||
update(data: UpdateData<T>): Promise<void> { | ||
return updateDoc(this.documentRef, data); | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Creates a new FirestoreDocumentDatabaseAccessorFactory for a Batch. | ||
* | ||
* @param batch | ||
* @returns | ||
*/ | ||
export function defaultFirestoreAccessorFactory<T>(): FirestoreDocumentDatabaseAccessorFactory<T> { | ||
return { | ||
accessorFor: (ref: DocumentReference<T>) => new DefaultFirestoreDocumentDatabaseAccessor(ref) | ||
}; | ||
} |
47 changes: 47 additions & 0 deletions
47
packages/dbx-firebase/src/lib/firestore/accessor.transaction.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { DocumentReference, DocumentSnapshot, Transaction, UpdateData, WithFieldValue } from "@angular/fire/firestore"; | ||
import { from, Observable } from "rxjs"; | ||
import { FirestoreDocumentDatabaseAccessor, FirestoreDocumentDatabaseAccessorFactory, FirestoreDocumentDatabaseAccessorStreamState } from "./accessor"; | ||
|
||
/** | ||
* FirestoreDocumentDatabaseAccessor implementation for a transaction. | ||
*/ | ||
export class TransactionFirestoreDocumentDatabaseAccessor<T> implements FirestoreDocumentDatabaseAccessor<T> { | ||
|
||
constructor(readonly transaction: Transaction, readonly documentRef: DocumentReference<T>) { } | ||
|
||
stream(): Observable<FirestoreDocumentDatabaseAccessorStreamState<T>> { | ||
return from(this.get().then(snapshot => ({ snapshot, isActiveStream: false }))); | ||
} | ||
|
||
get(): Promise<DocumentSnapshot<T>> { | ||
return this.transaction.get(this.documentRef); | ||
} | ||
|
||
delete(): Promise<void> { | ||
this.transaction.delete(this.documentRef); | ||
return Promise.resolve(); | ||
} | ||
|
||
set(data: WithFieldValue<T>): Promise<void> { | ||
this.transaction.set(this.documentRef, data); | ||
return Promise.resolve(); | ||
} | ||
|
||
update(data: UpdateData<T>): Promise<void> { | ||
this.transaction.update(this.documentRef, data); | ||
return Promise.resolve(); | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Creates a new FirestoreDocumentDatabaseAccessorFactory for a Transaction. | ||
* | ||
* @param transaction | ||
* @returns | ||
*/ | ||
export function transactionAccessorFactory<T>(transaction: Transaction): FirestoreDocumentDatabaseAccessorFactory<T> { | ||
return { | ||
accessorFor: (ref: DocumentReference<T>) => new TransactionFirestoreDocumentDatabaseAccessor(transaction, ref) | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { Observable } from 'rxjs'; | ||
import { DocumentReference, DocumentSnapshot, UpdateData, WithFieldValue } from '@angular/fire/firestore'; | ||
|
||
export interface FirestoreDocumentDatabaseAccessorStreamState<T> { | ||
isActiveStream: boolean; | ||
snapshot: DocumentSnapshot<T>; | ||
} | ||
|
||
export interface FirestoreDocumentDatabaseAccessorDocumentRef<T> { | ||
readonly documentRef: DocumentReference<T>; | ||
} | ||
|
||
/** | ||
* Firestore database accessor instance used to retrieve and make changes to items in the database. | ||
*/ | ||
export interface FirestoreDocumentDatabaseAccessor<T> extends FirestoreDocumentDatabaseAccessorDocumentRef<T> { | ||
/** | ||
* Returns a database stream of this object. | ||
* | ||
* Depending on the current context, the stream may not be active and return only the latest value. | ||
*/ | ||
stream(): Observable<FirestoreDocumentDatabaseAccessorStreamState<T>>; | ||
/** | ||
* Returns the current snapshot. | ||
*/ | ||
get(): Promise<DocumentSnapshot<T>>; | ||
/** | ||
* Deletes the document | ||
*/ | ||
delete(): Promise<void>; | ||
/** | ||
* Sets the data in the database. | ||
* | ||
* @param data | ||
*/ | ||
set(data: WithFieldValue<T>): Promise<void>; | ||
/** | ||
* Updates the data in the database. | ||
* | ||
* @param data | ||
*/ | ||
update(data: UpdateData<T>): Promise<void>; | ||
} | ||
|
||
/** | ||
* Contextual interface used for making a FirestoreDocumentModifier for a specific document. | ||
*/ | ||
export interface FirestoreDocumentDatabaseAccessorFactory<T> { | ||
|
||
/** | ||
* Creates a new FirestoreDocumentDatabaseAccessor for the input ref. | ||
* | ||
* @param ref | ||
*/ | ||
accessorFor(ref: DocumentReference<T>): FirestoreDocumentDatabaseAccessor<T>; | ||
|
||
} |
81 changes: 81 additions & 0 deletions
81
packages/dbx-firebase/src/lib/firestore/collection.document.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { DocumentReference } from '@angular/fire/firestore'; | ||
import { CollectionReference, doc, Firestore } from '@firebase/firestore'; | ||
import { FirestoreDocumentDatabaseAccessor, FirestoreDocumentDatabaseAccessorDocumentRef, FirestoreDocumentDatabaseAccessorFactory } from './accessor'; | ||
import { DbNgxFirestoreCollectionReference } from './collection'; | ||
import { FirestoreDocumentDatabaseContext } from './context'; | ||
import { defaultFirestoreDatabaseContext } from './context.default'; | ||
|
||
export interface DbNgxFirestoreCollectionDocument<T> extends FirestoreDocumentDatabaseAccessorDocumentRef<T> { } | ||
|
||
export interface DbNgxFirestoreCollectionDocumentAccessor<T, D extends DbNgxFirestoreCollectionDocument<T>> { | ||
|
||
readonly databaseContext: FirestoreDocumentDatabaseContext<T>; | ||
|
||
/** | ||
* Creates a new document. | ||
*/ | ||
newDocument(): D; | ||
|
||
/** | ||
* Loads a document from the datastore. | ||
* | ||
* @param ref | ||
*/ | ||
loadDocument(ref: DocumentReference<T>): D; | ||
|
||
} | ||
|
||
export interface DbNgxFirestoreCollectionDocumentAccessorFactory<T, D extends DbNgxFirestoreCollectionDocument<T>> { | ||
|
||
/** | ||
* Creates a new DbNgxFirestoreCollectionDocumentFactory using the given context. | ||
* | ||
* @param context Optional context to retrieve items from. | ||
*/ | ||
documentAccessor(context?: FirestoreDocumentDatabaseContext<T>): DbNgxFirestoreCollectionDocumentAccessor<T, D>; | ||
|
||
} | ||
|
||
/** | ||
* Used to generate a DbNgxFirestoreCollectionDocument from an input FirestoreDocumentDatabaseAccessor instance. | ||
*/ | ||
export type DbNgxFirestoreCollectionDocumentFactoryFunction<T, D extends DbNgxFirestoreCollectionDocument<T>> = (accessor: FirestoreDocumentDatabaseAccessor<T>) => D; | ||
|
||
// MARK: DbNgxFirestoreCollectionDocumentAccessorInstance | ||
|
||
/** | ||
* DbNgxFirestoreCollectionDocumentAccessorInstance configuration. | ||
*/ | ||
export interface DbNgxFirestoreCollectionDocumentAccessorInstanceConfig<T, D extends DbNgxFirestoreCollectionDocument<T>> extends DbNgxFirestoreCollectionReference<T> { | ||
readonly makeDocument: DbNgxFirestoreCollectionDocumentFactoryFunction<T, D>; | ||
} | ||
|
||
export class DbNgxFirestoreCollectionDocumentAccessorInstance<T, D extends DbNgxFirestoreCollectionDocument<T>> implements DbNgxFirestoreCollectionDocumentAccessor<T, D> { | ||
|
||
constructor(readonly config: DbNgxFirestoreCollectionDocumentAccessorInstanceConfig<T, D>, readonly databaseContext: FirestoreDocumentDatabaseContext<T> = defaultFirestoreDatabaseContext()) { } | ||
|
||
get collection(): CollectionReference<T> { | ||
return this.config.collection; | ||
} | ||
|
||
get accessorFactory(): FirestoreDocumentDatabaseAccessorFactory<T> { | ||
return this.databaseContext.accessorFactory; | ||
} | ||
|
||
newDocument(): D { | ||
const newDocRef = doc(this.collection); | ||
return this.loadDocument(newDocRef); | ||
} | ||
|
||
loadDocument(ref: DocumentReference<T>): D { | ||
const accessor = this.accessorFactory.accessorFor(ref); | ||
return this.config.makeDocument(accessor); | ||
} | ||
|
||
} | ||
|
||
export type DbNgxFirestoreCollectionDocumentAccessorFactoryFunction<T, D extends DbNgxFirestoreCollectionDocument<T>> = (context?: FirestoreDocumentDatabaseContext<T>) => DbNgxFirestoreCollectionDocumentAccessor<T, D>; | ||
|
||
export function firestoreCollectionDocumentAccessorFactory<T, D extends DbNgxFirestoreCollectionDocument<T>>(config: DbNgxFirestoreCollectionDocumentAccessorInstanceConfig<T, D>): DbNgxFirestoreCollectionDocumentAccessorFactoryFunction<T, D> { | ||
return (context?: FirestoreDocumentDatabaseContext<T>) => new DbNgxFirestoreCollectionDocumentAccessorInstance<T, D>(config, context); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { CollectionReference } from "@firebase/firestore"; | ||
|
||
/** | ||
* Contains a reference to a CollectionReference. | ||
*/ | ||
export interface DbNgxFirestoreCollectionReference<T> { | ||
readonly collection: CollectionReference<T>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { WriteBatch } from "@firebase/firestore"; | ||
import { writeBatchAccessorFactory } from "./accessor.batch"; | ||
import { FirestoreDocumentDatabaseContext, FirestoreDocumentDatabaseContextType } from "./context"; | ||
|
||
// MARK: Batch | ||
export class WriteBatchFirestoreDocumentDatabaseContext<T> implements FirestoreDocumentDatabaseContext<T> { | ||
|
||
readonly contextType = FirestoreDocumentDatabaseContextType.TRANSACTION; | ||
readonly accessorFactory = writeBatchAccessorFactory<T>(this.batch); | ||
|
||
constructor(readonly batch: WriteBatch) { } | ||
|
||
} | ||
|
||
export function writeBatchDatabaseContext<T>(batch: WriteBatch): WriteBatchFirestoreDocumentDatabaseContext<T> { | ||
return new WriteBatchFirestoreDocumentDatabaseContext<T>(batch); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { defaultFirestoreAccessorFactory } from "./accessor.default"; | ||
import { FirestoreDocumentDatabaseContext, FirestoreDocumentDatabaseContextType } from "./context"; | ||
|
||
export function defaultFirestoreDatabaseContext<T>(): FirestoreDocumentDatabaseContext<T> { | ||
return { | ||
contextType: FirestoreDocumentDatabaseContextType.NONE, | ||
accessorFactory: defaultFirestoreAccessorFactory<T>() | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
packages/dbx-firebase/src/lib/firestore/context.transaction.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { Transaction } from "@firebase/firestore"; | ||
import { transactionAccessorFactory } from "./accessor.transaction"; | ||
import { FirestoreDocumentDatabaseContext, FirestoreDocumentDatabaseContextType } from "./context"; | ||
|
||
// MARK: Transaction | ||
export class TransactionFirestoreDocumentDatabaseContext<T> implements FirestoreDocumentDatabaseContext<T> { | ||
|
||
readonly contextType = FirestoreDocumentDatabaseContextType.TRANSACTION; | ||
readonly accessorFactory = transactionAccessorFactory<T>(this.transaction); | ||
|
||
constructor(readonly transaction: Transaction) { } | ||
|
||
} | ||
|
||
export function transactionDatabaseContext<T>(transaction: Transaction): TransactionFirestoreDocumentDatabaseContext<T> { | ||
return new TransactionFirestoreDocumentDatabaseContext<T>(transaction); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { FirestoreDocumentDatabaseAccessorFactory } from "./accessor"; | ||
|
||
export enum FirestoreDocumentDatabaseContextType { | ||
NONE = 'none', | ||
TRANSACTION = 'transaction', | ||
BATCH = 'batch' | ||
} | ||
|
||
/** | ||
* Firebase database context used for accessing and modifying documents in a specific context, such as a transaction. | ||
*/ | ||
export interface FirestoreDocumentDatabaseContext<T> { | ||
|
||
/** | ||
* Context type | ||
*/ | ||
readonly contextType: FirestoreDocumentDatabaseContextType; | ||
|
||
/** | ||
* Database accessor | ||
*/ | ||
readonly accessorFactory: FirestoreDocumentDatabaseAccessorFactory<T>; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { DbNgxFirestoreCollectionDocument, DbNgxFirestoreCollectionDocumentAccessor, DbNgxFirestoreCollectionDocumentAccessorFactory, DbNgxFirestoreCollectionDocumentAccessorFactoryFunction, DbNgxFirestoreCollectionDocumentAccessorInstanceConfig, firestoreCollectionDocumentAccessorFactory } from "./collection.document"; | ||
import { FirestoreDocumentDatabaseContext } from "./context"; | ||
import { defaultFirestoreDatabaseContext } from "./context.default"; | ||
import { BaseFirestoreItemPageIterationConfig, FirestoreItemPageIterationFactory, firestoreItemPageIterationFactory, FirestoreItemPageIterationFactoryFunction, FirestoreItemPageIterationInstance, FirestoreItemPageIteratorFilter } from "./iterator"; | ||
|
||
|
||
export interface DbNgxFirestoreCollectionConfig<T, D extends DbNgxFirestoreCollectionDocument<T>> extends BaseFirestoreItemPageIterationConfig<T>, DbNgxFirestoreCollectionDocumentAccessorInstanceConfig<T, D> { } | ||
|
||
export class DbNgxFirestoreCollection<T, D extends DbNgxFirestoreCollectionDocument<T>> implements FirestoreItemPageIterationFactory<T>, DbNgxFirestoreCollectionDocumentAccessorFactory<T, D> { | ||
|
||
protected readonly _queryIterationFactory: FirestoreItemPageIterationFactoryFunction<T> = firestoreItemPageIterationFactory(this.config); | ||
protected readonly _documentAccessorFactory: DbNgxFirestoreCollectionDocumentAccessorFactoryFunction<T, D> = firestoreCollectionDocumentAccessorFactory(this.config); | ||
|
||
constructor(readonly config: DbNgxFirestoreCollectionConfig<T, D>) { } | ||
|
||
// MARK: FirestoreItemPageIterationFactory<T> | ||
firestoreIteration(filter?: FirestoreItemPageIteratorFilter): FirestoreItemPageIterationInstance<T> { | ||
return this._queryIterationFactory(filter); | ||
} | ||
|
||
documentAccessor(context?: FirestoreDocumentDatabaseContext<T>): DbNgxFirestoreCollectionDocumentAccessor<T, D> { | ||
return this._documentAccessorFactory(context); | ||
} | ||
|
||
} |
Oops, something went wrong.