@blackcode_sa/metaestetics-api 1.6.14 → 1.6.15
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.
- package/dist/admin/index.d.mts +343 -2
- package/dist/admin/index.d.ts +343 -2
- package/dist/admin/index.js +246 -157
- package/dist/admin/index.mjs +238 -157
- package/package.json +1 -1
- package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +2 -2
- package/src/admin/booking/booking.admin.ts +8 -4
- package/src/admin/calendar/calendar.admin.service.ts +8 -11
- package/src/admin/index.ts +21 -0
- package/src/admin/notifications/notifications.admin.ts +12 -30
- package/src/admin/requirements/patient-requirements.admin.service.ts +1 -1
- package/src/utils/TimestampUtils.ts +122 -17
package/src/admin/index.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { NotificationsAdmin } from "./notifications/notifications.admin";
|
|
2
|
+
import * as admin from "firebase-admin";
|
|
3
|
+
import { TimestampUtils } from "../utils/TimestampUtils";
|
|
2
4
|
|
|
3
5
|
import { UserRole } from "../types";
|
|
4
6
|
// Import types needed by admin consumers (like Cloud Functions)
|
|
@@ -111,3 +113,22 @@ console.log("[Admin Module] Initialized and services exported.");
|
|
|
111
113
|
// if they have dependencies (like Firestore db) that need to be injected.
|
|
112
114
|
// The initialization pattern might differ depending on how this module is consumed
|
|
113
115
|
// (e.g., within a larger NestJS app vs. standalone Cloud Functions).
|
|
116
|
+
|
|
117
|
+
// Initialize TimestampUtils for server-side use
|
|
118
|
+
TimestampUtils.enableServerMode();
|
|
119
|
+
|
|
120
|
+
// Export all admin services that are needed
|
|
121
|
+
export * from "./booking/booking.admin";
|
|
122
|
+
export * from "./booking/booking.calculator";
|
|
123
|
+
export * from "./booking/booking.types";
|
|
124
|
+
export * from "./calendar/calendar.admin.service";
|
|
125
|
+
export * from "./documentation-templates/document-manager.admin";
|
|
126
|
+
export * from "./logger";
|
|
127
|
+
export * from "./mailing/appointment/appointment.mailing.service";
|
|
128
|
+
export * from "./notifications/notifications.admin";
|
|
129
|
+
export * from "./requirements/patient-requirements.admin.service";
|
|
130
|
+
export * from "./aggregation/appointment/appointment.aggregation.service";
|
|
131
|
+
|
|
132
|
+
// Re-export types that Cloud Functions might need direct access to
|
|
133
|
+
export * from "../types/appointment";
|
|
134
|
+
// Add other types as needed
|
|
@@ -277,10 +277,7 @@ export class NotificationsAdmin {
|
|
|
277
277
|
.toLocaleDateString()} is confirmed.`;
|
|
278
278
|
}
|
|
279
279
|
|
|
280
|
-
const
|
|
281
|
-
const clientCompatibleNotificationTime = TimestampUtils.adminToClient(
|
|
282
|
-
adminTsNow
|
|
283
|
-
) as FirebaseClientTimestamp;
|
|
280
|
+
const notificationTimestampForDb = admin.firestore.Timestamp.now();
|
|
284
281
|
|
|
285
282
|
const notificationData: Omit<
|
|
286
283
|
Notification,
|
|
@@ -289,7 +286,7 @@ export class NotificationsAdmin {
|
|
|
289
286
|
userId: recipientUserId,
|
|
290
287
|
userRole: recipientRole,
|
|
291
288
|
notificationType: NotificationType.APPOINTMENT_STATUS_CHANGE,
|
|
292
|
-
notificationTime:
|
|
289
|
+
notificationTime: notificationTimestampForDb as any,
|
|
293
290
|
notificationTokens: recipientExpoTokens,
|
|
294
291
|
title,
|
|
295
292
|
body,
|
|
@@ -353,10 +350,7 @@ export class NotificationsAdmin {
|
|
|
353
350
|
}
|
|
354
351
|
}
|
|
355
352
|
|
|
356
|
-
const
|
|
357
|
-
const clientCompatibleNotificationTime = TimestampUtils.adminToClient(
|
|
358
|
-
adminTsNow
|
|
359
|
-
) as FirebaseClientTimestamp;
|
|
353
|
+
const notificationTimestampForDb = admin.firestore.Timestamp.now();
|
|
360
354
|
|
|
361
355
|
const notificationData: Omit<
|
|
362
356
|
Notification,
|
|
@@ -365,7 +359,7 @@ export class NotificationsAdmin {
|
|
|
365
359
|
userId: recipientUserId,
|
|
366
360
|
userRole: recipientRole,
|
|
367
361
|
notificationType: NotificationType.APPOINTMENT_CANCELLED,
|
|
368
|
-
notificationTime:
|
|
362
|
+
notificationTime: notificationTimestampForDb as any,
|
|
369
363
|
notificationTokens: recipientExpoTokens,
|
|
370
364
|
title,
|
|
371
365
|
body,
|
|
@@ -404,10 +398,7 @@ export class NotificationsAdmin {
|
|
|
404
398
|
const title = "Appointment Reschedule Proposed";
|
|
405
399
|
const body = `Action Required: A new time has been proposed for your appointment for ${appointment.procedureInfo.name}. Please review in the app.`;
|
|
406
400
|
|
|
407
|
-
const
|
|
408
|
-
const clientCompatibleNotificationTime = TimestampUtils.adminToClient(
|
|
409
|
-
adminTsNow
|
|
410
|
-
) as FirebaseClientTimestamp;
|
|
401
|
+
const notificationTimestampForDb = admin.firestore.Timestamp.now();
|
|
411
402
|
|
|
412
403
|
const notificationData: Omit<
|
|
413
404
|
Notification,
|
|
@@ -416,7 +407,7 @@ export class NotificationsAdmin {
|
|
|
416
407
|
userId: patientUserId,
|
|
417
408
|
userRole: UserRole.PATIENT,
|
|
418
409
|
notificationType: NotificationType.APPOINTMENT_RESCHEDULED_PROPOSAL,
|
|
419
|
-
notificationTime:
|
|
410
|
+
notificationTime: notificationTimestampForDb as any,
|
|
420
411
|
notificationTokens: patientExpoTokens,
|
|
421
412
|
title,
|
|
422
413
|
body,
|
|
@@ -458,10 +449,7 @@ export class NotificationsAdmin {
|
|
|
458
449
|
.toDate()
|
|
459
450
|
.toLocaleDateString()} is now ${appointment.paymentStatus}.`;
|
|
460
451
|
|
|
461
|
-
const
|
|
462
|
-
const clientCompatibleNotificationTime = TimestampUtils.adminToClient(
|
|
463
|
-
adminTsNow
|
|
464
|
-
) as FirebaseClientTimestamp;
|
|
452
|
+
const notificationTimestampForDb = admin.firestore.Timestamp.now();
|
|
465
453
|
|
|
466
454
|
const notificationType =
|
|
467
455
|
appointment.paymentStatus === PaymentStatus.PAID
|
|
@@ -475,7 +463,7 @@ export class NotificationsAdmin {
|
|
|
475
463
|
userId: patientUserId,
|
|
476
464
|
userRole: UserRole.PATIENT,
|
|
477
465
|
notificationType: notificationType,
|
|
478
|
-
notificationTime:
|
|
466
|
+
notificationTime: notificationTimestampForDb as any,
|
|
479
467
|
notificationTokens: patientExpoTokens,
|
|
480
468
|
title,
|
|
481
469
|
body,
|
|
@@ -514,10 +502,7 @@ export class NotificationsAdmin {
|
|
|
514
502
|
const title = "Leave a Review";
|
|
515
503
|
const body = `How was your recent appointment for ${appointment.procedureInfo.name}? We'd love to hear your feedback!`;
|
|
516
504
|
|
|
517
|
-
const
|
|
518
|
-
const clientCompatibleNotificationTime = TimestampUtils.adminToClient(
|
|
519
|
-
adminTsNow
|
|
520
|
-
) as FirebaseClientTimestamp;
|
|
505
|
+
const notificationTimestampForDb = admin.firestore.Timestamp.now();
|
|
521
506
|
|
|
522
507
|
const notificationData: Omit<
|
|
523
508
|
Notification,
|
|
@@ -526,7 +511,7 @@ export class NotificationsAdmin {
|
|
|
526
511
|
userId: patientUserId,
|
|
527
512
|
userRole: UserRole.PATIENT,
|
|
528
513
|
notificationType: NotificationType.REVIEW_REQUEST,
|
|
529
|
-
notificationTime:
|
|
514
|
+
notificationTime: notificationTimestampForDb as any,
|
|
530
515
|
notificationTokens: patientExpoTokens,
|
|
531
516
|
title,
|
|
532
517
|
body,
|
|
@@ -576,10 +561,7 @@ export class NotificationsAdmin {
|
|
|
576
561
|
.toDate()
|
|
577
562
|
.toLocaleDateString()}.`;
|
|
578
563
|
|
|
579
|
-
const
|
|
580
|
-
const clientCompatibleNotificationTime = TimestampUtils.adminToClient(
|
|
581
|
-
adminTsNow
|
|
582
|
-
) as FirebaseClientTimestamp;
|
|
564
|
+
const notificationTimestampForDb = admin.firestore.Timestamp.now();
|
|
583
565
|
|
|
584
566
|
const tempNotificationType = NotificationType.GENERAL_MESSAGE;
|
|
585
567
|
|
|
@@ -590,7 +572,7 @@ export class NotificationsAdmin {
|
|
|
590
572
|
userId: recipientUserId,
|
|
591
573
|
userRole: UserRole.PRACTITIONER,
|
|
592
574
|
notificationType: tempNotificationType,
|
|
593
|
-
notificationTime:
|
|
575
|
+
notificationTime: notificationTimestampForDb as any,
|
|
594
576
|
notificationTokens: recipientExpoTokens,
|
|
595
577
|
title,
|
|
596
578
|
body,
|
|
@@ -176,7 +176,7 @@ export class PatientRequirementsAdminService {
|
|
|
176
176
|
userId: patientId,
|
|
177
177
|
userRole: UserRole.PATIENT,
|
|
178
178
|
notificationType: NotificationType.REQUIREMENT_INSTRUCTION_DUE,
|
|
179
|
-
notificationTime: currentInstruction.dueTime, //
|
|
179
|
+
notificationTime: currentInstruction.dueTime as any, // dueTime should be an admin.firestore.Timestamp already
|
|
180
180
|
notificationTokens: patientExpoTokens,
|
|
181
181
|
title: `Reminder: ${instance.requirementName}`,
|
|
182
182
|
body: currentInstruction.instructionText,
|
|
@@ -1,22 +1,62 @@
|
|
|
1
1
|
import * as admin from "firebase-admin";
|
|
2
2
|
import { Timestamp as ClientTimestamp } from "firebase/firestore";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Detect if we're running in a server environment (like Cloud Functions)
|
|
6
|
+
* or compiled for server usage
|
|
7
|
+
*/
|
|
8
|
+
const IS_SERVER_ENV =
|
|
9
|
+
process.env.NODE_ENV === "production" ||
|
|
10
|
+
process.env.FUNCTIONS_EMULATOR === "true" ||
|
|
11
|
+
process.env.FIREBASE_CONFIG !== undefined;
|
|
12
|
+
|
|
4
13
|
/**
|
|
5
14
|
* Utilities for managing timestamps across client and server-side Firebase code.
|
|
6
15
|
* This module provides conversion functions to ensure timestamp compatibility
|
|
7
16
|
* between admin and client Firebase SDKs.
|
|
8
17
|
*/
|
|
9
18
|
export class TimestampUtils {
|
|
19
|
+
/**
|
|
20
|
+
* Flag to force server mode where admin timestamps are preserved
|
|
21
|
+
* This should be true in Cloud Functions environments
|
|
22
|
+
*/
|
|
23
|
+
private static serverMode = IS_SERVER_ENV;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Enables server mode where admin timestamps are preserved when saving
|
|
27
|
+
* to Firestore via the admin SDK
|
|
28
|
+
*/
|
|
29
|
+
static enableServerMode(): void {
|
|
30
|
+
this.serverMode = true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Disables server mode - use this only for client-side or mixed environments
|
|
35
|
+
*/
|
|
36
|
+
static disableServerMode(): void {
|
|
37
|
+
this.serverMode = false;
|
|
38
|
+
}
|
|
39
|
+
|
|
10
40
|
/**
|
|
11
41
|
* Converts an admin Firestore Timestamp to a client Firestore Timestamp
|
|
42
|
+
* In server mode, returns the original admin timestamp for storage consistency
|
|
43
|
+
*
|
|
12
44
|
* @param adminTimestamp - Admin SDK Timestamp (from firebase-admin)
|
|
13
|
-
* @returns A client SDK Timestamp (from firebase/firestore) with same seconds/nanoseconds
|
|
45
|
+
* @returns A client SDK Timestamp (from firebase/firestore) with same seconds/nanoseconds,
|
|
46
|
+
* or the original admin timestamp in server mode,
|
|
47
|
+
* or null if input is null
|
|
14
48
|
*/
|
|
15
49
|
static adminToClient(
|
|
16
50
|
adminTimestamp: admin.firestore.Timestamp | null
|
|
17
|
-
): ClientTimestamp | null {
|
|
51
|
+
): ClientTimestamp | admin.firestore.Timestamp | null {
|
|
18
52
|
if (!adminTimestamp) return null;
|
|
19
53
|
|
|
54
|
+
// In server mode (Cloud Functions), just return the admin timestamp
|
|
55
|
+
if (this.serverMode) {
|
|
56
|
+
return adminTimestamp;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// In client mode, convert to client timestamp
|
|
20
60
|
return new ClientTimestamp(
|
|
21
61
|
adminTimestamp.seconds,
|
|
22
62
|
adminTimestamp.nanoseconds
|
|
@@ -40,8 +80,21 @@ export class TimestampUtils {
|
|
|
40
80
|
}
|
|
41
81
|
|
|
42
82
|
/**
|
|
43
|
-
* Creates a
|
|
44
|
-
* @returns A
|
|
83
|
+
* Creates a timestamp for the current time in the appropriate format based on environment
|
|
84
|
+
* @returns A timestamp for the current time (admin timestamp in server mode, client in client mode)
|
|
85
|
+
*/
|
|
86
|
+
static nowAsTimestamp(): admin.firestore.Timestamp | ClientTimestamp {
|
|
87
|
+
const now = admin.firestore.Timestamp.now();
|
|
88
|
+
// In server mode, return the admin timestamp directly
|
|
89
|
+
if (this.serverMode) {
|
|
90
|
+
return now;
|
|
91
|
+
}
|
|
92
|
+
// In client mode, convert to client timestamp
|
|
93
|
+
return this.adminToClient(now) as ClientTimestamp;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @deprecated Use nowAsTimestamp() instead for better cross-environment compatibility
|
|
45
98
|
*/
|
|
46
99
|
static nowAsClient(): ClientTimestamp {
|
|
47
100
|
const now = admin.firestore.Timestamp.now();
|
|
@@ -49,33 +102,87 @@ export class TimestampUtils {
|
|
|
49
102
|
}
|
|
50
103
|
|
|
51
104
|
/**
|
|
52
|
-
* Converts a Date object to a
|
|
105
|
+
* Converts a Date object to a timestamp in the appropriate format based on environment
|
|
53
106
|
* @param date - JavaScript Date object
|
|
54
|
-
* @returns A client
|
|
107
|
+
* @returns A timestamp (admin timestamp in server mode, client in client mode) or null if input is null
|
|
55
108
|
*/
|
|
56
|
-
static
|
|
109
|
+
static dateToTimestamp(
|
|
110
|
+
date: Date | null
|
|
111
|
+
): admin.firestore.Timestamp | ClientTimestamp | null {
|
|
57
112
|
if (!date) return null;
|
|
58
113
|
|
|
114
|
+
if (this.serverMode) {
|
|
115
|
+
return admin.firestore.Timestamp.fromDate(date);
|
|
116
|
+
}
|
|
117
|
+
|
|
59
118
|
return ClientTimestamp.fromDate(date);
|
|
60
119
|
}
|
|
61
120
|
|
|
62
121
|
/**
|
|
63
|
-
*
|
|
64
|
-
|
|
65
|
-
|
|
122
|
+
* @deprecated Use dateToTimestamp() instead for better cross-environment compatibility
|
|
123
|
+
*/
|
|
124
|
+
static dateToClientTimestamp(date: Date | null): ClientTimestamp | null {
|
|
125
|
+
if (!date) return null;
|
|
126
|
+
return ClientTimestamp.fromDate(date);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @deprecated Use dateToTimestamp() instead for better cross-environment compatibility
|
|
66
131
|
*/
|
|
67
132
|
static dateToAdminTimestamp(
|
|
68
133
|
date: Date | null
|
|
69
134
|
): admin.firestore.Timestamp | null {
|
|
70
135
|
if (!date) return null;
|
|
71
|
-
|
|
72
136
|
return admin.firestore.Timestamp.fromDate(date);
|
|
73
137
|
}
|
|
74
138
|
|
|
75
139
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
|
|
140
|
+
* Gets a server timestamp field value for use in create/update operations
|
|
141
|
+
* Works in both admin and client environments
|
|
142
|
+
*/
|
|
143
|
+
static serverTimestamp(): admin.firestore.FieldValue | any {
|
|
144
|
+
if (this.serverMode) {
|
|
145
|
+
return admin.firestore.FieldValue.serverTimestamp();
|
|
146
|
+
}
|
|
147
|
+
// In client mode, we'd need to import from firebase/firestore
|
|
148
|
+
// This would be implemented for client environments
|
|
149
|
+
throw new Error("Server timestamp in client mode not implemented");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* For objects with mixed timestamp types, ensures all timestamps are
|
|
154
|
+
* in the correct format for the current environment
|
|
155
|
+
*/
|
|
156
|
+
static normalizeTimestamps<T>(obj: T): T {
|
|
157
|
+
if (!obj || typeof obj !== "object") {
|
|
158
|
+
return obj;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (obj instanceof admin.firestore.Timestamp) {
|
|
162
|
+
return this.serverMode ? obj : (this.adminToClient(obj) as unknown as T);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (obj instanceof ClientTimestamp && this.serverMode) {
|
|
166
|
+
return this.clientToAdmin(obj) as unknown as T;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (Array.isArray(obj)) {
|
|
170
|
+
return obj.map((item) => this.normalizeTimestamps(item)) as unknown as T;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const result = { ...obj } as any;
|
|
174
|
+
|
|
175
|
+
for (const key in result) {
|
|
176
|
+
if (Object.prototype.hasOwnProperty.call(result, key)) {
|
|
177
|
+
result[key] = this.normalizeTimestamps(result[key]);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return result as T;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* @deprecated Use normalizeTimestamps() instead for better cross-environment compatibility
|
|
79
186
|
*/
|
|
80
187
|
static convertObjectTimestampsAdminToClient<T>(obj: T): T {
|
|
81
188
|
if (!obj || typeof obj !== "object") {
|
|
@@ -104,9 +211,7 @@ export class TimestampUtils {
|
|
|
104
211
|
}
|
|
105
212
|
|
|
106
213
|
/**
|
|
107
|
-
*
|
|
108
|
-
* @param obj - Object that may contain client Firestore Timestamps
|
|
109
|
-
* @returns The same object with all client Timestamps converted to admin Timestamps
|
|
214
|
+
* @deprecated Use normalizeTimestamps() instead for better cross-environment compatibility
|
|
110
215
|
*/
|
|
111
216
|
static convertObjectTimestampsClientToAdmin<T>(obj: T): T {
|
|
112
217
|
if (!obj || typeof obj !== "object") {
|