Skip to content

Commit 4d27e90

Browse files
authored
Supporting APNS mutable-content option (#236)
* Supporting APNS mutable-content option * Renamed customFields to customData; Updated CHANGELOG
1 parent b1f3d03 commit 4d27e90

File tree

4 files changed

+102
-3
lines changed

4 files changed

+102
-3
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Unreleased
22

3-
-
3+
- [added] Added the `mutableContent` optional field to the `Aps` type of
4+
the FCM API.
5+
- [added] Added the support for specifying arbitrary custom key-value
6+
fields in the `Aps` type.
47

58
# v5.11.0
69

src/index.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,8 +405,10 @@ declare namespace admin.messaging {
405405
badge?: number;
406406
sound?: string;
407407
contentAvailable?: boolean;
408+
mutableContent?: boolean;
408409
category?: string;
409410
threadId?: string;
411+
[customData: string]: any;
410412
};
411413

412414
type ApsAlert = {

src/messaging/messaging.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ export interface Aps {
152152
contentAvailable?: boolean;
153153
category?: string;
154154
threadId?: string;
155+
mutableContent?: boolean;
156+
[customData: string]: any;
155157
}
156158

157159
export interface ApsAlert {
@@ -274,17 +276,34 @@ function validateAps(aps: Aps) {
274276

275277
const propertyMappings = {
276278
contentAvailable: 'content-available',
279+
mutableContent: 'mutable-content',
277280
threadId: 'thread-id',
278281
};
282+
Object.keys(propertyMappings).forEach((key) => {
283+
if (key in aps && propertyMappings[key] in aps) {
284+
throw new FirebaseMessagingError(
285+
MessagingClientErrorCode.INVALID_PAYLOAD, `Multiple specifications for ${key} in Aps`);
286+
}
287+
});
279288
renameProperties(aps, propertyMappings);
280289

281-
if (typeof aps['content-available'] !== 'undefined') {
282-
if (aps['content-available'] === true) {
290+
const contentAvailable = aps['content-available'];
291+
if (typeof contentAvailable !== 'undefined' && contentAvailable !== 1) {
292+
if (contentAvailable === true) {
283293
aps['content-available'] = 1;
284294
} else {
285295
delete aps['content-available'];
286296
}
287297
}
298+
299+
const mutableContent = aps['mutable-content'];
300+
if (typeof mutableContent !== 'undefined' && mutableContent !== 1) {
301+
if (mutableContent === true) {
302+
aps['mutable-content'] = 1;
303+
} else {
304+
delete aps['mutable-content'];
305+
}
306+
}
288307
}
289308

290309
/**

test/unit/messaging/messaging.spec.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1847,6 +1847,18 @@ describe('Messaging', () => {
18471847
}).to.throw('apns.payload.aps must be a non-null object');
18481848
});
18491849
});
1850+
it(`should throw given APNS payload with duplicate fields`, () => {
1851+
expect(() => {
1852+
messaging.send({
1853+
apns: {
1854+
payload: {
1855+
aps: {'mutableContent': true, 'mutable-content': 1},
1856+
},
1857+
},
1858+
token: 'token',
1859+
});
1860+
}).to.throw('Multiple specifications for mutableContent in Aps');
1861+
});
18501862

18511863
const invalidApnsAlerts: any = [null, [], true, 1.23];
18521864
invalidApnsAlerts.forEach((alert) => {
@@ -2272,6 +2284,7 @@ describe('Messaging', () => {
22722284
sound: 'test.sound',
22732285
category: 'test.category',
22742286
contentAvailable: true,
2287+
mutableContent: true,
22752288
threadId: 'thread.id',
22762289
},
22772290
customKey1: 'custom.value',
@@ -2298,6 +2311,7 @@ describe('Messaging', () => {
22982311
'sound': 'test.sound',
22992312
'category': 'test.category',
23002313
'content-available': 1,
2314+
'mutable-content': 1,
23012315
'thread-id': 'thread.id',
23022316
},
23032317
customKey1: 'custom.value',
@@ -2325,6 +2339,67 @@ describe('Messaging', () => {
23252339
},
23262340
},
23272341
},
2342+
{
2343+
label: 'APNS content-available set explicitly',
2344+
req: {
2345+
apns: {
2346+
payload: {
2347+
aps: {
2348+
'content-available': 1,
2349+
},
2350+
},
2351+
},
2352+
},
2353+
expectedReq: {
2354+
apns: {
2355+
payload: {
2356+
aps: {'content-available': 1},
2357+
},
2358+
},
2359+
},
2360+
},
2361+
{
2362+
label: 'APNS mutableContent explicitly false',
2363+
req: {
2364+
apns: {
2365+
payload: {
2366+
aps: {
2367+
mutableContent: false,
2368+
},
2369+
},
2370+
},
2371+
},
2372+
expectedReq: {
2373+
apns: {
2374+
payload: {
2375+
aps: {},
2376+
},
2377+
},
2378+
},
2379+
},
2380+
{
2381+
label: 'APNS custom fields',
2382+
req: {
2383+
apns: {
2384+
payload: {
2385+
aps: {
2386+
k1: 'v1',
2387+
k2: true,
2388+
},
2389+
},
2390+
},
2391+
},
2392+
expectedReq: {
2393+
apns: {
2394+
payload: {
2395+
aps: {
2396+
k1: 'v1',
2397+
k2: true,
2398+
},
2399+
},
2400+
},
2401+
},
2402+
},
23282403
];
23292404

23302405
validMessages.forEach((config) => {

0 commit comments

Comments
 (0)