Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions src/index.d.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -3579,6 +3579,7 @@ type BaseMessage = {
android?: admin.messaging.AndroidConfig;
webpush?: admin.messaging.WebpushConfig;
apns?: admin.messaging.ApnsConfig;
fcmOptions?: admin.messaging.FcmOptions;
};

interface TokenMessage extends BaseMessage {
Expand DownExpand Up@@ -3641,6 +3642,11 @@ declare namespace admin.messaging {
* Android notification to be included in the message.
*/
notification?: AndroidNotification;

/**
* Options for features provided by the FCM SDK for Android.
*/
fcmOptions?: AndroidFcmOptions;
}

/**
Expand DownExpand Up@@ -3726,6 +3732,17 @@ declare namespace admin.messaging {
channelId?: string;
}

/**
* Represents options for features provided by the FCM SDK for Android.
*/
interface AndroidFcmOptions {

/**
* The label associated with the message's analytics data.
*/
analyticsLabel?: string;
}

/**
* Represents the APNs-specific options that can be included in an
* {@link admin.messaging.Message}. Refer to
Expand All@@ -3743,6 +3760,11 @@ declare namespace admin.messaging {
* An APNs payload to be included in the message.
*/
payload?: ApnsPayload;

/**
* Options for features provided by the FCM SDK for iOS.
*/
fcmOptions?: ApnsFcmOptions;
}
/**
* Represents the payload of an APNs message. Mainly consists of the `aps`
Expand DownExpand Up@@ -3841,6 +3863,28 @@ declare namespace admin.messaging {
volume?: number;
}

/**
* Represents options for features provided by the FCM SDK for iOS.
*/
interface ApnsFcmOptions {

/**
* The label associated with the message's analytics data.
*/
analyticsLabel?: string;
}

/**
* Represents platform-independent options for features provided by the FCM SDKs.
*/
interface FcmOptions {

/**
* The label associated with the message's analytics data.
*/
analyticsLabel?: string;
}


/**
* A notification that can be included in {@link admin.messaging.Message}.
Expand Down
77 changes: 77 additions & 0 deletions src/messaging/messaging-types.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,7 @@ interface BaseMessage {
android?: AndroidConfig;
webpush?: WebpushConfig;
apns?: ApnsConfig;
fcmOptions?: FcmOptions;
}

interface TokenMessage extends BaseMessage {
Expand DownExpand Up@@ -60,6 +61,10 @@ export interface Notification {
body?: string;
}

export interface FcmOptions {
Comment thread
chemidy marked this conversation as resolved.
analyticsLabel?: string;
}

export interface WebpushConfig {
headers?: {[key: string]: string};
data?: {[key: string]: string};
Expand DownExpand Up@@ -97,6 +102,7 @@ export interface WebpushNotification {
export interface ApnsConfig {
headers?: {[key: string]: string};
payload?: ApnsPayload;
fcmOptions?: ApnsFcmOptions;
}

export interface ApnsPayload {
Expand DownExpand Up@@ -135,13 +141,18 @@ export interface ApsAlert {
launchImage?: string;
}

export interface ApnsFcmOptions {
analyticsLabel?: string;
}

export interface AndroidConfig {
collapseKey?: string;
priority?: ('high' | 'normal');
ttl?: number;
restrictedPackageName?: string;
data?: {[key: string]: string};
notification?: AndroidNotification;
fcmOptions?: AndroidFcmOptions;
}

export interface AndroidNotification {
Expand All@@ -159,6 +170,10 @@ export interface AndroidNotification {
channelId?: string;
}

export interface AndroidFcmOptions {
analyticsLabel?: string;
}

/* Payload for data messages */
export interface DataMessagePayload {
[key: string]: string;
Expand DownExpand Up@@ -291,6 +306,7 @@ export function validateMessage(message: Message) {
validateAndroidConfig(message.android);
validateWebpushConfig(message.webpush);
validateApnsConfig(message.apns);
validateFcmOptions(message.fcmOptions);
}

/**
Expand DownExpand Up@@ -345,8 +361,49 @@ function validateApnsConfig(config: ApnsConfig) {
}
validateStringMap(config.headers, 'apns.headers');
validateApnsPayload(config.payload);
validateApnsFcmOptions(config.fcmOptions);
}

/**
* Checks if the given ApnsFcmOptions object is valid.
*
* @param {ApnsFcmOptions} fcmOptions An object to be validated.
*/
function validateApnsFcmOptions(fcmOptions: ApnsFcmOptions) {
if (typeof fcmOptions === 'undefined') {
return;
} else if (!validator.isNonNullObject(fcmOptions)) {
throw new FirebaseMessagingError(
MessagingClientErrorCode.INVALID_PAYLOAD, 'fcmOptions must be a non-null object');
}

if (typeof fcmOptions.analyticsLabel !== 'undefined' && !validator.isString(fcmOptions.analyticsLabel)) {
throw new FirebaseMessagingError(
MessagingClientErrorCode.INVALID_PAYLOAD, 'analyticsLabel must be a string value');
}
}

/**
* Checks if the given FcmOptions object is valid.
*
* @param {FcmOptions} fcmOptions An object to be validated.
*/
function validateFcmOptions(fcmOptions: FcmOptions) {
if (typeof fcmOptions === 'undefined') {
return;
} else if (!validator.isNonNullObject(fcmOptions)) {
throw new FirebaseMessagingError(
MessagingClientErrorCode.INVALID_PAYLOAD, 'fcmOptions must be a non-null object');
}

if (typeof fcmOptions.analyticsLabel !== 'undefined' && !validator.isString(fcmOptions.analyticsLabel)) {
throw new FirebaseMessagingError(
MessagingClientErrorCode.INVALID_PAYLOAD, 'analyticsLabel must be a string value');
}
}



/**
* Checks if the given ApnsPayload object is valid. The object must have a valid aps value.
*
Expand DownExpand Up@@ -535,6 +592,7 @@ function validateAndroidConfig(config: AndroidConfig) {
}
validateStringMap(config.data, 'android.data');
validateAndroidNotification(config.notification);
validateAndroidFcmOptions(config.fcmOptions);

const propertyMappings = {
collapseKey: 'collapse_key',
Expand DownExpand Up@@ -585,3 +643,22 @@ function validateAndroidNotification(notification: AndroidNotification) {
};
renameProperties(notification, propertyMappings);
}

/**
* Checks if the given AndroidFcmOptions object is valid.
*
* @param {AndroidFcmOptions} fcmOptions An object to be validated.
*/
function validateAndroidFcmOptions(fcmOptions: AndroidFcmOptions) {
if (typeof fcmOptions === 'undefined') {
return;
} else if (!validator.isNonNullObject(fcmOptions)) {
throw new FirebaseMessagingError(
MessagingClientErrorCode.INVALID_PAYLOAD, 'fcmOptions must be a non-null object');
}

if (typeof fcmOptions.analyticsLabel !== 'undefined' && !validator.isString(fcmOptions.analyticsLabel)) {
throw new FirebaseMessagingError(
MessagingClientErrorCode.INVALID_PAYLOAD, 'analyticsLabel must be a string value');
}
}
38 changes: 38 additions & 0 deletions test/unit/messaging/messaging.spec.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2469,6 +2469,24 @@ describe('Messaging', () => {
messaging.send({data: arg, topic: 'test'});
}).to.throw('data must be a non-null object');
});

