@blackcode_sa/metaestetics-api 1.7.41 → 1.7.43

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.js CHANGED
@@ -825,7 +825,7 @@ var getFirebaseApp = async () => {
825
825
  };
826
826
 
827
827
  // src/services/auth.service.ts
828
- var import_auth5 = require("firebase/auth");
828
+ var import_auth7 = require("firebase/auth");
829
829
  var import_firestore25 = require("firebase/firestore");
830
830
 
831
831
  // src/types/calendar/index.ts
@@ -871,7 +871,7 @@ var UserRole = /* @__PURE__ */ ((UserRole2) => {
871
871
  var USERS_COLLECTION = "users";
872
872
 
873
873
  // src/services/auth.service.ts
874
- var import_zod20 = require("zod");
874
+ var import_zod22 = require("zod");
875
875
 
876
876
  // src/validations/schemas.ts
877
877
  var import_zod4 = require("zod");
@@ -882,12 +882,21 @@ var passwordSchema = import_zod4.z.string().min(8, "Password must be at least 8
882
882
  );
883
883
  var userRoleSchema = import_zod4.z.nativeEnum(UserRole);
884
884
  var userRolesSchema = import_zod4.z.array(userRoleSchema).min(1, "User must have at least one role").max(3, "User cannot have more than 3 roles");
885
- var timestampSchema = import_zod4.z.custom((data) => {
886
- if (data && typeof data === "object" && "isEqual" in data) {
887
- return true;
888
- }
889
- return data && typeof data === "object" && "toDate" in data && "seconds" in data && "nanoseconds" in data;
890
- }, "Must be a Timestamp object or serverTimestamp");
885
+ var timestampSchema = import_zod4.z.custom(
886
+ (data) => {
887
+ if (data && typeof data === "object" && "isEqual" in data) {
888
+ return true;
889
+ }
890
+ if (data && typeof data === "object" && "toDate" in data && "seconds" in data && "nanoseconds" in data) {
891
+ return true;
892
+ }
893
+ if (data instanceof Date) {
894
+ return true;
895
+ }
896
+ return false;
897
+ },
898
+ "Must be a Timestamp object, Date object, or serverTimestamp"
899
+ );
891
900
  var clinicAdminOptionsSchema = import_zod4.z.object({
892
901
  isGroupOwner: import_zod4.z.boolean(),
893
902
  groupToken: import_zod4.z.string().optional(),
@@ -1700,11 +1709,16 @@ var timestampSchema2 = import_zod5.z.union([
1700
1709
  seconds: import_zod5.z.number(),
1701
1710
  nanoseconds: import_zod5.z.number()
1702
1711
  }),
1703
- import_zod5.z.instanceof(import_firestore4.Timestamp)
1712
+ import_zod5.z.instanceof(import_firestore4.Timestamp),
1713
+ import_zod5.z.instanceof(Date)
1714
+ // Add support for Date objects that Firestore returns on client
1704
1715
  ]).transform((data) => {
1705
1716
  if (data instanceof import_firestore4.Timestamp) {
1706
1717
  return data;
1707
1718
  }
1719
+ if (data instanceof Date) {
1720
+ return import_firestore4.Timestamp.fromDate(data);
1721
+ }
1708
1722
  return new import_firestore4.Timestamp(data.seconds, data.nanoseconds);
1709
1723
  });
1710
1724
 
@@ -4618,10 +4632,10 @@ var practitionerBasicInfoSchema = import_zod14.z.object({
4618
4632
  lastName: import_zod14.z.string().min(2).max(50),
4619
4633
  title: import_zod14.z.string().min(2).max(100),
4620
4634
  email: import_zod14.z.string().email(),
4621
- phoneNumber: import_zod14.z.string().regex(/^\+?[1-9]\d{1,14}$/, "Invalid phone number"),
4622
- dateOfBirth: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date()),
4635
+ phoneNumber: import_zod14.z.string().regex(/^\+?[1-9]\d{1,14}$/, "Invalid phone number").nullable(),
4636
+ dateOfBirth: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date()).nullable(),
4623
4637
  gender: import_zod14.z.enum(["male", "female", "other"]),
4624
- profileImageUrl: mediaResourceSchema.optional(),
4638
+ profileImageUrl: mediaResourceSchema.optional().nullable(),
4625
4639
  bio: import_zod14.z.string().max(1e3).optional(),
4626
4640
  languages: import_zod14.z.array(import_zod14.z.string()).min(1)
4627
4641
  });
@@ -4631,7 +4645,7 @@ var practitionerCertificationSchema = import_zod14.z.object({
4631
4645
  licenseNumber: import_zod14.z.string().min(3).max(50),
4632
4646
  issuingAuthority: import_zod14.z.string().min(2).max(100),
4633
4647
  issueDate: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date()),
4634
- expiryDate: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date()).optional(),
4648
+ expiryDate: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date()).optional().nullable(),
4635
4649
  verificationStatus: import_zod14.z.enum(["pending", "verified", "rejected"])
4636
4650
  });
