firebase-admin 9.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +90 -0
  3. package/lib/app-check/app-check-api-client-internal.js +197 -0
  4. package/lib/app-check/app-check.js +79 -0
  5. package/lib/app-check/index.d.ts +160 -0
  6. package/lib/app-check/index.js +19 -0
  7. package/lib/app-check/token-generator.js +161 -0
  8. package/lib/app-check/token-verifier.js +152 -0
  9. package/lib/auth/action-code-settings-builder.js +118 -0
  10. package/lib/auth/auth-api-request.js +1856 -0
  11. package/lib/auth/auth-config.js +636 -0
  12. package/lib/auth/auth.js +836 -0
  13. package/lib/auth/identifier.js +40 -0
  14. package/lib/auth/index.d.ts +1927 -0
  15. package/lib/auth/index.js +18 -0
  16. package/lib/auth/tenant-manager.js +140 -0
  17. package/lib/auth/tenant.js +171 -0
  18. package/lib/auth/token-generator.js +200 -0
  19. package/lib/auth/token-verifier.js +259 -0
  20. package/lib/auth/user-import-builder.js +387 -0
  21. package/lib/auth/user-record.js +346 -0
  22. package/lib/credential/credential-internal.js +391 -0
  23. package/lib/credential/credential.js +44 -0
  24. package/lib/credential/index.d.ts +169 -0
  25. package/lib/credential/index.js +23 -0
  26. package/lib/database/database-internal.js +266 -0
  27. package/lib/database/index.d.ts +89 -0
  28. package/lib/database/index.js +31 -0
  29. package/lib/default-namespace.js +31 -0
  30. package/lib/firebase-app.js +349 -0
  31. package/lib/firebase-namespace-api.d.ts +243 -0
  32. package/lib/firebase-namespace-api.js +18 -0
  33. package/lib/firebase-namespace.d.ts +31 -0
  34. package/lib/firebase-namespace.js +417 -0
  35. package/lib/firestore/firestore-internal.js +105 -0
  36. package/lib/firestore/index.d.ts +50 -0
  37. package/lib/firestore/index.js +47 -0
  38. package/lib/index.d.ts +24 -0
  39. package/lib/index.js +27 -0
  40. package/lib/installations/index.d.ts +81 -0
  41. package/lib/installations/index.js +18 -0
  42. package/lib/installations/installations-request-handler.js +117 -0
  43. package/lib/installations/installations.js +62 -0
  44. package/lib/instance-id/index.d.ts +83 -0
  45. package/lib/instance-id/index.js +18 -0
  46. package/lib/instance-id/instance-id.js +87 -0
  47. package/lib/machine-learning/index.d.ts +249 -0
  48. package/lib/machine-learning/index.js +18 -0
  49. package/lib/machine-learning/machine-learning-api-client.js +304 -0
  50. package/lib/machine-learning/machine-learning-utils.js +62 -0
  51. package/lib/machine-learning/machine-learning.js +364 -0
  52. package/lib/messaging/batch-request-internal.js +129 -0
  53. package/lib/messaging/index.d.ts +1174 -0
  54. package/lib/messaging/index.js +18 -0
  55. package/lib/messaging/messaging-api-request-internal.js +128 -0
  56. package/lib/messaging/messaging-errors-internal.js +106 -0
  57. package/lib/messaging/messaging-internal.js +484 -0
  58. package/lib/messaging/messaging.js +846 -0
  59. package/lib/project-management/android-app.js +176 -0
  60. package/lib/project-management/index.d.ts +363 -0
  61. package/lib/project-management/index.js +41 -0
  62. package/lib/project-management/ios-app.js +88 -0
  63. package/lib/project-management/project-management-api-request-internal.js +273 -0
  64. package/lib/project-management/project-management.js +254 -0
  65. package/lib/remote-config/index.d.ts +369 -0
  66. package/lib/remote-config/index.js +18 -0
  67. package/lib/remote-config/remote-config-api-client-internal.js +407 -0
  68. package/lib/remote-config/remote-config.js +304 -0
  69. package/lib/security-rules/index.d.ts +216 -0
  70. package/lib/security-rules/index.js +18 -0
  71. package/lib/security-rules/security-rules-api-client-internal.js +237 -0
  72. package/lib/security-rules/security-rules-internal.js +41 -0
  73. package/lib/security-rules/security-rules.js +310 -0
  74. package/lib/storage/index.d.ts +60 -0
  75. package/lib/storage/index.js +18 -0
  76. package/lib/storage/storage.js +123 -0
  77. package/lib/utils/api-request.js +845 -0
  78. package/lib/utils/crypto-signer.js +237 -0
  79. package/lib/utils/deep-copy.js +78 -0
  80. package/lib/utils/error.js +1063 -0
  81. package/lib/utils/index.js +217 -0
  82. package/lib/utils/jwt.js +355 -0
  83. package/lib/utils/validator.js +271 -0
  84. package/package.json +122 -0
