|
16 | 16 | */
|
17 | 17 |
|
18 | 18 | import { _getProvider, FirebaseApp, getApp } from '@firebase/app';
|
| 19 | +import { deepEqual, getModularInstance } from '@firebase/util'; |
19 | 20 | import {
|
20 | 21 | CustomSignals,
|
21 | 22 | LogLevel as RemoteConfigLogLevel,
|
22 | 23 | RemoteConfig,
|
23 |
| - Value |
| 24 | + Value, |
| 25 | + RemoteConfigOptions |
24 | 26 | } from './public_types';
|
25 | 27 | import { RemoteConfigAbortSignal } from './client/remote_config_fetch_client';
|
26 | 28 | import {
|
27 | 29 | RC_COMPONENT_NAME,
|
28 | 30 | RC_CUSTOM_SIGNAL_KEY_MAX_LENGTH,
|
29 | 31 | RC_CUSTOM_SIGNAL_VALUE_MAX_LENGTH
|
30 | 32 | } from './constants';
|
31 |
| -import { ErrorCode, hasErrorCode } from './errors'; |
| 33 | +import { ERROR_FACTORY, ErrorCode, hasErrorCode } from './errors'; |
32 | 34 | import { RemoteConfig as RemoteConfigImpl } from './remote_config';
|
33 | 35 | import { Value as ValueImpl } from './value';
|
34 | 36 | import { LogLevel as FirebaseLogLevel } from '@firebase/logger';
|
35 |
| -import { getModularInstance } from '@firebase/util'; |
36 | 37 |
|
37 | 38 | /**
|
38 | 39 | *
|
39 | 40 | * @param app - The {@link @firebase/app#FirebaseApp} instance.
|
| 41 | + * @param options - Optional. The {@link RemoteConfigOptions} with which to instantiate the |
| 42 | + * Remote Config instance. |
40 | 43 | * @returns A {@link RemoteConfig} instance.
|
41 | 44 | *
|
42 | 45 | * @public
|
43 | 46 | */
|
44 |
| -export function getRemoteConfig(app: FirebaseApp = getApp()): RemoteConfig { |
| 47 | +export function getRemoteConfig( |
| 48 | + app: FirebaseApp = getApp(), |
| 49 | + options: RemoteConfigOptions = {} |
| 50 | +): RemoteConfig { |
45 | 51 | app = getModularInstance(app);
|
46 | 52 | const rcProvider = _getProvider(app, RC_COMPONENT_NAME);
|
47 |
| - return rcProvider.getImmediate(); |
| 53 | + if (rcProvider.isInitialized()) { |
| 54 | + const initialOptions = rcProvider.getOptions() as RemoteConfigOptions; |
| 55 | + if (deepEqual(initialOptions, options)) { |
| 56 | + return rcProvider.getImmediate(); |
| 57 | + } |
| 58 | + throw ERROR_FACTORY.create(ErrorCode.ALREADY_INITIALIZED); |
| 59 | + } |
| 60 | + rcProvider.initialize({ options }); |
| 61 | + const rc = rcProvider.getImmediate() as RemoteConfigImpl; |
| 62 | + |
| 63 | + if (options.initialFetchResponse) { |
| 64 | + // We use these initial writes as the initialization promise since they will hydrate the same |
| 65 | + // fields that `storageCache.loadFromStorage` would set. |
| 66 | + rc._initializePromise = Promise.all([ |
| 67 | + rc._storage.setLastSuccessfulFetchResponse(options.initialFetchResponse), |
| 68 | + rc._storage.setActiveConfigEtag(options.initialFetchResponse?.eTag || ''), |
| 69 | + rc._storageCache.setLastSuccessfulFetchTimestampMillis(Date.now()), |
| 70 | + rc._storageCache.setLastFetchStatus('success'), |
| 71 | + rc._storageCache.setActiveConfig( |
| 72 | + options.initialFetchResponse?.config || {} |
| 73 | + ) |
| 74 | + ]).then(); |
| 75 | + // The `storageCache` methods above set their in-memory fields synchronously, so it's |
| 76 | + // safe to declare our initialization complete at this point. |
| 77 | + rc._isInitializationComplete = true; |
| 78 | + } |
| 79 | + |
| 80 | + return rc; |
48 | 81 | }
|
49 | 82 |
|
50 | 83 | /**
|
|
0 commit comments