@parse/push-adapter 6.2.0 → 6.3.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.
- package/README.md +135 -40
- package/package.json +18 -23
- package/src/APNS.js +323 -0
- package/src/EXPO.js +107 -0
- package/{lib → src}/FCM.js +147 -140
- package/{lib → src}/GCM.js +57 -85
- package/src/ParsePushAdapter.js +96 -0
- package/src/PushAdapterUtils.js +45 -0
- package/src/WEB.js +106 -0
- package/src/index.js +20 -0
- package/lib/APNS.js +0 -400
- package/lib/EXPO.js +0 -204
- package/lib/ParsePushAdapter.js +0 -167
- package/lib/PushAdapterUtils.js +0 -95
- package/lib/WEB.js +0 -204
- package/lib/index.js +0 -52
package/lib/APNS.js
DELETED
|
@@ -1,400 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.APNS = undefined;
|
|
7
|
-
|
|
8
|
-
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
|
9
|
-
|
|
10
|
-
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
11
|
-
|
|
12
|
-
var _nodeApn = require('@parse/node-apn');
|
|
13
|
-
|
|
14
|
-
var _nodeApn2 = _interopRequireDefault(_nodeApn);
|
|
15
|
-
|
|
16
|
-
var _parse = require('parse');
|
|
17
|
-
|
|
18
|
-
var _parse2 = _interopRequireDefault(_parse);
|
|
19
|
-
|
|
20
|
-
var _npmlog = require('npmlog');
|
|
21
|
-
|
|
22
|
-
var _npmlog2 = _interopRequireDefault(_npmlog);
|
|
23
|
-
|
|
24
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
25
|
-
|
|
26
|
-
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
27
|
-
|
|
28
|
-
var LOG_PREFIX = 'parse-server-push-adapter APNS';
|
|
29
|
-
|
|
30
|
-
var APNS = exports.APNS = function () {
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Create a new provider for the APN service.
|
|
34
|
-
* @constructor
|
|
35
|
-
* @param {Object|Array} args An argument or a list of arguments to config APNS provider
|
|
36
|
-
* @param {Object} args.token {Object} Configuration for Provider Authentication Tokens. (Defaults to: null i.e. fallback to Certificates)
|
|
37
|
-
* @param {Buffer|String} args.token.key The filename of the provider token key (as supplied by Apple) to load from disk, or a Buffer/String containing the key data.
|
|
38
|
-
* @param {String} args.token.keyId The ID of the key issued by Apple
|
|
39
|
-
* @param {String} args.token.teamId ID of the team associated with the provider token key
|
|
40
|
-
* @param {Buffer|String} args.cert The filename of the connection certificate to load from disk, or a Buffer/String containing the certificate data.
|
|
41
|
-
* @param {Buffer|String} args.key {Buffer|String} The filename of the connection key to load from disk, or a Buffer/String containing the key data.
|
|
42
|
-
* @param {Buffer|String} args.pfx path for private key, certificate and CA certs in PFX or PKCS12 format, or a Buffer containing the PFX data. If supplied will always be used instead of certificate and key above.
|
|
43
|
-
* @param {String} args.passphrase The passphrase for the provider key, if required
|
|
44
|
-
* @param {Boolean} args.production Specifies which environment to connect to: Production (if true) or Sandbox
|
|
45
|
-
* @param {String} args.topic Specififies an App-Id for this Provider
|
|
46
|
-
* @param {String} args.bundleId DEPRECATED: Specifies an App-ID for this Provider
|
|
47
|
-
* @param {Number} args.connectionRetryLimit The maximum number of connection failures that will be tolerated before apn.Provider will "give up". (Defaults to: 3)
|
|
48
|
-
*/
|
|
49
|
-
function APNS(args) {
|
|
50
|
-
_classCallCheck(this, APNS);
|
|
51
|
-
|
|
52
|
-
// Define class members
|
|
53
|
-
this.providers = [];
|
|
54
|
-
|
|
55
|
-
// Since for ios, there maybe multiple cert/key pairs, typePushConfig can be an array.
|
|
56
|
-
var apnsArgsList = [];
|
|
57
|
-
if (Array.isArray(args)) {
|
|
58
|
-
apnsArgsList = apnsArgsList.concat(args);
|
|
59
|
-
} else if ((typeof args === 'undefined' ? 'undefined' : _typeof(args)) === 'object') {
|
|
60
|
-
apnsArgsList.push(args);
|
|
61
|
-
} else {
|
|
62
|
-
throw new _parse2.default.Error(_parse2.default.Error.PUSH_MISCONFIGURED, 'APNS Configuration is invalid');
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Create Provider from each arg-object
|
|
66
|
-
var _iteratorNormalCompletion = true;
|
|
67
|
-
var _didIteratorError = false;
|
|
68
|
-
var _iteratorError = undefined;
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
for (var _iterator = apnsArgsList[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
72
|
-
var apnsArgs = _step.value;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
// rewrite bundleId to topic for backward-compatibility
|
|
76
|
-
if (apnsArgs.bundleId) {
|
|
77
|
-
_npmlog2.default.warn(LOG_PREFIX, 'bundleId is deprecated, use topic instead');
|
|
78
|
-
apnsArgs.topic = apnsArgs.bundleId;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
var provider = APNS._createProvider(apnsArgs);
|
|
82
|
-
this.providers.push(provider);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Sort the providers based on priority ascending, high pri first
|
|
86
|
-
} catch (err) {
|
|
87
|
-
_didIteratorError = true;
|
|
88
|
-
_iteratorError = err;
|
|
89
|
-
} finally {
|
|
90
|
-
try {
|
|
91
|
-
if (!_iteratorNormalCompletion && _iterator.return) {
|
|
92
|
-
_iterator.return();
|
|
93
|
-
}
|
|
94
|
-
} finally {
|
|
95
|
-
if (_didIteratorError) {
|
|
96
|
-
throw _iteratorError;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
this.providers.sort(function (s1, s2) {
|
|
102
|
-
return s1.priority - s2.priority;
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
// Set index-property of providers
|
|
106
|
-
for (var index = 0; index < this.providers.length; index++) {
|
|
107
|
-
this.providers[index].index = index;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Send apns request.
|
|
113
|
-
*
|
|
114
|
-
* @param {Object} data The data we need to send, the format is the same with api request body
|
|
115
|
-
* @param {Array} allDevices An array of devices
|
|
116
|
-
* @returns {Object} A promise which is resolved immediately
|
|
117
|
-
*/
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
_createClass(APNS, [{
|
|
121
|
-
key: 'send',
|
|
122
|
-
value: function send(data, allDevices) {
|
|
123
|
-
var coreData = data && data.data;
|
|
124
|
-
if (!coreData || !allDevices || !Array.isArray(allDevices)) {
|
|
125
|
-
_npmlog2.default.warn(LOG_PREFIX, 'invalid push payload');
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
var expirationTime = data['expiration_time'] || coreData['expiration_time'];
|
|
129
|
-
var collapseId = data['collapse_id'] || coreData['collapse_id'];
|
|
130
|
-
var pushType = data['push_type'] || coreData['push_type'];
|
|
131
|
-
var priority = data['priority'] || coreData['priority'];
|
|
132
|
-
var allPromises = [];
|
|
133
|
-
|
|
134
|
-
var devicesPerAppIdentifier = {};
|
|
135
|
-
|
|
136
|
-
// Start by clustering the devices per appIdentifier
|
|
137
|
-
allDevices.forEach(function (device) {
|
|
138
|
-
var appIdentifier = device.appIdentifier;
|
|
139
|
-
devicesPerAppIdentifier[appIdentifier] = devicesPerAppIdentifier[appIdentifier] || [];
|
|
140
|
-
devicesPerAppIdentifier[appIdentifier].push(device);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
for (var key in devicesPerAppIdentifier) {
|
|
144
|
-
var devices = devicesPerAppIdentifier[key];
|
|
145
|
-
var appIdentifier = devices[0].appIdentifier;
|
|
146
|
-
var providers = this._chooseProviders(appIdentifier);
|
|
147
|
-
|
|
148
|
-
// No Providers found
|
|
149
|
-
if (!providers || providers.length === 0) {
|
|
150
|
-
var errorPromises = devices.map(function (device) {
|
|
151
|
-
return APNS._createErrorPromise(device.deviceToken, 'No Provider found');
|
|
152
|
-
});
|
|
153
|
-
allPromises = allPromises.concat(errorPromises);
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
var headers = { expirationTime: expirationTime, topic: appIdentifier, collapseId: collapseId, pushType: pushType, priority: priority };
|
|
158
|
-
var notification = APNS._generateNotification(coreData, headers);
|
|
159
|
-
var deviceIds = devices.map(function (device) {
|
|
160
|
-
return device.deviceToken;
|
|
161
|
-
});
|
|
162
|
-
var promise = this.sendThroughProvider(notification, deviceIds, providers);
|
|
163
|
-
allPromises.push(promise.then(this._handlePromise.bind(this)));
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return Promise.all(allPromises).then(function (results) {
|
|
167
|
-
// flatten all
|
|
168
|
-
return [].concat.apply([], results);
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
}, {
|
|
172
|
-
key: 'sendThroughProvider',
|
|
173
|
-
value: function sendThroughProvider(notification, devices, providers) {
|
|
174
|
-
var _this = this;
|
|
175
|
-
|
|
176
|
-
return providers[0].send(notification, devices).then(function (response) {
|
|
177
|
-
if (response.failed && response.failed.length > 0 && providers && providers.length > 1) {
|
|
178
|
-
var _devices = response.failed.map(function (failure) {
|
|
179
|
-
return failure.device;
|
|
180
|
-
});
|
|
181
|
-
// Reset the failures as we'll try next connection
|
|
182
|
-
response.failed = [];
|
|
183
|
-
return _this.sendThroughProvider(notification, _devices, providers.slice(1, providers.length)).then(function (retryResponse) {
|
|
184
|
-
response.failed = response.failed.concat(retryResponse.failed);
|
|
185
|
-
response.sent = response.sent.concat(retryResponse.sent);
|
|
186
|
-
return response;
|
|
187
|
-
});
|
|
188
|
-
} else {
|
|
189
|
-
return response;
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
}, {
|
|
194
|
-
key: '_chooseProviders',
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Choose appropriate providers based on device appIdentifier.
|
|
199
|
-
*
|
|
200
|
-
* @param {String} appIdentifier appIdentifier for required provider
|
|
201
|
-
* @returns {Array} Returns Array with appropriate providers
|
|
202
|
-
*/
|
|
203
|
-
value: function _chooseProviders(appIdentifier) {
|
|
204
|
-
// If the device we need to send to does not have appIdentifier, any provider could be a qualified provider
|
|
205
|
-
/*if (!appIdentifier || appIdentifier === '') {
|
|
206
|
-
return this.providers.map((provider) => provider.index);
|
|
207
|
-
}*/
|
|
208
|
-
|
|
209
|
-
// Otherwise we try to match the appIdentifier with topic on provider
|
|
210
|
-
var qualifiedProviders = this.providers.filter(function (provider) {
|
|
211
|
-
return appIdentifier === provider.topic;
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
if (qualifiedProviders.length > 0) {
|
|
215
|
-
return qualifiedProviders;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// If qualifiedProviders empty, add all providers without topic
|
|
219
|
-
return this.providers.filter(function (provider) {
|
|
220
|
-
return !provider.topic || provider.topic === '';
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
}, {
|
|
224
|
-
key: '_handlePromise',
|
|
225
|
-
value: function _handlePromise(response) {
|
|
226
|
-
var promises = [];
|
|
227
|
-
response.sent.forEach(function (token) {
|
|
228
|
-
_npmlog2.default.verbose(LOG_PREFIX, 'APNS transmitted to %s', token.device);
|
|
229
|
-
promises.push(APNS._createSuccesfullPromise(token.device));
|
|
230
|
-
});
|
|
231
|
-
response.failed.forEach(function (failure) {
|
|
232
|
-
promises.push(APNS._handlePushFailure(failure));
|
|
233
|
-
});
|
|
234
|
-
return Promise.all(promises);
|
|
235
|
-
}
|
|
236
|
-
}], [{
|
|
237
|
-
key: '_validateAPNArgs',
|
|
238
|
-
value: function _validateAPNArgs(apnsArgs) {
|
|
239
|
-
if (apnsArgs.topic) {
|
|
240
|
-
return true;
|
|
241
|
-
}
|
|
242
|
-
return !(apnsArgs.cert || apnsArgs.key || apnsArgs.pfx);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Creates an Provider base on apnsArgs.
|
|
247
|
-
*/
|
|
248
|
-
|
|
249
|
-
}, {
|
|
250
|
-
key: '_createProvider',
|
|
251
|
-
value: function _createProvider(apnsArgs) {
|
|
252
|
-
// if using certificate, then topic must be defined
|
|
253
|
-
if (!APNS._validateAPNArgs(apnsArgs)) {
|
|
254
|
-
throw new _parse2.default.Error(_parse2.default.Error.PUSH_MISCONFIGURED, 'topic is mssing for %j', apnsArgs);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
var provider = new _nodeApn2.default.Provider(apnsArgs);
|
|
258
|
-
|
|
259
|
-
// Sets the topic on this provider
|
|
260
|
-
provider.topic = apnsArgs.topic;
|
|
261
|
-
|
|
262
|
-
// Set the priority of the providers, prod cert has higher priority
|
|
263
|
-
if (apnsArgs.production) {
|
|
264
|
-
provider.priority = 0;
|
|
265
|
-
} else {
|
|
266
|
-
provider.priority = 1;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
return provider;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* Generate the apns Notification from the data we get from api request.
|
|
274
|
-
* @param {Object} coreData The data field under api request body
|
|
275
|
-
* @param {Object} headers The header properties for the notification (topic, expirationTime, collapseId, pushType, priority)
|
|
276
|
-
* @returns {Object} A apns Notification
|
|
277
|
-
*/
|
|
278
|
-
|
|
279
|
-
}, {
|
|
280
|
-
key: '_generateNotification',
|
|
281
|
-
value: function _generateNotification(coreData, headers) {
|
|
282
|
-
var notification = new _nodeApn2.default.Notification();
|
|
283
|
-
var payload = {};
|
|
284
|
-
for (var key in coreData) {
|
|
285
|
-
switch (key) {
|
|
286
|
-
case 'aps':
|
|
287
|
-
notification.aps = coreData.aps;
|
|
288
|
-
break;
|
|
289
|
-
case 'alert':
|
|
290
|
-
notification.setAlert(coreData.alert);
|
|
291
|
-
break;
|
|
292
|
-
case 'title':
|
|
293
|
-
notification.setTitle(coreData.title);
|
|
294
|
-
break;
|
|
295
|
-
case 'badge':
|
|
296
|
-
notification.setBadge(coreData.badge);
|
|
297
|
-
break;
|
|
298
|
-
case 'sound':
|
|
299
|
-
notification.setSound(coreData.sound);
|
|
300
|
-
break;
|
|
301
|
-
case 'content-available':
|
|
302
|
-
var isAvailable = coreData['content-available'] === 1;
|
|
303
|
-
notification.setContentAvailable(isAvailable);
|
|
304
|
-
break;
|
|
305
|
-
case 'mutable-content':
|
|
306
|
-
var isMutable = coreData['mutable-content'] === 1;
|
|
307
|
-
notification.setMutableContent(isMutable);
|
|
308
|
-
break;
|
|
309
|
-
case 'targetContentIdentifier':
|
|
310
|
-
notification.setTargetContentIdentifier(coreData.targetContentIdentifier);
|
|
311
|
-
break;
|
|
312
|
-
case 'interruptionLevel':
|
|
313
|
-
notification.setInterruptionLevel(coreData.interruptionLevel);
|
|
314
|
-
break;
|
|
315
|
-
case 'category':
|
|
316
|
-
notification.setCategory(coreData.category);
|
|
317
|
-
break;
|
|
318
|
-
case 'threadId':
|
|
319
|
-
notification.setThreadId(coreData.threadId);
|
|
320
|
-
break;
|
|
321
|
-
default:
|
|
322
|
-
payload[key] = coreData[key];
|
|
323
|
-
break;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
notification.payload = payload;
|
|
328
|
-
|
|
329
|
-
notification.topic = headers.topic;
|
|
330
|
-
notification.expiry = Math.round(headers.expirationTime / 1000);
|
|
331
|
-
notification.collapseId = headers.collapseId;
|
|
332
|
-
// set alert as default push type. If push type is not set notifications are not delivered to devices running iOS 13, watchOS 6 and later.
|
|
333
|
-
notification.pushType = 'alert';
|
|
334
|
-
if (headers.pushType) {
|
|
335
|
-
notification.pushType = headers.pushType;
|
|
336
|
-
}
|
|
337
|
-
if (headers.priority) {
|
|
338
|
-
// if headers priority is not set 'node-apn' defaults it to 5 which is min. required value for background pushes to launch the app in background.
|
|
339
|
-
notification.priority = headers.priority;
|
|
340
|
-
}
|
|
341
|
-
return notification;
|
|
342
|
-
}
|
|
343
|
-
}, {
|
|
344
|
-
key: '_handlePushFailure',
|
|
345
|
-
value: function _handlePushFailure(failure) {
|
|
346
|
-
if (failure.error) {
|
|
347
|
-
_npmlog2.default.error(LOG_PREFIX, 'APNS error transmitting to device %s with error %s', failure.device, failure.error);
|
|
348
|
-
return APNS._createErrorPromise(failure.device, failure.error);
|
|
349
|
-
} else if (failure.status && failure.response && failure.response.reason) {
|
|
350
|
-
_npmlog2.default.error(LOG_PREFIX, 'APNS error transmitting to device %s with status %s and reason %s', failure.device, failure.status, failure.response.reason);
|
|
351
|
-
return APNS._createErrorPromise(failure.device, failure.response.reason);
|
|
352
|
-
} else {
|
|
353
|
-
_npmlog2.default.error(LOG_PREFIX, 'APNS error transmitting to device with unkown error');
|
|
354
|
-
return APNS._createErrorPromise(failure.device, 'Unkown status');
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
/**
|
|
359
|
-
* Creates an errorPromise for return.
|
|
360
|
-
*
|
|
361
|
-
* @param {String} token Device-Token
|
|
362
|
-
* @param {String} errorMessage ErrrorMessage as string
|
|
363
|
-
*/
|
|
364
|
-
|
|
365
|
-
}, {
|
|
366
|
-
key: '_createErrorPromise',
|
|
367
|
-
value: function _createErrorPromise(token, errorMessage) {
|
|
368
|
-
return Promise.resolve({
|
|
369
|
-
transmitted: false,
|
|
370
|
-
device: {
|
|
371
|
-
deviceToken: token,
|
|
372
|
-
deviceType: 'ios'
|
|
373
|
-
},
|
|
374
|
-
response: { error: errorMessage }
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
/**
|
|
379
|
-
* Creates an successfulPromise for return.
|
|
380
|
-
*
|
|
381
|
-
* @param {String} token Device-Token
|
|
382
|
-
*/
|
|
383
|
-
|
|
384
|
-
}, {
|
|
385
|
-
key: '_createSuccesfullPromise',
|
|
386
|
-
value: function _createSuccesfullPromise(token) {
|
|
387
|
-
return Promise.resolve({
|
|
388
|
-
transmitted: true,
|
|
389
|
-
device: {
|
|
390
|
-
deviceToken: token,
|
|
391
|
-
deviceType: 'ios'
|
|
392
|
-
}
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
}]);
|
|
396
|
-
|
|
397
|
-
return APNS;
|
|
398
|
-
}();
|
|
399
|
-
|
|
400
|
-
exports.default = APNS;
|
package/lib/EXPO.js
DELETED
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.EXPO = undefined;
|
|
7
|
-
|
|
8
|
-
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
|
9
|
-
|
|
10
|
-
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
11
|
-
|
|
12
|
-
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
|
13
|
-
|
|
14
|
-
var _parse = require('parse');
|
|
15
|
-
|
|
16
|
-
var _parse2 = _interopRequireDefault(_parse);
|
|
17
|
-
|
|
18
|
-
var _npmlog = require('npmlog');
|
|
19
|
-
|
|
20
|
-
var _npmlog2 = _interopRequireDefault(_npmlog);
|
|
21
|
-
|
|
22
|
-
var _expoServerSdk = require('expo-server-sdk');
|
|
23
|
-
|
|
24
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
25
|
-
|
|
26
|
-
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
|
|
27
|
-
|
|
28
|
-
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
|
|
29
|
-
|
|
30
|
-
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
31
|
-
|
|
32
|
-
var LOG_PREFIX = 'parse-server-push-adapter EXPO';
|
|
33
|
-
|
|
34
|
-
function expoResultToParseResponse(result) {
|
|
35
|
-
if (result.status === 'ok') {
|
|
36
|
-
return result;
|
|
37
|
-
} else {
|
|
38
|
-
// ParseServer looks for "error", and supports ceratin codes like 'NotRegistered' for
|
|
39
|
-
// cleanup. Expo returns slighyly different ones so changing to match what is expected
|
|
40
|
-
// This can be taken out if the responsibility gets moved to the adapter itself.
|
|
41
|
-
var error = result.message === 'DeviceNotRegistered' ? 'NotRegistered' : result.message;
|
|
42
|
-
return _extends({
|
|
43
|
-
error: error
|
|
44
|
-
}, result);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
var EXPO = exports.EXPO = function () {
|
|
49
|
-
/**
|
|
50
|
-
* Create a new EXPO push adapter. Based on Web Adapter.
|
|
51
|
-
*
|
|
52
|
-
* @param {Object} args https://github.com/expo/expo-server-sdk-node / https://docs.expo.dev/push-notifications/sending-notifications/
|
|
53
|
-
*/
|
|
54
|
-
function EXPO(args) {
|
|
55
|
-
_classCallCheck(this, EXPO);
|
|
56
|
-
|
|
57
|
-
this.expo = undefined;
|
|
58
|
-
|
|
59
|
-
if ((typeof args === 'undefined' ? 'undefined' : _typeof(args)) !== 'object') {
|
|
60
|
-
throw new _parse2.default.Error(_parse2.default.Error.PUSH_MISCONFIGURED, 'EXPO Push Configuration is invalid');
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
this.expo = new _expoServerSdk.Expo(args);
|
|
64
|
-
this.options = args;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Send Expo push notification request.
|
|
69
|
-
*
|
|
70
|
-
* @param {Object} data The data we need to send, the format is the same with api request body
|
|
71
|
-
* @param {Array} devices An array of devices
|
|
72
|
-
* @returns {Object} A promise which is resolved immediately
|
|
73
|
-
*/
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
_createClass(EXPO, [{
|
|
77
|
-
key: 'send',
|
|
78
|
-
value: function () {
|
|
79
|
-
var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(data, devices) {
|
|
80
|
-
var coreData, devicesMap, deviceTokens, resolvers, promises, length, response;
|
|
81
|
-
return regeneratorRuntime.wrap(function _callee$(_context) {
|
|
82
|
-
while (1) {
|
|
83
|
-
switch (_context.prev = _context.next) {
|
|
84
|
-
case 0:
|
|
85
|
-
coreData = data && data.data;
|
|
86
|
-
|
|
87
|
-
if (!(!coreData || !devices || !Array.isArray(devices))) {
|
|
88
|
-
_context.next = 4;
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
_npmlog2.default.warn(LOG_PREFIX, 'invalid push payload');
|
|
93
|
-
return _context.abrupt('return');
|
|
94
|
-
|
|
95
|
-
case 4:
|
|
96
|
-
devicesMap = devices.reduce(function (memo, device) {
|
|
97
|
-
memo[device.deviceToken] = device;
|
|
98
|
-
return memo;
|
|
99
|
-
}, {});
|
|
100
|
-
deviceTokens = Object.keys(devicesMap);
|
|
101
|
-
resolvers = [];
|
|
102
|
-
promises = deviceTokens.map(function () {
|
|
103
|
-
return new Promise(function (resolve) {
|
|
104
|
-
return resolvers.push(resolve);
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
length = deviceTokens.length;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
_npmlog2.default.verbose(LOG_PREFIX, 'sending to ' + length + ' ' + (length > 1 ? 'devices' : 'device'));
|
|
111
|
-
|
|
112
|
-
_context.next = 12;
|
|
113
|
-
return this.sendNotifications(coreData, deviceTokens);
|
|
114
|
-
|
|
115
|
-
case 12:
|
|
116
|
-
response = _context.sent;
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
_npmlog2.default.verbose(LOG_PREFIX, 'EXPO Response: %d sent', response.length);
|
|
120
|
-
|
|
121
|
-
deviceTokens.forEach(function (token, index) {
|
|
122
|
-
var resolve = resolvers[index];
|
|
123
|
-
var result = response[index];
|
|
124
|
-
var device = devicesMap[token];
|
|
125
|
-
var resolution = {
|
|
126
|
-
transmitted: result.status === 'ok',
|
|
127
|
-
device: _extends({}, device, {
|
|
128
|
-
pushType: 'expo'
|
|
129
|
-
}),
|
|
130
|
-
response: expoResultToParseResponse(result)
|
|
131
|
-
};
|
|
132
|
-
resolve(resolution);
|
|
133
|
-
});
|
|
134
|
-
return _context.abrupt('return', Promise.all(promises));
|
|
135
|
-
|
|
136
|
-
case 16:
|
|
137
|
-
case 'end':
|
|
138
|
-
return _context.stop();
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}, _callee, this);
|
|
142
|
-
}));
|
|
143
|
-
|
|
144
|
-
function send(_x, _x2) {
|
|
145
|
-
return _ref.apply(this, arguments);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return send;
|
|
149
|
-
}()
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Send multiple Expo push notification request.
|
|
153
|
-
*
|
|
154
|
-
* @param {Object} payload The data we need to send, the format is the same with api request body
|
|
155
|
-
* @param {Array} deviceTokens An array of devicesTokens
|
|
156
|
-
* @param {Object} options The options for the request
|
|
157
|
-
* @returns {Object} A promise which is resolved immediately
|
|
158
|
-
*/
|
|
159
|
-
|
|
160
|
-
}, {
|
|
161
|
-
key: 'sendNotifications',
|
|
162
|
-
value: function () {
|
|
163
|
-
var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(_ref3, deviceTokens) {
|
|
164
|
-
var alert = _ref3.alert,
|
|
165
|
-
body = _ref3.body,
|
|
166
|
-
payload = _objectWithoutProperties(_ref3, ['alert', 'body']);
|
|
167
|
-
|
|
168
|
-
var messages;
|
|
169
|
-
return regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
170
|
-
while (1) {
|
|
171
|
-
switch (_context2.prev = _context2.next) {
|
|
172
|
-
case 0:
|
|
173
|
-
messages = deviceTokens.map(function (token) {
|
|
174
|
-
return _extends({
|
|
175
|
-
to: token,
|
|
176
|
-
body: body || alert
|
|
177
|
-
}, payload);
|
|
178
|
-
});
|
|
179
|
-
_context2.next = 3;
|
|
180
|
-
return this.expo.sendPushNotificationsAsync(messages);
|
|
181
|
-
|
|
182
|
-
case 3:
|
|
183
|
-
return _context2.abrupt('return', _context2.sent);
|
|
184
|
-
|
|
185
|
-
case 4:
|
|
186
|
-
case 'end':
|
|
187
|
-
return _context2.stop();
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}, _callee2, this);
|
|
191
|
-
}));
|
|
192
|
-
|
|
193
|
-
function sendNotifications(_x3, _x4) {
|
|
194
|
-
return _ref2.apply(this, arguments);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
return sendNotifications;
|
|
198
|
-
}()
|
|
199
|
-
}]);
|
|
200
|
-
|
|
201
|
-
return EXPO;
|
|
202
|
-
}();
|
|
203
|
-
|
|
204
|
-
exports.default = EXPO;
|