UNPKG

@elemental-design/expo-notifications

Version:
115 lines 4.82 kB
import { Platform, CodedError } from '@unimodules/core'; import * as Application from 'expo-application'; import Constants from 'expo-constants'; import InstallationIdProvider from './InstallationIdProvider'; import getDevicePushTokenAsync from './getDevicePushTokenAsync'; const productionBaseUrl = 'https://exp.host/--/api/v2/'; export default async function getExpoPushTokenAsync(options = {}) { const devicePushToken = options.devicePushToken || (await getDevicePushTokenAsync()); const deviceId = options.deviceId || (await getDeviceIdAsync()); const experienceId = options.experienceId || (Constants.manifest && Constants.manifest.id); if (!experienceId) { throw new CodedError('ERR_NOTIFICATIONS_NO_EXPERIENCE_ID', "No experienceId found. If it can't be inferred from the manifest (eg. in bare workflow), you have to pass it in yourself."); } const applicationId = options.applicationId || Application.applicationId; if (!applicationId) { throw new CodedError('ERR_NOTIFICATIONS_NO_APPLICATION_ID', "No applicationId found. If it can't be inferred from native configuration by expo-application, you have to pass it in yourself."); } const type = options.type || getTypeOfToken(devicePushToken); const development = options.development || (await shouldUseDevelopmentNotificationService()); const url = options.url || `${options.baseUrl || productionBaseUrl}push/getExpoPushToken`; const body = { type, deviceId, development, experienceId, appId: applicationId, deviceToken: getDeviceToken(devicePushToken), }; const response = await fetch(url, { method: 'POST', body: JSON.stringify(body), }).catch(error => { throw new CodedError('ERR_NOTIFICATIONS_NETWORK_ERROR', `Error encountered while fetching Expo token: ${error}.`); }); if (!response.ok) { const statusInfo = response.statusText || response.status; let body = undefined; try { body = await response.text(); } catch (error) { // do nothing } throw new CodedError('ERR_NOTIFICATIONS_SERVER_ERROR', `Error encountered while fetching Expo token, expected an OK response, received: ${statusInfo} (body: "${body}").`); } const expoPushToken = getExpoPushToken(await parseResponse(response)); return { type: 'expo', data: expoPushToken, }; } async function parseResponse(response) { try { return await response.json(); } catch (error) { try { throw new CodedError('ERR_NOTIFICATIONS_SERVER_ERROR', `Expected a JSON response from server when fetching Expo token, received body: ${JSON.stringify(await response.text())}.`); } catch (innerError) { throw new CodedError('ERR_NOTIFICATIONS_SERVER_ERROR', `Expected a JSON response from server when fetching Expo token, received response: ${JSON.stringify(response)}.`); } } } function getExpoPushToken(data) { if (!data || !(typeof data === 'object') || !data.data || !(typeof data.data === 'object') || !data.data.expoPushToken || !(typeof data.data.expoPushToken === 'string')) { throw new CodedError('ERR_NOTIFICATIONS_SERVER_ERROR', `Malformed response from server, expected "{ data: { expoPushToken: string } }", received: ${JSON.stringify(data, null, 2)}.`); } return data.data.expoPushToken; } async function getDeviceIdAsync() { try { return await InstallationIdProvider.getInstallationIdAsync(); } catch (e) { throw new CodedError('ERR_NOTIF_DEVICE_ID', `Could not have fetched installation ID of the application: ${e}.`); } } function getDeviceToken(devicePushToken) { if (typeof devicePushToken.data === 'string') { return devicePushToken.data; } return JSON.stringify(devicePushToken.data); } async function shouldUseDevelopmentNotificationService() { if (Platform.OS === 'ios') { try { const notificationServiceEnvironment = await Application.getIosPushNotificationServiceEnvironmentAsync(); if (notificationServiceEnvironment === 'development') { return true; } } catch (e) { // We can't do anything here, we'll fallback to false then. } } return false; } function getTypeOfToken(devicePushToken) { switch (devicePushToken.type) { case 'ios': return 'apns'; case 'android': return 'fcm'; // This probably will error on server, but let's make this function future-safe. default: return devicePushToken.type; } } //# sourceMappingURL=getExpoPushTokenAsync.js.map