Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions firestore/collection/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,10 +298,14 @@
);
}

export function collectionCountSnap(query: Query<unknown>): Observable<CountSnapshot> {
export function collectionCountSnap<AppModelType = DocumentData>(
query: Query<AppModelType>,

Check failure on line 302 in firestore/collection/index.ts

View workflow job for this annotation

GitHub Actions / Lint

Expected indentation of 4 spaces but found 2
): Observable<CountSnapshot<AppModelType>> {
return from(getCountFromServer(query));
}

export function collectionCount(query: Query<unknown>): Observable<number> {
export function collectionCount<AppModelType = DocumentData>(
query: Query<AppModelType>,

Check failure on line 308 in firestore/collection/index.ts

View workflow job for this annotation

GitHub Actions / Lint

Expected indentation of 4 spaces but found 2
): Observable<number> {
return collectionCountSnap(query).pipe(map((snap) => snap.data().count));
}
8 changes: 4 additions & 4 deletions firestore/document/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ export function snapToData<T=DocumentData, R extends T=T>(
return data;
}

return {
...data,
[options.idField]: snapshot.id,
};
// Preserve converter instances and custom prototypes by mutating the original object
// instead of creating a new one with spread syntax.
(data as Record<string, unknown>)[options.idField as string] = snapshot.id;
return data;
}
11 changes: 8 additions & 3 deletions firestore/lite/collection/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,15 @@ export function collectionData<T=DocumentData>(
);
}

