@blackcode_sa/metaestetics-api 1.7.40 → 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");
@@ -1832,6 +1832,7 @@ var createPatientLocationInfoSchema = import_zod7.z.object({
1832
1832
  var patientSensitiveInfoSchema = import_zod7.z.object({
1833
1833
  patientId: import_zod7.z.string(),
1834
1834
  userRef: import_zod7.z.string(),
1835
+ photoUrl: import_zod7.z.string().nullable().optional(),
1835
1836
  firstName: import_zod7.z.string().min(2),
1836
1837
  lastName: import_zod7.z.string().min(2),
1837
1838
  dateOfBirth: import_zod7.z.instanceof(import_firestore5.Timestamp).nullable(),
@@ -4617,10 +4618,10 @@ var practitionerBasicInfoSchema = import_zod14.z.object({
4617
4618
  lastName: import_zod14.z.string().min(2).max(50),
4618
4619
  title: import_zod14.z.string().min(2).max(100),
4619
4620
  email: import_zod14.z.string().email(),
4620
- phoneNumber: import_zod14.z.string().regex(/^\+?[1-9]\d{1,14}$/, "Invalid phone number"),
4621
- 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(),
4622
4623
  gender: import_zod14.z.enum(["male", "female", "other"]),
4623
- profileImageUrl: mediaResourceSchema.optional(),
4624
+ profileImageUrl: mediaResourceSchema.optional().nullable(),
4624
4625
  bio: import_zod14.z.string().max(1e3).optional(),
4625
4626
  languages: import_zod14.z.array(import_zod14.z.string()).min(1)
4626
4627
  });
@@ -4630,7 +4631,7 @@ var practitionerCertificationSchema = import_zod14.z.object({
4630
4631
  licenseNumber: import_zod14.z.string().min(3).max(50),
4631
4632
  issuingAuthority: import_zod14.z.string().min(2).max(100),
4632
4633
  issueDate: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date()),
4633
- 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(),
4634
4635
  verificationStatus: import_zod14.z.enum(["pending", "verified", "rejected"])
4635
4636
  });
4636
4637
  var timeSlotSchema = import_zod14.z.object({
@@ -7734,23 +7735,139 @@ var ClinicService = class extends BaseService {
7734
7735
  }
7735
7736
  };
7736
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
+
7737
7857
  // src/services/auth.service.ts
7738
7858
  var AuthService = class extends BaseService {
7739
7859
  constructor(db, auth, app, userService) {
7740
7860
  super(db, auth, app);
7741
- this.googleProvider = new import_auth5.GoogleAuthProvider();
7742
- this.facebookProvider = new import_auth5.FacebookAuthProvider();
7743
- this.appleProvider = new import_auth5.OAuthProvider("apple.com");
7744
- if (!userService) {
7745
- userService = new UserService(db, auth, app);
7746
- }
7747
- 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);
7748
7865
  }
7749
7866
  /**
7750
7867
  * Registruje novog korisnika sa email-om i lozinkom
7751
7868
  */
7752
7869
  async signUp(email, password, initialRole = "patient" /* PATIENT */) {
7753
- const { user: firebaseUser } = await (0, import_auth5.createUserWithEmailAndPassword)(
7870
+ const { user: firebaseUser } = await (0, import_auth7.createUserWithEmailAndPassword)(
7754
7871
  this.auth,
7755
7872
  email,
7756
7873
  password
@@ -7782,7 +7899,7 @@ var AuthService = class extends BaseService {
7782
7899
  console.log("[AUTH] Creating Firebase user");
7783
7900
  let firebaseUser;
7784
7901
  try {
7785
- const result = await (0, import_auth5.createUserWithEmailAndPassword)(
7902
+ const result = await (0, import_auth7.createUserWithEmailAndPassword)(
7786
7903
  this.auth,
7787
7904
  data.email,
7788
7905
  data.password
@@ -7793,7 +7910,7 @@ var AuthService = class extends BaseService {
7793
7910
  });
7794
7911
  } catch (firebaseError) {
7795
7912
  console.error("[AUTH] Firebase user creation failed:", firebaseError);
7796
- throw firebaseError;
7913
+ throw handleFirebaseError(firebaseError);
7797
7914
  }
7798
7915
  console.log("[AUTH] Creating user with CLINIC_ADMIN role");
7799
7916
  let user;
@@ -8047,7 +8164,7 @@ var AuthService = class extends BaseService {
8047
8164
  clinicAdmin: adminProfile
8048
8165
  };
8049
8166
  } catch (error) {
8050
- if (error instanceof import_zod20.z.ZodError) {
8167
+ if (error instanceof import_zod22.z.ZodError) {
8051
8168
  console.error(
8052
8169
  "[AUTH] Zod validation error in signUpClinicAdmin:",
8053
8170
  JSON.stringify(error.errors, null, 2)
@@ -8067,7 +8184,7 @@ var AuthService = class extends BaseService {
8067
8184
  * Prijavljuje korisnika sa email-om i lozinkom
8068
8185
  */
8069
8186
  async signIn(email, password) {
8070
- const { user: firebaseUser } = await (0, import_auth5.signInWithEmailAndPassword)(
8187
+ const { user: firebaseUser } = await (0, import_auth7.signInWithEmailAndPassword)(
8071
8188
  this.auth,
8072
8189
  email,
8073
8190
  password
@@ -8106,7 +8223,7 @@ var AuthService = class extends BaseService {
8106
8223
  mediaService
8107
8224
  );
8108
8225
  clinicAdminService.setServices(clinicGroupService, clinicService);
8109
- const { user: firebaseUser } = await (0, import_auth5.signInWithEmailAndPassword)(
8226
+ const { user: firebaseUser } = await (0, import_auth7.signInWithEmailAndPassword)(
8110
8227
  this.auth,
8111
8228
  email,
8112
8229
  password
@@ -8151,15 +8268,15 @@ var AuthService = class extends BaseService {
8151
8268
  * Prijavljuje korisnika sa Facebook-om
8152
8269
  */
8153
8270
  async signInWithFacebook() {
8154
- const provider = new import_auth5.FacebookAuthProvider();
8155
- 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);
8156
8273
  return this.userService.getOrCreateUser(firebaseUser);
8157
8274
  }
8158
8275
  /**
8159
8276
  * Prijavljuje korisnika sa Google nalogom
8160
8277
  */
8161
8278
  async signInWithGoogle(initialRole = "patient" /* PATIENT */) {
8162
- const { user: firebaseUser } = await (0, import_auth5.signInWithPopup)(
8279
+ const { user: firebaseUser } = await (0, import_auth7.signInWithPopup)(
8163
8280
  this.auth,
8164
8281
  this.googleProvider
8165
8282
  );
@@ -8169,22 +8286,22 @@ var AuthService = class extends BaseService {
8169
8286
  * Prijavljuje korisnika sa Apple-om
8170
8287
  */
8171
8288
  async signInWithApple() {
8172
- const provider = new import_auth5.OAuthProvider("apple.com");
8173
- 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);
8174
8291
  return this.userService.getOrCreateUser(firebaseUser);
8175
8292
  }
8176
8293
  /**
8177
8294
  * Prijavljuje korisnika anonimno
8178
8295
  */
8179
8296
  async signInAnonymously() {
8180
- const { user: firebaseUser } = await (0, import_auth5.signInAnonymously)(this.auth);
8297
+ const { user: firebaseUser } = await (0, import_auth7.signInAnonymously)(this.auth);
8181
8298
  return this.userService.getOrCreateUser(firebaseUser);
8182
8299
  }
8183
8300
  /**
8184
8301
  * Odjavljuje trenutnog korisnika
8185
8302
  */
8186
8303
  async signOut() {
8187
- await (0, import_auth5.signOut)(this.auth);
8304
+ await (0, import_auth7.signOut)(this.auth);
8188
8305
  }
8189
8306
  /**
8190
8307
  * Vraća trenutno prijavljenog korisnika
@@ -8198,7 +8315,7 @@ var AuthService = class extends BaseService {
8198
8315
  * Registruje callback za promene stanja autentifikacije
8199
8316
  */
8200
8317
  onAuthStateChange(callback) {
8201
- return (0, import_auth5.onAuthStateChanged)(this.auth, callback);
8318
+ return (0, import_auth7.onAuthStateChanged)(this.auth, callback);
8202
8319
  }
8203
8320
  async upgradeAnonymousUser(email, password) {
8204
8321
  try {
@@ -8215,14 +8332,14 @@ var AuthService = class extends BaseService {
8215
8332
  400
8216
8333
  );
8217
8334
  }
8218
- const credential = import_auth5.EmailAuthProvider.credential(email, password);
8219
- await (0, import_auth5.linkWithCredential)(currentUser, credential);
8335
+ const credential = import_auth7.EmailAuthProvider.credential(email, password);
8336
+ await (0, import_auth7.linkWithCredential)(currentUser, credential);
8220
8337
  return await this.userService.upgradeAnonymousUser(
8221
8338
  currentUser.uid,
8222
8339
  email
8223
8340
  );
8224
8341
  } catch (error) {
8225
- if (error instanceof import_zod20.z.ZodError) {
8342
+ if (error instanceof import_zod22.z.ZodError) {
8226
8343
  throw AUTH_ERRORS.VALIDATION_ERROR;
8227
8344
  }
8228
8345
  const firebaseError = error;
@@ -8255,7 +8372,7 @@ var AuthService = class extends BaseService {
8255
8372
  400
8256
8373
  );
8257
8374
  }
8258
- const userCredential = await (0, import_auth5.signInWithPopup)(
8375
+ const userCredential = await (0, import_auth7.signInWithPopup)(
8259
8376
  this.auth,
8260
8377
  this.googleProvider
8261
8378
  );
@@ -8286,7 +8403,7 @@ var AuthService = class extends BaseService {
8286
8403
  );
8287
8404
  }
8288
8405
  this.facebookProvider.addScope("email");
8289
- const userCredential = await (0, import_auth5.signInWithPopup)(
8406
+ const userCredential = await (0, import_auth7.signInWithPopup)(
8290
8407
  this.auth,
8291
8408
  this.facebookProvider
8292
8409
  );
@@ -8318,7 +8435,7 @@ var AuthService = class extends BaseService {
8318
8435
  }
8319
8436
  this.appleProvider.addScope("email");
8320
8437
  this.appleProvider.addScope("name");
8321
- const userCredential = await (0, import_auth5.signInWithPopup)(
8438
+ const userCredential = await (0, import_auth7.signInWithPopup)(
8322
8439
  this.auth,
8323
8440
  this.appleProvider
8324
8441
  );
@@ -8343,9 +8460,9 @@ var AuthService = class extends BaseService {
8343
8460
  async sendPasswordResetEmail(email) {
8344
8461
  try {
8345
8462
  await emailSchema.parseAsync(email);
8346
- await (0, import_auth5.sendPasswordResetEmail)(this.auth, email);
8463
+ await (0, import_auth7.sendPasswordResetEmail)(this.auth, email);
8347
8464
  } catch (error) {
8348
- if (error instanceof import_zod20.z.ZodError) {
8465
+ if (error instanceof import_zod22.z.ZodError) {
8349
8466
  throw AUTH_ERRORS.VALIDATION_ERROR;
8350
8467
  }
8351
8468
  const firebaseError = error;
@@ -8362,7 +8479,7 @@ var AuthService = class extends BaseService {
8362
8479
  */
8363
8480
  async verifyPasswordResetCode(oobCode) {
8364
8481
  try {
8365
- return await (0, import_auth5.verifyPasswordResetCode)(this.auth, oobCode);
8482
+ return await (0, import_auth7.verifyPasswordResetCode)(this.auth, oobCode);
8366
8483
  } catch (error) {
8367
8484
  const firebaseError = error;
8368
8485
  if (firebaseError.code === "auth/expired-action-code" /* EXPIRED_ACTION_CODE */) {
@@ -8382,9 +8499,9 @@ var AuthService = class extends BaseService {
8382
8499
  async confirmPasswordReset(oobCode, newPassword) {
8383
8500
  try {
8384
8501
  await passwordSchema.parseAsync(newPassword);
8385
- await (0, import_auth5.confirmPasswordReset)(this.auth, oobCode, newPassword);
8502
+ await (0, import_auth7.confirmPasswordReset)(this.auth, oobCode, newPassword);
8386
8503
  } catch (error) {
8387
- if (error instanceof import_zod20.z.ZodError) {
8504
+ if (error instanceof import_zod22.z.ZodError) {
8388
8505
  throw AUTH_ERRORS.VALIDATION_ERROR;
8389
8506
  }
8390
8507
  const firebaseError = error;
@@ -8399,33 +8516,23 @@ var AuthService = class extends BaseService {
8399
8516
  }
8400
8517
  }
8401
8518
  /**
8402
- * Registers a new practitioner user with email and password
8403
- * 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
8404
8521
  *
8405
8522
  * @param data - Practitioner signup data containing either new profile details or token for claiming draft profile
8406
8523
  * @returns Object containing the created user and practitioner profile
8407
8524
  */
8408
8525
  async signUpPractitioner(data) {
8409
- var _a, _b, _c, _d;
8526
+ let firebaseUser = null;
8410
8527
  try {
8411
- console.log("[AUTH] Starting practitioner signup process", {
8528
+ console.log("[AUTH] Starting atomic practitioner signup process", {
8412
8529
  email: data.email,
8413
8530
  hasToken: !!data.token
8414
8531
  });
8415
- try {
8416
- await practitionerSignupSchema.parseAsync(data);
8417
- console.log("[AUTH] Practitioner signup data validation passed");
8418
- } catch (validationError) {
8419
- console.error(
8420
- "[AUTH] Validation error in signUpPractitioner:",
8421
- validationError
8422
- );
8423
- throw validationError;
8424
- }
8532
+ await this.validateSignupData(data);
8425
8533
  console.log("[AUTH] Creating Firebase user");
8426
- let firebaseUser;
8427
8534
  try {
8428
- const result = await (0, import_auth5.createUserWithEmailAndPassword)(
8535
+ const result = await (0, import_auth7.createUserWithEmailAndPassword)(
8429
8536
  this.auth,
8430
8537
  data.email,
8431
8538
  data.password
@@ -8436,136 +8543,110 @@ var AuthService = class extends BaseService {
8436
8543
  });
8437
8544
  } catch (firebaseError) {
8438
8545
  console.error("[AUTH] Firebase user creation failed:", firebaseError);
8439
- throw firebaseError;
8546
+ throw handleFirebaseError(firebaseError);
8440
8547
  }
8441
- console.log("[AUTH] Creating user with PRACTITIONER role");
8442
- let user;
8443
- try {
8444
- user = await this.userService.createUser(
8445
- firebaseUser,
8446
- ["practitioner" /* PRACTITIONER */],
8447
- {
8448
- skipProfileCreation: true
8449
- // We'll create the profile separately
8450
- }
8451
- );
8452
- console.log("[AUTH] User with PRACTITIONER role created successfully", {
8453
- userId: user.uid
8454
- });
8455
- } catch (userCreationError) {
8456
- console.error("[AUTH] User creation failed:", userCreationError);
8457
- throw userCreationError;
8458
- }
8459
- console.log("[AUTH] Initializing practitioner service");
8460
- const practitionerService = new PractitionerService(
8548
+ console.log("[AUTH] Starting Firestore transaction");
8549
+ const transactionResult = await (0, import_firestore25.runTransaction)(
8461
8550
  this.db,
8462
- this.auth,
8463
- this.app
8464
- );
8465
- let practitioner = null;
8466
- if (data.token) {
8467
- console.log("[AUTH] Token provided, attempting to claim draft profile");
8468
- try {
8469
- practitioner = await practitionerService.validateTokenAndClaimProfile(
8470
- data.token,
8471
- firebaseUser.uid
8472
- );
8473
- if (!practitioner) {
8474
- throw new Error("Invalid or expired invitation token");
8475
- }
8476
- console.log("[AUTH] Successfully claimed draft profile", {
8477
- practitionerId: practitioner.id
8478
- });
8479
- await this.userService.updateUser(firebaseUser.uid, {
8480
- practitionerProfile: practitioner.id
8481
- });
8551
+ async (transaction) => {
8482
8552
  console.log(
8483
- "[AUTH] User updated with practitioner profile reference"
8553
+ "[AUTH] Transaction started - creating user and practitioner"
8484
8554
  );
8485
- } catch (tokenError) {
8486
- console.error("[AUTH] Failed to claim draft profile:", tokenError);
8487
- throw tokenError;
8488
- }
8489
- } else {
8490
- console.log("[AUTH] Creating new practitioner profile");
8491
- if (!data.profileData) {
8492
- data.profileData = {};
8493
- }
8494
- const basicInfo = {
8495
- firstName: data.firstName || "",
8496
- lastName: data.lastName || "",
8497
- email: data.email,
8498
- phoneNumber: ((_a = data.profileData.basicInfo) == null ? void 0 : _a.phoneNumber) || "",
8499
- profileImageUrl: ((_b = data.profileData.basicInfo) == null ? void 0 : _b.profileImageUrl) || "",
8500
- gender: ((_c = data.profileData.basicInfo) == null ? void 0 : _c.gender) || "other",
8501
- // Default to "other" if not provided
8502
- bio: ((_d = data.profileData.basicInfo) == null ? void 0 : _d.bio) || "",
8503
- title: "Practitioner",
8504
- // Default title
8505
- dateOfBirth: /* @__PURE__ */ new Date(),
8506
- // Default to today
8507
- languages: ["English"]
8508
- // Default language
8509
- };
8510
- const certification = data.profileData.certification || {
8511
- level: "aesthetician" /* AESTHETICIAN */,
8512
- specialties: [],
8513
- licenseNumber: "Pending",
8514
- issuingAuthority: "Pending",
8515
- issueDate: /* @__PURE__ */ new Date(),
8516
- verificationStatus: "pending"
8517
- };
8518
- const createPractitionerData = {
8519
- userRef: firebaseUser.uid,
8520
- basicInfo,
8521
- certification,
8522
- status: "active" /* ACTIVE */,
8523
- isActive: true,
8524
- isVerified: false
8525
- };
8526
- try {
8527
- practitioner = await practitionerService.createPractitioner(
8528
- createPractitionerData
8555
+ const practitionerService = new PractitionerService(
8556
+ this.db,
8557
+ this.auth,
8558
+ this.app
8529
8559
  );
8530
- console.log("[AUTH] Practitioner profile created successfully", {
8531
- practitionerId: practitioner.id
8532
- });
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");
8533
8590
  await this.userService.updateUser(firebaseUser.uid, {
8534
8591
  practitionerProfile: practitioner.id
8535
8592
  });
8536
- console.log(
8537
- "[AUTH] User updated with practitioner profile reference"
8538
- );
8539
- } catch (createError) {
8540
- console.error(
8541
- "[AUTH] Failed to create practitioner profile:",
8542
- createError
8543
- );
8544
- throw createError;
8593
+ console.log("[AUTH] Transaction operations completed successfully");
8594
+ return { user, practitioner };
8545
8595
  }
8546
- }
8547
- console.log("[AUTH] Practitioner signup completed successfully", {
8548
- userId: user.uid,
8549
- 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
8550
8600
  });
8551
- return {
8552
- user,
8553
- practitioner
8554
- };
8601
+ return transactionResult;
8555
8602
  } catch (error) {
8556
- if (error instanceof import_zod20.z.ZodError) {
8557
- console.error(
8558
- "[AUTH] Zod validation error in signUpPractitioner:",
8559
- JSON.stringify(error.errors, null, 2)
8560
- );
8561
- 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);
8562
8609
  }
8563
- const firebaseError = error;
8564
- if (firebaseError.code === "auth/email-already-in-use" /* EMAIL_ALREADY_IN_USE */) {
8565
- 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);
8566
8625
  throw AUTH_ERRORS.EMAIL_ALREADY_EXISTS;
8567
8626
  }
8568
- 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);
8569
8650
  throw error;
8570
8651
  }
8571
8652
  }
@@ -8588,7 +8669,7 @@ var AuthService = class extends BaseService {
8588
8669
  this.auth,
8589
8670
  this.app
8590
8671
  );
8591
- const { user: firebaseUser } = await (0, import_auth5.signInWithEmailAndPassword)(
8672
+ const { user: firebaseUser } = await (0, import_auth7.signInWithEmailAndPassword)(
8592
8673
  this.auth,
8593
8674
  email,
8594
8675
  password
@@ -8831,63 +8912,63 @@ var import_firestore27 = require("firebase/firestore");
8831
8912
  var PROCEDURES_COLLECTION = "procedures";
8832
8913
 
8833
8914
  // src/validations/procedure.schema.ts
8834
- var import_zod21 = require("zod");
8835
- var createProcedureSchema = import_zod21.z.object({
8836
- name: import_zod21.z.string().min(1).max(200),
8837
- description: import_zod21.z.string().min(1).max(2e3),
8838
- family: import_zod21.z.nativeEnum(ProcedureFamily),
8839
- categoryId: import_zod21.z.string().min(1),
8840
- subcategoryId: import_zod21.z.string().min(1),
8841
- technologyId: import_zod21.z.string().min(1),
8842
- productId: import_zod21.z.string().min(1),
8843
- price: import_zod21.z.number().min(0),
8844
- currency: import_zod21.z.nativeEnum(Currency),
8845
- pricingMeasure: import_zod21.z.nativeEnum(PricingMeasure),
8846
- 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),
8847
8928
  // Max 8 hours
8848
- practitionerId: import_zod21.z.string().min(1),
8849
- clinicBranchId: import_zod21.z.string().min(1),
8850
- photos: import_zod21.z.array(mediaResourceSchema).optional()
8851
- });
8852
- var updateProcedureSchema = import_zod21.z.object({
8853
- name: import_zod21.z.string().min(3).max(100).optional(),
8854
- description: import_zod21.z.string().min(3).max(1e3).optional(),
8855
- price: import_zod21.z.number().min(0).optional(),
8856
- currency: import_zod21.z.nativeEnum(Currency).optional(),
8857
- pricingMeasure: import_zod21.z.nativeEnum(PricingMeasure).optional(),
8858
- duration: import_zod21.z.number().min(0).optional(),
8859
- isActive: import_zod21.z.boolean().optional(),
8860
- practitionerId: import_zod21.z.string().optional(),
8861
- categoryId: import_zod21.z.string().optional(),
8862
- subcategoryId: import_zod21.z.string().optional(),
8863
- technologyId: import_zod21.z.string().optional(),
8864
- productId: import_zod21.z.string().optional(),
8865
- clinicBranchId: import_zod21.z.string().optional(),
8866
- 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()
8867
8948
  });
8868
8949
  var procedureSchema = createProcedureSchema.extend({
8869
- id: import_zod21.z.string().min(1),
8870
- category: import_zod21.z.any(),
8950
+ id: import_zod23.z.string().min(1),
8951
+ category: import_zod23.z.any(),
8871
8952
  // We'll validate the full category object separately
8872
- subcategory: import_zod21.z.any(),
8953
+ subcategory: import_zod23.z.any(),
8873
8954
  // We'll validate the full subcategory object separately
8874
- technology: import_zod21.z.any(),
8955
+ technology: import_zod23.z.any(),
8875
8956
  // We'll validate the full technology object separately
8876
- product: import_zod21.z.any(),
8957
+ product: import_zod23.z.any(),
8877
8958
  // We'll validate the full product object separately
8878
- blockingConditions: import_zod21.z.array(import_zod21.z.any()),
8959
+ blockingConditions: import_zod23.z.array(import_zod23.z.any()),
8879
8960
  // We'll validate blocking conditions separately
8880
- contraindications: import_zod21.z.array(import_zod21.z.any()),
8961
+ contraindications: import_zod23.z.array(import_zod23.z.any()),
8881
8962
  // We'll validate contraindications separately
8882
- treatmentBenefits: import_zod21.z.array(import_zod21.z.any()),
8963
+ treatmentBenefits: import_zod23.z.array(import_zod23.z.any()),
8883
8964
  // We'll validate treatment benefits separately
8884
- preRequirements: import_zod21.z.array(import_zod21.z.any()),
8965
+ preRequirements: import_zod23.z.array(import_zod23.z.any()),
8885
8966
  // We'll validate requirements separately
8886
- postRequirements: import_zod21.z.array(import_zod21.z.any()),
8967
+ postRequirements: import_zod23.z.array(import_zod23.z.any()),
8887
8968
  // We'll validate requirements separately
8888
- certificationRequirement: import_zod21.z.any(),
8969
+ certificationRequirement: import_zod23.z.any(),
8889
8970
  // We'll validate certification requirement separately
8890
- documentationTemplates: import_zod21.z.array(import_zod21.z.any()),
8971
+ documentationTemplates: import_zod23.z.array(import_zod23.z.any()),
8891
8972
  // We'll validate documentation templates separately
8892
8973
  clinicInfo: clinicInfoSchema,
8893
8974
  // Clinic info validation
@@ -8895,9 +8976,9 @@ var procedureSchema = createProcedureSchema.extend({
8895
8976
  // Doctor info validation
8896
8977
  reviewInfo: procedureReviewInfoSchema,
8897
8978
  // Procedure review info validation
8898
- isActive: import_zod21.z.boolean(),
8899
- createdAt: import_zod21.z.date(),
8900
- updatedAt: import_zod21.z.date()
8979
+ isActive: import_zod23.z.boolean(),
8980
+ createdAt: import_zod23.z.date(),
8981
+ updatedAt: import_zod23.z.date()
8901
8982
  });
8902
8983
 
8903
8984
  // src/services/procedure/procedure.service.ts
@@ -9319,20 +9400,20 @@ var ProcedureService = class extends BaseService {
9319
9400
  const proceduresCollection = (0, import_firestore27.collection)(this.db, PROCEDURES_COLLECTION);
9320
9401
  let proceduresQuery = (0, import_firestore27.query)(proceduresCollection);
9321
9402
  if (pagination && pagination > 0) {
9322
- const { limit: limit15, startAfter: startAfter13 } = await import("firebase/firestore");
9403
+ const { limit: limit16, startAfter: startAfter14 } = await import("firebase/firestore");
9323
9404
  if (lastDoc) {
9324
9405
  proceduresQuery = (0, import_firestore27.query)(
9325
9406
  proceduresCollection,
9326
9407
  (0, import_firestore27.orderBy)("name"),
9327
9408
  // Use imported orderBy
9328
- startAfter13(lastDoc),
9329
- limit15(pagination)
9409
+ startAfter14(lastDoc),
9410
+ limit16(pagination)
9330
9411
  );
9331
9412
  } else {
9332
9413
  proceduresQuery = (0, import_firestore27.query)(
9333
9414
  proceduresCollection,
9334
9415
  (0, import_firestore27.orderBy)("name"),
9335
- limit15(pagination)
9416
+ limit16(pagination)
9336
9417
  );
9337
9418
  }
9338
9419
  } else {
@@ -10731,42 +10812,42 @@ var SYNCED_CALENDARS_COLLECTION = "syncedCalendars";
10731
10812
  var import_firestore41 = require("firebase/firestore");
10732
10813
 
10733
10814
  // src/validations/calendar.schema.ts
10734
- var import_zod23 = require("zod");
10815
+ var import_zod25 = require("zod");
10735
10816
  var import_firestore32 = require("firebase/firestore");
10736
10817
 
10737
10818
  // src/validations/profile-info.schema.ts
10738
- var import_zod22 = require("zod");
10819
+ var import_zod24 = require("zod");
10739
10820
  var import_firestore31 = require("firebase/firestore");
10740
- var clinicInfoSchema2 = import_zod22.z.object({
10741
- id: import_zod22.z.string(),
10742
- featuredPhoto: import_zod22.z.string(),
10743
- name: import_zod22.z.string(),
10744
- 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(),
10745
10826
  location: clinicLocationSchema,
10746
10827
  contactInfo: clinicContactInfoSchema
10747
10828
  });
10748
- var practitionerProfileInfoSchema = import_zod22.z.object({
10749
- id: import_zod22.z.string(),
10750
- practitionerPhoto: import_zod22.z.string().nullable(),
10751
- name: import_zod22.z.string(),
10752
- email: import_zod22.z.string().email(),
10753
- 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(),
10754
10835
  certification: practitionerCertificationSchema
10755
10836
  });
10756
- var patientProfileInfoSchema = import_zod22.z.object({
10757
- id: import_zod22.z.string(),
10758
- fullName: import_zod22.z.string(),
10759
- email: import_zod22.z.string().email(),
10760
- phone: import_zod22.z.string().nullable(),
10761
- dateOfBirth: import_zod22.z.instanceof(import_firestore31.Timestamp),
10762
- 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)
10763
10844
  });
10764
10845
 
10765
10846
  // src/validations/calendar.schema.ts
10766
10847
  var MIN_APPOINTMENT_DURATION = 15;
10767
- var calendarEventTimeSchema = import_zod23.z.object({
10768
- start: import_zod23.z.instanceof(Date).or(import_zod23.z.instanceof(import_firestore32.Timestamp)),
10769
- 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))
10770
10851
  }).refine(
10771
10852
  (data) => {
10772
10853
  const startDate = data.start instanceof import_firestore32.Timestamp ? data.start.toDate() : data.start;
@@ -10787,46 +10868,46 @@ var calendarEventTimeSchema = import_zod23.z.object({
10787
10868
  path: ["start"]
10788
10869
  }
10789
10870
  );
10790
- var timeSlotSchema2 = import_zod23.z.object({
10791
- start: import_zod23.z.date(),
10792
- end: import_zod23.z.date(),
10793
- 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()
10794
10875
  }).refine((data) => data.start < data.end, {
10795
10876
  message: "End time must be after start time",
10796
10877
  path: ["end"]
10797
10878
  });
10798
- var syncedCalendarEventSchema = import_zod23.z.object({
10799
- eventId: import_zod23.z.string(),
10800
- syncedCalendarProvider: import_zod23.z.nativeEnum(SyncedCalendarProvider),
10801
- 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))
10802
10883
  });
10803
- var procedureInfoSchema = import_zod23.z.object({
10804
- name: import_zod23.z.string(),
10805
- description: import_zod23.z.string(),
10806
- duration: import_zod23.z.number().min(MIN_APPOINTMENT_DURATION),
10807
- price: import_zod23.z.number().min(0),
10808
- 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)
10809
10890
  });
10810
- var procedureCategorizationSchema = import_zod23.z.object({
10811
- procedureFamily: import_zod23.z.string(),
10891
+ var procedureCategorizationSchema = import_zod25.z.object({
10892
+ procedureFamily: import_zod25.z.string(),
10812
10893
  // Replace with proper enum when available
10813
- procedureCategory: import_zod23.z.string(),
10894
+ procedureCategory: import_zod25.z.string(),
10814
10895
  // Replace with proper enum when available
10815
- procedureSubcategory: import_zod23.z.string(),
10896
+ procedureSubcategory: import_zod25.z.string(),
10816
10897
  // Replace with proper enum when available
10817
- procedureTechnology: import_zod23.z.string(),
10898
+ procedureTechnology: import_zod25.z.string(),
10818
10899
  // Replace with proper enum when available
10819
- procedureProduct: import_zod23.z.string()
10900
+ procedureProduct: import_zod25.z.string()
10820
10901
  // Replace with proper enum when available
10821
10902
  });
10822
- var createAppointmentSchema2 = import_zod23.z.object({
10823
- clinicId: import_zod23.z.string().min(1, "Clinic ID is required"),
10824
- doctorId: import_zod23.z.string().min(1, "Doctor ID is required"),
10825
- patientId: import_zod23.z.string().min(1, "Patient ID is required"),
10826
- 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"),
10827
10908
  eventLocation: clinicLocationSchema,
10828
10909
  eventTime: calendarEventTimeSchema,
10829
- description: import_zod23.z.string().optional()
10910
+ description: import_zod25.z.string().optional()
10830
10911
  }).refine(
10831
10912
  (data) => {
10832
10913
  return true;
@@ -10835,95 +10916,95 @@ var createAppointmentSchema2 = import_zod23.z.object({
10835
10916
  message: "Invalid appointment parameters"
10836
10917
  }
10837
10918
  );
10838
- var updateAppointmentSchema2 = import_zod23.z.object({
10839
- appointmentId: import_zod23.z.string().min(1, "Appointment ID is required"),
10840
- clinicId: import_zod23.z.string().min(1, "Clinic ID is required"),
10841
- doctorId: import_zod23.z.string().min(1, "Doctor ID is required"),
10842
- 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"),
10843
10924
  eventTime: calendarEventTimeSchema.optional(),
10844
- description: import_zod23.z.string().optional(),
10845
- status: import_zod23.z.nativeEnum(CalendarEventStatus).optional()
10846
- });
10847
- var createCalendarEventSchema = import_zod23.z.object({
10848
- id: import_zod23.z.string(),
10849
- clinicBranchId: import_zod23.z.string().nullable().optional(),
10850
- clinicBranchInfo: import_zod23.z.any().nullable().optional(),
10851
- 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(),
10852
10933
  practitionerProfileInfo: practitionerProfileInfoSchema.nullable().optional(),
10853
- patientProfileId: import_zod23.z.string().nullable().optional(),
10934
+ patientProfileId: import_zod25.z.string().nullable().optional(),
10854
10935
  patientProfileInfo: patientProfileInfoSchema.nullable().optional(),
10855
- procedureId: import_zod23.z.string().nullable().optional(),
10856
- appointmentId: import_zod23.z.string().nullable().optional(),
10857
- syncedCalendarEventId: import_zod23.z.array(syncedCalendarEventSchema).nullable().optional(),
10858
- 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"),
10859
10940
  eventLocation: clinicLocationSchema.optional(),
10860
10941
  eventTime: calendarEventTimeSchema,
10861
- description: import_zod23.z.string().optional(),
10862
- status: import_zod23.z.nativeEnum(CalendarEventStatus),
10863
- syncStatus: import_zod23.z.nativeEnum(CalendarSyncStatus),
10864
- eventType: import_zod23.z.nativeEnum(CalendarEventType),
10865
- 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(),
10866
10947
  // FieldValue for server timestamp
10867
- updatedAt: import_zod23.z.any()
10948
+ updatedAt: import_zod25.z.any()
10868
10949
  // FieldValue for server timestamp
10869
10950
  });
10870
- var updateCalendarEventSchema = import_zod23.z.object({
10871
- syncedCalendarEventId: import_zod23.z.array(syncedCalendarEventSchema).nullable().optional(),
10872
- appointmentId: import_zod23.z.string().nullable().optional(),
10873
- 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(),
10874
10955
  eventTime: calendarEventTimeSchema.optional(),
10875
- description: import_zod23.z.string().optional(),
10876
- status: import_zod23.z.nativeEnum(CalendarEventStatus).optional(),
10877
- syncStatus: import_zod23.z.nativeEnum(CalendarSyncStatus).optional(),
10878
- eventType: import_zod23.z.nativeEnum(CalendarEventType).optional(),
10879
- 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()
10880
10961
  // FieldValue for server timestamp
10881
10962
  });
10882
- var calendarEventSchema = import_zod23.z.object({
10883
- id: import_zod23.z.string(),
10884
- clinicBranchId: import_zod23.z.string().nullable().optional(),
10885
- 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(),
10886
10967
  // Will be replaced with proper clinic info schema
10887
- practitionerProfileId: import_zod23.z.string().nullable().optional(),
10968
+ practitionerProfileId: import_zod25.z.string().nullable().optional(),
10888
10969
  practitionerProfileInfo: practitionerProfileInfoSchema.nullable().optional(),
10889
- patientProfileId: import_zod23.z.string().nullable().optional(),
10970
+ patientProfileId: import_zod25.z.string().nullable().optional(),
10890
10971
  patientProfileInfo: patientProfileInfoSchema.nullable().optional(),
10891
- procedureId: import_zod23.z.string().nullable().optional(),
10972
+ procedureId: import_zod25.z.string().nullable().optional(),
10892
10973
  procedureInfo: procedureInfoSchema.nullable().optional(),
10893
10974
  procedureCategorization: procedureCategorizationSchema.nullable().optional(),
10894
- appointmentId: import_zod23.z.string().nullable().optional(),
10895
- syncedCalendarEventId: import_zod23.z.array(syncedCalendarEventSchema).nullable().optional(),
10896
- 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(),
10897
10978
  eventLocation: clinicLocationSchema.optional(),
10898
10979
  eventTime: calendarEventTimeSchema,
10899
- description: import_zod23.z.string().optional(),
10900
- status: import_zod23.z.nativeEnum(CalendarEventStatus),
10901
- syncStatus: import_zod23.z.nativeEnum(CalendarSyncStatus),
10902
- eventType: import_zod23.z.nativeEnum(CalendarEventType),
10903
- createdAt: import_zod23.z.instanceof(Date).or(import_zod23.z.instanceof(import_firestore32.Timestamp)),
10904
- updatedAt: import_zod23.z.instanceof(Date).or(import_zod23.z.instanceof(import_firestore32.Timestamp))
10905
- });
10906
- var createBlockingEventSchema = import_zod23.z.object({
10907
- entityType: import_zod23.z.enum(["practitioner", "clinic"]),
10908
- entityId: import_zod23.z.string().min(1, "Entity ID is required"),
10909
- 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"),
10910
10991
  eventTime: calendarEventTimeSchema,
10911
- eventType: import_zod23.z.enum([
10992
+ eventType: import_zod25.z.enum([
10912
10993
  "blocking" /* BLOCKING */,
10913
10994
  "break" /* BREAK */,
10914
10995
  "free_day" /* FREE_DAY */,
10915
10996
  "other" /* OTHER */
10916
10997
  ]),
10917
- description: import_zod23.z.string().max(1e3, "Description too long").optional()
10998
+ description: import_zod25.z.string().max(1e3, "Description too long").optional()
10918
10999
  });
10919
- var updateBlockingEventSchema = import_zod23.z.object({
10920
- entityType: import_zod23.z.enum(["practitioner", "clinic"]),
10921
- entityId: import_zod23.z.string().min(1, "Entity ID is required"),
10922
- eventId: import_zod23.z.string().min(1, "Event ID is required"),
10923
- 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(),
10924
11005
  eventTime: calendarEventTimeSchema.optional(),
10925
- description: import_zod23.z.string().max(1e3, "Description too long").optional(),
10926
- 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()
10927
11008
  });
10928
11009
 
10929
11010
  // src/services/calendar/utils/clinic.utils.ts
@@ -13660,7 +13741,7 @@ var import_firestore44 = require("firebase/firestore");
13660
13741
  var REVIEWS_COLLECTION = "reviews";
13661
13742
 
13662
13743
  // src/services/reviews/reviews.service.ts
13663
- var import_zod24 = require("zod");
13744
+ var import_zod26 = require("zod");
13664
13745
  var ReviewService = class extends BaseService {
13665
13746
  constructor(db, auth, app) {
13666
13747
  super(db, auth, app);
@@ -13747,7 +13828,7 @@ var ReviewService = class extends BaseService {
13747
13828
  });
13748
13829
  return review;
13749
13830
  } catch (error) {
13750
- if (error instanceof import_zod24.z.ZodError) {
13831
+ if (error instanceof import_zod26.z.ZodError) {
13751
13832
  throw new Error(`Invalid review data: ${error.message}`);
13752
13833
  }
13753
13834
  throw error;
@@ -15948,63 +16029,63 @@ var ProductService = class extends BaseService {
15948
16029
  };
15949
16030
 
15950
16031
  // src/validations/notification.schema.ts
15951
- var import_zod25 = require("zod");
15952
- var baseNotificationSchema = import_zod25.z.object({
15953
- id: import_zod25.z.string().optional(),
15954
- userId: import_zod25.z.string(),
15955
- 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(),
15956
16037
  // Timestamp
15957
- notificationType: import_zod25.z.nativeEnum(NotificationType),
15958
- notificationTokens: import_zod25.z.array(import_zod25.z.string()),
15959
- status: import_zod25.z.nativeEnum(NotificationStatus),
15960
- 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(),
15961
16042
  // Timestamp
15962
- updatedAt: import_zod25.z.any().optional(),
16043
+ updatedAt: import_zod27.z.any().optional(),
15963
16044
  // Timestamp
15964
- title: import_zod25.z.string(),
15965
- body: import_zod25.z.string(),
15966
- isRead: import_zod25.z.boolean(),
15967
- 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)
15968
16049
  });
15969
16050
  var preRequirementNotificationSchema = baseNotificationSchema.extend({
15970
- notificationType: import_zod25.z.literal("preRequirementInstructionDue" /* PRE_REQUIREMENT_INSTRUCTION_DUE */),
15971
- treatmentId: import_zod25.z.string(),
15972
- requirements: import_zod25.z.array(import_zod25.z.string()),
15973
- 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()
15974
16055
  // Timestamp
15975
16056
  });
15976
16057
  var postRequirementNotificationSchema = baseNotificationSchema.extend({
15977
- notificationType: import_zod25.z.literal(
16058
+ notificationType: import_zod27.z.literal(
15978
16059
  "postRequirementInstructionDue" /* POST_REQUIREMENT_INSTRUCTION_DUE */
15979
16060
  ),
15980
- treatmentId: import_zod25.z.string(),
15981
- requirements: import_zod25.z.array(import_zod25.z.string()),
15982
- 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()
15983
16064
  // Timestamp
15984
16065
  });
15985
16066
  var requirementInstructionDueNotificationSchema = baseNotificationSchema.extend({
15986
- notificationType: import_zod25.z.literal("requirementInstructionDue" /* REQUIREMENT_INSTRUCTION_DUE */),
15987
- appointmentId: import_zod25.z.string(),
15988
- patientRequirementInstanceId: import_zod25.z.string(),
15989
- instructionId: import_zod25.z.string(),
15990
- 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()
15991
16072
  });
15992
16073
  var appointmentReminderNotificationSchema = baseNotificationSchema.extend({
15993
- notificationType: import_zod25.z.literal("appointmentReminder" /* APPOINTMENT_REMINDER */),
15994
- appointmentId: import_zod25.z.string(),
15995
- 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(),
15996
16077
  // Timestamp
15997
- treatmentType: import_zod25.z.string(),
15998
- doctorName: import_zod25.z.string()
16078
+ treatmentType: import_zod27.z.string(),
16079
+ doctorName: import_zod27.z.string()
15999
16080
  });
16000
16081
  var appointmentNotificationSchema = baseNotificationSchema.extend({
16001
- notificationType: import_zod25.z.literal("appointmentStatusChange" /* APPOINTMENT_STATUS_CHANGE */),
16002
- appointmentId: import_zod25.z.string(),
16003
- appointmentStatus: import_zod25.z.string(),
16004
- previousStatus: import_zod25.z.string(),
16005
- 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()
16006
16087
  });
16007
- var notificationSchema = import_zod25.z.discriminatedUnion("notificationType", [
16088
+ var notificationSchema = import_zod27.z.discriminatedUnion("notificationType", [
16008
16089
  preRequirementNotificationSchema,
16009
16090
  postRequirementNotificationSchema,
16010
16091
  requirementInstructionDueNotificationSchema,