Skip to content

Commit 03cf52f

Browse files
authored
feat: require firebase 10.5.0 or later (#247)
BREAKING CHANGE: require firebase 10.5.0 or later
1 parent 52949b2 commit 03cf52f

17 files changed

Lines changed: 790 additions & 1041 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ yarn add react-firehooks
2323

2424
## Compatibility
2525

26-
- [firebase](https://www.npmjs.com/package/firebase): 9.11.0 or later
26+
- [firebase](https://www.npmjs.com/package/firebase): 10.5.0 or later
2727
- [react](https://www.npmjs.com/package/react): 16.8.0 or later
2828

2929
## Usage

migrations/v4.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Migrate from v3 to v4
2+
3+
## Peer dependency
4+
5+
This library now requires firebase 10.5.0 or later

package-lock.json

Lines changed: 628 additions & 928 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
"eslint-plugin-prettier": "5.0.0",
6565
"eslint-plugin-react": "7.33.2",
6666
"eslint-plugin-react-hooks": "4.6.0",
67-
"firebase": "9.11.0",
67+
"firebase": "10.5.0",
6868
"happy-dom": "12.2.2",
6969
"husky": "8.0.3",
7070
"lint-staged": "14.0.1",
@@ -91,7 +91,7 @@
9191
"lint-staged": "lint-staged"
9292
},
9393
"peerDependencies": {
94-
"firebase": "^9.11.0 || ^10.0.0",
94+
"firebase": "^10.5.0",
9595
"react": ">=16.8.0"
9696
},
9797
"lint-staged": {

src/firestore/internal.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ import type { Source } from "./types.js";
1818
/**
1919
* @internal
2020
*/
21-
export async function getDocFromSource<Value extends DocumentData = DocumentData>(
22-
reference: DocumentReference<Value>,
21+
export async function getDocFromSource<AppModelType = DocumentData, DbModelType extends DocumentData = DocumentData>(
22+
reference: DocumentReference<AppModelType, DbModelType>,
2323
source: Source,
24-
): Promise<DocumentSnapshot<Value>> {
24+
): Promise<DocumentSnapshot<AppModelType, DbModelType>> {
2525
switch (source) {
2626
case "cache":
2727
return await getDocFromCache(reference);
@@ -35,10 +35,10 @@ export async function getDocFromSource<Value extends DocumentData = DocumentData
3535
/**
3636
* @internal
3737
*/
38-
export async function getDocsFromSource<Value extends DocumentData = DocumentData>(
39-
query: Query<Value>,
38+
export async function getDocsFromSource<AppModelType = DocumentData, DbModelType extends DocumentData = DocumentData>(
39+
query: Query<AppModelType, DbModelType>,
4040
source: Source,
41-
): Promise<QuerySnapshot<Value>> {
41+
): Promise<QuerySnapshot<AppModelType, DbModelType>> {
4242
switch (source) {
4343
case "cache":
4444
return await getDocsFromCache(query);
@@ -52,9 +52,9 @@ export async function getDocsFromSource<Value extends DocumentData = DocumentDat
5252
/**
5353
* @internal
5454
*/
55-
export function isDocRefEqual<Value>(
56-
a: DocumentReference<Value> | undefined,
57-
b: DocumentReference<Value> | undefined,
55+
export function isDocRefEqual<AppModelType = DocumentData, DbModelType extends DocumentData = DocumentData>(
56+
a: DocumentReference<AppModelType, DbModelType> | undefined,
57+
b: DocumentReference<AppModelType, DbModelType> | undefined,
5858
): boolean {
5959
const areBothUndefined = a === undefined && b === undefined;
6060
const areSameRef = a !== undefined && b !== undefined && refEqual(a, b);
@@ -64,7 +64,10 @@ export function isDocRefEqual<Value>(
6464
/**
6565
* @internal
6666
*/
67-
export function isQueryEqual<Value>(a: Query<Value> | undefined, b: Query<Value> | undefined): boolean {
67+
export function isQueryEqual<AppModelType = DocumentData, DbModelType extends DocumentData = DocumentData>(
68+
a: Query<AppModelType, DbModelType> | undefined,
69+
b: Query<AppModelType, DbModelType> | undefined,
70+
): boolean {
6871
const areBothUndefined = a === undefined && b === undefined;
6972
const areSameRef = a !== undefined && b !== undefined && queryEqual(a, b);
7073
return areBothUndefined || areSameRef;

src/firestore/useDocument.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@ import { useListen, UseListenOnChange } from "../internal/useListen.js";
1212
import { LoadingState } from "../internal/useLoadingValue.js";
1313
import { isDocRefEqual } from "./internal.js";
1414

15-
export type UseDocumentResult<Value extends DocumentData = DocumentData> = ValueHookResult<
16-
DocumentSnapshot<Value>,
17-
FirestoreError
18-
>;
15+
export type UseDocumentResult<AppModelType = DocumentData> = ValueHookResult<DocumentSnapshot<AppModelType>, FirestoreError>;
1916

2017
/**
2118
* Options to configure the subscription
@@ -26,24 +23,29 @@ export interface UseDocumentOptions {
2623

2724
/**
2825
* Returns and updates a DocumentSnapshot of a Firestore DocumentReference
29-
* @template Value Type of the document data
26+
* @template AppModelType Shape of the data after it was converted from firestore
27+
* @template DbModelType Shape of the data in firestore
3028
* @param reference Firestore DocumentReference that will be subscribed to
3129
* @param options Options to configure the subscription
3230
* @returns Document snapshot, loading state, and error
3331
* - value: DocumentSnapshot; `undefined` if document does not exist, is currently being fetched, or an error occurred
3432
* - loading: `true` while fetching the document; `false` if the document was fetched successfully or an error occurred
3533
* - error: `undefined` if no error occurred
3634
*/
37-
export function useDocument<Value extends DocumentData = DocumentData>(
38-
reference: DocumentReference<Value> | undefined | null,
35+
export function useDocument<AppModelType = DocumentData, DbModelType extends DocumentData = DocumentData>(
36+
reference: DocumentReference<AppModelType, DbModelType> | undefined | null,
3937
options?: UseDocumentOptions,
40-
): UseDocumentResult<Value> {
38+
): UseDocumentResult<AppModelType> {
4139
const { snapshotListenOptions } = options ?? {};
4240
const { includeMetadataChanges } = snapshotListenOptions ?? {};
4341

44-
const onChange: UseListenOnChange<DocumentSnapshot<Value>, FirestoreError, DocumentReference<Value>> = useCallback(
42+
const onChange: UseListenOnChange<
43+
DocumentSnapshot<AppModelType, DbModelType>,
44+
FirestoreError,
45+
DocumentReference<AppModelType, DbModelType>
46+
> = useCallback(
4547
(stableRef, next, error) =>
46-
onSnapshot<Value>(
48+
onSnapshot(
4749
stableRef,
4850
{ includeMetadataChanges },
4951
{

src/firestore/useDocumentData.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,21 @@ import { useListen, UseListenOnChange } from "../internal/useListen.js";
1212
import { LoadingState } from "../internal/useLoadingValue.js";
1313
import { isDocRefEqual } from "./internal.js";
1414

15-
export type UseDocumentDataResult<Value extends DocumentData = DocumentData> = ValueHookResult<Value, FirestoreError>;
15+
export type UseDocumentDataResult<AppModelType = DocumentData> = ValueHookResult<AppModelType, FirestoreError>;
1616

1717
/**
1818
* Options to configure the subscription
1919
*/
20-
export interface UseDocumentDataOptions<Value extends DocumentData = DocumentData> {
20+
export interface UseDocumentDataOptions<AppModelType = DocumentData> {
2121
snapshotListenOptions?: SnapshotListenOptions;
2222
snapshotOptions?: SnapshotOptions;
23-
initialValue?: Value;
23+
initialValue?: AppModelType;
2424
}
2525

2626
/**
2727
* Returns and updates the data of a Firestore DocumentReference
28-
* @template Value Type of the document data
28+
* @template AppModelType Shape of the data after it was converted from firestore
29+
* @template DbModelType Shape of the data in firestore
2930
* @param reference Firestore DocumentReference that will be subscribed to
3031
* @param options Options to configure the subscription
3132
* `initialValue`: Value that is returned while the document is being fetched.
@@ -34,17 +35,21 @@ export interface UseDocumentDataOptions<Value extends DocumentData = DocumentDat
3435
* - loading: `true` while fetching the document; `false` if the document was fetched successfully or an error occurred
3536
* - error: `undefined` if no error occurred
3637
*/
37-
export function useDocumentData<Value extends DocumentData = DocumentData>(
38-
reference: DocumentReference<Value> | undefined | null,
39-
options?: UseDocumentDataOptions<Value>,
40-
): UseDocumentDataResult<Value> {
38+
export function useDocumentData<AppModelType = DocumentData, DbModelType extends DocumentData = DocumentData>(
39+
reference: DocumentReference<AppModelType, DbModelType> | undefined | null,
40+
options?: UseDocumentDataOptions<AppModelType>,
41+
): UseDocumentDataResult<AppModelType> {
4142
const { snapshotListenOptions, snapshotOptions } = options ?? {};
4243
const { includeMetadataChanges } = snapshotListenOptions ?? {};
4344
const { serverTimestamps } = snapshotOptions ?? {};
4445

45-
const onChange: UseListenOnChange<Value, FirestoreError, DocumentReference<Value>> = useCallback(
46+
const onChange: UseListenOnChange<
47+
AppModelType,
48+
FirestoreError,
49+
DocumentReference<AppModelType, DbModelType>
50+
> = useCallback(
4651
(stableRef, next, error) =>
47-
onSnapshot<Value>(
52+
onSnapshot(
4853
stableRef,
4954
{ includeMetadataChanges },
5055
{

src/firestore/useDocumentDataOnce.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { useGet } from "../internal/useGet.js";
55
import { getDocFromSource, isDocRefEqual } from "./internal.js";
66
import type { Source } from "./types.js";
77

8-
export type UseDocumentDataOnceResult<Value extends DocumentData = DocumentData> = ValueHookResult<Value, FirestoreError>;
8+
export type UseDocumentDataOnceResult<AppModelType = DocumentData> = ValueHookResult<AppModelType, FirestoreError>;
99

1010
/**
1111
* Options to configure how the document is fetched
@@ -17,23 +17,24 @@ export interface UseDocumentDataOnceOptions {
1717

1818
/**
1919
* Returns the data of a Firestore DocumentReference
20-
* @template Value Type of the document data
20+
* @template AppModelType Shape of the data after it was converted from firestore
21+
* @template DbModelType Shape of the data in firestore
2122
* @param reference Firestore DocumentReference that will be subscribed to
2223
* @param options Options to configure how the document is fetched
2324
* @returns Document data, loading state, and error
2425
* - value: Document data; `undefined` if document does not exist, is currently being fetched, or an error occurred
2526
* - loading: `true` while fetching the document; `false` if the document was fetched successfully or an error occurred
2627
* - error: `undefined` if no error occurred
2728
*/
28-
export function useDocumentDataOnce<Value extends DocumentData = DocumentData>(
29-
reference: DocumentReference<Value> | undefined | null,
29+
export function useDocumentDataOnce<AppModelType = DocumentData, DbModelType extends DocumentData = DocumentData>(
30+
reference: DocumentReference<AppModelType, DbModelType> | undefined | null,
3031
options?: UseDocumentDataOnceOptions,
31-
): UseDocumentDataOnceResult<Value> {
32+
): UseDocumentDataOnceResult<AppModelType> {
3233
const { source = "default", snapshotOptions } = options ?? {};
3334
const { serverTimestamps } = snapshotOptions ?? {};
3435

3536
const getData = useCallback(
36-
async (stableRef: DocumentReference<Value>) => {
37+
async (stableRef: DocumentReference<AppModelType, DbModelType>) => {
3738
const snap = await getDocFromSource(stableRef, source);
3839
return snap.data({ serverTimestamps });
3940
},

src/firestore/useDocumentOnce.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import { useGet } from "../internal/useGet.js";
55
import { getDocFromSource, isDocRefEqual } from "./internal.js";
66
import type { Source } from "./types.js";
77

8-
export type UseDocumentOnceResult<Value extends DocumentData = DocumentData> = ValueHookResult<
9-
DocumentSnapshot<Value>,
8+
export type UseDocumentOnceResult<AppModelType = DocumentData> = ValueHookResult<
9+
DocumentSnapshot<AppModelType>,
1010
FirestoreError
1111
>;
1212

@@ -19,21 +19,25 @@ export interface UseDocumentOnceOptions {
1919

2020
/**
2121
* Returns the DocumentSnapshot of a Firestore DocumentReference. Does not update the DocumentSnapshot once initially fetched
22-
* @template Value Type of the document data
22+
* @template AppModelType Shape of the data after it was converted from firestore
23+
* @template DbModelType Shape of the data in firestore
2324
* @param reference Firestore DocumentReference that will be fetched
2425
* @param options Options to configure how the document is fetched
2526
* @returns DocumentSnapshot, loading state, and error
2627
* - value: DocumentSnapshot; `undefined` if document does not exist, is currently being fetched, or an error occurred
2728
* - loading: `true` while fetching the document; `false` if the document was fetched successfully or an error occurred
2829
* - error: `undefined` if no error occurred
2930
*/
30-
export function useDocumentOnce<Value extends DocumentData = DocumentData>(
31-
reference: DocumentReference<Value> | undefined | null,
31+
export function useDocumentOnce<AppModelType = DocumentData, DbModelType extends DocumentData = DocumentData>(
32+
reference: DocumentReference<AppModelType, DbModelType> | undefined | null,
3233
options?: UseDocumentOnceOptions,
33-
): UseDocumentOnceResult<Value> {
34+
): UseDocumentOnceResult<AppModelType> {
3435
const { source = "default" } = options ?? {};
3536

36-
const getData = useCallback((stableRef: DocumentReference<Value>) => getDocFromSource(stableRef, source), [source]);
37+
const getData = useCallback(
38+
(stableRef: DocumentReference<AppModelType, DbModelType>) => getDocFromSource(stableRef, source),
39+
[source],
40+
);
3741

3842
return useGet(reference ?? undefined, getData, isDocRefEqual);
3943
}

src/firestore/useQueries.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import { ValueHookResult } from "../common/types.js";
44
import { useMultiListen, UseMultiListenChange } from "../internal/useMultiListen.js";
55
import { isQueryEqual } from "./internal.js";
66

7-
export type UseQueriesResult<Values extends ReadonlyArray<DocumentData> = ReadonlyArray<DocumentData>> = {
8-
[Index in keyof Values]: ValueHookResult<QuerySnapshot<Values[Index]>, FirestoreError>;
9-
} & { length: Values["length"] };
7+
export type UseQueriesResult<AppModelTypes extends ReadonlyArray<unknown> = ReadonlyArray<DocumentData>> = {
8+
[Index in keyof AppModelTypes]: ValueHookResult<QuerySnapshot<AppModelTypes[Index]>, FirestoreError>;
9+
} & { length: AppModelTypes["length"] };
1010

1111
/**
1212
* Options to configure the subscription
@@ -17,22 +17,30 @@ export interface UseQueriesOptions {
1717

1818
/**
1919
* Returns and updates a QuerySnapshot of multiple Firestore queries
20-
* @template Values Tuple of types of the collection data
20+
* @template AppModelTypes Tuple of shapes of the data after it was converted from firestore
21+
* @template DbModelTypes Tuple of shapes of the data in firestore
2122
* @param queries Firestore queries that will be subscribed to
2223
* @param options Options to configure the subscription
2324
* @returns Array with tuple for each query:
2425
* - value: QuerySnapshot; `undefined` if query is currently being fetched, or an error occurred
2526
* - loading: `true` while fetching the query; `false` if the query was fetched successfully or an error occurred
2627
* - error: `undefined` if no error occurred
2728
*/
28-
export function useQueries<Values extends ReadonlyArray<DocumentData> = ReadonlyArray<DocumentData>>(
29-
queries: { [Index in keyof Values]: Query<Values[Index]> },
29+
export function useQuerie<
30+
AppModelTypes extends ReadonlyArray<unknown> = ReadonlyArray<DocumentData>,
31+
DbModelTypes extends ReadonlyArray<DocumentData> = ReadonlyArray<DocumentData>,
32+
>(
33+
queries: { [Index in keyof AppModelTypes]: Query<AppModelTypes[Index], DbModelTypes[number]> },
3034
options?: UseQueriesOptions,
31-
): UseQueriesResult<Values> {
35+
): UseQueriesResult<AppModelTypes> {
3236
const { snapshotListenOptions } = options ?? {};
3337
const { includeMetadataChanges } = snapshotListenOptions ?? {};
3438

35-
const onChange: UseMultiListenChange<QuerySnapshot<Values[number]>, FirestoreError, Query<Values[number]>> = useCallback(
39+
const onChange: UseMultiListenChange<
40+
QuerySnapshot<AppModelTypes[number], DbModelTypes[number]>,
41+
FirestoreError,
42+
Query<AppModelTypes[number], DbModelTypes[number]>
43+
> = useCallback(
3644
(query, next, error) =>
3745
onSnapshot(
3846
query,

0 commit comments

Comments
 (0)