diff --git a/reactfire/firebaseApp/sdk.tsx b/reactfire/firebaseApp/sdk.tsx index 83381840..eb119b7b 100644 --- a/reactfire/firebaseApp/sdk.tsx +++ b/reactfire/firebaseApp/sdk.tsx @@ -1,5 +1,25 @@ import { useFirebaseApp, preloadRequest, usePreloadedRequest } from '..'; +type RemoteConfig = import('firebase/app').remoteConfig.RemoteConfig; +type Storage = import('firebase/app').storage.Storage; +type Firestore = import('firebase/app').firestore.Firestore; +type Performance = import('firebase/app').performance.Performance; +type Messaging = import('firebase/app').messaging.Messaging; +type Functions = import('firebase/app').functions.Functions; +type Database = import('firebase/app').database.Database; +type Auth = import('firebase/app').auth.Auth; + +type FirebaseSDK = + | (() => firebase.analytics.Analytics) + | (() => firebase.auth.Auth) + | ((url?: string) => firebase.database.Database) + | (() => firebase.firestore.Firestore) + | ((region?: string) => firebase.functions.Functions) + | (() => firebase.messaging.Messaging) + | (() => firebase.performance.Performance) + | (() => firebase.remoteConfig.RemoteConfig) + | ((url?: string) => firebase.storage.Storage); + enum SDK { ANALYTICS = 'analytics', AUTH = 'auth', @@ -12,14 +32,21 @@ enum SDK { STORAGE = 'storage' } -function fetchSDK(sdk: SDK, firebaseApp: firebase.app.App) { +function fetchSDK( + sdk: SDK, + firebaseApp: firebase.app.App, + settingsCallback: (sdk: FirebaseSDK) => Promise | void = () => + Promise.resolve() +) { if (!firebaseApp) { throw new Error('Firebase app was not provided'); } - let sdkPromise; + let sdkPromise: Promise; if (firebaseApp[sdk]) { + // Don't apply settings here. Only needed for lazy loaded SDKs. + // If not lazy loaded, user can provide settings as normal sdkPromise = Promise.resolve(firebaseApp[sdk]); } else { switch (sdk) { @@ -67,8 +94,12 @@ function fetchSDK(sdk: SDK, firebaseApp: firebase.app.App) { ); break; } - sdkPromise = sdkPromise.then(() => firebaseApp[sdk]); + sdkPromise = sdkPromise + .then(() => settingsCallback(firebaseApp[sdk])) + .then(() => firebaseApp[sdk]); } + preloadRequest(() => sdkPromise, `firebase-sdk-${sdk}`); + return sdkPromise; } @@ -84,8 +115,11 @@ function useSDK(sdk: SDK, firebaseApp?: firebase.app.App) { return usePreloadedRequest(result); } -export function preloadAuth(firebaseApp: firebase.app.App) { - return fetchSDK(SDK.AUTH, firebaseApp); +export function preloadAuth( + firebaseApp: firebase.app.App, + settingsCallback?: (auth: () => Auth) => void +) { + return fetchSDK(SDK.AUTH, firebaseApp, settingsCallback); } export function useAuth(firebaseApp?: firebase.app.App) { @@ -100,56 +134,77 @@ export function useAnalytics(firebaseApp?: firebase.app.App) { return useSDK(SDK.ANALYTICS, firebaseApp); } -export function preloadDatabase(firebaseApp: firebase.app.App) { - return fetchSDK(SDK.DATABASE, firebaseApp); +export function preloadDatabase( + firebaseApp: firebase.app.App, + settingsCallback?: (database: () => Database) => void +) { + return fetchSDK(SDK.DATABASE, firebaseApp, settingsCallback); } export function useDatabase(firebaseApp?: firebase.app.App) { return useSDK(SDK.DATABASE, firebaseApp); } -export function preloadFirestore(firebaseApp: firebase.app.App) { - return fetchSDK(SDK.FIRESTORE, firebaseApp); +export function preloadFirestore( + firebaseApp: firebase.app.App, + settingsCallback?: (firestore: () => Firestore) => Promise +) { + return fetchSDK(SDK.FIRESTORE, firebaseApp, settingsCallback); } export function useFirestore(firebaseApp?: firebase.app.App) { return useSDK(SDK.FIRESTORE, firebaseApp); } -export function preloadFunctions(firebaseApp: firebase.app.App) { - return fetchSDK(SDK.FUNCTIONS, firebaseApp); +export function preloadFunctions( + firebaseApp?: firebase.app.App, + settingsCallback?: (functions: () => Functions) => void +) { + return fetchSDK(SDK.FUNCTIONS, firebaseApp, settingsCallback); } export function useFunctions(firebaseApp?: firebase.app.App) { return useSDK(SDK.FUNCTIONS, firebaseApp); } -export function preloadMessaging(firebaseApp: firebase.app.App) { - return fetchSDK(SDK.MESSAGING, firebaseApp); +export function preloadMessaging( + firebaseApp: firebase.app.App, + settingsCallback?: (messaging: () => Messaging) => void +) { + return fetchSDK(SDK.MESSAGING, firebaseApp, settingsCallback); } export function useMessaging(firebaseApp?: firebase.app.App) { return useSDK(SDK.MESSAGING, firebaseApp); } -export function preloadPerformance(firebaseApp: firebase.app.App) { - return fetchSDK(SDK.PERFORMANCE, firebaseApp); +export function preloadPerformance( + firebaseApp: firebase.app.App, + settingsCallback?: (performance: () => Performance) => void +) { + return fetchSDK(SDK.PERFORMANCE, firebaseApp, settingsCallback); } export function usePerformance(firebaseApp?: firebase.app.App) { return useSDK(SDK.PERFORMANCE, firebaseApp); } -export function preloadRemoteConfig(firebaseApp: firebase.app.App) { - return fetchSDK(SDK.REMOTE_CONFIG, firebaseApp); +export function preloadRemoteConfig( + firebaseApp: firebase.app.App, + settingsCallback?: (remoteConfig: () => RemoteConfig) => Promise +) { + return fetchSDK(SDK.REMOTE_CONFIG, firebaseApp, settingsCallback); } export function useRemoteConfig(firebaseApp?: firebase.app.App) { return useSDK(SDK.REMOTE_CONFIG, firebaseApp); } -export function preloadStorage(firebaseApp: firebase.app.App) { - return fetchSDK(SDK.STORAGE, firebaseApp); +export function preloadStorage( + firebaseApp: firebase.app.App, + settingsCallback: (storage: () => Storage) => Promise +) { + return fetchSDK(SDK.STORAGE, firebaseApp, settingsCallback); } export function useStorage(firebaseApp?: firebase.app.App) { diff --git a/sample/src/App.js b/sample/src/App.js index 359d73d0..69e8a634 100644 --- a/sample/src/App.js +++ b/sample/src/App.js @@ -38,11 +38,21 @@ const Card = ({ title, children }) => { // fetching them now const preloadSDKs = firebaseApp => { return Promise.all([ - preloadFirestore(firebaseApp), + preloadFirestore(firebaseApp, firestore => { + return firestore().enablePersistence(); + }), preloadDatabase(firebaseApp), - preloadStorage(firebaseApp), + preloadStorage(firebaseApp, storage => { + storage().setMaxUploadRetryTime(10000); + }), preloadAuth(firebaseApp), - preloadRemoteConfig(firebaseApp) + preloadRemoteConfig(firebaseApp, remoteConfig => { + remoteConfig().settings = { + minimumFetchIntervalMillis: 10000, + fetchTimeoutMillis: 10000 + }; + return remoteConfig().fetchAndActivate(); + }) ]); };