@blackcode_sa/metaestetics-api 1.7.41 → 1.7.42

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");
@@ -4618,10 +4618,10 @@ var practitionerBasicInfoSchema = import_zod14.z.object({
4618
4618
  lastName: import_zod14.z.string().min(2).max(50),
4619
4619
  title: import_zod14.z.string().min(2).max(100),
4620
4620
  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()),
4621
+ phoneNumber: import_zod14.z.string().regex(/^\+?[1-9]\d{1,14}$/, "Invalid phone number").nullable(),
4622
+ dateOfBirth: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date()).nullable(),
4623
4623
  gender: import_zod14.z.enum(["male", "female", "other"]),
4624
- profileImageUrl: mediaResourceSchema.optional(),
4624
+ profileImageUrl: mediaResourceSchema.optional().nullable(),
4625
4625
  bio: import_zod14.z.string().max(1e3).optional(),
4626
4626
  languages: import_zod14.z.array(import_zod14.z.string()).min(1)
4627
4627
  });
@@ -4631,7 +4631,7 @@ var practitionerCertificationSchema = import_zod14.z.object({
4631
4631
  licenseNumber: import_zod14.z.string().min(3).max(50),
4632
4632
  issuingAuthority: import_zod14.z.string().min(2).max(100),
4633
4633
  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(),
4634
+ expiryDate: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date()).optional().nullable(),
4635
4635
  verificationStatus: import_zod14.z.enum(["pending", "verified", "rejected"])
4636
4636
  });
