@mohasinac/validation 0.1.0 → 1.1.0

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.cjs CHANGED
@@ -21,13 +21,38 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  addressSchema: () => addressSchema,
24
+ calculatePasswordStrength: () => calculatePasswordStrength,
24
25
  dateStringSchema: () => dateStringSchema,
25
26
  emailSchema: () => emailSchema,
27
+ exactLength: () => exactLength,
28
+ extractCountryCode: () => extractCountryCode,
29
+ formatPhone: () => formatPhone,
30
+ inRange: () => inRange,
31
+ isCommonPassword: () => isCommonPassword,
32
+ isDisposableEmail: () => isDisposableEmail,
33
+ isExternalUrl: () => isExternalUrl,
34
+ isInList: () => isInList,
35
+ isNumeric: () => isNumeric,
36
+ isRequired: () => isRequired,
37
+ isValidEmail: () => isValidEmail,
38
+ isValidEmailDomain: () => isValidEmailDomain,
39
+ isValidIndianMobile: () => isValidIndianMobile,
40
+ isValidIndianPincode: () => isValidIndianPincode,
41
+ isValidPhone: () => isValidPhone,
42
+ isValidUrl: () => isValidUrl,
43
+ isValidUrlWithProtocol: () => isValidUrlWithProtocol,
44
+ matchesPattern: () => matchesPattern,
45
+ maxLength: () => maxLength,
26
46
  mediaUrlSchema: () => mediaUrlSchema,
47
+ meetsPasswordRequirements: () => meetsPasswordRequirements,
48
+ minLength: () => minLength,
49
+ normalizeEmail: () => normalizeEmail,
50
+ normalizePhone: () => normalizePhone,
27
51
  objectIdSchema: () => objectIdSchema,
28
52
  paginationQuerySchema: () => paginationQuerySchema,
29
53
  passwordSchema: () => passwordSchema,
30
54
  phoneSchema: () => phoneSchema,
55
+ sanitizeUrl: () => sanitizeUrl,
31
56
  setupZodErrorMap: () => setupZodErrorMap,
32
57
  urlSchema: () => urlSchema,
33
58
  zodErrorMap: () => zodErrorMap
@@ -162,22 +187,240 @@ function zodErrorMap(issue) {
162
187
  message: (_d = issue.message) != null ? _d : "Invalid value"
163
188
  };
164
189
  }
