
Research
2025 Report: Destructive Malware in Open Source Packages
Destructive malware is rising across open source registries, using delays and kill switches to wipe code, break builds, and disrupt CI/CD.
node-pushnotifications
Advanced tools
A node.js module for interfacing with Apple Push Notification, Google Cloud Messaging, Windows Push Notification and Amazon Device Messaging services.
NOTE: Version 1.x has completely been redesigned to be compatible with new apn 2.x.
npm install node-pushnotifications --save
const settings = {
gcm: {
id: null,
...
},
apn: {
cert: 'cert.pem',
key: 'key.pem',
...
},
adm: {
client_id: null,
client_secret: null,
...
},
wns: {
client_id: null,
client_secret: null,
notificationMethod: 'sendTileSquareBlock',
...
}
};
const PushNotifications = new require('node-pushnotifications');
const push = new PushNotifications(settings);
iOS: It is recomended to use provider authentication tokens. However, you can also use certificates. See node-apn to see how to prepare cert.pem and key.pem.
### 2. Define destination device ID. You can send to multiple devices, independently of platform, creating an array with different destination device IDs.
// Single destination
const registrationIds = 'INSERT_YOUR_DEVICE_ID';
// Multiple destinations
const registrationIds = [];
registrationIds.push('INSERT_YOUR_DEVICE_ID');
registrationIds.push('INSERT_OTHER_DEVICE_ID');
Both title and body fields are required (or alert for ios). The other fields are optional (see how message is created for each device type for additional info):
const data = {
title: 'New push notification', // REQUIRED
body: 'Powered by AppFeel', // REQUIRED
custom: {
sender: 'AppFeel',
},
priority: 1, // gcm, apn
collapseKey: '', // gcm for android
contentAvailable: true, // gcm for android
delayWhileIdle: true, // gcm for android
restrictedPackageName: '', // gcm for android
dryRun: false, // gcm for android
icon: '', // gcm for android
tag: '', // gcm for android
color: '', // gcm for android
clickAction: '', // gcm for android. In ios, category will be used if not supplied
locKey: '', // gcm, apn
bodyLocArgs: '', // gcm, apn
titleLocKey: '', // gcm, apn
titleLocArgs: '', // gcm, apn
retries: 1, // apn
encoding: '', // apn
badge: 2, // gcm for ios, apn
sound: 'ping.aiff', // gcm, apn
alert: {}, // apn, will take precedence over title and body
titleLocKey: '', // apn and gcm for ios
titleLocArgs: '', // apn and gcm for ios
launchImage: '', // apn and gcm for ios
action: '', // apn and gcm for ios
topic: '', // apn and gcm for ios
category: '', // apn and gcm for ios
contentAvailable: '', // apn and gcm for ios
mdm: '', // apn and gcm for ios
urlArgs: '', // apn and gcm for ios
truncateAtWordEnd: true, // apn and gcm for ios
expiry: ,
timeToLive: 28 * 86400, // if both expiry and timeToLive are given, expiry will take precedency
headers: [], // wns
launch: '', // wns
duration: '', // wns
consolidationKey: 'my notification', // ADM
};
push.send(registrationIds, data, (err, result) => {
if (err) {
console.log(err);
} else {
console.log(result);
}
});
// Or you could use it as a promise:
push.send(registrationIds, data)
.then((results) => { ... })
.catch((err) => { ... });
err will be null if all went fine, will return the error otherwise.result will contain an array with the following objects:[
{
method: 'gcm', // The method used send notifications and which this info is related to
multicastId: [], // (only Android) Array with unique ID (number) identifying the multicast message, one identifier for each chunk of 1.000 notifications)
success: 0, // Number of notifications that have been successfully sent. It does not mean that the notification has been deliveried.
failure: 0, // Number of notifications that have been failed to be send.
message: [{
messageId: '', // (only for android) String specifying a unique ID for each successfully processed message or undefined if error
regId: value, // The registrationId (device token id)
error: new Error('unknown'), // If any, there will be an Error object here
}],
},
{
method: 'apn',
... // Same structure here
},
...
]
NOTE If you provide more than 1.000 registration tokens, they will automatically be splitted in 1.000 chunks (see this issue in gcm repo) The following parameters are used to create a GCM message. See https://developers.google.com/cloud-messaging/http-server-ref#table5 for more info:
{
collapseKey: data.collapseKey,
priority: data.priority,
contentAvailable: data.contentAvailable || false,
delayWhileIdle: data.delayWhileIdle || false, // Deprecated from Nov 15th 2016 (will be ignored)
timeToLive: data.expiry - Math.floor(Date.now() / 1000) || data.timeToLive || 28 * 86400,
restrictedPackageName: data.restrictedPackageName,
dryRun: data.dryRun || false,
data: data.custom,
notification: {
title: data.title, // Android, iOS (Watch)
body: data.body, // Android, iOS
icon: data.icon, // Android
sound: data.sound, // Android, iOS
badge: data.badge, // iOS
tag: data.tag, // Android
color: data.color, // Android
click_action: data.clickAction || data.category, // Android, iOS
body_loc_key: data.locKey, // Android, iOS
body_loc_args: data.locArgs, // Android, iOS
title_loc_key: data.titleLocKey, // Android, iOS
title_loc_args: data.titleLocArgs, // Android, iOS
},
}
data is the parameter in push.send(registrationIds, data)
The following parameters are used to create an APN message:
{
retryLimit: data.retries || -1,
expiry: data.expiry || ((data.timeToLive || 28 * 86400) + Math.floor(Date.now() / 1000)),
priority: data.priority,
encoding: data.encoding,
payload: data.custom,
badge: data.badge,
sound: data.sound || 'ping.aiff',
alert: data.alert || {
title: data.title,
body: data.body,
'title-loc-key': data.titleLocKey,
'title-loc-args': data.titleLocArgs,
'loc-key': data.locKey,
'loc-args': data.locArgs,
'launch-image': data.launchImage,
action: data.action,
},
topic: data.topic || '',
category: data.category || data.clickAction,
contentAvailable: data.contentAvailable,
mdm: data.mdm,
urlArgs: data.urlArgs,
truncateAtWordEnd: data.truncateAtWordEnd,
}
data is the parameter in push.send(registrationIds, data)
The following parameters are used to create an ADM message:
const data = Object.assign({}, _data); // _data is the data passed as method parameter
const consolidationKey = data.consolidationKey;
const expiry = data.expiry;
const timeToLive = data.timeToLive;
delete data.consolidationKey;
delete data.expiry;
delete data.timeToLive;
const ADMmesssage = {
expiresAfter: expiry - Math.floor(Date.now() / 1000) || timeToLive || 28 * 86400,
consolidationKey,
data,
};
data is the parameter in push.send(registrationIds, data)
The following fields are used to create a WNS message:
const notificationMethod = settings.wns.notificationMethod;
const opts = Object.assign({}, settings.wns);
opts.headers = data.headers || opts.headers;
opts.launch = data.launch || opts.launch;
opts.duration = data.duration || opts.duration;
delete opts.notificationMethod;
delete data.headers;
delete data.launch;
delete data.duration;
wns[notificationMethod](regId, data, opts, (err, response) => { ... });
data is the parameter in push.send(registrationIds, data)
data.accessToken is supplied then each push notification will be sent after the previous one has been responded. This is due to the fact that in the response while sending a push notification it is possible that Microsoft servers responds with a new accessToken and it should be used for next requests. This can slow down the whole process.The MIT License (MIT)
Copyright (c) 2016 AppFeel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
FAQs
A cross-platform push service for node.js
The npm package node-pushnotifications receives a total of 8,712 weekly downloads. As such, node-pushnotifications popularity was classified as popular.
We found that node-pushnotifications demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
Destructive malware is rising across open source registries, using delays and kill switches to wipe code, break builds, and disrupt CI/CD.

Security News
Socket CTO Ahmad Nassri shares practical AI coding techniques, tools, and team workflows, plus what still feels noisy and why shipping remains human-led.

Research
/Security News
A five-month operation turned 27 npm packages into durable hosting for browser-run lures that mimic document-sharing portals and Microsoft sign-in, targeting 25 organizations across manufacturing, industrial automation, plastics, and healthcare for credential theft.