Skip to content

Commit d05dd23

Browse files
chemidyhiranya911
authored andcommitted
feat(fcm): Added support for specifying the analytics label for notifications. (#597)
* add analytics_label * update doc * nit fix * add validators * add test on fcmOptions
1 parent f7810f7 commit d05dd23

File tree

3 files changed

+159
-0
lines changed

3 files changed

+159
-0
lines changed

src/index.d.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3579,6 +3579,7 @@ type BaseMessage = {
35793579
android?: admin.messaging.AndroidConfig;
35803580
webpush?: admin.messaging.WebpushConfig;
35813581
apns?: admin.messaging.ApnsConfig;
3582+
fcmOptions?: admin.messaging.FcmOptions;
35823583
};
35833584

35843585
interface TokenMessage extends BaseMessage {
@@ -3641,6 +3642,11 @@ declare namespace admin.messaging {
36413642
* Android notification to be included in the message.
36423643
*/
36433644
notification?: AndroidNotification;
3645+
3646+
/**
3647+
* Options for features provided by the FCM SDK for Android.
3648+
*/
3649+
fcmOptions?: AndroidFcmOptions;
36443650
}
36453651

36463652
/**
@@ -3726,6 +3732,17 @@ declare namespace admin.messaging {
37263732
channelId?: string;
37273733
}
37283734

3735+
/**
3736+
* Represents options for features provided by the FCM SDK for Android.
3737+
*/
3738+
interface AndroidFcmOptions {
3739+
3740+
/**
3741+
* The label associated with the message's analytics data.
3742+
*/
3743+
analyticsLabel?: string;
3744+
}
3745+
37293746
/**
37303747
* Represents the APNs-specific options that can be included in an
37313748
* {@link admin.messaging.Message}. Refer to
@@ -3743,6 +3760,11 @@ declare namespace admin.messaging {
37433760
* An APNs payload to be included in the message.
37443761
*/
37453762
payload?: ApnsPayload;
3763+
3764+
/**
3765+
* Options for features provided by the FCM SDK for iOS.
3766+
*/
3767+
fcmOptions?: ApnsFcmOptions;
37463768
}
37473769
/**
37483770
* Represents the payload of an APNs message. Mainly consists of the `aps`
@@ -3841,6 +3863,28 @@ declare namespace admin.messaging {
38413863
volume?: number;
38423864
}
38433865

3866+
/**
3867+
* Represents options for features provided by the FCM SDK for iOS.
3868+
*/
3869+
interface ApnsFcmOptions {
3870+
3871+
/**
3872+
* The label associated with the message's analytics data.
3873+
*/
3874+
analyticsLabel?: string;
3875+
}
3876+
3877+
/**
3878+
* Represents platform-independent options for features provided by the FCM SDKs.
3879+
*/
3880+
interface FcmOptions {
3881+
3882+
/**
3883+
* The label associated with the message's analytics data.
3884+
*/
3885+
analyticsLabel?: string;
3886+
}
3887+
38443888

38453889
/**
38463890
* A notification that can be included in {@link admin.messaging.Message}.

src/messaging/messaging-types.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ interface BaseMessage {
2727
android?: AndroidConfig;
2828
webpush?: WebpushConfig;
2929
apns?: ApnsConfig;
30+
fcmOptions?: FcmOptions;
3031
}
3132

3233
interface TokenMessage extends BaseMessage {
@@ -60,6 +61,10 @@ export interface Notification {
6061
body?: string;
6162
}
6263

64+
export interface FcmOptions {
65+
analyticsLabel?: string;
66+
}
67+
6368
export interface WebpushConfig {
6469
headers?: {[key: string]: string};
6570
data?: {[key: string]: string};
@@ -97,6 +102,7 @@ export interface WebpushNotification {
97102
export interface ApnsConfig {
98103
headers?: {[key: string]: string};
99104
payload?: ApnsPayload;
105+
fcmOptions?: ApnsFcmOptions;
100106
}
101107

102108
export interface ApnsPayload {
@@ -135,13 +141,18 @@ export interface ApsAlert {
135141
launchImage?: string;
136142
}
137143

144+
export interface ApnsFcmOptions {
145+
analyticsLabel?: string;
146+
}
147+
138148
export interface AndroidConfig {
139149
collapseKey?: string;
140150
priority?: ('high' | 'normal');
141151
ttl?: number;
142152
restrictedPackageName?: string;
143153
data?: {[key: string]: string};
144154
notification?: AndroidNotification;
155+
fcmOptions?: AndroidFcmOptions;
145156
}
146157

147158
export interface AndroidNotification {
@@ -159,6 +170,10 @@ export interface AndroidNotification {
159170
channelId?: string;
160171
}
161172

173+
export interface AndroidFcmOptions {
174+
analyticsLabel?: string;
175+
}
176+
162177
/* Payload for data messages */
163178
export interface DataMessagePayload {
164179
[key: string]: string;
@@ -291,6 +306,7 @@ export function validateMessage(message: Message) {
291306
validateAndroidConfig(message.android);
292307
validateWebpushConfig(message.webpush);
293308
validateApnsConfig(message.apns);
309+
validateFcmOptions(message.fcmOptions);
294310
}
295311

296312
/**
@@ -345,8 +361,49 @@ function validateApnsConfig(config: ApnsConfig) {
345361
}
346362
validateStringMap(config.headers, 'apns.headers');
347363
validateApnsPayload(config.payload);
364+
validateApnsFcmOptions(config.fcmOptions);
348365
}
349366

367+
/**
368+
* Checks if the given ApnsFcmOptions object is valid.
369+
*
370+
* @param {ApnsFcmOptions} fcmOptions An object to be validated.
371+
*/
372+
function validateApnsFcmOptions(fcmOptions: ApnsFcmOptions) {
373+
if (typeof fcmOptions === 'undefined') {
374+
return;
375+
} else if (!validator.isNonNullObject(fcmOptions)) {
376+
throw new FirebaseMessagingError(
377+
MessagingClientErrorCode.INVALID_PAYLOAD, 'fcmOptions must be a non-null object');
378+
}
379+
380+
if (typeof fcmOptions.analyticsLabel !== 'undefined' && !validator.isString(fcmOptions.analyticsLabel)) {
381+
throw new FirebaseMessagingError(
382+
MessagingClientErrorCode.INVALID_PAYLOAD, 'analyticsLabel must be a string value');
383+
}
384+
}
385+
386+
/**
387+
* Checks if the given FcmOptions object is valid.
388+
*
389+
* @param {FcmOptions} fcmOptions An object to be validated.
390+
*/
391+
function validateFcmOptions(fcmOptions: FcmOptions) {
392+
if (typeof fcmOptions === 'undefined') {
393+
return;
394+
} else if (!validator.isNonNullObject(fcmOptions)) {
395+
throw new FirebaseMessagingError(
396+
MessagingClientErrorCode.INVALID_PAYLOAD, 'fcmOptions must be a non-null object');
397+
}
398+
399+
if (typeof fcmOptions.analyticsLabel !== 'undefined' && !validator.isString(fcmOptions.analyticsLabel)) {
400+
throw new FirebaseMessagingError(
401+
MessagingClientErrorCode.INVALID_PAYLOAD, 'analyticsLabel must be a string value');
402+
}
403+
}
404+
405+
406+
350407
/**
351408
* Checks if the given ApnsPayload object is valid. The object must have a valid aps value.
352409
*
@@ -535,6 +592,7 @@ function validateAndroidConfig(config: AndroidConfig) {
535592
}
536593
validateStringMap(config.data, 'android.data');
537594
validateAndroidNotification(config.notification);
595+
validateAndroidFcmOptions(config.fcmOptions);
538596

539597
const propertyMappings = {
540598
collapseKey: 'collapse_key',
@@ -585,3 +643,22 @@ function validateAndroidNotification(notification: AndroidNotification) {
585643
};
586644
renameProperties(notification, propertyMappings);
587645
}
646+
647+
/**
648+
* Checks if the given AndroidFcmOptions object is valid.
649+
*
650+
* @param {AndroidFcmOptions} fcmOptions An object to be validated.
651+
*/
652+
function validateAndroidFcmOptions(fcmOptions: AndroidFcmOptions) {
653+
if (typeof fcmOptions === 'undefined') {
654+
return;
655+
} else if (!validator.isNonNullObject(fcmOptions)) {
656+
throw new FirebaseMessagingError(
657+
MessagingClientErrorCode.INVALID_PAYLOAD, 'fcmOptions must be a non-null object');
658+
}
659+
660+
if (typeof fcmOptions.analyticsLabel !== 'undefined' && !validator.isString(fcmOptions.analyticsLabel)) {
661+
throw new FirebaseMessagingError(
662+
MessagingClientErrorCode.INVALID_PAYLOAD, 'analyticsLabel must be a string value');
663+
}
664+
}

test/unit/messaging/messaging.spec.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2469,6 +2469,24 @@ describe('Messaging', () => {
24692469
messaging.send({data: arg, topic: 'test'});
24702470
}).to.throw('data must be a non-null object');
24712471
});
2472+
2473+
it(`should throw given invalid fcmOptions: ${JSON.stringify(arg)}`, () => {
2474+
expect(() => {
2475+
messaging.send({fcmOptions: arg, topic: 'test'});
2476+
}).to.throw('fcmOptions must be a non-null object');
2477+
});
2478+
2479+
it(`should throw given invalid AndroidFcmOptions: ${JSON.stringify(arg)}`, () => {
2480+
expect(() => {
2481+
messaging.send({android: {fcmOptions: arg}, topic: 'test'});
2482+
}).to.throw('fcmOptions must be a non-null object');
2483+
});
2484+
2485+
it(`should throw given invalid ApnsFcmOptions: ${JSON.stringify(arg)}`, () => {
2486+
expect(() => {
2487+
messaging.send({apns: {fcmOptions: arg}, topic: 'test'});
2488+
}).to.throw('fcmOptions must be a non-null object');
2489+
});
24722490
});
24732491

