@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/admin/index.d.mts +4 -4
- package/dist/admin/index.d.ts +4 -4
- package/dist/backoffice/index.d.mts +4 -4
- package/dist/backoffice/index.d.ts +4 -4
- package/dist/index.d.mts +103 -98
- package/dist/index.d.ts +103 -98
- package/dist/index.js +454 -374
- package/dist/index.mjs +581 -500
- package/package.json +1 -1
- package/src/services/auth/index.ts +21 -0
- package/src/services/auth/utils/error.utils.ts +90 -0
- package/src/services/auth/utils/firebase.utils.ts +49 -0
- package/src/services/auth/utils/index.ts +21 -0
- package/src/services/auth/utils/practitioner.utils.ts +125 -0
- package/src/services/auth.service.ts +143 -155
- package/src/services/practitioner/practitioner.service.ts +5 -3
- package/src/types/practitioner/index.ts +4 -4
- package/src/validations/practitioner.schema.ts +7 -4
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
|
|
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
|
|
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
|
|
7743
|
-
this.facebookProvider = new
|
|
7744
|
-
this.appleProvider = new
|
|
7745
|
-
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
8156
|
-
const { user: firebaseUser } = await (0,
|
|
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,
|
|
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
|
|
8174
|
-
const { user: firebaseUser } = await (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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 =
|
|
8220
|
-
await (0,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
8463
|
+
await (0, import_auth7.sendPasswordResetEmail)(this.auth, email);
|
|
8348
8464
|
} catch (error) {
|
|
8349
|
-
if (error instanceof
|
|
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,
|
|
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,
|
|
8502
|
+
await (0, import_auth7.confirmPasswordReset)(this.auth, oobCode, newPassword);
|
|
8387
8503
|
} catch (error) {
|
|
8388
|
-
if (error instanceof
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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]
|
|
8443
|
-
|
|
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
|
-
|
|
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]
|
|
8553
|
+
"[AUTH] Transaction started - creating user and practitioner"
|
|
8485
8554
|
);
|
|
8486
|
-
|
|
8487
|
-
|
|
8488
|
-
|
|
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]
|
|
8532
|
-
|
|
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
|
-
|
|
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]
|
|
8549
|
-
userId: user.uid,
|
|
8550
|
-
practitionerId:
|
|
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
|
-
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8561
|
-
|
|
8562
|
-
|
|
8603
|
+
console.error(
|
|
8604
|
+
"[AUTH] Atomic signup failed, initiating cleanup...",
|
|
8605
|
+
error
|
|
8606
|
+
);
|
|
8607
|
+
if (firebaseUser) {
|
|
8608
|
+
await cleanupFirebaseUser(firebaseUser);
|
|
8563
8609
|
}
|
|
8564
|
-
|
|
8565
|
-
|
|
8566
|
-
|
|
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.
|
|
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,
|
|
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
|
|
8836
|
-
var createProcedureSchema =
|
|
8837
|
-
name:
|
|
8838
|
-
description:
|
|
8839
|
-
family:
|
|
8840
|
-
categoryId:
|
|
8841
|
-
subcategoryId:
|
|
8842
|
-
technologyId:
|
|
8843
|
-
productId:
|
|
8844
|
-
price:
|
|
8845
|
-
currency:
|
|
8846
|
-
pricingMeasure:
|
|
8847
|
-
duration:
|
|
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:
|
|
8850
|
-
clinicBranchId:
|
|
8851
|
-
photos:
|
|
8852
|
-
});
|
|
8853
|
-
var updateProcedureSchema =
|
|
8854
|
-
name:
|
|
8855
|
-
description:
|
|
8856
|
-
price:
|
|
8857
|
-
currency:
|
|
8858
|
-
pricingMeasure:
|
|
8859
|
-
duration:
|
|
8860
|
-
isActive:
|
|
8861
|
-
practitionerId:
|
|
8862
|
-
categoryId:
|
|
8863
|
-
subcategoryId:
|
|
8864
|
-
technologyId:
|
|
8865
|
-
productId:
|
|
8866
|
-
clinicBranchId:
|
|
8867
|
-
photos:
|
|
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:
|
|
8871
|
-
category:
|
|
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:
|
|
8953
|
+
subcategory: import_zod23.z.any(),
|
|
8874
8954
|
// We'll validate the full subcategory object separately
|
|
8875
|
-
technology:
|
|
8955
|
+
technology: import_zod23.z.any(),
|
|
8876
8956
|
// We'll validate the full technology object separately
|
|
8877
|
-
product:
|
|
8957
|
+
product: import_zod23.z.any(),
|
|
8878
8958
|
// We'll validate the full product object separately
|
|
8879
|
-
blockingConditions:
|
|
8959
|
+
blockingConditions: import_zod23.z.array(import_zod23.z.any()),
|
|
8880
8960
|
// We'll validate blocking conditions separately
|
|
8881
|
-
contraindications:
|
|
8961
|
+
contraindications: import_zod23.z.array(import_zod23.z.any()),
|
|
8882
8962
|
// We'll validate contraindications separately
|
|
8883
|
-
treatmentBenefits:
|
|
8963
|
+
treatmentBenefits: import_zod23.z.array(import_zod23.z.any()),
|
|
8884
8964
|
// We'll validate treatment benefits separately
|
|
8885
|
-
preRequirements:
|
|
8965
|
+
preRequirements: import_zod23.z.array(import_zod23.z.any()),
|
|
8886
8966
|
// We'll validate requirements separately
|
|
8887
|
-
postRequirements:
|
|
8967
|
+
postRequirements: import_zod23.z.array(import_zod23.z.any()),
|
|
8888
8968
|
// We'll validate requirements separately
|
|
8889
|
-
certificationRequirement:
|
|
8969
|
+
certificationRequirement: import_zod23.z.any(),
|
|
8890
8970
|
// We'll validate certification requirement separately
|
|
8891
|
-
documentationTemplates:
|
|
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:
|
|
8900
|
-
createdAt:
|
|
8901
|
-
updatedAt:
|
|
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:
|
|
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
|
-
|
|
9330
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
10819
|
+
var import_zod24 = require("zod");
|
|
10740
10820
|
var import_firestore31 = require("firebase/firestore");
|
|
10741
|
-
var clinicInfoSchema2 =
|
|
10742
|
-
id:
|
|
10743
|
-
featuredPhoto:
|
|
10744
|
-
name:
|
|
10745
|
-
description:
|
|
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 =
|
|
10750
|
-
id:
|
|
10751
|
-
practitionerPhoto:
|
|
10752
|
-
name:
|
|
10753
|
-
email:
|
|
10754
|
-
phone:
|
|
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 =
|
|
10758
|
-
id:
|
|
10759
|
-
fullName:
|
|
10760
|
-
email:
|
|
10761
|
-
phone:
|
|
10762
|
-
dateOfBirth:
|
|
10763
|
-
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 =
|
|
10769
|
-
start:
|
|
10770
|
-
end:
|
|
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 =
|
|
10792
|
-
start:
|
|
10793
|
-
end:
|
|
10794
|
-
isAvailable:
|
|
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 =
|
|
10800
|
-
eventId:
|
|
10801
|
-
syncedCalendarProvider:
|
|
10802
|
-
syncedAt:
|
|
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 =
|
|
10805
|
-
name:
|
|
10806
|
-
description:
|
|
10807
|
-
duration:
|
|
10808
|
-
price:
|
|
10809
|
-
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 =
|
|
10812
|
-
procedureFamily:
|
|
10891
|
+
var procedureCategorizationSchema = import_zod25.z.object({
|
|
10892
|
+
procedureFamily: import_zod25.z.string(),
|
|
10813
10893
|
// Replace with proper enum when available
|
|
10814
|
-
procedureCategory:
|
|
10894
|
+
procedureCategory: import_zod25.z.string(),
|
|
10815
10895
|
// Replace with proper enum when available
|
|
10816
|
-
procedureSubcategory:
|
|
10896
|
+
procedureSubcategory: import_zod25.z.string(),
|
|
10817
10897
|
// Replace with proper enum when available
|
|
10818
|
-
procedureTechnology:
|
|
10898
|
+
procedureTechnology: import_zod25.z.string(),
|
|
10819
10899
|
// Replace with proper enum when available
|
|
10820
|
-
procedureProduct:
|
|
10900
|
+
procedureProduct: import_zod25.z.string()
|
|
10821
10901
|
// Replace with proper enum when available
|
|
10822
10902
|
});
|
|
10823
|
-
var createAppointmentSchema2 =
|
|
10824
|
-
clinicId:
|
|
10825
|
-
doctorId:
|
|
10826
|
-
patientId:
|
|
10827
|
-
procedureId:
|
|
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:
|
|
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 =
|
|
10840
|
-
appointmentId:
|
|
10841
|
-
clinicId:
|
|
10842
|
-
doctorId:
|
|
10843
|
-
patientId:
|
|
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:
|
|
10846
|
-
status:
|
|
10847
|
-
});
|
|
10848
|
-
var createCalendarEventSchema =
|
|
10849
|
-
id:
|
|
10850
|
-
clinicBranchId:
|
|
10851
|
-
clinicBranchInfo:
|
|
10852
|
-
practitionerProfileId:
|
|
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:
|
|
10934
|
+
patientProfileId: import_zod25.z.string().nullable().optional(),
|
|
10855
10935
|
patientProfileInfo: patientProfileInfoSchema.nullable().optional(),
|
|
10856
|
-
procedureId:
|
|
10857
|
-
appointmentId:
|
|
10858
|
-
syncedCalendarEventId:
|
|
10859
|
-
eventName:
|
|
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:
|
|
10863
|
-
status:
|
|
10864
|
-
syncStatus:
|
|
10865
|
-
eventType:
|
|
10866
|
-
createdAt:
|
|
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:
|
|
10948
|
+
updatedAt: import_zod25.z.any()
|
|
10869
10949
|
// FieldValue for server timestamp
|
|
10870
10950
|
});
|
|
10871
|
-
var updateCalendarEventSchema =
|
|
10872
|
-
syncedCalendarEventId:
|
|
10873
|
-
appointmentId:
|
|
10874
|
-
eventName:
|
|
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:
|
|
10877
|
-
status:
|
|
10878
|
-
syncStatus:
|
|
10879
|
-
eventType:
|
|
10880
|
-
updatedAt:
|
|
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 =
|
|
10884
|
-
id:
|
|
10885
|
-
clinicBranchId:
|
|
10886
|
-
clinicBranchInfo:
|
|
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:
|
|
10968
|
+
practitionerProfileId: import_zod25.z.string().nullable().optional(),
|
|
10889
10969
|
practitionerProfileInfo: practitionerProfileInfoSchema.nullable().optional(),
|
|
10890
|
-
patientProfileId:
|
|
10970
|
+
patientProfileId: import_zod25.z.string().nullable().optional(),
|
|
10891
10971
|
patientProfileInfo: patientProfileInfoSchema.nullable().optional(),
|
|
10892
|
-
procedureId:
|
|
10972
|
+
procedureId: import_zod25.z.string().nullable().optional(),
|
|
10893
10973
|
procedureInfo: procedureInfoSchema.nullable().optional(),
|
|
10894
10974
|
procedureCategorization: procedureCategorizationSchema.nullable().optional(),
|
|
10895
|
-
appointmentId:
|
|
10896
|
-
syncedCalendarEventId:
|
|
10897
|
-
eventName:
|
|
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:
|
|
10901
|
-
status:
|
|
10902
|
-
syncStatus:
|
|
10903
|
-
eventType:
|
|
10904
|
-
createdAt:
|
|
10905
|
-
updatedAt:
|
|
10906
|
-
});
|
|
10907
|
-
var createBlockingEventSchema =
|
|
10908
|
-
entityType:
|
|
10909
|
-
entityId:
|
|
10910
|
-
eventName:
|
|
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:
|
|
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:
|
|
10998
|
+
description: import_zod25.z.string().max(1e3, "Description too long").optional()
|
|
10919
10999
|
});
|
|
10920
|
-
var updateBlockingEventSchema =
|
|
10921
|
-
entityType:
|
|
10922
|
-
entityId:
|
|
10923
|
-
eventId:
|
|
10924
|
-
eventName:
|
|
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:
|
|
10927
|
-
status:
|
|
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
|
|
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
|
|
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
|
|
15953
|
-
var baseNotificationSchema =
|
|
15954
|
-
id:
|
|
15955
|
-
userId:
|
|
15956
|
-
notificationTime:
|
|
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:
|
|
15959
|
-
notificationTokens:
|
|
15960
|
-
status:
|
|
15961
|
-
createdAt:
|
|
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:
|
|
16043
|
+
updatedAt: import_zod27.z.any().optional(),
|
|
15964
16044
|
// Timestamp
|
|
15965
|
-
title:
|
|
15966
|
-
body:
|
|
15967
|
-
isRead:
|
|
15968
|
-
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:
|
|
15972
|
-
treatmentId:
|
|
15973
|
-
requirements:
|
|
15974
|
-
deadline:
|
|
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:
|
|
16058
|
+
notificationType: import_zod27.z.literal(
|
|
15979
16059
|
"postRequirementInstructionDue" /* POST_REQUIREMENT_INSTRUCTION_DUE */
|
|
15980
16060
|
),
|
|
15981
|
-
treatmentId:
|
|
15982
|
-
requirements:
|
|
15983
|
-
deadline:
|
|
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:
|
|
15988
|
-
appointmentId:
|
|
15989
|
-
patientRequirementInstanceId:
|
|
15990
|
-
instructionId:
|
|
15991
|
-
originalRequirementId:
|
|
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:
|
|
15995
|
-
appointmentId:
|
|
15996
|
-
appointmentTime:
|
|
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:
|
|
15999
|
-
doctorName:
|
|
16078
|
+
treatmentType: import_zod27.z.string(),
|
|
16079
|
+
doctorName: import_zod27.z.string()
|
|
16000
16080
|
});
|
|
16001
16081
|
var appointmentNotificationSchema = baseNotificationSchema.extend({
|
|
16002
|
-
notificationType:
|
|
16003
|
-
appointmentId:
|
|
16004
|
-
appointmentStatus:
|
|
16005
|
-
previousStatus:
|
|
16006
|
-
reason:
|
|
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 =
|
|
16088
|
+
var notificationSchema = import_zod27.z.discriminatedUnion("notificationType", [
|
|
16009
16089
|
preRequirementNotificationSchema,
|
|
16010
16090
|
postRequirementNotificationSchema,
|
|
16011
16091
|
requirementInstructionDueNotificationSchema,
|