1 |
|
2 | "use strict";
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | Object.defineProperty(exports, "__esModule", { value: true });
|
19 | exports.validateMessage = exports.BLACKLISTED_OPTIONS_KEYS = exports.BLACKLISTED_DATA_PAYLOAD_KEYS = void 0;
|
20 | const index_1 = require("../utils/index");
|
21 | const error_1 = require("../utils/error");
|
22 | const validator = require("../utils/validator");
|
23 |
|
24 | exports.BLACKLISTED_DATA_PAYLOAD_KEYS = ['from'];
|
25 |
|
26 | exports.BLACKLISTED_OPTIONS_KEYS = [
|
27 | 'condition', 'data', 'notification', 'registrationIds', 'registration_ids', 'to',
|
28 | ];
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 | function validateMessage(message) {
|
37 | if (!validator.isNonNullObject(message)) {
|
38 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'Message must be a non-null object');
|
39 | }
|
40 | const anyMessage = message;
|
41 | if (anyMessage.topic) {
|
42 |
|
43 | if (anyMessage.topic.startsWith('/topics/')) {
|
44 | anyMessage.topic = anyMessage.topic.replace(/^\/topics\//, '');
|
45 | }
|
46 |
|
47 | if (!/^[a-zA-Z0-9-_.~%]+$/.test(anyMessage.topic)) {
|
48 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'Malformed topic name');
|
49 | }
|
50 | }
|
51 | const targets = [anyMessage.token, anyMessage.topic, anyMessage.condition];
|
52 | if (targets.filter((v) => validator.isNonEmptyString(v)).length !== 1) {
|
53 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'Exactly one of topic, token or condition is required');
|
54 | }
|
55 | validateStringMap(message.data, 'data');
|
56 | validateAndroidConfig(message.android);
|
57 | validateWebpushConfig(message.webpush);
|
58 | validateApnsConfig(message.apns);
|
59 | validateFcmOptions(message.fcmOptions);
|
60 | validateNotification(message.notification);
|
61 | }
|
62 | exports.validateMessage = validateMessage;
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 | function validateStringMap(map, label) {
|
70 | if (typeof map === 'undefined') {
|
71 | return;
|
72 | }
|
73 | else if (!validator.isNonNullObject(map)) {
|
74 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, `${label} must be a non-null object`);
|
75 | }
|
76 | Object.keys(map).forEach((key) => {
|
77 | if (!validator.isString(map[key])) {
|
78 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, `${label} must only contain string values`);
|
79 | }
|
80 | });
|
81 | }
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 | function validateWebpushConfig(config) {
|
88 | if (typeof config === 'undefined') {
|
89 | return;
|
90 | }
|
91 | else if (!validator.isNonNullObject(config)) {
|
92 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'webpush must be a non-null object');
|
93 | }
|
94 | validateStringMap(config.headers, 'webpush.headers');
|
95 | validateStringMap(config.data, 'webpush.data');
|
96 | }
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 | function validateApnsConfig(config) {
|
104 | if (typeof config === 'undefined') {
|
105 | return;
|
106 | }
|
107 | else if (!validator.isNonNullObject(config)) {
|
108 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns must be a non-null object');
|
109 | }
|
110 | validateStringMap(config.headers, 'apns.headers');
|
111 | validateApnsPayload(config.payload);
|
112 | validateApnsFcmOptions(config.fcmOptions);
|
113 | }
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 | function validateApnsFcmOptions(fcmOptions) {
|
120 | if (typeof fcmOptions === 'undefined') {
|
121 | return;
|
122 | }
|
123 | else if (!validator.isNonNullObject(fcmOptions)) {
|
124 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'fcmOptions must be a non-null object');
|
125 | }
|
126 | if (typeof fcmOptions.imageUrl !== 'undefined' &&
|
127 | !validator.isURL(fcmOptions.imageUrl)) {
|
128 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'imageUrl must be a valid URL string');
|
129 | }
|
130 | if (typeof fcmOptions.analyticsLabel !== 'undefined' && !validator.isString(fcmOptions.analyticsLabel)) {
|
131 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'analyticsLabel must be a string value');
|
132 | }
|
133 | const propertyMappings = {
|
134 | imageUrl: 'image',
|
135 | };
|
136 | Object.keys(propertyMappings).forEach((key) => {
|
137 | if (key in fcmOptions && propertyMappings[key] in fcmOptions) {
|
138 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, `Multiple specifications for ${key} in ApnsFcmOptions`);
|
139 | }
|
140 | });
|
141 | (0, index_1.renameProperties)(fcmOptions, propertyMappings);
|
142 | }
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 | function validateFcmOptions(fcmOptions) {
|
149 | if (typeof fcmOptions === 'undefined') {
|
150 | return;
|
151 | }
|
152 | else if (!validator.isNonNullObject(fcmOptions)) {
|
153 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'fcmOptions must be a non-null object');
|
154 | }
|
155 | if (typeof fcmOptions.analyticsLabel !== 'undefined' && !validator.isString(fcmOptions.analyticsLabel)) {
|
156 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'analyticsLabel must be a string value');
|
157 | }
|
158 | }
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 | function validateNotification(notification) {
|
165 | if (typeof notification === 'undefined') {
|
166 | return;
|
167 | }
|
168 | else if (!validator.isNonNullObject(notification)) {
|
169 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'notification must be a non-null object');
|
170 | }
|
171 | if (typeof notification.imageUrl !== 'undefined' && !validator.isURL(notification.imageUrl)) {
|
172 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'notification.imageUrl must be a valid URL string');
|
173 | }
|
174 | const propertyMappings = {
|
175 | imageUrl: 'image',
|
176 | };
|
177 | Object.keys(propertyMappings).forEach((key) => {
|
178 | if (key in notification && propertyMappings[key] in notification) {
|
179 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, `Multiple specifications for ${key} in Notification`);
|
180 | }
|
181 | });
|
182 | (0, index_1.renameProperties)(notification, propertyMappings);
|
183 | }
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 | function validateApnsPayload(payload) {
|
190 | if (typeof payload === 'undefined') {
|
191 | return;
|
192 | }
|
193 | else if (!validator.isNonNullObject(payload)) {
|
194 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload must be a non-null object');
|
195 | }
|
196 | validateAps(payload.aps);
|
197 | }
|
198 |
|
199 |
|
200 |
|
201 |
|
202 |
|
203 |
|
204 | function validateAps(aps) {
|
205 | if (typeof aps === 'undefined') {
|
206 | return;
|
207 | }
|
208 | else if (!validator.isNonNullObject(aps)) {
|
209 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload.aps must be a non-null object');
|
210 | }
|
211 | validateApsAlert(aps.alert);
|
212 | validateApsSound(aps.sound);
|
213 | const propertyMappings = {
|
214 | contentAvailable: 'content-available',
|
215 | mutableContent: 'mutable-content',
|
216 | threadId: 'thread-id',
|
217 | };
|
218 | Object.keys(propertyMappings).forEach((key) => {
|
219 | if (key in aps && propertyMappings[key] in aps) {
|
220 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, `Multiple specifications for ${key} in Aps`);
|
221 | }
|
222 | });
|
223 | (0, index_1.renameProperties)(aps, propertyMappings);
|
224 | const contentAvailable = aps['content-available'];
|
225 | if (typeof contentAvailable !== 'undefined' && contentAvailable !== 1) {
|
226 | if (contentAvailable === true) {
|
227 | aps['content-available'] = 1;
|
228 | }
|
229 | else {
|
230 | delete aps['content-available'];
|
231 | }
|
232 | }
|
233 | const mutableContent = aps['mutable-content'];
|
234 | if (typeof mutableContent !== 'undefined' && mutableContent !== 1) {
|
235 | if (mutableContent === true) {
|
236 | aps['mutable-content'] = 1;
|
237 | }
|
238 | else {
|
239 | delete aps['mutable-content'];
|
240 | }
|
241 | }
|
242 | }
|
243 | function validateApsSound(sound) {
|
244 | if (typeof sound === 'undefined' || validator.isNonEmptyString(sound)) {
|
245 | return;
|
246 | }
|
247 | else if (!validator.isNonNullObject(sound)) {
|
248 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload.aps.sound must be a non-empty string or a non-null object');
|
249 | }
|
250 | if (!validator.isNonEmptyString(sound.name)) {
|
251 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload.aps.sound.name must be a non-empty string');
|
252 | }
|
253 | const volume = sound.volume;
|
254 | if (typeof volume !== 'undefined') {
|
255 | if (!validator.isNumber(volume)) {
|
256 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload.aps.sound.volume must be a number');
|
257 | }
|
258 | if (volume < 0 || volume > 1) {
|
259 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload.aps.sound.volume must be in the interval [0, 1]');
|
260 | }
|
261 | }
|
262 | const soundObject = sound;
|
263 | const key = 'critical';
|
264 | const critical = soundObject[key];
|
265 | if (typeof critical !== 'undefined' && critical !== 1) {
|
266 | if (critical === true) {
|
267 | soundObject[key] = 1;
|
268 | }
|
269 | else {
|
270 | delete soundObject[key];
|
271 | }
|
272 | }
|
273 | }
|
274 |
|
275 |
|
276 |
|
277 |
|
278 |
|
279 |
|
280 |
|
281 | function validateApsAlert(alert) {
|
282 | if (typeof alert === 'undefined' || validator.isString(alert)) {
|
283 | return;
|
284 | }
|
285 | else if (!validator.isNonNullObject(alert)) {
|
286 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload.aps.alert must be a string or a non-null object');
|
287 | }
|
288 | const apsAlert = alert;
|
289 | if (validator.isNonEmptyArray(apsAlert.locArgs) &&
|
290 | !validator.isNonEmptyString(apsAlert.locKey)) {
|
291 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload.aps.alert.locKey is required when specifying locArgs');
|
292 | }
|
293 | if (validator.isNonEmptyArray(apsAlert.titleLocArgs) &&
|
294 | !validator.isNonEmptyString(apsAlert.titleLocKey)) {
|
295 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload.aps.alert.titleLocKey is required when specifying titleLocArgs');
|
296 | }
|
297 | if (validator.isNonEmptyArray(apsAlert.subtitleLocArgs) &&
|
298 | !validator.isNonEmptyString(apsAlert.subtitleLocKey)) {
|
299 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload.aps.alert.subtitleLocKey is required when specifying subtitleLocArgs');
|
300 | }
|
301 | const propertyMappings = {
|
302 | locKey: 'loc-key',
|
303 | locArgs: 'loc-args',
|
304 | titleLocKey: 'title-loc-key',
|
305 | titleLocArgs: 'title-loc-args',
|
306 | subtitleLocKey: 'subtitle-loc-key',
|
307 | subtitleLocArgs: 'subtitle-loc-args',
|
308 | actionLocKey: 'action-loc-key',
|
309 | launchImage: 'launch-image',
|
310 | };
|
311 | (0, index_1.renameProperties)(apsAlert, propertyMappings);
|
312 | }
|
313 |
|
314 |
|
315 |
|
316 |
|
317 |
|
318 |
|
319 |
|
320 | function validateAndroidConfig(config) {
|
321 | if (typeof config === 'undefined') {
|
322 | return;
|
323 | }
|
324 | else if (!validator.isNonNullObject(config)) {
|
325 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android must be a non-null object');
|
326 | }
|
327 | if (typeof config.ttl !== 'undefined') {
|
328 | if (!validator.isNumber(config.ttl) || config.ttl < 0) {
|
329 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'TTL must be a non-negative duration in milliseconds');
|
330 | }
|
331 | const duration = (0, index_1.transformMillisecondsToSecondsString)(config.ttl);
|
332 | config.ttl = duration;
|
333 | }
|
334 | validateStringMap(config.data, 'android.data');
|
335 | validateAndroidNotification(config.notification);
|
336 | validateAndroidFcmOptions(config.fcmOptions);
|
337 | const propertyMappings = {
|
338 | collapseKey: 'collapse_key',
|
339 | restrictedPackageName: 'restricted_package_name',
|
340 | };
|
341 | (0, index_1.renameProperties)(config, propertyMappings);
|
342 | }
|
343 |
|
344 |
|
345 |
|
346 |
|
347 |
|
348 |
|
349 |
|
350 | function validateAndroidNotification(notification) {
|
351 | if (typeof notification === 'undefined') {
|
352 | return;
|
353 | }
|
354 | else if (!validator.isNonNullObject(notification)) {
|
355 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android.notification must be a non-null object');
|
356 | }
|
357 | if (typeof notification.color !== 'undefined' && !/^#[0-9a-fA-F]{6}$/.test(notification.color)) {
|
358 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android.notification.color must be in the form #RRGGBB');
|
359 | }
|
360 | if (validator.isNonEmptyArray(notification.bodyLocArgs) &&
|
361 | !validator.isNonEmptyString(notification.bodyLocKey)) {
|
362 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android.notification.bodyLocKey is required when specifying bodyLocArgs');
|
363 | }
|
364 | if (validator.isNonEmptyArray(notification.titleLocArgs) &&
|
365 | !validator.isNonEmptyString(notification.titleLocKey)) {
|
366 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android.notification.titleLocKey is required when specifying titleLocArgs');
|
367 | }
|
368 | if (typeof notification.imageUrl !== 'undefined' &&
|
369 | !validator.isURL(notification.imageUrl)) {
|
370 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android.notification.imageUrl must be a valid URL string');
|
371 | }
|
372 | if (typeof notification.eventTimestamp !== 'undefined') {
|
373 | if (!(notification.eventTimestamp instanceof Date)) {
|
374 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android.notification.eventTimestamp must be a valid `Date` object');
|
375 | }
|
376 |
|
377 | const zuluTimestamp = notification.eventTimestamp.toISOString();
|
378 | notification.eventTimestamp = zuluTimestamp;
|
379 | }
|
380 | if (typeof notification.vibrateTimingsMillis !== 'undefined') {
|
381 | if (!validator.isNonEmptyArray(notification.vibrateTimingsMillis)) {
|
382 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android.notification.vibrateTimingsMillis must be a non-empty array of numbers');
|
383 | }
|
384 | const vibrateTimings = [];
|
385 | notification.vibrateTimingsMillis.forEach((value) => {
|
386 | if (!validator.isNumber(value) || value < 0) {
|
387 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android.notification.vibrateTimingsMillis must be non-negative durations in milliseconds');
|
388 | }
|
389 | const duration = (0, index_1.transformMillisecondsToSecondsString)(value);
|
390 | vibrateTimings.push(duration);
|
391 | });
|
392 | notification.vibrateTimingsMillis = vibrateTimings;
|
393 | }
|
394 | if (typeof notification.priority !== 'undefined') {
|
395 | const priority = 'PRIORITY_' + notification.priority.toUpperCase();
|
396 | notification.priority = priority;
|
397 | }
|
398 | if (typeof notification.visibility !== 'undefined') {
|
399 | const visibility = notification.visibility.toUpperCase();
|
400 | notification.visibility = visibility;
|
401 | }
|
402 | validateLightSettings(notification.lightSettings);
|
403 | const propertyMappings = {
|
404 | clickAction: 'click_action',
|
405 | bodyLocKey: 'body_loc_key',
|
406 | bodyLocArgs: 'body_loc_args',
|
407 | titleLocKey: 'title_loc_key',
|
408 | titleLocArgs: 'title_loc_args',
|
409 | channelId: 'channel_id',
|
410 | imageUrl: 'image',
|
411 | eventTimestamp: 'event_time',
|
412 | localOnly: 'local_only',
|
413 | priority: 'notification_priority',
|
414 | vibrateTimingsMillis: 'vibrate_timings',
|
415 | defaultVibrateTimings: 'default_vibrate_timings',
|
416 | defaultSound: 'default_sound',
|
417 | lightSettings: 'light_settings',
|
418 | defaultLightSettings: 'default_light_settings',
|
419 | notificationCount: 'notification_count',
|
420 | };
|
421 | (0, index_1.renameProperties)(notification, propertyMappings);
|
422 | }
|
423 |
|
424 |
|
425 |
|
426 |
|
427 |
|
428 |
|
429 |
|
430 | function validateLightSettings(lightSettings) {
|
431 | if (typeof lightSettings === 'undefined') {
|
432 | return;
|
433 | }
|
434 | else if (!validator.isNonNullObject(lightSettings)) {
|
435 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android.notification.lightSettings must be a non-null object');
|
436 | }
|
437 | if (!validator.isNumber(lightSettings.lightOnDurationMillis) || lightSettings.lightOnDurationMillis < 0) {
|
438 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android.notification.lightSettings.lightOnDurationMillis must be a non-negative duration in milliseconds');
|
439 | }
|
440 | const durationOn = (0, index_1.transformMillisecondsToSecondsString)(lightSettings.lightOnDurationMillis);
|
441 | lightSettings.lightOnDurationMillis = durationOn;
|
442 | if (!validator.isNumber(lightSettings.lightOffDurationMillis) || lightSettings.lightOffDurationMillis < 0) {
|
443 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android.notification.lightSettings.lightOffDurationMillis must be a non-negative duration in milliseconds');
|
444 | }
|
445 | const durationOff = (0, index_1.transformMillisecondsToSecondsString)(lightSettings.lightOffDurationMillis);
|
446 | lightSettings.lightOffDurationMillis = durationOff;
|
447 | if (!validator.isString(lightSettings.color) ||
|
448 | (!/^#[0-9a-fA-F]{6}$/.test(lightSettings.color) && !/^#[0-9a-fA-F]{8}$/.test(lightSettings.color))) {
|
449 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android.notification.lightSettings.color must be in the form #RRGGBB or #RRGGBBAA format');
|
450 | }
|
451 | const colorString = lightSettings.color.length === 7 ? lightSettings.color + 'FF' : lightSettings.color;
|
452 | const rgb = /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/i.exec(colorString);
|
453 | if (!rgb || rgb.length < 4) {
|
454 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INTERNAL_ERROR, 'regex to extract rgba values from ' + colorString + ' failed.');
|
455 | }
|
456 | const color = {
|
457 | red: parseInt(rgb[1], 16) / 255.0,
|
458 | green: parseInt(rgb[2], 16) / 255.0,
|
459 | blue: parseInt(rgb[3], 16) / 255.0,
|
460 | alpha: parseInt(rgb[4], 16) / 255.0,
|
461 | };
|
462 | lightSettings.color = color;
|
463 | const propertyMappings = {
|
464 | lightOnDurationMillis: 'light_on_duration',
|
465 | lightOffDurationMillis: 'light_off_duration',
|
466 | };
|
467 | (0, index_1.renameProperties)(lightSettings, propertyMappings);
|
468 | }
|
469 |
|
470 |
|
471 |
|
472 |
|
473 |
|
474 | function validateAndroidFcmOptions(fcmOptions) {
|
475 | if (typeof fcmOptions === 'undefined') {
|
476 | return;
|
477 | }
|
478 | else if (!validator.isNonNullObject(fcmOptions)) {
|
479 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'fcmOptions must be a non-null object');
|
480 | }
|
481 | if (typeof fcmOptions.analyticsLabel !== 'undefined' && !validator.isString(fcmOptions.analyticsLabel)) {
|
482 | throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'analyticsLabel must be a string value');
|
483 | }
|
484 | }
|