@zan-shop/push-notifications 1.0.0

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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +255 -0
  3. package/dist/index.d.ts +27 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +37 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/models/device-token.d.ts +30 -0
  8. package/dist/models/device-token.d.ts.map +1 -0
  9. package/dist/models/device-token.js +7 -0
  10. package/dist/models/device-token.js.map +1 -0
  11. package/dist/services/device-service.d.ts +51 -0
  12. package/dist/services/device-service.d.ts.map +1 -0
  13. package/dist/services/device-service.js +14 -0
  14. package/dist/services/device-service.js.map +1 -0
  15. package/dist/services/fcm-service.d.ts +48 -0
  16. package/dist/services/fcm-service.d.ts.map +1 -0
  17. package/dist/services/fcm-service.js +208 -0
  18. package/dist/services/fcm-service.js.map +1 -0
  19. package/dist/services/index.d.ts +8 -0
  20. package/dist/services/index.d.ts.map +1 -0
  21. package/dist/services/index.js +12 -0
  22. package/dist/services/index.js.map +1 -0
  23. package/dist/types/index.d.ts +7 -0
  24. package/dist/types/index.d.ts.map +1 -0
  25. package/dist/types/index.js +22 -0
  26. package/dist/types/index.js.map +1 -0
  27. package/dist/types/notification.d.ts +48 -0
  28. package/dist/types/notification.d.ts.map +1 -0
  29. package/dist/types/notification.js +7 -0
  30. package/dist/types/notification.js.map +1 -0
  31. package/dist/utils/index.d.ts +7 -0
  32. package/dist/utils/index.d.ts.map +1 -0
  33. package/dist/utils/index.js +23 -0
  34. package/dist/utils/index.js.map +1 -0
  35. package/dist/utils/notification-formatter.d.ts +18 -0
  36. package/dist/utils/notification-formatter.d.ts.map +1 -0
  37. package/dist/utils/notification-formatter.js +92 -0
  38. package/dist/utils/notification-formatter.js.map +1 -0
  39. package/dist/utils/validators.d.ts +18 -0
  40. package/dist/utils/validators.d.ts.map +1 -0
  41. package/dist/utils/validators.js +43 -0
  42. package/dist/utils/validators.js.map +1 -0
  43. package/package.json +54 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ZAN
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,255 @@
1
+ # @zan-shop/push-notifications
2
+
3
+ Push notification module for Medusa.js using Firebase Cloud Messaging (FCM). Provides type-safe utilities for sending mobile push notifications with built-in formatters for common e-commerce events.
4
+
5
+ ## Features
6
+
7
+ - ๐Ÿ”ฅ Firebase Cloud Messaging integration
8
+ - ๐Ÿ“ฑ iOS & Android support
9
+ - ๐Ÿ“ฆ Pre-built formatters (orders, shipments, returns, payouts)
10
+ - ๐Ÿ”„ Batch sending (up to 500 devices)
11
+ - โœ… Full TypeScript support
12
+ - ๐Ÿงช Dry-run mode for testing
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @zan-shop/push-notifications
18
+ ```
19
+
20
+ **Prerequisites:**
21
+ - Firebase project with Cloud Messaging enabled
22
+ - Firebase Admin SDK already initialized in your project
23
+ - Node.js >= 18.0.0
24
+
25
+ ## Quick Start
26
+
27
+ ### 1. Create FCM Service
28
+
29
+ ```typescript
30
+ import { FCMService } from '@zan-shop/push-notifications';
31
+
32
+ const fcmService = new FCMService({
33
+ firebaseApp,
34
+ dryRun: false, // Set to true for testing
35
+ });
36
+ ```
37
+
38
+ ### 2. Send Notifications
39
+
40
+ ```typescript
41
+ import { formatShipmentNotification } from '@zan-shop/push-notifications';
42
+
43
+ const notification = formatShipmentNotification({
44
+ type: 'shipment.created',
45
+ orderId: 'order_123',
46
+ trackingNumber: 'TRACK123',
47
+ carrier: 'FedEx',
48
+ estimatedDelivery: '2024-01-15',
49
+ });
50
+
51
+ const result = await fcmService.sendToDevice(deviceToken, notification);
52
+
53
+ if (result.success) {
54
+ console.log('Notification sent:', result.messageId);
55
+ } else {
56
+ console.error('Failed to send:', result.error);
57
+ }
58
+ ```
59
+
60
+ ## Event Formatters
61
+
62
+ Pre-built formatters for common e-commerce events:
63
+
64
+ ### Shipment Notifications
65
+
66
+ ```typescript
67
+ import { formatShipmentNotification } from '@zan-shop/push-notifications';
68
+
69
+ const notification = formatShipmentNotification({
70
+ type: 'shipment.created',
71
+ orderId: 'order_123',
72
+ trackingNumber: 'TRACK123',
73
+ carrier: 'FedEx',
74
+ });
75
+ // Output: "๐Ÿ“ฆ Order Shipped - Your order #order_123 has been shipped! Track your package..."
76
+ ```
77
+
78
+ ### Order Notifications
79
+
80
+ ```typescript
81
+ import { formatOrderNotification } from '@zan-shop/push-notifications';
82
+
83
+ const notification = formatOrderNotification({
84
+ type: 'order.placed',
85
+ orderId: 'order_123',
86
+ orderNumber: 'ORD-2024-001',
87
+ });
88
+ // Output: "โœ… Order Confirmed - Your order ORD-2024-001 has been confirmed!"
89
+ ```
90
+
91
+ ### Return Notifications
92
+
93
+ ```typescript
94
+ import { formatReturnNotification } from '@zan-shop/push-notifications';
95
+
96
+ const notification = formatReturnNotification({
97
+ type: 'return.approved',
98
+ returnId: 'return_123',
99
+ orderId: 'order_123',
100
+ });
101
+ // Output: "โœ… Return Approved - Your return request for order #order_123 has been approved!"
102
+ ```
103
+
104
+ ### Custom Notifications
105
+
106
+ ```typescript
107
+ import type { NotificationPayload } from '@zan-shop/push-notifications';
108
+
109
+ const customNotification: NotificationPayload = {
110
+ title: '๐ŸŽ‰ Special Offer',
111
+ body: 'Get 20% off your next purchase!',
112
+ data: {
113
+ type: 'promotion',
114
+ promoCode: 'SAVE20',
115
+ },
116
+ imageUrl: 'https://example.com/promo-banner.jpg',
117
+ clickAction: '/promotions/save20',
118
+ priority: 'high',
119
+ sound: 'default',
120
+ badge: 1,
121
+ };
122
+
123
+ await fcmService.sendToDevice(deviceToken, customNotification);
124
+ ```
125
+
126
+ ## Batch Sending
127
+
128
+ ```typescript
129
+ const tokens = ['token1', 'token2', 'token3'];
130
+ const result = await fcmService.sendToMultipleDevices(tokens, notification);
131
+
132
+ console.log(`Success: ${result.successCount}, Failed: ${result.failureCount}`);
133
+ ```
134
+
135
+ ## Medusa Integration
136
+
137
+ Example subscriber for shipment notifications:
138
+
139
+ ```typescript
140
+ import type { SubscriberArgs } from '@medusajs/framework';
141
+ import { FCMService, formatShipmentNotification } from '@zan-shop/push-notifications';
142
+
143
+ export default async function handleShipmentCreated({
144
+ event,
145
+ container,
146
+ }: SubscriberArgs<{ id: string }>) {
147
+ const fcmService = container.resolve<FCMService>('fcmService');
148
+ const deviceService = container.resolve('deviceService');
149
+
150
+ const shipment = await fetchShipmentDetails(event.data.id);
151
+
152
+ // Get customer's devices
153
+ const devices = await deviceService.getCustomerDevices(shipment.order.customer_id);
154
+
155
+ if (devices.length === 0) return;
156
+
157
+ // Format notification
158
+ const notification = formatShipmentNotification({
159
+ type: 'shipment.created',
160
+ orderId: shipment.order.id,
161
+ trackingNumber: shipment.tracking_number,
162
+ carrier: shipment.carrier,
163
+ });
164
+
165
+ // Send to all customer devices
166
+ const tokens = devices.map(d => d.token);
167
+ const result = await fcmService.sendToMultipleDevices(tokens, notification);
168
+
169
+ console.log(`Sent: ${result.successCount} succeeded, ${result.failureCount} failed`);
170
+ }
171
+ ```
172
+
173
+ ## API Reference
174
+
175
+ ### FCMService
176
+
177
+ - `sendToDevice(token, payload)` - Send to single device
178
+ - `sendToMultipleDevices(tokens, payload)` - Batch send (auto-splits into batches of 500)
179
+ - `sendToCustomer(customerId, payload)` - Send to all customer devices
180
+ - `sendToTopic(topic, payload)` - Broadcast to topic subscribers
181
+ - `validateToken(token)` - Check if token is valid
182
+
183
+ ### Formatters
184
+
185
+ - `formatShipmentNotification(data)` - Shipment events
186
+ - `formatOrderNotification(data)` - Order events
187
+ - `formatReturnNotification(data)` - Return events
188
+ - `formatPayoutNotification(data)` - Payout events
189
+
190
+ ### Types
191
+
192
+ ```typescript
193
+ import type {
194
+ NotificationPayload,
195
+ SendResult,
196
+ BatchResult,
197
+ DeviceToken,
198
+ DeviceRegistration,
199
+ } from '@zan-shop/push-notifications';
200
+ ```
201
+
202
+ ## Device Management
203
+
204
+ The package provides an abstract `DeviceService` class. Extend it with your database implementation:
205
+
206
+ ```typescript
207
+ import { DeviceService } from '@zan-shop/push-notifications';
208
+
209
+ class MyDeviceService extends DeviceService {
210
+ async registerDevice(customerId, deviceData) { /* ... */ }
211
+ async getCustomerDevices(customerId) { /* ... */ }
212
+ async deactivateDevice(token) { /* ... */ }
213
+ // ... other methods
214
+ }
215
+ ```
216
+
217
+ ## Testing
218
+
219
+ Enable dry-run mode for testing without sending actual notifications:
220
+
221
+ ```typescript
222
+ const fcmService = new FCMService({ firebaseApp, dryRun: true });
223
+ ```
224
+
225
+ ## Versioning
226
+
227
+ This package uses [semantic-release](https://github.com/semantic-release/semantic-release) for automated versioning. Use conventional commits:
228
+
229
+ ```
230
+ # For features (bumps minor version 1.0.0 -> 1.1.0)
231
+ git commit -m "feat: add notification scheduling"
232
+
233
+ # For fixes (bumps patch version 1.0.0 -> 1.0.1)
234
+ git commit -m "fix: handle expired tokens correctly"
235
+
236
+ # For breaking changes (bumps major version 1.0.0 -> 2.0.0)
237
+ git commit -m "feat!: change FCM service API
238
+
239
+ BREAKING CHANGE: sendToDevice now requires configuration object"
240
+
241
+ # No version bump
242
+ git commit -m "chore: update dependencies"
243
+ git commit -m "docs: update README"
244
+ ```
245
+
246
+ ## License
247
+
248
+ MIT
249
+
250
+ ## Links
251
+
252
+ - [GitHub Repository](https://github.com/zan-shop/push-notifications)
253
+ - [Issues](https://github.com/zan-shop/push-notifications/issues)
254
+ - [Firebase Cloud Messaging Docs](https://firebase.google.com/docs/cloud-messaging)
255
+ - [Medusa.js Docs](https://docs.medusajs.com)
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @zan-shop/push-notifications
3
+ *
4
+ * Reusable push notification module for Medusa.js using Firebase Cloud Messaging
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { FCMService, formatShipmentNotification } from '@zan-shop/push-notifications';
9
+ *
10
+ * const fcmService = new FCMService({ firebaseApp });
11
+ *
12
+ * const notification = formatShipmentNotification({
13
+ * type: 'shipment.created',
14
+ * orderId: '123',
15
+ * trackingNumber: 'ABC123',
16
+ * carrier: 'FedEx',
17
+ * });
18
+ *
19
+ * await fcmService.sendToDevice(deviceToken, notification);
20
+ * ```
21
+ */
22
+ export type { DeviceToken, DeviceInfo, DeviceRegistration, Platform, } from './models/device-token';
23
+ export { FCMService, DeviceService } from './services';
24
+ export type { FCMServiceOptions } from './services';
25
+ export type { NotificationPayload, NotificationPriority, SendResult, BatchResult, NotificationError, ShipmentNotification, OrderNotification, ReturnNotification, } from './types';
26
+ export { validateFCMToken, validatePlatform, validateAppVersion, formatShipmentNotification, formatOrderNotification, formatReturnNotification, } from './utils';
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,YAAY,EACV,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,QAAQ,GACT,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACvD,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGpD,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,0BAA0B,EAC1B,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ /**
3
+ * @zan-shop/push-notifications
4
+ *
5
+ * Reusable push notification module for Medusa.js using Firebase Cloud Messaging
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { FCMService, formatShipmentNotification } from '@zan-shop/push-notifications';
10
+ *
11
+ * const fcmService = new FCMService({ firebaseApp });
12
+ *
13
+ * const notification = formatShipmentNotification({
14
+ * type: 'shipment.created',
15
+ * orderId: '123',
16
+ * trackingNumber: 'ABC123',
17
+ * carrier: 'FedEx',
18
+ * });
19
+ *
20
+ * await fcmService.sendToDevice(deviceToken, notification);
21
+ * ```
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.formatReturnNotification = exports.formatOrderNotification = exports.formatShipmentNotification = exports.validateAppVersion = exports.validatePlatform = exports.validateFCMToken = exports.DeviceService = exports.FCMService = void 0;
25
+ // Services
26
+ var services_1 = require("./services");
27
+ Object.defineProperty(exports, "FCMService", { enumerable: true, get: function () { return services_1.FCMService; } });
28
+ Object.defineProperty(exports, "DeviceService", { enumerable: true, get: function () { return services_1.DeviceService; } });
29
+ // Utils
30
+ var utils_1 = require("./utils");
31
+ Object.defineProperty(exports, "validateFCMToken", { enumerable: true, get: function () { return utils_1.validateFCMToken; } });
32
+ Object.defineProperty(exports, "validatePlatform", { enumerable: true, get: function () { return utils_1.validatePlatform; } });
33
+ Object.defineProperty(exports, "validateAppVersion", { enumerable: true, get: function () { return utils_1.validateAppVersion; } });
34
+ Object.defineProperty(exports, "formatShipmentNotification", { enumerable: true, get: function () { return utils_1.formatShipmentNotification; } });
35
+ Object.defineProperty(exports, "formatOrderNotification", { enumerable: true, get: function () { return utils_1.formatOrderNotification; } });
36
+ Object.defineProperty(exports, "formatReturnNotification", { enumerable: true, get: function () { return utils_1.formatReturnNotification; } });
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;AAUH,WAAW;AACX,uCAAuD;AAA9C,sGAAA,UAAU,OAAA;AAAE,yGAAA,aAAa,OAAA;AAelC,QAAQ;AACR,iCAOiB;AANf,yGAAA,gBAAgB,OAAA;AAChB,yGAAA,gBAAgB,OAAA;AAChB,2GAAA,kBAAkB,OAAA;AAClB,mHAAA,0BAA0B,OAAA;AAC1B,gHAAA,uBAAuB,OAAA;AACvB,iHAAA,wBAAwB,OAAA"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Device Token Model
3
+ * Represents a registered mobile device for push notifications
4
+ */
5
+ export interface DeviceToken {
6
+ id: string;
7
+ customer_id: string;
8
+ token: string;
9
+ platform: 'ios' | 'android';
10
+ app_version?: string;
11
+ device_info?: DeviceInfo;
12
+ is_active: boolean;
13
+ last_used_at: Date;
14
+ created_at: Date;
15
+ updated_at: Date;
16
+ deleted_at?: Date | null;
17
+ }
18
+ export interface DeviceInfo {
19
+ model?: string;
20
+ os_version?: string;
21
+ manufacturer?: string;
22
+ }
23
+ export interface DeviceRegistration {
24
+ token: string;
25
+ platform: 'ios' | 'android';
26
+ app_version?: string;
27
+ device_info?: DeviceInfo;
28
+ }
29
+ export type Platform = 'ios' | 'android';
30
+ //# sourceMappingURL=device-token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-token.d.ts","sourceRoot":"","sources":["../../src/models/device-token.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,GAAG,SAAS,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,IAAI,CAAC;IACnB,UAAU,EAAE,IAAI,CAAC;IACjB,UAAU,EAAE,IAAI,CAAC;IACjB,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,GAAG,SAAS,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC"}
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * Device Token Model
4
+ * Represents a registered mobile device for push notifications
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ //# sourceMappingURL=device-token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-token.js","sourceRoot":"","sources":["../../src/models/device-token.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Device Service Interface
3
+ * Abstract interface for managing device tokens
4
+ *
5
+ * This is an abstract class that should be implemented with database-specific logic
6
+ * The implementing class in zan-backend will use Medusa's data layer
7
+ */
8
+ import { DeviceToken, DeviceRegistration } from '../models/device-token';
9
+ export declare abstract class DeviceService {
10
+ /**
11
+ * Register a new device token for a customer
12
+ * Should handle deduplication (same customer + token)
13
+ */
14
+ abstract registerDevice(customerId: string, deviceData: DeviceRegistration): Promise<DeviceToken>;
15
+ /**
16
+ * Update an existing device
17
+ */
18
+ abstract updateDevice(tokenId: string, updates: Partial<DeviceToken>): Promise<DeviceToken>;
19
+ /**
20
+ * Deactivate a device (e.g., on logout)
21
+ * Marks device as inactive rather than deleting
22
+ */
23
+ abstract deactivateDevice(token: string): Promise<void>;
24
+ /**
25
+ * Deactivate all devices for a customer (e.g., on account deletion)
26
+ */
27
+ abstract deactivateCustomerDevices(customerId: string): Promise<number>;
28
+ /**
29
+ * Get all active devices for a customer
30
+ */
31
+ abstract getCustomerDevices(customerId: string): Promise<DeviceToken[]>;
32
+ /**
33
+ * Get a specific device by token
34
+ */
35
+ abstract getDeviceByToken(token: string): Promise<DeviceToken | null>;
36
+ /**
37
+ * Update last_used_at timestamp for a device
38
+ */
39
+ abstract touchDevice(token: string): Promise<void>;
40
+ /**
41
+ * Clean up inactive tokens older than specified days
42
+ * Returns number of devices cleaned up
43
+ */
44
+ abstract cleanupInactiveTokens(daysThreshold: number): Promise<number>;
45
+ /**
46
+ * Handle invalid tokens (called when FCM reports token as invalid)
47
+ * Marks tokens as inactive
48
+ */
49
+ abstract markTokensAsInvalid(tokens: string[]): Promise<void>;
50
+ }
51
+ //# sourceMappingURL=device-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-service.d.ts","sourceRoot":"","sources":["../../src/services/device-service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEzE,8BAAsB,aAAa;IACjC;;;OAGG;IACH,QAAQ,CAAC,cAAc,CACrB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,kBAAkB,GAC7B,OAAO,CAAC,WAAW,CAAC;IAEvB;;OAEG;IACH,QAAQ,CAAC,YAAY,CACnB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAC5B,OAAO,CAAC,WAAW,CAAC;IAEvB;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAEvD;;OAEG;IACH,QAAQ,CAAC,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAEvE;;OAEG;IACH,QAAQ,CAAC,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAEvE;;OAEG;IACH,QAAQ,CAAC,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAErE;;OAEG;IACH,QAAQ,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAElD;;;OAGG;IACH,QAAQ,CAAC,qBAAqB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAEtE;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAC9D"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ /**
3
+ * Device Service Interface
4
+ * Abstract interface for managing device tokens
5
+ *
6
+ * This is an abstract class that should be implemented with database-specific logic
7
+ * The implementing class in zan-backend will use Medusa's data layer
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.DeviceService = void 0;
11
+ class DeviceService {
12
+ }
13
+ exports.DeviceService = DeviceService;
14
+ //# sourceMappingURL=device-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-service.js","sourceRoot":"","sources":["../../src/services/device-service.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAIH,MAAsB,aAAa;CAuDlC;AAvDD,sCAuDC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * FCM Service
3
+ * Handles sending push notifications via Firebase Cloud Messaging
4
+ */
5
+ import * as admin from 'firebase-admin';
6
+ import { NotificationPayload, SendResult, BatchResult } from '../types/notification';
7
+ export interface FCMServiceOptions {
8
+ firebaseApp: admin.app.App;
9
+ dryRun?: boolean;
10
+ }
11
+ export declare class FCMService {
12
+ private messaging;
13
+ private dryRun;
14
+ constructor(options: FCMServiceOptions);
15
+ /**
16
+ * Send notification to a single device
17
+ */
18
+ sendToDevice(token: string, payload: NotificationPayload): Promise<SendResult>;
19
+ /**
20
+ * Send notification to multiple devices
21
+ */
22
+ sendToMultipleDevices(tokens: string[], payload: NotificationPayload): Promise<BatchResult>;
23
+ /**
24
+ * Send notification to a topic (broadcast)
25
+ */
26
+ sendToTopic(topic: string, payload: NotificationPayload): Promise<SendResult>;
27
+ /**
28
+ * Validate a device token
29
+ */
30
+ validateToken(token: string): Promise<boolean>;
31
+ /**
32
+ * Send batch of notifications
33
+ */
34
+ private sendBatch;
35
+ /**
36
+ * Build FCM message for a single device
37
+ */
38
+ private buildMessage;
39
+ /**
40
+ * Build FCM message for a topic
41
+ */
42
+ private buildTopicMessage;
43
+ /**
44
+ * Parse Firebase error into standardized format
45
+ */
46
+ private parseError;
47
+ }
48
+ //# sourceMappingURL=fcm-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fcm-service.d.ts","sourceRoot":"","sources":["../../src/services/fcm-service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,EACL,mBAAmB,EACnB,UAAU,EACV,WAAW,EAEZ,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,MAAM,CAAU;gBAEZ,OAAO,EAAE,iBAAiB;IAKtC;;OAEG;IACG,YAAY,CAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,UAAU,CAAC;IAkBtB;;OAEG;IACG,qBAAqB,CACzB,MAAM,EAAE,MAAM,EAAE,EAChB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,WAAW,CAAC;IA6BvB;;OAEG;IACG,WAAW,CACf,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,UAAU,CAAC;IAkBtB;;OAEG;IACG,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAwBpD;;OAEG;YACW,SAAS;IA+BvB;;OAEG;IACH,OAAO,CAAC,YAAY;IAiCpB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA8BzB;;OAEG;IACH,OAAO,CAAC,UAAU;CAUnB"}
@@ -0,0 +1,208 @@
1
+ "use strict";
2
+ /**
3
+ * FCM Service
4
+ * Handles sending push notifications via Firebase Cloud Messaging
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.FCMService = void 0;
8
+ class FCMService {
9
+ constructor(options) {
10
+ this.messaging = options.firebaseApp.messaging();
11
+ this.dryRun = options.dryRun || false;
12
+ }
13
+ /**
14
+ * Send notification to a single device
15
+ */
16
+ async sendToDevice(token, payload) {
17
+ try {
18
+ const message = this.buildMessage(token, payload);
19
+ const messageId = await this.messaging.send(message, this.dryRun);
20
+ return {
21
+ success: true,
22
+ messageId,
23
+ };
24
+ }
25
+ catch (error) {
26
+ return {
27
+ success: false,
28
+ error: this.parseError(error, token),
29
+ };
30
+ }
31
+ }
32
+ /**
33
+ * Send notification to multiple devices
34
+ */
35
+ async sendToMultipleDevices(tokens, payload) {
36
+ if (tokens.length === 0) {
37
+ return {
38
+ successCount: 0,
39
+ failureCount: 0,
40
+ results: [],
41
+ };
42
+ }
43
+ // FCM allows max 500 tokens per batch
44
+ const batchSize = 500;
45
+ const results = [];
46
+ for (let i = 0; i < tokens.length; i += batchSize) {
47
+ const batch = tokens.slice(i, i + batchSize);
48
+ const batchResults = await this.sendBatch(batch, payload);
49
+ results.push(...batchResults);
50
+ }
51
+ const successCount = results.filter((r) => r.success).length;
52
+ const failureCount = results.length - successCount;
53
+ return {
54
+ successCount,
55
+ failureCount,
56
+ results,
57
+ };
58
+ }
59
+ /**
60
+ * Send notification to a topic (broadcast)
61
+ */
62
+ async sendToTopic(topic, payload) {
63
+ try {
64
+ const message = this.buildTopicMessage(topic, payload);
65
+ const messageId = await this.messaging.send(message, this.dryRun);
66
+ return {
67
+ success: true,
68
+ messageId,
69
+ };
70
+ }
71
+ catch (error) {
72
+ return {
73
+ success: false,
74
+ error: this.parseError(error),
75
+ };
76
+ }
77
+ }
78
+ /**
79
+ * Validate a device token
80
+ */
81
+ async validateToken(token) {
82
+ try {
83
+ // Try to send a dry-run message
84
+ await this.messaging.send({
85
+ token,
86
+ notification: {
87
+ title: 'Test',
88
+ body: 'Test',
89
+ },
90
+ }, true // Always dry run for validation
91
+ );
92
+ return true;
93
+ }
94
+ catch (error) {
95
+ // Token is invalid if we get specific error codes
96
+ const invalidTokenCodes = [
97
+ 'messaging/invalid-registration-token',
98
+ 'messaging/registration-token-not-registered',
99
+ ];
100
+ return !invalidTokenCodes.includes(error?.code);
101
+ }
102
+ }
103
+ /**
104
+ * Send batch of notifications
105
+ */
106
+ async sendBatch(tokens, payload) {
107
+ try {
108
+ const messages = tokens.map((token) => this.buildMessage(token, payload));
109
+ const response = await this.messaging.sendEach(messages, this.dryRun);
110
+ return response.responses.map((resp, index) => {
111
+ if (resp.success) {
112
+ return {
113
+ success: true,
114
+ messageId: resp.messageId,
115
+ };
116
+ }
117
+ else {
118
+ return {
119
+ success: false,
120
+ error: this.parseError(resp.error, tokens[index]),
121
+ };
122
+ }
123
+ });
124
+ }
125
+ catch (error) {
126
+ // If entire batch fails, return error for all tokens
127
+ return tokens.map((token) => ({
128
+ success: false,
129
+ error: this.parseError(error, token),
130
+ }));
131
+ }
132
+ }
133
+ /**
134
+ * Build FCM message for a single device
135
+ */
136
+ buildMessage(token, payload) {
137
+ return {
138
+ token,
139
+ notification: {
140
+ title: payload.title,
141
+ body: payload.body,
142
+ ...(payload.imageUrl && { imageUrl: payload.imageUrl }),
143
+ },
144
+ data: payload.data,
145
+ android: {
146
+ priority: payload.priority === 'high' ? 'high' : 'normal',
147
+ notification: {
148
+ sound: payload.sound || 'default',
149
+ clickAction: payload.clickAction,
150
+ },
151
+ },
152
+ apns: {
153
+ payload: {
154
+ aps: {
155
+ badge: payload.badge,
156
+ sound: payload.sound || 'default',
157
+ },
158
+ },
159
+ fcmOptions: {
160
+ ...(payload.imageUrl && { imageUrl: payload.imageUrl }),
161
+ },
162
+ },
163
+ };
164
+ }
165
+ /**
166
+ * Build FCM message for a topic
167
+ */
168
+ buildTopicMessage(topic, payload) {
169
+ return {
170
+ topic,
171
+ notification: {
172
+ title: payload.title,
173
+ body: payload.body,
174
+ ...(payload.imageUrl && { imageUrl: payload.imageUrl }),
175
+ },
176
+ data: payload.data,
177
+ android: {
178
+ priority: payload.priority === 'high' ? 'high' : 'normal',
179
+ notification: {
180
+ sound: payload.sound || 'default',
181
+ clickAction: payload.clickAction,
182
+ },
183
+ },
184
+ apns: {
185
+ payload: {
186
+ aps: {
187
+ badge: payload.badge,
188
+ sound: payload.sound || 'default',
189
+ },
190
+ },
191
+ },
192
+ };
193
+ }
194
+ /**
195
+ * Parse Firebase error into standardized format
196
+ */
197
+ parseError(error, token) {
198
+ const code = error?.code || 'unknown';
199
+ const message = error?.message || 'Unknown error occurred';
200
+ return {
201
+ code,
202
+ message,
203
+ ...(token && { token }),
204
+ };
205
+ }
206
+ }
207
+ exports.FCMService = FCMService;
208
+ //# sourceMappingURL=fcm-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fcm-service.js","sourceRoot":"","sources":["../../src/services/fcm-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Services Index
3
+ * Exports all service classes
4
+ */
5
+ export { FCMService } from './fcm-service';
6
+ export type { FCMServiceOptions } from './fcm-service';
7
+ export { DeviceService } from './device-service';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ /**
3
+ * Services Index
4
+ * Exports all service classes
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.DeviceService = exports.FCMService = void 0;
8
+ var fcm_service_1 = require("./fcm-service");
9
+ Object.defineProperty(exports, "FCMService", { enumerable: true, get: function () { return fcm_service_1.FCMService; } });
10
+ var device_service_1 = require("./device-service");
11
+ Object.defineProperty(exports, "DeviceService", { enumerable: true, get: function () { return device_service_1.DeviceService; } });
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,6CAA2C;AAAlC,yGAAA,UAAU,OAAA;AAEnB,mDAAiD;AAAxC,+GAAA,aAAa,OAAA"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Type Definitions Index
3
+ * Exports all type definitions for external use
4
+ */
5
+ export * from './notification';
6
+ export type { DeviceToken, DeviceInfo, DeviceRegistration, Platform, } from '../models/device-token';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,gBAAgB,CAAC;AAC/B,YAAY,EACV,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,QAAQ,GACT,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ /**
3
+ * Type Definitions Index
4
+ * Exports all type definitions for external use
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
+ };
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ __exportStar(require("./notification"), exports);
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;AAEH,iDAA+B"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Notification Types
3
+ * Type definitions for push notification payloads and results
4
+ */
5
+ export interface NotificationPayload {
6
+ title: string;
7
+ body: string;
8
+ data?: Record<string, string>;
9
+ imageUrl?: string;
10
+ sound?: string;
11
+ badge?: number;
12
+ clickAction?: string;
13
+ priority?: NotificationPriority;
14
+ }
15
+ export type NotificationPriority = 'high' | 'normal';
16
+ export interface SendResult {
17
+ success: boolean;
18
+ messageId?: string;
19
+ error?: NotificationError;
20
+ }
21
+ export interface BatchResult {
22
+ successCount: number;
23
+ failureCount: number;
24
+ results: SendResult[];
25
+ }
26
+ export interface NotificationError {
27
+ code: string;
28
+ message: string;
29
+ token?: string;
30
+ }
31
+ export interface ShipmentNotification {
32
+ type: 'shipment.created';
33
+ orderId: string;
34
+ trackingNumber?: string;
35
+ carrier?: string;
36
+ estimatedDelivery?: string;
37
+ }
38
+ export interface OrderNotification {
39
+ type: 'order.placed' | 'order.delivered' | 'order.canceled';
40
+ orderId: string;
41
+ orderNumber?: string;
42
+ }
43
+ export interface ReturnNotification {
44
+ type: 'return.created' | 'return.approved' | 'return.rejected';
45
+ returnId: string;
46
+ orderId: string;
47
+ }
48
+ //# sourceMappingURL=notification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../../src/types/notification.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CACjC;AAED,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,QAAQ,CAAC;AAErD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,iBAAiB,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,cAAc,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,gBAAgB,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * Notification Types
4
+ * Type definitions for push notification payloads and results
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ //# sourceMappingURL=notification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification.js","sourceRoot":"","sources":["../../src/types/notification.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Utils Index
3
+ * Exports all utility functions
4
+ */
5
+ export * from './validators';
6
+ export * from './notification-formatter';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,0BAA0B,CAAC"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ /**
3
+ * Utils Index
4
+ * Exports all utility functions
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
+ };
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ __exportStar(require("./validators"), exports);
22
+ __exportStar(require("./notification-formatter"), exports);
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;AAEH,+CAA6B;AAC7B,2DAAyC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Notification Formatters
3
+ * Helper functions to format notifications for different event types
4
+ */
5
+ import { NotificationPayload, ShipmentNotification, OrderNotification, ReturnNotification } from '../types/notification';
6
+ /**
7
+ * Format shipment notification
8
+ */
9
+ export declare function formatShipmentNotification(data: ShipmentNotification): NotificationPayload;
10
+ /**
11
+ * Format order notification
12
+ */
13
+ export declare function formatOrderNotification(data: OrderNotification): NotificationPayload;
14
+ /**
15
+ * Format return notification
16
+ */
17
+ export declare function formatReturnNotification(data: ReturnNotification): NotificationPayload;
18
+ //# sourceMappingURL=notification-formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification-formatter.d.ts","sourceRoot":"","sources":["../../src/utils/notification-formatter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AAE/B;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,oBAAoB,GACzB,mBAAmB,CA2BrB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,iBAAiB,GACtB,mBAAmB,CA0BrB;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,kBAAkB,GACvB,mBAAmB,CA0BrB"}
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ /**
3
+ * Notification Formatters
4
+ * Helper functions to format notifications for different event types
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.formatShipmentNotification = formatShipmentNotification;
8
+ exports.formatOrderNotification = formatOrderNotification;
9
+ exports.formatReturnNotification = formatReturnNotification;
10
+ /**
11
+ * Format shipment notification
12
+ */
13
+ function formatShipmentNotification(data) {
14
+ const { orderId, trackingNumber, carrier, estimatedDelivery } = data;
15
+ let body = `Your order #${orderId} has been shipped!`;
16
+ if (carrier && trackingNumber) {
17
+ body += ` Track your package with ${carrier}: ${trackingNumber}`;
18
+ }
19
+ else if (trackingNumber) {
20
+ body += ` Tracking: ${trackingNumber}`;
21
+ }
22
+ if (estimatedDelivery) {
23
+ body += ` Estimated delivery: ${estimatedDelivery}`;
24
+ }
25
+ return {
26
+ title: '๐Ÿ“ฆ Order Shipped',
27
+ body,
28
+ data: {
29
+ type: 'shipment.created',
30
+ orderId,
31
+ ...(trackingNumber && { trackingNumber }),
32
+ ...(carrier && { carrier }),
33
+ },
34
+ clickAction: `/orders/${orderId}`,
35
+ priority: 'high',
36
+ };
37
+ }
38
+ /**
39
+ * Format order notification
40
+ */
41
+ function formatOrderNotification(data) {
42
+ const { type, orderId, orderNumber } = data;
43
+ const titles = {
44
+ 'order.placed': 'โœ… Order Confirmed',
45
+ 'order.delivered': '๐ŸŽ‰ Order Delivered',
46
+ 'order.canceled': 'โŒ Order Canceled',
47
+ };
48
+ const bodies = {
49
+ 'order.placed': `Your order ${orderNumber || `#${orderId}`} has been confirmed!`,
50
+ 'order.delivered': `Your order ${orderNumber || `#${orderId}`} has been delivered!`,
51
+ 'order.canceled': `Your order ${orderNumber || `#${orderId}`} has been canceled.`,
52
+ };
53
+ return {
54
+ title: titles[type],
55
+ body: bodies[type],
56
+ data: {
57
+ type,
58
+ orderId,
59
+ ...(orderNumber && { orderNumber }),
60
+ },
61
+ clickAction: `/orders/${orderId}`,
62
+ priority: type === 'order.placed' ? 'high' : 'normal',
63
+ };
64
+ }
65
+ /**
66
+ * Format return notification
67
+ */
68
+ function formatReturnNotification(data) {
69
+ const { type, returnId, orderId } = data;
70
+ const titles = {
71
+ 'return.created': '๐Ÿ”„ Return Initiated',
72
+ 'return.approved': 'โœ… Return Approved',
73
+ 'return.rejected': 'โŒ Return Rejected',
74
+ };
75
+ const bodies = {
76
+ 'return.created': `Your return request for order #${orderId} has been submitted.`,
77
+ 'return.approved': `Your return request for order #${orderId} has been approved!`,
78
+ 'return.rejected': `Your return request for order #${orderId} was rejected.`,
79
+ };
80
+ return {
81
+ title: titles[type],
82
+ body: bodies[type],
83
+ data: {
84
+ type,
85
+ returnId,
86
+ orderId,
87
+ },
88
+ clickAction: `/returns/${returnId}`,
89
+ priority: 'normal',
90
+ };
91
+ }
92
+ //# sourceMappingURL=notification-formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification-formatter.js","sourceRoot":"","sources":["../../src/utils/notification-formatter.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAYH,gEA6BC;AAKD,0DA4BC;AAKD,4DA4BC;AAlGD;;GAEG;AACH,SAAgB,0BAA0B,CACxC,IAA0B;IAE1B,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAC;IAErE,IAAI,IAAI,GAAG,eAAe,OAAO,oBAAoB,CAAC;IAEtD,IAAI,OAAO,IAAI,cAAc,EAAE,CAAC;QAC9B,IAAI,IAAI,4BAA4B,OAAO,KAAK,cAAc,EAAE,CAAC;IACnE,CAAC;SAAM,IAAI,cAAc,EAAE,CAAC;QAC1B,IAAI,IAAI,cAAc,cAAc,EAAE,CAAC;IACzC,CAAC;IAED,IAAI,iBAAiB,EAAE,CAAC;QACtB,IAAI,IAAI,wBAAwB,iBAAiB,EAAE,CAAC;IACtD,CAAC;IAED,OAAO;QACL,KAAK,EAAE,kBAAkB;QACzB,IAAI;QACJ,IAAI,EAAE;YACJ,IAAI,EAAE,kBAAkB;YACxB,OAAO;YACP,GAAG,CAAC,cAAc,IAAI,EAAE,cAAc,EAAE,CAAC;YACzC,GAAG,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,CAAC;SAC5B;QACD,WAAW,EAAE,WAAW,OAAO,EAAE;QACjC,QAAQ,EAAE,MAAM;KACjB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,uBAAuB,CACrC,IAAuB;IAEvB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IAE5C,MAAM,MAAM,GAA8C;QACxD,cAAc,EAAE,mBAAmB;QACnC,iBAAiB,EAAE,oBAAoB;QACvC,gBAAgB,EAAE,kBAAkB;KACrC,CAAC;IAEF,MAAM,MAAM,GAA8C;QACxD,cAAc,EAAE,cAAc,WAAW,IAAI,IAAI,OAAO,EAAE,sBAAsB;QAChF,iBAAiB,EAAE,cAAc,WAAW,IAAI,IAAI,OAAO,EAAE,sBAAsB;QACnF,gBAAgB,EAAE,cAAc,WAAW,IAAI,IAAI,OAAO,EAAE,qBAAqB;KAClF,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;QAClB,IAAI,EAAE;YACJ,IAAI;YACJ,OAAO;YACP,GAAG,CAAC,WAAW,IAAI,EAAE,WAAW,EAAE,CAAC;SACpC;QACD,WAAW,EAAE,WAAW,OAAO,EAAE;QACjC,QAAQ,EAAE,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ;KACtD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,wBAAwB,CACtC,IAAwB;IAExB,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAEzC,MAAM,MAAM,GAA+C;QACzD,gBAAgB,EAAE,qBAAqB;QACvC,iBAAiB,EAAE,mBAAmB;QACtC,iBAAiB,EAAE,mBAAmB;KACvC,CAAC;IAEF,MAAM,MAAM,GAA+C;QACzD,gBAAgB,EAAE,kCAAkC,OAAO,sBAAsB;QACjF,iBAAiB,EAAE,kCAAkC,OAAO,qBAAqB;QACjF,iBAAiB,EAAE,kCAAkC,OAAO,gBAAgB;KAC7E,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;QAClB,IAAI,EAAE;YACJ,IAAI;YACJ,QAAQ;YACR,OAAO;SACR;QACD,WAAW,EAAE,YAAY,QAAQ,EAAE;QACnC,QAAQ,EAAE,QAAQ;KACnB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * FCM Token Validator
3
+ * Validates Firebase Cloud Messaging device tokens
4
+ */
5
+ /**
6
+ * Validate FCM token format
7
+ * FCM tokens are typically 152+ characters, alphanumeric with special chars
8
+ */
9
+ export declare function validateFCMToken(token: string): boolean;
10
+ /**
11
+ * Validate platform value
12
+ */
13
+ export declare function validatePlatform(platform: string): platform is 'ios' | 'android';
14
+ /**
15
+ * Validate app version format (semver-like)
16
+ */
17
+ export declare function validateAppVersion(version: string): boolean;
18
+ //# sourceMappingURL=validators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAavD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,IAAI,KAAK,GAAG,SAAS,CAEhF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAQ3D"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ /**
3
+ * FCM Token Validator
4
+ * Validates Firebase Cloud Messaging device tokens
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.validateFCMToken = validateFCMToken;
8
+ exports.validatePlatform = validatePlatform;
9
+ exports.validateAppVersion = validateAppVersion;
10
+ /**
11
+ * Validate FCM token format
12
+ * FCM tokens are typically 152+ characters, alphanumeric with special chars
13
+ */
14
+ function validateFCMToken(token) {
15
+ if (!token || typeof token !== 'string') {
16
+ return false;
17
+ }
18
+ // FCM tokens are typically 152-163 characters long
19
+ if (token.length < 140 || token.length > 200) {
20
+ return false;
21
+ }
22
+ // Should contain only alphanumeric, hyphens, underscores, and colons
23
+ const validTokenRegex = /^[a-zA-Z0-9_:-]+$/;
24
+ return validTokenRegex.test(token);
25
+ }
26
+ /**
27
+ * Validate platform value
28
+ */
29
+ function validatePlatform(platform) {
30
+ return platform === 'ios' || platform === 'android';
31
+ }
32
+ /**
33
+ * Validate app version format (semver-like)
34
+ */
35
+ function validateAppVersion(version) {
36
+ if (!version || typeof version !== 'string') {
37
+ return false;
38
+ }
39
+ // Accept formats like: 1.0.0, 1.0, 1.0.0-beta, etc.
40
+ const versionRegex = /^\d+\.\d+(\.\d+)?(-[a-zA-Z0-9.-]+)?$/;
41
+ return versionRegex.test(version);
42
+ }
43
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAMH,4CAaC;AAKD,4CAEC;AAKD,gDAQC;AArCD;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,KAAa;IAC5C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACxC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,mDAAmD;IACnD,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAC7C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,qEAAqE;IACrE,MAAM,eAAe,GAAG,mBAAmB,CAAC;IAC5C,OAAO,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,SAAgB,gBAAgB,CAAC,QAAgB;IAC/C,OAAO,QAAQ,KAAK,KAAK,IAAI,QAAQ,KAAK,SAAS,CAAC;AACtD,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAAC,OAAe;IAChD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,oDAAoD;IACpD,MAAM,YAAY,GAAG,sCAAsC,CAAC;IAC5D,OAAO,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACpC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@zan-shop/push-notifications",
3
+ "version": "1.0.0",
4
+ "description": "Push notification module for Medusa.js using Firebase Cloud Messaging",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "watch": "tsc --watch",
13
+ "test": "jest",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "keywords": [
17
+ "medusa",
18
+ "medusa-plugin",
19
+ "push-notifications",
20
+ "fcm",
21
+ "firebase",
22
+ "cloud-messaging"
23
+ ],
24
+ "author": "zan shop",
25
+ "license": "MIT",
26
+ "devDependencies": {
27
+ "@medusajs/framework": "^2.0.0",
28
+ "@semantic-release/changelog": "^6.0.3",
29
+ "@semantic-release/git": "^10.0.1",
30
+ "@types/jest": "^29.5.0",
31
+ "@types/node": "^20.0.0",
32
+ "jest": "^29.5.0",
33
+ "semantic-release": "^24.0.0",
34
+ "ts-jest": "^29.1.0",
35
+ "typescript": "^5.0.0"
36
+ },
37
+ "dependencies": {
38
+ "firebase-admin": "^12.0.0"
39
+ },
40
+ "peerDependencies": {
41
+ "@medusajs/framework": "^2.0.0"
42
+ },
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "git+https://github.com/zan-shop/push-notifications.git"
49
+ },
50
+ "homepage": "https://github.com/zan-shop/push-notifications#readme",
51
+ "bugs": {
52
+ "url": "https://github.com/zan-shop/push-notifications/issues"
53
+ }
54
+ }