@parse/push-adapter 6.1.1 → 6.2.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 +21 -4
- package/lib/EXPO.js +204 -0
- package/lib/ParsePushAdapter.js +8 -1
- package/lib/index.js +6 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -20,6 +20,7 @@ The official Push Notification adapter for Parse Server. See [Parse Server Push
|
|
|
20
20
|
- [Using a Custom Version on Parse Server](#using-a-custom-version-on-parse-server)
|
|
21
21
|
- [Install Push Adapter](#install-push-adapter)
|
|
22
22
|
- [Configure Parse Server](#configure-parse-server)
|
|
23
|
+
- [Expo Push Options](#expo-push-options)
|
|
23
24
|
|
|
24
25
|
# Silent Notifications
|
|
25
26
|
|
|
@@ -57,16 +58,32 @@ const parseServerOptions = {
|
|
|
57
58
|
push: {
|
|
58
59
|
adapter: new PushAdapter({
|
|
59
60
|
ios: {
|
|
60
|
-
/* Apple push
|
|
61
|
+
/* Apple push options */
|
|
61
62
|
},
|
|
62
63
|
android: {
|
|
63
64
|
/* Android push options */
|
|
64
|
-
}
|
|
65
|
+
},
|
|
65
66
|
web: {
|
|
66
67
|
/* Web push options */
|
|
67
|
-
}
|
|
68
|
-
|
|
68
|
+
},
|
|
69
|
+
expo: {
|
|
70
|
+
/* Expo push options */
|
|
71
|
+
},
|
|
72
|
+
}),
|
|
69
73
|
},
|
|
70
74
|
/* Other Parse Server options */
|
|
71
75
|
}
|
|
72
76
|
```
|
|
77
|
+
|
|
78
|
+
### Expo Push Options
|
|
79
|
+
|
|
80
|
+
Example options:
|
|
81
|
+
|
|
82
|
+
```js
|
|
83
|
+
expo: {
|
|
84
|
+
accessToken: '<EXPO_ACCESS_TOKEN>',
|
|
85
|
+
},
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
For more information see the [Expo docs](https://docs.expo.dev/push-notifications/overview/).
|
|
89
|
+
|
package/lib/EXPO.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
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;
|
package/lib/ParsePushAdapter.js
CHANGED
|
@@ -30,6 +30,10 @@ var _WEB = require('./WEB');
|
|
|
30
30
|
|
|
31
31
|
var _WEB2 = _interopRequireDefault(_WEB);
|
|
32
32
|
|
|
33
|
+
var _EXPO = require('./EXPO');
|
|
34
|
+
|
|
35
|
+
var _EXPO2 = _interopRequireDefault(_EXPO);
|
|
36
|
+
|
|
33
37
|
var _PushAdapterUtils = require('./PushAdapterUtils');
|
|
34
38
|
|
|
35
39
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -46,7 +50,7 @@ var ParsePushAdapter = function () {
|
|
|
46
50
|
|
|
47
51
|
this.supportsPushTracking = true;
|
|
48
52
|
|
|
49
|
-
this.validPushTypes = ['ios', 'osx', 'tvos', 'android', 'fcm', 'web'];
|
|
53
|
+
this.validPushTypes = ['ios', 'osx', 'tvos', 'android', 'fcm', 'web', 'expo'];
|
|
50
54
|
this.senderMap = {};
|
|
51
55
|
// used in PushController for Dashboard Features
|
|
52
56
|
this.feature = {
|
|
@@ -79,6 +83,9 @@ var ParsePushAdapter = function () {
|
|
|
79
83
|
case 'web':
|
|
80
84
|
this.senderMap[pushType] = new _WEB2.default(pushConfig[pushType]);
|
|
81
85
|
break;
|
|
86
|
+
case 'expo':
|
|
87
|
+
this.senderMap[pushType] = new _EXPO2.default(pushConfig[pushType]);
|
|
88
|
+
break;
|
|
82
89
|
case 'android':
|
|
83
90
|
case 'fcm':
|
|
84
91
|
if (pushConfig[pushType].hasOwnProperty('firebaseServiceAccount')) {
|
package/lib/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", {
|
|
7
7
|
value: true
|
|
8
8
|
});
|
|
9
|
-
exports.utils = exports.WEB = exports.GCM = exports.APNS = exports.ParsePushAdapter = undefined;
|
|
9
|
+
exports.utils = exports.EXPO = exports.WEB = exports.GCM = exports.APNS = exports.ParsePushAdapter = undefined;
|
|
10
10
|
|
|
11
11
|
var _npmlog = require('npmlog');
|
|
12
12
|
|
|
@@ -28,6 +28,10 @@ var _WEB = require('./WEB');
|
|
|
28
28
|
|
|
29
29
|
var _WEB2 = _interopRequireDefault(_WEB);
|
|
30
30
|
|
|
31
|
+
var _EXPO = require('./EXPO');
|
|
32
|
+
|
|
33
|
+
var _EXPO2 = _interopRequireDefault(_EXPO);
|
|
34
|
+
|
|
31
35
|
var _PushAdapterUtils = require('./PushAdapterUtils');
|
|
32
36
|
|
|
33
37
|
var utils = _interopRequireWildcard(_PushAdapterUtils);
|
|
@@ -44,4 +48,5 @@ exports.ParsePushAdapter = _ParsePushAdapter2.default;
|
|
|
44
48
|
exports.APNS = _APNS2.default;
|
|
45
49
|
exports.GCM = _GCM2.default;
|
|
46
50
|
exports.WEB = _WEB2.default;
|
|
51
|
+
exports.EXPO = _EXPO2.default;
|
|
47
52
|
exports.utils = utils;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parse/push-adapter",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.2.0",
|
|
4
4
|
"description": "Base parse-server-push-adapter",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"files": [
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@parse/node-apn": "6.0.1",
|
|
27
27
|
"@parse/node-gcm": "1.0.2",
|
|
28
|
+
"expo-server-sdk": "3.10.0",
|
|
28
29
|
"firebase-admin": "12.1.0",
|
|
29
30
|
"npmlog": "7.0.1",
|
|
30
31
|
"parse": "5.0.0",
|