@@ -0,0 +1,484 @@
1
+ /*! firebase-admin v9.12.0 */
2
+ "use strict";
3
+ /*!
4
+ * Copyright 2020 Google Inc.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.validateMessage = exports.BLACKLISTED_OPTIONS_KEYS = exports.BLACKLISTED_DATA_PAYLOAD_KEYS = void 0;
20
+ var index_1 = require("../utils/index");
21
+ var error_1 = require("../utils/error");
22
+ var validator = require("../utils/validator");
23
+ // Keys which are not allowed in the messaging data payload object.
24
+ exports.BLACKLISTED_DATA_PAYLOAD_KEYS = ['from'];
25
+ // Keys which are not allowed in the messaging options object.
26
+ exports.BLACKLISTED_OPTIONS_KEYS = [
27
+ 'condition', 'data', 'notification', 'registrationIds', 'registration_ids', 'to',
28
+ ];
29
+ /**
30
+ * Checks if the given Message object is valid. Recursively validates all the child objects
31
+ * included in the message (android, apns, data etc.). If successful, transforms the message
32
+ * in place by renaming the keys to what's expected by the remote FCM service.
33
+ *
34
+ * @param {Message} Message An object to be validated.
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
+ var anyMessage = message;
41
+ if (anyMessage.topic) {
42
+ // If the topic name is prefixed, remove it.
43
+ if (anyMessage.topic.startsWith('/topics/')) {
44
+ anyMessage.topic = anyMessage.topic.replace(/^\/topics\//, '');
45
+ }
46
+ // Checks for illegal characters and empty string.
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
+ var targets = [anyMessage.token, anyMessage.topic, anyMessage.condition];
52
+ if (targets.filter(function (v) { return 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
+ * Checks if the given object only contains strings as child values.
65
+ *
66
+ * @param {object} map An object to be validated.
67
+ * @param {string} label A label to be included in the errors thrown.
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(function (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
+ * Checks if the given WebpushConfig object is valid. The object must have valid headers and data.
84
+ *
85
+ * @param {WebpushConfig} config An object to be validated.
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
+ * Checks if the given ApnsConfig object is valid. The object must have valid headers and a
99
+ * payload.
100
+ *
101
+ * @param {ApnsConfig} config An object to be validated.
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
+ * Checks if the given ApnsFcmOptions object is valid.
116
+ *
117
+ * @param {ApnsFcmOptions} fcmOptions An object to be validated.
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
+ var propertyMappings = {
134
+ imageUrl: 'image',
135
+ };
136
+ Object.keys(propertyMappings).forEach(function (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
+ index_1.renameProperties(fcmOptions, propertyMappings);
142
+ }
143
+ /**
144
+ * Checks if the given FcmOptions object is valid.
145
+ *
146
+ * @param {FcmOptions} fcmOptions An object to be validated.
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
+ * Checks if the given Notification object is valid.
161
+ *
162
+ * @param {Notification} notification An object to be validated.
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
+ var propertyMappings = {
175
+ imageUrl: 'image',
176
+ };
177
+ Object.keys(propertyMappings).forEach(function (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
+ index_1.renameProperties(notification, propertyMappings);
183
+ }
184
+ /**
185
+ * Checks if the given ApnsPayload object is valid. The object must have a valid aps value.
186
+ *
187
+ * @param {ApnsPayload} payload An object to be validated.
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
+ * Checks if the given Aps object is valid. The object must have a valid alert. If the validation
200
+ * is successful, transforms the input object by renaming the keys to valid APNS payload keys.
201
+ *
202
+ * @param {Aps} aps An object to be validated.
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
+ var propertyMappings = {
214
+ contentAvailable: 'content-available',
215
+ mutableContent: 'mutable-content',
216
+ threadId: 'thread-id',
217
+ };
218
+ Object.keys(propertyMappings).forEach(function (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
+ index_1.renameProperties(aps, propertyMappings);
224
+ var 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
+ var 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
+ var 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
+ var soundObject = sound;
263
+ var key = 'critical';
264
+ var 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
+ * Checks if the given alert object is valid. Alert could be a string or a complex object.
276
+ * If specified as an object, it must have valid localization parameters. If successful, transforms
277
+ * the input object by renaming the keys to valid APNS payload keys.
278
+ *
279
+ * @param {string | ApsAlert} alert An alert string or an object to be validated.
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
+ var 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
+ var 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
+ index_1.renameProperties(apsAlert, propertyMappings);
312
+ }
313
+ /**
314
+ * Checks if the given AndroidConfig object is valid. The object must have valid ttl, data,
315
+ * and notification fields. If successful, transforms the input object by renaming keys to valid
316
+ * Android keys. Also transforms the ttl value to the format expected by FCM service.
317
+ *
318
+ * @param {AndroidConfig} config An object to be validated.
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
+ var duration = 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
+ var propertyMappings = {
338
+ collapseKey: 'collapse_key',
339
+ restrictedPackageName: 'restricted_package_name',
340
+ };
341
+ index_1.renameProperties(config, propertyMappings);
342
+ }
343
+ /**
344
+ * Checks if the given AndroidNotification object is valid. The object must have valid color and
345
+ * localization parameters. If successful, transforms the input object by renaming keys to valid
346
+ * Android keys.
347
+ *
348
+ * @param {AndroidNotification} notification An object to be validated.
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
+ // Convert timestamp to RFC3339 UTC "Zulu" format, example "2014-10-02T15:01:23.045123456Z"
377
+ var 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
+ var vibrateTimings_1 = [];
385
+ notification.vibrateTimingsMillis.forEach(function (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
+ var duration = index_1.transformMillisecondsToSecondsString(value);
390
+ vibrateTimings_1.push(duration);
391
+ });
392
+ notification.vibrateTimingsMillis = vibrateTimings_1;
393
+ }
394
+ if (typeof notification.priority !== 'undefined') {
395
+ var priority = 'PRIORITY_' + notification.priority.toUpperCase();
396
+ notification.priority = priority;
397
+ }
398
+ if (typeof notification.visibility !== 'undefined') {
399
+ var visibility = notification.visibility.toUpperCase();
400
+ notification.visibility = visibility;
401
+ }
402
+ validateLightSettings(notification.lightSettings);
403
+ var 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
+ index_1.renameProperties(notification, propertyMappings);
422
+ }
423
+ /**
424
+ * Checks if the given LightSettings object is valid. The object must have valid color and
425
+ * light on/off duration parameters. If successful, transforms the input object by renaming
426
+ * keys to valid Android keys.
427
+ *
428
+ * @param {LightSettings} lightSettings An object to be validated.
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
+ var durationOn = 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
+ var durationOff = 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
+ var colorString = lightSettings.color.length === 7 ? lightSettings.color + 'FF' : lightSettings.color;
452
+ var 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
+ var 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
+ var propertyMappings = {
464
+ lightOnDurationMillis: 'light_on_duration',
465
+ lightOffDurationMillis: 'light_off_duration',
466
+ };
467
+ index_1.renameProperties(lightSettings, propertyMappings);
468
+ }
469
+ /**
470
+ * Checks if the given AndroidFcmOptions object is valid.
471
+ *
472
+ * @param {AndroidFcmOptions} fcmOptions An object to be validated.
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
+ }