@blackcode_sa/metaestetics-api 1.7.22 → 1.7.23

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/index.d.mts CHANGED
@@ -7606,7 +7606,17 @@ declare class AppointmentService extends BaseService {
7606
7606
  * Admin proposes to reschedule an appointment.
7607
7607
  * Sets status to RESCHEDULED_BY_CLINIC and updates times.
7608
7608
  */
7609
- rescheduleAppointmentAdmin(appointmentId: string, newStartTime: Timestamp, newEndTime: Timestamp): Promise<Appointment>;
7609
+ rescheduleAppointmentAdmin(params: {
7610
+ appointmentId: string;
7611
+ newStartTime: any;
7612
+ newEndTime: any;
7613
+ }): Promise<Appointment>;
7614
+ /**
7615
+ * Helper method to convert various timestamp formats to Firestore Timestamp
7616
+ * @param value - Any timestamp format (Timestamp, number, string, Date, serialized Timestamp)
7617
+ * @returns Firestore Timestamp object
7618
+ */
7619
+ private convertToTimestamp;
7610
7620
  /**
7611
7621
  * User confirms a reschedule proposed by the clinic.
7612
7622
  * Status changes from RESCHEDULED_BY_CLINIC to CONFIRMED.
package/dist/index.d.ts CHANGED
@@ -7606,7 +7606,17 @@ declare class AppointmentService extends BaseService {
7606
7606
  * Admin proposes to reschedule an appointment.
7607
7607
  * Sets status to RESCHEDULED_BY_CLINIC and updates times.
7608
7608
  */
7609
- rescheduleAppointmentAdmin(appointmentId: string, newStartTime: Timestamp, newEndTime: Timestamp): Promise<Appointment>;
7609
+ rescheduleAppointmentAdmin(params: {
7610
+ appointmentId: string;
7611
+ newStartTime: any;
7612
+ newEndTime: any;
7613
+ }): Promise<Appointment>;
7614
+ /**
7615
+ * Helper method to convert various timestamp formats to Firestore Timestamp
7616
+ * @param value - Any timestamp format (Timestamp, number, string, Date, serialized Timestamp)
7617
+ * @returns Firestore Timestamp object
7618
+ */
7619
+ private convertToTimestamp;
7610
7620
  /**
7611
7621
  * User confirms a reschedule proposed by the clinic.
7612
7622
  * Status changes from RESCHEDULED_BY_CLINIC to CONFIRMED.
package/dist/index.js CHANGED
@@ -703,6 +703,17 @@ var searchAppointmentsSchema = import_zod2.z.object({
703
703
  path: ["endDate"]
704
704
  }
705
705
  );
706
+ var rescheduleAppointmentSchema = import_zod2.z.object({
707
+ appointmentId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Appointment ID is required"),
708
+ newStartTime: import_zod2.z.any().refine(
709
+ (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
710
+ "New start time must be a valid timestamp, Date object, number, or string"
711
+ ),
712
+ newEndTime: import_zod2.z.any().refine(
713
+ (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
714
+ "New end time must be a valid timestamp, Date object, number, or string"
715
+ )
716
+ });
706
717
 
707
718
  // src/config/firebase.ts
708
719
  var import_app = require("firebase/app");
@@ -13492,22 +13503,63 @@ var AppointmentService = class extends BaseService {
13492
13503
  * Admin proposes to reschedule an appointment.
13493
13504
  * Sets status to RESCHEDULED_BY_CLINIC and updates times.
13494
13505
  */
13495
- async rescheduleAppointmentAdmin(appointmentId, newStartTime, newEndTime) {
13506
+ async rescheduleAppointmentAdmin(params) {
13496
13507
  console.log(
13497
- `[APPOINTMENT_SERVICE] Admin rescheduling appointment: ${appointmentId}`
13508
+ `[APPOINTMENT_SERVICE] Admin rescheduling appointment: ${params.appointmentId}`
13509
+ );
13510
+ const validatedParams = await rescheduleAppointmentSchema.parseAsync(
13511
+ params
13512
+ );
13513
+ const startTimestamp = this.convertToTimestamp(
13514
+ validatedParams.newStartTime
13498
13515
  );
13499
- if (newEndTime.toMillis() <= newStartTime.toMillis()) {
13516
+ const endTimestamp = this.convertToTimestamp(validatedParams.newEndTime);
13517
+ if (endTimestamp.toMillis() <= startTimestamp.toMillis()) {
13500
13518
  throw new Error("New end time must be after new start time.");
13501
13519
  }
13502
13520
  const updateData = {
13503
13521
  status: "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */,
13504
- appointmentStartTime: newStartTime,
13505
- appointmentEndTime: newEndTime,
13522
+ appointmentStartTime: startTimestamp,
13523
+ appointmentEndTime: endTimestamp,
13506
13524
  rescheduleTime: import_firestore43.Timestamp.now(),
13507
13525
  confirmationTime: null,
13508
13526
  updatedAt: (0, import_firestore43.serverTimestamp)()
13509
13527
  };
13510
- return this.updateAppointment(appointmentId, updateData);
13528
+ return this.updateAppointment(validatedParams.appointmentId, updateData);
13529
+ }
13530
+ /**
13531
+ * Helper method to convert various timestamp formats to Firestore Timestamp
13532
+ * @param value - Any timestamp format (Timestamp, number, string, Date, serialized Timestamp)
13533
+ * @returns Firestore Timestamp object
13534
+ */
13535
+ convertToTimestamp(value) {
13536
+ console.log(`[APPOINTMENT_SERVICE] Converting timestamp:`, {
13537
+ value,
13538
+ type: typeof value
13539
+ });
13540
+ if (value && typeof value.toMillis === "function") {
13541
+ return value;
13542
+ }
13543
+ if (typeof value === "number") {
13544
+ return import_firestore43.Timestamp.fromMillis(value);
13545
+ }
13546
+ if (typeof value === "string") {
13547
+ return import_firestore43.Timestamp.fromDate(new Date(value));
13548
+ }
13549
+ if (value instanceof Date) {
13550
+ return import_firestore43.Timestamp.fromDate(value);
13551
+ }
13552
+ if (value && typeof value._seconds === "number") {
13553
+ return new import_firestore43.Timestamp(value._seconds, value._nanoseconds || 0);
13554
+ }
13555
+ if (value && typeof value.seconds === "number") {
13556
+ return new import_firestore43.Timestamp(value.seconds, value.nanoseconds || 0);
13557
+ }
13558
+ throw new Error(
13559
+ `Invalid timestamp format: ${typeof value}, value: ${JSON.stringify(
13560
+ value
13561
+ )}`
13562
+ );
13511
13563
  }
13512
13564
  /**
13513
13565
  * User confirms a reschedule proposed by the clinic.
package/dist/index.mjs CHANGED
@@ -464,6 +464,17 @@ var searchAppointmentsSchema = z2.object({
464
464
  path: ["endDate"]
465
465
  }
466
466
  );
467
+ var rescheduleAppointmentSchema = z2.object({
468
+ appointmentId: z2.string().min(MIN_STRING_LENGTH, "Appointment ID is required"),
469
+ newStartTime: z2.any().refine(
470
+ (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
471
+ "New start time must be a valid timestamp, Date object, number, or string"
472
+ ),
473
+ newEndTime: z2.any().refine(
474
+ (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
475
+ "New end time must be a valid timestamp, Date object, number, or string"
476
+ )
477
+ });
467
478
 
468
479
  // src/config/firebase.ts
469
480
  import { initializeApp } from "firebase/app";
@@ -13613,22 +13624,63 @@ var AppointmentService = class extends BaseService {
13613
13624
  * Admin proposes to reschedule an appointment.
13614
13625
  * Sets status to RESCHEDULED_BY_CLINIC and updates times.
13615
13626
  */
13616
- async rescheduleAppointmentAdmin(appointmentId, newStartTime, newEndTime) {
13627
+ async rescheduleAppointmentAdmin(params) {
13617
13628
  console.log(
13618
- `[APPOINTMENT_SERVICE] Admin rescheduling appointment: ${appointmentId}`
13629
+ `[APPOINTMENT_SERVICE] Admin rescheduling appointment: ${params.appointmentId}`
13630
+ );
13631
+ const validatedParams = await rescheduleAppointmentSchema.parseAsync(
13632
+ params
13633
+ );
13634
+ const startTimestamp = this.convertToTimestamp(
13635
+ validatedParams.newStartTime
13619
13636
  );
13620
- if (newEndTime.toMillis() <= newStartTime.toMillis()) {
13637
+ const endTimestamp = this.convertToTimestamp(validatedParams.newEndTime);
13638
+ if (endTimestamp.toMillis() <= startTimestamp.toMillis()) {
13621
13639
  throw new Error("New end time must be after new start time.");
13622
13640
  }
13623
13641
  const updateData = {
13624
13642
  status: "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */,
13625
- appointmentStartTime: newStartTime,
13626
- appointmentEndTime: newEndTime,
13643
+ appointmentStartTime: startTimestamp,
13644
+ appointmentEndTime: endTimestamp,
13627
13645
  rescheduleTime: Timestamp29.now(),
13628
13646
  confirmationTime: null,
13629
13647
  updatedAt: serverTimestamp24()
13630
13648
  };
13631
- return this.updateAppointment(appointmentId, updateData);
13649
+ return this.updateAppointment(validatedParams.appointmentId, updateData);
13650
+ }
13651
+ /**
13652
+ * Helper method to convert various timestamp formats to Firestore Timestamp
13653
+ * @param value - Any timestamp format (Timestamp, number, string, Date, serialized Timestamp)
13654
+ * @returns Firestore Timestamp object
13655
+ */
13656
+ convertToTimestamp(value) {
13657
+ console.log(`[APPOINTMENT_SERVICE] Converting timestamp:`, {
13658
+ value,
13659
+ type: typeof value
13660
+ });
13661
+ if (value && typeof value.toMillis === "function") {
13662
+ return value;
13663
+ }
13664
+ if (typeof value === "number") {
13665
+ return Timestamp29.fromMillis(value);
13666
+ }
13667
+ if (typeof value === "string") {
13668
+ return Timestamp29.fromDate(new Date(value));
13669
+ }
13670
+ if (value instanceof Date) {
13671
+ return Timestamp29.fromDate(value);
13672
+ }
13673
+ if (value && typeof value._seconds === "number") {
13674
+ return new Timestamp29(value._seconds, value._nanoseconds || 0);
13675
+ }
13676
+ if (value && typeof value.seconds === "number") {
13677
+ return new Timestamp29(value.seconds, value.nanoseconds || 0);
13678
+ }
13679
+ throw new Error(
13680
+ `Invalid timestamp format: ${typeof value}, value: ${JSON.stringify(
13681
+ value
13682
+ )}`
13683
+ );
13632
13684
  }
13633
13685
  /**
13634
13686
  * User confirms a reschedule proposed by the clinic.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@blackcode_sa/metaestetics-api",
3
3
  "private": false,
4
- "version": "1.7.22",
4
+ "version": "1.7.23",
5
5
  "description": "Firebase authentication service with anonymous upgrade support",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.mjs",
@@ -35,6 +35,7 @@ import {
35
35
  createAppointmentSchema,
36
36
  updateAppointmentSchema,
37
37
  searchAppointmentsSchema,
38
+ rescheduleAppointmentSchema,
38
39
  } from "../../validations/appointment.schema";
39
40
 
40
41
  // Import other services needed (dependency injection pattern)
@@ -682,26 +683,87 @@ export class AppointmentService extends BaseService {
682
683
  * Admin proposes to reschedule an appointment.
683
684
  * Sets status to RESCHEDULED_BY_CLINIC and updates times.
684
685
  */
685
- async rescheduleAppointmentAdmin(
686
- appointmentId: string,
687
- newStartTime: Timestamp,
688
- newEndTime: Timestamp
689
- ): Promise<Appointment> {
686
+ async rescheduleAppointmentAdmin(params: {
687
+ appointmentId: string;
688
+ newStartTime: any; // Accept any type (number, string, Timestamp, etc.)
689
+ newEndTime: any; // Accept any type (number, string, Timestamp, etc.)
690
+ }): Promise<Appointment> {
690
691
  console.log(
691
- `[APPOINTMENT_SERVICE] Admin rescheduling appointment: ${appointmentId}`
692
+ `[APPOINTMENT_SERVICE] Admin rescheduling appointment: ${params.appointmentId}`
693
+ );
694
+
695
+ // Validate input data
696
+ const validatedParams = await rescheduleAppointmentSchema.parseAsync(
697
+ params
692
698
  );
693
- if (newEndTime.toMillis() <= newStartTime.toMillis()) {
699
+
700
+ // Convert input to Timestamp objects
701
+ const startTimestamp = this.convertToTimestamp(
702
+ validatedParams.newStartTime
703
+ );
704
+ const endTimestamp = this.convertToTimestamp(validatedParams.newEndTime);
705
+
706
+ if (endTimestamp.toMillis() <= startTimestamp.toMillis()) {
694
707
  throw new Error("New end time must be after new start time.");
695
708
  }
709
+
696
710
  const updateData: UpdateAppointmentData = {
697
711
  status: AppointmentStatus.RESCHEDULED_BY_CLINIC,
698
- appointmentStartTime: newStartTime,
699
- appointmentEndTime: newEndTime,
712
+ appointmentStartTime: startTimestamp,
713
+ appointmentEndTime: endTimestamp,
700
714
  rescheduleTime: Timestamp.now(),
701
715
  confirmationTime: null,
702
716
  updatedAt: serverTimestamp(),
703
717
  };
704
- return this.updateAppointment(appointmentId, updateData);
718
+ return this.updateAppointment(validatedParams.appointmentId, updateData);
719
+ }
720
+
721
+ /**
722
+ * Helper method to convert various timestamp formats to Firestore Timestamp
723
+ * @param value - Any timestamp format (Timestamp, number, string, Date, serialized Timestamp)
724
+ * @returns Firestore Timestamp object
725
+ */
726
+ private convertToTimestamp(value: any): Timestamp {
727
+ console.log(`[APPOINTMENT_SERVICE] Converting timestamp:`, {
728
+ value,
729
+ type: typeof value,
730
+ });
731
+
732
+ // If it's already a Timestamp object with methods
733
+ if (value && typeof value.toMillis === "function") {
734
+ return value;
735
+ }
736
+
737
+ // If it's a number (milliseconds since epoch)
738
+ if (typeof value === "number") {
739
+ return Timestamp.fromMillis(value);
740
+ }
741
+
742
+ // If it's a string (ISO date string)
743
+ if (typeof value === "string") {
744
+ return Timestamp.fromDate(new Date(value));
745
+ }
746
+
747
+ // If it's a Date object
748
+ if (value instanceof Date) {
749
+ return Timestamp.fromDate(value);
750
+ }
751
+
752
+ // If it has _seconds property (serialized Timestamp) - THIS IS WHAT FRONTEND SENDS
753
+ if (value && typeof value._seconds === "number") {
754
+ return new Timestamp(value._seconds, value._nanoseconds || 0);
755
+ }
756
+
757
+ // If it has seconds property (serialized Timestamp)
758
+ if (value && typeof value.seconds === "number") {
759
+ return new Timestamp(value.seconds, value.nanoseconds || 0);
760
+ }
761
+
762
+ throw new Error(
763
+ `Invalid timestamp format: ${typeof value}, value: ${JSON.stringify(
764
+ value
765
+ )}`
766
+ );
705
767
  }
706
768
 
707
769
  /**
@@ -360,3 +360,36 @@ export const searchAppointmentsSchema = z
360
360
  path: ["endDate"],
361
361
  }
362
362
  );
363
+
364
+ /**
365
+ * Schema for validating appointment reschedule data
366
+ */
367
+ export const rescheduleAppointmentSchema = z.object({
368
+ appointmentId: z
369
+ .string()
370
+ .min(MIN_STRING_LENGTH, "Appointment ID is required"),
371
+ newStartTime: z
372
+ .any()
373
+ .refine(
374
+ (val) =>
375
+ val instanceof Date ||
376
+ val?._seconds !== undefined ||
377
+ val?.seconds !== undefined ||
378
+ typeof val === "number" ||
379
+ typeof val === "string" ||
380
+ (val && typeof val.toMillis === "function"),
381
+ "New start time must be a valid timestamp, Date object, number, or string"
382
+ ),
383
+ newEndTime: z
384
+ .any()
385
+ .refine(
386
+ (val) =>
387
+ val instanceof Date ||
388
+ val?._seconds !== undefined ||
389
+ val?.seconds !== undefined ||
390
+ typeof val === "number" ||
391
+ typeof val === "string" ||
392
+ (val && typeof val.toMillis === "function"),
393
+ "New end time must be a valid timestamp, Date object, number, or string"
394
+ ),
395
+ });