zod-ir 1.0.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/README.md +24 -11
- package/dist/index.d.mts +13 -34
- package/dist/index.d.ts +13 -34
- 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
|
@@ -1,18 +1,31 @@
|
|
|
1
1
|
# Zod Iranian Utils 🇮🇷
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<div align="center">
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- 📱 **Mobile Number** validation (supports +98, 09xx, 9xx).
|
|
10
|
-
- 🌍 **Bilingual Error Messages** (Persian & English).
|
|
11
|
-
- 🌲 **Tree-shakable** & Type-safe.
|
|
9
|
+
**A lightweight, type-safe Zod extension for validating Iranian specific data.**
|
|
10
|
+
Compatible with **React Hook Form**, **Next.js**, and Node.js backends.
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
## Features ✨
|
|
15
|
+
|
|
16
|
+
- ✅ **National Code:** Official checksum validation.
|
|
17
|
+
- 💳 **Bank Card:** 16-digit Luhn algorithm check.
|
|
18
|
+
- 📱 **Mobile Number:** Supports `09xx`, `+989xx`, `9xx`.
|
|
19
|
+
- 🏦 **Sheba (IBAN):** ISO 7064 structure validation.
|
|
20
|
+
- 📮 **Postal Code:** Iranian 10-digit postal code format.
|
|
21
|
+
- ☎️ **Landline:** Fixed line validation with area code.
|
|
22
|
+
- 🌍 **Bilingual:** Built-in Persian & English error messages.
|
|
23
|
+
- 🌲 **Tree-shakable:** Minimal bundle size.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Installation 📦
|
|
14
28
|
|
|
15
29
|
```bash
|
|
16
|
-
npm install zod zod-
|
|
17
|
-
|
|
18
|
-
yarn add zod zod-iranian-utils
|
|
30
|
+
npm install zod zod-ir
|
|
31
|
+
```
|
package/dist/index.d.mts
CHANGED
|
@@ -1,68 +1,47 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Validates Iranian National Code (Melli Code) based on the official algorithm.
|
|
5
|
-
* @param code The 10-digit national code string.
|
|
6
|
-
*/
|
|
7
3
|
declare function isMelliCode(code: string): boolean;
|
|
8
|
-
/**
|
|
9
|
-
* Validates Bank Card Number using the Luhn algorithm.
|
|
10
|
-
* @param code The 16-digit card number.
|
|
11
|
-
*/
|
|
12
4
|
declare function isCardNumber(code: string): boolean;
|
|
13
5
|
interface MobileValidationOptions {
|
|
14
|
-
/**
|
|
15
|
-
* strictZero:
|
|
16
|
-
* - true: Must start with 0 (e.g., 0912...)
|
|
17
|
-
* - false: Must NOT start with 0 (e.g., 912...)
|
|
18
|
-
* - "optional": Both are accepted (default)
|
|
19
|
-
*/
|
|
20
6
|
strictZero?: boolean | "optional";
|
|
21
7
|
}
|
|
22
|
-
/**
|
|
23
|
-
* Validates Iranian Mobile Number.
|
|
24
|
-
* Supports 09xx, 9xx, and +989xx formats.
|
|
25
|
-
*/
|
|
26
8
|
declare function isIranianMobile(mobile: string, { strictZero }?: MobileValidationOptions): boolean;
|
|
9
|
+
declare function isSheba(code: string): boolean;
|
|
10
|
+
declare function isPostalCode(code: string): boolean;
|
|
11
|
+
declare function isLandline(code: string): boolean;
|
|
27
12
|
|
|
28
|
-
/**
|
|
29
|
-
* Default error messages for validation failures.
|
|
30
|
-
* Supports Persian (fa) and English (en).
|
|
31
|
-
*/
|
|
32
13
|
declare const ERROR_MESSAGES: {
|
|
33
14
|
readonly fa: {
|
|
34
15
|
readonly melliCode: "کد ملی نامعتبر است";
|
|
35
16
|
readonly cardNumber: "شماره کارت نامعتبر است";
|
|
36
17
|
readonly mobile: "شماره موبایل نامعتبر است";
|
|
18
|
+
readonly sheba: "شماره شبا نامعتبر است";
|
|
19
|
+
readonly postalCode: "کد پستی نامعتبر است";
|
|
20
|
+
readonly landline: "شماره تلفن ثابت نامعتبر است";
|
|
37
21
|
};
|
|
38
22
|
readonly en: {
|
|
39
23
|
readonly melliCode: "Invalid national code";
|
|
40
24
|
readonly cardNumber: "Invalid card number";
|
|
41
25
|
readonly mobile: "Invalid mobile number";
|
|
26
|
+
readonly sheba: "Invalid Sheba (IBAN) number";
|
|
27
|
+
readonly postalCode: "Invalid postal code";
|
|
28
|
+
readonly landline: "Invalid landline number";
|
|
42
29
|
};
|
|
43
30
|
};
|
|
44
31
|
type Language = keyof typeof ERROR_MESSAGES;
|
|
45
32
|
interface BaseOptions {
|
|
46
|
-
/** Custom error message to override the default one */
|
|
47
33
|
message?: string;
|
|
48
|
-
/** Language for the default error message (default: 'fa') */
|
|
49
34
|
locale?: Language;
|
|
50
35
|
}
|
|
51
36
|
|
|
52
|
-
/**
|
|
53
|
-
* Zod schema for validating Iranian National Code (Melli Code).
|
|
54
|
-
*/
|
|
55
37
|
declare const zMelliCode: (options?: BaseOptions) => z.ZodString;
|
|
56
|
-
/**
|
|
57
|
-
* Zod schema for validating Iranian Bank Card Numbers (Luhn Algorithm).
|
|
58
|
-
*/
|
|
59
38
|
declare const zCardNumber: (options?: BaseOptions) => z.ZodString;
|
|
60
39
|
interface MobileOptions extends BaseOptions {
|
|
61
40
|
strictZero?: boolean | "optional";
|
|
62
41
|
}
|
|
63
|
-
/**
|
|
64
|
-
* Zod schema for validating Iranian Mobile Numbers.
|
|
65
|
-
*/
|
|
66
42
|
declare const zIranianMobile: (options?: MobileOptions) => z.ZodString;
|
|
43
|
+
declare const zSheba: (options?: BaseOptions) => z.ZodString;
|
|
44
|
+
declare const zPostalCode: (options?: BaseOptions) => z.ZodString;
|
|
45
|
+
declare const zLandline: (options?: BaseOptions) => z.ZodString;
|
|
67
46
|
|
|
68
|
-
export { isCardNumber, isIranianMobile, isMelliCode, zCardNumber, zIranianMobile, zMelliCode };
|
|
47
|
+
export { isCardNumber, isIranianMobile, isLandline, isMelliCode, isPostalCode, isSheba, zCardNumber, zIranianMobile, zLandline, zMelliCode, zPostalCode, zSheba };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,68 +1,47 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Validates Iranian National Code (Melli Code) based on the official algorithm.
|
|
5
|
-
* @param code The 10-digit national code string.
|
|
6
|
-
*/
|
|
7
3
|
declare function isMelliCode(code: string): boolean;
|
|
8
|
-
/**
|
|
9
|
-
* Validates Bank Card Number using the Luhn algorithm.
|
|
10
|
-
* @param code The 16-digit card number.
|
|
11
|
-
*/
|
|
12
4
|
declare function isCardNumber(code: string): boolean;
|
|
13
5
|
interface MobileValidationOptions {
|
|
14
|
-
/**
|
|
15
|
-
* strictZero:
|
|
16
|
-
* - true: Must start with 0 (e.g., 0912...)
|
|
17
|
-
* - false: Must NOT start with 0 (e.g., 912...)
|
|
18
|
-
* - "optional": Both are accepted (default)
|
|
19
|
-
*/
|
|
20
6
|
strictZero?: boolean | "optional";
|
|
21
7
|
}
|
|
22
|
-
/**
|
|
23
|
-
* Validates Iranian Mobile Number.
|
|
24
|
-
* Supports 09xx, 9xx, and +989xx formats.
|
|
25
|
-
*/
|
|
26
8
|
declare function isIranianMobile(mobile: string, { strictZero }?: MobileValidationOptions): boolean;
|
|
9
|
+
declare function isSheba(code: string): boolean;
|
|
10
|
+
declare function isPostalCode(code: string): boolean;
|
|
11
|
+
declare function isLandline(code: string): boolean;
|
|
27
12
|
|
|
28
|
-
/**
|
|
29
|
-
* Default error messages for validation failures.
|
|
30
|
-
* Supports Persian (fa) and English (en).
|
|
31
|
-
*/
|
|
32
13
|
declare const ERROR_MESSAGES: {
|
|
33
14
|
readonly fa: {
|
|
34
15
|
readonly melliCode: "کد ملی نامعتبر است";
|
|
35
16
|
readonly cardNumber: "شماره کارت نامعتبر است";
|
|
36
17
|
readonly mobile: "شماره موبایل نامعتبر است";
|
|
18
|
+
readonly sheba: "شماره شبا نامعتبر است";
|
|
19
|
+
readonly postalCode: "کد پستی نامعتبر است";
|
|
20
|
+
readonly landline: "شماره تلفن ثابت نامعتبر است";
|
|
37
21
|
};
|
|
38
22
|
readonly en: {
|
|
39
23
|
readonly melliCode: "Invalid national code";
|
|
40
24
|
readonly cardNumber: "Invalid card number";
|
|
41
25
|
readonly mobile: "Invalid mobile number";
|
|
26
|
+
readonly sheba: "Invalid Sheba (IBAN) number";
|
|
27
|
+
readonly postalCode: "Invalid postal code";
|
|
28
|
+
readonly landline: "Invalid landline number";
|
|
42
29
|
};
|
|
43
30
|
};
|
|
44
31
|
type Language = keyof typeof ERROR_MESSAGES;
|
|
45
32
|
interface BaseOptions {
|
|
46
|
-
/** Custom error message to override the default one */
|
|
47
33
|
message?: string;
|
|
48
|
-
/** Language for the default error message (default: 'fa') */
|
|
49
34
|
locale?: Language;
|
|
50
35
|
}
|
|
51
36
|
|
|
52
|
-
/**
|
|
53
|
-
* Zod schema for validating Iranian National Code (Melli Code).
|
|
54
|
-
*/
|
|
55
37
|
declare const zMelliCode: (options?: BaseOptions) => z.ZodString;
|
|
56
|
-
/**
|
|
57
|
-
* Zod schema for validating Iranian Bank Card Numbers (Luhn Algorithm).
|
|
58
|
-
*/
|
|
59
38
|
declare const zCardNumber: (options?: BaseOptions) => z.ZodString;
|
|
60
39
|
interface MobileOptions extends BaseOptions {
|
|
61
40
|
strictZero?: boolean | "optional";
|
|
62
41
|
}
|
|
63
|
-
/**
|
|
64
|
-
* Zod schema for validating Iranian Mobile Numbers.
|
|
65
|
-
*/
|
|
66
42
|
declare const zIranianMobile: (options?: MobileOptions) => z.ZodString;
|
|
43
|
+
declare const zSheba: (options?: BaseOptions) => z.ZodString;
|
|
44
|
+
declare const zPostalCode: (options?: BaseOptions) => z.ZodString;
|
|
45
|
+
declare const zLandline: (options?: BaseOptions) => z.ZodString;
|
|
67
46
|
|
|
68
|
-
export { isCardNumber, isIranianMobile, isMelliCode, zCardNumber, zIranianMobile, zMelliCode };
|
|
47
|
+
export { isCardNumber, isIranianMobile, isLandline, isMelliCode, isPostalCode, isSheba, zCardNumber, zIranianMobile, zLandline, zMelliCode, zPostalCode, zSheba };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var l=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var
|
|
1
|
+
"use strict";var l=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var C=Object.prototype.hasOwnProperty;var I=(t,e)=>{for(var n in e)l(t,n,{get:e[n],enumerable:!0})},O=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of x(e))!C.call(t,r)&&r!==n&&l(t,r,{get:()=>e[r],enumerable:!(s=m(e,r))||s.enumerable});return t};var M=t=>O(l({},"__esModule",{value:!0}),t);var N={};I(N,{isCardNumber:()=>f,isIranianMobile:()=>d,isLandline:()=>g,isMelliCode:()=>p,isPostalCode:()=>b,isSheba:()=>u,zCardNumber:()=>R,zIranianMobile:()=>$,zLandline:()=>z,zMelliCode:()=>h,zPostalCode:()=>E,zSheba:()=>B});module.exports=M(N);var a=require("zod");function p(t){if(!/^\d{10}$/.test(t))return!1;let e=parseInt(t[9]);if(/^(\d)\1+$/.test(t))return!1;let 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 f(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 u(t){let e=t.toUpperCase().replace(/[\-\s]/g,"");if(e.length!==26||!e.startsWith("IR"))return!1;let n=e.substring(4)+"1827"+e.substring(2,4),s=Array.from(n).map(r=>parseInt(r,36)).reduce((r,i)=>{let c=(i<10,i);return(+(r+""+c)%97).toString()},"");return parseInt(s)===1}function b(t){return!(!/^\d{10}$/.test(t)||t.startsWith("0"))}function g(t){return/^0\d{2}\d{8}$/.test(t)}var S={fa:{melliCode:"\u06A9\u062F \u0645\u0644\u06CC \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",cardNumber:"Invalid card number",mobile:"Invalid mobile number",sheba:"Invalid Sheba (IBAN) number",postalCode:"Invalid postal code",landline:"Invalid landline number"}},o=(t,e)=>{if(e?.message)return e.message;let n=e?.locale||"fa";return S[n][t]};var h=t=>a.z.string().refine(e=>p(e),{message:o("melliCode",t)}),R=t=>a.z.string().refine(e=>f(e),{message:o("cardNumber",t)}),$=t=>a.z.string().refine(e=>d(e,{strictZero:t?.strictZero}),{message:o("mobile",t)}),B=t=>a.z.string().refine(e=>u(e),{message:o("sheba",t)}),E=t=>a.z.string().refine(e=>b(e),{message:o("postalCode",t)}),z=t=>a.z.string().refine(e=>g(e),{message:o("landline",t)});0&&(module.exports={isCardNumber,isIranianMobile,isLandline,isMelliCode,isPostalCode,isSheba,zCardNumber,zIranianMobile,zLandline,zMelliCode,zPostalCode,zSheba});
|
|
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 {
|
|
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\n const check = parseInt(code[9]);\n if (/^(\\d)\\1+$/.test(code)) return false;\n\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) return false;\n if (!iban.startsWith(\"IR\")) return false;\n\n const newStr = iban.substring(4) + \"1827\" + iban.substring(2, 4);\n\n const remainder = Array.from(newStr)\n .map((c) => parseInt(c, 36))\n .reduce((remainder, value) => {\n const v = value < 10 ? value : value;\n return (Number(remainder + \"\" + v) % 97).toString();\n }, \"\");\n\n return parseInt(remainder) === 1;\n}\n\nexport function isPostalCode(code: string): boolean {\n if (!/^\\d{10}$/.test(code)) return false;\n if (code.startsWith(\"0\")) return false;\n return true;\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","isCardNumber","sanitized","shouldDouble","i","digit","isIranianMobile","mobile","strictZero","corePattern","pattern","isSheba","iban","newStr","remainder","c","value","v","isPostalCode","isLandline","ERROR_MESSAGES","getMessage","key","options","lang","zMelliCode","options","val","isMelliCode","getMessage","zCardNumber","isCardNumber","zIranianMobile","isIranianMobile","zSheba","isSheba","zPostalCode","isPostalCode","zLandline","isLandline"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{z as a}from"zod";function l(
|
|
1
|
+
import{z as a}from"zod";function l(e){if(!/^\d{10}$/.test(e))return!1;let t=parseInt(e[9]);if(/^(\d)\1+$/.test(e))return!1;let 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 p(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 f(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 n=t.substring(4)+"1827"+t.substring(2,4),s=Array.from(n).map(i=>parseInt(i,36)).reduce((i,r)=>{let g=(r<10,r);return(+(i+""+g)%97).toString()},"");return parseInt(s)===1}function u(e){return!(!/^\d{10}$/.test(e)||e.startsWith("0"))}function b(e){return/^0\d{2}\d{8}$/.test(e)}var c={fa:{melliCode:"\u06A9\u062F \u0645\u0644\u06CC \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",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 c[n][e]};var S=e=>a.string().refine(t=>l(t),{message:o("melliCode",e)}),h=e=>a.string().refine(t=>p(t),{message:o("cardNumber",e)}),R=e=>a.string().refine(t=>f(t,{strictZero:e?.strictZero}),{message:o("mobile",e)}),$=e=>a.string().refine(t=>d(t),{message:o("sheba",e)}),B=e=>a.string().refine(t=>u(t),{message:o("postalCode",e)}),E=e=>a.string().refine(t=>b(t),{message:o("landline",e)});export{p as isCardNumber,f as isIranianMobile,b as isLandline,l as isMelliCode,u as isPostalCode,d as isSheba,h as zCardNumber,R as zIranianMobile,E as zLandline,S as zMelliCode,B as zPostalCode,$ as zSheba};
|
|
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 {
|
|
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\n const check = parseInt(code[9]);\n if (/^(\\d)\\1+$/.test(code)) return false;\n\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) return false;\n if (!iban.startsWith(\"IR\")) return false;\n\n const newStr = iban.substring(4) + \"1827\" + iban.substring(2, 4);\n\n const remainder = Array.from(newStr)\n .map((c) => parseInt(c, 36))\n .reduce((remainder, value) => {\n const v = value < 10 ? value : value;\n return (Number(remainder + \"\" + v) % 97).toString();\n }, \"\");\n\n return parseInt(remainder) === 1;\n}\n\nexport function isPostalCode(code: string): boolean {\n if (!/^\\d{10}$/.test(code)) return false;\n if (code.startsWith(\"0\")) return false;\n return true;\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","i","isCardNumber","sanitized","shouldDouble","digit","isIranianMobile","mobile","strictZero","corePattern","pattern","isSheba","iban","newStr","remainder","c","value","v","isPostalCode","isLandline","ERROR_MESSAGES","getMessage","key","options","lang","zMelliCode","options","z","val","isMelliCode","getMessage","zCardNumber","isCardNumber","zIranianMobile","isIranianMobile","zSheba","isSheba","zPostalCode","isPostalCode","zLandline","isLandline"]}
|