reactfire 4.0.0-exp.e80fc49 → 4.0.0-exp.eb1428b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,35 +1,30 @@
1
- import { ObservableStatus } from '../useObservable';
2
- import { AllParameters } from './getValue';
1
+ import { ObservableStatus } from './useObservable';
2
+ import { AllParameters } from 'rxfire/remote-config';
3
3
  import type { Value as RemoteConfigValue } from 'firebase/remote-config';
4
4
  /**
5
5
  * Accepts a key and optionally a Remote Config instance. Returns a
6
6
  * Remote Config Value.
7
7
  *
8
8
  * @param key The parameter key in Remote Config
9
- * @param remoteConfig Optional instance. If not provided ReactFire will either grab the default instance or lazy load.
10
9
  */
11
10
  export declare function useRemoteConfigValue(key: string): ObservableStatus<RemoteConfigValue>;
12
11
  /**
13
12
  * Convience method similar to useRemoteConfigValue. Returns a `string` from a Remote Config parameter.
14
13
  * @param key The parameter key in Remote Config
15
- * @param remoteConfig Optional instance. If not provided ReactFire will either grab the default instance or lazy load.
16
14
  */
17
15
  export declare function useRemoteConfigString(key: string): ObservableStatus<string>;
18
16
  /**
19
17
  * Convience method similar to useRemoteConfigValue. Returns a `number` from a Remote Config parameter.
20
18
  * @param key The parameter key in Remote Config
21
- * @param remoteConfig Optional instance. If not provided ReactFire will either grab the default instance or lazy load.
22
19
  */
23
20
  export declare function useRemoteConfigNumber(key: string): ObservableStatus<number>;
24
21
  /**
25
22
  * Convience method similar to useRemoteConfigValue. Returns a `boolean` from a Remote Config parameter.
26
23
  * @param key The parameter key in Remote Config
27
- * @param remoteConfig Optional instance. If not provided ReactFire will either grab the default instance or lazy load.
28
24
  */
29
25
  export declare function useRemoteConfigBoolean(key: string): ObservableStatus<boolean>;
30
26
  /**
31
27
  * Convience method similar to useRemoteConfigValue. Returns allRemote Config parameters.
32
28
  * @param key The parameter key in Remote Config
33
- * @param remoteConfig Optional instance. If not provided ReactFire will either grab the default instance or lazy load.
34
29
  */
35
30
  export declare function useRemoteConfigAll(key: string): ObservableStatus<AllParameters>;
package/dist/sdk.d.ts CHANGED
@@ -1,23 +1,44 @@
1
1
  import * as React from 'react';
2
+ import type { AppCheck } from 'firebase/app-check';
2
3
  import type { Auth } from 'firebase/auth';
4
+ import type { Analytics } from 'firebase/analytics';
3
5
  import type { Database } from 'firebase/database';
4
6
  import type { Firestore } from 'firebase/firestore';
7
+ import type { Functions } from 'firebase/functions';
5
8
  import type { FirebasePerformance } from 'firebase/performance';
6
9
  import type { FirebaseStorage } from 'firebase/storage';
7
10
  import type { RemoteConfig } from 'firebase/remote-config';
8
11
  import { FirebaseApp } from 'firebase/app';
9
12
  import { ObservableStatus } from './useObservable';
10
13
  import { ReactFireOptions } from '.';
11
- declare type FirebaseSdks = Auth | Database | Firestore | FirebasePerformance | FirebaseStorage | RemoteConfig;
14
+ export declare const AppCheckSdkContext: React.Context<AppCheck | undefined>;
15
+ export declare const AuthSdkContext: React.Context<Auth | undefined>;
16
+ export declare const AnalyticsSdkContext: React.Context<Analytics | undefined>;
17
+ export declare const DatabaseSdkContext: React.Context<Database | undefined>;
18
+ export declare const FirestoreSdkContext: React.Context<Firestore | undefined>;
19
+ export declare const FunctionsSdkContext: React.Context<Functions | undefined>;
20
+ export declare const StorageSdkContext: React.Context<FirebaseStorage | undefined>;
21
+ export declare const PerformanceSdkContext: React.Context<FirebasePerformance | undefined>;
22
+ export declare const RemoteConfigSdkContext: React.Context<RemoteConfig | undefined>;
23
+ declare type FirebaseSdks = Analytics | AppCheck | Auth | Database | Firestore | FirebasePerformance | FirebaseStorage | Functions | RemoteConfig;
24
+ export declare const AppCheckProvider: (props: React.PropsWithChildren<{
25
+ sdk: AppCheck;
26
+ }>) => JSX.Element;
12
27
  export declare const AuthProvider: (props: React.PropsWithChildren<{
13
28
  sdk: Auth;
14
29
  }>) => JSX.Element;