4637
4637
  var timeSlotSchema = import_zod14.z.object({
@@ -7735,23 +7735,139 @@ var ClinicService = class extends BaseService {
7735
7735
  }
7736
7736
  };
7737
7737
 
7738
+ // src/services/auth/utils/firebase.utils.ts
7739
+ var import_auth5 = require("firebase/auth");
7740
+ var checkEmailExists = async (auth, email) => {
7741
+ try {
7742
+ const methods = await (0, import_auth5.fetchSignInMethodsForEmail)(auth, email);
7743
+ return methods.length > 0;
7744
+ } catch (error) {
7745
+ console.warn(
7746
+ "[FIREBASE] Could not check email existence, allowing signup to proceed:",
7747
+ error
7748
+ );
7749
+ return false;
7750
+ }
7751
+ };
7752
+ var cleanupFirebaseUser = async (firebaseUser) => {
7753
+ try {
7754
+ console.log("[FIREBASE] Cleaning up Firebase user", {
7755
+ uid: firebaseUser.uid
7756
+ });
7757
+ await firebaseUser.delete();
7758
+ console.log("[FIREBASE] Firebase user cleanup successful");
7759
+ } catch (cleanupError) {
7760
+ console.error("[FIREBASE] Failed to cleanup Firebase user:", cleanupError);
7761
+ }
7762
+ };
7763
+
7764
+ // src/services/auth/utils/error.utils.ts
7765
+ var import_zod20 = require("zod");
7766
+ var handleFirebaseError = (error) => {
7767
+ const firebaseError = error;
7768
+ switch (firebaseError.code) {
7769
+ case "auth/email-already-in-use" /* EMAIL_ALREADY_IN_USE */:
7770
+ return AUTH_ERRORS.EMAIL_ALREADY_EXISTS;
7771
+ case "auth/weak-password":
7772
+ return new Error(
7773
+ "Password is too weak. Please choose a stronger password."
7774
+ );
7775
+ case "auth/invalid-email":
7776
+ return new Error("Please enter a valid email address.");
7777
+ case "auth/network-request-failed":
7778
+ return new Error(
7779
+ "Network error. Please check your internet connection and try again."
7780
+ );
7781
+ default:
7782
+ return new Error(
7783
+ `Account creation failed: ${firebaseError.message || "Unknown error"}`
7784
+ );
7785
+ }
7786
+ };
7787
+ var handleSignupError = (error) => {
7788
+ if (error instanceof import_zod20.z.ZodError) {
7789
+ const errorMessages = error.errors.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
7790
+ return new Error(`Validation failed: ${errorMessages}`);
7791
+ }
7792
+ if (error.code && error.code.startsWith("auth/")) {
7793
+ return handleFirebaseError(error);
7794
+ }
7795
+ if (error.message && error.message.includes("token")) {
7796
+ return new Error("Invalid or expired invitation token");
7797
+ }
7798
+ if (error.message && error.message.includes("validation")) {
7799
+ return new Error(`Invalid practitioner data: ${error.message}`);
7800
+ }
7801
+ return new Error(
7802
+ `Registration failed: ${error.message || "Unknown error occurred"}`
7803
+ );
7804
+ };
7805
+
7806
+ // src/services/auth/utils/practitioner.utils.ts
7807
+ var import_zod21 = require("zod");
7808
+ var profileDataSchema = import_zod21.z.object({
7809
+ basicInfo: practitionerBasicInfoSchema.partial().optional(),
7810
+ certification: practitionerCertificationSchema.partial().optional()
7811
+ }).partial();
7812
+ var buildPractitionerData = (data, userRef) => {
7813
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
7814
+ const basicInfo = {
7815
+ firstName: data.firstName || "Name",
7816
+ lastName: data.lastName || "Surname",
7817
+ email: data.email,
7818
+ phoneNumber: ((_b = (_a = data.profileData) == null ? void 0 : _a.basicInfo) == null ? void 0 : _b.phoneNumber) || null,
7819
+ profileImageUrl: ((_d = (_c = data.profileData) == null ? void 0 : _c.basicInfo) == null ? void 0 : _d.profileImageUrl) || "",
7820
+ gender: ((_f = (_e = data.profileData) == null ? void 0 : _e.basicInfo) == null ? void 0 : _f.gender) || "other",
7821
+ bio: ((_h = (_g = data.profileData) == null ? void 0 : _g.basicInfo) == null ? void 0 : _h.bio) || "",
7822
+ title: "Practitioner",
7823
+ dateOfBirth: ((_j = (_i = data.profileData) == null ? void 0 : _i.basicInfo) == null ? void 0 : _j.dateOfBirth) || /* @__PURE__ */ new Date(),
7824
+ languages: ((_l = (_k = data.profileData) == null ? void 0 : _k.basicInfo) == null ? void 0 : _l.languages) || ["English"]
7825
+ };
7826
+ const certification = ((_m = data.profileData) == null ? void 0 : _m.certification) || {
7827
+ level: "aesthetician" /* AESTHETICIAN */,
7828
+ specialties: [],
7829
+ licenseNumber: "Pending",
7830
+ issuingAuthority: "Pending",
7831
+ issueDate: /* @__PURE__ */ new Date(),
7832
+ verificationStatus: "pending"
7833
+ };
7834
+ return {
7835
+ userRef,
7836
+ basicInfo,
7837
+ certification,
7838
+ status: "active" /* ACTIVE */,
7839
+ isActive: true,
7840
+ isVerified: false
7841
+ };
7842
+ };
7843
+ var validatePractitionerProfileData = async (profileData) => {
7844
+ try {
7845
+ await profileDataSchema.parseAsync(profileData);
7846
+ } catch (error) {
7847
+ if (error instanceof import_zod21.z.ZodError) {
7848
+ const errorMessages = error.errors.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
7849
+ throw new Error(
7850
+ `Practitioner profile validation failed: ${errorMessages}`
7851
+ );
7852
+ }
7853
+ throw error;
7854
+ }
7855
+ };
7856
+
7738
7857
  // src/services/auth.service.ts
7739
7858
  var AuthService = class extends BaseService {
7740
7859
  constructor(db, auth, app, userService) {
7741
7860
  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;
7861
+ this.googleProvider = new import_auth7.GoogleAuthProvider();
7862
+ this.facebookProvider = new import_auth7.FacebookAuthProvider();
7863
+ this.appleProvider = new import_auth7.OAuthProvider("apple.com");
7864
+ this.userService = userService || new UserService(db, auth, app);
7749
7865
  }
7750
7866
  /**
7751
7867
  * Registruje novog korisnika sa email-om i lozinkom
7752
7868
  */
7753
7869
  async signUp(email, password, initialRole = "patient" /* PATIENT */) {
7754
- const { user: firebaseUser } = await (0, import_auth5.createUserWithEmailAndPassword)(
7870
+ const { user: firebaseUser } = await (0, import_auth7.createUserWithEmailAndPassword)(
7755
7871
  this.auth,
7756
7872
  email,
7757
7873
  password
@@ -7783,7 +7899,7 @@ var AuthService = class extends BaseService {
7783
7899
  console.log("[AUTH] Creating Firebase user");
7784
7900
  let firebaseUser;
7785
7901
  try {
7786
- const result = await (0, import_auth5.createUserWithEmailAndPassword)(
7902
+ const result = await (0, import_auth7.createUserWithEmailAndPassword)(
7787
7903
  this.auth,
7788
7904
  data.email,
7789
7905
  data.password
@@ -7794,7 +7910,7 @@ var AuthService = class extends BaseService {
7794
7910
  });
7795
7911
  } catch (firebaseError) {
7796
7912
  console.error("[AUTH] Firebase user creation failed:", firebaseError);
7797
- throw firebaseError;
7913
+ throw handleFirebaseError(firebaseError);
7798
7914
  }
7799
7915
  console.log("[AUTH] Creating user with CLINIC_ADMIN role");
7800
7916
  let user;
@@ -8048,7 +8164,7 @@ var AuthService = class extends BaseService {
8048
8164
  clinicAdmin: adminProfile
8049
8165
  };
8050
8166
  } catch (error) {
8051
- if (error instanceof import_zod20.z.ZodError) {
8167
+ if (error instanceof import_zod22.z.ZodError) {
8052
8168
  console.error(
8053
8169
  "[AUTH] Zod validation error in signUpClinicAdmin:",
8054
8170
  JSON.stringify(error.errors, null, 2)
@@ -8068,7 +8184,7 @@ var AuthService = class extends BaseService {
8068
8184
  * Prijavljuje korisnika sa email-om i lozinkom
8069
8185
  */
8070
8186
  async signIn(email, password) {
8071
- const { user: firebaseUser } = await (0, import_auth5.signInWithEmailAndPassword)(
8187
+ const { user: firebaseUser } = await (0, import_auth7.signInWithEmailAndPassword)(
8072
8188
  this.auth,
8073
8189
  email,
8074
8190
  password
@@ -8107,7 +8223,7 @@ var AuthService = class extends BaseService {
8107
8223
  mediaService
8108
8224
  );
8109
8225
  clinicAdminService.setServices(clinicGroupService, clinicService);
8110
- const { user: firebaseUser } = await (0, import_auth5.signInWithEmailAndPassword)(
8226
+ const { user: firebaseUser } = await (0, import_auth7.signInWithEmailAndPassword)(
8111
8227
  this.auth,
8112
8228
  email,
8113
8229
  password
@@ -8152,15 +8268,15 @@ var AuthService = class extends BaseService {
8152
8268
  * Prijavljuje korisnika sa Facebook-om
8153
8269
  */
8154
8270
  async signInWithFacebook() {
8155
- const provider = new import_auth5.FacebookAuthProvider();
8156
- const { user: firebaseUser } = await (0, import_auth5.signInWithPopup)(this.auth, provider);
8271
+ const provider = new import_auth7.FacebookAuthProvider();
8272
+ const { user: firebaseUser } = await (0, import_auth7.signInWithPopup)(this.auth, provider);
8157
8273
  return this.userService.getOrCreateUser(firebaseUser);
8158
8274
  }
8159
8275
  /**
8160
8276
  * Prijavljuje korisnika sa Google nalogom
8161
8277
  */
8162
8278
  async signInWithGoogle(initialRole = "patient" /* PATIENT */) {
8163
- const { user: firebaseUser } = await (0, import_auth5.signInWithPopup)(
8279
+ const { user: firebaseUser } = await (0, import_auth7.signInWithPopup)(
8164
8280
  this.auth,
8165
8281
  this.googleProvider
8166
8282
  );
@@ -8170,22 +8286,22 @@ var AuthService = class extends BaseService {
8170
8286
  * Prijavljuje korisnika sa Apple-om
8171
8287
  */
8172
8288
  async signInWithApple() {
8173
- const provider = new import_auth5.OAuthProvider("apple.com");
8174
- const { user: firebaseUser } = await (0, import_auth5.signInWithPopup)(this.auth, provider);
8289
+ const provider = new import_auth7.OAuthProvider("apple.com");
8290
+ const { user: firebaseUser } = await (0, import_auth7.signInWithPopup)(this.auth, provider);
8175
8291
  return this.userService.getOrCreateUser(firebaseUser);
8176
8292
  }
8177
8293
  /**
8178
8294
  * Prijavljuje korisnika anonimno
8179
8295
  */
8180
8296
  async signInAnonymously() {
8181
- const { user: firebaseUser } = await (0, import_auth5.signInAnonymously)(this.auth);
8297
+ const { user: firebaseUser } = await (0, import_auth7.signInAnonymously)(this.auth);
8182
8298
  return this.userService.getOrCreateUser(firebaseUser);
8183
8299
  }
8184
8300
  /**
8185
8301
  * Odjavljuje trenutnog korisnika
8186
8302
  */
8187
8303
  async signOut() {
8188
- await (0, import_auth5.signOut)(this.auth);
8304
+ await (0, import_auth7.signOut)(this.auth);
8189
8305
  }
8190
8306
  /**
8191
8307
  * Vraća trenutno prijavljenog korisnika
@@ -8199,7 +8315,7 @@ var AuthService = class extends BaseService {
8199
8315
  * Registruje callback za promene stanja autentifikacije
8200
8316
  */
8201
8317
  onAuthStateChange(callback) {
8202
- return (0, import_auth5.onAuthStateChanged)(this.auth, callback);
8318
+ return (0, import_auth7.onAuthStateChanged)(this.auth, callback);
8203
8319
  }
8204
8320
  async upgradeAnonymousUser(email, password) {
8205
8321
  try {
@@ -8216,14 +8332,14 @@ var AuthService = class extends BaseService {
8216
8332
  400
8217
8333
  );
8218
8334
  }
8219
- const credential = import_auth5.EmailAuthProvider.credential(email, password);
8220
- await (0, import_auth5.linkWithCredential)(currentUser, credential);
8335
+ const credential = import_auth7.EmailAuthProvider.credential(email, password);
8336
+ await (0, import_auth7.linkWithCredential)(currentUser, credential);
8221
8337
  return await this.userService.upgradeAnonymousUser(
8222
8338
  currentUser.uid,
8223
8339
  email
8224
8340
  );
8225
8341
  } catch (error) {
8226
- if (error instanceof import_zod20.z.ZodError) {
8342
+ if (error instanceof import_zod22.z.ZodError) {
8227
8343
  throw AUTH_ERRORS.VALIDATION_ERROR;
8228
8344
  }
8229
8345
  const firebaseError = error;
@@ -8256,7 +8372,7 @@ var AuthService = class extends BaseService {
8256
8372
  400
8257
8373
  );
8258
8374
  }
8259
- const userCredential = await (0, import_auth5.signInWithPopup)(
8375
+ const userCredential = await (0, import_auth7.signInWithPopup)(
8260
8376
  this.auth,
8261
8377
  this.googleProvider
8262
8378
  );
@@ -8287,7 +8403,7 @@ var AuthService = class extends BaseService {
8287
8403
  );
8288
8404
  }
8289
8405
  this.facebookProvider.addScope("email");
8290
- const userCredential = await (0, import_auth5.signInWithPopup)(
8406
+ const userCredential = await (0, import_auth7.signInWithPopup)(
8291
8407
  this.auth,
8292
8408
  this.facebookProvider
8293
8409
  );
@@ -8319,7 +8435,7 @@ var AuthService = class extends BaseService {
8319
8435
  }
8320
8436
  this.appleProvider.addScope("email");
8321
8437
  this.appleProvider.addScope("name");
8322
- const userCredential = await (0, import_auth5.signInWithPopup)(
8438
+ const userCredential = await (0, import_auth7.signInWithPopup)(
8323
8439
  this.auth,
8324
8440
  this.appleProvider
8325
8441
  );
@@ -8344,9 +8460,9 @@ var AuthService = class extends BaseService {
8344
8460
  async sendPasswordResetEmail(email) {
8345
8461
  try {
8346
8462
  await emailSchema.parseAsync(email);
8347
- await (0, import_auth5.sendPasswordResetEmail)(this.auth, email);
8463
+ await (0, import_auth7.sendPasswordResetEmail)(this.auth, email);
8348
8464
  } catch (error) {
8349
- if (error instanceof import_zod20.z.ZodError) {
8465
+ if (error instanceof import_zod22.z.ZodError) {
8350
8466
  throw AUTH_ERRORS.VALIDATION_ERROR;
8351
8467
  }
8352
8468
  const firebaseError = error;
@@ -8363,7 +8479,7 @@ var AuthService = class extends BaseService {
8363
8479
  */
8364
8480
  async verifyPasswordResetCode(oobCode) {
8365
8481
  try {
8366
- return await (0, import_auth5.verifyPasswordResetCode)(this.auth, oobCode);
8482
+ return await (0, import_auth7.verifyPasswordResetCode)(this.auth, oobCode);
8367
8483
  } catch (error) {
8368
8484
  const firebaseError = error;
8369
8485
  if (firebaseError.code === "auth/expired-action-code" /* EXPIRED_ACTION_CODE */) {
@@ -8383,9 +8499,9 @@ var AuthService = class extends BaseService {
8383
8499
  async confirmPasswordReset(oobCode, newPassword) {
8384
8500
  try {
8385
8501
  await passwordSchema.parseAsync(newPassword);
8386
- await (0, import_auth5.confirmPasswordReset)(this.auth, oobCode, newPassword);
8502
+ await (0, import_auth7.confirmPasswordReset)(this.auth, oobCode, newPassword);
8387
8503
  } catch (error) {
8388
- if (error instanceof import_zod20.z.ZodError) {
8504
+ if (error instanceof import_zod22.z.ZodError) {
8389
8505
  throw AUTH_ERRORS.VALIDATION_ERROR;
8390
8506
  }
8391
8507
  const firebaseError = error;
@@ -8400,33 +8516,23 @@ var AuthService = class extends BaseService {
8400
8516
  }
8401
8517
  }
8402
8518
  /**
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
8519
+ * Registers a new practitioner user with email and password (ATOMIC VERSION)
8520
+ * Uses Firestore transactions to ensure atomicity and proper rollback on failures
8405
8521
  *
8406
8522
  * @param data - Practitioner signup data containing either new profile details or token for claiming draft profile
8407
8523
  * @returns Object containing the created user and practitioner profile
8408
8524
  */
8409
8525
  async signUpPractitioner(data) {
8410
- var _a, _b, _c, _d;
8526
+ let firebaseUser = null;
8411
8527
  try {
8412
- console.log("[AUTH] Starting practitioner signup process", {
8528
+ console.log("[AUTH] Starting atomic practitioner signup process", {
8413
8529
  email: data.email,
8414
8530
  hasToken: !!data.token
8415
8531
  });
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
- }
8532
+ await this.validateSignupData(data);
8426
8533
  console.log("[AUTH] Creating Firebase user");
8427
- let firebaseUser;
8428
8534
  try {
8429
- const result = await (0, import_auth5.createUserWithEmailAndPassword)(
8535
+ const result = await (0, import_auth7.createUserWithEmailAndPassword)(
8430
8536
  this.auth,
8431
8537
  data.email,
8432
8538
  data.password
@@ -8437,136 +8543,110 @@ var AuthService = class extends BaseService {
8437
8543
  });
8438
8544
  } catch (firebaseError) {
8439
8545
  console.error("[AUTH] Firebase user creation failed:", firebaseError);
8440
- throw firebaseError;
8546
+ throw handleFirebaseError(firebaseError);
8441
8547
  }
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;
8459
- }
8460
- console.log("[AUTH] Initializing practitioner service");
8461
- const practitionerService = new PractitionerService(
8548
+ console.log("[AUTH] Starting Firestore transaction");
8549
+ const transactionResult = await (0, import_firestore25.runTransaction)(
8462
8550
  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
- });
8551
+ async (transaction) => {
8483
8552
  console.log(
8484
- "[AUTH] User updated with practitioner profile reference"
8553
+ "[AUTH] Transaction started - creating user and practitioner"
8485
8554
  );
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
8555
+ const practitionerService = new PractitionerService(
8556
+ this.db,
8557
+ this.auth,
8558
+ this.app
8530
8559
  );
8531
- console.log("[AUTH] Practitioner profile created successfully", {
8532
- practitionerId: practitioner.id
8533
- });
8560
+ console.log("[AUTH] Creating user document");
8561
+ const user = await this.userService.createUser(
8562
+ firebaseUser,
8563
+ ["practitioner" /* PRACTITIONER */],
8564
+ { skipProfileCreation: true }
8565
+ );
8566
+ let practitioner;
8567
+ if (data.token) {
8568
+ console.log(
8569
+ "[AUTH] Claiming existing practitioner profile with token"
8570
+ );
8571
+ const claimedPractitioner = await practitionerService.validateTokenAndClaimProfile(
8572
+ data.token,
8573
+ firebaseUser.uid
8574
+ );
8575
+ if (!claimedPractitioner) {
8576
+ throw new Error("Invalid or expired invitation token");
8577
+ }
8578
+ practitioner = claimedPractitioner;
8579
+ } else {
8580
+ console.log("[AUTH] Creating new practitioner profile");
8581
+ const practitionerData = buildPractitionerData(
8582
+ data,
8583
+ firebaseUser.uid
8584
+ );
8585
+ practitioner = await practitionerService.createPractitioner(
8586
+ practitionerData
8587
+ );
8588
+ }
8589
+ console.log("[AUTH] Linking practitioner to user");
8534
8590
  await this.userService.updateUser(firebaseUser.uid, {
8535
8591
  practitionerProfile: practitioner.id
8536
8592
  });
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;
8593
+ console.log("[AUTH] Transaction operations completed successfully");
8594
+ return { user, practitioner };
8546
8595
  }
8547
- }
8548
- console.log("[AUTH] Practitioner signup completed successfully", {
8549
- userId: user.uid,
8550
- practitionerId: (practitioner == null ? void 0 : practitioner.id) || "unknown"
8596
+ );
8597
+ console.log("[AUTH] Atomic practitioner signup completed successfully", {
8598
+ userId: transactionResult.user.uid,
8599
+ practitionerId: transactionResult.practitioner.id
8551
8600
  });
8552
- return {
8553
- user,
8554
- practitioner
8555
- };
8601
+ return transactionResult;
8556
8602
  } 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;
8603
+ console.error(
8604
+ "[AUTH] Atomic signup failed, initiating cleanup...",
8605
+ error
8606
+ );
8607
+ if (firebaseUser) {
8608
+ await cleanupFirebaseUser(firebaseUser);
8563
8609
  }
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);
8610
+ throw handleSignupError(error);
8611
+ }
8612
+ }
8613
+ /**
8614
+ * Pre-validate all signup data before any mutations
8615
+ * Prevents partial creation by catching issues early
8616
+ */
8617
+ async validateSignupData(data) {
8618
+ console.log("[AUTH] Pre-validating signup data");
8619
+ try {
8620
+ await practitionerSignupSchema.parseAsync(data);
8621
+ console.log("[AUTH] Schema validation passed");
8622
+ const emailExists = await checkEmailExists(this.auth, data.email);
8623
+ if (emailExists) {
8624
+ console.log("[AUTH] Email already exists:", data.email);
8567
8625
  throw AUTH_ERRORS.EMAIL_ALREADY_EXISTS;
8568
8626
  }
8569
- console.error("[AUTH] Unhandled error in signUpPractitioner:", error);
8627
+ console.log("[AUTH] Email availability confirmed");
8628
+ if (data.token) {
8629
+ const practitionerService = new PractitionerService(
8630
+ this.db,
8631
+ this.auth,
8632
+ this.app
8633
+ );
8634
+ const isValidToken = await practitionerService.validateToken(
8635
+ data.token
8636
+ );
8637
+ if (!isValidToken) {
8638
+ console.log("[AUTH] Invalid token provided:", data.token);
8639
+ throw new Error("Invalid or expired invitation token");
8640
+ }
8641
+ console.log("[AUTH] Token validation passed");
8642
+ }
8643
+ if (data.profileData) {
8644
+ await validatePractitionerProfileData(data.profileData);
8645
+ console.log("[AUTH] Profile data validation passed");
8646
+ }
8647
+ console.log("[AUTH] All pre-validation checks passed");
8648
+ } catch (error) {
8649
+ console.error("[AUTH] Pre-validation failed:", error);
8570
8650
  throw error;
8571
8651
  }
8572
8652
  }
@@ -8589,7 +8669,7 @@ var AuthService = class extends BaseService {
8589
8669
  this.auth,
8590
8670
  this.app
8591
8671
  );
8592
- const { user: firebaseUser } = await (0, import_auth5.signInWithEmailAndPassword)(
8672
+ const { user: firebaseUser } = await (0, import_auth7.signInWithEmailAndPassword)(
8593
8673
  this.auth,
8594
8674
  email,
8595
8675
  password
@@ -8832,63 +8912,63 @@ var import_firestore27 = require("firebase/firestore");
8832
8912
  var PROCEDURES_COLLECTION = "procedures";
8833
8913
 
8834
8914
  // 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),
8915
+ var import_zod23 = require("zod");
8916
+ var createProcedureSchema = import_zod23.z.object({
8917
+ name: import_zod23.z.string().min(1).max(200),
8918
+ description: import_zod23.z.string().min(1).max(2e3),
8919
+ family: import_zod23.z.nativeEnum(ProcedureFamily),
8920
+ categoryId: import_zod23.z.string().min(1),
8921
+ subcategoryId: import_zod23.z.string().min(1),
8922
+ technologyId: import_zod23.z.string().min(1),
8923
+ productId: import_zod23.z.string().min(1),
8924
+ price: import_zod23.z.number().min(0),
8925
+ currency: import_zod23.z.nativeEnum(Currency),
8926
+ pricingMeasure: import_zod23.z.nativeEnum(PricingMeasure),
8927
+ duration: import_zod23.z.number().min(1).max(480),
8848
8928
  // 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()
8929
+ practitionerId: import_zod23.z.string().min(1),
8930
+ clinicBranchId: import_zod23.z.string().min(1),
8931
+ photos: import_zod23.z.array(mediaResourceSchema).optional()
8932
+ });
8933
+ var updateProcedureSchema = import_zod23.z.object({
8934
+ name: import_zod23.z.string().min(3).max(100).optional(),
8935
+ description: import_zod23.z.string().min(3).max(1e3).optional(),
8936
+ price: import_zod23.z.number().min(0).optional(),
8937
+ currency: import_zod23.z.nativeEnum(Currency).optional(),
8938
+ pricingMeasure: import_zod23.z.nativeEnum(PricingMeasure).optional(),
8939
+ duration: import_zod23.z.number().min(0).optional(),
8940
+ isActive: import_zod23.z.boolean().optional(),
8941
+ practitionerId: import_zod23.z.string().optional(),
8942
+ categoryId: import_zod23.z.string().optional(),
8943
+ subcategoryId: import_zod23.z.string().optional(),
8944
+ technologyId: import_zod23.z.string().optional(),
8945
+ productId: import_zod23.z.string().optional(),
8946
+ clinicBranchId: import_zod23.z.string().optional(),
8947
+ photos: import_zod23.z.array(mediaResourceSchema).optional()
8868
8948
  });
8869
8949
  var procedureSchema = createProcedureSchema.extend({
8870
- id: import_zod21.z.string().min(1),
8871
- category: import_zod21.z.any(),
8950
+ id: import_zod23.z.string().min(1),
8951
+ category: import_zod23.z.any(),
8872
8952
  // We'll validate the full category object separately
8873
- subcategory: import_zod21.z.any(),
8953
+ subcategory: import_zod23.z.any(),
8874
8954
  // We'll validate the full subcategory object separately
8875
- technology: import_zod21.z.any(),
8955
+ technology: import_zod23.z.any(),
8876
8956
  // We'll validate the full technology object separately
8877
- product: import_zod21.z.any(),
8957
+ product: import_zod23.z.any(),
8878
8958
  // We'll validate the full product object separately
8879
- blockingConditions: import_zod21.z.array(import_zod21.z.any()),
8959
+ blockingConditions: import_zod23.z.array(import_zod23.z.any()),
8880
8960
  // We'll validate blocking conditions separately
8881
- contraindications: import_zod21.z.array(import_zod21.z.any()),
8961
+ contraindications: import_zod23.z.array(import_zod23.z.any()),
8882
8962
  // We'll validate contraindications separately
8883
- treatmentBenefits: import_zod21.z.array(import_zod21.z.any()),
8963
+ treatmentBenefits: import_zod23.z.array(import_zod23.z.any()),
8884
8964
  // We'll validate treatment benefits separately
8885
- preRequirements: import_zod21.z.array(import_zod21.z.any()),
8965
+ preRequirements: import_zod23.z.array(import_zod23.z.any()),
8886
8966
  // We'll validate requirements separately
8887
- postRequirements: import_zod21.z.array(import_zod21.z.any()),
8967
+ postRequirements: import_zod23.z.array(import_zod23.z.any()),
8888
8968
  // We'll validate requirements separately
8889
- certificationRequirement: import_zod21.z.any(),
8969
+ certificationRequirement: import_zod23.z.any(),
8890
8970
  // We'll validate certification requirement separately
8891
- documentationTemplates: import_zod21.z.array(import_zod21.z.any()),
8971
+ documentationTemplates: import_zod23.z.array(import_zod23.z.any()),
8892
8972
  // We'll validate documentation templates separately
8893
8973
  clinicInfo: clinicInfoSchema,
8894
8974
  // Clinic info validation
@@ -8896,9 +8976,9 @@ var procedureSchema = createProcedureSchema.extend({
8896
8976
  // Doctor info validation
8897
8977
  reviewInfo: procedureReviewInfoSchema,
8898
8978
  // Procedure review info validation
8899
- isActive: import_zod21.z.boolean(),
8900
- createdAt: import_zod21.z.date(),
8901
- updatedAt: import_zod21.z.date()
8979
+ isActive: import_zod23.z.boolean(),
8980
+ createdAt: import_zod23.z.date(),
8981
+ updatedAt: import_zod23.z.date()
8902
8982
  });
8903
8983
 
8904
8984
  // src/services/procedure/procedure.service.ts
@@ -9320,20 +9400,20 @@ var ProcedureService = class extends BaseService {
9320
9400
  const proceduresCollection = (0, import_firestore27.collection)(this.db, PROCEDURES_COLLECTION);
9321
9401
  let proceduresQuery = (0, import_firestore27.query)(proceduresCollection);
9322
9402
  if (pagination && pagination > 0) {
9323
- const { limit: limit15, startAfter: startAfter13 } = await import("firebase/firestore");
9403
+ const { limit: limit16, startAfter: startAfter14 } = await import("firebase/firestore");
9324
9404
  if (lastDoc) {
9325
9405
  proceduresQuery = (0, import_firestore27.query)(
9326
9406
  proceduresCollection,
9327
9407
  (0, import_firestore27.orderBy)("name"),
9328
9408
  // Use imported orderBy
9329
- startAfter13(lastDoc),
9330
- limit15(pagination)
9409
+ startAfter14(lastDoc),
9410
+ limit16(pagination)
9331
9411
  );
9332
9412
  } else {
9333
9413
  proceduresQuery = (0, import_firestore27.query)(
9334
9414
  proceduresCollection,
9335
9415
  (0, import_firestore27.orderBy)("name"),
9336
- limit15(pagination)
9416
+ limit16(pagination)
9337
9417
  );
9338
9418
  }
9339
9419
  } else {
@@ -10732,42 +10812,42 @@ var SYNCED_CALENDARS_COLLECTION = "syncedCalendars";
10732
10812
  var import_firestore41 = require("firebase/firestore");
10733
10813
 
10734
10814
  // src/validations/calendar.schema.ts
10735
- var import_zod23 = require("zod");
10815
+ var import_zod25 = require("zod");
10736
10816
  var import_firestore32 = require("firebase/firestore");
10737
10817
 
10738
10818
  // src/validations/profile-info.schema.ts
10739
- var import_zod22 = require("zod");
10819
+ var import_zod24 = require("zod");
10740
10820
  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(),
10821
+ var clinicInfoSchema2 = import_zod24.z.object({
10822
+ id: import_zod24.z.string(),
10823
+ featuredPhoto: import_zod24.z.string(),
10824
+ name: import_zod24.z.string(),
10825
+ description: import_zod24.z.string(),
10746
10826
  location: clinicLocationSchema,
10747
10827
  contactInfo: clinicContactInfoSchema
10748
10828
  });
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(),
10829
+ var practitionerProfileInfoSchema = import_zod24.z.object({
10830
+ id: import_zod24.z.string(),
10831
+ practitionerPhoto: import_zod24.z.string().nullable(),
10832
+ name: import_zod24.z.string(),
10833
+ email: import_zod24.z.string().email(),
10834
+ phone: import_zod24.z.string().nullable(),
10755
10835
  certification: practitionerCertificationSchema
10756
10836
  });
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)
10837
+ var patientProfileInfoSchema = import_zod24.z.object({
10838
+ id: import_zod24.z.string(),
10839
+ fullName: import_zod24.z.string(),
10840
+ email: import_zod24.z.string().email(),
10841
+ phone: import_zod24.z.string().nullable(),
10842
+ dateOfBirth: import_zod24.z.instanceof(import_firestore31.Timestamp),
10843
+ gender: import_zod24.z.nativeEnum(Gender)
10764
10844
  });
10765
10845
 
10766
10846
  // src/validations/calendar.schema.ts
10767
10847
  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))
10848
+ var calendarEventTimeSchema = import_zod25.z.object({
10849
+ start: import_zod25.z.instanceof(Date).or(import_zod25.z.instanceof(import_firestore32.Timestamp)),
10850
+ end: import_zod25.z.instanceof(Date).or(import_zod25.z.instanceof(import_firestore32.Timestamp))
10771
10851
  }).refine(
10772
10852
  (data) => {
10773
10853
  const startDate = data.start instanceof import_firestore32.Timestamp ? data.start.toDate() : data.start;
@@ -10788,46 +10868,46 @@ var calendarEventTimeSchema = import_zod23.z.object({
10788
10868
  path: ["start"]
10789
10869
  }
10790
10870
  );
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()
10871
+ var timeSlotSchema2 = import_zod25.z.object({
10872
+ start: import_zod25.z.date(),
10873
+ end: import_zod25.z.date(),
10874
+ isAvailable: import_zod25.z.boolean()
10795
10875
  }).refine((data) => data.start < data.end, {
10796
10876
  message: "End time must be after start time",
10797
10877
  path: ["end"]
10798
10878
  });
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))
10879
+ var syncedCalendarEventSchema = import_zod25.z.object({
10880
+ eventId: import_zod25.z.string(),
10881
+ syncedCalendarProvider: import_zod25.z.nativeEnum(SyncedCalendarProvider),
10882
+ syncedAt: import_zod25.z.instanceof(Date).or(import_zod25.z.instanceof(import_firestore32.Timestamp))
10803
10883
  });
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)
10884
+ var procedureInfoSchema = import_zod25.z.object({
10885
+ name: import_zod25.z.string(),
10886
+ description: import_zod25.z.string(),
10887
+ duration: import_zod25.z.number().min(MIN_APPOINTMENT_DURATION),
10888
+ price: import_zod25.z.number().min(0),
10889
+ currency: import_zod25.z.nativeEnum(Currency)
10810
10890
  });
10811
- var procedureCategorizationSchema = import_zod23.z.object({
10812
- procedureFamily: import_zod23.z.string(),
10891
+ var procedureCategorizationSchema = import_zod25.z.object({
10892
+ procedureFamily: import_zod25.z.string(),
10813
10893
  // Replace with proper enum when available
10814
- procedureCategory: import_zod23.z.string(),
10894
+ procedureCategory: import_zod25.z.string(),
10815
10895
  // Replace with proper enum when available
10816
- procedureSubcategory: import_zod23.z.string(),
10896
+ procedureSubcategory: import_zod25.z.string(),
10817
10897
  // Replace with proper enum when available
10818
- procedureTechnology: import_zod23.z.string(),
10898
+ procedureTechnology: import_zod25.z.string(),
10819
10899
  // Replace with proper enum when available
10820
- procedureProduct: import_zod23.z.string()
10900
+ procedureProduct: import_zod25.z.string()
10821
10901
  // Replace with proper enum when available
10822
10902
  });
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"),
10903
+ var createAppointmentSchema2 = import_zod25.z.object({
10904
+ clinicId: import_zod25.z.string().min(1, "Clinic ID is required"),
10905
+ doctorId: import_zod25.z.string().min(1, "Doctor ID is required"),
10906
+ patientId: import_zod25.z.string().min(1, "Patient ID is required"),
10907
+ procedureId: import_zod25.z.string().min(1, "Procedure ID is required"),
10828
10908
  eventLocation: clinicLocationSchema,
10829
10909
  eventTime: calendarEventTimeSchema,
10830
- description: import_zod23.z.string().optional()
10910
+ description: import_zod25.z.string().optional()
10831
10911
  }).refine(
10832
10912
  (data) => {
10833
10913
  return true;
@@ -10836,95 +10916,95 @@ var createAppointmentSchema2 = import_zod23.z.object({
10836
10916
  message: "Invalid appointment parameters"
10837
10917
  }
10838
10918
  );
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"),
10919
+ var updateAppointmentSchema2 = import_zod25.z.object({
10920
+ appointmentId: import_zod25.z.string().min(1, "Appointment ID is required"),
10921
+ clinicId: import_zod25.z.string().min(1, "Clinic ID is required"),
10922
+ doctorId: import_zod25.z.string().min(1, "Doctor ID is required"),
10923
+ patientId: import_zod25.z.string().min(1, "Patient ID is required"),
10844
10924
  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(),
10925
+ description: import_zod25.z.string().optional(),
10926
+ status: import_zod25.z.nativeEnum(CalendarEventStatus).optional()
10927
+ });
10928
+ var createCalendarEventSchema = import_zod25.z.object({
10929
+ id: import_zod25.z.string(),
10930
+ clinicBranchId: import_zod25.z.string().nullable().optional(),
10931
+ clinicBranchInfo: import_zod25.z.any().nullable().optional(),
10932
+ practitionerProfileId: import_zod25.z.string().nullable().optional(),
10853
10933
  practitionerProfileInfo: practitionerProfileInfoSchema.nullable().optional(),
10854
- patientProfileId: import_zod23.z.string().nullable().optional(),
10934
+ patientProfileId: import_zod25.z.string().nullable().optional(),
10855
10935
  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"),
10936
+ procedureId: import_zod25.z.string().nullable().optional(),
10937
+ appointmentId: import_zod25.z.string().nullable().optional(),
10938
+ syncedCalendarEventId: import_zod25.z.array(syncedCalendarEventSchema).nullable().optional(),
10939
+ eventName: import_zod25.z.string().min(1, "Event name is required"),
10860
10940
  eventLocation: clinicLocationSchema.optional(),
10861
10941
  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(),
10942
+ description: import_zod25.z.string().optional(),
10943
+ status: import_zod25.z.nativeEnum(CalendarEventStatus),
10944
+ syncStatus: import_zod25.z.nativeEnum(CalendarSyncStatus),
10945
+ eventType: import_zod25.z.nativeEnum(CalendarEventType),
10946
+ createdAt: import_zod25.z.any(),
10867
10947
  // FieldValue for server timestamp
10868
- updatedAt: import_zod23.z.any()
10948
+ updatedAt: import_zod25.z.any()
10869
10949
  // FieldValue for server timestamp
10870
10950
  });
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(),
10951
+ var updateCalendarEventSchema = import_zod25.z.object({
10952
+ syncedCalendarEventId: import_zod25.z.array(syncedCalendarEventSchema).nullable().optional(),
10953
+ appointmentId: import_zod25.z.string().nullable().optional(),
10954
+ eventName: import_zod25.z.string().optional(),
10875
10955
  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()
10956
+ description: import_zod25.z.string().optional(),
10957
+ status: import_zod25.z.nativeEnum(CalendarEventStatus).optional(),
10958
+ syncStatus: import_zod25.z.nativeEnum(CalendarSyncStatus).optional(),
10959
+ eventType: import_zod25.z.nativeEnum(CalendarEventType).optional(),
10960
+ updatedAt: import_zod25.z.any()
10881
10961
  // FieldValue for server timestamp
10882
10962
  });
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(),
10963
+ var calendarEventSchema = import_zod25.z.object({
10964
+ id: import_zod25.z.string(),
10965
+ clinicBranchId: import_zod25.z.string().nullable().optional(),
10966
+ clinicBranchInfo: import_zod25.z.any().nullable().optional(),
10887
10967
  // Will be replaced with proper clinic info schema
10888
- practitionerProfileId: import_zod23.z.string().nullable().optional(),
10968
+ practitionerProfileId: import_zod25.z.string().nullable().optional(),
10889
10969
  practitionerProfileInfo: practitionerProfileInfoSchema.nullable().optional(),
10890
- patientProfileId: import_zod23.z.string().nullable().optional(),
10970
+ patientProfileId: import_zod25.z.string().nullable().optional(),
10891
10971
  patientProfileInfo: patientProfileInfoSchema.nullable().optional(),
10892
- procedureId: import_zod23.z.string().nullable().optional(),
10972
+ procedureId: import_zod25.z.string().nullable().optional(),
10893
10973
  procedureInfo: procedureInfoSchema.nullable().optional(),
10894
10974
  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(),
10975
+ appointmentId: import_zod25.z.string().nullable().optional(),
10976
+ syncedCalendarEventId: import_zod25.z.array(syncedCalendarEventSchema).nullable().optional(),
10977
+ eventName: import_zod25.z.string(),
10898
10978
  eventLocation: clinicLocationSchema.optional(),
10899
10979
  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"),
10980
+ description: import_zod25.z.string().optional(),
10981
+ status: import_zod25.z.nativeEnum(CalendarEventStatus),
10982
+ syncStatus: import_zod25.z.nativeEnum(CalendarSyncStatus),
10983
+ eventType: import_zod25.z.nativeEnum(CalendarEventType),
10984
+ createdAt: import_zod25.z.instanceof(Date).or(import_zod25.z.instanceof(import_firestore32.Timestamp)),
10985
+ updatedAt: import_zod25.z.instanceof(Date).or(import_zod25.z.instanceof(import_firestore32.Timestamp))
10986
+ });
10987
+ var createBlockingEventSchema = import_zod25.z.object({
10988
+ entityType: import_zod25.z.enum(["practitioner", "clinic"]),
10989
+ entityId: import_zod25.z.string().min(1, "Entity ID is required"),
10990
+ eventName: import_zod25.z.string().min(1, "Event name is required").max(200, "Event name too long"),
10911
10991
  eventTime: calendarEventTimeSchema,
10912
- eventType: import_zod23.z.enum([
10992
+ eventType: import_zod25.z.enum([
10913
10993
  "blocking" /* BLOCKING */,
10914
10994
  "break" /* BREAK */,
10915
10995
  "free_day" /* FREE_DAY */,
10916
10996
  "other" /* OTHER */
10917
10997
  ]),
10918
- description: import_zod23.z.string().max(1e3, "Description too long").optional()
10998
+ description: import_zod25.z.string().max(1e3, "Description too long").optional()
10919
10999
  });
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(),
11000
+ var updateBlockingEventSchema = import_zod25.z.object({
11001
+ entityType: import_zod25.z.enum(["practitioner", "clinic"]),
11002
+ entityId: import_zod25.z.string().min(1, "Entity ID is required"),
11003
+ eventId: import_zod25.z.string().min(1, "Event ID is required"),
11004
+ eventName: import_zod25.z.string().min(1, "Event name is required").max(200, "Event name too long").optional(),
10925
11005
  eventTime: calendarEventTimeSchema.optional(),
10926
- description: import_zod23.z.string().max(1e3, "Description too long").optional(),
10927
- status: import_zod23.z.nativeEnum(CalendarEventStatus).optional()
11006
+ description: import_zod25.z.string().max(1e3, "Description too long").optional(),
11007
+ status: import_zod25.z.nativeEnum(CalendarEventStatus).optional()
10928
11008
  });
10929
11009
 
10930
11010
  // src/services/calendar/utils/clinic.utils.ts
@@ -13661,7 +13741,7 @@ var import_firestore44 = require("firebase/firestore");
13661
13741
  var REVIEWS_COLLECTION = "reviews";
13662
13742
 
13663
13743
  // src/services/reviews/reviews.service.ts
13664
- var import_zod24 = require("zod");
13744
+ var import_zod26 = require("zod");
13665
13745
  var ReviewService = class extends BaseService {
13666
13746
  constructor(db, auth, app) {
13667
13747
  super(db, auth, app);
@@ -13748,7 +13828,7 @@ var ReviewService = class extends BaseService {
13748
13828
  });
13749
13829
  return review;
13750
13830
  } catch (error) {
13751
- if (error instanceof import_zod24.z.ZodError) {
13831
+ if (error instanceof import_zod26.z.ZodError) {
13752
13832
  throw new Error(`Invalid review data: ${error.message}`);
13753
13833
  }
13754
13834
  throw error;
@@ -15949,63 +16029,63 @@ var ProductService = class extends BaseService {
15949
16029
  };
15950
16030
 
15951
16031
  // 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(),
16032
+ var import_zod27 = require("zod");
16033
+ var baseNotificationSchema = import_zod27.z.object({
16034
+ id: import_zod27.z.string().optional(),
16035
+ userId: import_zod27.z.string(),
16036
+ notificationTime: import_zod27.z.any(),
15957
16037
  // 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(),
16038
+ notificationType: import_zod27.z.nativeEnum(NotificationType),
16039
+ notificationTokens: import_zod27.z.array(import_zod27.z.string()),
16040
+ status: import_zod27.z.nativeEnum(NotificationStatus),
16041
+ createdAt: import_zod27.z.any().optional(),
15962
16042
  // Timestamp
15963
- updatedAt: import_zod25.z.any().optional(),
16043
+ updatedAt: import_zod27.z.any().optional(),
15964
16044
  // 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)
16045
+ title: import_zod27.z.string(),
16046
+ body: import_zod27.z.string(),
16047
+ isRead: import_zod27.z.boolean(),
16048
+ userRole: import_zod27.z.nativeEnum(UserRole)
15969
16049
  });
15970
16050
  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()
16051
+ notificationType: import_zod27.z.literal("preRequirementInstructionDue" /* PRE_REQUIREMENT_INSTRUCTION_DUE */),
16052
+ treatmentId: import_zod27.z.string(),
16053
+ requirements: import_zod27.z.array(import_zod27.z.string()),
16054
+ deadline: import_zod27.z.any()
15975
16055
  // Timestamp
15976
16056
  });
15977
16057
  var postRequirementNotificationSchema = baseNotificationSchema.extend({
15978
- notificationType: import_zod25.z.literal(
16058
+ notificationType: import_zod27.z.literal(
15979
16059
  "postRequirementInstructionDue" /* POST_REQUIREMENT_INSTRUCTION_DUE */
15980
16060
  ),
15981
- treatmentId: import_zod25.z.string(),
15982
- requirements: import_zod25.z.array(import_zod25.z.string()),
15983
- deadline: import_zod25.z.any()
16061
+ treatmentId: import_zod27.z.string(),
16062
+ requirements: import_zod27.z.array(import_zod27.z.string()),
16063
+ deadline: import_zod27.z.any()
15984
16064
  // Timestamp
15985
16065
  });
15986
16066
  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()
16067
+ notificationType: import_zod27.z.literal("requirementInstructionDue" /* REQUIREMENT_INSTRUCTION_DUE */),
16068
+ appointmentId: import_zod27.z.string(),
16069
+ patientRequirementInstanceId: import_zod27.z.string(),
16070
+ instructionId: import_zod27.z.string(),
16071
+ originalRequirementId: import_zod27.z.string().optional()
15992
16072
  });
15993
16073
  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(),
16074
+ notificationType: import_zod27.z.literal("appointmentReminder" /* APPOINTMENT_REMINDER */),
16075
+ appointmentId: import_zod27.z.string(),
16076
+ appointmentTime: import_zod27.z.any(),
15997
16077
  // Timestamp
15998
- treatmentType: import_zod25.z.string(),
15999
- doctorName: import_zod25.z.string()
16078
+ treatmentType: import_zod27.z.string(),
16079
+ doctorName: import_zod27.z.string()
16000
16080
  });
16001
16081
  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()
16082
+ notificationType: import_zod27.z.literal("appointmentStatusChange" /* APPOINTMENT_STATUS_CHANGE */),
16083
+ appointmentId: import_zod27.z.string(),
16084
+ appointmentStatus: import_zod27.z.string(),
16085
+ previousStatus: import_zod27.z.string(),
16086
+ reason: import_zod27.z.string().optional()
16007
16087
  });
16008
- var notificationSchema = import_zod25.z.discriminatedUnion("notificationType", [
16088
+ var notificationSchema = import_zod27.z.discriminatedUnion("notificationType", [
16009
16089
  preRequirementNotificationSchema,
16010
16090
  postRequirementNotificationSchema,
16011
16091
  requirementInstructionDueNotificationSchema,