@@ -108,50 +108,135 @@ const NO_REPLACEMENT = true;
108108
109109const mapOfDeprecationReplacements = {
110110 crashlytics : {
111- checkForUnsentReports : 'checkForUnsentReports()' ,
112- crash : 'crash()' ,
113- deleteUnsentReports : 'deleteUnsentReports()' ,
114- didCrashOnPreviousExecution : 'didCrashOnPreviousExecution()' ,
115- log : 'log()' ,
116- setAttribute : 'setAttribute()' ,
117- setAttributes : 'setAttributes()' ,
118- setUserId : 'setUserId()' ,
119- recordError : 'recordError()' ,
120- sendUnsentReports : 'sendUnsentReports()' ,
121- setCrashlyticsCollectionEnabled : 'setCrashlyticsCollectionEnabled()' ,
111+ default : {
112+ checkForUnsentReports : 'checkForUnsentReports()' ,
113+ crash : 'crash()' ,
114+ deleteUnsentReports : 'deleteUnsentReports()' ,
115+ didCrashOnPreviousExecution : 'didCrashOnPreviousExecution()' ,
116+ log : 'log()' ,
117+ setAttribute : 'setAttribute()' ,
118+ setAttributes : 'setAttributes()' ,
119+ setUserId : 'setUserId()' ,
120+ recordError : 'recordError()' ,
121+ sendUnsentReports : 'sendUnsentReports()' ,
122+ setCrashlyticsCollectionEnabled : 'setCrashlyticsCollectionEnabled()' ,
123+ } ,
124+ } ,
125+ firestore : {
126+ default : {
127+ batch : 'writeBatch()' ,
128+ loadBundle : 'loadBundle()' ,
129+ namedQuery : 'namedQuery()' ,
130+ clearPersistence : 'clearIndexedDbPersistence()' ,
131+ waitForPendingWrites : 'waitForPendingWrites()' ,
132+ terminate : 'terminate()' ,
133+ useEmulator : 'connectFirestoreEmulator()' ,
134+ collection : 'collection()' ,
135+ collectionGroup : 'collectionGroup()' ,
136+ disableNetwork : 'disableNetwork()' ,
137+ doc : 'doc()' ,
138+ enableNetwork : 'enableNetwork()' ,
139+ runTransaction : 'runTransaction()' ,
140+ settings : 'settings()' ,
141+ persistentCacheIndexManager : 'getPersistentCacheIndexManager()' ,
142+ } ,
143+ statics : {
144+ setLogLevel : 'setLogLevel()' ,
145+ Filter : 'where()' ,
146+ FieldValue : 'FieldValue' ,
147+ Timestamp : 'Timestamp' ,
148+ GeoPoint : 'GeoPoint' ,
149+ Blob : 'Bytes' ,
150+ FieldPath : 'FieldPath' ,
151+ } ,
152+ FirestoreCollectionReference : {
153+ count : 'getCountFromServer()' ,
154+ countFromServer : 'getCountFromServer()' ,
155+ endAt : 'endAt()' ,
156+ endBefore : 'endBefore()' ,
157+ get : 'getDocs()' ,
158+ isEqual : NO_REPLACEMENT ,
159+ limit : 'limit()' ,
160+ limitToLast : 'limitToLast()' ,
161+ onSnapshot : 'onSnapshot()' ,
162+ orderBy : 'orderBy()' ,
163+ startAfter : 'startAfter()' ,
164+ startAt : 'startAt()' ,
165+ where : 'where()' ,
166+ add : 'addDoc()' ,
167+ doc : 'doc()' ,
168+ } ,
169+ FirestoreDocumentReference : {
170+ collection : 'collection()' ,
171+ delete : 'deleteDoc()' ,
172+ get : 'getDoc()' ,
173+ isEqual : NO_REPLACEMENT ,
174+ onSnapshot : 'onSnapshot()' ,
175+ set : 'setDoc()' ,
176+ update : 'updateDoc()' ,
177+ } ,
178+ FirestoreDocumentSnapshot : {
179+ isEqual : NO_REPLACEMENT ,
180+ } ,
181+ FirestoreFieldValue : {
182+ arrayRemove : 'arrayRemove()' ,
183+ arrayUnion : 'arrayUnion()' ,
184+ delete : 'deleteField()' ,
185+ increment : 'increment()' ,
186+ serverTimestamp : 'serverTimestamp()' ,
187+ } ,
188+ Filter : {
189+ or : 'or()' ,
190+ and : 'and()' ,
191+ } ,
192+ FirestorePersistentCacheIndexManager : {
193+ enableIndexAutoCreation : 'enablePersistentCacheIndexAutoCreation()' ,
194+ disableIndexAutoCreation : 'disablePersistentCacheIndexAutoCreation()' ,
195+ deleteAllIndexes : 'deleteAllPersistentCacheIndexes()' ,
196+ } ,
197+ FirestoreTimestamp : {
198+ seconds : NO_REPLACEMENT ,
199+ nanoseconds : NO_REPLACEMENT ,
200+ } ,
122201 } ,
123202} ;
124203
125204const v8deprecationMessage =
126205 'This v8 method is deprecated and will be removed in the next major release ' +
127206 'as part of move to match Firebase Web modular v9 SDK API.' ;
128207
129- export function deprecationConsoleWarning ( moduleName , methodName , isModularMethod ) {
208+ export function deprecationConsoleWarning ( nameSpace , methodName , instanceName , isModularMethod ) {
130209 if ( ! isModularMethod ) {
131- const moduleMap = mapOfDeprecationReplacements [ moduleName ] ;
210+ const moduleMap = mapOfDeprecationReplacements [ nameSpace ] ;
132211 if ( moduleMap ) {
133- const replacementMethodName = moduleMap [ methodName ] ;
134- // only warn if it is mapped and purposefully deprecated
135- if ( replacementMethodName ) {
136- const message = createMessage ( moduleName , methodName ) ;
137-
212+ const instanceMap = moduleMap [ instanceName ] ;
213+ const deprecatedMethod = instanceMap [ methodName ] ;
214+ if ( instanceMap && deprecatedMethod ) {
215+ const message = createMessage ( nameSpace , methodName , instanceName ) ;
138216 // eslint-disable-next-line no-console
139217 console . warn ( message ) ;
140218 }
141219 }
142220 }
143221}
144222
145- export function createMessage ( moduleName , methodName , uniqueMessage = '' ) {
146- if ( uniqueMessage . length > 0 ) {
223+ export function createMessage (
224+ nameSpace ,
225+ methodName ,
226+ instanceName = 'default' ,
227+ uniqueMessage = null ,
228+ ) {
229+ if ( uniqueMessage ) {
147230 // Unique deprecation message used for testing
148231 return uniqueMessage ;
149232 }
150233
151- const moduleMap = mapOfDeprecationReplacements [ moduleName ] ;
234+ const moduleMap = mapOfDeprecationReplacements [ nameSpace ] ;
152235 if ( moduleMap ) {
153- const replacementMethodName = moduleMap [ methodName ] ;
154- if ( replacementMethodName ) {
236+ const instance = moduleMap [ instanceName ] ;
237+ if ( instance ) {
238+ const replacementMethodName = instance [ methodName ] ;
239+
155240 if ( replacementMethodName !== NO_REPLACEMENT ) {
156241 return v8deprecationMessage + ` Please use \`${ replacementMethodName } \` instead.` ;
157242 } else {
@@ -161,9 +246,98 @@ export function createMessage(moduleName, methodName, uniqueMessage = '') {
161246 }
162247}
163248
249+ function getNamespace ( target ) {
250+ if ( target . GeoPoint ) {
251+ // target is statics object. GeoPoint is a static class on Firestore
252+ return 'firestore' ;
253+ }
254+ if ( target . _config && target . _config . namespace ) {
255+ return target . _config . namespace ;
256+ }
257+ const className = target . name ? target . name : target . constructor . name ;
258+ return Object . keys ( mapOfDeprecationReplacements ) . find ( key => {
259+ if ( mapOfDeprecationReplacements [ key ] [ className ] ) {
260+ return key ;
261+ }
262+ } ) ;
263+ }
264+
265+ function getInstanceName ( target ) {
266+ if ( target . GeoPoint ) {
267+ // target is statics object. GeoPoint is a static class on Firestore
268+ return 'statics' ;
269+ }
270+ if ( target . _config ) {
271+ // module class instance, we use default to store map of deprecated methods
272+ return 'default' ;
273+ }
274+ if ( target . name ) {
275+ // It's a function which has a name property unlike classes
276+ return target . name ;
277+ }
278+ // It's a class instance
279+ return target . constructor . name ;
280+ }
281+
282+ export function createDeprecationProxy ( instance ) {
283+ return new Proxy ( instance , {
284+ construct ( target , args ) {
285+ // needed for Timestamp which we pass as static, when we construct new instance, we need to wrap it in proxy again.
286+ return createDeprecationProxy ( new target ( ...args ) ) ;
287+ } ,
288+ get ( target , prop , receiver ) {
289+ const originalMethod = target [ prop ] ;
290+
291+ if ( prop === 'constructor' ) {
292+ return Reflect . get ( target , prop , receiver ) ;
293+ }
294+
295+ if ( target && target . constructor && target . constructor . name === 'FirestoreTimestamp' ) {
296+ deprecationConsoleWarning ( 'firestore' , prop , 'FirestoreTimestamp' , false ) ;
297+ return Reflect . get ( target , prop , receiver ) ;
298+ }
299+
300+ if ( target && target . name === 'firebaseModuleWithApp' ) {
301+ // statics
302+ if (
303+ prop === 'Filter' ||
304+ prop === 'FieldValue' ||
305+ prop === 'Timestamp' ||
306+ prop === 'GeoPoint' ||
307+ prop === 'Blob' ||
308+ prop === 'FieldPath'
309+ ) {
310+ deprecationConsoleWarning ( 'firestore' , prop , 'statics' , false ) ;
311+ }
312+ if ( prop !== 'setLogLevel' ) {
313+ // we want to capture setLogLevel function call which we do below
314+ return Reflect . get ( target , prop , receiver ) ;
315+ }
316+ }
317+
318+ if ( typeof originalMethod === 'function' ) {
319+ return function ( ...args ) {
320+ const isModularMethod = args . includes ( MODULAR_DEPRECATION_ARG ) ;
321+ const instanceName = getInstanceName ( target ) ;
322+ const nameSpace = getNamespace ( target ) ;
323+
324+ deprecationConsoleWarning ( nameSpace , prop , instanceName , isModularMethod ) ;
325+
326+ return originalMethod . apply ( target , filterModularArgument ( args ) ) ;
327+ } ;
328+ }
329+ return Reflect . get ( target , prop , receiver ) ;
330+ } ,
331+ } ) ;
332+ }
333+
164334export const MODULAR_DEPRECATION_ARG = 'react-native-firebase-modular-method-call' ;
165335
166- export function warnIfNotModularCall ( args , replacementMethodName , noAlternative ) {
336+ export function filterModularArgument ( list ) {
337+ return list . filter ( arg => arg !== MODULAR_DEPRECATION_ARG ) ;
338+ }
339+
340+ export function warnIfNotModularCall ( args , replacementMethodName = '' ) {
167341 for ( let i = 0 ; i < args . length ; i ++ ) {
168342 if ( args [ i ] === MODULAR_DEPRECATION_ARG ) {
169343 return ;
@@ -173,7 +347,7 @@ export function warnIfNotModularCall(args, replacementMethodName, noAlternative)
173347 'This v8 method is deprecated and will be removed in the next major release ' +
174348 'as part of move to match Firebase Web modular v9 SDK API.' ;
175349
176- if ( ! noAlternative ) {
350+ if ( replacementMethodName . length > 0 ) {
177351 message += ` Please use \`${ replacementMethodName } \` instead.` ;
178352 }
179353
0 commit comments