30
+ export declare const AnalyticsProvider: (props: React.PropsWithChildren<{
31
+ sdk: Analytics;
32
+ }>) => JSX.Element;
15
33
  export declare const DatabaseProvider: (props: React.PropsWithChildren<{
16
34
  sdk: Database;
17
35
  }>) => JSX.Element;
18
36
  export declare const FirestoreProvider: (props: React.PropsWithChildren<{
19
37
  sdk: Firestore;
20
38
  }>) => JSX.Element;
39
+ export declare const FunctionsProvider: (props: React.PropsWithChildren<{
40
+ sdk: Functions;
41
+ }>) => JSX.Element;
21
42
  export declare const PerformanceProvider: (props: React.PropsWithChildren<{
22
43
  sdk: FirebasePerformance;
23
44
  }>) => JSX.Element;
@@ -27,16 +48,22 @@ export declare const StorageProvider: (props: React.PropsWithChildren<{
27
48
  export declare const RemoteConfigProvider: (props: React.PropsWithChildren<{
28
49
  sdk: RemoteConfig;
29
50
  }>) => JSX.Element;
51
+ export declare const useAppCheck: () => AppCheck;
30
52
  export declare const useAuth: () => Auth;
53
+ export declare const useAnalytics: () => Analytics;
31
54
  export declare const useDatabase: () => Database;
32
55
  export declare const useFirestore: () => Firestore;
56
+ export declare const useFunctions: () => Functions;
33
57
  export declare const usePerformance: () => FirebasePerformance;
34
58
  export declare const useStorage: () => FirebaseStorage;
35
59
  export declare const useRemoteConfig: () => RemoteConfig;
36
60
  declare type InitSdkHook<Sdk extends FirebaseSdks> = (initializer: (firebaseApp: FirebaseApp) => Promise<Sdk>, options?: ReactFireOptions<Sdk>) => ObservableStatus<Sdk>;
61
+ export declare const useInitAppCheck: InitSdkHook<AppCheck>;
37
62
  export declare const useInitAuth: InitSdkHook<Auth>;
63
+ export declare const useInitAnalytics: InitSdkHook<Analytics>;
38
64
  export declare const useInitDatabase: InitSdkHook<Database>;
39
65
  export declare const useInitFirestore: InitSdkHook<Firestore>;
66
+ export declare const useInitFunctions: InitSdkHook<Functions>;
40
67
  export declare const useInitPerformance: InitSdkHook<FirebasePerformance>;
41
68
  export declare const useInitRemoteConfig: InitSdkHook<RemoteConfig>;
42
69
  export declare const useInitStorage: InitSdkHook<FirebaseStorage>;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.0.0-exp.e80fc49",
2
+ "version": "4.0.0-exp.eb1428b",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -14,19 +14,21 @@
14
14
  "start": "tsdx watch",
15
15
  "build": "tsdx build",
16
16
  "test:tsdx": "tsdx test",
17
- "test": "firebase emulators:exec --only firestore,database,auth,storage --project=rxfire-525a3 \"tsdx test\"",
17
+ "test": "firebase emulators:exec --project=rxfire-525a3 \"tsdx test\"",
18
18
  "test:firestore": "firebase emulators:exec --only firestore --project=rxfire-525a3 \"tsdx test firestore --verbose\"",
19
19
  "test:database": "firebase emulators:exec --only database --project=rxfire-525a3 \"tsdx test database --verbose\"",
20
20
  "test:auth": "firebase emulators:exec --only auth --project=rxfire-525a3 \"tsdx test auth --verbose\"",
21
+ "test:functions": "firebase emulators:exec --only functions --project=rxfire-525a3 \"tsdx test functions --verbose\"",
21
22
  "test:storage": "firebase emulators:exec --only storage --project=rxfire-525a3 \"tsdx test storage --verbose\"",
22
23
  "test:useObservable": "tsdx test useObservable --verbose",
23
24
  "lint": "tsdx lint src test",
24
25
  "size": "size-limit",
25
26
  "analyze": "size-limit --why",
26
- "docs": "typedoc --options typedoc.json && markdown-toc -i docs/use.md"
27
+ "docs": "typedoc --options typedoc.json && markdown-toc -i docs/use.md",
28
+ "docs:fork": "typedoc --options typedoc.json --gitRemote upstream && markdown-toc -i docs/use.md"
27
29
  },
28
30
  "peerDependencies": {
29
- "firebase": "9.0.0-2021720181311",
31
+ "firebase": "^9.0.0",
30
32
  "react": ">=16 || experimental"
31
33
  },
32
34
  "husky": {
@@ -81,8 +83,8 @@
81
83
  "babel-jest": "^26.6.3",
82
84
  "babel-plugin-minify-replace": "^0.5.0",
83
85
  "eslint-plugin-no-only-tests": "^2.6.0",
84
- "firebase": "9.0.0-2021720181311",
85
- "firebase-tools": "^9.16.0",
86
+ "firebase": "^9.0.1",
87
+ "firebase-tools": "^10.9.2",
86
88
  "globalthis": "^1.0.1",
87
89
  "husky": "^4.3.0",
88
90
  "jest-environment-jsdom": "^26.6.2",
@@ -99,7 +101,7 @@
99
101
  "typescript": "^4.2.4"
100
102
  },
101
103
  "dependencies": {
102
- "rxfire": "6.0.0-rc.1",
104
+ "rxfire": "^6.0.2",
103
105
  "rxjs": "^6.6.3 || ^7.0.1"
104
106
  },
105
107
  "resolutions": {
@@ -10,9 +10,9 @@ export class SuspenseSubject<T> extends Subject<T> {
10
10
  private _innerObservable: Observable<T>;
11
11
  private _warmupSubscription: Subscription;
12
12
 
13
- // @ts-ignore: TODO: double check to see if this is an RXJS thing or if we should listen to TS
13
+ // @ts-expect-error: TODO: double check to see if this is an RXJS thing or if we should listen to TS
14
14
  private _innerSubscriber: Subscription;
15
- // @ts-ignore: TODO: double check to see if this is an RXJS thing or if we should listen to TS
15
+ // @ts-expect-error: TODO: double check to see if this is an RXJS thing or if we should listen to TS
16
16
  private _resolveFirstEmission: () => void;
17
17
 
18
18
  constructor(innerObservable: Observable<T>, private _timeoutWindow: number) {
@@ -48,14 +48,16 @@ export class SuspenseSubject<T> extends Subject<T> {
48
48
  return this._hasValue || !!this._error;
49
49
  }
50
50
 
51
- get value(): T | undefined {
51
+ get value(): T {
52
52
  // TODO figure out how to reset the cache here, if I _reset() here before throwing
53
53
  // it doesn't seem to work.
54
54
  // As it is now, this will burn the cache entry until the timeout fires.
55
55
  if (this._error) {
56
56
  throw this._error;
57
+ } else if (!this.hasValue) {
58
+ throw Error('Can only get value if SuspenseSubject has a value');
57
59
  }
58
- return this._value;
60
+ return this._value as T;
59
61
  }
60
62
 
61
63
  get firstEmission(): Promise<void> {
package/src/auth.tsx CHANGED
@@ -24,15 +24,15 @@ export function useUser<T = unknown>(options?: ReactFireOptions<T>): ObservableS
24
24
 
25
25
  const observableId = `auth:user:${auth.name}`;
26
26
  const observable$ = user(auth);
27
+ const _options: ReactFireOptions<T> = {...options} ?? {};
27
28
 
28
- let currentUser = auth.currentUser;
29
-
30
- // Only use options.initialData if auth.currentUser is unavailable
31
- if (!currentUser && (options?.initialData ?? options?.startWithValue)) {
32
- currentUser = options.initialData ?? options.startWithValue;
29
+ // only set/override initialData if auth has finished loading
30
+ if (auth.currentUser !== undefined) {
31
+ _options.initialData = auth.currentUser;
32
+ _options.startWithValue = auth.currentUser;
33
33
  }
34
34
 
35
- return useObservable(observableId, observable$, { ...options, initialData: currentUser });
35
+ return useObservable(observableId, observable$, _options);
36
36
  }
37
37
 
38
38
  export function useIdTokenResult(user: User, forceRefresh: boolean = false, options?: ReactFireOptions<IdTokenResult>): ObservableStatus<IdTokenResult> {
package/src/database.tsx CHANGED
@@ -1,9 +1,6 @@
1
- import { list, object, QueryChange, listVal } from 'rxfire/database';
1
+ import { list, object, QueryChange, listVal, objectVal } from 'rxfire/database';
2
2
  import { ReactFireOptions, useObservable, checkIdField, ObservableStatus, ReactFireGlobals } from './';
3
3
 
4
- import { Observable } from 'rxjs';
5
- import { map } from 'rxjs/operators';
6
-
7
4
  import type { Query as DatabaseQuery, DatabaseReference } from 'firebase/database';
8
5
 
9
6
  // Since we're side-effect free, we need to ensure our observableId cache is global
@@ -34,33 +31,10 @@ export function useDatabaseObject<T = unknown>(ref: DatabaseReference, options?:
34
31
  return useObservable(observableId, observable$, options);
35
32
  }
36
33
 
37
- // ============================================================================
38
- // TODO: switch to rxfire's objectVal once this PR is merged:
39
- // https://github.com/firebase/firebase-js-sdk/pull/2352
40
-
41
- function objectVal<T>(query: DatabaseQuery, keyField?: string): Observable<T> {
42
- return object(query).pipe(map((change) => changeToData(change, keyField) as T));
43
- }
44
-
45
- function changeToData(change: QueryChange, keyField?: string): {} {
46
- const val = change.snapshot.val();
47
-
48
- // don't worry about setting IDs if the value is a primitive type
49
- if (typeof val !== 'object') {
50
- return val;
51
- }
52
-
53
- return {
54
- ...change.snapshot.val(),
55
- ...(keyField ? { [keyField]: change.snapshot.key } : null),
56
- };
57
- }
58
- // ============================================================================
59
-
60
34
  export function useDatabaseObjectData<T>(ref: DatabaseReference, options?: ReactFireOptions<T>): ObservableStatus<T> {
61
35
  const idField = options ? checkIdField(options) : 'NO_ID_FIELD';
62
36
  const observableId = `database:objectVal:${ref.toString()}:idField=${idField}`;
63
- const observable$ = objectVal<T>(ref, idField);
37
+ const observable$ = objectVal<T>(ref, { keyField: idField });
64
38
 
65
39
  return useObservable(observableId, observable$, options);
66
40
  }
@@ -87,6 +61,6 @@ export function useDatabaseListData<T = { [key: string]: unknown }>(
87
61
  ): ObservableStatus<T[] | null> {
88
62
  const idField = options ? checkIdField(options) : 'NO_ID_FIELD';
89
63
  const observableId = `database:listVal:${getUniqueIdForDatabaseQuery(ref)}:idField=${idField}`;
90
- const observable$ = listVal<T>(ref, idField);
64
+ const observable$ = listVal<T>(ref, { keyField: idField });
91
65
  return useObservable(observableId, observable$, options);
92
66
  }
@@ -16,7 +16,7 @@ interface FirebaseAppProviderProps {
16
16
  suspense?: boolean;
17
17
  }
18
18
 
19
- // @ts-ignore: "__REACTFIRE_VERSION__" is replaced with actual ReactFire version (see babel.config.js)
19
+ // @ts-expect-error: "__REACTFIRE_VERSION__" is replaced with actual ReactFire version (see babel.config.js)
20
20
  export const version = __REACTFIRE_VERSION__;
21
21
 
22
22
  const shallowEq = (a: { [key: string]: any }, b: { [key: string]: any }) => a === b || [...Object.keys(a), ...Object.keys(b)].every((key) => a[key] === b[key]);
package/src/firestore.tsx CHANGED
@@ -63,7 +63,7 @@ export function useFirestoreDocData<T = unknown>(ref: DocumentReference<T>, opti
63
63
  const idField = options ? checkIdField(options) : 'NO_ID_FIELD';
64
64
 
65
65
  const observableId = `firestore:docData:${ref.firestore.app.name}:${ref.path}:idField=${idField}`;
66
- const observable = docData(ref, idField);
66
+ const observable = docData(ref, { idField });
67
67
 
68
68
  return useObservable(observableId, observable, options);
69
69
  }
@@ -75,7 +75,7 @@ export function useFirestoreDocDataOnce<T = unknown>(ref: DocumentReference<T>,
75
75
  const idField = options ? checkIdField(options) : 'NO_ID_FIELD';
76
76
 
77
77
  const observableId = `firestore:docDataOnce:${ref.firestore.app.name}:${ref.path}:idField=${idField}`;
78
- const observable$ = docData(ref, idField).pipe(first());
78
+ const observable$ = docData(ref, { idField }).pipe(first());
79
79
 
80
80
  return useObservable(observableId, observable$, options);
81
81
  }
@@ -96,7 +96,7 @@ export function useFirestoreCollection<T = DocumentData>(query: FirestoreQuery<T
96
96
  export function useFirestoreCollectionData<T = DocumentData>(query: FirestoreQuery<T>, options?: ReactFireOptions<T[]>): ObservableStatus<T[]> {
97
97
  const idField = options ? checkIdField(options) : 'NO_ID_FIELD';
98
98
  const observableId = `firestore:collectionData:${getUniqueIdForFirestoreQuery(query)}:idField=${idField}`;
99
- const observable$ = collectionData(query, idField);
99
+ const observable$ = collectionData(query, { idField });
100
100
 
101
101
  return useObservable(observableId, observable$, options);
102
102
  }
@@ -0,0 +1,26 @@
1
+ import { httpsCallable as rxHttpsCallable } from 'rxfire/functions';
2
+ import { ReactFireOptions, useObservable, ObservableStatus } from './';
3
+ import { useFunctions } from '.';
4
+
5
+ import type { HttpsCallableOptions } from 'firebase/functions';
6
+
7
+ /**
8
+ * Calls a callable function.
9
+ *
10
+ * @param functionName - The name of the function to call
11
+ * @param options
12
+ */
13
+ export function useCallableFunctionResponse<RequestData, ResponseData>(
14
+ functionName: string,
15
+ options?: ReactFireOptions<ResponseData> & {
16
+ httpsCallableOptions?: HttpsCallableOptions;
17
+ data?: RequestData;
18
+ }
19
+ ): ObservableStatus<ResponseData> {
20
+ const functions = useFunctions();
21
+ const observableId = `functions:callableResponse:${functionName}:${JSON.stringify(options?.data)}:${JSON.stringify(options?.httpsCallableOptions)}`;
22
+ const obsFactory = rxHttpsCallable<RequestData, ResponseData>(functions, functionName, options?.httpsCallableOptions);
23
+ const observable$ = obsFactory(options?.data);
24
+
25
+ return useObservable(observableId, observable$, options);
26
+ }
package/src/index.ts CHANGED
@@ -52,6 +52,7 @@ export * from './auth';
52
52
  export * from './database';
53
53
  export * from './firebaseApp';
54
54
  export * from './firestore';
55
+ export * from './functions';
55
56
  export * from './performance';
56
57
  export * from './remote-config';
57
58
  export * from './storage';
@@ -1,17 +1,12 @@
1
- import { useRemoteConfig } from '../';
2
- import { useObservable, ObservableStatus } from '../useObservable';
3
- import { getValue, getString, getBoolean, getNumber, getAll, AllParameters } from './getValue';
1
+ import { useRemoteConfig } from './';
2
+ import { useObservable, ObservableStatus } from './useObservable';
3
+ import { getValue, getString, getBoolean, getNumber, getAll, AllParameters } from 'rxfire/remote-config';
4
4
  import { Observable } from 'rxjs';
5
5
 
6
6
  import type { RemoteConfig, Value as RemoteConfigValue } from 'firebase/remote-config';
7
7
 
8
8
  type Getter$<T> = (remoteConfig: RemoteConfig, key: string) => Observable<T>;
9
9
 
10
- interface RemoteConfigWithPrivate extends RemoteConfig {
11
- // This is a private API, assume optional
12
- _storage?: { appName: string };
13
- }
14
-
15
10
  /**
16
11
  * Helper function to construct type safe functions. Since Remote Config has
17
12
  * methods that return different types for values, we need to be extra safe
@@ -23,9 +18,7 @@ interface RemoteConfigWithPrivate extends RemoteConfig {
23
18
  function useRemoteConfigValue_INTERNAL<T>(key: string, getter: Getter$<T>): ObservableStatus<T> {
24
19
  const remoteConfig = useRemoteConfig();
25
20
 
26
- // INVESTIGATE need to use a public API to get at the app name, one doesn't appear to exist...
27
- // we might need to iterate over the Firebase apps and check for remoteConfig equality? this works for now
28
- const appName = (remoteConfig as RemoteConfigWithPrivate)._storage?.appName;
21
+ const appName = remoteConfig.app.name;
29
22
  const $value = getter(remoteConfig, key);
30
23
 
31
24
  const observableId = `remoteConfig:${key}:${getter.name}:${appName}`;
@@ -37,7 +30,6 @@ function useRemoteConfigValue_INTERNAL<T>(key: string, getter: Getter$<T>): Obse
37
30
  * Remote Config Value.
38
31
  *
39
32
  * @param key The parameter key in Remote Config
40
- * @param remoteConfig Optional instance. If not provided ReactFire will either grab the default instance or lazy load.
41
33
  */
42
34
  export function useRemoteConfigValue(key: string): ObservableStatus<RemoteConfigValue> {
43
35
  return useRemoteConfigValue_INTERNAL<RemoteConfigValue>(key, getValue);
@@ -46,7 +38,6 @@ export function useRemoteConfigValue(key: string): ObservableStatus<RemoteConfig
46
38
  /**
47
39
  * Convience method similar to useRemoteConfigValue. Returns a `string` from a Remote Config parameter.
48
40
  * @param key The parameter key in Remote Config
49
- * @param remoteConfig Optional instance. If not provided ReactFire will either grab the default instance or lazy load.
50
41
  */
51
42
  export function useRemoteConfigString(key: string): ObservableStatus<string> {
52
43
  return useRemoteConfigValue_INTERNAL<string>(key, getString);
@@ -55,7 +46,6 @@ export function useRemoteConfigString(key: string): ObservableStatus<string> {
55
46
  /**
56
47
  * Convience method similar to useRemoteConfigValue. Returns a `number` from a Remote Config parameter.
57
48
  * @param key The parameter key in Remote Config
58
- * @param remoteConfig Optional instance. If not provided ReactFire will either grab the default instance or lazy load.
59
49
  */
60
50
  export function useRemoteConfigNumber(key: string): ObservableStatus<number> {
61
51
  return useRemoteConfigValue_INTERNAL<number>(key, getNumber);
@@ -64,7 +54,6 @@ export function useRemoteConfigNumber(key: string): ObservableStatus<number> {
64
54
  /**
65
55
  * Convience method similar to useRemoteConfigValue. Returns a `boolean` from a Remote Config parameter.
66
56
  * @param key The parameter key in Remote Config
67
- * @param remoteConfig Optional instance. If not provided ReactFire will either grab the default instance or lazy load.
68
57
  */
69
58
  export function useRemoteConfigBoolean(key: string): ObservableStatus<boolean> {
70
59
  return useRemoteConfigValue_INTERNAL<boolean>(key, getBoolean);
@@ -73,7 +62,6 @@ export function useRemoteConfigBoolean(key: string): ObservableStatus<boolean> {
73
62
  /**
74
63
  * Convience method similar to useRemoteConfigValue. Returns allRemote Config parameters.
75
64
  * @param key The parameter key in Remote Config
76
- * @param remoteConfig Optional instance. If not provided ReactFire will either grab the default instance or lazy load.
77
65
  */
78
66
  export function useRemoteConfigAll(key: string): ObservableStatus<AllParameters> {
79
67
  return useRemoteConfigValue_INTERNAL<AllParameters>(key, getAll);
package/src/sdk.tsx CHANGED
@@ -1,8 +1,11 @@
1
1
  import * as React from 'react';
2
2
 
3
+ import type { AppCheck } from 'firebase/app-check';
3
4
  import type { Auth } from 'firebase/auth';
5
+ import type { Analytics } from 'firebase/analytics';
4
6
  import type { Database } from 'firebase/database';
5
7
  import type { Firestore } from 'firebase/firestore';
8
+ import type { Functions } from 'firebase/functions';
6
9
  import type { FirebasePerformance } from 'firebase/performance';
7
10
  import type { FirebaseStorage } from 'firebase/storage';
8
11
  import type { RemoteConfig } from 'firebase/remote-config';
@@ -12,38 +15,25 @@ import { ObservableStatus, useObservable } from './useObservable';
12
15
  import { from } from 'rxjs';
13
16
  import { ReactFireOptions } from '.';
14
17
 
15
- const AuthSdkContext = React.createContext<Auth | undefined>(undefined);
16
- const DatabaseSdkContext = React.createContext<Database | undefined>(undefined);
17
- const FirestoreSdkContext = React.createContext<Firestore | undefined>(undefined);
18
- const StorageSdkContext = React.createContext<FirebaseStorage | undefined>(undefined);
19
- const PerformanceSdkContext = React.createContext<FirebasePerformance | undefined>(undefined);
20
- const RemoteConfigSdkContext = React.createContext<RemoteConfig | undefined>(undefined);
18
+ export const AppCheckSdkContext = React.createContext<AppCheck | undefined>(undefined);
19
+ export const AuthSdkContext = React.createContext<Auth | undefined>(undefined);
20
+ export const AnalyticsSdkContext = React.createContext<Analytics | undefined>(undefined);
21
+ export const DatabaseSdkContext = React.createContext<Database | undefined>(undefined);
22
+ export const FirestoreSdkContext = React.createContext<Firestore | undefined>(undefined);
23
+ export const FunctionsSdkContext = React.createContext<Functions | undefined>(undefined);
24
+ export const StorageSdkContext = React.createContext<FirebaseStorage | undefined>(undefined);
25
+ export const PerformanceSdkContext = React.createContext<FirebasePerformance | undefined>(undefined);
26
+ export const RemoteConfigSdkContext = React.createContext<RemoteConfig | undefined>(undefined);
21
27
 
22
- type FirebaseSdks = Auth | Database | Firestore | FirebasePerformance | FirebaseStorage | RemoteConfig;
28
+ type FirebaseSdks = Analytics | AppCheck | Auth | Database | Firestore | FirebasePerformance | FirebaseStorage | Functions | RemoteConfig;
23
29
 
24
30
  function getSdkProvider<Sdk extends FirebaseSdks>(SdkContext: React.Context<Sdk | undefined>) {
25
31
  return function SdkProvider(props: React.PropsWithChildren<{ sdk: Sdk }>) {
26
- const contextualAppName = useFirebaseApp().name;
27
- let sdkAppName;
28
-
29
- // @ts-ignore Auth doesn't have field 'app'
30
- if (props.sdk.app) {
31
- // @ts-ignore Auth doesn't have field 'app'
32
- sdkAppName = props.sdk.app.name;
33
-
34
- // @ts-ignore only Auth has field 'name'
35
- } else if (props.sdk.name) {
36
- // @ts-ignore only Auth has field 'name'
37
- sdkAppName = props.sdk.name;
38
- }
32
+ if (!props.sdk) throw new Error('no sdk provided');
39
33
 
40
- if (sdkAppName !== contextualAppName) {
41
- throw new Error('sdk was initialized with a different firebase app');
42
- }
43
-
44
- if (!props.sdk) {
45
- throw new Error('no sdk provided');
46
- }
34
+ const contextualAppName = useFirebaseApp().name;
35
+ const sdkAppName = props?.sdk?.app?.name;
36
+ if (sdkAppName !== contextualAppName) throw new Error('sdk was initialized with a different firebase app');
47
37
 
48
38
  return <SdkContext.Provider value={props.sdk} {...props} />;
49
39
  };
@@ -79,16 +69,22 @@ function useInitSdk<Sdk extends FirebaseSdks>(
79
69
  return useObservable<Sdk>(`firebase-sdk:${sdkName}:${firebaseApp.name}`, from(initializeSdk), options);
80
70
  }
81
71
 
72
+ export const AppCheckProvider = getSdkProvider<AppCheck>(AppCheckSdkContext);
82
73
  export const AuthProvider = getSdkProvider<Auth>(AuthSdkContext);
74
+ export const AnalyticsProvider = getSdkProvider<Analytics>(AnalyticsSdkContext);
83
75
  export const DatabaseProvider = getSdkProvider<Database>(DatabaseSdkContext);
84
76
  export const FirestoreProvider = getSdkProvider<Firestore>(FirestoreSdkContext);
77
+ export const FunctionsProvider = getSdkProvider<Functions>(FunctionsSdkContext);
85
78
  export const PerformanceProvider = getSdkProvider<FirebasePerformance>(PerformanceSdkContext);
86
79
  export const StorageProvider = getSdkProvider<FirebaseStorage>(StorageSdkContext);
87
80
  export const RemoteConfigProvider = getSdkProvider<RemoteConfig>(RemoteConfigSdkContext);
88
81
 
82
+ export const useAppCheck = () => useSdk<AppCheck>(AppCheckSdkContext);
89
83
  export const useAuth = () => useSdk<Auth>(AuthSdkContext);
84
+ export const useAnalytics = () => useSdk<Analytics>(AnalyticsSdkContext);
90
85
  export const useDatabase = () => useSdk<Database>(DatabaseSdkContext);
91
86
  export const useFirestore = () => useSdk<Firestore>(FirestoreSdkContext);
87
+ export const useFunctions = () => useSdk<Functions>(FunctionsSdkContext);
92
88
  export const usePerformance = () => useSdk<FirebasePerformance>(PerformanceSdkContext);
93
89
  export const useStorage = () => useSdk<FirebaseStorage>(StorageSdkContext);
94
90
  export const useRemoteConfig = () => useSdk<RemoteConfig>(RemoteConfigSdkContext);
@@ -98,9 +94,12 @@ type InitSdkHook<Sdk extends FirebaseSdks> = (
98
94
  options?: ReactFireOptions<Sdk>
99
95
  ) => ObservableStatus<Sdk>;
100
96
 
97
+ export const useInitAppCheck: InitSdkHook<AppCheck> = (initializer, options) => useInitSdk<AppCheck>('appcheck', AppCheckSdkContext, initializer, options);
101
98
  export const useInitAuth: InitSdkHook<Auth> = (initializer, options) => useInitSdk<Auth>('auth', AuthSdkContext, initializer, options);
99
+ export const useInitAnalytics: InitSdkHook<Analytics> = (initializer, options) => useInitSdk<Analytics>('analytics', AnalyticsSdkContext, initializer, options);
102
100
  export const useInitDatabase: InitSdkHook<Database> = (initializer, options) => useInitSdk<Database>('database', DatabaseSdkContext, initializer, options);
103
101
  export const useInitFirestore: InitSdkHook<Firestore> = (initializer, options) => useInitSdk<Firestore>('firestore', FirestoreSdkContext, initializer, options);
102
+ export const useInitFunctions: InitSdkHook<Functions> = (initializer, options) => useInitSdk<Functions>('functions', FunctionsSdkContext, initializer, options);
104
103
  export const useInitPerformance: InitSdkHook<FirebasePerformance> = (initializer, options) =>
105
104
  useInitSdk<FirebasePerformance>('performance', PerformanceSdkContext, initializer, options);
106
105
  export const useInitRemoteConfig: InitSdkHook<RemoteConfig> = (initializer, options) =>
package/src/storage.tsx CHANGED
@@ -1,33 +1,11 @@
1
1
  import * as React from 'react';
2
- import { getDownloadURL } from 'rxfire/storage';
3
- import { Observable } from 'rxjs';
2
+ import { getDownloadURL, fromTask } from 'rxfire/storage';
4
3
  import { ReactFireOptions, useObservable, ObservableStatus, useStorage } from './';
5
4
  import { useSuspenseEnabledFromConfigAndContext } from './firebaseApp';
6
5
  import { ref } from 'firebase/storage';
7
6
 
8
7
  import type { UploadTask, UploadTaskSnapshot, StorageReference, FirebaseStorage } from 'firebase/storage';
9
8
 
10
- /**
11
- * modified version of rxFire's _fromTask
12
- *
13
- * @param task
14
- */
15
- function _fromTask(task: UploadTask) {
16
- return new Observable<UploadTaskSnapshot>((subscriber) => {
17
- const progress = (snap: UploadTaskSnapshot) => {
18
- return subscriber.next(snap);
19
- };
20
- const error = (e: any) => subscriber.error(e);
21
- const complete = () => {
22
- return subscriber.complete();
23
- };
24
- task.on('state_changed', progress, error, complete);
25
-
26
- // I REMOVED THE UNSUBSCRIBE RETURN BECAUSE IT CANCELS THE UPLOAD
27
- // https://github.com/firebase/firebase-js-sdk/issues/1659
28
- });
29
- }
30
-
31
9
  /**
32
10
  * Subscribe to the progress of a storage task
33
11
  *
@@ -37,7 +15,7 @@ function _fromTask(task: UploadTask) {
37
15
  */
38
16
  export function useStorageTask<T = unknown>(task: UploadTask, ref: StorageReference, options?: ReactFireOptions<T>): ObservableStatus<UploadTaskSnapshot | T> {
39
17
  const observableId = `storage:task:${ref.toString()}`;
40
- const observable$ = _fromTask(task);
18
+ const observable$ = fromTask(task);
41
19
 
42
20
  return useObservable(observableId, observable$, options);
43
21
  }