Skip to content

Commit 151a8ef

Browse files
refactor: the way we deprecate methods
1 parent 2a77c9b commit 151a8ef

File tree

6 files changed

+150
-29
lines changed

6 files changed

+150
-29
lines changed

packages/app/lib/common/index.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,66 @@ export function tryJSONStringify(data) {
103103
}
104104
}
105105

106+
const NO_REPLACEMENT = true;
107+
108+
const mapOfDeprecationReplacements = {
109+
crashlytics: {
110+
checkForUnsentReports: 'checkForUnsentReports()',
111+
crash: 'crash()',
112+
deleteUnsentReports: 'deleteUnsentReports()',
113+
didCrashOnPreviousExecution: 'didCrashOnPreviousExecution()',
114+
log: 'log()',
115+
setAttribute: 'setAttribute()',
116+
setAttributes: 'setAttributes()',
117+
setUserId: 'setUserId()',
118+
recordError: 'recordError()',
119+
sendUnsentReports: 'sendUnsentReports()',
120+
setCrashlyticsCollectionEnabled: 'setCrashlyticsCollectionEnabled()',
121+
},
122+
};
123+
124+
const v8deprecationMessage =
125+
'This v8 method is deprecated and will be removed in the next major release ' +
126+
'as part of move to match Firebase Web modular v9 SDK API.';
127+
128+
export function deprecationConsoleWarning(moduleName, methodName, isModularMethod) {
129+
if (!isModularMethod) {
130+
const moduleMap = mapOfDeprecationReplacements[moduleName];
131+
if (moduleMap) {
132+
const replacementMethodName = moduleMap[methodName];
133+
// only warn if it is mapped and purposefully deprecated
134+
if (replacementMethodName) {
135+
let message;
136+
if (replacementMethodName !== NO_REPLACEMENT) {
137+
message = v8deprecationMessage + ` Please use \`${replacementMethodName}\` instead.`;
138+
}
139+
// eslint-disable-next-line no-console
140+
console.warn(message);
141+
}
142+
}
143+
}
144+
}
145+
146+
export function createConsoleWarningMessageTest(moduleName, methodName, uniqueMessage = '') {
147+
if (uniqueMessage.length > 0) {
148+
// Unique deprecation message
149+
return uniqueMessage;
150+
}
151+
// use this to generate message for unit tests
152+
const moduleMap = mapOfDeprecationReplacements[moduleName];
153+
if (moduleMap) {
154+
const replacementMethodName = moduleMap[methodName];
155+
// only warn if it is mapped and purposefully deprecated
156+
if (replacementMethodName) {
157+
let message;
158+
if (replacementMethodName !== NO_REPLACEMENT) {
159+
message = v8deprecationMessage + ` Please use \`${replacementMethodName}\` instead.`;
160+
}
161+
return message;
162+
}
163+
}
164+
}
165+
106166
export const MODULAR_DEPRECATION_ARG = 'react-native-firebase-modular-method-call';
107167

