The official Push Notification adapter for Parse Server. See Parse Server Push Configuration for more details.
npm install --save @parse/push-adapter@<VERSION>Replace <VERSION> with the version you want to install.
import { ParsePushAdapter } from '@parse/push-adapter';
// For CommonJS replace the import statemtent above with the following line:
// const ParsePushAdapter = require('@parse/push-adapter').default;
const parseServerOptions = {
push: {
adapter: new ParsePushAdapter({
ios: {
// Apple push options
},
android: {
// Android push options
},
web: {
// Web push options
},
expo: {
// Expo push options
}
})
}
// Other Parse Server options
};Parse Server Push Adapter currently supports these types of Apple ecosystems:
ios: iPhone, iPad, and iPod touch appsosx: macOS, and macCatalyst appstvos: tvOS appswatchos: watchOS apps
Push notifications can be delivered to Apple devices either via Apple Push Notification Service (APNS) or Firebase Cloud Messaging (FMC). Note that each category of Apple devices requires their own configuration section:
- APNS requires a private key that can be downloaded from the Apple Developer Center at https://developer.apple.com/account under Certificates > Identifiers & Profiles. The adapter options also require the app ID and team ID, which can be found there.
- FCM requires a private key that can be downloaded from the Firebase Console at https://console.firebase.google.com in your project under Settings > Cloud Messaging.
Example options:
Both services (APNS, FCM) can be used in combination for different Apple ecosystems.
ios: {
// Deliver push notifications to iOS devices via APNS
token: {
key: __dirname + '/apns.p8',
keyId: '<APNS_KEY_ID>',
teamId: '<APNS_TEAM_ID>'
},
topic: '<BUNDLE_IDENTIFIER>',
production: true
},
osx: {
// Deliver push notifications to macOS devices via FCM
firebaseServiceAccount: __dirname + '/firebase.json'
}Delivering push notifications to Android devices can be done via Firebase Cloud Messaging (FCM):
- FCM requires a private key that can be downloaded from the Firebase Console at https://console.firebase.google.com in your project under Settings > Cloud Messaging.
Example options:
android: {
firebaseServiceAccount: __dirname + '/firebase.json'
}This section contains some considerations when using FCM, regardless of the destination ecosystems the push notification is sent to.
The Firebase console allows to easily create and download a Google Cloud service account key JSON file with the required permissions. Instead of setting firebaseServiceAccount to the path of the JSON file, you can provide an object representing a Google Cloud service account key:
android: {
firebaseServiceAccount: {
projectId: '<PROJECT_ID>',
clientEmail: 'example@<PROJECT_ID>.iam.gserviceaccount.com',
privateKey: '-----BEGIN PRIVATE KEY-----<KEY>-----END PRIVATE KEY-----\n'
}
}This can be helpful if you are already managing credentials to Google Cloud APIs in other parts of your code and you want to reuse these credentials, or if you want to manage credentials on a more granular level directly in Google Cloud. Make sure that the service account has the permission cloudmessaging.messages.create which is for example part of role Firebase Cloud Messaging API Admin.
apiKey with firebaseServiceAccount.
Example options (deprecated):
android: {
// Deliver push notifications via FCM legacy API (deprecated)
apiKey: '<API_KEY>'
}With the introduction of the FCM HTTP v1 API, support for HTTP/2 was added which provides faster throughput for push notifications. To use the older version HTTP/1.1 set fcmEnableLegacyHttpTransport: true in your push options.
Example options:
android: {
firebaseServiceAccount: __dirname + '/firebase.json',
fcmEnableLegacyHttpTransport: true
}Occasionally, errors within the Firebase Cloud Messaging (FCM) client may not be managed internally and are instead passed to the Parse Server Push Adapter. These errors can occur, for instance, due to unhandled FCM server connection issues.
resolveUnhandledClientError: true: Logs the error and gracefully resolves it, ensuring that push sending does not result in a failure.resolveUnhandledClientError: false: Causes push sending to fail, returning aParse.Error.OTHER_CAUSEwith error details that can be parsed to handle it accordingly. This is the default.
In both cases, detailed error logs are recorded in the Parse Server logs for debugging purposes.
Example options:
expo: {
accessToken: '<EXPO_ACCESS_TOKEN>'
}For more information see the Expo docs.
By default, pushes are sent as fast as possible. However, push providers usually throttle their APIs, so that sending too many pushes notifications within a short time may cause the API to reject requests. To address this, push sending can be throttled per provider by adding the queue option to the respective push configuration.
| Parameter | Default | Optional | Description |
|---|---|---|---|
queue.concurrency |
Infinity |
Yes | The maximum number of pushes to process concurrently. |
queue.intervalCapacity |
Infinity |
Yes | The interval capacity, meaning the maximum number of tasks to process in a given interval. |
queue.interval |
0 |
Yes | The interval in milliseconds for the interval capacity. |
Example configuration to throttle the queue to max. 1 push every 100ms, equivalent to max. 10 pushes per second:
const parseServerOptions = {
push: {
adapter: new ParsePushAdapter({
ios: {
// ...
queue: {
concurrency: 1,
intervalCapacity: 1,
interval: 100,
},
}
})
}
};Keep in mind that concurrency: 1 means that pushes are sent in serial. For example, if sending a request to the push provider takes up to 500ms to complete, then the configuration above may be limited to only 2 pushes per second if every request takes 500ms. To address this, you can send pushes in parallel by setting the concurrency to a value greater than 1, and increasing intervalCapacity and interval to fully utilize parallelism.
Example configuration sending pushes in parallel:
const parseServerOptions = {
push: {
adapter: new ParsePushAdapter({
ios: {
// ...
queue: {
concurrency: 5,
intervalCapacity: 5,
interval: 500,
},
}
})
}
};In the example above, pushes will be sent in bursts of 5 at once, with max. 10 pushes within 1s. On a timeline that means at t=0ms, 5 pushes will be sent in parallel. If sending the pushes take less than 500ms, then intervalCapacity will still limit to 5 pushes within the first 500ms. At t=500ms the second interval begins and another max. 5 pushes are sent in parallel. That effectively means a throughput of up to 10 pushes per second.
Each push request may specify the following options for handling in the queue.
| Parameter | Default | Optional | Description |
|---|---|---|---|
queue.ttl |
Infinity |
Yes | The time-to-live of the push in the queue in seconds. If a queued push expires before it is sent to the push provider, it is discarded. Default is Infinity, meaning pushes never expire. |
queue.priority |
0 |
Yes | The priority of the push in the queue. When processing the queue, pushes are sent in order of their priority. For example, a push with priority 1 is sent before a push with priority 0. |
Example push payload:
pushData = {
queue: {
// Discard after 10 seconds from queue if push has not been sent to push provider yet
ttl: 10,
// Send with higher priority than default pushes
priority: 1,
},
data: { alert: 'Hello' }
};Parse Server already comes bundled with a specific version of the push adapter. This installation is only necessary when customizing the push adapter version that should be used by Parse Server. When using a customized version of the push adapter, ensure that it's compatible with the version of Parse Server you are using.
When using the bundled version, it is not necessary to initialize the push adapter in code and the push options are configured directly in the push key, without the nested adapter key:
const parseServerOptions = {
push: {
ios: {
// Apple push options
}
// Other push options
}
// Other Parse Server options
};You can enable verbose logging to produce a more detailed output for all push sending attempts with the following environment variables:
VERBOSE=1or
VERBOSE_PARSE_SERVER_PUSH_ADAPTER=1