Skip to content

Commit e92e9f0

Browse files
committed
refactor: enhance push notification handling with PushNotificationService integration
1 parent 2b313a7 commit e92e9f0

File tree

4 files changed

+126
-39
lines changed

4 files changed

+126
-39
lines changed

App/FeatureSet/Notification/API/PushRelay.ts

Lines changed: 7 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ import Express, {
77
import Response from "Common/Server/Utils/Response";
88
import BadDataException from "Common/Types/Exception/BadDataException";
99
import { JSONObject } from "Common/Types/JSON";
10-
import { Expo, ExpoPushMessage, ExpoPushTicket } from "expo-server-sdk";
11-
import { ExpoAccessToken } from "Common/Server/EnvironmentConfig";
12-
import logger from "Common/Server/Utils/Logger";
10+
import PushNotificationService from "Common/Server/Services/PushNotificationService";
1311

1412
const router: ExpressRouter = Express.getRouter();
1513

@@ -44,11 +42,6 @@ setInterval(() => {
4442
}
4543
}, 5 * 60 * 1000);
4644

47-
// Expo client for sending push notifications (only available when EXPO_ACCESS_TOKEN is set)
48-
const expoClient: Expo | null = ExpoAccessToken
49-
? new Expo({ accessToken: ExpoAccessToken })
50-
: null;
51-
5245
router.post(
5346
"/send",
5447
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
@@ -65,7 +58,7 @@ router.post(
6558
return;
6659
}
6760

68-
if (!expoClient) {
61+
if (!PushNotificationService.hasExpoAccessToken()) {
6962
throw new BadDataException(
7063
"Push relay is not configured. EXPO_ACCESS_TOKEN is not set on this server.",
7164
);
@@ -75,7 +68,7 @@ router.post(
7568

7669
const to: string | undefined = body["to"] as string | undefined;
7770

78-
if (!to || !Expo.isExpoPushToken(to)) {
71+
if (!to || !PushNotificationService.isValidExpoPushToken(to)) {
7972
throw new BadDataException(
8073
"Invalid or missing push token. Must be a valid Expo push token.",
8174
);
@@ -92,40 +85,15 @@ router.post(
9285
);
9386
}
9487

95-
const expoPushMessage: ExpoPushMessage = {
88+
await PushNotificationService.sendRelayPushNotification({
9689
to: to,
9790
title: title,
9891
body: messageBody,
9992
data: (body["data"] as { [key: string]: string }) || {},
100-
sound: (body["sound"] as "default" | null) || "default",
101-
priority: (body["priority"] as "default" | "normal" | "high") || "high",
93+
sound: (body["sound"] as string) || "default",
94+
priority: (body["priority"] as string) || "high",
10295
channelId: (body["channelId"] as string) || "default",
103-
};
104-
105-
const tickets: ExpoPushTicket[] =
106-
await expoClient.sendPushNotificationsAsync([expoPushMessage]);
107-
108-
const ticket: ExpoPushTicket | undefined = tickets[0];
109-
110-
if (ticket && ticket.status === "error") {
111-
const errorTicket: ExpoPushTicket & {
112-
message?: string;
113-
details?: { error?: string };
114-
} = ticket as ExpoPushTicket & {
115-
message?: string;
116-
details?: { error?: string };
117-
};
118-
119-
logger.error(
120-
`Push relay: Expo push notification error: ${errorTicket.message}`,
121-
);
122-
123-
throw new BadDataException(
124-
`Failed to send push notification: ${errorTicket.message}`,
125-
);
126-
}
127-
128-
logger.info(`Push relay: notification sent successfully to ${to}`);
96+
});
12997

13098
return Response.sendJsonObjectResponse(req, res, { success: true });
13199
} catch (err) {

App/package-lock.json

Lines changed: 58 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

App/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"@sendgrid/mail": "^8.1.0",
2424
"Common": "file:../Common",
2525
"ejs": "^3.1.9",
26+
"expo-server-sdk": "^5.0.0",
2627
"handlebars": "^4.7.8",
2728
"nodemailer": "^6.9.7",
2829
"ts-node": "^10.9.1",

Common/Server/Services/PushNotificationService.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,66 @@ export default class PushNotificationService {
468468
}
469469
}
470470

471+
public static isValidExpoPushToken(token: string): boolean {
472+
return Expo.isExpoPushToken(token);
473+
}
474+
475+
public static hasExpoAccessToken(): boolean {
476+
return Boolean(ExpoAccessToken);
477+
}
478+
479+
public static async sendRelayPushNotification(data: {
480+
to: string;
481+
title?: string;
482+
body?: string;
483+
data?: { [key: string]: string };
484+
sound?: string;
485+
priority?: string;
486+
channelId?: string;
487+
}): Promise<void> {
488+
if (!ExpoAccessToken) {
489+
throw new Error(
490+
"Push relay is not configured. EXPO_ACCESS_TOKEN is not set on this server.",
491+
);
492+
}
493+
494+
const expoPushMessage: ExpoPushMessage = {
495+
to: data.to,
496+
title: data.title,
497+
body: data.body,
498+
data: data.data || {},
499+
sound: (data.sound as "default" | null) || "default",
500+
priority:
501+
(data.priority as "default" | "normal" | "high") || "high",
502+
channelId: data.channelId || "default",
503+
};
504+
505+
const tickets: ExpoPushTicket[] =
506+
await this.expoClient.sendPushNotificationsAsync([expoPushMessage]);
507+
508+
const ticket: ExpoPushTicket | undefined = tickets[0];
509+
510+
if (ticket && ticket.status === "error") {
511+
const errorTicket: ExpoPushTicket & {
512+
message?: string;
513+
details?: { error?: string };
514+
} = ticket as ExpoPushTicket & {
515+
message?: string;
516+
details?: { error?: string };
517+
};
518+
519+
logger.error(
520+
`Push relay: Expo push notification error: ${errorTicket.message}`,
521+
);
522+
523+
throw new Error(
524+
`Failed to send push notification: ${errorTicket.message}`,
525+
);
526+
}
527+
528+
logger.info(`Push relay: notification sent successfully to ${data.to}`);
529+
}
530+
471531
public static async sendPushNotificationToUser(
472532
userId: ObjectID,
473533
projectId: ObjectID,

0 commit comments

Comments
 (0)