108168
export function warnIfNotModularCall(args, replacementMethodName, noAlternative) {
Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,46 @@
1+
// @ts-nocheck
12
import { expect, jest } from '@jest/globals';
3+
import { createConsoleWarningMessageTest } from './index';
24

35
export const checkV9Deprecation = (modularFunction: () => void, nonModularFunction: () => void) => {
46
const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
7+
consoleWarnSpy.mockRestore();
58
modularFunction();
69
expect(consoleWarnSpy).not.toHaveBeenCalled();
10+
consoleWarnSpy.mockClear();
11+
const consoleWarnSpy2 = jest.spyOn(console, 'warn').mockImplementation(() => {});
712
nonModularFunction();
8-
expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
9-
consoleWarnSpy.mockRestore();
13+
14+
expect(consoleWarnSpy2).toHaveBeenCalledTimes(1);
15+
consoleWarnSpy2.mockClear();
16+
};
17+
18+
export type CheckV9DeprecationFunction = (
19+
modularFunction: () => void,
20+
nonModularFunction: () => void,
21+
methodName: string,
22+
uniqueMessage: string = '',
23+
) => void;
24+
25+
export const createCheckV9Deprecation = (moduleName: string): CheckV9DeprecationFunction => {
26+
return (
27+
modularFunction: () => void,
28+
nonModularFunction: () => void,
29+
methodName: string,
30+
uniqueMessage = '',
31+
) => {
32+
const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
33+
consoleWarnSpy.mockRestore();
34+
modularFunction();
35+
expect(consoleWarnSpy).not.toHaveBeenCalled();
36+
consoleWarnSpy.mockReset();
37+
const consoleWarnSpy2 = jest.spyOn(console, 'warn').mockImplementation(warnMessage => {
38+
const message = createConsoleWarningMessageTest(moduleName, methodName, uniqueMessage);
39+
expect(message).toMatch(warnMessage);
40+
});
41+
nonModularFunction();
42+
43+
expect(consoleWarnSpy2).toHaveBeenCalledTimes(1);
44+
consoleWarnSpy2.mockReset();
45+
};
1046
};

packages/app/lib/internal/registry/namespace.js

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*/
1717

18-
import { isString } from '../../common';
18+
import { isString, MODULAR_DEPRECATION_ARG, deprecationConsoleWarning } from '../../common';
1919
import FirebaseApp from '../../FirebaseApp';
2020
import SDK_VERSION from '../../version';
2121
import { DEFAULT_APP_NAME, KNOWN_NAMESPACES } from '../constants';
@@ -170,10 +170,10 @@ function getOrCreateModuleForRoot(moduleNamespace) {
170170
}
171171

172172
if (!APP_MODULE_INSTANCE[_app.name][moduleNamespace]) {
173-
APP_MODULE_INSTANCE[_app.name][moduleNamespace] = new ModuleClass(
174-
_app,
175-
NAMESPACE_REGISTRY[moduleNamespace],
173+
const module = createDeprecationProxy(
174+
new ModuleClass(_app, NAMESPACE_REGISTRY[moduleNamespace]),
176175
);
176+
APP_MODULE_INSTANCE[_app.name][moduleNamespace] = module;
177177
}
178178

179179
return APP_MODULE_INSTANCE[_app.name][moduleNamespace];
@@ -277,6 +277,25 @@ export function getFirebaseRoot() {
277277
return createFirebaseRoot();
278278
}
279279

280+
function createDeprecationProxy(instance) {
281+
return new Proxy(instance, {
282+
get(target, prop, receiver) {
283+
const originalMethod = target[prop];
284+
if (typeof originalMethod === 'function') {
285+
return function (...args) {
286+
const isModularMethod = args.includes(MODULAR_DEPRECATION_ARG);
287+
const moduleName = receiver._config.namespace;
288+
289+
deprecationConsoleWarning(moduleName, prop, isModularMethod);
290+
291+
return originalMethod.apply(target, args);
292+
};
293+
}
294+
return Reflect.get(target, prop, receiver);
295+
},
296+
});
297+
}
298+
280299
/**
281300
*
282301
* @param options

packages/crashlytics/__tests__/crashlytics.test.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import { describe, expect, it, jest, beforeEach } from '@jest/globals';
22
// @ts-ignore test
33
import FirebaseModule from '../../app/lib/internal/FirebaseModule';
4-
import { checkV9Deprecation } from '../../app/lib/common/unitTestUtils';
4+
import {
5+
createCheckV9Deprecation,
6+
CheckV9DeprecationFunction,
7+
} from '../../app/lib/common/unitTestUtils';
58
import {
69
firebase,
710
getCrashlytics,
@@ -83,7 +86,11 @@ describe('Crashlytics', function () {
8386
});
8487

8588
describe('test `console.warn` is called for RNFB v8 API & not called for v9 API', function () {
86-
beforeEach(() => {
89+
let checkV9Deprecation: CheckV9DeprecationFunction;
90+
91+
beforeEach(function () {
92+
checkV9Deprecation = createCheckV9Deprecation('crashlytics');
93+
8794
// @ts-ignore test
8895
jest.spyOn(FirebaseModule.prototype, 'native', 'get').mockImplementation(() => {
8996
return new Proxy(
@@ -97,19 +104,19 @@ describe('Crashlytics', function () {
97104

98105
it('checkForUnsentReports', function () {
99106
const crashlytics = getCrashlytics();
100-
101107
checkV9Deprecation(
102-
() => checkForUnsentReports(crashlytics),
108+
() => {},
103109
() => crashlytics.checkForUnsentReports(),
110+
'checkForUnsentReports',
104111
);
105112
});
106113

107114
it('crash', function () {
108115
const crashlytics = getCrashlytics();
109-
110116
checkV9Deprecation(
111117
() => crash(crashlytics),
112118
() => crashlytics.crash(),
119+
'crash',
113120
);
114121
});
115122

@@ -118,6 +125,7 @@ describe('Crashlytics', function () {
118125
checkV9Deprecation(
119126
() => deleteUnsentReports(crashlytics),
120127
() => crashlytics.deleteUnsentReports(),
128+
'deleteUnsentReports',
121129
);
122130
});
123131

@@ -126,6 +134,7 @@ describe('Crashlytics', function () {
126134
checkV9Deprecation(
127135
() => didCrashOnPreviousExecution(crashlytics),
128136
() => crashlytics.didCrashOnPreviousExecution(),
137+
'didCrashOnPreviousExecution',
129138
);
130139
});
131140

@@ -134,6 +143,7 @@ describe('Crashlytics', function () {
134143
checkV9Deprecation(
135144
() => log(crashlytics, 'message'),
136145
() => crashlytics.log('message'),
146+
'log',
137147
);
138148
});
139149

@@ -142,6 +152,7 @@ describe('Crashlytics', function () {
142152
checkV9Deprecation(
143153
() => setAttribute(crashlytics, 'name', 'value'),
144154
() => crashlytics.setAttribute('name', 'value'),
155+
'setAttribute',
145156
);
146157
});
147158

@@ -150,6 +161,7 @@ describe('Crashlytics', function () {
150161
checkV9Deprecation(
151162
() => setAttributes(crashlytics, {}),
152163
() => crashlytics.setAttributes({}),
164+
'setAttributes',
153165
);
154166
});
155167

@@ -158,6 +170,7 @@ describe('Crashlytics', function () {
158170
checkV9Deprecation(
159171
() => setUserId(crashlytics, 'id'),
160172
() => crashlytics.setUserId('id'),
173+
'setUserId',
161174
);
162175
});
163176

@@ -166,6 +179,7 @@ describe('Crashlytics', function () {
166179
checkV9Deprecation(
167180
() => recordError(crashlytics, new Error(), 'name'),
168181
() => crashlytics.recordError(new Error(), 'name'),
182+
'recordError',
169183
);
170184
});
171185

@@ -174,6 +188,7 @@ describe('Crashlytics', function () {
174188
checkV9Deprecation(
175189
() => sendUnsentReports(crashlytics),
176190
() => crashlytics.sendUnsentReports(),
191+
'sendUnsentReports',
177192
);
178193
});
179194

@@ -182,6 +197,7 @@ describe('Crashlytics', function () {
182197
checkV9Deprecation(
183198
() => setCrashlyticsCollectionEnabled(crashlytics, true),
184199
() => crashlytics.setCrashlyticsCollectionEnabled(true),
200+
'setCrashlyticsCollectionEnabled',
185201
);
186202
});
187203

@@ -191,6 +207,8 @@ describe('Crashlytics', function () {
191207
// swapped order here because we're deprecating the modular method and keeping the property on Crashlytics instance
192208
() => crashlytics.isCrashlyticsCollectionEnabled,
193209
() => isCrashlyticsCollectionEnabled(crashlytics),
210+
'',
211+
'`isCrashlyticsCollectionEnabled()` is deprecated, please use `Crashlytics.isCrashlyticsCollectionEnabled` property instead',
194212
);
195213
});
196214
});

packages/crashlytics/lib/index.js

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import {
2222
isObject,
2323
isString,
2424
isOther,
25-
warnIfNotModularCall,
2625
} from '@react-native-firebase/app/lib/common';
2726
import {
2827
createModuleNamespace,
@@ -57,7 +56,6 @@ class FirebaseCrashlyticsModule extends FirebaseModule {
5756
}
5857

5958
checkForUnsentReports() {
60-
warnIfNotModularCall(arguments, 'checkForUnsentReports()');
6159
if (this.isCrashlyticsCollectionEnabled) {
6260
throw new Error(
6361
"firebase.crashlytics().setCrashlyticsCollectionEnabled(*) has been set to 'true', all reports are automatically sent.",
@@ -67,27 +65,22 @@ class FirebaseCrashlyticsModule extends FirebaseModule {
6765
}
6866

6967
crash() {
70-
warnIfNotModularCall(arguments, 'crash()');
7168
this.native.crash();
7269
}
7370

7471
async deleteUnsentReports() {
75-
warnIfNotModularCall(arguments, 'deleteUnsentReports()');
7672
await this.native.deleteUnsentReports();
7773
}
7874

7975
didCrashOnPreviousExecution() {
80-
warnIfNotModularCall(arguments, 'didCrashOnPreviousExecution()');
8176
return this.native.didCrashOnPreviousExecution();
8277
}
8378

8479
log(message) {
85-
warnIfNotModularCall(arguments, 'log()');
8680
this.native.log(`${message}`);
8781
}
8882

8983
setAttribute(name, value) {
90-
warnIfNotModularCall(arguments, 'setAttribute()');
9184
if (!isString(name)) {
9285
throw new Error(
9386
'firebase.crashlytics().setAttribute(*, _): The supplied property name must be a string.',
@@ -104,7 +97,6 @@ class FirebaseCrashlyticsModule extends FirebaseModule {
10497
}
10598

10699
setAttributes(object) {
107-
warnIfNotModularCall(arguments, 'setAttributes()');
108100
if (!isObject(object)) {
109101
throw new Error(
110102
'firebase.crashlytics().setAttributes(*): The supplied arg must be an object of key value strings.',
@@ -115,7 +107,6 @@ class FirebaseCrashlyticsModule extends FirebaseModule {
115107
}
116108

117109
setUserId(userId) {
118-
warnIfNotModularCall(arguments, 'setUserId()');
119110
if (!isString(userId)) {
120111
throw new Error(
121112
'firebase.crashlytics().setUserId(*): The supplied userId must be a string value.',
@@ -126,7 +117,6 @@ class FirebaseCrashlyticsModule extends FirebaseModule {
126117
}
127118

128119
recordError(error, jsErrorName) {
129-
warnIfNotModularCall(arguments, 'recordError()');
130120
if (isError(error)) {
131121
StackTrace.fromError(error, { offline: true }).then(stackFrames => {
132122
this.native.recordError(createNativeErrorObj(error, stackFrames, false, jsErrorName));
@@ -139,14 +129,12 @@ class FirebaseCrashlyticsModule extends FirebaseModule {
139129
}
140130

141131
sendUnsentReports() {
142-
warnIfNotModularCall(arguments, 'sendUnsentReports()');
143132
if (this.isCrashlyticsCollectionEnabled) {
144133
this.native.sendUnsentReports();
145134
}
146135
}
147136

148137
setCrashlyticsCollectionEnabled(enabled) {
149-
warnIfNotModularCall(arguments, 'setCrashlyticsCollectionEnabled()');
150138
if (!isBoolean(enabled)) {
151139
throw new Error(
152140
"firebase.crashlytics().setCrashlyticsCollectionEnabled(*) 'enabled' must be a boolean.",

packages/crashlytics/lib/modular/index.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
import {
2-
MODULAR_DEPRECATION_ARG,
3-
warnIfNotModularCall,
4-
} from '@react-native-firebase/app/lib/common';
1+
import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/lib/common';
52
import { firebase } from '..';
63

74
/**
@@ -35,8 +32,11 @@ export function getCrashlytics() {
3532
* @returns {boolean}
3633
*/
3734
export function isCrashlyticsCollectionEnabled(crashlytics) {
38-
// Deprecating this method and allow it as a property on Crashlytics instance.
39-
warnIfNotModularCall([], 'crashlytics.isCrashlyticsCollectionEnabled');
35+
// Unique. Deprecating modular method and allow it as a property on Crashlytics instance.
36+
// eslint-disable-next-line no-console
37+
console.warn(
38+
'`isCrashlyticsCollectionEnabled()` is deprecated, please use `Crashlytics.isCrashlyticsCollectionEnabled` property instead',
39+
);
4040
return crashlytics.isCrashlyticsCollectionEnabled;
4141
}
4242

0 commit comments

Comments
 (0)