it(`should throw given invalid fcmOptions: ${JSON.stringify(arg)}`, () => {
expect(() => {
messaging.send({fcmOptions: arg, topic: 'test'});
}).to.throw('fcmOptions must be a non-null object');
});

it(`should throw given invalid AndroidFcmOptions: ${JSON.stringify(arg)}`, () => {
expect(() => {
messaging.send({android: {fcmOptions: arg}, topic: 'test'});
}).to.throw('fcmOptions must be a non-null object');
});

it(`should throw given invalid ApnsFcmOptions: ${JSON.stringify(arg)}`, () => {
expect(() => {
messaging.send({apns: {fcmOptions: arg}, topic: 'test'});
}).to.throw('fcmOptions must be a non-null object');
});
});

const invalidDataMessages: any[] = [
Expand DownExpand Up@@ -2750,6 +2768,14 @@ describe('Messaging', () => {
},
},
},
{
label: 'Generic fcmOptions message',
req: {
fcmOptions: {
analyticsLabel: 'test.analytics',
Comment thread
chong-shao marked this conversation as resolved.
},
},
},
{
label: 'Android data message',
req: {
Expand DownExpand Up@@ -2852,6 +2878,9 @@ describe('Messaging', () => {
bodyLocArgs: ['arg1', 'arg2'],
channelId: 'test.channel',
},
fcmOptions: {
analyticsLabel: 'test.analytics',
Comment thread
chemidy marked this conversation as resolved.
},
},
},
expectedReq: {
Expand All@@ -2878,6 +2907,9 @@ describe('Messaging', () => {
body_loc_args: ['arg1', 'arg2'],
channel_id: 'test.channel',
},
fcmOptions: {
analyticsLabel: 'test.analytics',
},
},
},
},
Expand DownExpand Up@@ -2999,6 +3031,9 @@ describe('Messaging', () => {
customKey1: 'custom.value',
customKey2: {nested: 'value'},
},
fcmOptions: {
analyticsLabel: 'test.analytics',
},
},
},
expectedReq: {
Expand DownExpand Up@@ -3032,6 +3067,9 @@ describe('Messaging', () => {
customKey1: 'custom.value',
customKey2: {nested: 'value'},
},
fcmOptions: {
analyticsLabel: 'test.analytics',
},
},
},
},
Expand Down