zod-ir 1.1.2 → 1.2.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/README.md +51 -38
- package/dist/index.d.mts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<p>
|
|
7
7
|
A lightweight, TypeScript-first extension for Zod.
|
|
8
8
|
<br />
|
|
9
|
-
Compatible with React Hook Form, Next.js, and Node.js.
|
|
9
|
+
Compatible with React Hook Form, Next.js, NestJS, and Node.js.
|
|
10
10
|
</p>
|
|
11
11
|
|
|
12
12
|
<p>
|
|
@@ -27,11 +27,14 @@
|
|
|
27
27
|
## Features ✨
|
|
28
28
|
|
|
29
29
|
- ✅ **National Code:** Validates using the official checksum algorithm.
|
|
30
|
+
- 🏢 **Shenase Melli:** Validates Legal Person ID (Company ID).
|
|
30
31
|
- 💳 **Bank Card:** Validates 16-digit card numbers (Luhn algorithm).
|
|
31
32
|
- 📱 **Mobile Number:** Validates `09xx`, `+989xx`, `9xx`.
|
|
32
33
|
- 🏦 **Sheba (IBAN):** Validates structure and checksum (ISO 7064).
|
|
34
|
+
- ✈️ **Passport:** Validates Iranian Passport numbers.
|
|
33
35
|
- 📮 **Postal Code:** Validates 10-digit Iranian postal codes.
|
|
34
36
|
- ☎️ **Landline:** Validates fixed line numbers with area codes.
|
|
37
|
+
- 🔄 **Auto-fix Digits:** Helper to automatically convert Persian/Arabic digits to English.
|
|
35
38
|
- 🌍 **Bilingual:** Built-in error messages in **Persian** and **English**.
|
|
36
39
|
|
|
37
40
|
---
|
|
@@ -46,51 +49,52 @@ yarn add zod zod-ir
|
|
|
46
49
|
|
|
47
50
|
## Usage 🚀
|
|
48
51
|
|
|
49
|
-
1. Basic Validation
|
|
52
|
+
1. Basic Validation & Auto-Fix
|
|
53
|
+
This example shows how to validate a form and automatically convert Persian digits (e.g., ۰۹۱۲) to English.
|
|
50
54
|
|
|
51
55
|
```typescript
|
|
52
56
|
import { z } from "zod";
|
|
53
57
|
import {
|
|
54
58
|
zMelliCode,
|
|
55
|
-
|
|
59
|
+
zShenaseMelli,
|
|
56
60
|
zIranianMobile,
|
|
57
61
|
zCardNumber,
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
zSheba,
|
|
63
|
+
zPassport,
|
|
64
|
+
preprocessNumber,
|
|
60
65
|
} from "zod-ir";
|
|
61
66
|
|
|
62
67
|
const UserSchema = z.object({
|
|
63
|
-
//
|
|
64
|
-
nationalCode: zMelliCode(),
|
|
68
|
+
// 1. National Code with Auto-Fix (Converts ۱۲۳ -> 123)
|
|
69
|
+
nationalCode: preprocessNumber(zMelliCode()),
|
|
65
70
|
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
strictZero: true,
|
|
69
|
-
message: "شماره موبایل اشتباه است",
|
|
70
|
-
}),
|
|
71
|
+
// 2. Company ID (Shenase Melli)
|
|
72
|
+
companyId: zShenaseMelli({ message: "شناسه ملی نامعتبر است" }),
|
|
71
73
|
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
+
// 3. Mobile (Strict Mode: Must start with 0)
|
|
75
|
+
mobile: zIranianMobile({ strictZero: true }),
|
|
74
76
|
|
|
75
|
-
// Bank Card
|
|
77
|
+
// 4. Bank Card
|
|
76
78
|
card: zCardNumber(),
|
|
77
79
|
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
+
// 5. Sheba (IBAN) - English Error
|
|
81
|
+
iban: zSheba({ locale: "en" }),
|
|
80
82
|
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
+
// 6. Passport
|
|
84
|
+
passport: zPassport(),
|
|
83
85
|
});
|
|
84
86
|
|
|
87
|
+
// Example Usage
|
|
85
88
|
try {
|
|
86
|
-
UserSchema.parse({
|
|
87
|
-
nationalCode: "
|
|
89
|
+
const result = UserSchema.parse({
|
|
90
|
+
nationalCode: "۱۲۳۴۵۶۷۸۹۱", // User typed in Farsi
|
|
91
|
+
companyId: "10100448712",
|
|
88
92
|
mobile: "09121234567",
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
phone: "02122334455",
|
|
93
|
+
card: "6362147010005732",
|
|
94
|
+
iban: "IR330620000000202901868005",
|
|
95
|
+
passport: "A12345678",
|
|
93
96
|
});
|
|
97
|
+
console.log("Valid Data:", result);
|
|
94
98
|
} catch (err) {
|
|
95
99
|
console.log(err);
|
|
96
100
|
}
|
|
@@ -102,10 +106,11 @@ try {
|
|
|
102
106
|
import { useForm } from "react-hook-form";
|
|
103
107
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
104
108
|
import { z } from "zod";
|
|
105
|
-
import { zMelliCode } from "zod-ir";
|
|
109
|
+
import { zMelliCode, preprocessNumber } from "zod-ir";
|
|
106
110
|
|
|
107
111
|
const schema = z.object({
|
|
108
|
-
|
|
112
|
+
// Automatically fixes Persian digits typed by user
|
|
113
|
+
nationalId: preprocessNumber(zMelliCode({ message: "کد ملی صحیح نیست" })),
|
|
109
114
|
});
|
|
110
115
|
|
|
111
116
|
export default function MyForm() {
|
|
@@ -119,8 +124,12 @@ export default function MyForm() {
|
|
|
119
124
|
|
|
120
125
|
return (
|
|
121
126
|
<form onSubmit={handleSubmit((d) => console.log(d))}>
|
|
122
|
-
<input
|
|
123
|
-
|
|
127
|
+
<input
|
|
128
|
+
{...register("nationalId")}
|
|
129
|
+
placeholder="کد ملی (حتی فارسی)"
|
|
130
|
+
dir="auto"
|
|
131
|
+
/>
|
|
132
|
+
<p style={{ color: "red" }}>{errors.nationalId?.message}</p>
|
|
124
133
|
<button type="submit">Submit</button>
|
|
125
134
|
</form>
|
|
126
135
|
);
|
|
@@ -129,23 +138,27 @@ export default function MyForm() {
|
|
|
129
138
|
|
|
130
139
|
## API Reference 📚
|
|
131
140
|
|
|
132
|
-
| Validator
|
|
133
|
-
|
|
|
134
|
-
| `zMelliCode`
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
137
|
-
| `
|
|
138
|
-
| `
|
|
139
|
-
| `
|
|
141
|
+
| Validator | Description |
|
|
142
|
+
| :----------------- | :----------------------------------------------------------------- |
|
|
143
|
+
| `zMelliCode` | Validates Iranian National Code (Melli Code). |
|
|
144
|
+
| `zShenaseMelli` | Validates Legal Person ID (Company ID). |
|
|
145
|
+
| `zCardNumber` | Validates 16-digit bank card numbers (Luhn). |
|
|
146
|
+
| `zIranianMobile` | Validates Iranian mobile numbers. |
|
|
147
|
+
| `zSheba` | Validates IBAN (Sheba) structure and checksum. |
|
|
148
|
+
| `zPassport` | Validates Iranian Passport numbers. |
|
|
149
|
+
| `zPostalCode` | Validates 10-digit Iranian postal codes. |
|
|
150
|
+
| `zLandline` | Validates landline phone numbers with area codes. |
|
|
151
|
+
| `preprocessNumber` | Utility: Wraps any validator to convert Persian digits to English. |
|
|
140
152
|
|
|
141
153
|
#### Options Interface
|
|
154
|
+
|
|
142
155
|
All validators accept an optional configuration object to customize behavior.
|
|
143
156
|
|
|
144
157
|
| Name | Type | Description |
|
|
145
158
|
| :----------- | :-------------------- | :--------------------------------------------------------- |
|
|
146
159
|
| `message` | `string` | Custom error message to display when validation fails. |
|
|
147
160
|
| `locale` | `"fa"`, `"en"` | Language for the default error message (defaults to "fa"). |
|
|
148
|
-
| `strictZero` | `boolean`, `optional` | (Mobile Only)
|
|
161
|
+
| `strictZero` | `boolean`, `optional` | (Mobile Only) If true, input must start with 0. |
|
|
149
162
|
|
|
150
163
|
## License
|
|
151
164
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
3
|
declare function isMelliCode(code: string): boolean;
|
|
4
|
+
declare function isShenaseMelli(code: string): boolean;
|
|
5
|
+
declare function isPassport(code: string): boolean;
|
|
4
6
|
declare function isCardNumber(code: string): boolean;
|
|
5
7
|
interface MobileValidationOptions {
|
|
6
8
|
strictZero?: boolean | "optional";
|
|
@@ -9,10 +11,13 @@ declare function isIranianMobile(mobile: string, { strictZero }?: MobileValidati
|
|
|
9
11
|
declare function isSheba(code: string): boolean;
|
|
10
12
|
declare function isPostalCode(code: string): boolean;
|
|
11
13
|
declare function isLandline(code: string): boolean;
|
|
14
|
+
declare function verifyAndNormalize(value: string): string;
|
|
12
15
|
|
|
13
16
|
declare const ERROR_MESSAGES: {
|
|
14
17
|
readonly fa: {
|
|
15
18
|
readonly melliCode: "کد ملی نامعتبر است";
|
|
19
|
+
readonly shenaseMelli: "شناسه ملی نامعتبر است";
|
|
20
|
+
readonly passport: "شماره گذرنامه نامعتبر است";
|
|
16
21
|
readonly cardNumber: "شماره کارت نامعتبر است";
|
|
17
22
|
readonly mobile: "شماره موبایل نامعتبر است";
|
|
18
23
|
readonly sheba: "شماره شبا نامعتبر است";
|
|
@@ -21,6 +26,8 @@ declare const ERROR_MESSAGES: {
|
|
|
21
26
|
};
|
|
22
27
|
readonly en: {
|
|
23
28
|
readonly melliCode: "Invalid national code";
|
|
29
|
+
readonly shenaseMelli: "Invalid legal person ID (Shenase Melli)";
|
|
30
|
+
readonly passport: "Invalid passport number";
|
|
24
31
|
readonly cardNumber: "Invalid card number";
|
|
25
32
|
readonly mobile: "Invalid mobile number";
|
|
26
33
|
readonly sheba: "Invalid Sheba (IBAN) number";
|
|
@@ -35,6 +42,8 @@ interface BaseOptions {
|
|
|
35
42
|
}
|
|
36
43
|
|
|
37
44
|
declare const zMelliCode: (options?: BaseOptions) => z.ZodString;
|
|
45
|
+
declare const zShenaseMelli: (options?: BaseOptions) => z.ZodString;
|
|
46
|
+
declare const zPassport: (options?: BaseOptions) => z.ZodString;
|
|
38
47
|
declare const zCardNumber: (options?: BaseOptions) => z.ZodString;
|
|
39
48
|
interface MobileOptions extends BaseOptions {
|
|
40
49
|
strictZero?: boolean | "optional";
|
|
@@ -43,5 +52,6 @@ declare const zIranianMobile: (options?: MobileOptions) => z.ZodString;
|
|
|
43
52
|
declare const zSheba: (options?: BaseOptions) => z.ZodString;
|
|
44
53
|
declare const zPostalCode: (options?: BaseOptions) => z.ZodString;
|
|
45
54
|
declare const zLandline: (options?: BaseOptions) => z.ZodString;
|
|
55
|
+
declare const preprocessNumber: (schema: z.ZodTypeAny) => z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
46
56
|
|
|
47
|
-
export { isCardNumber, isIranianMobile, isLandline, isMelliCode, isPostalCode, isSheba, zCardNumber, zIranianMobile, zLandline, zMelliCode, zPostalCode, zSheba };
|
|
57
|
+
export { isCardNumber, isIranianMobile, isLandline, isMelliCode, isPassport, isPostalCode, isSheba, isShenaseMelli, preprocessNumber, verifyAndNormalize, zCardNumber, zIranianMobile, zLandline, zMelliCode, zPassport, zPostalCode, zSheba, zShenaseMelli };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
3
|
declare function isMelliCode(code: string): boolean;
|
|
4
|
+
declare function isShenaseMelli(code: string): boolean;
|
|
5
|
+
declare function isPassport(code: string): boolean;
|
|
4
6
|
declare function isCardNumber(code: string): boolean;
|
|
5
7
|
interface MobileValidationOptions {
|
|
6
8
|
strictZero?: boolean | "optional";
|
|
@@ -9,10 +11,13 @@ declare function isIranianMobile(mobile: string, { strictZero }?: MobileValidati
|
|
|
9
11
|
declare function isSheba(code: string): boolean;
|
|
10
12
|
declare function isPostalCode(code: string): boolean;
|
|
11
13
|
declare function isLandline(code: string): boolean;
|
|
14
|
+
declare function verifyAndNormalize(value: string): string;
|
|
12
15
|
|
|
13
16
|
declare const ERROR_MESSAGES: {
|
|
14
17
|
readonly fa: {
|
|
15
18
|
readonly melliCode: "کد ملی نامعتبر است";
|
|
19
|
+
readonly shenaseMelli: "شناسه ملی نامعتبر است";
|
|
20
|
+
readonly passport: "شماره گذرنامه نامعتبر است";
|
|
16
21
|
readonly cardNumber: "شماره کارت نامعتبر است";
|
|
17
22
|
readonly mobile: "شماره موبایل نامعتبر است";
|
|
18
23
|
readonly sheba: "شماره شبا نامعتبر است";
|
|
@@ -21,6 +26,8 @@ declare const ERROR_MESSAGES: {
|
|
|
21
26
|
};
|
|
22
27
|
readonly en: {
|
|
23
28
|
readonly melliCode: "Invalid national code";
|
|
29
|
+
readonly shenaseMelli: "Invalid legal person ID (Shenase Melli)";
|
|
30
|
+
readonly passport: "Invalid passport number";
|
|
24
31
|
readonly cardNumber: "Invalid card number";
|
|
25
32
|
readonly mobile: "Invalid mobile number";
|
|
26
33
|
readonly sheba: "Invalid Sheba (IBAN) number";
|
|
@@ -35,6 +42,8 @@ interface BaseOptions {
|
|
|
35
42
|
}
|
|
36
43
|
|
|
37
44
|
declare const zMelliCode: (options?: BaseOptions) => z.ZodString;
|
|
45
|
+
declare const zShenaseMelli: (options?: BaseOptions) => z.ZodString;
|
|
46
|
+
declare const zPassport: (options?: BaseOptions) => z.ZodString;
|
|
38
47
|
declare const zCardNumber: (options?: BaseOptions) => z.ZodString;
|
|
39
48
|
interface MobileOptions extends BaseOptions {
|
|
40
49
|
strictZero?: boolean | "optional";
|
|
@@ -43,5 +52,6 @@ declare const zIranianMobile: (options?: MobileOptions) => z.ZodString;
|
|
|
43
52
|
declare const zSheba: (options?: BaseOptions) => z.ZodString;
|
|
44
53
|
declare const zPostalCode: (options?: BaseOptions) => z.ZodString;
|
|
45
54
|
declare const zLandline: (options?: BaseOptions) => z.ZodString;
|
|
55
|
+
declare const preprocessNumber: (schema: z.ZodTypeAny) => z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
46
56
|
|
|
47
|
-
export { isCardNumber, isIranianMobile, isLandline, isMelliCode, isPostalCode, isSheba, zCardNumber, zIranianMobile, zLandline, zMelliCode, zPostalCode, zSheba };
|
|
57
|
+
export { isCardNumber, isIranianMobile, isLandline, isMelliCode, isPassport, isPostalCode, isSheba, isShenaseMelli, preprocessNumber, verifyAndNormalize, zCardNumber, zIranianMobile, zLandline, zMelliCode, zPassport, zPostalCode, zSheba, zShenaseMelli };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var p=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var M=Object.getOwnPropertyNames;var C=Object.prototype.hasOwnProperty;var O=(t,e)=>{for(var n in e)p(t,n,{get:e[n],enumerable:!0})},B=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of M(e))!C.call(t,r)&&r!==n&&p(t,r,{get:()=>e[r],enumerable:!(s=S(e,r))||s.enumerable});return t};var z=t=>B(p({},"__esModule",{value:!0}),t);var Z={};O(Z,{isCardNumber:()=>u,isIranianMobile:()=>d,isLandline:()=>x,isMelliCode:()=>c,isPassport:()=>f,isPostalCode:()=>m,isSheba:()=>b,isShenaseMelli:()=>g,preprocessNumber:()=>L,verifyAndNormalize:()=>h,zCardNumber:()=>N,zIranianMobile:()=>A,zLandline:()=>k,zMelliCode:()=>y,zPassport:()=>E,zPostalCode:()=>P,zSheba:()=>v,zShenaseMelli:()=>R});module.exports=z(Z);var o=require("zod");function c(t){if(!/^\d{10}$/.test(t)||/^(\d)\1+$/.test(t))return!1;let e=parseInt(t[9]),n=t.substring(0,9).split("").reduce((s,r,i)=>s+parseInt(r)*(10-i),0)%11;return n<2?e===n:e===11-n}function g(t){if(t.length!==11||!/^\d{11}$/.test(t))return!1;let e=parseInt(t[9]),n=parseInt(t[10]),s=[29,27,23,19,17,29,27,23,19,17],r=0;for(let l=0;l<10;l++){let I=parseInt(t[l]);r+=(I+e+2)*s[l]}let i=r%11;return(i===10?0:i)===n}function f(t){return/^[A-Za-z][0-9]{8,9}$/.test(t)}function u(t){let e=t.replace(/[\-\s]/g,"");if(!/^\d{16}$/.test(e))return!1;let n=0,s=!1;for(let r=e.length-1;r>=0;r--){let i=parseInt(e[r]);s&&(i*=2,i>9&&(i-=9)),n+=i,s=!s}return n%10===0}function d(t,{strictZero:e="optional"}={}){let n="9\\d{9}",s="";return e===!0?s=`^0${n}$`:e===!1?s=`^${n}$`:s=`^(?:0|\\+98)?${n}$`,new RegExp(s).test(t)}function b(t){let e=t.toUpperCase().replace(/[\-\s]/g,"");if(e.length!==26||!e.startsWith("IR"))return!1;let s=(e.substring(4)+e.substring(0,4)).split("").map(r=>{let i=r.charCodeAt(0);return i>=48&&i<=57?r:(i-55).toString()}).join("");try{return BigInt(s)%BigInt(97)===BigInt(1)}catch{return!1}}function m(t){return/^[1-9]\d{9}$/.test(t)}function x(t){return/^0\d{2}\d{8}$/.test(t)}function h(t){return t.replace(/[۰-۹]/g,e=>"\u06F0\u06F1\u06F2\u06F3\u06F4\u06F5\u06F6\u06F7\u06F8\u06F9".indexOf(e).toString()).replace(/[٠-٩]/g,e=>"\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669".indexOf(e).toString())}var $={fa:{melliCode:"\u06A9\u062F \u0645\u0644\u06CC \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0633\u062A",shenaseMelli:"\u0634\u0646\u0627\u0633\u0647 \u0645\u0644\u06CC \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0633\u062A",passport:"\u0634\u0645\u0627\u0631\u0647 \u06AF\u0630\u0631\u0646\u0627\u0645\u0647 \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0633\u062A",cardNumber:"\u0634\u0645\u0627\u0631\u0647 \u06A9\u0627\u0631\u062A \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0633\u062A",mobile:"\u0634\u0645\u0627\u0631\u0647 \u0645\u0648\u0628\u0627\u06CC\u0644 \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0633\u062A",sheba:"\u0634\u0645\u0627\u0631\u0647 \u0634\u0628\u0627 \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0633\u062A",postalCode:"\u06A9\u062F \u067E\u0633\u062A\u06CC \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0633\u062A",landline:"\u0634\u0645\u0627\u0631\u0647 \u062A\u0644\u0641\u0646 \u062B\u0627\u0628\u062A \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0633\u062A"},en:{melliCode:"Invalid national code",shenaseMelli:"Invalid legal person ID (Shenase Melli)",passport:"Invalid passport number",cardNumber:"Invalid card number",mobile:"Invalid mobile number",sheba:"Invalid Sheba (IBAN) number",postalCode:"Invalid postal code",landline:"Invalid landline number"}},a=(t,e)=>{if(e?.message)return e.message;let n=e?.locale||"fa";return $[n][t]};var y=t=>o.z.string().refine(e=>c(e),{message:a("melliCode",t)}),R=t=>o.z.string().refine(e=>g(e),{message:a("shenaseMelli",t)}),E=t=>o.z.string().refine(e=>f(e),{message:a("passport",t)}),N=t=>o.z.string().refine(e=>u(e),{message:a("cardNumber",t)}),A=t=>o.z.string().refine(e=>d(e,{strictZero:t?.strictZero}),{message:a("mobile",t)}),v=t=>o.z.string().refine(e=>b(e),{message:a("sheba",t)}),P=t=>o.z.string().refine(e=>m(e),{message:a("postalCode",t)}),k=t=>o.z.string().refine(e=>x(e),{message:a("landline",t)}),L=t=>o.z.preprocess(e=>typeof e=="string"?h(e):e,t);0&&(module.exports={isCardNumber,isIranianMobile,isLandline,isMelliCode,isPassport,isPostalCode,isSheba,isShenaseMelli,preprocessNumber,verifyAndNormalize,zCardNumber,zIranianMobile,zLandline,zMelliCode,zPassport,zPostalCode,zSheba,zShenaseMelli});
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/constants.ts"],"sourcesContent":["import { z } from \"zod\";\nimport {\n isMelliCode,\n isCardNumber,\n isIranianMobile,\n isSheba,\n isPostalCode,\n isLandline,\n} from \"./utils\";\nimport { getMessage, BaseOptions } from \"./constants\";\n\nexport const zMelliCode = (options?: BaseOptions) =>\n z.string().refine((val) => isMelliCode(val), {\n message: getMessage(\"melliCode\", options),\n });\n\nexport const zCardNumber = (options?: BaseOptions) =>\n z.string().refine((val) => isCardNumber(val), {\n message: getMessage(\"cardNumber\", options),\n });\n\ninterface MobileOptions extends BaseOptions {\n strictZero?: boolean | \"optional\";\n}\n\nexport const zIranianMobile = (options?: MobileOptions) =>\n z\n .string()\n .refine(\n (val) => isIranianMobile(val, { strictZero: options?.strictZero }),\n {\n message: getMessage(\"mobile\", options),\n }\n );\n\nexport const zSheba = (options?: BaseOptions) =>\n z.string().refine((val) => isSheba(val), {\n message: getMessage(\"sheba\", options),\n });\n\nexport const zPostalCode = (options?: BaseOptions) =>\n z.string().refine((val) => isPostalCode(val), {\n message: getMessage(\"postalCode\", options),\n });\n\nexport const zLandline = (options?: BaseOptions) =>\n z.string().refine((val) => isLandline(val), {\n message: getMessage(\"landline\", options),\n });\n\nexport {\n isMelliCode,\n isCardNumber,\n isIranianMobile,\n isSheba,\n isPostalCode,\n isLandline,\n};\n","export function isMelliCode(code: string): boolean {\n if (!/^\\d{10}$/.test(code)) return false;\n if (/^(\\d)\\1+$/.test(code)) return false;\n\n const check = parseInt(code[9]);\n const sum =\n code\n .substring(0, 9)\n .split(\"\")\n .reduce((acc, x, i) => acc + parseInt(x) * (10 - i), 0) % 11;\n\n return sum < 2 ? check === sum : check === 11 - sum;\n}\n\nexport function isCardNumber(code: string): boolean {\n const sanitized = code.replace(/[\\-\\s]/g, \"\");\n if (!/^\\d{16}$/.test(sanitized)) return false;\n\n let sum = 0;\n let shouldDouble = false;\n\n for (let i = sanitized.length - 1; i >= 0; i--) {\n let digit = parseInt(sanitized[i]);\n\n if (shouldDouble) {\n digit *= 2;\n if (digit > 9) digit -= 9;\n }\n\n sum += digit;\n shouldDouble = !shouldDouble;\n }\n\n return sum % 10 === 0;\n}\n\ninterface MobileValidationOptions {\n strictZero?: boolean | \"optional\";\n}\n\nexport function isIranianMobile(\n mobile: string,\n { strictZero = \"optional\" }: MobileValidationOptions = {}\n): boolean {\n const corePattern = \"9\\\\d{9}\";\n let pattern = \"\";\n\n if (strictZero === true) {\n pattern = `^0${corePattern}$`;\n } else if (strictZero === false) {\n pattern = `^${corePattern}$`;\n } else {\n pattern = `^(?:0|\\\\+98)?${corePattern}$`;\n }\n\n return new RegExp(pattern).test(mobile);\n}\n\nexport function isSheba(code: string): boolean {\n const iban = code.toUpperCase().replace(/[\\-\\s]/g, \"\");\n\n if (iban.length !== 26 || !iban.startsWith(\"IR\")) return false;\n\n const newStr = iban.substring(4) + iban.substring(0, 4);\n\n const numericString = newStr\n .split(\"\")\n .map((char) => {\n const code = char.charCodeAt(0);\n return code >= 48 && code <= 57 ? char : (code - 55).toString();\n })\n .join(\"\");\n\n try {\n const remainder = BigInt(numericString) % BigInt(97);\n return remainder === BigInt(1);\n } catch {\n return false;\n }\n}\n\nexport function isPostalCode(code: string): boolean {\n return /^[1-9]\\d{9}$/.test(code);\n}\n\nexport function isLandline(code: string): boolean {\n return /^0\\d{2}\\d{8}$/.test(code);\n}\n","export const ERROR_MESSAGES = {\n fa: {\n melliCode: \"کد ملی نامعتبر است\",\n cardNumber: \"شماره کارت نامعتبر است\",\n mobile: \"شماره موبایل نامعتبر است\",\n sheba: \"شماره شبا نامعتبر است\",\n postalCode: \"کد پستی نامعتبر است\",\n landline: \"شماره تلفن ثابت نامعتبر است\",\n },\n en: {\n melliCode: \"Invalid national code\",\n cardNumber: \"Invalid card number\",\n mobile: \"Invalid mobile number\",\n sheba: \"Invalid Sheba (IBAN) number\",\n postalCode: \"Invalid postal code\",\n landline: \"Invalid landline number\",\n },\n} as const;\n\nexport type Language = keyof typeof ERROR_MESSAGES;\n\nexport interface BaseOptions {\n message?: string;\n locale?: Language;\n}\n\nexport const getMessage = (\n key: keyof (typeof ERROR_MESSAGES)[\"fa\"],\n options?: BaseOptions\n): string => {\n if (options?.message) return options.message;\n const lang = options?.locale || \"fa\";\n return ERROR_MESSAGES[lang][key];\n};\n"],"mappings":"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","names":["index_exports","__export","isCardNumber","isIranianMobile","isLandline","isMelliCode","isPostalCode","isSheba","zCardNumber","zIranianMobile","zLandline","zMelliCode","zPostalCode","zSheba","__toCommonJS","import_zod","isMelliCode","code","check","sum","acc","x","i","isCardNumber","sanitized","shouldDouble","digit","isIranianMobile","mobile","strictZero","corePattern","pattern","isSheba","iban","numericString","char","isPostalCode","isLandline","ERROR_MESSAGES","getMessage","key","options","lang","zMelliCode","options","val","isMelliCode","getMessage","zCardNumber","isCardNumber","zIranianMobile","isIranianMobile","zSheba","isSheba","zPostalCode","isPostalCode","zLandline","isLandline"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/constants.ts"],"sourcesContent":["import { z } from \"zod\";\nimport {\n isMelliCode,\n isShenaseMelli,\n isPassport,\n isCardNumber,\n isIranianMobile,\n isSheba,\n isPostalCode,\n isLandline,\n verifyAndNormalize,\n} from \"./utils\";\nimport { getMessage, BaseOptions } from \"./constants\";\n\nexport const zMelliCode = (options?: BaseOptions) =>\n z.string().refine((val) => isMelliCode(val), {\n message: getMessage(\"melliCode\", options),\n });\n\nexport const zShenaseMelli = (options?: BaseOptions) =>\n z.string().refine((val) => isShenaseMelli(val), {\n message: getMessage(\"shenaseMelli\", options),\n });\n\nexport const zPassport = (options?: BaseOptions) =>\n z.string().refine((val) => isPassport(val), {\n message: getMessage(\"passport\", options),\n });\n\nexport const zCardNumber = (options?: BaseOptions) =>\n z.string().refine((val) => isCardNumber(val), {\n message: getMessage(\"cardNumber\", options),\n });\n\ninterface MobileOptions extends BaseOptions {\n strictZero?: boolean | \"optional\";\n}\n\nexport const zIranianMobile = (options?: MobileOptions) =>\n z\n .string()\n .refine(\n (val) => isIranianMobile(val, { strictZero: options?.strictZero }),\n {\n message: getMessage(\"mobile\", options),\n }\n );\n\nexport const zSheba = (options?: BaseOptions) =>\n z.string().refine((val) => isSheba(val), {\n message: getMessage(\"sheba\", options),\n });\n\nexport const zPostalCode = (options?: BaseOptions) =>\n z.string().refine((val) => isPostalCode(val), {\n message: getMessage(\"postalCode\", options),\n });\n\nexport const zLandline = (options?: BaseOptions) =>\n z.string().refine((val) => isLandline(val), {\n message: getMessage(\"landline\", options),\n });\n\nexport const preprocessNumber = (schema: z.ZodTypeAny) =>\n z.preprocess((val) => {\n if (typeof val === \"string\") {\n return verifyAndNormalize(val);\n }\n return val;\n }, schema);\n\nexport {\n isMelliCode,\n isShenaseMelli,\n isPassport,\n isCardNumber,\n isIranianMobile,\n isSheba,\n isPostalCode,\n isLandline,\n verifyAndNormalize,\n};\n","export function isMelliCode(code: string): boolean {\n if (!/^\\d{10}$/.test(code)) return false;\n if (/^(\\d)\\1+$/.test(code)) return false;\n\n const check = parseInt(code[9]);\n const sum =\n code\n .substring(0, 9)\n .split(\"\")\n .reduce((acc, x, i) => acc + parseInt(x) * (10 - i), 0) % 11;\n\n return sum < 2 ? check === sum : check === 11 - sum;\n}\n\nexport function isShenaseMelli(code: string): boolean {\n if (code.length !== 11 || !/^\\d{11}$/.test(code)) return false;\n\n const tenth = parseInt(code[9]);\n const inputCheck = parseInt(code[10]);\n const coefficients = [29, 27, 23, 19, 17, 29, 27, 23, 19, 17];\n\n let sum = 0;\n for (let i = 0; i < 10; i++) {\n const digit = parseInt(code[i]);\n sum += (digit + tenth + 2) * coefficients[i];\n }\n\n const remainder = sum % 11;\n const calculatedCheck = remainder === 10 ? 0 : remainder;\n\n return calculatedCheck === inputCheck;\n}\n\nexport function isPassport(code: string): boolean {\n return /^[A-Za-z][0-9]{8,9}$/.test(code);\n}\n\nexport function isCardNumber(code: string): boolean {\n const sanitized = code.replace(/[\\-\\s]/g, \"\");\n if (!/^\\d{16}$/.test(sanitized)) return false;\n\n let sum = 0;\n let shouldDouble = false;\n for (let i = sanitized.length - 1; i >= 0; i--) {\n let digit = parseInt(sanitized[i]);\n if (shouldDouble) {\n digit *= 2;\n if (digit > 9) digit -= 9;\n }\n sum += digit;\n shouldDouble = !shouldDouble;\n }\n return sum % 10 === 0;\n}\n\ninterface MobileValidationOptions {\n strictZero?: boolean | \"optional\";\n}\n\nexport function isIranianMobile(\n mobile: string,\n { strictZero = \"optional\" }: MobileValidationOptions = {}\n): boolean {\n const corePattern = \"9\\\\d{9}\";\n let pattern = \"\";\n if (strictZero === true) pattern = `^0${corePattern}$`;\n else if (strictZero === false) pattern = `^${corePattern}$`;\n else pattern = `^(?:0|\\\\+98)?${corePattern}$`;\n\n return new RegExp(pattern).test(mobile);\n}\n\nexport function isSheba(code: string): boolean {\n const iban = code.toUpperCase().replace(/[\\-\\s]/g, \"\");\n if (iban.length !== 26 || !iban.startsWith(\"IR\")) return false;\n\n const newStr = iban.substring(4) + iban.substring(0, 4);\n const numericString = newStr\n .split(\"\")\n .map((c) => {\n const code = c.charCodeAt(0);\n return code >= 48 && code <= 57 ? c : (code - 55).toString();\n })\n .join(\"\");\n\n try {\n return BigInt(numericString) % BigInt(97) === BigInt(1);\n } catch {\n return false;\n }\n}\n\nexport function isPostalCode(code: string): boolean {\n return /^[1-9]\\d{9}$/.test(code);\n}\n\nexport function isLandline(code: string): boolean {\n return /^0\\d{2}\\d{8}$/.test(code);\n}\n\nexport function verifyAndNormalize(value: string): string {\n return value\n .replace(/[۰-۹]/g, (d) => \"۰۱۲۳۴۵۶۷۸۹\".indexOf(d).toString())\n .replace(/[٠-٩]/g, (d) => \"٠١٢٣٤٥٦٧٨٩\".indexOf(d).toString());\n}\n","export const ERROR_MESSAGES = {\n fa: {\n melliCode: \"کد ملی نامعتبر است\",\n shenaseMelli: \"شناسه ملی نامعتبر است\",\n passport: \"شماره گذرنامه نامعتبر است\",\n cardNumber: \"شماره کارت نامعتبر است\",\n mobile: \"شماره موبایل نامعتبر است\",\n sheba: \"شماره شبا نامعتبر است\",\n postalCode: \"کد پستی نامعتبر است\",\n landline: \"شماره تلفن ثابت نامعتبر است\",\n },\n en: {\n melliCode: \"Invalid national code\",\n shenaseMelli: \"Invalid legal person ID (Shenase Melli)\",\n passport: \"Invalid passport number\",\n cardNumber: \"Invalid card number\",\n mobile: \"Invalid mobile number\",\n sheba: \"Invalid Sheba (IBAN) number\",\n postalCode: \"Invalid postal code\",\n landline: \"Invalid landline number\",\n },\n} as const;\n\nexport type Language = keyof typeof ERROR_MESSAGES;\n\nexport interface BaseOptions {\n message?: string;\n locale?: Language;\n}\n\nexport const getMessage = (\n key: keyof typeof ERROR_MESSAGES[\"fa\"],\n options?: BaseOptions\n): string => {\n if (options?.message) return options.message;\n const lang = options?.locale || \"fa\";\n return ERROR_MESSAGES[lang][key];\n};"],"mappings":"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","names":["index_exports","__export","isCardNumber","isIranianMobile","isLandline","isMelliCode","isPassport","isPostalCode","isSheba","isShenaseMelli","preprocessNumber","verifyAndNormalize","zCardNumber","zIranianMobile","zLandline","zMelliCode","zPassport","zPostalCode","zSheba","zShenaseMelli","__toCommonJS","import_zod","isMelliCode","code","check","sum","acc","x","isShenaseMelli","tenth","inputCheck","coefficients","i","digit","remainder","isPassport","isCardNumber","sanitized","shouldDouble","isIranianMobile","mobile","strictZero","corePattern","pattern","isSheba","iban","numericString","c","isPostalCode","isLandline","verifyAndNormalize","value","d","ERROR_MESSAGES","getMessage","key","options","lang","zMelliCode","options","val","isMelliCode","getMessage","zShenaseMelli","isShenaseMelli","zPassport","isPassport","zCardNumber","isCardNumber","zIranianMobile","isIranianMobile","zSheba","isSheba","zPostalCode","isPostalCode","zLandline","isLandline","preprocessNumber","schema","verifyAndNormalize"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{z as a}from"zod";function
|
|
1
|
+
import{z as a}from"zod";function p(e){if(!/^\d{10}$/.test(e)||/^(\d)\1+$/.test(e))return!1;let t=parseInt(e[9]),n=e.substring(0,9).split("").reduce((s,i,r)=>s+parseInt(i)*(10-r),0)%11;return n<2?t===n:t===11-n}function c(e){if(e.length!==11||!/^\d{11}$/.test(e))return!1;let t=parseInt(e[9]),n=parseInt(e[10]),s=[29,27,23,19,17,29,27,23,19,17],i=0;for(let l=0;l<10;l++){let h=parseInt(e[l]);i+=(h+t+2)*s[l]}let r=i%11;return(r===10?0:r)===n}function g(e){return/^[A-Za-z][0-9]{8,9}$/.test(e)}function f(e){let t=e.replace(/[\-\s]/g,"");if(!/^\d{16}$/.test(t))return!1;let n=0,s=!1;for(let i=t.length-1;i>=0;i--){let r=parseInt(t[i]);s&&(r*=2,r>9&&(r-=9)),n+=r,s=!s}return n%10===0}function u(e,{strictZero:t="optional"}={}){let n="9\\d{9}",s="";return t===!0?s=`^0${n}$`:t===!1?s=`^${n}$`:s=`^(?:0|\\+98)?${n}$`,new RegExp(s).test(e)}function d(e){let t=e.toUpperCase().replace(/[\-\s]/g,"");if(t.length!==26||!t.startsWith("IR"))return!1;let s=(t.substring(4)+t.substring(0,4)).split("").map(i=>{let r=i.charCodeAt(0);return r>=48&&r<=57?i:(r-55).toString()}).join("");try{return BigInt(s)%BigInt(97)===BigInt(1)}catch{return!1}}function b(e){return/^[1-9]\d{9}$/.test(e)}function m(e){return/^0\d{2}\d{8}$/.test(e)}function x(e){return e.replace(/[۰-۹]/g,t=>"\u06F0\u06F1\u06F2\u06F3\u06F4\u06F5\u06F6\u06F7\u06F8\u06F9".indexOf(t).toString()).replace(/[٠-٩]/g,t=>"\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669".indexOf(t).toString())}var I={fa:{melliCode:"\u06A9\u062F \u0645\u0644\u06CC \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0633\u062A",shenaseMelli:"\u0634\u0646\u0627\u0633\u0647 \u0645\u0644\u06CC \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0633\u062A",passport:"\u0634\u0645\u0627\u0631\u0647 \u06AF\u0630\u0631\u0646\u0627\u0645\u0647 \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0633\u062A",cardNumber:"\u0634\u0645\u0627\u0631\u0647 \u06A9\u0627\u0631\u062A \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0633\u062A",mobile:"\u0634\u0645\u0627\u0631\u0647 \u0645\u0648\u0628\u0627\u06CC\u0644 \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0633\u062A",sheba:"\u0634\u0645\u0627\u0631\u0647 \u0634\u0628\u0627 \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0633\u062A",postalCode:"\u06A9\u062F \u067E\u0633\u062A\u06CC \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0633\u062A",landline:"\u0634\u0645\u0627\u0631\u0647 \u062A\u0644\u0641\u0646 \u062B\u0627\u0628\u062A \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0633\u062A"},en:{melliCode:"Invalid national code",shenaseMelli:"Invalid legal person ID (Shenase Melli)",passport:"Invalid passport number",cardNumber:"Invalid card number",mobile:"Invalid mobile number",sheba:"Invalid Sheba (IBAN) number",postalCode:"Invalid postal code",landline:"Invalid landline number"}},o=(e,t)=>{if(t?.message)return t.message;let n=t?.locale||"fa";return I[n][e]};var y=e=>a.string().refine(t=>p(t),{message:o("melliCode",e)}),R=e=>a.string().refine(t=>c(t),{message:o("shenaseMelli",e)}),E=e=>a.string().refine(t=>g(t),{message:o("passport",e)}),N=e=>a.string().refine(t=>f(t),{message:o("cardNumber",e)}),A=e=>a.string().refine(t=>u(t,{strictZero:e?.strictZero}),{message:o("mobile",e)}),v=e=>a.string().refine(t=>d(t),{message:o("sheba",e)}),P=e=>a.string().refine(t=>b(t),{message:o("postalCode",e)}),k=e=>a.string().refine(t=>m(t),{message:o("landline",e)}),L=e=>a.preprocess(t=>typeof t=="string"?x(t):t,e);export{f as isCardNumber,u as isIranianMobile,m as isLandline,p as isMelliCode,g as isPassport,b as isPostalCode,d as isSheba,c as isShenaseMelli,L as preprocessNumber,x as verifyAndNormalize,N as zCardNumber,A as zIranianMobile,k as zLandline,y as zMelliCode,E as zPassport,P as zPostalCode,v as zSheba,R as zShenaseMelli};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/constants.ts"],"sourcesContent":["import { z } from \"zod\";\nimport {\n isMelliCode,\n isCardNumber,\n isIranianMobile,\n isSheba,\n isPostalCode,\n isLandline,\n} from \"./utils\";\nimport { getMessage, BaseOptions } from \"./constants\";\n\nexport const zMelliCode = (options?: BaseOptions) =>\n z.string().refine((val) => isMelliCode(val), {\n message: getMessage(\"melliCode\", options),\n });\n\nexport const zCardNumber = (options?: BaseOptions) =>\n z.string().refine((val) => isCardNumber(val), {\n message: getMessage(\"cardNumber\", options),\n });\n\ninterface MobileOptions extends BaseOptions {\n strictZero?: boolean | \"optional\";\n}\n\nexport const zIranianMobile = (options?: MobileOptions) =>\n z\n .string()\n .refine(\n (val) => isIranianMobile(val, { strictZero: options?.strictZero }),\n {\n message: getMessage(\"mobile\", options),\n }\n );\n\nexport const zSheba = (options?: BaseOptions) =>\n z.string().refine((val) => isSheba(val), {\n message: getMessage(\"sheba\", options),\n });\n\nexport const zPostalCode = (options?: BaseOptions) =>\n z.string().refine((val) => isPostalCode(val), {\n message: getMessage(\"postalCode\", options),\n });\n\nexport const zLandline = (options?: BaseOptions) =>\n z.string().refine((val) => isLandline(val), {\n message: getMessage(\"landline\", options),\n });\n\nexport {\n isMelliCode,\n isCardNumber,\n isIranianMobile,\n isSheba,\n isPostalCode,\n isLandline,\n};\n","export function isMelliCode(code: string): boolean {\n if (!/^\\d{10}$/.test(code)) return false;\n if (/^(\\d)\\1+$/.test(code)) return false;\n\n const check = parseInt(code[9]);\n const sum =\n code\n .substring(0, 9)\n .split(\"\")\n .reduce((acc, x, i) => acc + parseInt(x) * (10 - i), 0) % 11;\n\n return sum < 2 ? check === sum : check === 11 - sum;\n}\n\nexport function isCardNumber(code: string): boolean {\n const sanitized = code.replace(/[\\-\\s]/g, \"\");\n if (!/^\\d{16}$/.test(sanitized)) return false;\n\n let sum = 0;\n let shouldDouble = false;\n\n for (let i = sanitized.length - 1; i >= 0; i--) {\n let digit = parseInt(sanitized[i]);\n\n if (shouldDouble) {\n digit *= 2;\n if (digit > 9) digit -= 9;\n }\n\n sum += digit;\n shouldDouble = !shouldDouble;\n }\n\n return sum % 10 === 0;\n}\n\ninterface MobileValidationOptions {\n strictZero?: boolean | \"optional\";\n}\n\nexport function isIranianMobile(\n mobile: string,\n { strictZero = \"optional\" }: MobileValidationOptions = {}\n): boolean {\n const corePattern = \"9\\\\d{9}\";\n let pattern = \"\";\n\n if (strictZero === true) {\n pattern = `^0${corePattern}$`;\n } else if (strictZero === false) {\n pattern = `^${corePattern}$`;\n } else {\n pattern = `^(?:0|\\\\+98)?${corePattern}$`;\n }\n\n return new RegExp(pattern).test(mobile);\n}\n\nexport function isSheba(code: string): boolean {\n const iban = code.toUpperCase().replace(/[\\-\\s]/g, \"\");\n\n if (iban.length !== 26 || !iban.startsWith(\"IR\")) return false;\n\n const newStr = iban.substring(4) + iban.substring(0, 4);\n\n const numericString = newStr\n .split(\"\")\n .map((char) => {\n const code = char.charCodeAt(0);\n return code >= 48 && code <= 57 ? char : (code - 55).toString();\n })\n .join(\"\");\n\n try {\n const remainder = BigInt(numericString) % BigInt(97);\n return remainder === BigInt(1);\n } catch {\n return false;\n }\n}\n\nexport function isPostalCode(code: string): boolean {\n return /^[1-9]\\d{9}$/.test(code);\n}\n\nexport function isLandline(code: string): boolean {\n return /^0\\d{2}\\d{8}$/.test(code);\n}\n","export const ERROR_MESSAGES = {\n fa: {\n melliCode: \"کد ملی نامعتبر است\",\n cardNumber: \"شماره کارت نامعتبر است\",\n mobile: \"شماره موبایل نامعتبر است\",\n sheba: \"شماره شبا نامعتبر است\",\n postalCode: \"کد پستی نامعتبر است\",\n landline: \"شماره تلفن ثابت نامعتبر است\",\n },\n en: {\n melliCode: \"Invalid national code\",\n cardNumber: \"Invalid card number\",\n mobile: \"Invalid mobile number\",\n sheba: \"Invalid Sheba (IBAN) number\",\n postalCode: \"Invalid postal code\",\n landline: \"Invalid landline number\",\n },\n} as const;\n\nexport type Language = keyof typeof ERROR_MESSAGES;\n\nexport interface BaseOptions {\n message?: string;\n locale?: Language;\n}\n\nexport const getMessage = (\n key: keyof (typeof ERROR_MESSAGES)[\"fa\"],\n options?: BaseOptions\n): string => {\n if (options?.message) return options.message;\n const lang = options?.locale || \"fa\";\n return ERROR_MESSAGES[lang][key];\n};\n"],"mappings":"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","names":["z","isMelliCode","code","check","sum","acc","x","isCardNumber","sanitized","shouldDouble","i","digit","isIranianMobile","mobile","strictZero","corePattern","pattern","isSheba","iban","numericString","char","isPostalCode","isLandline","ERROR_MESSAGES","getMessage","key","options","lang","zMelliCode","options","z","val","isMelliCode","getMessage","zCardNumber","isCardNumber","zIranianMobile","isIranianMobile","zSheba","isSheba","zPostalCode","isPostalCode","zLandline","isLandline"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/constants.ts"],"sourcesContent":["import { z } from \"zod\";\nimport {\n isMelliCode,\n isShenaseMelli,\n isPassport,\n isCardNumber,\n isIranianMobile,\n isSheba,\n isPostalCode,\n isLandline,\n verifyAndNormalize,\n} from \"./utils\";\nimport { getMessage, BaseOptions } from \"./constants\";\n\nexport const zMelliCode = (options?: BaseOptions) =>\n z.string().refine((val) => isMelliCode(val), {\n message: getMessage(\"melliCode\", options),\n });\n\nexport const zShenaseMelli = (options?: BaseOptions) =>\n z.string().refine((val) => isShenaseMelli(val), {\n message: getMessage(\"shenaseMelli\", options),\n });\n\nexport const zPassport = (options?: BaseOptions) =>\n z.string().refine((val) => isPassport(val), {\n message: getMessage(\"passport\", options),\n });\n\nexport const zCardNumber = (options?: BaseOptions) =>\n z.string().refine((val) => isCardNumber(val), {\n message: getMessage(\"cardNumber\", options),\n });\n\ninterface MobileOptions extends BaseOptions {\n strictZero?: boolean | \"optional\";\n}\n\nexport const zIranianMobile = (options?: MobileOptions) =>\n z\n .string()\n .refine(\n (val) => isIranianMobile(val, { strictZero: options?.strictZero }),\n {\n message: getMessage(\"mobile\", options),\n }\n );\n\nexport const zSheba = (options?: BaseOptions) =>\n z.string().refine((val) => isSheba(val), {\n message: getMessage(\"sheba\", options),\n });\n\nexport const zPostalCode = (options?: BaseOptions) =>\n z.string().refine((val) => isPostalCode(val), {\n message: getMessage(\"postalCode\", options),\n });\n\nexport const zLandline = (options?: BaseOptions) =>\n z.string().refine((val) => isLandline(val), {\n message: getMessage(\"landline\", options),\n });\n\nexport const preprocessNumber = (schema: z.ZodTypeAny) =>\n z.preprocess((val) => {\n if (typeof val === \"string\") {\n return verifyAndNormalize(val);\n }\n return val;\n }, schema);\n\nexport {\n isMelliCode,\n isShenaseMelli,\n isPassport,\n isCardNumber,\n isIranianMobile,\n isSheba,\n isPostalCode,\n isLandline,\n verifyAndNormalize,\n};\n","export function isMelliCode(code: string): boolean {\n if (!/^\\d{10}$/.test(code)) return false;\n if (/^(\\d)\\1+$/.test(code)) return false;\n\n const check = parseInt(code[9]);\n const sum =\n code\n .substring(0, 9)\n .split(\"\")\n .reduce((acc, x, i) => acc + parseInt(x) * (10 - i), 0) % 11;\n\n return sum < 2 ? check === sum : check === 11 - sum;\n}\n\nexport function isShenaseMelli(code: string): boolean {\n if (code.length !== 11 || !/^\\d{11}$/.test(code)) return false;\n\n const tenth = parseInt(code[9]);\n const inputCheck = parseInt(code[10]);\n const coefficients = [29, 27, 23, 19, 17, 29, 27, 23, 19, 17];\n\n let sum = 0;\n for (let i = 0; i < 10; i++) {\n const digit = parseInt(code[i]);\n sum += (digit + tenth + 2) * coefficients[i];\n }\n\n const remainder = sum % 11;\n const calculatedCheck = remainder === 10 ? 0 : remainder;\n\n return calculatedCheck === inputCheck;\n}\n\nexport function isPassport(code: string): boolean {\n return /^[A-Za-z][0-9]{8,9}$/.test(code);\n}\n\nexport function isCardNumber(code: string): boolean {\n const sanitized = code.replace(/[\\-\\s]/g, \"\");\n if (!/^\\d{16}$/.test(sanitized)) return false;\n\n let sum = 0;\n let shouldDouble = false;\n for (let i = sanitized.length - 1; i >= 0; i--) {\n let digit = parseInt(sanitized[i]);\n if (shouldDouble) {\n digit *= 2;\n if (digit > 9) digit -= 9;\n }\n sum += digit;\n shouldDouble = !shouldDouble;\n }\n return sum % 10 === 0;\n}\n\ninterface MobileValidationOptions {\n strictZero?: boolean | \"optional\";\n}\n\nexport function isIranianMobile(\n mobile: string,\n { strictZero = \"optional\" }: MobileValidationOptions = {}\n): boolean {\n const corePattern = \"9\\\\d{9}\";\n let pattern = \"\";\n if (strictZero === true) pattern = `^0${corePattern}$`;\n else if (strictZero === false) pattern = `^${corePattern}$`;\n else pattern = `^(?:0|\\\\+98)?${corePattern}$`;\n\n return new RegExp(pattern).test(mobile);\n}\n\nexport function isSheba(code: string): boolean {\n const iban = code.toUpperCase().replace(/[\\-\\s]/g, \"\");\n if (iban.length !== 26 || !iban.startsWith(\"IR\")) return false;\n\n const newStr = iban.substring(4) + iban.substring(0, 4);\n const numericString = newStr\n .split(\"\")\n .map((c) => {\n const code = c.charCodeAt(0);\n return code >= 48 && code <= 57 ? c : (code - 55).toString();\n })\n .join(\"\");\n\n try {\n return BigInt(numericString) % BigInt(97) === BigInt(1);\n } catch {\n return false;\n }\n}\n\nexport function isPostalCode(code: string): boolean {\n return /^[1-9]\\d{9}$/.test(code);\n}\n\nexport function isLandline(code: string): boolean {\n return /^0\\d{2}\\d{8}$/.test(code);\n}\n\nexport function verifyAndNormalize(value: string): string {\n return value\n .replace(/[۰-۹]/g, (d) => \"۰۱۲۳۴۵۶۷۸۹\".indexOf(d).toString())\n .replace(/[٠-٩]/g, (d) => \"٠١٢٣٤٥٦٧٨٩\".indexOf(d).toString());\n}\n","export const ERROR_MESSAGES = {\n fa: {\n melliCode: \"کد ملی نامعتبر است\",\n shenaseMelli: \"شناسه ملی نامعتبر است\",\n passport: \"شماره گذرنامه نامعتبر است\",\n cardNumber: \"شماره کارت نامعتبر است\",\n mobile: \"شماره موبایل نامعتبر است\",\n sheba: \"شماره شبا نامعتبر است\",\n postalCode: \"کد پستی نامعتبر است\",\n landline: \"شماره تلفن ثابت نامعتبر است\",\n },\n en: {\n melliCode: \"Invalid national code\",\n shenaseMelli: \"Invalid legal person ID (Shenase Melli)\",\n passport: \"Invalid passport number\",\n cardNumber: \"Invalid card number\",\n mobile: \"Invalid mobile number\",\n sheba: \"Invalid Sheba (IBAN) number\",\n postalCode: \"Invalid postal code\",\n landline: \"Invalid landline number\",\n },\n} as const;\n\nexport type Language = keyof typeof ERROR_MESSAGES;\n\nexport interface BaseOptions {\n message?: string;\n locale?: Language;\n}\n\nexport const getMessage = (\n key: keyof typeof ERROR_MESSAGES[\"fa\"],\n options?: BaseOptions\n): string => {\n if (options?.message) return options.message;\n const lang = options?.locale || \"fa\";\n return ERROR_MESSAGES[lang][key];\n};"],"mappings":"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","names":["z","isMelliCode","code","check","sum","acc","x","i","isShenaseMelli","tenth","inputCheck","coefficients","digit","remainder","isPassport","isCardNumber","sanitized","shouldDouble","isIranianMobile","mobile","strictZero","corePattern","pattern","isSheba","iban","numericString","c","isPostalCode","isLandline","verifyAndNormalize","value","d","ERROR_MESSAGES","getMessage","key","options","lang","zMelliCode","options","z","val","isMelliCode","getMessage","zShenaseMelli","isShenaseMelli","zPassport","isPassport","zCardNumber","isCardNumber","zIranianMobile","isIranianMobile","zSheba","isSheba","zPostalCode","isPostalCode","zLandline","isLandline","preprocessNumber","schema","verifyAndNormalize"]}
|