165
- var _applied = false;
166
190
  function setupZodErrorMap() {
167
- if (_applied) return;
191
+ if (globalThis.__mohasinac_zod_applied__) return;
168
192
  import_zod2.z.setErrorMap(zodErrorMap);
169
- _applied = true;
193
+ globalThis.__mohasinac_zod_applied__ = true;
194
+ }
195
+
196
+ // src/email.validator.ts
197
+ function isValidEmail(email) {
198
+ const emailRegex = /^[^\s@]+@[^\s@.][^\s@]*[^\s@.]\.[^\s@]+$|^[^\s@]+@[^\s@.]\.[^\s@]+$/;
199
+ if (!emailRegex.test(email)) return false;
200
+ if (email.includes("..")) return false;
201
+ return true;
202
+ }
203
+ function isValidEmailDomain(email, allowedDomains) {
204
+ if (!isValidEmail(email)) return false;
205
+ if (!allowedDomains || allowedDomains.length === 0) return true;
206
+ const domain = email.split("@")[1].toLowerCase();
207
+ return allowedDomains.some((allowed) => domain === allowed.toLowerCase());
208
+ }
209
+ function normalizeEmail(email) {
210
+ return email.trim().toLowerCase();
211
+ }
212
+ function isDisposableEmail(email) {
213
+ var _a;
214
+ const disposableDomains = [
215
+ "tempmail.com",
216
+ "10minutemail.com",
217
+ "guerrillamail.com",
218
+ "mailinator.com",
219
+ "throwaway.email"
220
+ ];
221
+ const domain = (_a = email.split("@")[1]) == null ? void 0 : _a.toLowerCase();
222
+ return disposableDomains.includes(domain);
223
+ }
224
+
225
+ // src/password.validator.ts
226
+ var DEFAULT_REQUIREMENTS = {
227
+ minLength: 8,
228
+ requireUppercase: true,
229
+ requireLowercase: true,
230
+ requireNumbers: true,
231
+ requireSpecialChars: true
232
+ };
233
+ function meetsPasswordRequirements(password, requirements = DEFAULT_REQUIREMENTS) {
234
+ const missing = [];
235
+ if (password.length < requirements.minLength)
236
+ missing.push(`At least ${requirements.minLength} characters`);
237
+ if (requirements.requireUppercase && !/[A-Z]/.test(password))
238
+ missing.push("One uppercase letter");
239
+ if (requirements.requireLowercase && !/[a-z]/.test(password))
240
+ missing.push("One lowercase letter");
241
+ if (requirements.requireNumbers && !/\d/.test(password))
242
+ missing.push("One number");
243
+ if (requirements.requireSpecialChars && !/[!@#$%^&*(),.?":{}|<>]/.test(password))
244
+ missing.push("One special character");
245
+ return { valid: missing.length === 0, missing };
246
+ }
247
+ function calculatePasswordStrength(password) {
248
+ let score = 0;
249
+ const feedback = [];
250
+ if (password.length >= 8) score++;
251
+ if (password.length >= 12) score++;
252
+ if (password.length < 8) feedback.push("Password is too short");
253
+ if (/[a-z]/.test(password) && /[A-Z]/.test(password)) score++;
254
+ if (/\d/.test(password)) score++;
255
+ if (/[!@#$%^&*(),.?":{}|<>]/.test(password)) score++;
256
+ if (/(.)\1{2,}/.test(password)) {
257
+ score = Math.max(0, score - 1);
258
+ feedback.push("Avoid repeated characters");
259
+ }
260
+ if (/^(?:password|123456|qwerty)/i.test(password)) {
261
+ score = 0;
262
+ feedback.push("Avoid common passwords");
263
+ }
264
+ score = Math.min(4, Math.max(0, score));
265
+ const levels = ["too-weak", "weak", "fair", "good", "strong"];
266
+ return { score, level: levels[score], feedback };
267
+ }
268
+ function isCommonPassword(password) {
269
+ const commonPasswords = [
270
+ "password",
271
+ "123456",
272
+ "123456789",
273
+ "qwerty",
274
+ "abc123",
275
+ "monkey",
276
+ "1234567",
277
+ "letmein",
278
+ "trustno1",
279
+ "dragon",
280
+ "baseball",
281
+ "iloveyou",
282
+ "master",
283
+ "sunshine",
284
+ "ashley",
285
+ "bailey",
286
+ "passw0rd",
287
+ "shadow",
288
+ "123123",
289
+ "654321"
290
+ ];
291
+ return commonPasswords.includes(password.toLowerCase());
292
+ }
293
+
294
+ // src/phone.validator.ts
295
+ function isValidPhone(phone) {
296
+ const phoneRegex = /^\+?[\d\s-()]+$/;
297
+ const cleaned = phone.replace(/[\s-()]/g, "");
298
+ return phoneRegex.test(phone) && cleaned.length >= 10 && cleaned.length <= 15;
299
+ }
300
+ function normalizePhone(phone) {
301
+ return phone.replace(/[\s-()]/g, "");
302
+ }
303
+ function formatPhone(phone, countryCode = "US") {
304
+ const cleaned = normalizePhone(phone);
305
+ if (countryCode === "US" && cleaned.length === 10) {
306
+ return `(${cleaned.slice(0, 3)}) ${cleaned.slice(3, 6)}-${cleaned.slice(6)}`;
307
+ }
308
+ if (cleaned.startsWith("+")) return cleaned;
309
+ return `+${cleaned}`;
310
+ }
311
+ function extractCountryCode(phone) {
312
+ const cleaned = normalizePhone(phone);
313
+ if (!cleaned.startsWith("+")) return null;
314
+ const match = cleaned.match(/^\+(\d{1,3})/);
315
+ return match ? `+${match[1]}` : null;
316
+ }
317
+ function isValidIndianMobile(phone) {
318
+ const cleaned = normalizePhone(phone).replace(/^\+91/, "");
319
+ return /^[6-9]\d{9}$/.test(cleaned);
320
+ }
321
+ function isValidIndianPincode(pincode) {
322
+ return /^\d{6}$/.test(pincode.trim());
323
+ }
324
+
325
+ // src/url.validator.ts
326
+ function isValidUrl(url) {
327
+ try {
328
+ new URL(url);
329
+ return true;
330
+ } catch (e) {
331
+ return false;
332
+ }
333
+ }
334
+ function isValidUrlWithProtocol(url, protocols = ["http", "https"]) {
335
+ if (!isValidUrl(url)) return false;
336
+ try {
337
+ const urlObj = new URL(url);
338
+ return protocols.includes(urlObj.protocol.replace(":", ""));
339
+ } catch (e) {
340
+ return false;
341
+ }
342
+ }
343
+ function isExternalUrl(url, currentDomain) {
344
+ if (!isValidUrl(url)) return false;
345
+ try {
346
+ const urlObj = new URL(url);
347
+ const currentHost = currentDomain || (typeof window !== "undefined" ? window.location.hostname : "");
348
+ return urlObj.hostname !== currentHost;
349
+ } catch (e) {
350
+ return false;
351
+ }
352
+ }
353
+ function sanitizeUrl(url) {
354
+ const dangerousProtocols = ["javascript:", "data:", "vbscript:"];
355
+ for (const protocol of dangerousProtocols) {
356
+ if (url.toLowerCase().startsWith(protocol)) return "about:blank";
357
+ }
358
+ return url;
359
+ }
360
+
361
+ // src/input.validator.ts
362
+ function isRequired(value) {
363
+ if (value === null || value === void 0) return false;
364
+ if (typeof value === "string") return value.trim().length > 0;
365
+ if (Array.isArray(value)) return value.length > 0;
366
+ return true;
367
+ }
368
+ function minLength(value, min) {
369
+ return value.length >= min;
370
+ }
371
+ function maxLength(value, max) {
372
+ return value.length <= max;
373
+ }
374
+ function exactLength(value, length) {
375
+ return value.length === length;
376
+ }
377
+ function isNumeric(value) {
378
+ return !isNaN(Number(value)) && !isNaN(parseFloat(value));
379
+ }
380
+ function inRange(value, min, max) {
381
+ return value >= min && value <= max;
382
+ }
383
+ function matchesPattern(value, pattern) {
384
+ return pattern.test(value);
385
+ }
386
+ function isInList(value, list) {
387
+ return list.includes(value);
170
388
  }
171
389
  // Annotate the CommonJS export names for ESM import in node:
172
390
  0 && (module.exports = {
173
391
  addressSchema,
392
+ calculatePasswordStrength,
174
393
  dateStringSchema,
175
394
  emailSchema,
395
+ exactLength,
396
+ extractCountryCode,
397
+ formatPhone,
398
+ inRange,
399
+ isCommonPassword,
400
+ isDisposableEmail,
401
+ isExternalUrl,
402
+ isInList,
403
+ isNumeric,
404
+ isRequired,
405
+ isValidEmail,
406
+ isValidEmailDomain,
407
+ isValidIndianMobile,
408
+ isValidIndianPincode,
409
+ isValidPhone,
410
+ isValidUrl,
411
+ isValidUrlWithProtocol,
412
+ matchesPattern,
413
+ maxLength,
176
414
  mediaUrlSchema,
415
+ meetsPasswordRequirements,
416
+ minLength,
417
+ normalizeEmail,
418
+ normalizePhone,
177
419
  objectIdSchema,
178
420
  paginationQuerySchema,
179
421
  passwordSchema,
180
422
  phoneSchema,
423
+ sanitizeUrl,
181
424
  setupZodErrorMap,
182
425
  urlSchema,
183
426
  zodErrorMap
package/dist/index.d.cts CHANGED
@@ -57,7 +57,70 @@ declare const addressSchema: z.ZodObject<{
57
57
  declare function zodErrorMap(issue: Parameters<Parameters<typeof z.setErrorMap>[0]>[0]): {
58
58
  message: string;
59
59
  };
60
+ declare global {
61
+ var __mohasinac_zod_applied__: boolean | undefined;
62
+ }
60
63
  /** Apply the custom error map globally. Safe to call multiple times. */
61
64
  declare function setupZodErrorMap(): void;
62
65
 
63
- export { addressSchema, dateStringSchema, emailSchema, mediaUrlSchema, objectIdSchema, paginationQuerySchema, passwordSchema, phoneSchema, setupZodErrorMap, urlSchema, zodErrorMap };
66
+ /**
67
+ * Email Validation Utilities
68
+ */
69
+ declare function isValidEmail(email: string): boolean;
70
+ declare function isValidEmailDomain(email: string, allowedDomains?: string[]): boolean;
71
+ declare function normalizeEmail(email: string): string;
72
+ declare function isDisposableEmail(email: string): boolean;
73
+
74
+ /**
75
+ * Password Validation Utilities
76
+ */
77
+ interface PasswordStrength {
78
+ score: number;
79
+ level: "too-weak" | "weak" | "fair" | "good" | "strong";
80
+ feedback: string[];
81
+ }
82
+ interface PasswordRequirements {
83
+ minLength: number;
84
+ requireUppercase: boolean;
85
+ requireLowercase: boolean;
86
+ requireNumbers: boolean;
87
+ requireSpecialChars: boolean;
88
+ }
89
+ declare function meetsPasswordRequirements(password: string, requirements?: PasswordRequirements): {
90
+ valid: boolean;
91
+ missing: string[];
92
+ };
93
+ declare function calculatePasswordStrength(password: string): PasswordStrength;
94
+ declare function isCommonPassword(password: string): boolean;
95
+
96
+ /**
97
+ * Phone Number Validation Utilities
98
+ */
99
+ declare function isValidPhone(phone: string): boolean;
100
+ declare function normalizePhone(phone: string): string;
101
+ declare function formatPhone(phone: string, countryCode?: string): string;
102
+ declare function extractCountryCode(phone: string): string | null;
103
+ declare function isValidIndianMobile(phone: string): boolean;
104
+ declare function isValidIndianPincode(pincode: string): boolean;
105
+
106
+ /**
107
+ * URL Validation Utilities
108
+ */
109
+ declare function isValidUrl(url: string): boolean;
110
+ declare function isValidUrlWithProtocol(url: string, protocols?: string[]): boolean;
111
+ declare function isExternalUrl(url: string, currentDomain?: string): boolean;
112
+ declare function sanitizeUrl(url: string): string;
113
+
114
+ /**
115
+ * General Input Validation Utilities
116
+ */
117
+ declare function isRequired(value: any): boolean;
118
+ declare function minLength(value: string, min: number): boolean;
119
+ declare function maxLength(value: string, max: number): boolean;
120
+ declare function exactLength(value: string, length: number): boolean;
121
+ declare function isNumeric(value: string): boolean;
122
+ declare function inRange(value: number, min: number, max: number): boolean;
123
+ declare function matchesPattern(value: string, pattern: RegExp): boolean;
124
+ declare function isInList<T>(value: T, list: T[]): boolean;
125
+
126
+ export { type PasswordRequirements, type PasswordStrength, addressSchema, calculatePasswordStrength, dateStringSchema, emailSchema, exactLength, extractCountryCode, formatPhone, inRange, isCommonPassword, isDisposableEmail, isExternalUrl, isInList, isNumeric, isRequired, isValidEmail, isValidEmailDomain, isValidIndianMobile, isValidIndianPincode, isValidPhone, isValidUrl, isValidUrlWithProtocol, matchesPattern, maxLength, mediaUrlSchema, meetsPasswordRequirements, minLength, normalizeEmail, normalizePhone, objectIdSchema, paginationQuerySchema, passwordSchema, phoneSchema, sanitizeUrl, setupZodErrorMap, urlSchema, zodErrorMap };
package/dist/index.d.ts CHANGED
@@ -57,7 +57,70 @@ declare const addressSchema: z.ZodObject<{
57
57
  declare function zodErrorMap(issue: Parameters<Parameters<typeof z.setErrorMap>[0]>[0]): {
58
58
  message: string;
59
59
  };
60
+ declare global {
61
+ var __mohasinac_zod_applied__: boolean | undefined;
62
+ }
60
63
  /** Apply the custom error map globally. Safe to call multiple times. */
61
64
  declare function setupZodErrorMap(): void;
62
65
 
63
- export { addressSchema, dateStringSchema, emailSchema, mediaUrlSchema, objectIdSchema, paginationQuerySchema, passwordSchema, phoneSchema, setupZodErrorMap, urlSchema, zodErrorMap };
66
+ /**
67
+ * Email Validation Utilities
68
+ */
69
+ declare function isValidEmail(email: string): boolean;
70
+ declare function isValidEmailDomain(email: string, allowedDomains?: string[]): boolean;
71
+ declare function normalizeEmail(email: string): string;
72
+ declare function isDisposableEmail(email: string): boolean;
73
+
74
+ /**
75
+ * Password Validation Utilities
76
+ */
77
+ interface PasswordStrength {
78
+ score: number;
79
+ level: "too-weak" | "weak" | "fair" | "good" | "strong";
80
+ feedback: string[];
81
+ }
82
+ interface PasswordRequirements {
83
+ minLength: number;
84
+ requireUppercase: boolean;
85
+ requireLowercase: boolean;
86
+ requireNumbers: boolean;
87
+ requireSpecialChars: boolean;
88
+ }
89
+ declare function meetsPasswordRequirements(password: string, requirements?: PasswordRequirements): {
90
+ valid: boolean;
91
+ missing: string[];
92
+ };
93
+ declare function calculatePasswordStrength(password: string): PasswordStrength;
94
+ declare function isCommonPassword(password: string): boolean;
95
+
96
+ /**
97
+ * Phone Number Validation Utilities
98
+ */
99
+ declare function isValidPhone(phone: string): boolean;
100
+ declare function normalizePhone(phone: string): string;
101
+ declare function formatPhone(phone: string, countryCode?: string): string;
102
+ declare function extractCountryCode(phone: string): string | null;
103
+ declare function isValidIndianMobile(phone: string): boolean;
104
+ declare function isValidIndianPincode(pincode: string): boolean;
105
+
106
+ /**
107
+ * URL Validation Utilities
108
+ */
109
+ declare function isValidUrl(url: string): boolean;
110
+ declare function isValidUrlWithProtocol(url: string, protocols?: string[]): boolean;
111
+ declare function isExternalUrl(url: string, currentDomain?: string): boolean;
112
+ declare function sanitizeUrl(url: string): string;
113
+
114
+ /**
115
+ * General Input Validation Utilities
116
+ */
117
+ declare function isRequired(value: any): boolean;
118
+ declare function minLength(value: string, min: number): boolean;
119
+ declare function maxLength(value: string, max: number): boolean;
120
+ declare function exactLength(value: string, length: number): boolean;
121
+ declare function isNumeric(value: string): boolean;
122
+ declare function inRange(value: number, min: number, max: number): boolean;
123
+ declare function matchesPattern(value: string, pattern: RegExp): boolean;
124
+ declare function isInList<T>(value: T, list: T[]): boolean;
125
+
126
+ export { type PasswordRequirements, type PasswordStrength, addressSchema, calculatePasswordStrength, dateStringSchema, emailSchema, exactLength, extractCountryCode, formatPhone, inRange, isCommonPassword, isDisposableEmail, isExternalUrl, isInList, isNumeric, isRequired, isValidEmail, isValidEmailDomain, isValidIndianMobile, isValidIndianPincode, isValidPhone, isValidUrl, isValidUrlWithProtocol, matchesPattern, maxLength, mediaUrlSchema, meetsPasswordRequirements, minLength, normalizeEmail, normalizePhone, objectIdSchema, paginationQuerySchema, passwordSchema, phoneSchema, sanitizeUrl, setupZodErrorMap, urlSchema, zodErrorMap };
package/dist/index.js CHANGED
@@ -126,21 +126,239 @@ function zodErrorMap(issue) {
126
126
  message: (_d = issue.message) != null ? _d : "Invalid value"
127
127
  };
128
128
  }
129
- var _applied = false;
130
129
  function setupZodErrorMap() {
131
- if (_applied) return;
130
+ if (globalThis.__mohasinac_zod_applied__) return;
132
131
  z2.setErrorMap(zodErrorMap);
133
- _applied = true;
132
+ globalThis.__mohasinac_zod_applied__ = true;
133
+ }
134
+
135
+ // src/email.validator.ts
136
+ function isValidEmail(email) {
137
+ const emailRegex = /^[^\s@]+@[^\s@.][^\s@]*[^\s@.]\.[^\s@]+$|^[^\s@]+@[^\s@.]\.[^\s@]+$/;
138
+ if (!emailRegex.test(email)) return false;
139
+ if (email.includes("..")) return false;
140
+ return true;
141
+ }
142
+ function isValidEmailDomain(email, allowedDomains) {
143
+ if (!isValidEmail(email)) return false;
144
+ if (!allowedDomains || allowedDomains.length === 0) return true;
145
+ const domain = email.split("@")[1].toLowerCase();
146
+ return allowedDomains.some((allowed) => domain === allowed.toLowerCase());
147
+ }
148
+ function normalizeEmail(email) {
149
+ return email.trim().toLowerCase();
150
+ }
151
+ function isDisposableEmail(email) {
152
+ var _a;
153
+ const disposableDomains = [
154
+ "tempmail.com",
155
+ "10minutemail.com",
156
+ "guerrillamail.com",
157
+ "mailinator.com",
158
+ "throwaway.email"
159
+ ];
160
+ const domain = (_a = email.split("@")[1]) == null ? void 0 : _a.toLowerCase();
161
+ return disposableDomains.includes(domain);
162
+ }
163
+
164
+ // src/password.validator.ts
165
+ var DEFAULT_REQUIREMENTS = {
166
+ minLength: 8,
167
+ requireUppercase: true,
168
+ requireLowercase: true,
169
+ requireNumbers: true,
170
+ requireSpecialChars: true
171
+ };
172
+ function meetsPasswordRequirements(password, requirements = DEFAULT_REQUIREMENTS) {
173
+ const missing = [];
174
+ if (password.length < requirements.minLength)
175
+ missing.push(`At least ${requirements.minLength} characters`);
176
+ if (requirements.requireUppercase && !/[A-Z]/.test(password))
177
+ missing.push("One uppercase letter");
178
+ if (requirements.requireLowercase && !/[a-z]/.test(password))
179
+ missing.push("One lowercase letter");
180
+ if (requirements.requireNumbers && !/\d/.test(password))
181
+ missing.push("One number");
182
+ if (requirements.requireSpecialChars && !/[!@#$%^&*(),.?":{}|<>]/.test(password))
183
+ missing.push("One special character");
184
+ return { valid: missing.length === 0, missing };
185
+ }
186
+ function calculatePasswordStrength(password) {
187
+ let score = 0;
188
+ const feedback = [];
189
+ if (password.length >= 8) score++;
190
+ if (password.length >= 12) score++;
191
+ if (password.length < 8) feedback.push("Password is too short");
192
+ if (/[a-z]/.test(password) && /[A-Z]/.test(password)) score++;
193
+ if (/\d/.test(password)) score++;
194
+ if (/[!@#$%^&*(),.?":{}|<>]/.test(password)) score++;
195
+ if (/(.)\1{2,}/.test(password)) {
196
+ score = Math.max(0, score - 1);
197
+ feedback.push("Avoid repeated characters");
198
+ }
199
+ if (/^(?:password|123456|qwerty)/i.test(password)) {
200
+ score = 0;
201
+ feedback.push("Avoid common passwords");
202
+ }
203
+ score = Math.min(4, Math.max(0, score));
204
+ const levels = ["too-weak", "weak", "fair", "good", "strong"];
205
+ return { score, level: levels[score], feedback };
206
+ }
207
+ function isCommonPassword(password) {
208
+ const commonPasswords = [
209
+ "password",
210
+ "123456",
211
+ "123456789",
212
+ "qwerty",
213
+ "abc123",
214
+ "monkey",
215
+ "1234567",
216
+ "letmein",
217
+ "trustno1",
218
+ "dragon",
219
+ "baseball",
220
+ "iloveyou",
221
+ "master",
222
+ "sunshine",
223
+ "ashley",
224
+ "bailey",
225
+ "passw0rd",
226
+ "shadow",
227
+ "123123",
228
+ "654321"
229
+ ];
230
+ return commonPasswords.includes(password.toLowerCase());
231
+ }
232
+
233
+ // src/phone.validator.ts
234
+ function isValidPhone(phone) {
235
+ const phoneRegex = /^\+?[\d\s-()]+$/;
236
+ const cleaned = phone.replace(/[\s-()]/g, "");
237
+ return phoneRegex.test(phone) && cleaned.length >= 10 && cleaned.length <= 15;
238
+ }
239
+ function normalizePhone(phone) {
240
+ return phone.replace(/[\s-()]/g, "");
241
+ }
242
+ function formatPhone(phone, countryCode = "US") {
243
+ const cleaned = normalizePhone(phone);
244
+ if (countryCode === "US" && cleaned.length === 10) {
245
+ return `(${cleaned.slice(0, 3)}) ${cleaned.slice(3, 6)}-${cleaned.slice(6)}`;
246
+ }
247
+ if (cleaned.startsWith("+")) return cleaned;
248
+ return `+${cleaned}`;
249
+ }
250
+ function extractCountryCode(phone) {
251
+ const cleaned = normalizePhone(phone);
252
+ if (!cleaned.startsWith("+")) return null;
253
+ const match = cleaned.match(/^\+(\d{1,3})/);
254
+ return match ? `+${match[1]}` : null;
255
+ }
256
+ function isValidIndianMobile(phone) {
257
+ const cleaned = normalizePhone(phone).replace(/^\+91/, "");
258
+ return /^[6-9]\d{9}$/.test(cleaned);
259
+ }
260
+ function isValidIndianPincode(pincode) {
261
+ return /^\d{6}$/.test(pincode.trim());
262
+ }
263
+
264
+ // src/url.validator.ts
265
+ function isValidUrl(url) {
266
+ try {
267
+ new URL(url);
268
+ return true;
269
+ } catch (e) {
270
+ return false;
271
+ }
272
+ }
273
+ function isValidUrlWithProtocol(url, protocols = ["http", "https"]) {
274
+ if (!isValidUrl(url)) return false;
275
+ try {
276
+ const urlObj = new URL(url);
277
+ return protocols.includes(urlObj.protocol.replace(":", ""));
278
+ } catch (e) {
279
+ return false;
280
+ }
281
+ }
282
+ function isExternalUrl(url, currentDomain) {
283
+ if (!isValidUrl(url)) return false;
284
+ try {
285
+ const urlObj = new URL(url);
286
+ const currentHost = currentDomain || (typeof window !== "undefined" ? window.location.hostname : "");
287
+ return urlObj.hostname !== currentHost;
288
+ } catch (e) {
289
+ return false;
290
+ }
291
+ }
292
+ function sanitizeUrl(url) {
293
+ const dangerousProtocols = ["javascript:", "data:", "vbscript:"];
294
+ for (const protocol of dangerousProtocols) {
295
+ if (url.toLowerCase().startsWith(protocol)) return "about:blank";
296
+ }
297
+ return url;
298
+ }
299
+
300
+ // src/input.validator.ts
301
+ function isRequired(value) {
302
+ if (value === null || value === void 0) return false;
303
+ if (typeof value === "string") return value.trim().length > 0;
304
+ if (Array.isArray(value)) return value.length > 0;
305
+ return true;
306
+ }
307
+ function minLength(value, min) {
308
+ return value.length >= min;
309
+ }
310
+ function maxLength(value, max) {
311
+ return value.length <= max;
312
+ }
313
+ function exactLength(value, length) {
314
+ return value.length === length;
315
+ }
316
+ function isNumeric(value) {
317
+ return !isNaN(Number(value)) && !isNaN(parseFloat(value));
318
+ }
319
+ function inRange(value, min, max) {
320
+ return value >= min && value <= max;
321
+ }
322
+ function matchesPattern(value, pattern) {
323
+ return pattern.test(value);
324
+ }
325
+ function isInList(value, list) {
326
+ return list.includes(value);
134
327
  }
135
328
  export {
136
329
  addressSchema,
330
+ calculatePasswordStrength,
137
331
  dateStringSchema,
138
332
  emailSchema,
333
+ exactLength,
334
+ extractCountryCode,
335
+ formatPhone,
336
+ inRange,
337
+ isCommonPassword,
338
+ isDisposableEmail,
339
+ isExternalUrl,
340
+ isInList,
341
+ isNumeric,
342
+ isRequired,
343
+ isValidEmail,
344
+ isValidEmailDomain,
345
+ isValidIndianMobile,
346
+ isValidIndianPincode,
347
+ isValidPhone,
348
+ isValidUrl,
349
+ isValidUrlWithProtocol,
350
+ matchesPattern,
351
+ maxLength,
139
352
  mediaUrlSchema,
353
+ meetsPasswordRequirements,
354
+ minLength,
355
+ normalizeEmail,
356
+ normalizePhone,
140
357
  objectIdSchema,
141
358
  paginationQuerySchema,
142
359
  passwordSchema,
143
360
  phoneSchema,
361
+ sanitizeUrl,
144
362
  setupZodErrorMap,
145
363
  urlSchema,
146
364
  zodErrorMap
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mohasinac/validation",
3
- "version": "0.1.0",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "publishConfig": {