24742492
const invalidDataMessages: any[] = [
@@ -2750,6 +2768,14 @@ describe('Messaging', () => {
27502768
},
27512769
},
27522770
},
2771+
{
2772+
label: 'Generic fcmOptions message',
2773+
req: {
2774+
fcmOptions: {
2775+
analyticsLabel: 'test.analytics',
2776+
},
2777+
},
2778+
},
27532779
{
27542780
label: 'Android data message',
27552781
req: {
@@ -2852,6 +2878,9 @@ describe('Messaging', () => {
28522878
bodyLocArgs: ['arg1', 'arg2'],
28532879
channelId: 'test.channel',
28542880
},
2881+
fcmOptions: {
2882+
analyticsLabel: 'test.analytics',
2883+
},
28552884
},
28562885
},
28572886
expectedReq: {
@@ -2878,6 +2907,9 @@ describe('Messaging', () => {
28782907
body_loc_args: ['arg1', 'arg2'],
28792908
channel_id: 'test.channel',
28802909
},
2910+
fcmOptions: {
2911+
analyticsLabel: 'test.analytics',
2912+
},
28812913
},
28822914
},
28832915
},
@@ -2999,6 +3031,9 @@ describe('Messaging', () => {
29993031
customKey1: 'custom.value',
30003032
customKey2: {nested: 'value'},
30013033
},
3034+
fcmOptions: {
3035+
analyticsLabel: 'test.analytics',
3036+
},
30023037
},
30033038
},
30043039
expectedReq: {
@@ -3032,6 +3067,9 @@ describe('Messaging', () => {
30323067
customKey1: 'custom.value',
30333068
customKey2: {nested: 'value'},
30343069
},
3070+
fcmOptions: {
3071+
analyticsLabel: 'test.analytics',
3072+
},
30353073
},
30363074
},
30373075
},

0 commit comments

Comments
 (0)