vr-commons 1.0.85 → 1.0.86

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.
@@ -150,8 +150,12 @@ export declare const getSortOrder: (sortBy?: string, order?: string) => any[];
150
150
  * Generate unique jacket ID
151
151
  */
152
152
  export declare const generateJacketId: () => Promise<string>;
153
+ export interface ValidationError {
154
+ field: string;
155
+ message: string;
156
+ }
153
157
  /**
154
- * Validate unique user fields
158
+ * Validate unique user fields (phone number is in PhoneContact table)
155
159
  */
156
160
  export declare const validateUniqueFields: (fields: {
157
161
  phoneNumber?: string;
@@ -381,41 +381,62 @@ const generateJacketId = async () => {
381
381
  return jacketId;
382
382
  };
383
383
  exports.generateJacketId = generateJacketId;
384
- // ============================================================================
385
- // VALIDATION FUNCTIONS
386
- // ============================================================================
387
384
  /**
388
- * Validate unique user fields
385
+ * Validate unique user fields (phone number is in PhoneContact table)
389
386
  */
390
387
  const validateUniqueFields = async (fields, excludeUserId) => {
391
388
  const errors = [];
392
- for (const [field, value] of Object.entries(fields)) {
393
- if (!value)
394
- continue;
395
- const where = { [field]: value };
389
+ // Check phone number (in PhoneContact table)
390
+ if (fields.phoneNumber) {
391
+ const phoneWhere = { phoneNumber: fields.phoneNumber, isActive: true };
396
392
  if (excludeUserId) {
397
- where.id = { [sequelize_1.Op.ne]: excludeUserId };
393
+ phoneWhere.userId = { [sequelize_1.Op.ne]: excludeUserId };
398
394
  }
399
- const existing = await vr_models_1.User.findOne({ where });
400
- if (existing) {
401
- let message = "";
402
- switch (field) {
403
- case "phoneNumber":
404
- message = "Phone number already registered";
405
- break;
406
- case "nationalId":
407
- message = "National ID already registered";
408
- break;
409
- case "email":
410
- message = "Email already registered";
411
- break;
412
- case "jacketId":
413
- message = "Jacket ID already taken";
414
- break;
415
- default:
416
- message = `${field} already exists`;
417
- }
418
- errors.push({ field, message });
395
+ const existingPhone = await vr_models_1.PhoneContact.findOne({
396
+ where: phoneWhere,
397
+ include: [{ model: vr_models_1.User, as: "user", attributes: ["id"] }],
398
+ });
399
+ if (existingPhone && existingPhone.userId !== excludeUserId) {
400
+ errors.push({
401
+ field: "phoneNumber",
402
+ message: "Phone number already registered",
403
+ });
404
+ }
405
+ }
406
+ // Check nationalId (on User model)
407
+ if (fields.nationalId) {
408
+ const userWhere = { nationalId: fields.nationalId };
409
+ if (excludeUserId) {
410
+ userWhere.id = { [sequelize_1.Op.ne]: excludeUserId };
411
+ }
412
+ const existingUser = await vr_models_1.User.findOne({ where: userWhere });
413
+ if (existingUser) {
414
+ errors.push({
415
+ field: "nationalId",
416
+ message: "National ID already registered",
417
+ });
418
+ }
419
+ }
420
+ // Check email (on User model)
421
+ if (fields.email) {
422
+ const userWhere = { email: fields.email };
423
+ if (excludeUserId) {
424
+ userWhere.id = { [sequelize_1.Op.ne]: excludeUserId };
425
+ }
426
+ const existingUser = await vr_models_1.User.findOne({ where: userWhere });
427
+ if (existingUser) {
428
+ errors.push({ field: "email", message: "Email already registered" });
429
+ }
430
+ }
431
+ // Check jacketId (on User model)
432
+ if (fields.jacketId) {
433
+ const userWhere = { jacketId: fields.jacketId };
434
+ if (excludeUserId) {
435
+ userWhere.id = { [sequelize_1.Op.ne]: excludeUserId };
436
+ }
437
+ const existingUser = await vr_models_1.User.findOne({ where: userWhere });
438
+ if (existingUser) {
439
+ errors.push({ field: "jacketId", message: "Jacket ID already taken" });
419
440
  }
420
441
  }
421
442
  return errors;
@@ -1,37 +1,6 @@
1
1
  import { z } from "zod";
2
2
  export declare const phoneRegex: RegExp;
3
3
  export declare const passwordRegex: RegExp;
4
- export declare const riderLoginSchema: z.ZodObject<{
5
- body: z.ZodObject<{
6
- phoneNumber: z.ZodString;
7
- nationalId: z.ZodString;
8
- }, "strip", z.ZodTypeAny, {
9
- phoneNumber: string;
10
- nationalId: string;
11
- }, {
12
- phoneNumber: string;
13
- nationalId: string;
14
- }>;
15
- query: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
16
- params: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
17
- headers: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
18
- }, "strip", z.ZodTypeAny, {
19
- body: {
20
- phoneNumber: string;
21
- nationalId: string;
22
- };
23
- params?: {} | undefined;
24
- query?: {} | undefined;
25
- headers?: {} | undefined;
26
- }, {
27
- body: {
28
- phoneNumber: string;
29
- nationalId: string;
30
- };
31
- params?: {} | undefined;
32
- query?: {} | undefined;
33
- headers?: {} | undefined;
34
- }>;
35
4
  export declare const userLoginSchema: z.ZodObject<{
36
5
  body: z.ZodObject<{
37
6
  email: z.ZodString;
@@ -71,6 +40,28 @@ export declare const forgotPasswordSchema: z.ZodObject<{
71
40
  email: string;
72
41
  };
73
42
  }>;
43
+ export declare const changePasswordSchema: z.ZodObject<{
44
+ body: z.ZodObject<{
45
+ oldPassword: z.ZodString;
46
+ newPassword: z.ZodString;
47
+ }, "strip", z.ZodTypeAny, {
48
+ oldPassword: string;
49
+ newPassword: string;
50
+ }, {
51
+ oldPassword: string;
52
+ newPassword: string;
53
+ }>;
54
+ }, "strip", z.ZodTypeAny, {
55
+ body: {
56
+ oldPassword: string;
57
+ newPassword: string;
58
+ };
59
+ }, {
60
+ body: {
61
+ oldPassword: string;
62
+ newPassword: string;
63
+ };
64
+ }>;
74
65
  export declare const refreshTokenSchema: z.ZodObject<{
75
66
  body: z.ZodObject<{
76
67
  refreshToken: z.ZodString;
@@ -96,35 +87,66 @@ export declare const registerSchema: z.ZodObject<{
96
87
  email: z.ZodOptional<z.ZodString>;
97
88
  password: z.ZodString;
98
89
  }, "strict", z.ZodTypeAny, {
99
- phoneNumber: string;
100
90
  password: string;
101
91
  firstName: string;
102
92
  lastName: string;
93
+ phoneNumber: string;
103
94
  email?: string | undefined;
104
95
  }, {
105
- phoneNumber: string;
106
96
  password: string;
107
97
  firstName: string;
108
98
  lastName: string;
99
+ phoneNumber: string;
109
100
  email?: string | undefined;
110
101
  }>;
111
102
  }, "strip", z.ZodTypeAny, {
112
103
  body: {
113
- phoneNumber: string;
114
104
  password: string;
115
105
  firstName: string;
116
106
  lastName: string;
107
+ phoneNumber: string;
117
108
  email?: string | undefined;
118
109
  };
119
110
  }, {
120
111
  body: {
121
- phoneNumber: string;
122
112
  password: string;
123
113
  firstName: string;
124
114
  lastName: string;
115
+ phoneNumber: string;
125
116
  email?: string | undefined;
126
117
  };
127
118
  }>;
119
+ export declare const riderLoginSchema: z.ZodObject<{
120
+ body: z.ZodObject<{
121
+ phoneNumber: z.ZodString;
122
+ nationalId: z.ZodString;
123
+ }, "strip", z.ZodTypeAny, {
124
+ phoneNumber: string;
125
+ nationalId: string;
126
+ }, {
127
+ phoneNumber: string;
128
+ nationalId: string;
129
+ }>;
130
+ query: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
131
+ params: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
132
+ headers: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
133
+ }, "strip", z.ZodTypeAny, {
134
+ body: {
135
+ phoneNumber: string;
136
+ nationalId: string;
137
+ };
138
+ params?: {} | undefined;
139
+ query?: {} | undefined;
140
+ headers?: {} | undefined;
141
+ }, {
142
+ body: {
143
+ phoneNumber: string;
144
+ nationalId: string;
145
+ };
146
+ params?: {} | undefined;
147
+ query?: {} | undefined;
148
+ headers?: {} | undefined;
149
+ }>;
128
150
  export declare const requestOtpSchema: z.ZodObject<{
129
151
  body: z.ZodObject<{
130
152
  phoneNumber: z.ZodString;
@@ -1,22 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resendOtpSchema = exports.verifyOtpSchema = exports.requestOtpSchema = exports.registerSchema = exports.refreshTokenSchema = exports.forgotPasswordSchema = exports.userLoginSchema = exports.riderLoginSchema = exports.passwordRegex = exports.phoneRegex = void 0;
3
+ exports.resendOtpSchema = exports.verifyOtpSchema = exports.requestOtpSchema = exports.riderLoginSchema = exports.registerSchema = exports.refreshTokenSchema = exports.changePasswordSchema = exports.forgotPasswordSchema = exports.userLoginSchema = exports.passwordRegex = exports.phoneRegex = void 0;
4
+ // src/validations/auth.schema.ts
4
5
  const zod_1 = require("zod");
5
6
  exports.phoneRegex = /^\+250(78|79|73|72)[0-9]{7}$/;
6
7
  exports.passwordRegex = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{6,}$/;
7
- exports.riderLoginSchema = zod_1.z.object({
8
- body: zod_1.z.object({
9
- phoneNumber: zod_1.z
10
- .string()
11
- .trim()
12
- .min(10, "Phone number must be at least 10 digits")
13
- .max(15, "Phone number must be at most 15 digits"),
14
- nationalId: zod_1.z.string().min(16, "National ID must be atleast 16 digits"),
15
- }),
16
- query: zod_1.z.object({}).optional(),
17
- params: zod_1.z.object({}).optional(),
18
- headers: zod_1.z.object({}).optional(),
19
- });
8
+ // ==================== ADMIN AUTH VALIDATIONS ====================
20
9
  exports.userLoginSchema = zod_1.z.object({
21
10
  body: zod_1.z.object({
22
11
  email: zod_1.z.string().email(),
@@ -28,6 +17,14 @@ exports.forgotPasswordSchema = zod_1.z.object({
28
17
  email: zod_1.z.string().email(),
29
18
  }),
30
19
  });
20
+ exports.changePasswordSchema = zod_1.z.object({
21
+ body: zod_1.z.object({
22
+ oldPassword: zod_1.z.string().min(1, "Old password is required"),
23
+ newPassword: zod_1.z
24
+ .string()
25
+ .regex(exports.passwordRegex, "Password must be at least 6 characters with at least one letter and one number"),
26
+ }),
27
+ });
31
28
  exports.refreshTokenSchema = zod_1.z.object({
32
29
  body: zod_1.z.object({
33
30
  refreshToken: zod_1.z.string().min(1, "Refresh token is required"),
@@ -52,6 +49,20 @@ exports.registerSchema = zod_1.z.object({
52
49
  })
53
50
  .strict(),
54
51
  });
52
+ // ==================== USER (RIDER/PASSENGER) AUTH VALIDATIONS ====================
53
+ exports.riderLoginSchema = zod_1.z.object({
54
+ body: zod_1.z.object({
55
+ phoneNumber: zod_1.z
56
+ .string()
57
+ .trim()
58
+ .min(10, "Phone number must be at least 10 digits")
59
+ .max(15, "Phone number must be at most 15 digits"),
60
+ nationalId: zod_1.z.string().min(16, "National ID must be atleast 16 digits"),
61
+ }),
62
+ query: zod_1.z.object({}).optional(),
63
+ params: zod_1.z.object({}).optional(),
64
+ headers: zod_1.z.object({}).optional(),
65
+ });
55
66
  exports.requestOtpSchema = zod_1.z.object({
56
67
  body: zod_1.z.object({
57
68
  phoneNumber: zod_1.z
@@ -76,8 +87,6 @@ exports.verifyOtpSchema = zod_1.z.object({
76
87
  .optional(),
77
88
  })
78
89
  .refine((data) => {
79
- // If it's a new user, firstName and lastName are required
80
- // We'll check this in service by checking if user exists
81
90
  return true;
82
91
  }, {
83
92
  message: "First name and last name are required for new users",
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.extendSessionSchema = exports.unlockDeviceSchema = void 0;
4
4
  const zod_1 = require("zod");
5
- const serialRegex = /^[A-Z0-9]{8,32}$/i;
5
+ const serialRegex = /^[A-Z0-9]{8,24}$/i;
6
6
  exports.unlockDeviceSchema = zod_1.z.object({
7
7
  body: zod_1.z.object({
8
8
  deviceSerialNumber: zod_1.z
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vr-commons",
3
- "version": "1.0.85",
3
+ "version": "1.0.86",
4
4
  "description": "Shared functions package",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",