15
15
* limitations under the License.
16
16
*/
17
17
18
- import { FirebaseApp } from '@firebase/app-types' ;
18
+ import { FirebaseApp } from '@firebase/app-types-exp ' ;
19
19
import {
20
20
RemoteConfig as RemoteConfigType ,
21
21
FetchStatus ,
22
- Settings ,
23
- Value as ValueType ,
24
- LogLevel as RemoteConfigLogLevel
25
- } from '@firebase/remote-config-types' ;
22
+ Settings
23
+ } from '@firebase/remote-config-types-exp' ;
26
24
import { StorageCache } from './storage/storage_cache' ;
27
- import {
28
- RemoteConfigFetchClient ,
29
- RemoteConfigAbortSignal
30
- } from './client/remote_config_fetch_client' ;
31
- import { Value } from './value' ;
32
- import { ErrorCode , hasErrorCode } from './errors' ;
25
+ import { RemoteConfigFetchClient } from './client/remote_config_fetch_client' ;
33
26
import { Storage } from './storage/storage' ;
34
- import { Logger , LogLevel as FirebaseLogLevel } from '@firebase/logger' ;
27
+ import { Logger } from '@firebase/logger' ;
35
28
36
29
const DEFAULT_FETCH_TIMEOUT_MILLIS = 60 * 1000 ; // One minute
37
30
const DEFAULT_CACHE_MAX_AGE_MILLIS = 12 * 60 * 60 * 1000 ; // Twelve hours.
@@ -42,11 +35,17 @@ const DEFAULT_CACHE_MAX_AGE_MILLIS = 12 * 60 * 60 * 1000; // Twelve hours.
42
35
* See {@link https://github.com/FirebasePrivate/firebase-js-sdk/blob/master/packages/firebase/index.d.ts|interface documentation} for method descriptions.
43
36
*/
44
37
export class RemoteConfig implements RemoteConfigType {
45
- // Tracks completion of initialization promise.
46
- private _isInitializationComplete = false ;
38
+ /**
39
+ * Tracks completion of initialization promise.
40
+ * @internal
41
+ */
42
+ public _isInitializationComplete = false ;
47
43
48
- // De-duplicates initialization calls.
49
- private _initializePromise ?: Promise < void > ;
44
+ /**
45
+ * De-duplicates initialization calls.
46
+ * @internal
47
+ */
48
+ public _initializePromise ?: Promise < void > ;
50
49
51
50
settings : Settings = {
52
51
fetchTimeoutMillis : DEFAULT_FETCH_TIMEOUT_MILLIS ,
@@ -55,21 +54,6 @@ export class RemoteConfig implements RemoteConfigType {
55
54
56
55
defaultConfig : { [ key : string ] : string | number | boolean } = { } ;
57
56
58
- // Based on packages/firestore/src/util/log.ts but not static because we need per-instance levels
59
- // to differentiate 2p and 3p use-cases.
60
- setLogLevel ( logLevel : RemoteConfigLogLevel ) : void {
61
- switch ( logLevel ) {
62
- case 'debug' :
63
- this . _logger . logLevel = FirebaseLogLevel . DEBUG ;
64
- break ;
65
- case 'silent' :
66
- this . _logger . logLevel = FirebaseLogLevel . SILENT ;
67
- break ;
68
- default :
69
- this . _logger . logLevel = FirebaseLogLevel . ERROR ;
70
- }
71
- }
72
-
73
57
get fetchTimeMillis ( ) : number {
74
58
return this . _storageCache . getLastSuccessfulFetchTimestampMillis ( ) || - 1 ;
75
59
}
@@ -89,131 +73,4 @@ export class RemoteConfig implements RemoteConfigType {
89
73
private readonly _storage : Storage ,
90
74
private readonly _logger : Logger
91
75
) { }
92
-
93
- async activate ( ) : Promise < boolean > {
94
- const [ lastSuccessfulFetchResponse , activeConfigEtag ] = await Promise . all ( [
95
- this . _storage . getLastSuccessfulFetchResponse ( ) ,
96
- this . _storage . getActiveConfigEtag ( )
97
- ] ) ;
98
- if (
99
- ! lastSuccessfulFetchResponse ||
100
- ! lastSuccessfulFetchResponse . config ||
101
- ! lastSuccessfulFetchResponse . eTag ||
102
- lastSuccessfulFetchResponse . eTag === activeConfigEtag
103
- ) {
104
- // Either there is no successful fetched config, or is the same as current active
105
- // config.
106
- return false ;
107
- }
108
- await Promise . all ( [
109
- this . _storageCache . setActiveConfig ( lastSuccessfulFetchResponse . config ) ,
110
- this . _storage . setActiveConfigEtag ( lastSuccessfulFetchResponse . eTag )
111
- ] ) ;
112
- return true ;
113
- }
114
-
115
- ensureInitialized ( ) : Promise < void > {
116
- if ( ! this . _initializePromise ) {
117
- this . _initializePromise = this . _storageCache
118
- . loadFromStorage ( )
119
- . then ( ( ) => {
120
- this . _isInitializationComplete = true ;
121
- } ) ;
122
- }
123
- return this . _initializePromise ;
124
- }
125
-
126
- /**
127
- * @throws a {@link ErrorCode.FETCH_CLIENT_TIMEOUT} if the request takes longer than
128
- * {@link Settings.fetchTimeoutInSeconds} or
129
- * {@link DEFAULT_FETCH_TIMEOUT_SECONDS}.
130
- */
131
- async fetch ( ) : Promise < void > {
132
- // Aborts the request after the given timeout, causing the fetch call to
133
- // reject with an AbortError.
134
- //
135
- // <p>Aborting after the request completes is a no-op, so we don't need a
136
- // corresponding clearTimeout.
137
- //
138
- // Locating abort logic here because:
139
- // * it uses a developer setting (timeout)
140
- // * it applies to all retries (like curl's max-time arg)
141
- // * it is consistent with the Fetch API's signal input
142
- const abortSignal = new RemoteConfigAbortSignal ( ) ;
143
-
144
- setTimeout ( async ( ) => {
145
- // Note a very low delay, eg < 10ms, can elapse before listeners are initialized.
146
- abortSignal . abort ( ) ;
147
- } , this . settings . fetchTimeoutMillis ) ;
148
-
149
- // Catches *all* errors thrown by client so status can be set consistently.
150
- try {
151
- await this . _client . fetch ( {
152
- cacheMaxAgeMillis : this . settings . minimumFetchIntervalMillis ,
153
- signal : abortSignal
154
- } ) ;
155
-
156
- await this . _storageCache . setLastFetchStatus ( 'success' ) ;
157
- } catch ( e ) {
158
- const lastFetchStatus = hasErrorCode ( e , ErrorCode . FETCH_THROTTLE )
159
- ? 'throttle'
160
- : 'failure' ;
161
- await this . _storageCache . setLastFetchStatus ( lastFetchStatus ) ;
162
- throw e ;
163
- }
164
- }
165
-
166
- async fetchAndActivate ( ) : Promise < boolean > {
167
- await this . fetch ( ) ;
168
- return this . activate ( ) ;
169
- }
170
-
171
- getAll ( ) : { [ key : string ] : ValueType } {
172
- return getAllKeys (
173
- this . _storageCache . getActiveConfig ( ) ,
174
- this . defaultConfig
175
- ) . reduce ( ( allConfigs , key ) => {
176
- allConfigs [ key ] = this . getValue ( key ) ;
177
- return allConfigs ;
178
- } , { } as { [ key : string ] : ValueType } ) ;
179
- }
180
-
181
- getBoolean ( key : string ) : boolean {
182
- return this . getValue ( key ) . asBoolean ( ) ;
183
- }
184
-
185
- getNumber ( key : string ) : number {
186
- return this . getValue ( key ) . asNumber ( ) ;
187
- }
188
-
189
- getString ( key : string ) : string {
190
- return this . getValue ( key ) . asString ( ) ;
191
- }
192
-
193
- getValue ( key : string ) : ValueType {
194
- if ( ! this . _isInitializationComplete ) {
195
- this . _logger . debug (
196
- `A value was requested for key "${ key } " before SDK initialization completed.` +
197
- ' Await on ensureInitialized if the intent was to get a previously activated value.'
198
- ) ;
199
- }
200
- const activeConfig = this . _storageCache . getActiveConfig ( ) ;
201
- if ( activeConfig && activeConfig [ key ] !== undefined ) {
202
- return new Value ( 'remote' , activeConfig [ key ] ) ;
203
- } else if ( this . defaultConfig && this . defaultConfig [ key ] !== undefined ) {
204
- return new Value ( 'default' , String ( this . defaultConfig [ key ] ) ) ;
205
- }
206
- this . _logger . debug (
207
- `Returning static value for key "${ key } ".` +
208
- ' Define a default or remote value if this is unintentional.'
209
- ) ;
210
- return new Value ( 'static' ) ;
211
- }
212
- }
213
-
214
- /**
215
- * Dedupes and returns an array of all the keys of the received objects.
216
- */
217
- function getAllKeys ( obj1 : { } = { } , obj2 : { } = { } ) : string [ ] {
218
- return Object . keys ( { ...obj1 , ...obj2 } ) ;
219
76
}
0 commit comments