reactfire 4.0.0-exp.cb3fede → 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.
- package/README.md +12 -34
- package/dist/SuspenseSubject.d.ts +1 -1
- package/dist/functions.d.ts +12 -0
- package/dist/index.d.ts +1 -0
- package/dist/reactfire.cjs.development.js +155 -212
- package/dist/reactfire.cjs.development.js.map +1 -1
- package/dist/reactfire.cjs.production.min.js +1 -1
- package/dist/reactfire.cjs.production.min.js.map +1 -1
- package/dist/reactfire.esm.js +136 -212
- package/dist/reactfire.esm.js.map +1 -1
- package/dist/{remote-config/index.d.ts → remote-config.d.ts} +2 -7
- package/dist/sdk.d.ts +28 -1
- package/package.json +9 -7
- package/src/SuspenseSubject.ts +6 -4
- package/src/auth.tsx +6 -6
- package/src/database.tsx +3 -29
- package/src/firebaseApp.tsx +1 -1
- package/src/firestore.tsx +3 -3
- package/src/functions.tsx +26 -0
- package/src/index.ts +1 -0
- package/src/{remote-config/index.tsx → remote-config.tsx} +4 -16
- package/src/sdk.tsx +26 -27
- package/src/storage.tsx +2 -24
- package/src/useObservable.ts +48 -28
- package/dist/remote-config/getValue.d.ts +0 -10
- package/src/remote-config/getValue.tsx +0 -58
package/src/useObservable.ts
CHANGED
|
@@ -63,55 +63,75 @@ export interface ObservableStatus<T> {
|
|
|
63
63
|
firstValuePromise: Promise<void>;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
function reducerFactory<T>(observable: SuspenseSubject<T>) {
|
|
67
|
+
return function reducer(state: ObservableStatus<T>, action: 'value' | 'error' | 'complete'): ObservableStatus<T> {
|
|
68
|
+
// always make sure these values are in sync with the observable
|
|
69
|
+
const newState = {
|
|
70
|
+
...state,
|
|
71
|
+
hasEmitted: state.hasEmitted || observable.hasValue,
|
|
72
|
+
error: observable.ourError,
|
|
73
|
+
firstValuePromise: observable.firstEmission,
|
|
74
|
+
};
|
|
75
|
+
if (observable.hasValue) {
|
|
76
|
+
newState.data = observable.value;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
switch (action) {
|
|
80
|
+
case 'value':
|
|
81
|
+
newState.status = 'success';
|
|
82
|
+
return newState;
|
|
83
|
+
case 'error':
|
|
84
|
+
newState.status = 'error';
|
|
85
|
+
return newState;
|
|
86
|
+
case 'complete':
|
|
87
|
+
newState.isComplete = true;
|
|
88
|
+
return newState;
|
|
89
|
+
default:
|
|
90
|
+
throw new Error(`invalid action "${action}"`);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
66
95
|
export function useObservable<T = unknown>(observableId: string, source: Observable<T>, config: ReactFireOptions = {}): ObservableStatus<T> {
|
|
96
|
+
// Register the observable with the cache
|
|
67
97
|
if (!observableId) {
|
|
68
98
|
throw new Error('cannot call useObservable without an observableId');
|
|
69
99
|
}
|
|
70
100
|
const observable = preloadObservable(source, observableId);
|
|
71
101
|
|
|
102
|
+
// Suspend if suspense is enabled and no initial data exists
|
|
72
103
|
const hasInitialData = config.hasOwnProperty('initialData') || config.hasOwnProperty('startWithValue');
|
|
73
|
-
|
|
104
|
+
const hasData = observable.hasValue || hasInitialData;
|
|
74
105
|
const suspenseEnabled = useSuspenseEnabledFromConfigAndContext(config.suspense);
|
|
75
|
-
|
|
76
|
-
if (suspenseEnabled === true && !observable.hasValue && (!config?.initialData ?? !config?.startWithValue)) {
|
|
106
|
+
if (suspenseEnabled === true && !hasData) {
|
|
77
107
|
throw observable.firstEmission;
|
|
78
108
|
}
|
|
79
109
|
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
110
|
+
const initialState: ObservableStatus<T> = {
|
|
111
|
+
status: hasData ? 'success' : 'loading',
|
|
112
|
+
hasEmitted: hasData,
|
|
113
|
+
isComplete: false,
|
|
114
|
+
data: observable.hasValue ? observable.value : config?.initialData ?? config?.startWithValue,
|
|
115
|
+
error: observable.ourError,
|
|
116
|
+
firstValuePromise: observable.firstEmission,
|
|
117
|
+
};
|
|
118
|
+
const [status, dispatch] = React.useReducer<React.Reducer<ObservableStatus<T>, 'value' | 'error' | 'complete'>>(reducerFactory<T>(observable), initialState);
|
|
119
|
+
|
|
83
120
|
React.useEffect(() => {
|
|
84
121
|
const subscription = observable.subscribe({
|
|
85
|
-
next: (
|
|
86
|
-
|
|
122
|
+
next: () => {
|
|
123
|
+
dispatch('value');
|
|
87
124
|
},
|
|
88
125
|
error: (e) => {
|
|
89
|
-
|
|
126
|
+
dispatch('error');
|
|
90
127
|
throw e;
|
|
91
128
|
},
|
|
92
129
|
complete: () => {
|
|
93
|
-
|
|
130
|
+
dispatch('complete');
|
|
94
131
|
},
|
|
95
132
|
});
|
|
96
133
|
return () => subscription.unsubscribe();
|
|
97
134
|
}, [observable]);
|
|
98
135
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (hasError) {
|
|
102
|
-
status = 'error';
|
|
103
|
-
} else if (observable.hasValue || hasInitialData) {
|
|
104
|
-
status = 'success';
|
|
105
|
-
} else {
|
|
106
|
-
status = 'loading';
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
status,
|
|
111
|
-
hasEmitted: observable.hasValue || hasInitialData,
|
|
112
|
-
isComplete: isComplete,
|
|
113
|
-
data: latest,
|
|
114
|
-
error: observable.ourError,
|
|
115
|
-
firstValuePromise: observable.firstEmission,
|
|
116
|
-
};
|
|
136
|
+
return status;
|
|
117
137
|
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
2
|
-
import type { RemoteConfig, Value as RemoteConfigValue } from 'firebase/remote-config';
|
|
3
|
-
export declare type AllParameters = {
|
|
4
|
-
[key: string]: RemoteConfigValue;
|
|
5
|
-
};
|
|
6
|
-
export declare function getValue(remoteConfig: RemoteConfig, key: string): Observable<RemoteConfigValue>;
|
|
7
|
-
export declare function getString(remoteConfig: RemoteConfig, key: string): Observable<string>;
|
|
8
|
-
export declare function getNumber(remoteConfig: RemoteConfig, key: string): Observable<number>;
|
|
9
|
-
export declare function getBoolean(remoteConfig: RemoteConfig, key: string): Observable<boolean>;
|
|
10
|
-
export declare function getAll(remoteConfig: RemoteConfig): Observable<AllParameters>;
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
2
|
-
import {
|
|
3
|
-
ensureInitialized,
|
|
4
|
-
getValue as rcGetValue,
|
|
5
|
-
getString as rcGetString,
|
|
6
|
-
getNumber as rcGetNumber,
|
|
7
|
-
getBoolean as rcGetBoolean,
|
|
8
|
-
getAll as rcGetAll,
|
|
9
|
-
} from 'firebase/remote-config';
|
|
10
|
-
|
|
11
|
-
import type { RemoteConfig, Value as RemoteConfigValue } from 'firebase/remote-config';
|
|
12
|
-
|
|
13
|
-
export type AllParameters = {
|
|
14
|
-
[key: string]: RemoteConfigValue;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
interface ParameterSettings<T> {
|
|
18
|
-
remoteConfig: RemoteConfig;
|
|
19
|
-
key: string;
|
|
20
|
-
getter: (key: string) => T;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// TODO(davideast): Replace with RxFire functions when they land
|
|
24
|
-
function parameter$<T>({ remoteConfig, key, getter }: ParameterSettings<T>): Observable<T> {
|
|
25
|
-
return new Observable((subscriber) => {
|
|
26
|
-
ensureInitialized(remoteConfig).then(() => {
|
|
27
|
-
// 'this' for the getter loses context in the next()
|
|
28
|
-
// call, so it needs to be bound.
|
|
29
|
-
subscriber.next(getter.bind(remoteConfig)(key));
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function getValue(remoteConfig: RemoteConfig, key: string) {
|
|
35
|
-
const getter = () => rcGetValue(remoteConfig, key);
|
|
36
|
-
return parameter$({ remoteConfig, key, getter });
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function getString(remoteConfig: RemoteConfig, key: string) {
|
|
40
|
-
const getter = () => rcGetString(remoteConfig, key);
|
|
41
|
-
return parameter$<string>({ remoteConfig, key, getter });
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function getNumber(remoteConfig: RemoteConfig, key: string) {
|
|
45
|
-
const getter = () => rcGetNumber(remoteConfig, key);
|
|
46
|
-
return parameter$<number>({ remoteConfig, key, getter });
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function getBoolean(remoteConfig: RemoteConfig, key: string) {
|
|
50
|
-
const getter = () => rcGetBoolean(remoteConfig, key);
|
|
51
|
-
return parameter$<boolean>({ remoteConfig, key, getter });
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function getAll(remoteConfig: RemoteConfig) {
|
|
55
|
-
const getter = () => rcGetAll(remoteConfig);
|
|
56
|
-
// No key is needed for getAll()
|
|
57
|
-
return parameter$<AllParameters>({ remoteConfig, key: '', getter });
|
|
58
|
-
}
|