@parse/push-adapter 6.4.0 → 6.4.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parse/push-adapter",
3
- "version": "6.4.0",
3
+ "version": "6.4.1",
4
4
  "description": "Base parse-server-push-adapter",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -8,6 +8,8 @@
8
8
  "src/"
9
9
  ],
10
10
  "scripts": {
11
+ "lint": "eslint --cache ./",
12
+ "lint:fix": "eslint --fix --cache ./",
11
13
  "test": "TESTING=1 c8 ./node_modules/.bin/jasmine"
12
14
  },
13
15
  "keywords": [
@@ -27,10 +29,11 @@
27
29
  "expo-server-sdk": "3.10.0",
28
30
  "firebase-admin": "12.1.1",
29
31
  "npmlog": "7.0.1",
30
- "parse": "5.1.0",
32
+ "parse": "5.2.0",
31
33
  "web-push": "3.6.7"
32
34
  },
33
35
  "devDependencies": {
36
+ "@eslint/js": "9.6.0",
34
37
  "@semantic-release/changelog": "6.0.3",
35
38
  "@semantic-release/commit-analyzer": "13.0.0",
36
39
  "@semantic-release/git": "10.0.1",
@@ -39,6 +42,7 @@
39
42
  "@semantic-release/release-notes-generator": "14.0.1",
40
43
  "c8": "10.1.2",
41
44
  "codecov": "3.8.0",
45
+ "eslint": "9.6.0",
42
46
  "jasmine": "5.1.0",
43
47
  "jasmine-spec-reporter": "7.0.0",
44
48
  "semantic-release": "24.0.0"
package/src/APNS.js CHANGED
@@ -39,7 +39,7 @@ export class APNS {
39
39
  }
40
40
 
41
41
  // Create Provider from each arg-object
42
- for (let apnsArgs of apnsArgsList) {
42
+ for (const apnsArgs of apnsArgsList) {
43
43
 
44
44
  // rewrite bundleId to topic for backward-compatibility
45
45
  if (apnsArgs.bundleId) {
@@ -47,7 +47,7 @@ export class APNS {
47
47
  apnsArgs.topic = apnsArgs.bundleId
48
48
  }
49
49
 
50
- let provider = APNS._createProvider(apnsArgs);
50
+ const provider = APNS._createProvider(apnsArgs);
51
51
  this.providers.push(provider);
52
52
  }
53
53
 
@@ -70,42 +70,42 @@ export class APNS {
70
70
  * @returns {Object} A promise which is resolved immediately
71
71
  */
72
72
  send(data, allDevices) {
73
- let coreData = data && data.data;
73
+ const coreData = data && data.data;
74
74
  if (!coreData || !allDevices || !Array.isArray(allDevices)) {
75
75
  log.warn(LOG_PREFIX, 'invalid push payload');
76
76
  return;
77
77
  }
78
- let expirationTime = data['expiration_time'] || coreData['expiration_time'];
79
- let collapseId = data['collapse_id'] || coreData['collapse_id'];
80
- let pushType = data['push_type'] || coreData['push_type'];
81
- let priority = data['priority'] || coreData['priority'];
78
+ const expirationTime = data['expiration_time'] || coreData['expiration_time'];
79
+ const collapseId = data['collapse_id'] || coreData['collapse_id'];
80
+ const pushType = data['push_type'] || coreData['push_type'];
81
+ const priority = data['priority'] || coreData['priority'];
82
82
  let allPromises = [];
83
83
 
84
- let devicesPerAppIdentifier = {};
84
+ const devicesPerAppIdentifier = {};
85
85
 
86
86
  // Start by clustering the devices per appIdentifier
87
87
  allDevices.forEach(device => {
88
- let appIdentifier = device.appIdentifier;
88
+ const appIdentifier = device.appIdentifier;
89
89
  devicesPerAppIdentifier[appIdentifier] = devicesPerAppIdentifier[appIdentifier] || [];
90
90
  devicesPerAppIdentifier[appIdentifier].push(device);
91
91
  });
92
92
 
93
- for (let key in devicesPerAppIdentifier) {
94
- let devices = devicesPerAppIdentifier[key];
95
- let appIdentifier = devices[0].appIdentifier;
96
- let providers = this._chooseProviders(appIdentifier);
93
+ for (const key in devicesPerAppIdentifier) {
94
+ const devices = devicesPerAppIdentifier[key];
95
+ const appIdentifier = devices[0].appIdentifier;
96
+ const providers = this._chooseProviders(appIdentifier);
97
97
 
98
98
  // No Providers found
99
99
  if (!providers || providers.length === 0) {
100
- let errorPromises = devices.map(device => APNS._createErrorPromise(device.deviceToken, 'No Provider found'));
100
+ const errorPromises = devices.map(device => APNS._createErrorPromise(device.deviceToken, 'No Provider found'));
101
101
  allPromises = allPromises.concat(errorPromises);
102
102
  continue;
103
103
  }
104
104
 
105
- let headers = { expirationTime: expirationTime, topic: appIdentifier, collapseId: collapseId, pushType: pushType, priority: priority }
106
- let notification = APNS._generateNotification(coreData, headers);
105
+ const headers = { expirationTime: expirationTime, topic: appIdentifier, collapseId: collapseId, pushType: pushType, priority: priority }
106
+ const notification = APNS._generateNotification(coreData, headers);
107
107
  const deviceIds = devices.map(device => device.deviceToken);
108
- let promise = this.sendThroughProvider(notification, deviceIds, providers);
108
+ const promise = this.sendThroughProvider(notification, deviceIds, providers);
109
109
  allPromises.push(promise.then(this._handlePromise.bind(this)));
110
110
  }
111
111
 
@@ -117,25 +117,25 @@ export class APNS {
117
117
 
118
118
  sendThroughProvider(notification, devices, providers) {
119
119
  return providers[0]
120
- .send(notification, devices)
121
- .then((response) => {
122
- if (response.failed
120
+ .send(notification, devices)
121
+ .then((response) => {
122
+ if (response.failed
123
123
  && response.failed.length > 0
124
124
  && providers && providers.length > 1) {
125
- let devices = response.failed.map((failure) => { return failure.device; });
126
- // Reset the failures as we'll try next connection
127
- response.failed = [];
128
- return this.sendThroughProvider(notification,
129
- devices,
130
- providers.slice(1, providers.length)).then((retryResponse) => {
131
- response.failed = response.failed.concat(retryResponse.failed);
132
- response.sent = response.sent.concat(retryResponse.sent);
133
- return response;
134
- });
135
- } else {
125
+ const devices = response.failed.map((failure) => { return failure.device; });
126
+ // Reset the failures as we'll try next connection
127
+ response.failed = [];
128
+ return this.sendThroughProvider(notification,
129
+ devices,
130
+ providers.slice(1, providers.length)).then((retryResponse) => {
131
+ response.failed = response.failed.concat(retryResponse.failed);
132
+ response.sent = response.sent.concat(retryResponse.sent);
136
133
  return response;
137
- }
138
- });
134
+ });
135
+ } else {
136
+ return response;
137
+ }
138
+ });
139
139
  }
140
140
 
141
141
  static _validateAPNArgs(apnsArgs) {
@@ -154,7 +154,7 @@ export class APNS {
154
154
  throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED, 'topic is mssing for %j', apnsArgs);
155
155
  }
156
156
 
157
- let provider = new apn.Provider(apnsArgs);
157
+ const provider = new apn.Provider(apnsArgs);
158
158
 
159
159
  // Sets the topic on this provider
160
160
  provider.topic = apnsArgs.topic;
@@ -176,48 +176,46 @@ export class APNS {
176
176
  * @returns {Object} A apns Notification
177
177
  */
178
178
  static _generateNotification(coreData, headers) {
179
- let notification = new apn.Notification();
180
- let payload = {};
181
- for (let key in coreData) {
179
+ const notification = new apn.Notification();
180
+ const payload = {};
181
+ for (const key in coreData) {
182
182
  switch (key) {
183
- case 'aps':
184
- notification.aps = coreData.aps;
185
- break;
186
- case 'alert':
187
- notification.setAlert(coreData.alert);
188
- break;
189
- case 'title':
190
- notification.setTitle(coreData.title);
183
+ case 'aps':
184
+ notification.aps = coreData.aps;
185
+ break;
186
+ case 'alert':
187
+ notification.setAlert(coreData.alert);
188
+ break;
189
+ case 'title':
190
+ notification.setTitle(coreData.title);
191
+ break;
192
+ case 'badge':
193
+ notification.setBadge(coreData.badge);
194
+ break;
195
+ case 'sound':
196
+ notification.setSound(coreData.sound);
197
+ break;
198
+ case 'content-available':
199
+ notification.setContentAvailable(coreData['content-available'] === 1);
200
+ break;
201
+ case 'mutable-content':
202
+ notification.setMutableContent(coreData['mutable-content'] === 1);
203
+ break;
204
+ case 'targetContentIdentifier':
205
+ notification.setTargetContentIdentifier(coreData.targetContentIdentifier);
206
+ break;
207
+ case 'interruptionLevel':
208
+ notification.setInterruptionLevel(coreData.interruptionLevel);
209
+ break;
210
+ case 'category':
211
+ notification.setCategory(coreData.category);
212
+ break;
213
+ case 'threadId':
214
+ notification.setThreadId(coreData.threadId);
215
+ break;
216
+ default:
217
+ payload[key] = coreData[key];
191
218
  break;
192
- case 'badge':
193
- notification.setBadge(coreData.badge);
194
- break;
195
- case 'sound':
196
- notification.setSound(coreData.sound);
197
- break;
198
- case 'content-available':
199
- let isAvailable = coreData['content-available'] === 1;
200
- notification.setContentAvailable(isAvailable);
201
- break;
202
- case 'mutable-content':
203
- let isMutable = coreData['mutable-content'] === 1;
204
- notification.setMutableContent(isMutable);
205
- break;
206
- case 'targetContentIdentifier':
207
- notification.setTargetContentIdentifier(coreData.targetContentIdentifier);
208
- break;
209
- case 'interruptionLevel':
210
- notification.setInterruptionLevel(coreData.interruptionLevel);
211
- break;
212
- case 'category':
213
- notification.setCategory(coreData.category);
214
- break;
215
- case 'threadId':
216
- notification.setThreadId(coreData.threadId);
217
- break;
218
- default:
219
- payload[key] = coreData[key];
220
- break;
221
219
  }
222
220
  }
223
221
 
@@ -251,7 +249,7 @@ export class APNS {
251
249
  }*/
252
250
 
253
251
  // Otherwise we try to match the appIdentifier with topic on provider
254
- let qualifiedProviders = this.providers.filter((provider) => appIdentifier === provider.topic);
252
+ const qualifiedProviders = this.providers.filter((provider) => appIdentifier === provider.topic);
255
253
 
256
254
  if (qualifiedProviders.length > 0) {
257
255
  return qualifiedProviders;
@@ -263,7 +261,7 @@ export class APNS {
263
261
  }
264
262
 
265
263
  _handlePromise(response) {
266
- let promises = [];
264
+ const promises = [];
267
265
  response.sent.forEach((token) => {
268
266
  log.verbose(LOG_PREFIX, 'APNS transmitted to %s', token.device);
269
267
  promises.push(APNS._createSuccesfullPromise(token.device));
@@ -282,8 +280,8 @@ export class APNS {
282
280
  log.error(LOG_PREFIX, 'APNS error transmitting to device %s with status %s and reason %s', failure.device, failure.status, failure.response.reason);
283
281
  return APNS._createErrorPromise(failure.device, failure.response.reason);
284
282
  } else {
285
- log.error(LOG_PREFIX, 'APNS error transmitting to device with unkown error');
286
- return APNS._createErrorPromise(failure.device, 'Unkown status');
283
+ log.error(LOG_PREFIX, 'APNS error transmitting to device with unkown error');
284
+ return APNS._createErrorPromise(failure.device, 'Unkown status');
287
285
  }
288
286
  }
289
287
 
package/src/EXPO.js CHANGED
@@ -7,19 +7,19 @@ import { Expo } from 'expo-server-sdk';
7
7
  const LOG_PREFIX = 'parse-server-push-adapter EXPO';
8
8
 
9
9
  function expoResultToParseResponse(result) {
10
- if (result.status === 'ok') {
11
- return result;
12
- } else {
13
- // ParseServer looks for "error", and supports ceratin codes like 'NotRegistered' for
14
- // cleanup. Expo returns slighyly different ones so changing to match what is expected
15
- // This can be taken out if the responsibility gets moved to the adapter itself.
16
- const error = result.message === 'DeviceNotRegistered' ?
17
- 'NotRegistered' : result.message;
18
- return {
19
- error,
20
- ...result
21
- }
10
+ if (result.status === 'ok') {
11
+ return result;
12
+ } else {
13
+ // ParseServer looks for "error", and supports ceratin codes like 'NotRegistered' for
14
+ // cleanup. Expo returns slighyly different ones so changing to match what is expected
15
+ // This can be taken out if the responsibility gets moved to the adapter itself.
16
+ const error = result.message === 'DeviceNotRegistered' ?
17
+ 'NotRegistered' : result.message;
18
+ return {
19
+ error,
20
+ ...result
22
21
  }
22
+ }
23
23
  }
24
24
 
25
25
  export class EXPO {
@@ -60,7 +60,7 @@ export class EXPO {
60
60
 
61
61
  const resolvers = [];
62
62
  const promises = deviceTokens.map(() => new Promise(resolve => resolvers.push(resolve)));
63
- let length = deviceTokens.length;
63
+ const length = deviceTokens.length;
64
64
 
65
65
  log.verbose(LOG_PREFIX, `sending to ${length} ${length > 1 ? 'devices' : 'device'}`);
66
66
 
package/src/FCM.js CHANGED
@@ -142,14 +142,14 @@ function _APNSToFCMPayload(requestData) {
142
142
  coreData = requestData.data;
143
143
  }
144
144
 
145
- let expirationTime =
145
+ const expirationTime =
146
146
  requestData['expiration_time'] || coreData['expiration_time'];
147
- let collapseId = requestData['collapse_id'] || coreData['collapse_id'];
148
- let pushType = requestData['push_type'] || coreData['push_type'];
149
- let priority = requestData['priority'] || coreData['priority'];
147
+ const collapseId = requestData['collapse_id'] || coreData['collapse_id'];
148
+ const pushType = requestData['push_type'] || coreData['push_type'];
149
+ const priority = requestData['priority'] || coreData['priority'];
150
150
 
151
- let apnsPayload = { apns: { payload: { aps: {} } } };
152
- let headers = {};
151
+ const apnsPayload = { apns: { payload: { aps: {} } } };
152
+ const headers = {};
153
153
 
154
154
  // Set to alert by default if not set explicitly
155
155
  headers['apns-push-type'] = 'alert';
@@ -172,70 +172,70 @@ function _APNSToFCMPayload(requestData) {
172
172
  apnsPayload.apns.headers = headers;
173
173
  }
174
174
 
175
- for (let key in coreData) {
175
+ for (const key in coreData) {
176
176
  switch (key) {
177
- case 'aps':
178
- apnsPayload['apns']['payload']['aps'] = coreData.aps;
179
- break;
180
- case 'alert':
181
- if (typeof coreData.alert == 'object') {
182
- // When we receive a dictionary, use as is to remain
183
- // compatible with how the APNS.js + node-apn work
184
- apnsPayload['apns']['payload']['aps']['alert'] = coreData.alert;
185
- } else {
186
- // When we receive a value, prepare `alert` dictionary
187
- // and set its `body` property
188
- apnsPayload['apns']['payload']['aps']['alert'] = {};
189
- apnsPayload['apns']['payload']['aps']['alert']['body'] = coreData.alert;
190
- }
191
- break;
192
- case 'title':
193
- // Ensure the alert object exists before trying to assign the title
194
- // title always goes into the nested `alert` dictionary
195
- if (!apnsPayload['apns']['payload']['aps'].hasOwnProperty('alert')) {
196
- apnsPayload['apns']['payload']['aps']['alert'] = {};
197
- }
198
- apnsPayload['apns']['payload']['aps']['alert']['title'] = coreData.title;
199
- break;
200
- case 'badge':
201
- apnsPayload['apns']['payload']['aps']['badge'] = coreData.badge;
202
- break;
203
- case 'sound':
204
- apnsPayload['apns']['payload']['aps']['sound'] = coreData.sound;
205
- break;
206
- case 'content-available':
207
- apnsPayload['apns']['payload']['aps']['content-available'] =
177
+ case 'aps':
178
+ apnsPayload['apns']['payload']['aps'] = coreData.aps;
179
+ break;
180
+ case 'alert':
181
+ if (typeof coreData.alert == 'object') {
182
+ // When we receive a dictionary, use as is to remain
183
+ // compatible with how the APNS.js + node-apn work
184
+ apnsPayload['apns']['payload']['aps']['alert'] = coreData.alert;
185
+ } else {
186
+ // When we receive a value, prepare `alert` dictionary
187
+ // and set its `body` property
188
+ apnsPayload['apns']['payload']['aps']['alert'] = {};
189
+ apnsPayload['apns']['payload']['aps']['alert']['body'] = coreData.alert;
190
+ }
191
+ break;
192
+ case 'title':
193
+ // Ensure the alert object exists before trying to assign the title
194
+ // title always goes into the nested `alert` dictionary
195
+ if (!apnsPayload['apns']['payload']['aps'].hasOwnProperty('alert')) {
196
+ apnsPayload['apns']['payload']['aps']['alert'] = {};
197
+ }
198
+ apnsPayload['apns']['payload']['aps']['alert']['title'] = coreData.title;
199
+ break;
200
+ case 'badge':
201
+ apnsPayload['apns']['payload']['aps']['badge'] = coreData.badge;
202
+ break;
203
+ case 'sound':
204
+ apnsPayload['apns']['payload']['aps']['sound'] = coreData.sound;
205
+ break;
206
+ case 'content-available':
207
+ apnsPayload['apns']['payload']['aps']['content-available'] =
208
208
  coreData['content-available'];
209
- break;
210
- case 'mutable-content':
211
- apnsPayload['apns']['payload']['aps']['mutable-content'] =
209
+ break;
210
+ case 'mutable-content':
211
+ apnsPayload['apns']['payload']['aps']['mutable-content'] =
212
212
  coreData['mutable-content'];
213
- break;
214
- case 'targetContentIdentifier':
215
- apnsPayload['apns']['payload']['aps']['target-content-id'] =
213
+ break;
214
+ case 'targetContentIdentifier':
215
+ apnsPayload['apns']['payload']['aps']['target-content-id'] =
216
216
  coreData.targetContentIdentifier;
217
- break;
218
- case 'interruptionLevel':
219
- apnsPayload['apns']['payload']['aps']['interruption-level'] =
217
+ break;
218
+ case 'interruptionLevel':
219
+ apnsPayload['apns']['payload']['aps']['interruption-level'] =
220
220
  coreData.interruptionLevel;
221
- break;
222
- case 'category':
223
- apnsPayload['apns']['payload']['aps']['category'] = coreData.category;
224
- break;
225
- case 'threadId':
226
- apnsPayload['apns']['payload']['aps']['thread-id'] = coreData.threadId;
227
- break;
228
- case 'expiration_time': // Exclude header-related fields as these are set above
229
- break;
230
- case 'collapse_id':
231
- break;
232
- case 'push_type':
233
- break;
234
- case 'priority':
235
- break;
236
- default:
237
- apnsPayload['apns']['payload'][key] = coreData[key]; // Custom keys should be outside aps
238
- break;
221
+ break;
222
+ case 'category':
223
+ apnsPayload['apns']['payload']['aps']['category'] = coreData.category;
224
+ break;
225
+ case 'threadId':
226
+ apnsPayload['apns']['payload']['aps']['thread-id'] = coreData.threadId;
227
+ break;
228
+ case 'expiration_time': // Exclude header-related fields as these are set above
229
+ break;
230
+ case 'collapse_id':
231
+ break;
232
+ case 'push_type':
233
+ break;
234
+ case 'priority':
235
+ break;
236
+ default:
237
+ apnsPayload['apns']['payload'][key] = coreData[key]; // Custom keys should be outside aps
238
+ break;
239
239
  }
240
240
  }
241
241
  return apnsPayload;
package/src/GCM.js CHANGED
@@ -12,7 +12,7 @@ const GCMRegistrationTokensMax = 1000;
12
12
  export default function GCM(args) {
13
13
  if (typeof args !== 'object' || !args.apiKey) {
14
14
  throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
15
- 'GCM Configuration is invalid');
15
+ 'GCM Configuration is invalid');
16
16
  }
17
17
  this.sender = new gcm.Sender(args.apiKey, args.requestOptions);
18
18
  }
@@ -30,23 +30,23 @@ GCM.prototype.send = function(data, devices) {
30
30
  log.warn(LOG_PREFIX, 'invalid push payload');
31
31
  return;
32
32
  }
33
- let pushId = randomString(10);
33
+ const pushId = randomString(10);
34
34
  // Make a new array
35
- devices=devices.slice(0);
36
- let timestamp = Date.now();
35
+ devices = devices.slice(0);
36
+ const timestamp = Date.now();
37
37
  // For android, we can only have 1000 recepients per send, so we need to slice devices to
38
38
  // chunk if necessary
39
- let slices = sliceDevices(devices, GCM.GCMRegistrationTokensMax);
39
+ const slices = sliceDevices(devices, GCM.GCMRegistrationTokensMax);
40
40
  if (slices.length > 1) {
41
41
  log.verbose(LOG_PREFIX, `the number of devices exceeds ${GCMRegistrationTokensMax}`);
42
42
  // Make 1 send per slice
43
- let promises = slices.reduce((memo, slice) => {
44
- let promise = this.send(data, slice, timestamp);
43
+ const promises = slices.reduce((memo, slice) => {
44
+ const promise = this.send(data, slice, timestamp);
45
45
  memo.push(promise);
46
46
  return memo;
47
47
  }, [])
48
- return Promise.all(promises).then((results) => {
49
- let allResults = results.reduce((memo, result) => {
48
+ return Promise.all(promises).then((results) => {
49
+ const allResults = results.reduce((memo, result) => {
50
50
  return memo.concat(result);
51
51
  }, []);
52
52
  return Promise.resolve(allResults);
@@ -63,23 +63,23 @@ GCM.prototype.send = function(data, devices) {
63
63
  }
64
64
  // Generate gcm payload
65
65
  // PushId is not a formal field of GCM, but Parse Android SDK uses this field to deduplicate push notifications
66
- let gcmPayload = generateGCMPayload(data, pushId, timestamp, expirationTime);
66
+ const gcmPayload = generateGCMPayload(data, pushId, timestamp, expirationTime);
67
67
  // Make and send gcm request
68
- let message = new gcm.Message(gcmPayload);
68
+ const message = new gcm.Message(gcmPayload);
69
69
 
70
70
  // Build a device map
71
- let devicesMap = devices.reduce((memo, device) => {
71
+ const devicesMap = devices.reduce((memo, device) => {
72
72
  memo[device.deviceToken] = device;
73
73
  return memo;
74
74
  }, {});
75
75
 
76
- let deviceTokens = Object.keys(devicesMap);
76
+ const deviceTokens = Object.keys(devicesMap);
77
77
 
78
78
  const resolvers = [];
79
- const promises = deviceTokens.map(() => new Promise(resolve => resolvers.push(resolve)));
80
- let registrationTokens = deviceTokens;
81
- let length = registrationTokens.length;
82
- log.verbose(LOG_PREFIX, `sending to ${length} ${length > 1 ? 'devices' : 'device'}`);
79
+ const promises = deviceTokens.map(() => new Promise(resolve => resolvers.push(resolve)));
80
+ const registrationTokens = deviceTokens;
81
+ const length = registrationTokens.length;
82
+ log.verbose(LOG_PREFIX, `sending to ${length} ${length > 1 ? 'devices' : 'device'}`);
83
83
  this.sender.send(message, { registrationTokens: registrationTokens }, 5, (error, response) => {
84
84
  // example response:
85
85
  /*
@@ -97,13 +97,13 @@ GCM.prototype.send = function(data, devices) {
97
97
  } else {
98
98
  log.verbose(LOG_PREFIX, `GCM Response: %s`, JSON.stringify(response, null, 4));
99
99
  }
100
- let { results, multicast_id } = response || {};
100
+ const { results, multicast_id } = response || {};
101
101
  registrationTokens.forEach((token, index) => {
102
- let resolve = resolvers[index];
103
- let result = results ? results[index] : undefined;
104
- let device = devicesMap[token];
102
+ const resolve = resolvers[index];
103
+ const result = results ? results[index] : undefined;
104
+ const device = devicesMap[token];
105
105
  device.deviceType = 'android';
106
- let resolution = {
106
+ const resolution = {
107
107
  device,
108
108
  multicast_id,
109
109
  response: error || result,
@@ -128,7 +128,7 @@ GCM.prototype.send = function(data, devices) {
128
128
  * @returns {Object} A promise which is resolved after we get results from gcm
129
129
  */
130
130
  function generateGCMPayload(requestData, pushId, timeStamp, expirationTime) {
131
- let payload = {
131
+ const payload = {
132
132
  priority: 'high'
133
133
  };
134
134
  payload.data = {
@@ -144,7 +144,7 @@ function generateGCMPayload(requestData, pushId, timeStamp, expirationTime) {
144
144
  });
145
145
 
146
146
  if (expirationTime) {
147
- // The timeStamp and expiration is in milliseconds but gcm requires second
147
+ // The timeStamp and expiration is in milliseconds but gcm requires second
148
148
  let timeToLive = Math.floor((expirationTime - timeStamp) / 1000);
149
149
  if (timeToLive < 0) {
150
150
  timeToLive = 0;
@@ -164,7 +164,7 @@ function generateGCMPayload(requestData, pushId, timeStamp, expirationTime) {
164
164
  * @returns {Array} An array which contaisn several arries of devices with fixed chunk size
165
165
  */
166
166
  function sliceDevices(devices, chunkSize) {
167
- let chunkDevices = [];
167
+ const chunkDevices = [];
168
168
  while (devices.length > 0) {
169
169
  chunkDevices.push(devices.splice(0, chunkSize));
170
170
  }
@@ -21,38 +21,38 @@ export default class ParsePushAdapter {
21
21
  this.feature = {
22
22
  immediatePush: true
23
23
  };
24
- let pushTypes = Object.keys(pushConfig);
24
+ const pushTypes = Object.keys(pushConfig);
25
25
 
26
- for (let pushType of pushTypes) {
26
+ for (const pushType of pushTypes) {
27
27
  // adapter may be passed as part of the parse-server initialization
28
28
  if (this.validPushTypes.indexOf(pushType) < 0 && pushType != 'adapter') {
29
29
  throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
30
- 'Push to ' + pushType + ' is not supported');
30
+ 'Push to ' + pushType + ' is not supported');
31
31
  }
32
32
  switch (pushType) {
33
- case 'ios':
34
- case 'tvos':
35
- case 'osx':
36
- if (pushConfig[pushType].hasOwnProperty('firebaseServiceAccount')) {
37
- this.senderMap[pushType] = new FCM(pushConfig[pushType], 'apple');
38
- } else {
39
- this.senderMap[pushType] = new APNS(pushConfig[pushType]);
40
- }
41
- break;
42
- case 'web':
43
- this.senderMap[pushType] = new WEB(pushConfig[pushType]);
44
- break;
45
- case 'expo':
46
- this.senderMap[pushType] = new EXPO(pushConfig[pushType]);
47
- break;
48
- case 'android':
49
- case 'fcm':
50
- if (pushConfig[pushType].hasOwnProperty('firebaseServiceAccount')) {
51
- this.senderMap[pushType] = new FCM(pushConfig[pushType], 'android');
52
- } else {
53
- this.senderMap[pushType] = new GCM(pushConfig[pushType]);
54
- }
55
- break;
33
+ case 'ios':
34
+ case 'tvos':
35
+ case 'osx':
36
+ if (pushConfig[pushType].hasOwnProperty('firebaseServiceAccount')) {
37
+ this.senderMap[pushType] = new FCM(pushConfig[pushType], 'apple');
38
+ } else {
39
+ this.senderMap[pushType] = new APNS(pushConfig[pushType]);
40
+ }
41
+ break;
42
+ case 'web':
43
+ this.senderMap[pushType] = new WEB(pushConfig[pushType]);
44
+ break;
45
+ case 'expo':
46
+ this.senderMap[pushType] = new EXPO(pushConfig[pushType]);
47
+ break;
48
+ case 'android':
49
+ case 'fcm':
50
+ if (pushConfig[pushType].hasOwnProperty('firebaseServiceAccount')) {
51
+ this.senderMap[pushType] = new FCM(pushConfig[pushType], 'android');
52
+ } else {
53
+ this.senderMap[pushType] = new GCM(pushConfig[pushType]);
54
+ }
55
+ break;
56
56
  }
57
57
  }
58
58
  }
@@ -66,16 +66,16 @@ export default class ParsePushAdapter {
66
66
  }
67
67
 
68
68
  send(data, installations) {
69
- let deviceMap = classifyInstallations(installations, this.validPushTypes);
70
- let sendPromises = [];
71
- for (let pushType in deviceMap) {
72
- let sender = this.senderMap[pushType];
73
- let devices = deviceMap[pushType];
69
+ const deviceMap = classifyInstallations(installations, this.validPushTypes);
70
+ const sendPromises = [];
71
+ for (const pushType in deviceMap) {
72
+ const sender = this.senderMap[pushType];
73
+ const devices = deviceMap[pushType];
74
74
 
75
75
  if(Array.isArray(devices) && devices.length > 0) {
76
76
  if (!sender) {
77
77
  log.verbose(LOG_PREFIX, `Can not find sender for push type ${pushType}, ${data}`)
78
- let results = devices.map((device) => {
78
+ const results = devices.map((device) => {
79
79
  return Promise.resolve({
80
80
  device,
81
81
  transmitted: false,
@@ -88,7 +88,7 @@ export default class ParsePushAdapter {
88
88
  }
89
89
  }
90
90
  }
91
- return Promise.all(sendPromises).then((promises) => {
91
+ return Promise.all(sendPromises).then((promises) => {
92
92
  // flatten all
93
93
  return [].concat.apply([], promises);
94
94
  })
@@ -8,16 +8,16 @@ import { randomBytes } from 'crypto';
8
8
  */
9
9
  export function classifyInstallations(installations, validPushTypes) {
10
10
  // Init deviceTokenMap, create a empty array for each valid pushType
11
- let deviceMap = {};
12
- for (let validPushType of validPushTypes) {
11
+ const deviceMap = {};
12
+ for (const validPushType of validPushTypes) {
13
13
  deviceMap[validPushType] = [];
14
14
  }
15
- for (let installation of installations) {
15
+ for (const installation of installations) {
16
16
  // No deviceToken, ignore
17
17
  if (!installation.deviceToken) {
18
18
  continue;
19
19
  }
20
- let devices = deviceMap[installation.pushType] || deviceMap[installation.deviceType] || null;
20
+ const devices = deviceMap[installation.pushType] || deviceMap[installation.deviceType] || null;
21
21
  if (Array.isArray(devices)) {
22
22
  devices.push({
23
23
  deviceToken: installation.deviceToken,
@@ -33,11 +33,11 @@ export function randomString(size) {
33
33
  if (size === 0) {
34
34
  throw new Error('Zero-length randomString is useless.');
35
35
  }
36
- let chars = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
36
+ const chars = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
37
37
  'abcdefghijklmnopqrstuvwxyz' +
38
38
  '0123456789');
39
39
  let objectId = '';
40
- let bytes = randomBytes(size);
40
+ const bytes = randomBytes(size);
41
41
  for (let i = 0; i < bytes.length; ++i) {
42
42
  objectId += chars[bytes.readUInt8(i) % chars.length];
43
43
  }
package/src/WEB.js CHANGED
@@ -9,7 +9,7 @@ const LOG_PREFIX = 'parse-server-push-adapter WEB';
9
9
  export class WEB {
10
10
  /**
11
11
  * Create a new WEB push adapter.
12
- *
12
+ *
13
13
  * @param {Object} args https://github.com/web-push-libs/web-push#api-reference
14
14
  */
15
15
  constructor(args) {
@@ -39,9 +39,9 @@ export class WEB {
39
39
  const deviceTokens = Object.keys(devicesMap);
40
40
 
41
41
  const resolvers = [];
42
- const promises = deviceTokens.map(() => new Promise(resolve => resolvers.push(resolve)));
43
- let length = deviceTokens.length;
44
- log.verbose(LOG_PREFIX, `sending to ${length} ${length > 1 ? 'devices' : 'device'}`);
42
+ const promises = deviceTokens.map(() => new Promise(resolve => resolvers.push(resolve)));
43
+ const length = deviceTokens.length;
44
+ log.verbose(LOG_PREFIX, `sending to ${length} ${length > 1 ? 'devices' : 'device'}`);
45
45
 
46
46
  const response = await WEB.sendNotifications(coreData, deviceTokens, this.options);
47
47
  const { results, sent, failed } = response;
package/src/index.js CHANGED
@@ -3,11 +3,13 @@
3
3
  // PushAdapter, it uses GCM for android push, APNS for ios push.
4
4
  // WEB for web push.
5
5
  import log from 'npmlog';
6
+ import { booleanParser } from './utils.js';
6
7
 
7
- /* istanbul ignore if */
8
- if (process.env.VERBOSE || process.env.VERBOSE_PARSE_SERVER_PUSH_ADAPTER) {
8
+ /* c8 ignore start */
9
+ if (booleanParser(process.env.VERBOSE || process.env.VERBOSE_PARSE_SERVER_PUSH_ADAPTER)) {
9
10
  log.level = 'verbose';
10
11
  }
12
+ /* c8 ignore stop */
11
13
 
12
14
  import ParsePushAdapter from './ParsePushAdapter.js';
13
15
  import GCM from './GCM.js';
package/src/utils.js ADDED
@@ -0,0 +1,10 @@
1
+ function booleanParser(opt) {
2
+ if (opt == true || opt == 'true' || opt == '1') {
3
+ return true;
4
+ }
5
+ return false;
6
+ }
7
+
8
+ export {
9
+ booleanParser,
10
+ }