@blackcode_sa/metaestetics-api 1.13.3 → 1.13.5
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 +15 -28
- package/dist/admin/index.d.ts +15 -28
- package/dist/index.d.mts +18 -30
- package/dist/index.d.ts +18 -30
- package/dist/index.js +11 -3
- package/dist/index.mjs +11 -3
- package/package.json +121 -119
- package/src/__mocks__/firstore.ts +10 -10
- package/src/admin/aggregation/README.md +79 -79
- package/src/admin/aggregation/appointment/README.md +128 -128
- package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +1984 -1984
- package/src/admin/aggregation/appointment/index.ts +1 -1
- package/src/admin/aggregation/clinic/README.md +52 -52
- package/src/admin/aggregation/clinic/clinic.aggregation.service.ts +703 -703
- package/src/admin/aggregation/clinic/index.ts +1 -1
- package/src/admin/aggregation/forms/README.md +13 -13
- package/src/admin/aggregation/forms/filled-forms.aggregation.service.ts +322 -322
- package/src/admin/aggregation/forms/index.ts +1 -1
- package/src/admin/aggregation/index.ts +8 -8
- package/src/admin/aggregation/patient/README.md +27 -27
- package/src/admin/aggregation/patient/index.ts +1 -1
- package/src/admin/aggregation/patient/patient.aggregation.service.ts +141 -141
- package/src/admin/aggregation/practitioner/README.md +42 -42
- package/src/admin/aggregation/practitioner/index.ts +1 -1
- package/src/admin/aggregation/practitioner/practitioner.aggregation.service.ts +433 -433
- package/src/admin/aggregation/practitioner-invite/index.ts +1 -1
- package/src/admin/aggregation/practitioner-invite/practitioner-invite.aggregation.service.ts +961 -961
- package/src/admin/aggregation/procedure/README.md +43 -43
- package/src/admin/aggregation/procedure/index.ts +1 -1
- package/src/admin/aggregation/procedure/procedure.aggregation.service.ts +702 -702
- package/src/admin/aggregation/reviews/index.ts +1 -1
- package/src/admin/aggregation/reviews/reviews.aggregation.service.ts +689 -689
- package/src/admin/analytics/analytics.admin.service.ts +278 -278
- package/src/admin/analytics/index.ts +2 -2
- package/src/admin/booking/README.md +125 -125
- package/src/admin/booking/booking.admin.ts +1037 -1037
- package/src/admin/booking/booking.calculator.ts +712 -712
- package/src/admin/booking/booking.types.ts +59 -59
- package/src/admin/booking/index.ts +3 -3
- package/src/admin/booking/timezones-problem.md +185 -185
- package/src/admin/calendar/README.md +7 -7
- package/src/admin/calendar/calendar.admin.service.ts +345 -345
- package/src/admin/calendar/index.ts +1 -1
- package/src/admin/documentation-templates/document-manager.admin.ts +260 -260
- package/src/admin/documentation-templates/index.ts +1 -1
- package/src/admin/free-consultation/free-consultation-utils.admin.ts +148 -148
- package/src/admin/free-consultation/index.ts +1 -1
- package/src/admin/index.ts +81 -81
- package/src/admin/logger/index.ts +78 -78
- package/src/admin/mailing/README.md +95 -95
- package/src/admin/mailing/appointment/appointment.mailing.service.ts +732 -732
- package/src/admin/mailing/appointment/index.ts +1 -1
- package/src/admin/mailing/appointment/templates/patient/appointment-confirmed.html +40 -40
- package/src/admin/mailing/base.mailing.service.ts +208 -208
- package/src/admin/mailing/index.ts +3 -3
- package/src/admin/mailing/practitionerInvite/existing-practitioner-invite.mailing.ts +611 -611
- package/src/admin/mailing/practitionerInvite/index.ts +2 -2
- package/src/admin/mailing/practitionerInvite/practitionerInvite.mailing.ts +395 -395
- package/src/admin/mailing/practitionerInvite/templates/existing-practitioner-invitation.template.ts +155 -155
- package/src/admin/mailing/practitionerInvite/templates/invitation.template.ts +101 -101
- package/src/admin/mailing/practitionerInvite/templates/invite-accepted-notification.template.ts +228 -228
- package/src/admin/mailing/practitionerInvite/templates/invite-rejected-notification.template.ts +242 -242
- package/src/admin/notifications/index.ts +1 -1
- package/src/admin/notifications/notifications.admin.ts +710 -710
- package/src/admin/requirements/README.md +128 -128
- package/src/admin/requirements/index.ts +1 -1
- package/src/admin/requirements/patient-requirements.admin.service.ts +475 -475
- package/src/admin/users/index.ts +1 -1
- package/src/admin/users/user-profile.admin.ts +405 -405
- package/src/backoffice/constants/certification.constants.ts +13 -13
- package/src/backoffice/constants/index.ts +1 -1
- package/src/backoffice/errors/backoffice.errors.ts +181 -181
- package/src/backoffice/errors/index.ts +1 -1
- package/src/backoffice/expo-safe/README.md +26 -26
- package/src/backoffice/expo-safe/index.ts +41 -41
- package/src/backoffice/index.ts +5 -5
- package/src/backoffice/services/FIXES_README.md +102 -102
- package/src/backoffice/services/README.md +57 -57
- package/src/backoffice/services/analytics.service.proposal.md +863 -863
- package/src/backoffice/services/analytics.service.summary.md +143 -143
- package/src/backoffice/services/brand.service.ts +256 -256
- package/src/backoffice/services/category.service.ts +384 -384
- package/src/backoffice/services/constants.service.ts +385 -385
- package/src/backoffice/services/documentation-template.service.ts +202 -202
- package/src/backoffice/services/index.ts +10 -10
- package/src/backoffice/services/migrate-products.ts +116 -116
- package/src/backoffice/services/product.service.ts +553 -553
- package/src/backoffice/services/requirement.service.ts +235 -235
- package/src/backoffice/services/subcategory.service.ts +461 -461
- package/src/backoffice/services/technology.service.ts +1151 -1151
- package/src/backoffice/types/README.md +12 -12
- package/src/backoffice/types/admin-constants.types.ts +69 -69
- package/src/backoffice/types/brand.types.ts +29 -29
- package/src/backoffice/types/category.types.ts +67 -67
- package/src/backoffice/types/documentation-templates.types.ts +28 -28
- package/src/backoffice/types/index.ts +10 -10
- package/src/backoffice/types/procedure-product.types.ts +38 -38
- package/src/backoffice/types/product.types.ts +240 -240
- package/src/backoffice/types/requirement.types.ts +63 -63
- package/src/backoffice/types/static/README.md +18 -18
- package/src/backoffice/types/static/blocking-condition.types.ts +21 -21
- package/src/backoffice/types/static/certification.types.ts +37 -37
- package/src/backoffice/types/static/contraindication.types.ts +19 -19
- package/src/backoffice/types/static/index.ts +6 -6
- package/src/backoffice/types/static/pricing.types.ts +16 -16
- package/src/backoffice/types/static/procedure-family.types.ts +14 -14
- package/src/backoffice/types/static/treatment-benefit.types.ts +22 -22
- package/src/backoffice/types/subcategory.types.ts +34 -34
- package/src/backoffice/types/technology.types.ts +168 -168
- package/src/backoffice/validations/index.ts +1 -1
- package/src/backoffice/validations/schemas.ts +164 -164
- package/src/config/__mocks__/firebase.ts +99 -99
- package/src/config/firebase.ts +78 -78
- package/src/config/index.ts +9 -9
- package/src/errors/auth.error.ts +6 -6
- package/src/errors/auth.errors.ts +200 -200
- package/src/errors/clinic.errors.ts +32 -32
- package/src/errors/firebase.errors.ts +47 -47
- package/src/errors/user.errors.ts +99 -99
- package/src/index.backup.ts +407 -407
- package/src/index.ts +6 -6
- package/src/locales/en.ts +31 -31
- package/src/recommender/admin/index.ts +1 -1
- package/src/recommender/admin/services/recommender.service.admin.ts +5 -5
- package/src/recommender/front/index.ts +1 -1
- package/src/recommender/front/services/onboarding.service.ts +5 -5
- package/src/recommender/front/services/recommender.service.ts +3 -3
- package/src/recommender/index.ts +1 -1
- package/src/services/PATIENTAUTH.MD +197 -197
- package/src/services/README.md +106 -106
- package/src/services/__tests__/auth/auth.mock.test.ts +17 -17
- package/src/services/__tests__/auth/auth.setup.ts +293 -293
- package/src/services/__tests__/auth.service.test.ts +346 -346
- package/src/services/__tests__/base.service.test.ts +77 -77
- package/src/services/__tests__/user.service.test.ts +528 -528
- package/src/services/analytics/ARCHITECTURE.md +199 -199
- package/src/services/analytics/CLOUD_FUNCTIONS.md +225 -225
- package/src/services/analytics/GROUPED_ANALYTICS.md +501 -501
- package/src/services/analytics/QUICK_START.md +393 -393
- package/src/services/analytics/README.md +304 -304
- package/src/services/analytics/SUMMARY.md +141 -141
- package/src/services/analytics/TRENDS.md +380 -380
- package/src/services/analytics/USAGE_GUIDE.md +518 -518
- package/src/services/analytics/analytics-cloud.service.ts +222 -222
- package/src/services/analytics/analytics.service.ts +2142 -2142
- package/src/services/analytics/index.ts +4 -4
- package/src/services/analytics/review-analytics.service.ts +941 -941
- package/src/services/analytics/utils/appointment-filtering.utils.ts +138 -138
- package/src/services/analytics/utils/cost-calculation.utils.ts +182 -182
- package/src/services/analytics/utils/grouping.utils.ts +434 -434
- package/src/services/analytics/utils/stored-analytics.utils.ts +347 -347
- package/src/services/analytics/utils/time-calculation.utils.ts +186 -186
- package/src/services/analytics/utils/trend-calculation.utils.ts +200 -200
- package/src/services/appointment/README.md +17 -17
- package/src/services/appointment/appointment.service.ts +2558 -2558
- package/src/services/appointment/index.ts +1 -1
- package/src/services/appointment/utils/appointment.utils.ts +552 -552
- package/src/services/appointment/utils/extended-procedure.utils.ts +314 -314
- package/src/services/appointment/utils/form-initialization.utils.ts +225 -225
- package/src/services/appointment/utils/recommended-procedure.utils.ts +195 -195
- package/src/services/appointment/utils/zone-management.utils.ts +353 -353
- package/src/services/appointment/utils/zone-photo.utils.ts +152 -152
- package/src/services/auth/auth.service.ts +989 -989
- package/src/services/auth/auth.v2.service.ts +961 -961
- package/src/services/auth/index.ts +7 -7
- package/src/services/auth/utils/error.utils.ts +90 -90
- package/src/services/auth/utils/firebase.utils.ts +49 -49
- package/src/services/auth/utils/index.ts +21 -21
- package/src/services/auth/utils/practitioner.utils.ts +125 -125
- package/src/services/base.service.ts +41 -41
- package/src/services/calendar/calendar.service.ts +1077 -1077
- package/src/services/calendar/calendar.v2.service.ts +1683 -1683
- package/src/services/calendar/calendar.v3.service.ts +313 -313
- package/src/services/calendar/externalCalendar.service.ts +178 -178
- package/src/services/calendar/index.ts +5 -5
- package/src/services/calendar/synced-calendars.service.ts +743 -743
- package/src/services/calendar/utils/appointment.utils.ts +265 -265
- package/src/services/calendar/utils/calendar-event.utils.ts +646 -646
- package/src/services/calendar/utils/clinic.utils.ts +237 -237
- package/src/services/calendar/utils/docs.utils.ts +157 -157
- package/src/services/calendar/utils/google-calendar.utils.ts +697 -697
- package/src/services/calendar/utils/index.ts +8 -8
- package/src/services/calendar/utils/patient.utils.ts +198 -198
- package/src/services/calendar/utils/practitioner.utils.ts +221 -221
- package/src/services/calendar/utils/synced-calendar.utils.ts +472 -472
- package/src/services/clinic/README.md +204 -204
- package/src/services/clinic/__tests__/clinic-admin.service.test.ts +287 -287
- package/src/services/clinic/__tests__/clinic-group.service.test.ts +352 -352
- package/src/services/clinic/__tests__/clinic.service.test.ts +354 -354
- package/src/services/clinic/billing-transactions.service.ts +217 -217
- package/src/services/clinic/clinic-admin.service.ts +202 -202
- package/src/services/clinic/clinic-group.service.ts +310 -310
- package/src/services/clinic/clinic.service.ts +708 -708
- package/src/services/clinic/index.ts +5 -5
- package/src/services/clinic/practitioner-invite.service.ts +519 -519
- package/src/services/clinic/utils/admin.utils.ts +551 -551
- package/src/services/clinic/utils/clinic-group.utils.ts +646 -646
- package/src/services/clinic/utils/clinic.utils.ts +949 -949
- package/src/services/clinic/utils/filter.utils.d.ts +23 -23
- package/src/services/clinic/utils/filter.utils.ts +446 -446
- package/src/services/clinic/utils/index.ts +11 -11
- package/src/services/clinic/utils/photos.utils.ts +188 -188
- package/src/services/clinic/utils/search.utils.ts +84 -84
- package/src/services/clinic/utils/tag.utils.ts +124 -124
- package/src/services/documentation-templates/documentation-template.service.ts +537 -537
- package/src/services/documentation-templates/filled-document.service.ts +587 -587
- package/src/services/documentation-templates/index.ts +2 -2
- package/src/services/index.ts +14 -14
- package/src/services/media/index.ts +1 -1
- package/src/services/media/media.service.ts +418 -418
- package/src/services/notifications/__tests__/notification.service.test.ts +242 -242
- package/src/services/notifications/index.ts +1 -1
- package/src/services/notifications/notification.service.ts +215 -215
- package/src/services/patient/README.md +48 -48
- package/src/services/patient/To-Do.md +43 -43
- package/src/services/patient/__tests__/patient.service.test.ts +294 -294
- package/src/services/patient/index.ts +2 -2
- package/src/services/patient/patient.service.ts +883 -883
- package/src/services/patient/patientRequirements.service.ts +285 -285
- package/src/services/patient/utils/aesthetic-analysis.utils.ts +176 -176
- package/src/services/patient/utils/clinic.utils.ts +80 -80
- package/src/services/patient/utils/docs.utils.ts +142 -142
- package/src/services/patient/utils/index.ts +9 -9
- package/src/services/patient/utils/location.utils.ts +126 -126
- package/src/services/patient/utils/medical-stuff.utils.ts +143 -143
- package/src/services/patient/utils/medical.utils.ts +458 -458
- package/src/services/patient/utils/practitioner.utils.ts +260 -260
- package/src/services/patient/utils/profile.utils.ts +510 -510
- package/src/services/patient/utils/sensitive.utils.ts +260 -260
- package/src/services/patient/utils/token.utils.ts +211 -211
- package/src/services/practitioner/README.md +145 -145
- package/src/services/practitioner/index.ts +1 -1
- package/src/services/practitioner/practitioner.service.ts +1742 -1742
- package/src/services/procedure/README.md +163 -163
- package/src/services/procedure/index.ts +1 -1
- package/src/services/procedure/procedure.service.ts +2200 -2191
- package/src/services/reviews/index.ts +1 -1
- package/src/services/reviews/reviews.service.ts +734 -734
- package/src/services/user/index.ts +1 -1
- package/src/services/user/user.service.ts +489 -489
- package/src/services/user/user.v2.service.ts +466 -466
- package/src/types/analytics/analytics.types.ts +597 -597
- package/src/types/analytics/grouped-analytics.types.ts +173 -173
- package/src/types/analytics/index.ts +4 -4
- package/src/types/analytics/stored-analytics.types.ts +137 -137
- package/src/types/appointment/index.ts +480 -480
- package/src/types/calendar/index.ts +258 -258
- package/src/types/calendar/synced-calendar.types.ts +66 -66
- package/src/types/clinic/index.ts +498 -489
- package/src/types/clinic/practitioner-invite.types.ts +91 -91
- package/src/types/clinic/preferences.types.ts +159 -159
- package/src/types/clinic/to-do +3 -3
- package/src/types/documentation-templates/index.ts +308 -308
- package/src/types/index.ts +47 -47
- package/src/types/notifications/README.md +77 -77
- package/src/types/notifications/index.ts +286 -286
- package/src/types/patient/aesthetic-analysis.types.ts +66 -66
- package/src/types/patient/allergies.ts +58 -58
- package/src/types/patient/index.ts +275 -275
- package/src/types/patient/medical-info.types.ts +152 -152
- package/src/types/patient/patient-requirements.ts +92 -92
- package/src/types/patient/token.types.ts +61 -61
- package/src/types/practitioner/index.ts +206 -206
- package/src/types/procedure/index.ts +181 -181
- package/src/types/profile/index.ts +39 -39
- package/src/types/reviews/index.ts +132 -132
- package/src/types/tz-lookup.d.ts +4 -4
- package/src/types/user/index.ts +38 -38
- package/src/utils/TIMESTAMPS.md +176 -176
- package/src/utils/TimestampUtils.ts +241 -241
- package/src/utils/index.ts +1 -1
- package/src/validations/appointment.schema.ts +574 -574
- package/src/validations/calendar.schema.ts +225 -225
- package/src/validations/clinic.schema.ts +494 -493
- package/src/validations/common.schema.ts +25 -25
- package/src/validations/documentation-templates/index.ts +1 -1
- package/src/validations/documentation-templates/template.schema.ts +220 -220
- package/src/validations/documentation-templates.schema.ts +10 -10
- package/src/validations/index.ts +20 -20
- package/src/validations/media.schema.ts +10 -10
- package/src/validations/notification.schema.ts +90 -90
- package/src/validations/patient/aesthetic-analysis.schema.ts +55 -55
- package/src/validations/patient/medical-info.schema.ts +125 -125
- package/src/validations/patient/patient-requirements.schema.ts +84 -84
- package/src/validations/patient/token.schema.ts +29 -29
- package/src/validations/patient.schema.ts +217 -217
- package/src/validations/practitioner.schema.ts +222 -222
- package/src/validations/procedure-product.schema.ts +41 -41
- package/src/validations/procedure.schema.ts +124 -124
- package/src/validations/profile-info.schema.ts +41 -41
- package/src/validations/reviews.schema.ts +195 -195
- package/src/validations/schemas.ts +104 -104
- package/src/validations/shared.schema.ts +78 -78
package/src/utils/TIMESTAMPS.md
CHANGED
|
@@ -1,176 +1,176 @@
|
|
|
1
|
-
# Timestamp Management Strategy
|
|
2
|
-
|
|
3
|
-
## Problem Statement
|
|
4
|
-
|
|
5
|
-
Firebase provides two different Timestamp implementations across its SDKs:
|
|
6
|
-
|
|
7
|
-
1. **Client-side Timestamp**: `import { Timestamp } from 'firebase/firestore'`
|
|
8
|
-
|
|
9
|
-
- Used in client applications (web, mobile)
|
|
10
|
-
- Lives in the `firebase/firestore` package
|
|
11
|
-
|
|
12
|
-
2. **Admin-side Timestamp**: `import * as admin from 'firebase-admin'; admin.firestore.Timestamp`
|
|
13
|
-
- Used in server-side code (Cloud Functions)
|
|
14
|
-
- Lives in the `firebase-admin` package
|
|
15
|
-
|
|
16
|
-
These types are structurally similar but are different JavaScript classes, causing type conflicts when:
|
|
17
|
-
|
|
18
|
-
- Data with client Timestamps is processed in admin code
|
|
19
|
-
- Data with admin Timestamps is sent to client code
|
|
20
|
-
- Shared type definitions across client and admin code
|
|
21
|
-
|
|
22
|
-
## Solution: TimestampUtils
|
|
23
|
-
|
|
24
|
-
We've created a central `TimestampUtils` class providing:
|
|
25
|
-
|
|
26
|
-
1. Conversion utilities between admin and client Timestamps
|
|
27
|
-
2. Best practices for timestamp handling
|
|
28
|
-
3. Consistent patterns for timestamp operations
|
|
29
|
-
|
|
30
|
-
## Usage Guidelines
|
|
31
|
-
|
|
32
|
-
### 1. Type Definitions
|
|
33
|
-
|
|
34
|
-
All shared type definitions (in `src/types/*`) should:
|
|
35
|
-
|
|
36
|
-
- Import Timestamp from client SDK: `import { Timestamp } from 'firebase/firestore'`
|
|
37
|
-
- Define fields using this client Timestamp: `timestamp: Timestamp`
|
|
38
|
-
|
|
39
|
-
This ensures types are consumable by both client and admin code.
|
|
40
|
-
|
|
41
|
-
### 2. Admin Code (Cloud Functions)
|
|
42
|
-
|
|
43
|
-
When writing admin code that:
|
|
44
|
-
|
|
45
|
-
- **Reads data from Firestore**: No conversion needed, as Firestore returns admin Timestamps
|
|
46
|
-
- **Processes timestamps**: Use standard admin timestamp methods
|
|
47
|
-
- **Writes data to shared types**: Convert admin → client using `TimestampUtils.adminToClient()`
|
|
48
|
-
- **Creates server timestamps**: For fields created with `serverTimestamp()`, use Firebase Admin's version: `admin.firestore.FieldValue.serverTimestamp()`
|
|
49
|
-
|
|
50
|
-
Example:
|
|
51
|
-
|
|
52
|
-
```typescript
|
|
53
|
-
import * as admin from "firebase-admin";
|
|
54
|
-
import { TimestampUtils } from "../../utils/TimestampUtils";
|
|
55
|
-
import { YourSharedType } from "../../types/shared";
|
|
56
|
-
|
|
57
|
-
// In your admin service
|
|
58
|
-
async function processAndUpdateData() {
|
|
59
|
-
const adminTsNow = admin.firestore.Timestamp.now();
|
|
60
|
-
|
|
61
|
-
// When populating a shared type that clients will use
|
|
62
|
-
const data: YourSharedType = {
|
|
63
|
-
// Convert admin timestamp to client timestamp
|
|
64
|
-
createdAt: TimestampUtils.adminToClient(adminTsNow),
|
|
65
|
-
|
|
66
|
-
// For server timestamps, use admin version
|
|
67
|
-
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
|
68
|
-
|
|
69
|
-
// Other fields...
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
// When you need to process objects with nested timestamps
|
|
73
|
-
const objectWithNestedTimestamps = {
|
|
74
|
-
// Complex data from another source
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
// Convert all timestamps in the object from admin to client
|
|
78
|
-
const clientCompatible = TimestampUtils.convertObjectTimestampsAdminToClient(
|
|
79
|
-
objectWithNestedTimestamps
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### 3. Client Code (Web/Mobile Apps)
|
|
85
|
-
|
|
86
|
-
Client code should:
|
|
87
|
-
|
|
88
|
-
- Use `firebase/firestore` Timestamp when needed
|
|
89
|
-
- No conversion is necessary for data returned by `getDocs()` or similar client SDK methods
|
|
90
|
-
- For new timestamps, use `Timestamp.now()` or `Timestamp.fromDate()`
|
|
91
|
-
|
|
92
|
-
### 4. Utility Functions
|
|
93
|
-
|
|
94
|
-
The `TimestampUtils` class provides these key functions:
|
|
95
|
-
|
|
96
|
-
- `adminToClient(adminTimestamp)`: Converts admin → client Timestamp
|
|
97
|
-
- `clientToAdmin(clientTimestamp)`: Converts client → admin Timestamp
|
|
98
|
-
- `nowAsClient()`: Creates current timestamp as client Timestamp
|
|
99
|
-
- `dateToClientTimestamp(date)`: Converts Date → client Timestamp
|
|
100
|
-
- `dateToAdminTimestamp(date)`: Converts Date → admin Timestamp
|
|
101
|
-
- `convertObjectTimestampsAdminToClient(obj)`: Deep conversion of all timestamps in an object from admin → client
|
|
102
|
-
- `convertObjectTimestampsClientToAdmin(obj)`: Deep conversion of all timestamps in an object from client → admin
|
|
103
|
-
|
|
104
|
-
## Common Patterns
|
|
105
|
-
|
|
106
|
-
### 1. Creating New Documents
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
// In admin code
|
|
110
|
-
const adminTimestamp = admin.firestore.Timestamp.now();
|
|
111
|
-
const clientCompatibleTimestamp = TimestampUtils.adminToClient(adminTimestamp);
|
|
112
|
-
|
|
113
|
-
const newDocument = {
|
|
114
|
-
id: "doc123",
|
|
115
|
-
createdAt: clientCompatibleTimestamp,
|
|
116
|
-
// For server-managed timestamps, use serverTimestamp()
|
|
117
|
-
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
await docRef.set(newDocument);
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### 2. Updating Fields in a Document
|
|
124
|
-
|
|
125
|
-
```typescript
|
|
126
|
-
// In admin code
|
|
127
|
-
await docRef.update({
|
|
128
|
-
someField: "new value",
|
|
129
|
-
// For immediate timestamp, convert admin to client
|
|
130
|
-
processedAt: TimestampUtils.adminToClient(admin.firestore.Timestamp.now()),
|
|
131
|
-
// For server-managed timestamps, use serverTimestamp()
|
|
132
|
-
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
|
133
|
-
});
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### 3. Processing Calendar Events
|
|
137
|
-
|
|
138
|
-
Calendar events and date ranges should be consistently handled:
|
|
139
|
-
|
|
140
|
-
```typescript
|
|
141
|
-
// Calendar event time conversion
|
|
142
|
-
const firestoreCompatibleEventTime = {
|
|
143
|
-
start: {
|
|
144
|
-
seconds: newEventTime.start.seconds,
|
|
145
|
-
nanoseconds: newEventTime.start.nanoseconds,
|
|
146
|
-
},
|
|
147
|
-
end: {
|
|
148
|
-
seconds: newEventTime.end.seconds,
|
|
149
|
-
nanoseconds: newEventTime.end.nanoseconds,
|
|
150
|
-
},
|
|
151
|
-
};
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
## Edge Cases and Limitations
|
|
155
|
-
|
|
156
|
-
1. **null/undefined Handling**: All utility methods handle null safely
|
|
157
|
-
2. **Serialization**: If serializing for JSON, convert to ISO strings first
|
|
158
|
-
3. **Performance**: The conversion is lightweight, but for large batches, process efficiently
|
|
159
|
-
|
|
160
|
-
## Migration Strategy
|
|
161
|
-
|
|
162
|
-
1. Identify timestamp usage in your code using static analysis or grep
|
|
163
|
-
2. Replace direct timestamp conversions with TimestampUtils methods
|
|
164
|
-
3. Update methods like:
|
|
165
|
-
- `adminTimestampToClientTimestamp` → `TimestampUtils.adminToClient`
|
|
166
|
-
- Direct creation of client timestamps → `TimestampUtils.nowAsClient`
|
|
167
|
-
4. Test thoroughly after each change
|
|
168
|
-
|
|
169
|
-
## Conclusion
|
|
170
|
-
|
|
171
|
-
Following this strategy will:
|
|
172
|
-
|
|
173
|
-
- Eliminate type errors between admin and client code
|
|
174
|
-
- Provide consistent timestamp handling throughout the codebase
|
|
175
|
-
- Minimize conversion bugs by centralizing conversion logic
|
|
176
|
-
- Make it easier to onboard new developers to the codebase
|
|
1
|
+
# Timestamp Management Strategy
|
|
2
|
+
|
|
3
|
+
## Problem Statement
|
|
4
|
+
|
|
5
|
+
Firebase provides two different Timestamp implementations across its SDKs:
|
|
6
|
+
|
|
7
|
+
1. **Client-side Timestamp**: `import { Timestamp } from 'firebase/firestore'`
|
|
8
|
+
|
|
9
|
+
- Used in client applications (web, mobile)
|
|
10
|
+
- Lives in the `firebase/firestore` package
|
|
11
|
+
|
|
12
|
+
2. **Admin-side Timestamp**: `import * as admin from 'firebase-admin'; admin.firestore.Timestamp`
|
|
13
|
+
- Used in server-side code (Cloud Functions)
|
|
14
|
+
- Lives in the `firebase-admin` package
|
|
15
|
+
|
|
16
|
+
These types are structurally similar but are different JavaScript classes, causing type conflicts when:
|
|
17
|
+
|
|
18
|
+
- Data with client Timestamps is processed in admin code
|
|
19
|
+
- Data with admin Timestamps is sent to client code
|
|
20
|
+
- Shared type definitions across client and admin code
|
|
21
|
+
|
|
22
|
+
## Solution: TimestampUtils
|
|
23
|
+
|
|
24
|
+
We've created a central `TimestampUtils` class providing:
|
|
25
|
+
|
|
26
|
+
1. Conversion utilities between admin and client Timestamps
|
|
27
|
+
2. Best practices for timestamp handling
|
|
28
|
+
3. Consistent patterns for timestamp operations
|
|
29
|
+
|
|
30
|
+
## Usage Guidelines
|
|
31
|
+
|
|
32
|
+
### 1. Type Definitions
|
|
33
|
+
|
|
34
|
+
All shared type definitions (in `src/types/*`) should:
|
|
35
|
+
|
|
36
|
+
- Import Timestamp from client SDK: `import { Timestamp } from 'firebase/firestore'`
|
|
37
|
+
- Define fields using this client Timestamp: `timestamp: Timestamp`
|
|
38
|
+
|
|
39
|
+
This ensures types are consumable by both client and admin code.
|
|
40
|
+
|
|
41
|
+
### 2. Admin Code (Cloud Functions)
|
|
42
|
+
|
|
43
|
+
When writing admin code that:
|
|
44
|
+
|
|
45
|
+
- **Reads data from Firestore**: No conversion needed, as Firestore returns admin Timestamps
|
|
46
|
+
- **Processes timestamps**: Use standard admin timestamp methods
|
|
47
|
+
- **Writes data to shared types**: Convert admin → client using `TimestampUtils.adminToClient()`
|
|
48
|
+
- **Creates server timestamps**: For fields created with `serverTimestamp()`, use Firebase Admin's version: `admin.firestore.FieldValue.serverTimestamp()`
|
|
49
|
+
|
|
50
|
+
Example:
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import * as admin from "firebase-admin";
|
|
54
|
+
import { TimestampUtils } from "../../utils/TimestampUtils";
|
|
55
|
+
import { YourSharedType } from "../../types/shared";
|
|
56
|
+
|
|
57
|
+
// In your admin service
|
|
58
|
+
async function processAndUpdateData() {
|
|
59
|
+
const adminTsNow = admin.firestore.Timestamp.now();
|
|
60
|
+
|
|
61
|
+
// When populating a shared type that clients will use
|
|
62
|
+
const data: YourSharedType = {
|
|
63
|
+
// Convert admin timestamp to client timestamp
|
|
64
|
+
createdAt: TimestampUtils.adminToClient(adminTsNow),
|
|
65
|
+
|
|
66
|
+
// For server timestamps, use admin version
|
|
67
|
+
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
|
68
|
+
|
|
69
|
+
// Other fields...
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// When you need to process objects with nested timestamps
|
|
73
|
+
const objectWithNestedTimestamps = {
|
|
74
|
+
// Complex data from another source
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// Convert all timestamps in the object from admin to client
|
|
78
|
+
const clientCompatible = TimestampUtils.convertObjectTimestampsAdminToClient(
|
|
79
|
+
objectWithNestedTimestamps
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 3. Client Code (Web/Mobile Apps)
|
|
85
|
+
|
|
86
|
+
Client code should:
|
|
87
|
+
|
|
88
|
+
- Use `firebase/firestore` Timestamp when needed
|
|
89
|
+
- No conversion is necessary for data returned by `getDocs()` or similar client SDK methods
|
|
90
|
+
- For new timestamps, use `Timestamp.now()` or `Timestamp.fromDate()`
|
|
91
|
+
|
|
92
|
+
### 4. Utility Functions
|
|
93
|
+
|
|
94
|
+
The `TimestampUtils` class provides these key functions:
|
|
95
|
+
|
|
96
|
+
- `adminToClient(adminTimestamp)`: Converts admin → client Timestamp
|
|
97
|
+
- `clientToAdmin(clientTimestamp)`: Converts client → admin Timestamp
|
|
98
|
+
- `nowAsClient()`: Creates current timestamp as client Timestamp
|
|
99
|
+
- `dateToClientTimestamp(date)`: Converts Date → client Timestamp
|
|
100
|
+
- `dateToAdminTimestamp(date)`: Converts Date → admin Timestamp
|
|
101
|
+
- `convertObjectTimestampsAdminToClient(obj)`: Deep conversion of all timestamps in an object from admin → client
|
|
102
|
+
- `convertObjectTimestampsClientToAdmin(obj)`: Deep conversion of all timestamps in an object from client → admin
|
|
103
|
+
|
|
104
|
+
## Common Patterns
|
|
105
|
+
|
|
106
|
+
### 1. Creating New Documents
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
// In admin code
|
|
110
|
+
const adminTimestamp = admin.firestore.Timestamp.now();
|
|
111
|
+
const clientCompatibleTimestamp = TimestampUtils.adminToClient(adminTimestamp);
|
|
112
|
+
|
|
113
|
+
const newDocument = {
|
|
114
|
+
id: "doc123",
|
|
115
|
+
createdAt: clientCompatibleTimestamp,
|
|
116
|
+
// For server-managed timestamps, use serverTimestamp()
|
|
117
|
+
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
await docRef.set(newDocument);
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### 2. Updating Fields in a Document
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
// In admin code
|
|
127
|
+
await docRef.update({
|
|
128
|
+
someField: "new value",
|
|
129
|
+
// For immediate timestamp, convert admin to client
|
|
130
|
+
processedAt: TimestampUtils.adminToClient(admin.firestore.Timestamp.now()),
|
|
131
|
+
// For server-managed timestamps, use serverTimestamp()
|
|
132
|
+
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 3. Processing Calendar Events
|
|
137
|
+
|
|
138
|
+
Calendar events and date ranges should be consistently handled:
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
// Calendar event time conversion
|
|
142
|
+
const firestoreCompatibleEventTime = {
|
|
143
|
+
start: {
|
|
144
|
+
seconds: newEventTime.start.seconds,
|
|
145
|
+
nanoseconds: newEventTime.start.nanoseconds,
|
|
146
|
+
},
|
|
147
|
+
end: {
|
|
148
|
+
seconds: newEventTime.end.seconds,
|
|
149
|
+
nanoseconds: newEventTime.end.nanoseconds,
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Edge Cases and Limitations
|
|
155
|
+
|
|
156
|
+
1. **null/undefined Handling**: All utility methods handle null safely
|
|
157
|
+
2. **Serialization**: If serializing for JSON, convert to ISO strings first
|
|
158
|
+
3. **Performance**: The conversion is lightweight, but for large batches, process efficiently
|
|
159
|
+
|
|
160
|
+
## Migration Strategy
|
|
161
|
+
|
|
162
|
+
1. Identify timestamp usage in your code using static analysis or grep
|
|
163
|
+
2. Replace direct timestamp conversions with TimestampUtils methods
|
|
164
|
+
3. Update methods like:
|
|
165
|
+
- `adminTimestampToClientTimestamp` → `TimestampUtils.adminToClient`
|
|
166
|
+
- Direct creation of client timestamps → `TimestampUtils.nowAsClient`
|
|
167
|
+
4. Test thoroughly after each change
|
|
168
|
+
|
|
169
|
+
## Conclusion
|
|
170
|
+
|
|
171
|
+
Following this strategy will:
|
|
172
|
+
|
|
173
|
+
- Eliminate type errors between admin and client code
|
|
174
|
+
- Provide consistent timestamp handling throughout the codebase
|
|
175
|
+
- Minimize conversion bugs by centralizing conversion logic
|
|
176
|
+
- Make it easier to onboard new developers to the codebase
|