@indodev/toolkit 0.3.1 → 0.3.3
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/{compare-CZadJMGl.d.cts → compare-Ku_8OhuU.d.cts} +25 -1
- package/dist/{compare-CZadJMGl.d.ts → compare-Ku_8OhuU.d.ts} +25 -1
- package/dist/email-validator/index.cjs +83 -0
- package/dist/email-validator/index.cjs.map +1 -0
- package/dist/email-validator/index.d.cts +13 -0
- package/dist/email-validator/index.d.ts +13 -0
- package/dist/email-validator/index.js +76 -0
- package/dist/email-validator/index.js.map +1 -0
- package/dist/email-validator-R9L5unIw.d.cts +120 -0
- package/dist/email-validator-R9L5unIw.d.ts +120 -0
- package/dist/index.cjs +77 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +74 -1
- package/dist/index.js.map +1 -1
- package/dist/text/index.cjs +110 -0
- package/dist/text/index.cjs.map +1 -1
- package/dist/text/index.d.cts +200 -2
- package/dist/text/index.d.ts +200 -2
- package/dist/text/index.js +106 -1
- package/dist/text/index.js.map +1 -1
- package/package.json +11 -1
|
@@ -131,6 +131,30 @@ interface TruncateOptions {
|
|
|
131
131
|
*/
|
|
132
132
|
wordBoundary?: boolean;
|
|
133
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Options for text masking
|
|
136
|
+
*/
|
|
137
|
+
interface MaskOptions {
|
|
138
|
+
/**
|
|
139
|
+
* Masking pattern to apply
|
|
140
|
+
* - `all`: Mask all characters (preserves spaces)
|
|
141
|
+
* - `middle`: Keep start and end visible, mask middle
|
|
142
|
+
* - `email`: Keep first 2 chars of local part and full domain
|
|
143
|
+
*/
|
|
144
|
+
pattern?: 'all' | 'middle' | 'email';
|
|
145
|
+
/**
|
|
146
|
+
* Character to use for masking (default: '*')
|
|
147
|
+
*/
|
|
148
|
+
maskChar?: string;
|
|
149
|
+
/**
|
|
150
|
+
* Number of characters to keep visible at start (for 'middle' pattern, default: 2)
|
|
151
|
+
*/
|
|
152
|
+
visibleStart?: number;
|
|
153
|
+
/**
|
|
154
|
+
* Number of characters to keep visible at end (for 'middle' pattern, default: 2)
|
|
155
|
+
*/
|
|
156
|
+
visibleEnd?: number;
|
|
157
|
+
}
|
|
134
158
|
|
|
135
159
|
/**
|
|
136
160
|
* Capitalize the first letter of a string and lowercase the rest
|
|
@@ -988,4 +1012,4 @@ declare function compareStrings(str1: string, str2: string, options?: CompareOpt
|
|
|
988
1012
|
*/
|
|
989
1013
|
declare function similarity(str1: string, str2: string): number;
|
|
990
1014
|
|
|
991
|
-
export { type CompareOptions as C, type ExtractOptions as E, type SlugifyOptions as S, type TitleCaseOptions as T, toSentenceCase as a, sanitize as b, capitalize as c, contractAbbreviation as d, expandAbbreviation as e, truncate as f, extractWords as g, removeStopwords as h, toFormal as i, isAlay as j, compareStrings as k, similarity as l, type SanitizeOptions as m, normalizeWhitespace as n, type TruncateOptions as o, profanityFilter as p, removeAccents as r, slugify as s, toTitleCase as t };
|
|
1015
|
+
export { type CompareOptions as C, type ExtractOptions as E, type MaskOptions as M, type SlugifyOptions as S, type TitleCaseOptions as T, toSentenceCase as a, sanitize as b, capitalize as c, contractAbbreviation as d, expandAbbreviation as e, truncate as f, extractWords as g, removeStopwords as h, toFormal as i, isAlay as j, compareStrings as k, similarity as l, type SanitizeOptions as m, normalizeWhitespace as n, type TruncateOptions as o, profanityFilter as p, removeAccents as r, slugify as s, toTitleCase as t };
|
|
@@ -131,6 +131,30 @@ interface TruncateOptions {
|
|
|
131
131
|
*/
|
|
132
132
|
wordBoundary?: boolean;
|
|
133
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Options for text masking
|
|
136
|
+
*/
|
|
137
|
+
interface MaskOptions {
|
|
138
|
+
/**
|
|
139
|
+
* Masking pattern to apply
|
|
140
|
+
* - `all`: Mask all characters (preserves spaces)
|
|
141
|
+
* - `middle`: Keep start and end visible, mask middle
|
|
142
|
+
* - `email`: Keep first 2 chars of local part and full domain
|
|
143
|
+
*/
|
|
144
|
+
pattern?: 'all' | 'middle' | 'email';
|
|
145
|
+
/**
|
|
146
|
+
* Character to use for masking (default: '*')
|
|
147
|
+
*/
|
|
148
|
+
maskChar?: string;
|
|
149
|
+
/**
|
|
150
|
+
* Number of characters to keep visible at start (for 'middle' pattern, default: 2)
|
|
151
|
+
*/
|
|
152
|
+
visibleStart?: number;
|
|
153
|
+
/**
|
|
154
|
+
* Number of characters to keep visible at end (for 'middle' pattern, default: 2)
|
|
155
|
+
*/
|
|
156
|
+
visibleEnd?: number;
|
|
157
|
+
}
|
|
134
158
|
|
|
135
159
|
/**
|
|
136
160
|
* Capitalize the first letter of a string and lowercase the rest
|
|
@@ -988,4 +1012,4 @@ declare function compareStrings(str1: string, str2: string, options?: CompareOpt
|
|
|
988
1012
|
*/
|
|
989
1013
|
declare function similarity(str1: string, str2: string): number;
|
|
990
1014
|
|
|
991
|
-
export { type CompareOptions as C, type ExtractOptions as E, type SlugifyOptions as S, type TitleCaseOptions as T, toSentenceCase as a, sanitize as b, capitalize as c, contractAbbreviation as d, expandAbbreviation as e, truncate as f, extractWords as g, removeStopwords as h, toFormal as i, isAlay as j, compareStrings as k, similarity as l, type SanitizeOptions as m, normalizeWhitespace as n, type TruncateOptions as o, profanityFilter as p, removeAccents as r, slugify as s, toTitleCase as t };
|
|
1015
|
+
export { type CompareOptions as C, type ExtractOptions as E, type MaskOptions as M, type SlugifyOptions as S, type TitleCaseOptions as T, toSentenceCase as a, sanitize as b, capitalize as c, contractAbbreviation as d, expandAbbreviation as e, truncate as f, extractWords as g, removeStopwords as h, toFormal as i, isAlay as j, compareStrings as k, similarity as l, type SanitizeOptions as m, normalizeWhitespace as n, type TruncateOptions as o, profanityFilter as p, removeAccents as r, slugify as s, toTitleCase as t };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/email-validator/constants.ts
|
|
4
|
+
var EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?)*$/;
|
|
5
|
+
var DISPOSABLE_DOMAINS = [
|
|
6
|
+
"mailinator.com",
|
|
7
|
+
"10minutemail.com",
|
|
8
|
+
"temp-mail.org",
|
|
9
|
+
"guerrillamail.com"
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
// src/email-validator/email-validator.ts
|
|
13
|
+
var COMMON_PROVIDERS = ["gmail.com", "yahoo.com", "outlook.com", "hotmail.com", "icloud.com"];
|
|
14
|
+
var MAX_EMAIL_LENGTH = 254;
|
|
15
|
+
function validateEmail(email, options) {
|
|
16
|
+
if (!email || typeof email !== "string") {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
const trimmedEmail = email.trim().toLowerCase();
|
|
20
|
+
if (trimmedEmail.length > MAX_EMAIL_LENGTH) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
const parts = trimmedEmail.split("@");
|
|
24
|
+
if (parts.length !== 2) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
const [username, domain] = parts;
|
|
28
|
+
if (!username || !domain) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
if (username.length > 64) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
if (username.includes("..") || username.startsWith(".") || username.endsWith(".") || domain.startsWith(".") || domain.endsWith(".") || domain.includes("..")) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
if (!EMAIL_REGEX.test(trimmedEmail)) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
if (options?.blockDisposable) {
|
|
41
|
+
if (DISPOSABLE_DOMAINS.includes(domain)) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
function getEmailInfo(email) {
|
|
48
|
+
if (!validateEmail(email)) return null;
|
|
49
|
+
const [username, domain] = email.trim().toLowerCase().split("@");
|
|
50
|
+
return {
|
|
51
|
+
username,
|
|
52
|
+
domain,
|
|
53
|
+
isCommonProvider: COMMON_PROVIDERS.includes(domain),
|
|
54
|
+
isDisposable: DISPOSABLE_DOMAINS.includes(domain)
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function maskEmail(email, options) {
|
|
58
|
+
if (!validateEmail(email)) return email;
|
|
59
|
+
const { visibleStart = 1, visibleEnd = 1, maskChar = "*" } = options || {};
|
|
60
|
+
const [username, domain] = email.split("@");
|
|
61
|
+
if (username.length <= 3) {
|
|
62
|
+
return `${username[0]}${maskChar.repeat(3)}@${domain}`;
|
|
63
|
+
}
|
|
64
|
+
const maskedLength = username.length - (visibleStart + visibleEnd);
|
|
65
|
+
if (maskedLength <= 0) {
|
|
66
|
+
return `${username[0]}${maskChar.repeat(3)}@${domain}`;
|
|
67
|
+
}
|
|
68
|
+
const start = username.slice(0, visibleStart);
|
|
69
|
+
const end = username.slice(username.length - visibleEnd);
|
|
70
|
+
return `${start}${maskChar.repeat(maskedLength)}${end}@${domain}`;
|
|
71
|
+
}
|
|
72
|
+
function normalizeEmail(email) {
|
|
73
|
+
return email.trim().toLowerCase();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
exports.DISPOSABLE_DOMAINS = DISPOSABLE_DOMAINS;
|
|
77
|
+
exports.EMAIL_REGEX = EMAIL_REGEX;
|
|
78
|
+
exports.getEmailInfo = getEmailInfo;
|
|
79
|
+
exports.maskEmail = maskEmail;
|
|
80
|
+
exports.normalizeEmail = normalizeEmail;
|
|
81
|
+
exports.validateEmail = validateEmail;
|
|
82
|
+
//# sourceMappingURL=index.cjs.map
|
|
83
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/email-validator/constants.ts","../../src/email-validator/email-validator.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Regular expression for standard email validation.\n * Optimized for RFC 5322 compliance.\n */\nexport const EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?)*$/;\n\n/**\n * Common disposable email domains to block if needed.\n */\nexport const DISPOSABLE_DOMAINS = [\n 'mailinator.com',\n '10minutemail.com',\n 'temp-mail.org',\n 'guerrillamail.com',\n];\n","import { EMAIL_REGEX, DISPOSABLE_DOMAINS } from './constants';\nimport type { EmailValidationOptions, EmailMaskOptions, EmailInfo } from './types';\n\n/**\n * List of common global email providers.\n */\nconst COMMON_PROVIDERS = ['gmail.com', 'yahoo.com', 'outlook.com', 'hotmail.com', 'icloud.com'];\n\n/**\n * The maximum length of an email address according to RFC 5321.\n */\nconst MAX_EMAIL_LENGTH = 254;\n\n/**\n * Validates if a string is a properly formatted email address based on RFC 5322.\n * \n * Performs checks for:\n * - Proper email format (regex).\n * - RFC specific rules (no double dots, username length < 64).\n * - Maximum total length (254 characters).\n * - Optional: disposable email detection.\n * \n * @param email - The email string to validate.\n * @param options - Optional validation configuration.\n * @returns `true` if valid, `false` otherwise.\n * \n * @example\n * ```typescript\n * import { validateEmail } from '@indodev/toolkit/email-validator';\n * \n * validateEmail('user@example.com'); // true\n * validateEmail('invalid-email'); // false\n * validateEmail('spam@mailinator.com', { blockDisposable: true }); // false\n * ```\n */\nexport function validateEmail(email: string, options?: EmailValidationOptions): boolean {\n if (!email || typeof email !== 'string') {\n return false;\n }\n\n const trimmedEmail = email.trim().toLowerCase();\n\n if (trimmedEmail.length > MAX_EMAIL_LENGTH) {\n return false;\n }\n\n const parts = trimmedEmail.split('@');\n if (parts.length !== 2) {\n return false;\n }\n\n const [username, domain] = parts;\n\n if (!username || !domain) {\n return false;\n }\n\n if (username.length > 64) {\n return false;\n }\n\n if (\n username.includes('..') ||\n username.startsWith('.') ||\n username.endsWith('.') ||\n domain.startsWith('.') ||\n domain.endsWith('.') ||\n domain.includes('..')\n ) {\n return false;\n }\n\n if (!EMAIL_REGEX.test(trimmedEmail)) {\n return false;\n }\n\n if (options?.blockDisposable) {\n if (DISPOSABLE_DOMAINS.includes(domain)) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Parses an email address to extract useful metadata.\n * \n * @param email - The email address to parse.\n * @returns `EmailInfo` object containing details or `null` if the email is invalid.\n * \n * @example\n * ```typescript\n * import { getEmailInfo } from '@indodev/toolkit/email-validator';\n * \n * const info = getEmailInfo('adam@gmail.com');\n * // { username: 'adam', domain: 'gmail.com', isCommonProvider: true, isDisposable: false }\n * ```\n */\nexport function getEmailInfo(email: string): EmailInfo | null {\n if (!validateEmail(email)) return null;\n\n const [username, domain] = email.trim().toLowerCase().split('@');\n\n return {\n username,\n domain,\n isCommonProvider: COMMON_PROVIDERS.includes(domain),\n isDisposable: DISPOSABLE_DOMAINS.includes(domain),\n };\n}\n\n/**\n * Masks the username portion of an email for privacy protection.\n * \n * Falls back to a standard mask if the username is too short to respect visibleStart/visibleEnd.\n * \n * @param email - The email address to mask.\n * @param options - Optional masking configuration.\n * @returns Masked email string or original if invalid.\n * \n * @example\n * ```typescript\n * import { maskEmail } from '@indodev/toolkit/email-validator';\n * \n * maskEmail('user@example.com'); // 'u**r@example.com'\n * maskEmail('user@example.com', { maskChar: '#' }); // 'u##r@example.com'\n * ```\n */\nexport function maskEmail(email: string, options?: EmailMaskOptions): string {\n if (!validateEmail(email)) return email;\n\n const { visibleStart = 1, visibleEnd = 1, maskChar = '*' } = options || {};\n const [username, domain] = email.split('@');\n\n // Fallback for very short usernames\n if (username.length <= 3) {\n return `${username[0]}${maskChar.repeat(3)}@${domain}`;\n }\n\n // Calculate masked length\n const maskedLength = username.length - (visibleStart + visibleEnd);\n\n // If the result of masking would be empty or negative, use fallback\n if (maskedLength <= 0) {\n return `${username[0]}${maskChar.repeat(3)}@${domain}`;\n }\n\n const start = username.slice(0, visibleStart);\n const end = username.slice(username.length - visibleEnd);\n\n return `${start}${maskChar.repeat(maskedLength)}${end}@${domain}`;\n}\n\n/**\n * Normalizes an email address by trimming whitespace and converting to lowercase.\n * \n * @param email - The email to normalize.\n * @returns Normalized email string.\n * \n * @example\n * ```typescript\n * import { normalizeEmail } from '@indodev/toolkit/email-validator';\n * \n * normalizeEmail(' USER@Example.COM '); // 'user@example.com'\n * ```\n */\nexport function normalizeEmail(email: string): string {\n return email.trim().toLowerCase();\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { c as EmailInfo, b as EmailMaskOptions, E as EmailValidationOptions, a as EmailValidationResult, g as getEmailInfo, m as maskEmail, n as normalizeEmail, v as validateEmail } from '../email-validator-R9L5unIw.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Regular expression for standard email validation.
|
|
5
|
+
* Optimized for RFC 5322 compliance.
|
|
6
|
+
*/
|
|
7
|
+
declare const EMAIL_REGEX: RegExp;
|
|
8
|
+
/**
|
|
9
|
+
* Common disposable email domains to block if needed.
|
|
10
|
+
*/
|
|
11
|
+
declare const DISPOSABLE_DOMAINS: string[];
|
|
12
|
+
|
|
13
|
+
export { DISPOSABLE_DOMAINS, EMAIL_REGEX };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { c as EmailInfo, b as EmailMaskOptions, E as EmailValidationOptions, a as EmailValidationResult, g as getEmailInfo, m as maskEmail, n as normalizeEmail, v as validateEmail } from '../email-validator-R9L5unIw.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Regular expression for standard email validation.
|
|
5
|
+
* Optimized for RFC 5322 compliance.
|
|
6
|
+
*/
|
|
7
|
+
declare const EMAIL_REGEX: RegExp;
|
|
8
|
+
/**
|
|
9
|
+
* Common disposable email domains to block if needed.
|
|
10
|
+
*/
|
|
11
|
+
declare const DISPOSABLE_DOMAINS: string[];
|
|
12
|
+
|
|
13
|
+
export { DISPOSABLE_DOMAINS, EMAIL_REGEX };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// src/email-validator/constants.ts
|
|
2
|
+
var EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?)*$/;
|
|
3
|
+
var DISPOSABLE_DOMAINS = [
|
|
4
|
+
"mailinator.com",
|
|
5
|
+
"10minutemail.com",
|
|
6
|
+
"temp-mail.org",
|
|
7
|
+
"guerrillamail.com"
|
|
8
|
+
];
|
|
9
|
+
|
|
10
|
+
// src/email-validator/email-validator.ts
|
|
11
|
+
var COMMON_PROVIDERS = ["gmail.com", "yahoo.com", "outlook.com", "hotmail.com", "icloud.com"];
|
|
12
|
+
var MAX_EMAIL_LENGTH = 254;
|
|
13
|
+
function validateEmail(email, options) {
|
|
14
|
+
if (!email || typeof email !== "string") {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
const trimmedEmail = email.trim().toLowerCase();
|
|
18
|
+
if (trimmedEmail.length > MAX_EMAIL_LENGTH) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
const parts = trimmedEmail.split("@");
|
|
22
|
+
if (parts.length !== 2) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
const [username, domain] = parts;
|
|
26
|
+
if (!username || !domain) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
if (username.length > 64) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
if (username.includes("..") || username.startsWith(".") || username.endsWith(".") || domain.startsWith(".") || domain.endsWith(".") || domain.includes("..")) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
if (!EMAIL_REGEX.test(trimmedEmail)) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
if (options?.blockDisposable) {
|
|
39
|
+
if (DISPOSABLE_DOMAINS.includes(domain)) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
function getEmailInfo(email) {
|
|
46
|
+
if (!validateEmail(email)) return null;
|
|
47
|
+
const [username, domain] = email.trim().toLowerCase().split("@");
|
|
48
|
+
return {
|
|
49
|
+
username,
|
|
50
|
+
domain,
|
|
51
|
+
isCommonProvider: COMMON_PROVIDERS.includes(domain),
|
|
52
|
+
isDisposable: DISPOSABLE_DOMAINS.includes(domain)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function maskEmail(email, options) {
|
|
56
|
+
if (!validateEmail(email)) return email;
|
|
57
|
+
const { visibleStart = 1, visibleEnd = 1, maskChar = "*" } = options || {};
|
|
58
|
+
const [username, domain] = email.split("@");
|
|
59
|
+
if (username.length <= 3) {
|
|
60
|
+
return `${username[0]}${maskChar.repeat(3)}@${domain}`;
|
|
61
|
+
}
|
|
62
|
+
const maskedLength = username.length - (visibleStart + visibleEnd);
|
|
63
|
+
if (maskedLength <= 0) {
|
|
64
|
+
return `${username[0]}${maskChar.repeat(3)}@${domain}`;
|
|
65
|
+
}
|
|
66
|
+
const start = username.slice(0, visibleStart);
|
|
67
|
+
const end = username.slice(username.length - visibleEnd);
|
|
68
|
+
return `${start}${maskChar.repeat(maskedLength)}${end}@${domain}`;
|
|
69
|
+
}
|
|
70
|
+
function normalizeEmail(email) {
|
|
71
|
+
return email.trim().toLowerCase();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { DISPOSABLE_DOMAINS, EMAIL_REGEX, getEmailInfo, maskEmail, normalizeEmail, validateEmail };
|
|
75
|
+
//# sourceMappingURL=index.js.map
|
|
76
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/email-validator/constants.ts","../../src/email-validator/email-validator.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Regular expression for standard email validation.\n * Optimized for RFC 5322 compliance.\n */\nexport const EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?)*$/;\n\n/**\n * Common disposable email domains to block if needed.\n */\nexport const DISPOSABLE_DOMAINS = [\n 'mailinator.com',\n '10minutemail.com',\n 'temp-mail.org',\n 'guerrillamail.com',\n];\n","import { EMAIL_REGEX, DISPOSABLE_DOMAINS } from './constants';\nimport type { EmailValidationOptions, EmailMaskOptions, EmailInfo } from './types';\n\n/**\n * List of common global email providers.\n */\nconst COMMON_PROVIDERS = ['gmail.com', 'yahoo.com', 'outlook.com', 'hotmail.com', 'icloud.com'];\n\n/**\n * The maximum length of an email address according to RFC 5321.\n */\nconst MAX_EMAIL_LENGTH = 254;\n\n/**\n * Validates if a string is a properly formatted email address based on RFC 5322.\n * \n * Performs checks for:\n * - Proper email format (regex).\n * - RFC specific rules (no double dots, username length < 64).\n * - Maximum total length (254 characters).\n * - Optional: disposable email detection.\n * \n * @param email - The email string to validate.\n * @param options - Optional validation configuration.\n * @returns `true` if valid, `false` otherwise.\n * \n * @example\n * ```typescript\n * import { validateEmail } from '@indodev/toolkit/email-validator';\n * \n * validateEmail('user@example.com'); // true\n * validateEmail('invalid-email'); // false\n * validateEmail('spam@mailinator.com', { blockDisposable: true }); // false\n * ```\n */\nexport function validateEmail(email: string, options?: EmailValidationOptions): boolean {\n if (!email || typeof email !== 'string') {\n return false;\n }\n\n const trimmedEmail = email.trim().toLowerCase();\n\n if (trimmedEmail.length > MAX_EMAIL_LENGTH) {\n return false;\n }\n\n const parts = trimmedEmail.split('@');\n if (parts.length !== 2) {\n return false;\n }\n\n const [username, domain] = parts;\n\n if (!username || !domain) {\n return false;\n }\n\n if (username.length > 64) {\n return false;\n }\n\n if (\n username.includes('..') ||\n username.startsWith('.') ||\n username.endsWith('.') ||\n domain.startsWith('.') ||\n domain.endsWith('.') ||\n domain.includes('..')\n ) {\n return false;\n }\n\n if (!EMAIL_REGEX.test(trimmedEmail)) {\n return false;\n }\n\n if (options?.blockDisposable) {\n if (DISPOSABLE_DOMAINS.includes(domain)) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Parses an email address to extract useful metadata.\n * \n * @param email - The email address to parse.\n * @returns `EmailInfo` object containing details or `null` if the email is invalid.\n * \n * @example\n * ```typescript\n * import { getEmailInfo } from '@indodev/toolkit/email-validator';\n * \n * const info = getEmailInfo('adam@gmail.com');\n * // { username: 'adam', domain: 'gmail.com', isCommonProvider: true, isDisposable: false }\n * ```\n */\nexport function getEmailInfo(email: string): EmailInfo | null {\n if (!validateEmail(email)) return null;\n\n const [username, domain] = email.trim().toLowerCase().split('@');\n\n return {\n username,\n domain,\n isCommonProvider: COMMON_PROVIDERS.includes(domain),\n isDisposable: DISPOSABLE_DOMAINS.includes(domain),\n };\n}\n\n/**\n * Masks the username portion of an email for privacy protection.\n * \n * Falls back to a standard mask if the username is too short to respect visibleStart/visibleEnd.\n * \n * @param email - The email address to mask.\n * @param options - Optional masking configuration.\n * @returns Masked email string or original if invalid.\n * \n * @example\n * ```typescript\n * import { maskEmail } from '@indodev/toolkit/email-validator';\n * \n * maskEmail('user@example.com'); // 'u**r@example.com'\n * maskEmail('user@example.com', { maskChar: '#' }); // 'u##r@example.com'\n * ```\n */\nexport function maskEmail(email: string, options?: EmailMaskOptions): string {\n if (!validateEmail(email)) return email;\n\n const { visibleStart = 1, visibleEnd = 1, maskChar = '*' } = options || {};\n const [username, domain] = email.split('@');\n\n // Fallback for very short usernames\n if (username.length <= 3) {\n return `${username[0]}${maskChar.repeat(3)}@${domain}`;\n }\n\n // Calculate masked length\n const maskedLength = username.length - (visibleStart + visibleEnd);\n\n // If the result of masking would be empty or negative, use fallback\n if (maskedLength <= 0) {\n return `${username[0]}${maskChar.repeat(3)}@${domain}`;\n }\n\n const start = username.slice(0, visibleStart);\n const end = username.slice(username.length - visibleEnd);\n\n return `${start}${maskChar.repeat(maskedLength)}${end}@${domain}`;\n}\n\n/**\n * Normalizes an email address by trimming whitespace and converting to lowercase.\n * \n * @param email - The email to normalize.\n * @returns Normalized email string.\n * \n * @example\n * ```typescript\n * import { normalizeEmail } from '@indodev/toolkit/email-validator';\n * \n * normalizeEmail(' USER@Example.COM '); // 'user@example.com'\n * ```\n */\nexport function normalizeEmail(email: string): string {\n return email.trim().toLowerCase();\n}\n"]}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email validation options.
|
|
3
|
+
*/
|
|
4
|
+
interface EmailValidationOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Whether to block known disposable email domains.
|
|
7
|
+
* @default false
|
|
8
|
+
*/
|
|
9
|
+
blockDisposable?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Detailed email validation result.
|
|
13
|
+
*/
|
|
14
|
+
interface EmailValidationResult {
|
|
15
|
+
isValid: boolean;
|
|
16
|
+
domain?: string;
|
|
17
|
+
isDisposable?: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Options for email masking.
|
|
21
|
+
*/
|
|
22
|
+
interface EmailMaskOptions {
|
|
23
|
+
/**
|
|
24
|
+
* Number of characters to keep visible at the start of the username.
|
|
25
|
+
* @default 1
|
|
26
|
+
*/
|
|
27
|
+
visibleStart?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Number of characters to keep visible at the end of the username.
|
|
30
|
+
* @default 1
|
|
31
|
+
*/
|
|
32
|
+
visibleEnd?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Character used for masking.
|
|
35
|
+
* @default '*'
|
|
36
|
+
*/
|
|
37
|
+
maskChar?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Detailed email information.
|
|
41
|
+
*/
|
|
42
|
+
interface EmailInfo {
|
|
43
|
+
username: string;
|
|
44
|
+
domain: string;
|
|
45
|
+
isCommonProvider: boolean;
|
|
46
|
+
isDisposable: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Validates if a string is a properly formatted email address based on RFC 5322.
|
|
51
|
+
*
|
|
52
|
+
* Performs checks for:
|
|
53
|
+
* - Proper email format (regex).
|
|
54
|
+
* - RFC specific rules (no double dots, username length < 64).
|
|
55
|
+
* - Maximum total length (254 characters).
|
|
56
|
+
* - Optional: disposable email detection.
|
|
57
|
+
*
|
|
58
|
+
* @param email - The email string to validate.
|
|
59
|
+
* @param options - Optional validation configuration.
|
|
60
|
+
* @returns `true` if valid, `false` otherwise.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* import { validateEmail } from '@indodev/toolkit/email-validator';
|
|
65
|
+
*
|
|
66
|
+
* validateEmail('user@example.com'); // true
|
|
67
|
+
* validateEmail('invalid-email'); // false
|
|
68
|
+
* validateEmail('spam@mailinator.com', { blockDisposable: true }); // false
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
declare function validateEmail(email: string, options?: EmailValidationOptions): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Parses an email address to extract useful metadata.
|
|
74
|
+
*
|
|
75
|
+
* @param email - The email address to parse.
|
|
76
|
+
* @returns `EmailInfo` object containing details or `null` if the email is invalid.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* import { getEmailInfo } from '@indodev/toolkit/email-validator';
|
|
81
|
+
*
|
|
82
|
+
* const info = getEmailInfo('adam@gmail.com');
|
|
83
|
+
* // { username: 'adam', domain: 'gmail.com', isCommonProvider: true, isDisposable: false }
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
declare function getEmailInfo(email: string): EmailInfo | null;
|
|
87
|
+
/**
|
|
88
|
+
* Masks the username portion of an email for privacy protection.
|
|
89
|
+
*
|
|
90
|
+
* Falls back to a standard mask if the username is too short to respect visibleStart/visibleEnd.
|
|
91
|
+
*
|
|
92
|
+
* @param email - The email address to mask.
|
|
93
|
+
* @param options - Optional masking configuration.
|
|
94
|
+
* @returns Masked email string or original if invalid.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* import { maskEmail } from '@indodev/toolkit/email-validator';
|
|
99
|
+
*
|
|
100
|
+
* maskEmail('user@example.com'); // 'u**r@example.com'
|
|
101
|
+
* maskEmail('user@example.com', { maskChar: '#' }); // 'u##r@example.com'
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
declare function maskEmail(email: string, options?: EmailMaskOptions): string;
|
|
105
|
+
/**
|
|
106
|
+
* Normalizes an email address by trimming whitespace and converting to lowercase.
|
|
107
|
+
*
|
|
108
|
+
* @param email - The email to normalize.
|
|
109
|
+
* @returns Normalized email string.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```typescript
|
|
113
|
+
* import { normalizeEmail } from '@indodev/toolkit/email-validator';
|
|
114
|
+
*
|
|
115
|
+
* normalizeEmail(' USER@Example.COM '); // 'user@example.com'
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
declare function normalizeEmail(email: string): string;
|
|
119
|
+
|
|
120
|
+
export { type EmailValidationOptions as E, type EmailValidationResult as a, type EmailMaskOptions as b, type EmailInfo as c, getEmailInfo as g, maskEmail as m, normalizeEmail as n, validateEmail as v };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email validation options.
|
|
3
|
+
*/
|
|
4
|
+
interface EmailValidationOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Whether to block known disposable email domains.
|
|
7
|
+
* @default false
|
|
8
|
+
*/
|
|
9
|
+
blockDisposable?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Detailed email validation result.
|
|
13
|
+
*/
|
|
14
|
+
interface EmailValidationResult {
|
|
15
|
+
isValid: boolean;
|
|
16
|
+
domain?: string;
|
|
17
|
+
isDisposable?: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Options for email masking.
|
|
21
|
+
*/
|
|
22
|
+
interface EmailMaskOptions {
|
|
23
|
+
/**
|
|
24
|
+
* Number of characters to keep visible at the start of the username.
|
|
25
|
+
* @default 1
|
|
26
|
+
*/
|
|
27
|
+
visibleStart?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Number of characters to keep visible at the end of the username.
|
|
30
|
+
* @default 1
|
|
31
|
+
*/
|
|
32
|
+
visibleEnd?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Character used for masking.
|
|
35
|
+
* @default '*'
|
|
36
|
+
*/
|
|
37
|
+
maskChar?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Detailed email information.
|
|
41
|
+
*/
|
|
42
|
+
interface EmailInfo {
|
|
43
|
+
username: string;
|
|
44
|
+
domain: string;
|
|
45
|
+
isCommonProvider: boolean;
|
|
46
|
+
isDisposable: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Validates if a string is a properly formatted email address based on RFC 5322.
|
|
51
|
+
*
|
|
52
|
+
* Performs checks for:
|
|
53
|
+
* - Proper email format (regex).
|
|
54
|
+
* - RFC specific rules (no double dots, username length < 64).
|
|
55
|
+
* - Maximum total length (254 characters).
|
|
56
|
+
* - Optional: disposable email detection.
|
|
57
|
+
*
|
|
58
|
+
* @param email - The email string to validate.
|
|
59
|
+
* @param options - Optional validation configuration.
|
|
60
|
+
* @returns `true` if valid, `false` otherwise.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* import { validateEmail } from '@indodev/toolkit/email-validator';
|
|
65
|
+
*
|
|
66
|
+
* validateEmail('user@example.com'); // true
|
|
67
|
+
* validateEmail('invalid-email'); // false
|
|
68
|
+
* validateEmail('spam@mailinator.com', { blockDisposable: true }); // false
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
declare function validateEmail(email: string, options?: EmailValidationOptions): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Parses an email address to extract useful metadata.
|
|
74
|
+
*
|
|
75
|
+
* @param email - The email address to parse.
|
|
76
|
+
* @returns `EmailInfo` object containing details or `null` if the email is invalid.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* import { getEmailInfo } from '@indodev/toolkit/email-validator';
|
|
81
|
+
*
|
|
82
|
+
* const info = getEmailInfo('adam@gmail.com');
|
|
83
|
+
* // { username: 'adam', domain: 'gmail.com', isCommonProvider: true, isDisposable: false }
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
declare function getEmailInfo(email: string): EmailInfo | null;
|
|
87
|
+
/**
|
|
88
|
+
* Masks the username portion of an email for privacy protection.
|
|
89
|
+
*
|
|
90
|
+
* Falls back to a standard mask if the username is too short to respect visibleStart/visibleEnd.
|
|
91
|
+
*
|
|
92
|
+
* @param email - The email address to mask.
|
|
93
|
+
* @param options - Optional masking configuration.
|
|
94
|
+
* @returns Masked email string or original if invalid.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* import { maskEmail } from '@indodev/toolkit/email-validator';
|
|
99
|
+
*
|
|
100
|
+
* maskEmail('user@example.com'); // 'u**r@example.com'
|
|
101
|
+
* maskEmail('user@example.com', { maskChar: '#' }); // 'u##r@example.com'
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
declare function maskEmail(email: string, options?: EmailMaskOptions): string;
|
|
105
|
+
/**
|
|
106
|
+
* Normalizes an email address by trimming whitespace and converting to lowercase.
|
|
107
|
+
*
|
|
108
|
+
* @param email - The email to normalize.
|
|
109
|
+
* @returns Normalized email string.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```typescript
|
|
113
|
+
* import { normalizeEmail } from '@indodev/toolkit/email-validator';
|
|
114
|
+
*
|
|
115
|
+
* normalizeEmail(' USER@Example.COM '); // 'user@example.com'
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
declare function normalizeEmail(email: string): string;
|
|
119
|
+
|
|
120
|
+
export { type EmailValidationOptions as E, type EmailValidationResult as a, type EmailMaskOptions as b, type EmailInfo as c, getEmailInfo as g, maskEmail as m, normalizeEmail as n, validateEmail as v };
|
package/dist/index.cjs
CHANGED
|
@@ -1251,6 +1251,79 @@ function validateVIN(vin) {
|
|
|
1251
1251
|
return actualCheckDigit === expectedCheckDigit;
|
|
1252
1252
|
}
|
|
1253
1253
|
|
|
1254
|
+
// src/email-validator/constants.ts
|
|
1255
|
+
var EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?)*$/;
|
|
1256
|
+
var DISPOSABLE_DOMAINS = [
|
|
1257
|
+
"mailinator.com",
|
|
1258
|
+
"10minutemail.com",
|
|
1259
|
+
"temp-mail.org",
|
|
1260
|
+
"guerrillamail.com"
|
|
1261
|
+
];
|
|
1262
|
+
|
|
1263
|
+
// src/email-validator/email-validator.ts
|
|
1264
|
+
var COMMON_PROVIDERS = ["gmail.com", "yahoo.com", "outlook.com", "hotmail.com", "icloud.com"];
|
|
1265
|
+
var MAX_EMAIL_LENGTH = 254;
|
|
1266
|
+
function validateEmail(email, options) {
|
|
1267
|
+
if (!email || typeof email !== "string") {
|
|
1268
|
+
return false;
|
|
1269
|
+
}
|
|
1270
|
+
const trimmedEmail = email.trim().toLowerCase();
|
|
1271
|
+
if (trimmedEmail.length > MAX_EMAIL_LENGTH) {
|
|
1272
|
+
return false;
|
|
1273
|
+
}
|
|
1274
|
+
const parts = trimmedEmail.split("@");
|
|
1275
|
+
if (parts.length !== 2) {
|
|
1276
|
+
return false;
|
|
1277
|
+
}
|
|
1278
|
+
const [username, domain] = parts;
|
|
1279
|
+
if (!username || !domain) {
|
|
1280
|
+
return false;
|
|
1281
|
+
}
|
|
1282
|
+
if (username.length > 64) {
|
|
1283
|
+
return false;
|
|
1284
|
+
}
|
|
1285
|
+
if (username.includes("..") || username.startsWith(".") || username.endsWith(".") || domain.startsWith(".") || domain.endsWith(".") || domain.includes("..")) {
|
|
1286
|
+
return false;
|
|
1287
|
+
}
|
|
1288
|
+
if (!EMAIL_REGEX.test(trimmedEmail)) {
|
|
1289
|
+
return false;
|
|
1290
|
+
}
|
|
1291
|
+
if (options?.blockDisposable) {
|
|
1292
|
+
if (DISPOSABLE_DOMAINS.includes(domain)) {
|
|
1293
|
+
return false;
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
return true;
|
|
1297
|
+
}
|
|
1298
|
+
function getEmailInfo(email) {
|
|
1299
|
+
if (!validateEmail(email)) return null;
|
|
1300
|
+
const [username, domain] = email.trim().toLowerCase().split("@");
|
|
1301
|
+
return {
|
|
1302
|
+
username,
|
|
1303
|
+
domain,
|
|
1304
|
+
isCommonProvider: COMMON_PROVIDERS.includes(domain),
|
|
1305
|
+
isDisposable: DISPOSABLE_DOMAINS.includes(domain)
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1308
|
+
function maskEmail(email, options) {
|
|
1309
|
+
if (!validateEmail(email)) return email;
|
|
1310
|
+
const { visibleStart = 1, visibleEnd = 1, maskChar = "*" } = options || {};
|
|
1311
|
+
const [username, domain] = email.split("@");
|
|
1312
|
+
if (username.length <= 3) {
|
|
1313
|
+
return `${username[0]}${maskChar.repeat(3)}@${domain}`;
|
|
1314
|
+
}
|
|
1315
|
+
const maskedLength = username.length - (visibleStart + visibleEnd);
|
|
1316
|
+
if (maskedLength <= 0) {
|
|
1317
|
+
return `${username[0]}${maskChar.repeat(3)}@${domain}`;
|
|
1318
|
+
}
|
|
1319
|
+
const start = username.slice(0, visibleStart);
|
|
1320
|
+
const end = username.slice(username.length - visibleEnd);
|
|
1321
|
+
return `${start}${maskChar.repeat(maskedLength)}${end}@${domain}`;
|
|
1322
|
+
}
|
|
1323
|
+
function normalizeEmail(email) {
|
|
1324
|
+
return email.trim().toLowerCase();
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1254
1327
|
// src/currency/format.ts
|
|
1255
1328
|
function formatRupiah(amount, options) {
|
|
1256
1329
|
const {
|
|
@@ -3229,6 +3302,7 @@ exports.generateSmsLink = generateSmsLink;
|
|
|
3229
3302
|
exports.generateTelLink = generateTelLink;
|
|
3230
3303
|
exports.generateWALink = generateWALink;
|
|
3231
3304
|
exports.getAge = getAge;
|
|
3305
|
+
exports.getEmailInfo = getEmailInfo;
|
|
3232
3306
|
exports.getOperator = getOperator;
|
|
3233
3307
|
exports.getRegionFromPlate = getRegionFromPlate;
|
|
3234
3308
|
exports.isAlay = isAlay;
|
|
@@ -3237,9 +3311,11 @@ exports.isMobileNumber = isMobileNumber;
|
|
|
3237
3311
|
exports.isProvider = isProvider;
|
|
3238
3312
|
exports.isValidForBirthDate = isValidForBirthDate;
|
|
3239
3313
|
exports.isValidForGender = isValidForGender;
|
|
3314
|
+
exports.maskEmail = maskEmail;
|
|
3240
3315
|
exports.maskNIK = maskNIK;
|
|
3241
3316
|
exports.maskNPWP = maskNPWP;
|
|
3242
3317
|
exports.maskPhoneNumber = maskPhoneNumber;
|
|
3318
|
+
exports.normalizeEmail = normalizeEmail;
|
|
3243
3319
|
exports.normalizeWhitespace = normalizeWhitespace;
|
|
3244
3320
|
exports.parseNIK = parseNIK;
|
|
3245
3321
|
exports.parseNPWP = parseNPWP;
|
|
@@ -3260,6 +3336,7 @@ exports.toSentenceCase = toSentenceCase;
|
|
|
3260
3336
|
exports.toTitleCase = toTitleCase;
|
|
3261
3337
|
exports.toWords = toWords;
|
|
3262
3338
|
exports.truncate = truncate;
|
|
3339
|
+
exports.validateEmail = validateEmail;
|
|
3263
3340
|
exports.validateNIK = validateNIK;
|
|
3264
3341
|
exports.validateNPWP = validateNPWP;
|
|
3265
3342
|
exports.validatePhoneNumber = validatePhoneNumber;
|