4637
4651
  var timeSlotSchema = import_zod14.z.object({
@@ -7735,23 +7749,139 @@ var ClinicService = class extends BaseService {
7735
7749
  }
7736
7750
  };
7737
7751
 
7752
+ // src/services/auth/utils/firebase.utils.ts
7753
+ var import_auth5 = require("firebase/auth");
7754
+ var checkEmailExists = async (auth, email) => {
7755
+ try {
7756
+ const methods = await (0, import_auth5.fetchSignInMethodsForEmail)(auth, email);
7757
+ return methods.length > 0;
7758
+ } catch (error) {
7759
+ console.warn(
7760
+ "[FIREBASE] Could not check email existence, allowing signup to proceed:",
7761
+ error
7762
+ );
7763
+ return false;
7764
+ }
7765
+ };
7766
+ var cleanupFirebaseUser = async (firebaseUser) => {
7767
+ try {
7768
+ console.log("[FIREBASE] Cleaning up Firebase user", {
7769
+ uid: firebaseUser.uid
7770
+ });
7771
+ await firebaseUser.delete();
7772
+ console.log("[FIREBASE] Firebase user cleanup successful");
7773
+ } catch (cleanupError) {
7774
+ console.error("[FIREBASE] Failed to cleanup Firebase user:", cleanupError);
7775
+ }
7776
+ };
7777
+
7778
+ // src/services/auth/utils/error.utils.ts
7779
+ var import_zod20 = require("zod");
7780
+ var handleFirebaseError = (error) => {
7781
+ const firebaseError = error;
7782
+ switch (firebaseError.code) {
7783
+ case "auth/email-already-in-use" /* EMAIL_ALREADY_IN_USE */:
7784
+ return AUTH_ERRORS.EMAIL_ALREADY_EXISTS;
7785
+ case "auth/weak-password":
7786
+ return new Error(
7787
+ "Password is too weak. Please choose a stronger password."
7788
+ );
7789
+ case "auth/invalid-email":
7790
+ return new Error("Please enter a valid email address.");
7791
+ case "auth/network-request-failed":
7792
+ return new Error(
7793
+ "Network error. Please check your internet connection and try again."
7794
+ );
7795
+ default:
7796
+ return new Error(
7797
+ `Account creation failed: ${firebaseError.message || "Unknown error"}`
7798
+ );
7799
+ }
7800
+ };
7801
+ var handleSignupError = (error) => {
7802
+ if (error instanceof import_zod20.z.ZodError) {
7803
+ const errorMessages = error.errors.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
7804
+ return new Error(`Validation failed: ${errorMessages}`);
7805
+ }
7806
+ if (error.code && error.code.startsWith("auth/")) {
7807
+ return handleFirebaseError(error);
7808
+ }
7809
+ if (error.message && error.message.includes("token")) {
7810
+ return new Error("Invalid or expired invitation token");
7811
+ }
7812
+ if (error.message && error.message.includes("validation")) {
7813
+ return new Error(`Invalid practitioner data: ${error.message}`);
7814
+ }
7815
+ return new Error(
7816
+ `Registration failed: ${error.message || "Unknown error occurred"}`
7817
+ );
7818
+ };
7819
+
7820
+ // src/services/auth/utils/practitioner.utils.ts
7821
+ var import_zod21 = require("zod");
7822
+ var profileDataSchema = import_zod21.z.object({
7823
+ basicInfo: practitionerBasicInfoSchema.partial().optional(),
7824
+ certification: practitionerCertificationSchema.partial().optional()
7825
+ }).partial();
7826
+ var buildPractitionerData = (data, userRef) => {
7827
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
7828
+ const basicInfo = {
7829
+ firstName: data.firstName || "Name",
7830
+ lastName: data.lastName || "Surname",
7831
+ email: data.email,
7832
+ phoneNumber: ((_b = (_a = data.profileData) == null ? void 0 : _a.basicInfo) == null ? void 0 : _b.phoneNumber) || null,
7833
+ profileImageUrl: ((_d = (_c = data.profileData) == null ? void 0 : _c.basicInfo) == null ? void 0 : _d.profileImageUrl) || "",
7834
+ gender: ((_f = (_e = data.profileData) == null ? void 0 : _e.basicInfo) == null ? void 0 : _f.gender) || "other",
7835
+ bio: ((_h = (_g = data.profileData) == null ? void 0 : _g.basicInfo) == null ? void 0 : _h.bio) || "",
7836
+ title: "Practitioner",
7837
+ dateOfBirth: ((_j = (_i = data.profileData) == null ? void 0 : _i.basicInfo) == null ? void 0 : _j.dateOfBirth) || /* @__PURE__ */ new Date(),
7838
+ languages: ((_l = (_k = data.profileData) == null ? void 0 : _k.basicInfo) == null ? void 0 : _l.languages) || ["English"]
7839
+ };
7840
+ const certification = ((_m = data.profileData) == null ? void 0 : _m.certification) || {
7841
+ level: "aesthetician" /* AESTHETICIAN */,
7842
+ specialties: [],
7843
+ licenseNumber: "Pending",
7844
+ issuingAuthority: "Pending",
7845
+ issueDate: /* @__PURE__ */ new Date(),
7846
+ verificationStatus: "pending"
7847
+ };
7848
+ return {
7849
+ userRef,
7850
+ basicInfo,
7851
+ certification,
7852
+ status: "active" /* ACTIVE */,
7853
+ isActive: true,
7854
+ isVerified: false
7855
+ };
7856
+ };
7857
+ var validatePractitionerProfileData = async (profileData) => {
7858
+ try {
7859
+ await profileDataSchema.parseAsync(profileData);
7860
+ } catch (error) {
7861
+ if (error instanceof import_zod21.z.ZodError) {
7862
+ const errorMessages = error.errors.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
7863
+ throw new Error(
7864
+ `Practitioner profile validation failed: ${errorMessages}`
7865
+ );
7866
+ }
7867
+ throw error;
7868
+ }
7869
+ };
7870
+
7738
7871
  // src/services/auth.service.ts
7739
7872
  var AuthService = class extends BaseService {
7740
7873
  constructor(db, auth, app, userService) {
7741
7874
  super(db, auth, app);
7742
- this.googleProvider = new import_auth5.GoogleAuthProvider();
7743
- this.facebookProvider = new import_auth5.FacebookAuthProvider();
7744
- this.appleProvider = new import_auth5.OAuthProvider("apple.com");
7745
- if (!userService) {
7746
- userService = new UserService(db, auth, app);
7747
- }
7748
- this.userService = userService;
7875
+ this.googleProvider = new import_auth7.GoogleAuthProvider();
7876
+ this.facebookProvider = new import_auth7.FacebookAuthProvider();
7877
+ this.appleProvider = new import_auth7.OAuthProvider("apple.com");
7878
+ this.userService = userService || new UserService(db, auth, app);
7749
7879
  }
7750
7880
  /**
7751
7881
  * Registruje novog korisnika sa email-om i lozinkom
7752
7882
  */
7753
7883
  async signUp(email, password, initialRole = "patient" /* PATIENT */) {
7754
- const { user: firebaseUser } = await (0, import_auth5.createUserWithEmailAndPassword)(
7884
+ const { user: firebaseUser } = await (0, import_auth7.createUserWithEmailAndPassword)(
7755
7885
  this.auth,
7756
7886
  email,
7757
7887
  password
@@ -7783,7 +7913,7 @@ var AuthService = class extends BaseService {
7783
7913
  console.log("[AUTH] Creating Firebase user");
7784
7914
  let firebaseUser;
7785
7915
  try {
7786
- const result = await (0, import_auth5.createUserWithEmailAndPassword)(
7916
+ const result = await (0, import_auth7.createUserWithEmailAndPassword)(
7787
7917
  this.auth,
7788
7918
  data.email,
7789
7919
  data.password
@@ -7794,7 +7924,7 @@ var AuthService = class extends BaseService {
7794
7924
  });
7795
7925
  } catch (firebaseError) {
7796
7926
  console.error("[AUTH] Firebase user creation failed:", firebaseError);
7797
- throw firebaseError;
7927
+ throw handleFirebaseError(firebaseError);
7798
7928
  }
7799
7929
  console.log("[AUTH] Creating user with CLINIC_ADMIN role");
7800
7930
  let user;
@@ -8048,7 +8178,7 @@ var AuthService = class extends BaseService {
8048
8178
  clinicAdmin: adminProfile
8049
8179
  };
8050
8180
  } catch (error) {
8051
- if (error instanceof import_zod20.z.ZodError) {
8181
+ if (error instanceof import_zod22.z.ZodError) {
8052
8182
  console.error(
8053
8183
  "[AUTH] Zod validation error in signUpClinicAdmin:",
8054
8184
  JSON.stringify(error.errors, null, 2)
@@ -8068,7 +8198,7 @@ var AuthService = class extends BaseService {
8068
8198
  * Prijavljuje korisnika sa email-om i lozinkom
8069
8199
  */
8070
8200
  async signIn(email, password) {
8071
- const { user: firebaseUser } = await (0, import_auth5.signInWithEmailAndPassword)(
8201
+ const { user: firebaseUser } = await (0, import_auth7.signInWithEmailAndPassword)(
8072
8202
  this.auth,
8073
8203
  email,
8074
8204
  password
@@ -8107,7 +8237,7 @@ var AuthService = class extends BaseService {
8107
8237
  mediaService
8108
8238
  );
8109
8239
  clinicAdminService.setServices(clinicGroupService, clinicService);
8110
- const { user: firebaseUser } = await (0, import_auth5.signInWithEmailAndPassword)(
8240
+ const { user: firebaseUser } = await (0, import_auth7.signInWithEmailAndPassword)(
8111
8241
  this.auth,
8112
8242
  email,
8113
8243
  password
@@ -8152,15 +8282,15 @@ var AuthService = class extends BaseService {
8152
8282
  * Prijavljuje korisnika sa Facebook-om
8153
8283
  */
8154
8284
  async signInWithFacebook() {
8155
- const provider = new import_auth5.FacebookAuthProvider();
8156
- const { user: firebaseUser } = await (0, import_auth5.signInWithPopup)(this.auth, provider);
8285
+ const provider = new import_auth7.FacebookAuthProvider();
8286
+ const { user: firebaseUser } = await (0, import_auth7.signInWithPopup)(this.auth, provider);
8157
8287
  return this.userService.getOrCreateUser(firebaseUser);
8158
8288
  }
8159
8289
  /**
8160
8290
  * Prijavljuje korisnika sa Google nalogom
8161
8291
  */
8162
8292
  async signInWithGoogle(initialRole = "patient" /* PATIENT */) {
8163
- const { user: firebaseUser } = await (0, import_auth5.signInWithPopup)(
8293
+ const { user: firebaseUser } = await (0, import_auth7.signInWithPopup)(
8164
8294
  this.auth,
8165
8295
  this.googleProvider
8166
8296
  );
@@ -8170,22 +8300,22 @@ var AuthService = class extends BaseService {
8170
8300
  * Prijavljuje korisnika sa Apple-om
8171
8301
  */
8172
8302
  async signInWithApple() {
8173
- const provider = new import_auth5.OAuthProvider("apple.com");
8174
- const { user: firebaseUser } = await (0, import_auth5.signInWithPopup)(this.auth, provider);
8303
+ const provider = new import_auth7.OAuthProvider("apple.com");
8304
+ const { user: firebaseUser } = await (0, import_auth7.signInWithPopup)(this.auth, provider);
8175
8305
  return this.userService.getOrCreateUser(firebaseUser);
8176
8306
  }
8177
8307
  /**
8178
8308
  * Prijavljuje korisnika anonimno
8179
8309
  */
8180
8310
  async signInAnonymously() {
8181
- const { user: firebaseUser } = await (0, import_auth5.signInAnonymously)(this.auth);
8311
+ const { user: firebaseUser } = await (0, import_auth7.signInAnonymously)(this.auth);
8182
8312
  return this.userService.getOrCreateUser(firebaseUser);
8183
8313
  }
8184
8314
  /**
8185
8315
  * Odjavljuje trenutnog korisnika
8186
8316
  */
8187
8317
  async signOut() {
8188
- await (0, import_auth5.signOut)(this.auth);
8318
+ await (0, import_auth7.signOut)(this.auth);
8189
8319
  }
8190
8320
  /**
8191
8321
  * Vraća trenutno prijavljenog korisnika
@@ -8199,7 +8329,7 @@ var AuthService = class extends BaseService {
8199
8329
  * Registruje callback za promene stanja autentifikacije
8200
8330
  */
8201
8331
  onAuthStateChange(callback) {
8202
- return (0, import_auth5.onAuthStateChanged)(this.auth, callback);
8332
+ return (0, import_auth7.onAuthStateChanged)(this.auth, callback);
8203
8333
  }
8204
8334
  async upgradeAnonymousUser(email, password) {
8205
8335
  try {
@@ -8216,14 +8346,14 @@ var AuthService = class extends BaseService {
8216
8346
  400
8217
8347
  );
8218
8348
  }
8219
- const credential = import_auth5.EmailAuthProvider.credential(email, password);
8220
- await (0, import_auth5.linkWithCredential)(currentUser, credential);
8349
+ const credential = import_auth7.EmailAuthProvider.credential(email, password);
8350
+ await (0, import_auth7.linkWithCredential)(currentUser, credential);
8221
8351
  return await this.userService.upgradeAnonymousUser(
8222
8352
  currentUser.uid,
8223
8353
  email
8224
8354
  );
8225
8355
  } catch (error) {
8226
- if (error instanceof import_zod20.z.ZodError) {
8356
+ if (error instanceof import_zod22.z.ZodError) {
8227
8357
  throw AUTH_ERRORS.VALIDATION_ERROR;
8228
8358
  }
8229
8359
  const firebaseError = error;
@@ -8256,7 +8386,7 @@ var AuthService = class extends BaseService {
8256
8386
  400
8257
8387
  );
8258
8388
  }
8259
- const userCredential = await (0, import_auth5.signInWithPopup)(
8389
+ const userCredential = await (0, import_auth7.signInWithPopup)(
8260
8390
  this.auth,
8261
8391
  this.googleProvider
8262
8392
  );
@@ -8287,7 +8417,7 @@ var AuthService = class extends BaseService {
8287
8417
  );
8288
8418
  }
8289
8419
  this.facebookProvider.addScope("email");
8290
- const userCredential = await (0, import_auth5.signInWithPopup)(
8420
+ const userCredential = await (0, import_auth7.signInWithPopup)(
8291
8421
  this.auth,
8292
8422
  this.facebookProvider
8293
8423
  );
@@ -8319,7 +8449,7 @@ var AuthService = class extends BaseService {
8319
8449
  }
8320
8450
  this.appleProvider.addScope("email");
8321
8451
  this.appleProvider.addScope("name");
8322
- const userCredential = await (0, import_auth5.signInWithPopup)(
8452
+ const userCredential = await (0, import_auth7.signInWithPopup)(
8323
8453
  this.auth,
8324
8454
  this.appleProvider
8325
8455
  );
@@ -8344,9 +8474,9 @@ var AuthService = class extends BaseService {
8344
8474
  async sendPasswordResetEmail(email) {
8345
8475
  try {
8346
8476
  await emailSchema.parseAsync(email);
8347
- await (0, import_auth5.sendPasswordResetEmail)(this.auth, email);
8477
+ await (0, import_auth7.sendPasswordResetEmail)(this.auth, email);
8348
8478
  } catch (error) {
8349
- if (error instanceof import_zod20.z.ZodError) {
8479
+ if (error instanceof import_zod22.z.ZodError) {
8350
8480
  throw AUTH_ERRORS.VALIDATION_ERROR;
8351
8481
  }
8352
8482
  const firebaseError = error;
@@ -8363,7 +8493,7 @@ var AuthService = class extends BaseService {
8363
8493
  */
8364
8494
  async verifyPasswordResetCode(oobCode) {
8365
8495
  try {
8366
- return await (0, import_auth5.verifyPasswordResetCode)(this.auth, oobCode);
8496
+ return await (0, import_auth7.verifyPasswordResetCode)(this.auth, oobCode);
8367
8497
  } catch (error) {
8368
8498
  const firebaseError = error;
8369
8499
  if (firebaseError.code === "auth/expired-action-code" /* EXPIRED_ACTION_CODE */) {
@@ -8383,9 +8513,9 @@ var AuthService = class extends BaseService {
8383
8513
  async confirmPasswordReset(oobCode, newPassword) {
8384
8514
  try {
8385
8515
  await passwordSchema.parseAsync(newPassword);
8386
- await (0, import_auth5.confirmPasswordReset)(this.auth, oobCode, newPassword);
8516
+ await (0, import_auth7.confirmPasswordReset)(this.auth, oobCode, newPassword);
8387
8517
  } catch (error) {
8388
- if (error instanceof import_zod20.z.ZodError) {
8518
+ if (error instanceof import_zod22.z.ZodError) {
8389
8519
  throw AUTH_ERRORS.VALIDATION_ERROR;
8390
8520
  }
8391
8521
  const firebaseError = error;
@@ -8400,33 +8530,23 @@ var AuthService = class extends BaseService {
8400
8530
  }
8401
8531
  }
8402
8532
  /**
8403
- * Registers a new practitioner user with email and password
8404
- * Can either create a new practitioner profile or claim an existing draft profile with a token
8533
+ * Registers a new practitioner user with email and password (ATOMIC VERSION)
8534
+ * Uses Firestore transactions to ensure atomicity and proper rollback on failures
8405
8535
  *
8406
8536
  * @param data - Practitioner signup data containing either new profile details or token for claiming draft profile
8407
8537
  * @returns Object containing the created user and practitioner profile
8408
8538
  */
8409
8539
  async signUpPractitioner(data) {
8410
- var _a, _b, _c, _d;
8540
+ let firebaseUser = null;
8411
8541
  try {
8412
- console.log("[AUTH] Starting practitioner signup process", {
8542
+ console.log("[AUTH] Starting atomic practitioner signup process", {
8413
8543
  email: data.email,
8414
8544
  hasToken: !!data.token
8415
8545
  });
8416
- try {
8417
- await practitionerSignupSchema.parseAsync(data);
8418
- console.log("[AUTH] Practitioner signup data validation passed");
8419
- } catch (validationError) {
8420
- console.error(
8421
- "[AUTH] Validation error in signUpPractitioner:",
8422
- validationError
8423
- );
8424
- throw validationError;
8425
- }
8546
+ await this.validateSignupData(data);
8426
8547
  console.log("[AUTH] Creating Firebase user");
8427
- let firebaseUser;
8428
8548
  try {
8429
- const result = await (0, import_auth5.createUserWithEmailAndPassword)(
8549
+ const result = await (0, import_auth7.createUserWithEmailAndPassword)(
8430
8550
  this.auth,
8431
8551
  data.email,
8432
8552
  data.password
@@ -8437,136 +8557,110 @@ var AuthService = class extends BaseService {
8437
8557
  });
8438
8558
  } catch (firebaseError) {
8439
8559
  console.error("[AUTH] Firebase user creation failed:", firebaseError);
8440
- throw firebaseError;
8441
- }
8442
- console.log("[AUTH] Creating user with PRACTITIONER role");
8443
- let user;
8444
- try {
8445
- user = await this.userService.createUser(
8446
- firebaseUser,
8447
- ["practitioner" /* PRACTITIONER */],
8448
- {
8449
- skipProfileCreation: true
8450
- // We'll create the profile separately
8451
- }
8452
- );
8453
- console.log("[AUTH] User with PRACTITIONER role created successfully", {
8454
- userId: user.uid
8455
- });
8456
- } catch (userCreationError) {
8457
- console.error("[AUTH] User creation failed:", userCreationError);
8458
- throw userCreationError;
8560
+ throw handleFirebaseError(firebaseError);
8459
8561
  }
8460
- console.log("[AUTH] Initializing practitioner service");
8461
- const practitionerService = new PractitionerService(
8562
+ console.log("[AUTH] Starting Firestore transaction");
8563
+ const transactionResult = await (0, import_firestore25.runTransaction)(
8462
8564
  this.db,
8463
- this.auth,
8464
- this.app
8465
- );
8466
- let practitioner = null;
8467
- if (data.token) {
8468
- console.log("[AUTH] Token provided, attempting to claim draft profile");
8469
- try {
8470
- practitioner = await practitionerService.validateTokenAndClaimProfile(
8471
- data.token,
8472
- firebaseUser.uid
8473
- );
8474
- if (!practitioner) {
8475
- throw new Error("Invalid or expired invitation token");
8476
- }
8477
- console.log("[AUTH] Successfully claimed draft profile", {
8478
- practitionerId: practitioner.id
8479
- });
8480
- await this.userService.updateUser(firebaseUser.uid, {
8481
- practitionerProfile: practitioner.id
8482
- });
8565
+ async (transaction) => {
8483
8566
  console.log(
8484
- "[AUTH] User updated with practitioner profile reference"
8567
+ "[AUTH] Transaction started - creating user and practitioner"
8485
8568
  );
8486
- } catch (tokenError) {
8487
- console.error("[AUTH] Failed to claim draft profile:", tokenError);
8488
- throw tokenError;
8489
- }
8490
- } else {
8491
- console.log("[AUTH] Creating new practitioner profile");
8492
- if (!data.profileData) {
8493
- data.profileData = {};
8494
- }
8495
- const basicInfo = {
8496
- firstName: data.firstName || "",
8497
- lastName: data.lastName || "",
8498
- email: data.email,
8499
- phoneNumber: ((_a = data.profileData.basicInfo) == null ? void 0 : _a.phoneNumber) || "",
8500
- profileImageUrl: ((_b = data.profileData.basicInfo) == null ? void 0 : _b.profileImageUrl) || "",
8501
- gender: ((_c = data.profileData.basicInfo) == null ? void 0 : _c.gender) || "other",
8502
- // Default to "other" if not provided
8503
- bio: ((_d = data.profileData.basicInfo) == null ? void 0 : _d.bio) || "",
8504
- title: "Practitioner",
8505
- // Default title
8506
- dateOfBirth: /* @__PURE__ */ new Date(),
8507
- // Default to today
8508
- languages: ["English"]
8509
- // Default language
8510
- };
8511
- const certification = data.profileData.certification || {
8512
- level: "aesthetician" /* AESTHETICIAN */,
8513
- specialties: [],
8514
- licenseNumber: "Pending",
8515
- issuingAuthority: "Pending",
8516
- issueDate: /* @__PURE__ */ new Date(),
8517
- verificationStatus: "pending"
8518
- };
8519
- const createPractitionerData = {
8520
- userRef: firebaseUser.uid,
8521
- basicInfo,
8522
- certification,
8523
- status: "active" /* ACTIVE */,
8524
- isActive: true,
8525
- isVerified: false
8526
- };
8527
- try {
8528
- practitioner = await practitionerService.createPractitioner(
8529
- createPractitionerData
8569
+ const practitionerService = new PractitionerService(
8570
+ this.db,
8571
+ this.auth,
8572
+ this.app
8530
8573
  );
8531
- console.log("[AUTH] Practitioner profile created successfully", {
8532
- practitionerId: practitioner.id
8533
- });
8574
+ console.log("[AUTH] Creating user document");
8575
+ const user = await this.userService.createUser(
8576
+ firebaseUser,
8577
+ ["practitioner" /* PRACTITIONER */],
8578
+ { skipProfileCreation: true }
8579
+ );
8580
+ let practitioner;
8581
+ if (data.token) {
8582
+ console.log(
8583
+ "[AUTH] Claiming existing practitioner profile with token"
8584
+ );
8585
+ const claimedPractitioner = await practitionerService.validateTokenAndClaimProfile(
8586
+ data.token,
8587
+ firebaseUser.uid
8588
+ );
8589
+ if (!claimedPractitioner) {
8590
+ throw new Error("Invalid or expired invitation token");
8591
+ }
8592
+ practitioner = claimedPractitioner;
8593
+ } else {
8594
+ console.log("[AUTH] Creating new practitioner profile");
8595
+ const practitionerData = buildPractitionerData(
8596
+ data,
8597
+ firebaseUser.uid
8598
+ );
8599
+ practitioner = await practitionerService.createPractitioner(
8600
+ practitionerData
8601
+ );
8602
+ }
8603
+ console.log("[AUTH] Linking practitioner to user");
8534
8604
  await this.userService.updateUser(firebaseUser.uid, {
8535
8605
  practitionerProfile: practitioner.id
8536
8606
  });
8537
- console.log(
8538
- "[AUTH] User updated with practitioner profile reference"
8539
- );
8540
- } catch (createError) {
8541
- console.error(
8542
- "[AUTH] Failed to create practitioner profile:",
8543
- createError
8544
- );
8545
- throw createError;
8607
+ console.log("[AUTH] Transaction operations completed successfully");
8608
+ return { user, practitioner };
8546
8609
  }
8547
- }
8548
- console.log("[AUTH] Practitioner signup completed successfully", {
8549
- userId: user.uid,
8550
- practitionerId: (practitioner == null ? void 0 : practitioner.id) || "unknown"
8610
+ );
8611
+ console.log("[AUTH] Atomic practitioner signup completed successfully", {
8612
+ userId: transactionResult.user.uid,
8613
+ practitionerId: transactionResult.practitioner.id
8551
8614
  });
8552
- return {
8553
- user,
8554
- practitioner
8555
- };
8615
+ return transactionResult;
8556
8616
  } catch (error) {
8557
- if (error instanceof import_zod20.z.ZodError) {
8558
- console.error(
8559
- "[AUTH] Zod validation error in signUpPractitioner:",
8560
- JSON.stringify(error.errors, null, 2)
8561
- );
8562
- throw AUTH_ERRORS.VALIDATION_ERROR;
8617
+ console.error(
8618
+ "[AUTH] Atomic signup failed, initiating cleanup...",
8619
+ error
8620
+ );
8621
+ if (firebaseUser) {
8622
+ await cleanupFirebaseUser(firebaseUser);
8563
8623
  }
8564
- const firebaseError = error;
8565
- if (firebaseError.code === "auth/email-already-in-use" /* EMAIL_ALREADY_IN_USE */) {
8566
- console.error("[AUTH] Email already in use:", data.email);
8624
+ throw handleSignupError(error);
8625
+ }
8626
+ }
8627
+ /**
8628
+ * Pre-validate all signup data before any mutations
8629
+ * Prevents partial creation by catching issues early
8630
+ */
8631
+ async validateSignupData(data) {
8632
+ console.log("[AUTH] Pre-validating signup data");
8633
+ try {
8634
+ await practitionerSignupSchema.parseAsync(data);
8635
+ console.log("[AUTH] Schema validation passed");
8636
+ const emailExists = await checkEmailExists(this.auth, data.email);
8637
+ if (emailExists) {
8638
+ console.log("[AUTH] Email already exists:", data.email);
8567
8639
  throw AUTH_ERRORS.EMAIL_ALREADY_EXISTS;
8568
8640
  }
8569
- console.error("[AUTH] Unhandled error in signUpPractitioner:", error);
8641
+ console.log("[AUTH] Email availability confirmed");
8642
+ if (data.token) {
8643
+ const practitionerService = new PractitionerService(
8644
+ this.db,
8645
+ this.auth,
8646
+ this.app
8647
+ );
8648
+ const isValidToken = await practitionerService.validateToken(
8649
+ data.token
8650
+ );
8651
+ if (!isValidToken) {
8652
+ console.log("[AUTH] Invalid token provided:", data.token);
8653
+ throw new Error("Invalid or expired invitation token");
8654
+ }
8655
+ console.log("[AUTH] Token validation passed");
8656
+ }
8657
+ if (data.profileData) {
8658
+ await validatePractitionerProfileData(data.profileData);
8659
+ console.log("[AUTH] Profile data validation passed");
8660
+ }
8661
+ console.log("[AUTH] All pre-validation checks passed");
8662
+ } catch (error) {
8663
+ console.error("[AUTH] Pre-validation failed:", error);
8570
8664
  throw error;
8571
8665
  }
8572
8666
  }
@@ -8589,7 +8683,7 @@ var AuthService = class extends BaseService {
8589
8683
  this.auth,
8590
8684
  this.app
8591
8685
  );
8592
- const { user: firebaseUser } = await (0, import_auth5.signInWithEmailAndPassword)(
8686
+ const { user: firebaseUser } = await (0, import_auth7.signInWithEmailAndPassword)(
8593
8687
  this.auth,
8594
8688
  email,
8595
8689
  password
@@ -8832,63 +8926,63 @@ var import_firestore27 = require("firebase/firestore");
8832
8926
  var PROCEDURES_COLLECTION = "procedures";
8833
8927
 
8834
8928
  // src/validations/procedure.schema.ts
8835
- var import_zod21 = require("zod");
8836
- var createProcedureSchema = import_zod21.z.object({
8837
- name: import_zod21.z.string().min(1).max(200),
8838
- description: import_zod21.z.string().min(1).max(2e3),
8839
- family: import_zod21.z.nativeEnum(ProcedureFamily),
8840
- categoryId: import_zod21.z.string().min(1),
8841
- subcategoryId: import_zod21.z.string().min(1),
8842
- technologyId: import_zod21.z.string().min(1),
8843
- productId: import_zod21.z.string().min(1),
8844
- price: import_zod21.z.number().min(0),
8845
- currency: import_zod21.z.nativeEnum(Currency),
8846
- pricingMeasure: import_zod21.z.nativeEnum(PricingMeasure),
8847
- duration: import_zod21.z.number().min(1).max(480),
8929
+ var import_zod23 = require("zod");
8930
+ var createProcedureSchema = import_zod23.z.object({
8931
+ name: import_zod23.z.string().min(1).max(200),
8932
+ description: import_zod23.z.string().min(1).max(2e3),
8933
+ family: import_zod23.z.nativeEnum(ProcedureFamily),
8934
+ categoryId: import_zod23.z.string().min(1),
8935
+ subcategoryId: import_zod23.z.string().min(1),
8936
+ technologyId: import_zod23.z.string().min(1),
8937
+ productId: import_zod23.z.string().min(1),
8938
+ price: import_zod23.z.number().min(0),
8939
+ currency: import_zod23.z.nativeEnum(Currency),
8940
+ pricingMeasure: import_zod23.z.nativeEnum(PricingMeasure),
8941
+ duration: import_zod23.z.number().min(1).max(480),
8848
8942
  // Max 8 hours
8849
- practitionerId: import_zod21.z.string().min(1),
8850
- clinicBranchId: import_zod21.z.string().min(1),
8851
- photos: import_zod21.z.array(mediaResourceSchema).optional()
8852
- });
8853
- var updateProcedureSchema = import_zod21.z.object({
8854
- name: import_zod21.z.string().min(3).max(100).optional(),
8855
- description: import_zod21.z.string().min(3).max(1e3).optional(),
8856
- price: import_zod21.z.number().min(0).optional(),
8857
- currency: import_zod21.z.nativeEnum(Currency).optional(),
8858
- pricingMeasure: import_zod21.z.nativeEnum(PricingMeasure).optional(),
8859
- duration: import_zod21.z.number().min(0).optional(),
8860
- isActive: import_zod21.z.boolean().optional(),
8861
- practitionerId: import_zod21.z.string().optional(),
8862
- categoryId: import_zod21.z.string().optional(),
8863
- subcategoryId: import_zod21.z.string().optional(),
8864
- technologyId: import_zod21.z.string().optional(),
8865
- productId: import_zod21.z.string().optional(),
8866
- clinicBranchId: import_zod21.z.string().optional(),
8867
- photos: import_zod21.z.array(mediaResourceSchema).optional()
8943
+ practitionerId: import_zod23.z.string().min(1),
8944
+ clinicBranchId: import_zod23.z.string().min(1),
8945
+ photos: import_zod23.z.array(mediaResourceSchema).optional()
8946
+ });
8947
+ var updateProcedureSchema = import_zod23.z.object({
8948
+ name: import_zod23.z.string().min(3).max(100).optional(),
8949
+ description: import_zod23.z.string().min(3).max(1e3).optional(),
8950
+ price: import_zod23.z.number().min(0).optional(),
8951
+ currency: import_zod23.z.nativeEnum(Currency).optional(),
8952
+ pricingMeasure: import_zod23.z.nativeEnum(PricingMeasure).optional(),
8953
+ duration: import_zod23.z.number().min(0).optional(),
8954
+ isActive: import_zod23.z.boolean().optional(),
8955
+ practitionerId: import_zod23.z.string().optional(),
8956
+ categoryId: import_zod23.z.string().optional(),
8957
+ subcategoryId: import_zod23.z.string().optional(),
8958
+ technologyId: import_zod23.z.string().optional(),
8959
+ productId: import_zod23.z.string().optional(),
8960
+ clinicBranchId: import_zod23.z.string().optional(),
8961
+ photos: import_zod23.z.array(mediaResourceSchema).optional()
8868
8962
  });
8869
8963
  var procedureSchema = createProcedureSchema.extend({
8870
- id: import_zod21.z.string().min(1),
8871
- category: import_zod21.z.any(),
8964
+ id: import_zod23.z.string().min(1),
8965
+ category: import_zod23.z.any(),
8872
8966
  // We'll validate the full category object separately
8873
- subcategory: import_zod21.z.any(),
8967
+ subcategory: import_zod23.z.any(),
8874
8968
  // We'll validate the full subcategory object separately
8875
- technology: import_zod21.z.any(),
8969
+ technology: import_zod23.z.any(),
8876
8970
  // We'll validate the full technology object separately
8877
- product: import_zod21.z.any(),
8971
+ product: import_zod23.z.any(),
8878
8972
  // We'll validate the full product object separately
8879
- blockingConditions: import_zod21.z.array(import_zod21.z.any()),
8973
+ blockingConditions: import_zod23.z.array(import_zod23.z.any()),
8880
8974
  // We'll validate blocking conditions separately
8881
- contraindications: import_zod21.z.array(import_zod21.z.any()),
8975
+ contraindications: import_zod23.z.array(import_zod23.z.any()),
8882
8976
  // We'll validate contraindications separately
8883
- treatmentBenefits: import_zod21.z.array(import_zod21.z.any()),
8977
+ treatmentBenefits: import_zod23.z.array(import_zod23.z.any()),
8884
8978
  // We'll validate treatment benefits separately
8885
- preRequirements: import_zod21.z.array(import_zod21.z.any()),
8979
+ preRequirements: import_zod23.z.array(import_zod23.z.any()),
8886
8980
  // We'll validate requirements separately
8887
- postRequirements: import_zod21.z.array(import_zod21.z.any()),
8981
+ postRequirements: import_zod23.z.array(import_zod23.z.any()),
8888
8982
  // We'll validate requirements separately
8889
- certificationRequirement: import_zod21.z.any(),
8983
+ certificationRequirement: import_zod23.z.any(),
8890
8984
  // We'll validate certification requirement separately
8891
- documentationTemplates: import_zod21.z.array(import_zod21.z.any()),
8985
+ documentationTemplates: import_zod23.z.array(import_zod23.z.any()),
8892
8986
  // We'll validate documentation templates separately
8893
8987
  clinicInfo: clinicInfoSchema,
8894
8988
  // Clinic info validation
@@ -8896,9 +8990,9 @@ var procedureSchema = createProcedureSchema.extend({
8896
8990
  // Doctor info validation
8897
8991
  reviewInfo: procedureReviewInfoSchema,
8898
8992
  // Procedure review info validation
8899
- isActive: import_zod21.z.boolean(),
8900
- createdAt: import_zod21.z.date(),
8901
- updatedAt: import_zod21.z.date()
8993
+ isActive: import_zod23.z.boolean(),
8994
+ createdAt: import_zod23.z.date(),
8995
+ updatedAt: import_zod23.z.date()
8902
8996
  });
8903
8997
 
8904
8998
  // src/services/procedure/procedure.service.ts
@@ -9320,20 +9414,20 @@ var ProcedureService = class extends BaseService {
9320
9414
  const proceduresCollection = (0, import_firestore27.collection)(this.db, PROCEDURES_COLLECTION);
9321
9415
  let proceduresQuery = (0, import_firestore27.query)(proceduresCollection);
9322
9416
  if (pagination && pagination > 0) {
9323
- const { limit: limit15, startAfter: startAfter13 } = await import("firebase/firestore");
9417
+ const { limit: limit16, startAfter: startAfter14 } = await import("firebase/firestore");
9324
9418
  if (lastDoc) {
9325
9419
  proceduresQuery = (0, import_firestore27.query)(
9326
9420
  proceduresCollection,
9327
9421
  (0, import_firestore27.orderBy)("name"),
9328
9422
  // Use imported orderBy
9329
- startAfter13(lastDoc),
9330
- limit15(pagination)
9423
+ startAfter14(lastDoc),
9424
+ limit16(pagination)
9331
9425
  );
9332
9426
  } else {
9333
9427
  proceduresQuery = (0, import_firestore27.query)(
9334
9428
  proceduresCollection,
9335
9429
  (0, import_firestore27.orderBy)("name"),
9336
- limit15(pagination)
9430
+ limit16(pagination)
9337
9431
  );
9338
9432
  }
9339
9433
  } else {
@@ -10732,42 +10826,42 @@ var SYNCED_CALENDARS_COLLECTION = "syncedCalendars";
10732
10826
  var import_firestore41 = require("firebase/firestore");
10733
10827
 
10734
10828
  // src/validations/calendar.schema.ts
10735
- var import_zod23 = require("zod");
10829
+ var import_zod25 = require("zod");
10736
10830
  var import_firestore32 = require("firebase/firestore");
10737
10831
 
10738
10832
  // src/validations/profile-info.schema.ts
10739
- var import_zod22 = require("zod");
10833
+ var import_zod24 = require("zod");
10740
10834
  var import_firestore31 = require("firebase/firestore");
10741
- var clinicInfoSchema2 = import_zod22.z.object({
10742
- id: import_zod22.z.string(),
10743
- featuredPhoto: import_zod22.z.string(),
10744
- name: import_zod22.z.string(),
10745
- description: import_zod22.z.string(),
10835
+ var clinicInfoSchema2 = import_zod24.z.object({
10836
+ id: import_zod24.z.string(),
10837
+ featuredPhoto: import_zod24.z.string(),
10838
+ name: import_zod24.z.string(),
10839
+ description: import_zod24.z.string(),
10746
10840
  location: clinicLocationSchema,
10747
10841
  contactInfo: clinicContactInfoSchema
10748
10842
  });
10749
- var practitionerProfileInfoSchema = import_zod22.z.object({
10750
- id: import_zod22.z.string(),
10751
- practitionerPhoto: import_zod22.z.string().nullable(),
10752
- name: import_zod22.z.string(),
10753
- email: import_zod22.z.string().email(),
10754
- phone: import_zod22.z.string().nullable(),
10843
+ var practitionerProfileInfoSchema = import_zod24.z.object({
10844
+ id: import_zod24.z.string(),
10845
+ practitionerPhoto: import_zod24.z.string().nullable(),
10846
+ name: import_zod24.z.string(),
10847
+ email: import_zod24.z.string().email(),
10848
+ phone: import_zod24.z.string().nullable(),
10755
10849
  certification: practitionerCertificationSchema
10756
10850
  });
10757
- var patientProfileInfoSchema = import_zod22.z.object({
10758
- id: import_zod22.z.string(),
10759
- fullName: import_zod22.z.string(),
10760
- email: import_zod22.z.string().email(),
10761
- phone: import_zod22.z.string().nullable(),
10762
- dateOfBirth: import_zod22.z.instanceof(import_firestore31.Timestamp),
10763
- gender: import_zod22.z.nativeEnum(Gender)
10851
+ var patientProfileInfoSchema = import_zod24.z.object({
10852
+ id: import_zod24.z.string(),
10853
+ fullName: import_zod24.z.string(),
10854
+ email: import_zod24.z.string().email(),
10855
+ phone: import_zod24.z.string().nullable(),
10856
+ dateOfBirth: import_zod24.z.instanceof(import_firestore31.Timestamp),
10857
+ gender: import_zod24.z.nativeEnum(Gender)
10764
10858
  });
10765
10859
 
10766
10860
  // src/validations/calendar.schema.ts
10767
10861
  var MIN_APPOINTMENT_DURATION = 15;
10768
- var calendarEventTimeSchema = import_zod23.z.object({
10769
- start: import_zod23.z.instanceof(Date).or(import_zod23.z.instanceof(import_firestore32.Timestamp)),
10770
- end: import_zod23.z.instanceof(Date).or(import_zod23.z.instanceof(import_firestore32.Timestamp))
10862
+ var calendarEventTimeSchema = import_zod25.z.object({
10863
+ start: import_zod25.z.instanceof(Date).or(import_zod25.z.instanceof(import_firestore32.Timestamp)),
10864
+ end: import_zod25.z.instanceof(Date).or(import_zod25.z.instanceof(import_firestore32.Timestamp))
10771
10865
  }).refine(
10772
10866
  (data) => {
10773
10867
  const startDate = data.start instanceof import_firestore32.Timestamp ? data.start.toDate() : data.start;
@@ -10788,46 +10882,46 @@ var calendarEventTimeSchema = import_zod23.z.object({
10788
10882
  path: ["start"]
10789
10883
  }
10790
10884
  );
10791
- var timeSlotSchema2 = import_zod23.z.object({
10792
- start: import_zod23.z.date(),
10793
- end: import_zod23.z.date(),
10794
- isAvailable: import_zod23.z.boolean()
10885
+ var timeSlotSchema2 = import_zod25.z.object({
10886
+ start: import_zod25.z.date(),
10887
+ end: import_zod25.z.date(),
10888
+ isAvailable: import_zod25.z.boolean()
10795
10889
  }).refine((data) => data.start < data.end, {
10796
10890
  message: "End time must be after start time",
10797
10891
  path: ["end"]
10798
10892
  });
10799
- var syncedCalendarEventSchema = import_zod23.z.object({
10800
- eventId: import_zod23.z.string(),
10801
- syncedCalendarProvider: import_zod23.z.nativeEnum(SyncedCalendarProvider),
10802
- syncedAt: import_zod23.z.instanceof(Date).or(import_zod23.z.instanceof(import_firestore32.Timestamp))
10893
+ var syncedCalendarEventSchema = import_zod25.z.object({
10894
+ eventId: import_zod25.z.string(),
10895
+ syncedCalendarProvider: import_zod25.z.nativeEnum(SyncedCalendarProvider),
10896
+ syncedAt: import_zod25.z.instanceof(Date).or(import_zod25.z.instanceof(import_firestore32.Timestamp))
10803
10897
  });
10804
- var procedureInfoSchema = import_zod23.z.object({
10805
- name: import_zod23.z.string(),
10806
- description: import_zod23.z.string(),
10807
- duration: import_zod23.z.number().min(MIN_APPOINTMENT_DURATION),
10808
- price: import_zod23.z.number().min(0),
10809
- currency: import_zod23.z.nativeEnum(Currency)
10898
+ var procedureInfoSchema = import_zod25.z.object({
10899
+ name: import_zod25.z.string(),
10900
+ description: import_zod25.z.string(),
10901
+ duration: import_zod25.z.number().min(MIN_APPOINTMENT_DURATION),
10902
+ price: import_zod25.z.number().min(0),
10903
+ currency: import_zod25.z.nativeEnum(Currency)
10810
10904
  });
10811
- var procedureCategorizationSchema = import_zod23.z.object({
10812
- procedureFamily: import_zod23.z.string(),
10905
+ var procedureCategorizationSchema = import_zod25.z.object({
10906
+ procedureFamily: import_zod25.z.string(),
10813
10907
  // Replace with proper enum when available
10814
- procedureCategory: import_zod23.z.string(),
10908
+ procedureCategory: import_zod25.z.string(),
10815
10909
  // Replace with proper enum when available
10816
- procedureSubcategory: import_zod23.z.string(),
10910
+ procedureSubcategory: import_zod25.z.string(),
10817
10911
  // Replace with proper enum when available
10818
- procedureTechnology: import_zod23.z.string(),
10912
+ procedureTechnology: import_zod25.z.string(),
10819
10913
  // Replace with proper enum when available
10820
- procedureProduct: import_zod23.z.string()
10914
+ procedureProduct: import_zod25.z.string()
10821
10915
  // Replace with proper enum when available
10822
10916
  });
10823
- var createAppointmentSchema2 = import_zod23.z.object({
10824
- clinicId: import_zod23.z.string().min(1, "Clinic ID is required"),
10825
- doctorId: import_zod23.z.string().min(1, "Doctor ID is required"),
10826
- patientId: import_zod23.z.string().min(1, "Patient ID is required"),
10827
- procedureId: import_zod23.z.string().min(1, "Procedure ID is required"),
10917
+ var createAppointmentSchema2 = import_zod25.z.object({
10918
+ clinicId: import_zod25.z.string().min(1, "Clinic ID is required"),
10919
+ doctorId: import_zod25.z.string().min(1, "Doctor ID is required"),
10920
+ patientId: import_zod25.z.string().min(1, "Patient ID is required"),
10921
+ procedureId: import_zod25.z.string().min(1, "Procedure ID is required"),
10828
10922
  eventLocation: clinicLocationSchema,
10829
10923
  eventTime: calendarEventTimeSchema,
10830
- description: import_zod23.z.string().optional()
10924
+ description: import_zod25.z.string().optional()
10831
10925
  }).refine(
10832
10926
  (data) => {
10833
10927
  return true;
@@ -10836,95 +10930,95 @@ var createAppointmentSchema2 = import_zod23.z.object({
10836
10930
  message: "Invalid appointment parameters"
10837
10931
  }
10838
10932
  );
10839
- var updateAppointmentSchema2 = import_zod23.z.object({
10840
- appointmentId: import_zod23.z.string().min(1, "Appointment ID is required"),
10841
- clinicId: import_zod23.z.string().min(1, "Clinic ID is required"),
10842
- doctorId: import_zod23.z.string().min(1, "Doctor ID is required"),
10843
- patientId: import_zod23.z.string().min(1, "Patient ID is required"),
10933
+ var updateAppointmentSchema2 = import_zod25.z.object({
10934
+ appointmentId: import_zod25.z.string().min(1, "Appointment ID is required"),
10935
+ clinicId: import_zod25.z.string().min(1, "Clinic ID is required"),
10936
+ doctorId: import_zod25.z.string().min(1, "Doctor ID is required"),
10937
+ patientId: import_zod25.z.string().min(1, "Patient ID is required"),
10844
10938
  eventTime: calendarEventTimeSchema.optional(),
10845
- description: import_zod23.z.string().optional(),
10846
- status: import_zod23.z.nativeEnum(CalendarEventStatus).optional()
10847
- });
10848
- var createCalendarEventSchema = import_zod23.z.object({
10849
- id: import_zod23.z.string(),
10850
- clinicBranchId: import_zod23.z.string().nullable().optional(),
10851
- clinicBranchInfo: import_zod23.z.any().nullable().optional(),
10852
- practitionerProfileId: import_zod23.z.string().nullable().optional(),
10939
+ description: import_zod25.z.string().optional(),
10940
+ status: import_zod25.z.nativeEnum(CalendarEventStatus).optional()
10941
+ });
10942
+ var createCalendarEventSchema = import_zod25.z.object({
10943
+ id: import_zod25.z.string(),
10944
+ clinicBranchId: import_zod25.z.string().nullable().optional(),
10945
+ clinicBranchInfo: import_zod25.z.any().nullable().optional(),
10946
+ practitionerProfileId: import_zod25.z.string().nullable().optional(),
10853
10947
  practitionerProfileInfo: practitionerProfileInfoSchema.nullable().optional(),
10854
- patientProfileId: import_zod23.z.string().nullable().optional(),
10948
+ patientProfileId: import_zod25.z.string().nullable().optional(),
10855
10949
  patientProfileInfo: patientProfileInfoSchema.nullable().optional(),
10856
- procedureId: import_zod23.z.string().nullable().optional(),
10857
- appointmentId: import_zod23.z.string().nullable().optional(),
10858
- syncedCalendarEventId: import_zod23.z.array(syncedCalendarEventSchema).nullable().optional(),
10859
- eventName: import_zod23.z.string().min(1, "Event name is required"),
10950
+ procedureId: import_zod25.z.string().nullable().optional(),
10951
+ appointmentId: import_zod25.z.string().nullable().optional(),
10952
+ syncedCalendarEventId: import_zod25.z.array(syncedCalendarEventSchema).nullable().optional(),
10953
+ eventName: import_zod25.z.string().min(1, "Event name is required"),
10860
10954
  eventLocation: clinicLocationSchema.optional(),
10861
10955
  eventTime: calendarEventTimeSchema,
10862
- description: import_zod23.z.string().optional(),
10863
- status: import_zod23.z.nativeEnum(CalendarEventStatus),
10864
- syncStatus: import_zod23.z.nativeEnum(CalendarSyncStatus),
10865
- eventType: import_zod23.z.nativeEnum(CalendarEventType),
10866
- createdAt: import_zod23.z.any(),
10956
+ description: import_zod25.z.string().optional(),
10957
+ status: import_zod25.z.nativeEnum(CalendarEventStatus),
10958
+ syncStatus: import_zod25.z.nativeEnum(CalendarSyncStatus),
10959
+ eventType: import_zod25.z.nativeEnum(CalendarEventType),
10960
+ createdAt: import_zod25.z.any(),
10867
10961
  // FieldValue for server timestamp
10868
- updatedAt: import_zod23.z.any()
10962
+ updatedAt: import_zod25.z.any()
10869
10963
  // FieldValue for server timestamp
10870
10964
  });
10871
- var updateCalendarEventSchema = import_zod23.z.object({
10872
- syncedCalendarEventId: import_zod23.z.array(syncedCalendarEventSchema).nullable().optional(),
10873
- appointmentId: import_zod23.z.string().nullable().optional(),
10874
- eventName: import_zod23.z.string().optional(),
10965
+ var updateCalendarEventSchema = import_zod25.z.object({
10966
+ syncedCalendarEventId: import_zod25.z.array(syncedCalendarEventSchema).nullable().optional(),
10967
+ appointmentId: import_zod25.z.string().nullable().optional(),
10968
+ eventName: import_zod25.z.string().optional(),
10875
10969
  eventTime: calendarEventTimeSchema.optional(),
10876
- description: import_zod23.z.string().optional(),
10877
- status: import_zod23.z.nativeEnum(CalendarEventStatus).optional(),
10878
- syncStatus: import_zod23.z.nativeEnum(CalendarSyncStatus).optional(),
10879
- eventType: import_zod23.z.nativeEnum(CalendarEventType).optional(),
10880
- updatedAt: import_zod23.z.any()
10970
+ description: import_zod25.z.string().optional(),
10971
+ status: import_zod25.z.nativeEnum(CalendarEventStatus).optional(),
10972
+ syncStatus: import_zod25.z.nativeEnum(CalendarSyncStatus).optional(),
10973
+ eventType: import_zod25.z.nativeEnum(CalendarEventType).optional(),
10974
+ updatedAt: import_zod25.z.any()
10881
10975
  // FieldValue for server timestamp
10882
10976
  });
10883
- var calendarEventSchema = import_zod23.z.object({
10884
- id: import_zod23.z.string(),
10885
- clinicBranchId: import_zod23.z.string().nullable().optional(),
10886
- clinicBranchInfo: import_zod23.z.any().nullable().optional(),
10977
+ var calendarEventSchema = import_zod25.z.object({
10978
+ id: import_zod25.z.string(),
10979
+ clinicBranchId: import_zod25.z.string().nullable().optional(),
10980
+ clinicBranchInfo: import_zod25.z.any().nullable().optional(),
10887
10981
  // Will be replaced with proper clinic info schema
10888
- practitionerProfileId: import_zod23.z.string().nullable().optional(),
10982
+ practitionerProfileId: import_zod25.z.string().nullable().optional(),
10889
10983
  practitionerProfileInfo: practitionerProfileInfoSchema.nullable().optional(),
10890
- patientProfileId: import_zod23.z.string().nullable().optional(),
10984
+ patientProfileId: import_zod25.z.string().nullable().optional(),
10891
10985
  patientProfileInfo: patientProfileInfoSchema.nullable().optional(),
10892
- procedureId: import_zod23.z.string().nullable().optional(),
10986
+ procedureId: import_zod25.z.string().nullable().optional(),
10893
10987
  procedureInfo: procedureInfoSchema.nullable().optional(),
10894
10988
  procedureCategorization: procedureCategorizationSchema.nullable().optional(),
10895
- appointmentId: import_zod23.z.string().nullable().optional(),
10896
- syncedCalendarEventId: import_zod23.z.array(syncedCalendarEventSchema).nullable().optional(),
10897
- eventName: import_zod23.z.string(),
10989
+ appointmentId: import_zod25.z.string().nullable().optional(),
10990
+ syncedCalendarEventId: import_zod25.z.array(syncedCalendarEventSchema).nullable().optional(),
10991
+ eventName: import_zod25.z.string(),
10898
10992
  eventLocation: clinicLocationSchema.optional(),
10899
10993
  eventTime: calendarEventTimeSchema,
10900
- description: import_zod23.z.string().optional(),
10901
- status: import_zod23.z.nativeEnum(CalendarEventStatus),
10902
- syncStatus: import_zod23.z.nativeEnum(CalendarSyncStatus),
10903
- eventType: import_zod23.z.nativeEnum(CalendarEventType),
10904
- createdAt: import_zod23.z.instanceof(Date).or(import_zod23.z.instanceof(import_firestore32.Timestamp)),
10905
- updatedAt: import_zod23.z.instanceof(Date).or(import_zod23.z.instanceof(import_firestore32.Timestamp))
10906
- });
10907
- var createBlockingEventSchema = import_zod23.z.object({
10908
- entityType: import_zod23.z.enum(["practitioner", "clinic"]),
10909
- entityId: import_zod23.z.string().min(1, "Entity ID is required"),
10910
- eventName: import_zod23.z.string().min(1, "Event name is required").max(200, "Event name too long"),
10994
+ description: import_zod25.z.string().optional(),
10995
+ status: import_zod25.z.nativeEnum(CalendarEventStatus),
10996
+ syncStatus: import_zod25.z.nativeEnum(CalendarSyncStatus),
10997
+ eventType: import_zod25.z.nativeEnum(CalendarEventType),
10998
+ createdAt: import_zod25.z.instanceof(Date).or(import_zod25.z.instanceof(import_firestore32.Timestamp)),
10999
+ updatedAt: import_zod25.z.instanceof(Date).or(import_zod25.z.instanceof(import_firestore32.Timestamp))
11000
+ });
11001
+ var createBlockingEventSchema = import_zod25.z.object({
11002
+ entityType: import_zod25.z.enum(["practitioner", "clinic"]),
11003
+ entityId: import_zod25.z.string().min(1, "Entity ID is required"),
11004
+ eventName: import_zod25.z.string().min(1, "Event name is required").max(200, "Event name too long"),
10911
11005
  eventTime: calendarEventTimeSchema,
10912
- eventType: import_zod23.z.enum([
11006
+ eventType: import_zod25.z.enum([
10913
11007
  "blocking" /* BLOCKING */,
10914
11008
  "break" /* BREAK */,
10915
11009
  "free_day" /* FREE_DAY */,
10916
11010
  "other" /* OTHER */
10917
11011
  ]),
10918
- description: import_zod23.z.string().max(1e3, "Description too long").optional()
11012
+ description: import_zod25.z.string().max(1e3, "Description too long").optional()
10919
11013
  });
10920
- var updateBlockingEventSchema = import_zod23.z.object({
10921
- entityType: import_zod23.z.enum(["practitioner", "clinic"]),
10922
- entityId: import_zod23.z.string().min(1, "Entity ID is required"),
10923
- eventId: import_zod23.z.string().min(1, "Event ID is required"),
10924
- eventName: import_zod23.z.string().min(1, "Event name is required").max(200, "Event name too long").optional(),
11014
+ var updateBlockingEventSchema = import_zod25.z.object({
11015
+ entityType: import_zod25.z.enum(["practitioner", "clinic"]),
11016
+ entityId: import_zod25.z.string().min(1, "Entity ID is required"),
11017
+ eventId: import_zod25.z.string().min(1, "Event ID is required"),
11018
+ eventName: import_zod25.z.string().min(1, "Event name is required").max(200, "Event name too long").optional(),
10925
11019
  eventTime: calendarEventTimeSchema.optional(),
10926
- description: import_zod23.z.string().max(1e3, "Description too long").optional(),
10927
- status: import_zod23.z.nativeEnum(CalendarEventStatus).optional()
11020
+ description: import_zod25.z.string().max(1e3, "Description too long").optional(),
11021
+ status: import_zod25.z.nativeEnum(CalendarEventStatus).optional()
10928
11022
  });
10929
11023
 
10930
11024
  // src/services/calendar/utils/clinic.utils.ts
@@ -13661,7 +13755,7 @@ var import_firestore44 = require("firebase/firestore");
13661
13755
  var REVIEWS_COLLECTION = "reviews";
13662
13756
 
13663
13757
  // src/services/reviews/reviews.service.ts
13664
- var import_zod24 = require("zod");
13758
+ var import_zod26 = require("zod");
13665
13759
  var ReviewService = class extends BaseService {
13666
13760
  constructor(db, auth, app) {
13667
13761
  super(db, auth, app);
@@ -13748,7 +13842,7 @@ var ReviewService = class extends BaseService {
13748
13842
  });
13749
13843
  return review;
13750
13844
  } catch (error) {
13751
- if (error instanceof import_zod24.z.ZodError) {
13845
+ if (error instanceof import_zod26.z.ZodError) {
13752
13846
  throw new Error(`Invalid review data: ${error.message}`);
13753
13847
  }
13754
13848
  throw error;
@@ -15949,63 +16043,63 @@ var ProductService = class extends BaseService {
15949
16043
  };
15950
16044
 
15951
16045
  // src/validations/notification.schema.ts
15952
- var import_zod25 = require("zod");
15953
- var baseNotificationSchema = import_zod25.z.object({
15954
- id: import_zod25.z.string().optional(),
15955
- userId: import_zod25.z.string(),
15956
- notificationTime: import_zod25.z.any(),
16046
+ var import_zod27 = require("zod");
16047
+ var baseNotificationSchema = import_zod27.z.object({
16048
+ id: import_zod27.z.string().optional(),
16049
+ userId: import_zod27.z.string(),
16050
+ notificationTime: import_zod27.z.any(),
15957
16051
  // Timestamp
15958
- notificationType: import_zod25.z.nativeEnum(NotificationType),
15959
- notificationTokens: import_zod25.z.array(import_zod25.z.string()),
15960
- status: import_zod25.z.nativeEnum(NotificationStatus),
15961
- createdAt: import_zod25.z.any().optional(),
16052
+ notificationType: import_zod27.z.nativeEnum(NotificationType),
16053
+ notificationTokens: import_zod27.z.array(import_zod27.z.string()),
16054
+ status: import_zod27.z.nativeEnum(NotificationStatus),
16055
+ createdAt: import_zod27.z.any().optional(),
15962
16056
  // Timestamp
15963
- updatedAt: import_zod25.z.any().optional(),
16057
+ updatedAt: import_zod27.z.any().optional(),
15964
16058
  // Timestamp
15965
- title: import_zod25.z.string(),
15966
- body: import_zod25.z.string(),
15967
- isRead: import_zod25.z.boolean(),
15968
- userRole: import_zod25.z.nativeEnum(UserRole)
16059
+ title: import_zod27.z.string(),
16060
+ body: import_zod27.z.string(),
16061
+ isRead: import_zod27.z.boolean(),
16062
+ userRole: import_zod27.z.nativeEnum(UserRole)
15969
16063
  });
15970
16064
  var preRequirementNotificationSchema = baseNotificationSchema.extend({
15971
- notificationType: import_zod25.z.literal("preRequirementInstructionDue" /* PRE_REQUIREMENT_INSTRUCTION_DUE */),
15972
- treatmentId: import_zod25.z.string(),
15973
- requirements: import_zod25.z.array(import_zod25.z.string()),
15974
- deadline: import_zod25.z.any()
16065
+ notificationType: import_zod27.z.literal("preRequirementInstructionDue" /* PRE_REQUIREMENT_INSTRUCTION_DUE */),
16066
+ treatmentId: import_zod27.z.string(),
16067
+ requirements: import_zod27.z.array(import_zod27.z.string()),
16068
+ deadline: import_zod27.z.any()
15975
16069
  // Timestamp
15976
16070
  });
15977
16071
  var postRequirementNotificationSchema = baseNotificationSchema.extend({
15978
- notificationType: import_zod25.z.literal(
16072
+ notificationType: import_zod27.z.literal(
15979
16073
  "postRequirementInstructionDue" /* POST_REQUIREMENT_INSTRUCTION_DUE */
15980
16074
  ),
15981
- treatmentId: import_zod25.z.string(),
15982
- requirements: import_zod25.z.array(import_zod25.z.string()),
15983
- deadline: import_zod25.z.any()
16075
+ treatmentId: import_zod27.z.string(),
16076
+ requirements: import_zod27.z.array(import_zod27.z.string()),
16077
+ deadline: import_zod27.z.any()
15984
16078
  // Timestamp
15985
16079
  });
15986
16080
  var requirementInstructionDueNotificationSchema = baseNotificationSchema.extend({
15987
- notificationType: import_zod25.z.literal("requirementInstructionDue" /* REQUIREMENT_INSTRUCTION_DUE */),
15988
- appointmentId: import_zod25.z.string(),
15989
- patientRequirementInstanceId: import_zod25.z.string(),
15990
- instructionId: import_zod25.z.string(),
15991
- originalRequirementId: import_zod25.z.string().optional()
16081
+ notificationType: import_zod27.z.literal("requirementInstructionDue" /* REQUIREMENT_INSTRUCTION_DUE */),
16082
+ appointmentId: import_zod27.z.string(),
16083
+ patientRequirementInstanceId: import_zod27.z.string(),
16084
+ instructionId: import_zod27.z.string(),
16085
+ originalRequirementId: import_zod27.z.string().optional()
15992
16086
  });
15993
16087
  var appointmentReminderNotificationSchema = baseNotificationSchema.extend({
15994
- notificationType: import_zod25.z.literal("appointmentReminder" /* APPOINTMENT_REMINDER */),
15995
- appointmentId: import_zod25.z.string(),
15996
- appointmentTime: import_zod25.z.any(),
16088
+ notificationType: import_zod27.z.literal("appointmentReminder" /* APPOINTMENT_REMINDER */),
16089
+ appointmentId: import_zod27.z.string(),
16090
+ appointmentTime: import_zod27.z.any(),
15997
16091
  // Timestamp
15998
- treatmentType: import_zod25.z.string(),
15999
- doctorName: import_zod25.z.string()
16092
+ treatmentType: import_zod27.z.string(),
16093
+ doctorName: import_zod27.z.string()
16000
16094
  });
16001
16095
  var appointmentNotificationSchema = baseNotificationSchema.extend({
16002
- notificationType: import_zod25.z.literal("appointmentStatusChange" /* APPOINTMENT_STATUS_CHANGE */),
16003
- appointmentId: import_zod25.z.string(),
16004
- appointmentStatus: import_zod25.z.string(),
16005
- previousStatus: import_zod25.z.string(),
16006
- reason: import_zod25.z.string().optional()
16096
+ notificationType: import_zod27.z.literal("appointmentStatusChange" /* APPOINTMENT_STATUS_CHANGE */),
16097
+ appointmentId: import_zod27.z.string(),
16098
+ appointmentStatus: import_zod27.z.string(),
16099
+ previousStatus: import_zod27.z.string(),
16100
+ reason: import_zod27.z.string().optional()
16007
16101
  });
16008
- var notificationSchema = import_zod25.z.discriminatedUnion("notificationType", [
16102
+ var notificationSchema = import_zod27.z.discriminatedUnion("notificationType", [
16009
16103
  preRequirementNotificationSchema,
16010
16104
  postRequirementNotificationSchema,
16011
16105
  requirementInstructionDueNotificationSchema,