export function collectionCountSnap(query: Query<unknown>): Observable<CountSnapshot> {
return from(getCount(query));
export function collectionCountSnap<
AppModelType = DocumentData,
DbModelType extends DocumentData = DocumentData,
>(query: Query<AppModelType, DbModelType>): Observable<CountSnapshot<AppModelType, DbModelType>> {
return from(getCount(query) as Promise<CountSnapshot<AppModelType, DbModelType>>);
}

export function collectionCount(query: Query<unknown>): Observable<number> {
export function collectionCount<AppModelType = DocumentData, DbModelType extends DocumentData = DocumentData>(
query: Query<AppModelType, DbModelType>,
): Observable<number> {
return collectionCountSnap(query).pipe(map((snap) => snap.data().count));
}
18 changes: 14 additions & 4 deletions firestore/lite/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,20 @@ import type * as lite from 'firebase/firestore/lite';

export type DocumentReference<T> = lite.DocumentReference<T>;
export type DocumentData = lite.DocumentData;
export type Query<T> = lite.Query<T>;
export type Query<
AppModelType,
DbModelType extends DocumentData = DocumentData,
> = lite.Query<AppModelType, DbModelType>;
export type DocumentSnapshot<T> = lite.DocumentSnapshot<T>;
export type QuerySnapshot<T> = lite.QuerySnapshot<T>;
export type QueryDocumentSnapshot<T> = lite.QueryDocumentSnapshot<T>;
export type CountSnapshot = lite.AggregateQuerySnapshot<{
count: lite.AggregateField<number>;
}, any, DocumentData>;
export type CountSnapshot<
AppModelType = DocumentData,
DbModelType extends DocumentData = DocumentData,
> = lite.AggregateQuerySnapshot<
{
count: lite.AggregateField<number>;
},
AppModelType,
DbModelType
>;
84 changes: 40 additions & 44 deletions performance/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,10 @@
export const trace = <T = any>(name: string) => (source$: Observable<T>) => new Observable<T>((subscriber) => {
const traceSubscription = trace$(name).subscribe();
return source$.pipe(
tap(
() => traceSubscription.unsubscribe(),
() => {
},
() => traceSubscription.unsubscribe(),
),
tap({

Check failure on line 53 in performance/index.ts

View workflow job for this annotation

GitHub Actions / Lint

Expected indentation of 6 spaces but found 4
next: () => traceSubscription.unsubscribe(),

Check failure on line 54 in performance/index.ts

View workflow job for this annotation

GitHub Actions / Lint

Expected indentation of 8 spaces but found 6
complete: () => traceSubscription.unsubscribe(),

Check failure on line 55 in performance/index.ts

View workflow job for this annotation

GitHub Actions / Lint

Expected indentation of 8 spaces but found 6
}),

Check failure on line 56 in performance/index.ts

View workflow job for this annotation

GitHub Actions / Lint

Expected indentation of 6 spaces but found 4
).subscribe(subscriber);
});

Expand All @@ -73,14 +71,16 @@
options?: { orComplete?: boolean },
) => (source$: Observable<T>) => new Observable<T>((subscriber) => {
const traceSubscription = trace$(name).subscribe();
return source$.pipe(
tap(
(a) => test(a) && traceSubscription.unsubscribe(),
() => {
},
() => options && options.orComplete && traceSubscription.unsubscribe(),
),
).subscribe(subscriber);
return source$
.pipe(

Check failure on line 75 in performance/index.ts

View workflow job for this annotation

GitHub Actions / Lint

Expected indentation of 6 spaces but found 4
tap({

Check failure on line 76 in performance/index.ts

View workflow job for this annotation

GitHub Actions / Lint

Expected indentation of 10 spaces but found 6
next: (a) => test(a) && traceSubscription.unsubscribe(),

Check failure on line 77 in performance/index.ts

View workflow job for this annotation

GitHub Actions / Lint

Expected indentation of 12 spaces but found 8
complete: () =>

Check failure on line 78 in performance/index.ts

View workflow job for this annotation

GitHub Actions / Lint

Expected indentation of 12 spaces but found 8
options &&
options.orComplete &&
traceSubscription.unsubscribe(),
}),
).subscribe(subscriber);
});

/**
Expand All @@ -98,23 +98,27 @@
options?: { orComplete?: boolean },
) => (source$: Observable<T>) => new Observable<T>((subscriber) => {
let traceSubscription: Subscription | undefined;
return source$.pipe(
tap(
(a) => {
if (test(a)) {
traceSubscription = traceSubscription || trace$(name).subscribe();
} else {
if (traceSubscription) {
traceSubscription.unsubscribe();
}
traceSubscription = undefined;
return source$
.pipe(
tap({
next: (a) => {
if (test(a)) {
traceSubscription =
traceSubscription || trace$(name).subscribe();
} else {
if (traceSubscription) {
traceSubscription.unsubscribe();
}
},
() => {
},
() => options && options.orComplete && traceSubscription && traceSubscription.unsubscribe(),
),
).subscribe(subscriber);
traceSubscription = undefined;
}
},
complete: () =>
options &&
options.orComplete &&
traceSubscription &&
traceSubscription.unsubscribe(),
}),
).subscribe(subscriber);
});

/**
Expand All @@ -126,13 +130,9 @@
export const traceUntilComplete = <T = any>(name: string) => (source$: Observable<T>) => new Observable<T>((subscriber) => {
const traceSubscription = trace$(name).subscribe();
return source$.pipe(
tap(
() => {
},
() => {
},
() => traceSubscription.unsubscribe(),
),
tap({
complete: () => traceSubscription.unsubscribe(),
}),
).subscribe(subscriber);
});

Expand All @@ -145,12 +145,8 @@
export const traceUntilFirst = <T = any>(name: string) => (source$: Observable<T>) => new Observable<T>((subscriber) => {
const traceSubscription = trace$(name).subscribe();
return source$.pipe(
tap(
() => traceSubscription.unsubscribe(),
() => {
},
() => {
},
),
tap({
complete: () => traceSubscription.unsubscribe(),
}),
).subscribe(subscriber);
});
23 changes: 18 additions & 5 deletions storage/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,23 @@ import {
import {Observable, from} from 'rxjs';
import {map, shareReplay} from 'rxjs/operators';

import type {UploadTaskSnapshot, StorageReference, UploadMetadata, StringFormat, UploadTask, UploadResult} from 'firebase/storage';
import type {
UploadTaskSnapshot,
StorageReference,
UploadMetadata,
StringFormat,
UploadTask,
UploadResult,
FullMetadata,
StorageError,
} from 'firebase/storage';

export function fromTask(task: UploadTask): Observable<UploadTaskSnapshot> {
return new Observable<UploadTaskSnapshot>((subscriber) => {
let lastSnapshot: UploadTaskSnapshot | null = null;
let complete = false;
let hasError = false;
let error: any = null;
let error: StorageError | null = null;

const emit = (snapshot: UploadTaskSnapshot) => {
lastSnapshot = snapshot;
Expand Down Expand Up @@ -74,9 +83,13 @@ export function getDownloadURL(ref: StorageReference): Observable<string> {
return from(_getDownloadURL(ref));
}

// TODO: fix storage typing in firebase, then apply the same fix here
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function getMetadata(ref: StorageReference): Observable<any> {
/**
* Retrieves the metadata for a given storage reference.
*
* @param ref The storage reference for which to retrieve metadata.
* @returns An observable that emits the metadata for the given reference.
*/
export function getMetadata(ref: StorageReference): Observable<FullMetadata> {
return from(_getMetadata(ref));
}

Expand Down
23 changes: 23 additions & 0 deletions test/firestore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,29 @@ describe('RxFire Firestore', () => {
});
});

it('docData should preserve converter instances when idField is set', (done: jest.DoneCallback) => {
class Folk {
constructor(public name: string) {}
static fromFirestore(snap: QueryDocumentSnapshot) {
return new Folk(snap.data().name);
}
static toFirestore(model: Folk) {
return model;
}
}

seedTest(firestore).then(({davidDoc}) => {
const unwrapped = docData(davidDoc.withConverter(Folk), {idField: 'UID'});

unwrapped.pipe(take(1)).subscribe((val) => {
expect(val).toBeInstanceOf(Folk);
expect((val as Folk).name).toBe('David');
expect((val as Folk & {UID: string}).UID).toBe('david');
done();
});
});
});

/**
* TODO(jamesdaniels)
* Having trouble gettings these test green with the emulators
Expand Down
Loading