superjs-core 0.4.3 → 0.5.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/CHANGELOG.md +117 -0
- package/CONTRIBUTING.md +55 -0
- package/PUBLISH.md +45 -0
- package/README.md +9 -5
- package/ROADMAP.md +72 -0
- package/SECURITY.md +35 -0
- package/SUMMARY.md +321 -0
- package/dist/async/index.d.ts +106 -1
- package/dist/async/index.js +128 -1
- package/dist/async/index.js.map +1 -1
- package/dist/collection/index.d.ts +135 -1
- package/dist/collection/index.js +145 -1
- package/dist/collection/index.js.map +1 -1
- package/dist/color/index.d.ts +79 -1
- package/dist/color/index.js +101 -0
- package/dist/color/index.js.map +1 -1
- package/dist/date/index.d.ts +316 -1
- package/dist/date/index.js +339 -1
- package/dist/date/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/isNoRekening-CHSpgD4P.d.ts +167 -0
- package/dist/math/index.d.ts +188 -1
- package/dist/math/index.js +199 -1
- package/dist/math/index.js.map +1 -1
- package/dist/string/index.d.ts +71 -1
- package/dist/string/index.js +94 -0
- package/dist/string/index.js.map +1 -1
- package/dist/validation/index.d.ts +22 -150
- package/dist/validation/index.js +27 -0
- package/dist/validation/index.js.map +1 -1
- package/package.json +3 -2
|
@@ -1,167 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
* Validates an Indonesian NIK (Nomor Induk Kependudukan / Resident Identity Number).
|
|
3
|
-
*
|
|
4
|
-
* A valid NIK:
|
|
5
|
-
* - Must be exactly 16 digits
|
|
6
|
-
* - Structure: PP CC DD DDMMYY SSSS
|
|
7
|
-
* - PP: Province code (2 digits)
|
|
8
|
-
* - CC: City code (2 digits)
|
|
9
|
-
* - DD: District code (2 digits)
|
|
10
|
-
* - DDMMYY: Birth date (6 digits; for women the day is incremented by 40)
|
|
11
|
-
* - SSSS: Serial number (4 digits)
|
|
12
|
-
* - The birth date must correspond to a valid calendar date
|
|
13
|
-
*
|
|
14
|
-
* @param value - The NIK string (digits only or with dots)
|
|
15
|
-
* @returns `true` if the value is a valid NIK
|
|
16
|
-
*
|
|
17
|
-
* @example isNIK('3201010203940001') // => true (male, born 2 March 1994)
|
|
18
|
-
* @example isNIK('3201015203940001') // => true (female, born 12 March 1994)
|
|
19
|
-
* @example isNIK('1234567890123456') // => false (invalid birth date)
|
|
20
|
-
* @example isNIK('320101') // => false (too short)
|
|
21
|
-
*/
|
|
22
|
-
declare function isNIK(value: string): boolean;
|
|
1
|
+
export { N as NIKInfo, i as isEmail, a as isKodepos, b as isNIK, c as isNPWP, d as isNoRekening, e as isPhone, f as isPlatNomor, g as isURL, p as parseNIK } from '../isNoRekening-CHSpgD4P.js';
|
|
23
2
|
|
|
24
3
|
/**
|
|
25
|
-
*
|
|
4
|
+
* Validasi Nomor SIM Indonesia.
|
|
5
|
+
* Format: 12 digit angka (2 digit golongan + 6 digit tanggal lahir + 4 digit nomor seri).
|
|
26
6
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* - The last digit is a checksum computed from the preceding digits
|
|
30
|
-
*
|
|
31
|
-
* The checksum uses a weighted-sum algorithm with a repeating weight pattern of
|
|
32
|
-
* `[3, 7, 1]`. The computed checksum must equal the last digit.
|
|
33
|
-
*
|
|
34
|
-
* @param value - The NPWP string (formatted with dots & dash, or plain digits)
|
|
35
|
-
* @returns `true` if the value is a valid NPWP
|
|
36
|
-
*
|
|
37
|
-
* @example isNPWP('12.345.678.9-012.344') // => true
|
|
38
|
-
* @example isNPWP('123456789012344') // => true (plain digits)
|
|
39
|
-
* @example isNPWP('12.345.678.9-012.345') // => false (invalid checksum)
|
|
7
|
+
* @example isNoSIM('123456789012') // true (12 digit)
|
|
8
|
+
* @example isNoSIM('12345') // false
|
|
40
9
|
*/
|
|
41
|
-
declare function
|
|
10
|
+
declare function isNoSIM(value: string): boolean;
|
|
42
11
|
|
|
43
12
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* For Indonesian numbers (`country = 'id'`):
|
|
47
|
-
* - Accepted formats: `08xx…`, `+628xx…`, `628xx…`
|
|
48
|
-
* - Must start with a valid operator prefix:
|
|
49
|
-
* 0811-0819, 0821-0829, 0851-0859, 0877-0879, 0895-0899
|
|
50
|
-
* - 10–13 digits after the country code
|
|
51
|
-
*
|
|
52
|
-
* For generic numbers (`country = 'any'`):
|
|
53
|
-
* - Any string with 10–15 digits is accepted
|
|
54
|
-
*
|
|
55
|
-
* @param value - The phone number string
|
|
56
|
-
* @param country - Country to validate against (`'id'` or `'any'`; default `'id'`)
|
|
57
|
-
* @returns `true` if the value is a valid phone number
|
|
58
|
-
*
|
|
59
|
-
* @example isPhone('08123456789') // => true
|
|
60
|
-
* @example isPhone('+628123456789') // => true
|
|
61
|
-
* @example isPhone('628123456789') // => true
|
|
62
|
-
* @example isPhone('081234567') // => false (too short)
|
|
63
|
-
* @example isPhone('089123456789') // => false (invalid prefix 91)
|
|
64
|
-
*/
|
|
65
|
-
declare function isPhone(value: string, country?: 'id' | 'any'): boolean;
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* RFC‑compliant email address validation.
|
|
69
|
-
*
|
|
70
|
-
* Validation rules:
|
|
71
|
-
* - Total length ≤ 254 characters
|
|
72
|
-
* - Local part ≤ 64 characters; supports quoted strings (including escaped
|
|
73
|
-
* characters), unquoted letters / digits / `!#$%&'*+/=?^_`{|}~-`, and dots
|
|
74
|
-
* (no leading, trailing, or consecutive dots)
|
|
75
|
-
* - Domain part ≤ 255 characters; valid DNS labels separated by dots, each
|
|
76
|
-
* label ≤ 63 characters, no leading/trailing hyphens, at least two labels
|
|
77
|
-
*
|
|
78
|
-
* @param value - The email address string
|
|
79
|
-
* @returns `true` if the value is a syntactically valid email address
|
|
80
|
-
*
|
|
81
|
-
* @example isEmail('user@example.com') // => true
|
|
82
|
-
* @example isEmail('user.name+tag@example.co.id') // => true
|
|
83
|
-
* @example isEmail('"quoted@local"@example.com') // => true
|
|
84
|
-
* @example isEmail('not-an-email') // => false
|
|
85
|
-
*/
|
|
86
|
-
declare function isEmail(value: string): boolean;
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Validates a URL.
|
|
90
|
-
*
|
|
91
|
-
* A valid URL:
|
|
92
|
-
* - Must use the `http` or `https` protocol
|
|
93
|
-
* - Must have a valid hostname (DNS name, IPv4, IPv6 literal, or `localhost`)
|
|
94
|
-
* - May include an optional port, path, query string, and fragment
|
|
95
|
-
*
|
|
96
|
-
* @param value - The URL string
|
|
97
|
-
* @returns `true` if the value is a valid http/https URL
|
|
98
|
-
*
|
|
99
|
-
* @example isURL('https://example.com') // => true
|
|
100
|
-
* @example isURL('http://example.com:8080/path?q=1#f') // => true
|
|
101
|
-
* @example isURL('ftp://example.com') // => false
|
|
102
|
-
* @example isURL('not-a-url') // => false
|
|
103
|
-
*/
|
|
104
|
-
declare function isURL(value: string): boolean;
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Parse data dari NIK (Nomor Induk Kependudukan).
|
|
108
|
-
*
|
|
109
|
-
* @example parseNIK('3201010203940001')
|
|
110
|
-
* // { nik: '3201010203940001', valid: true, gender: 'LAKI-LAKI', birthDate: Date(1994-03-02), province: 'JAWA BARAT', city: 'BOGOR', district: 'CIAWI' }
|
|
111
|
-
*
|
|
112
|
-
* @example parseNIK('3201015203940001')
|
|
113
|
-
* // { nik: '3201015203940001', valid: true, gender: 'PEREMPUAN', birthDate: Date(1994-03-12), province: 'JAWA BARAT', ... }
|
|
114
|
-
*/
|
|
115
|
-
declare function parseNIK(value: string): NIKInfo;
|
|
116
|
-
interface NIKInfo {
|
|
117
|
-
nik: string;
|
|
118
|
-
valid: boolean;
|
|
119
|
-
gender: 'LAKI-LAKI' | 'PEREMPUAN' | null;
|
|
120
|
-
birthDate: Date | null;
|
|
121
|
-
province: string | null;
|
|
122
|
-
provinceCode: string | null;
|
|
123
|
-
city: string | null;
|
|
124
|
-
cityCode: string | null;
|
|
125
|
-
district: string | null;
|
|
126
|
-
districtCode: string | null;
|
|
127
|
-
uniqueCode: string | null;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Validasi Plat Nomor Kendaraan Bermotor Indonesia.
|
|
132
|
-
*
|
|
133
|
-
* Format: [KODE_DEPAN] [ANGKA] [KODE_BELAKANG]
|
|
134
|
-
* - Kode depan: 1-2 huruf (kode daerah)
|
|
135
|
-
* - Angka: 1-4 digit
|
|
136
|
-
* - Kode belakang: 1-3 huruf (opsional)
|
|
13
|
+
* Validasi nomor paspor Indonesia.
|
|
14
|
+
* Format: 2 huruf + 7 digit angka (total 9 karakter).
|
|
137
15
|
*
|
|
138
|
-
* @example
|
|
139
|
-
* @example
|
|
140
|
-
* @example isPlatNomor('B 1 A') // true
|
|
141
|
-
* @example isPlatNomor('INVALID') // false
|
|
16
|
+
* @example isPassport('AB1234567') // true
|
|
17
|
+
* @example isPassport('123456789') // false (harus ada huruf)
|
|
142
18
|
*/
|
|
143
|
-
declare function
|
|
19
|
+
declare function isPassport(value: string): boolean;
|
|
144
20
|
|
|
145
21
|
/**
|
|
146
|
-
* Validasi
|
|
147
|
-
*
|
|
22
|
+
* Validasi nomor BPJS Kesehatan Indonesia.
|
|
23
|
+
* Format: 13 digit angka.
|
|
148
24
|
*
|
|
149
|
-
* @example
|
|
150
|
-
* @example
|
|
151
|
-
* @example isKodepos('1234') // false (kurang)
|
|
152
|
-
* @example isKodepos('ABCDE') // false
|
|
25
|
+
* @example isNoBPJS('1234567890123') // true
|
|
26
|
+
* @example isNoBPJS('12345') // false
|
|
153
27
|
*/
|
|
154
|
-
declare function
|
|
28
|
+
declare function isNoBPJS(value: string): boolean;
|
|
155
29
|
|
|
156
30
|
/**
|
|
157
|
-
* Validasi
|
|
158
|
-
* Format:
|
|
31
|
+
* Validasi Nomor Kartu Keluarga (KK) Indonesia.
|
|
32
|
+
* Format: 16 digit angka.
|
|
159
33
|
*
|
|
160
|
-
* @example
|
|
161
|
-
* @example
|
|
162
|
-
* @example isNoRekening('1234567890123456') // true (16 digit - maksimum)
|
|
163
|
-
* @example isNoRekening('12345') // false (kurang dari 8 digit)
|
|
34
|
+
* @example isNoKK('1234567890123456') // true
|
|
35
|
+
* @example isNoKK('12345') // false
|
|
164
36
|
*/
|
|
165
|
-
declare function
|
|
37
|
+
declare function isNoKK(value: string): boolean;
|
|
166
38
|
|
|
167
|
-
export {
|
|
39
|
+
export { isNoBPJS, isNoKK, isNoSIM, isPassport };
|
package/dist/validation/index.js
CHANGED
|
@@ -361,12 +361,39 @@ function isNoRekening(value) {
|
|
|
361
361
|
if (digits.length < 8 || digits.length > 16) return false;
|
|
362
362
|
return true;
|
|
363
363
|
}
|
|
364
|
+
|
|
365
|
+
// src/validation/isNoSIM.ts
|
|
366
|
+
function isNoSIM(value) {
|
|
367
|
+
const digits = value.replace(/\D/g, "");
|
|
368
|
+
return digits.length === 12;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// src/validation/isPassport.ts
|
|
372
|
+
function isPassport(value) {
|
|
373
|
+
return /^[A-Za-z]{2}\d{7}$/.test(value.trim());
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// src/validation/isNoBPJS.ts
|
|
377
|
+
function isNoBPJS(value) {
|
|
378
|
+
const digits = value.replace(/\D/g, "");
|
|
379
|
+
return digits.length === 13;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// src/validation/isNoKK.ts
|
|
383
|
+
function isNoKK(value) {
|
|
384
|
+
const digits = value.replace(/\D/g, "");
|
|
385
|
+
return digits.length === 16;
|
|
386
|
+
}
|
|
364
387
|
export {
|
|
365
388
|
isEmail,
|
|
366
389
|
isKodepos,
|
|
367
390
|
isNIK,
|
|
368
391
|
isNPWP,
|
|
392
|
+
isNoBPJS,
|
|
393
|
+
isNoKK,
|
|
369
394
|
isNoRekening,
|
|
395
|
+
isNoSIM,
|
|
396
|
+
isPassport,
|
|
370
397
|
isPhone,
|
|
371
398
|
isPlatNomor,
|
|
372
399
|
isURL,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/validation/isNIK.ts","../../src/validation/isNPWP.ts","../../src/validation/isPhone.ts","../../src/validation/isEmail.ts","../../src/validation/isURL.ts","../../src/validation/parseNIK.ts","../../src/validation/isPlatNomor.ts","../../src/validation/isKodepos.ts","../../src/validation/isNoRekening.ts"],"sourcesContent":["/**\n * Validates an Indonesian NIK (Nomor Induk Kependudukan / Resident Identity Number).\n *\n * A valid NIK:\n * - Must be exactly 16 digits\n * - Structure: PP CC DD DDMMYY SSSS\n * - PP: Province code (2 digits)\n * - CC: City code (2 digits)\n * - DD: District code (2 digits)\n * - DDMMYY: Birth date (6 digits; for women the day is incremented by 40)\n * - SSSS: Serial number (4 digits)\n * - The birth date must correspond to a valid calendar date\n *\n * @param value - The NIK string (digits only or with dots)\n * @returns `true` if the value is a valid NIK\n *\n * @example isNIK('3201010203940001') // => true (male, born 2 March 1994)\n * @example isNIK('3201015203940001') // => true (female, born 12 March 1994)\n * @example isNIK('1234567890123456') // => false (invalid birth date)\n * @example isNIK('320101') // => false (too short)\n */\nexport function isNIK(value: string): boolean {\n const digits = value.replace(/\\D/g, '')\n if (digits.length !== 16) return false\n\n const rawDay = Number.parseInt(digits.slice(6, 8), 10)\n const month = Number.parseInt(digits.slice(8, 10), 10)\n const year = Number.parseInt(digits.slice(10, 12), 10)\n\n if (rawDay < 1 || rawDay > 71) return false\n if (month < 1 || month > 12) return false\n\n let day = rawDay\n if (day >= 41) day -= 40\n\n const fullYear = year < 70 ? 2000 + year : 1900 + year\n const date = new Date(fullYear, month - 1, day)\n\n return (\n date.getFullYear() === fullYear &&\n date.getMonth() === month - 1 &&\n date.getDate() === day\n )\n}\n","/**\n * Validates an Indonesian NPWP (Nomor Pokok Wajib Pajak / Tax Identification Number).\n *\n * A valid NPWP:\n * - Must be 15 or 16 digits (formatted: `XX.XXX.XXX.X-XXX.XXX` or plain digits)\n * - The last digit is a checksum computed from the preceding digits\n *\n * The checksum uses a weighted-sum algorithm with a repeating weight pattern of\n * `[3, 7, 1]`. The computed checksum must equal the last digit.\n *\n * @param value - The NPWP string (formatted with dots & dash, or plain digits)\n * @returns `true` if the value is a valid NPWP\n *\n * @example isNPWP('12.345.678.9-012.344') // => true\n * @example isNPWP('123456789012344') // => true (plain digits)\n * @example isNPWP('12.345.678.9-012.345') // => false (invalid checksum)\n */\nexport function isNPWP(value: string): boolean {\n const digits = value.replace(/\\D/g, '')\n if (digits.length !== 15 && digits.length !== 16) return false\n\n const nums: number[] = []\n for (let i = 0; i < digits.length; i++) {\n nums.push(Number.parseInt(digits[i]!, 10))\n }\n\n const checkDigit = nums[nums.length - 1]!\n\n let sum = 0\n for (let i = 0; i < nums.length - 1; i++) {\n sum += nums[i]! * [3, 7, 1][i % 3]!\n }\n\n const computed = (11 - (sum % 11)) % 10\n return computed === checkDigit\n}\n","const INDONESIAN_PREFIXES: ReadonlyArray<[number, number]> = [\n [11, 19],\n [21, 29],\n [51, 59],\n [77, 79],\n [95, 99],\n]\n\nfunction isValidIndonesianPrefix(prefix: number): boolean {\n for (const [min, max] of INDONESIAN_PREFIXES) {\n if (prefix >= min && prefix <= max) return true\n }\n return false\n}\n\n/**\n * Validates a phone number.\n *\n * For Indonesian numbers (`country = 'id'`):\n * - Accepted formats: `08xx…`, `+628xx…`, `628xx…`\n * - Must start with a valid operator prefix:\n * 0811-0819, 0821-0829, 0851-0859, 0877-0879, 0895-0899\n * - 10–13 digits after the country code\n *\n * For generic numbers (`country = 'any'`):\n * - Any string with 10–15 digits is accepted\n *\n * @param value - The phone number string\n * @param country - Country to validate against (`'id'` or `'any'`; default `'id'`)\n * @returns `true` if the value is a valid phone number\n *\n * @example isPhone('08123456789') // => true\n * @example isPhone('+628123456789') // => true\n * @example isPhone('628123456789') // => true\n * @example isPhone('081234567') // => false (too short)\n * @example isPhone('089123456789') // => false (invalid prefix 91)\n */\nexport function isPhone(value: string, country: 'id' | 'any' = 'id'): boolean {\n const digits = value.replace(/\\D/g, '')\n\n if (country === 'any') {\n return digits.length >= 10 && digits.length <= 15\n }\n\n if (digits.length < 10) return false\n\n let normalized: string\n if (digits.startsWith('62')) {\n normalized = digits.slice(2)\n } else if (digits.startsWith('0')) {\n normalized = digits.slice(1)\n } else {\n normalized = digits\n }\n\n if (normalized.length < 10 || normalized.length > 13) return false\n if (!normalized.startsWith('8')) return false\n\n const prefix = Number.parseInt(normalized.slice(1, 3), 10)\n return isValidIndonesianPrefix(prefix)\n}\n","const LOCAL_SPECIAL = \"!#$%&'*+/=?^_`{|}~-\"\n\nfunction isQuotedLocalPart(local: string): boolean {\n if (local.length < 2) return false\n let i = 1\n while (i < local.length - 1) {\n const ch = local[i]!\n if (ch === '\\\\') {\n i++\n if (i >= local.length - 1) return false\n } else if (ch === '\"') {\n return false\n }\n i++\n }\n return true\n}\n\nfunction isUnquotedLocalPart(local: string): boolean {\n if (local.length === 0 || local.startsWith('.') || local.endsWith('.')) return false\n\n for (let i = 0; i < local.length; i++) {\n const ch = local[i]!\n if (\n (ch >= 'a' && ch <= 'z') ||\n (ch >= 'A' && ch <= 'Z') ||\n (ch >= '0' && ch <= '9') ||\n ch === '.' ||\n LOCAL_SPECIAL.includes(ch)\n ) {\n continue\n }\n return false\n }\n\n for (let i = 1; i < local.length; i++) {\n if (local[i] === '.' && local[i - 1] === '.') return false\n }\n\n return true\n}\n\nfunction isValidDomain(domain: string): boolean {\n if (domain.length === 0 || domain.startsWith('.') || domain.endsWith('.')) return false\n\n const labels = domain.split('.')\n if (labels.length < 2) return false\n\n for (const label of labels) {\n if (label.length === 0 || label.length > 63) return false\n if (label.startsWith('-') || label.endsWith('-')) return false\n\n for (let i = 0; i < label.length; i++) {\n const ch = label[i]!\n if (\n !(\n (ch >= 'a' && ch <= 'z') ||\n (ch >= 'A' && ch <= 'Z') ||\n (ch >= '0' && ch <= '9') ||\n ch === '-'\n )\n ) {\n return false\n }\n }\n }\n\n return true\n}\n\n/**\n * RFC‑compliant email address validation.\n *\n * Validation rules:\n * - Total length ≤ 254 characters\n * - Local part ≤ 64 characters; supports quoted strings (including escaped\n * characters), unquoted letters / digits / `!#$%&'*+/=?^_`{|}~-`, and dots\n * (no leading, trailing, or consecutive dots)\n * - Domain part ≤ 255 characters; valid DNS labels separated by dots, each\n * label ≤ 63 characters, no leading/trailing hyphens, at least two labels\n *\n * @param value - The email address string\n * @returns `true` if the value is a syntactically valid email address\n *\n * @example isEmail('user@example.com') // => true\n * @example isEmail('user.name+tag@example.co.id') // => true\n * @example isEmail('\"quoted@local\"@example.com') // => true\n * @example isEmail('not-an-email') // => false\n */\nexport function isEmail(value: string): boolean {\n if (value.length > 254) return false\n\n const atIndex = value.lastIndexOf('@')\n if (atIndex < 1 || atIndex === value.length - 1) return false\n\n const localPart = value.slice(0, atIndex)\n const domainPart = value.slice(atIndex + 1)\n\n if (localPart.length > 64) return false\n if (domainPart.length > 255) return false\n\n if (localPart.startsWith('\"') && localPart.endsWith('\"')) {\n if (!isQuotedLocalPart(localPart)) return false\n } else {\n if (!isUnquotedLocalPart(localPart)) return false\n }\n\n return isValidDomain(domainPart)\n}\n","const IPV4_OCTET = /^(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/\n\nfunction isValidIPv4(hostname: string): boolean {\n const octets = hostname.split('.')\n if (octets.length !== 4) return false\n return octets.every(octet => IPV4_OCTET.test(octet))\n}\n\nfunction isValidDNSHostname(hostname: string): boolean {\n if (hostname.startsWith('.') || hostname.endsWith('.')) return false\n\n const labels = hostname.split('.')\n if (labels.length < 2) return false\n\n for (const label of labels) {\n if (label.length === 0 || label.length > 63) return false\n if (label.startsWith('-') || label.endsWith('-')) return false\n\n for (let i = 0; i < label.length; i++) {\n const ch = label[i]!\n if (\n !(\n (ch >= 'a' && ch <= 'z') ||\n (ch >= 'A' && ch <= 'Z') ||\n (ch >= '0' && ch <= '9') ||\n ch === '-'\n )\n ) {\n return false\n }\n }\n }\n\n return true\n}\n\nfunction isValidHostname(hostname: string): boolean {\n if (hostname.length === 0) return false\n\n // IPv6 literal\n if (hostname.startsWith('[') && hostname.endsWith(']')) {\n return hostname.length > 2\n }\n\n // IPv4\n if (/^\\d/.test(hostname) || /\\d$/.test(hostname)) {\n if (isValidIPv4(hostname)) return true\n }\n\n // localhost\n if (hostname === 'localhost') return true\n\n // DNS hostname\n return isValidDNSHostname(hostname)\n}\n\n/**\n * Validates a URL.\n *\n * A valid URL:\n * - Must use the `http` or `https` protocol\n * - Must have a valid hostname (DNS name, IPv4, IPv6 literal, or `localhost`)\n * - May include an optional port, path, query string, and fragment\n *\n * @param value - The URL string\n * @returns `true` if the value is a valid http/https URL\n *\n * @example isURL('https://example.com') // => true\n * @example isURL('http://example.com:8080/path?q=1#f') // => true\n * @example isURL('ftp://example.com') // => false\n * @example isURL('not-a-url') // => false\n */\nexport function isURL(value: string): boolean {\n try {\n const url = new URL(value)\n\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n return false\n }\n\n return isValidHostname(url.hostname)\n } catch {\n return false\n }\n}\n","/**\n * Parse data dari NIK (Nomor Induk Kependudukan).\n *\n * @example parseNIK('3201010203940001')\n * // { nik: '3201010203940001', valid: true, gender: 'LAKI-LAKI', birthDate: Date(1994-03-02), province: 'JAWA BARAT', city: 'BOGOR', district: 'CIAWI' }\n *\n * @example parseNIK('3201015203940001')\n * // { nik: '3201015203940001', valid: true, gender: 'PEREMPUAN', birthDate: Date(1994-03-12), province: 'JAWA BARAT', ... }\n */\nexport function parseNIK(value: string): NIKInfo {\n const digits = value.replace(/\\D/g, '')\n const info: NIKInfo = {\n nik: value,\n valid: false,\n gender: null,\n birthDate: null,\n province: null,\n provinceCode: null,\n city: null,\n cityCode: null,\n district: null,\n districtCode: null,\n uniqueCode: null,\n }\n\n if (digits.length !== 16) return info\n\n const provinceCode = digits.slice(0, 2)\n const cityCode = digits.slice(2, 4)\n const districtCode = digits.slice(4, 6)\n const rawDay = Number.parseInt(digits.slice(6, 8), 10)\n const month = Number.parseInt(digits.slice(8, 10), 10)\n const year = Number.parseInt(digits.slice(10, 12), 10)\n const uniqueCode = digits.slice(12, 16)\n\n if (rawDay < 1 || rawDay > 71 || month < 1 || month > 12) return info\n\n const gender: 'LAKI-LAKI' | 'PEREMPUAN' = rawDay >= 41 ? 'PEREMPUAN' : 'LAKI-LAKI'\n let day = rawDay\n if (day >= 41) day -= 40\n\n const fullYear = year < 70 ? 2000 + year : 1900 + year\n const birthDate = new Date(fullYear, month - 1, day)\n\n if (\n birthDate.getFullYear() !== fullYear ||\n birthDate.getMonth() !== month - 1 ||\n birthDate.getDate() !== day\n ) {\n return info\n }\n\n return {\n nik: value,\n valid: true,\n gender,\n birthDate,\n province: PROVINCE_CODES[provinceCode] ?? null,\n provinceCode,\n city: null,\n cityCode,\n district: null,\n districtCode,\n uniqueCode,\n }\n}\n\nexport interface NIKInfo {\n nik: string\n valid: boolean\n gender: 'LAKI-LAKI' | 'PEREMPUAN' | null\n birthDate: Date | null\n province: string | null\n provinceCode: string | null\n city: string | null\n cityCode: string | null\n district: string | null\n districtCode: string | null\n uniqueCode: string | null\n}\n\nconst PROVINCE_CODES: Record<string, string> = {\n '11': 'ACEH',\n '12': 'SUMATERA UTARA',\n '13': 'SUMATERA BARAT',\n '14': 'RIAU',\n '15': 'JAMBI',\n '16': 'SUMATERA SELATAN',\n '17': 'BENGKULU',\n '18': 'LAMPUNG',\n '19': 'KEPULAUAN BANGKA BELITUNG',\n '21': 'KEPULAUAN RIAU',\n '31': 'DKI JAKARTA',\n '32': 'JAWA BARAT',\n '33': 'JAWA TENGAH',\n '34': 'DI YOGYAKARTA',\n '35': 'JAWA TIMUR',\n '36': 'BANTEN',\n '51': 'BALI',\n '52': 'NUSA TENGGARA BARAT',\n '53': 'NUSA TENGGARA TIMUR',\n '61': 'KALIMANTAN BARAT',\n '62': 'KALIMANTAN TENGAH',\n '63': 'KALIMANTAN SELATAN',\n '64': 'KALIMANTAN TIMUR',\n '65': 'KALIMANTAN UTARA',\n '71': 'SULAWESI UTARA',\n '72': 'SULAWESI TENGAH',\n '73': 'SULAWESI SELATAN',\n '74': 'SULAWESI TENGGARA',\n '75': 'GORONTALO',\n '76': 'SULAWESI BARAT',\n '81': 'MALUKU',\n '82': 'MALUKU UTARA',\n '91': 'PAPUA',\n '92': 'PAPUA BARAT',\n '93': 'PAPUA SELATAN',\n '94': 'PAPUA TENGAH',\n '95': 'PAPUA PEGUNUNGAN',\n}\n","/**\n * Validasi Plat Nomor Kendaraan Bermotor Indonesia.\n *\n * Format: [KODE_DEPAN] [ANGKA] [KODE_BELAKANG]\n * - Kode depan: 1-2 huruf (kode daerah)\n * - Angka: 1-4 digit\n * - Kode belakang: 1-3 huruf (opsional)\n *\n * @example isPlatNomor('B 1234 CD') // true (Jakarta)\n * @example isPlatNomor('AB 5678 XYZ') // true\n * @example isPlatNomor('B 1 A') // true\n * @example isPlatNomor('INVALID') // false\n */\nexport function isPlatNomor(value: string): boolean {\n const trimmed = value.trim().toUpperCase()\n const regex = /^([A-Z]{1,2})\\s*(\\d{1,4})\\s*([A-Z]{0,3})$/\n const match = trimmed.match(regex)\n if (!match) return false\n\n const kodeDepan = match[1]!\n const angka = parseInt(match[2]!, 10)\n const kodeBelakang = match[3] || ''\n\n if (!KODE_DAERAH.includes(kodeDepan)) return false\n if (angka < 1 || angka > 9999) return false\n if (kodeBelakang.length > 3) return false\n return true\n}\n\nconst KODE_DAERAH = [\n 'A', 'AA', 'AB', 'AD', 'AE', 'AG', 'B', 'BA', 'BB', 'BD', 'BE', 'BG',\n 'BH', 'BK', 'BL', 'BM', 'BN', 'BP', 'BR', 'BT', 'BU', 'BV', 'BW', 'D',\n 'DA', 'DB', 'DC', 'DD', 'DE', 'DF', 'DG', 'DH', 'DK', 'DL', 'DM', 'DN',\n 'DP', 'DR', 'DT', 'DU', 'DW', 'E', 'EA', 'EB', 'ED', 'EE', 'F', 'G',\n 'H', 'K', 'KB', 'KH', 'KI', 'KU', 'KT', 'L', 'M', 'N', 'NB', 'NG',\n 'NK', 'NM', 'P', 'PA', 'PB', 'R', 'S', 'ST', 'T', 'W', 'Z',\n]\n","/**\n * Validasi kode pos Indonesia.\n * Kode pos Indonesia terdiri dari 5 digit angka.\n *\n * @example isKodepos('16110') // true (Bogor)\n * @example isKodepos('12345') // true\n * @example isKodepos('1234') // false (kurang)\n * @example isKodepos('ABCDE') // false\n */\nexport function isKodepos(value: string): boolean {\n if (value.length !== 5) return false\n return /^\\d{5}$/.test(value)\n}\n","/**\n * Validasi nomor rekening bank Indonesia.\n * Format: 8-16 digit angka (tergantung bank).\n *\n * @example isNoRekening('1234567890') // true (10 digit)\n * @example isNoRekening('12345678') // true (8 digit - minimum)\n * @example isNoRekening('1234567890123456') // true (16 digit - maksimum)\n * @example isNoRekening('12345') // false (kurang dari 8 digit)\n */\nexport function isNoRekening(value: string): boolean {\n const digits = value.replace(/\\D/g, '')\n if (digits.length < 8 || digits.length > 16) return false\n return true\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/validation/isNIK.ts","../../src/validation/isNPWP.ts","../../src/validation/isPhone.ts","../../src/validation/isEmail.ts","../../src/validation/isURL.ts","../../src/validation/parseNIK.ts","../../src/validation/isPlatNomor.ts","../../src/validation/isKodepos.ts","../../src/validation/isNoRekening.ts","../../src/validation/isNoSIM.ts","../../src/validation/isPassport.ts","../../src/validation/isNoBPJS.ts","../../src/validation/isNoKK.ts"],"sourcesContent":["/**\n * Validates an Indonesian NIK (Nomor Induk Kependudukan / Resident Identity Number).\n *\n * A valid NIK:\n * - Must be exactly 16 digits\n * - Structure: PP CC DD DDMMYY SSSS\n * - PP: Province code (2 digits)\n * - CC: City code (2 digits)\n * - DD: District code (2 digits)\n * - DDMMYY: Birth date (6 digits; for women the day is incremented by 40)\n * - SSSS: Serial number (4 digits)\n * - The birth date must correspond to a valid calendar date\n *\n * @param value - The NIK string (digits only or with dots)\n * @returns `true` if the value is a valid NIK\n *\n * @example isNIK('3201010203940001') // => true (male, born 2 March 1994)\n * @example isNIK('3201015203940001') // => true (female, born 12 March 1994)\n * @example isNIK('1234567890123456') // => false (invalid birth date)\n * @example isNIK('320101') // => false (too short)\n */\nexport function isNIK(value: string): boolean {\n const digits = value.replace(/\\D/g, '')\n if (digits.length !== 16) return false\n\n const rawDay = Number.parseInt(digits.slice(6, 8), 10)\n const month = Number.parseInt(digits.slice(8, 10), 10)\n const year = Number.parseInt(digits.slice(10, 12), 10)\n\n if (rawDay < 1 || rawDay > 71) return false\n if (month < 1 || month > 12) return false\n\n let day = rawDay\n if (day >= 41) day -= 40\n\n const fullYear = year < 70 ? 2000 + year : 1900 + year\n const date = new Date(fullYear, month - 1, day)\n\n return (\n date.getFullYear() === fullYear &&\n date.getMonth() === month - 1 &&\n date.getDate() === day\n )\n}\n","/**\n * Validates an Indonesian NPWP (Nomor Pokok Wajib Pajak / Tax Identification Number).\n *\n * A valid NPWP:\n * - Must be 15 or 16 digits (formatted: `XX.XXX.XXX.X-XXX.XXX` or plain digits)\n * - The last digit is a checksum computed from the preceding digits\n *\n * The checksum uses a weighted-sum algorithm with a repeating weight pattern of\n * `[3, 7, 1]`. The computed checksum must equal the last digit.\n *\n * @param value - The NPWP string (formatted with dots & dash, or plain digits)\n * @returns `true` if the value is a valid NPWP\n *\n * @example isNPWP('12.345.678.9-012.344') // => true\n * @example isNPWP('123456789012344') // => true (plain digits)\n * @example isNPWP('12.345.678.9-012.345') // => false (invalid checksum)\n */\nexport function isNPWP(value: string): boolean {\n const digits = value.replace(/\\D/g, '')\n if (digits.length !== 15 && digits.length !== 16) return false\n\n const nums: number[] = []\n for (let i = 0; i < digits.length; i++) {\n nums.push(Number.parseInt(digits[i]!, 10))\n }\n\n const checkDigit = nums[nums.length - 1]!\n\n let sum = 0\n for (let i = 0; i < nums.length - 1; i++) {\n sum += nums[i]! * [3, 7, 1][i % 3]!\n }\n\n const computed = (11 - (sum % 11)) % 10\n return computed === checkDigit\n}\n","const INDONESIAN_PREFIXES: ReadonlyArray<[number, number]> = [\n [11, 19],\n [21, 29],\n [51, 59],\n [77, 79],\n [95, 99],\n]\n\nfunction isValidIndonesianPrefix(prefix: number): boolean {\n for (const [min, max] of INDONESIAN_PREFIXES) {\n if (prefix >= min && prefix <= max) return true\n }\n return false\n}\n\n/**\n * Validates a phone number.\n *\n * For Indonesian numbers (`country = 'id'`):\n * - Accepted formats: `08xx…`, `+628xx…`, `628xx…`\n * - Must start with a valid operator prefix:\n * 0811-0819, 0821-0829, 0851-0859, 0877-0879, 0895-0899\n * - 10–13 digits after the country code\n *\n * For generic numbers (`country = 'any'`):\n * - Any string with 10–15 digits is accepted\n *\n * @param value - The phone number string\n * @param country - Country to validate against (`'id'` or `'any'`; default `'id'`)\n * @returns `true` if the value is a valid phone number\n *\n * @example isPhone('08123456789') // => true\n * @example isPhone('+628123456789') // => true\n * @example isPhone('628123456789') // => true\n * @example isPhone('081234567') // => false (too short)\n * @example isPhone('089123456789') // => false (invalid prefix 91)\n */\nexport function isPhone(value: string, country: 'id' | 'any' = 'id'): boolean {\n const digits = value.replace(/\\D/g, '')\n\n if (country === 'any') {\n return digits.length >= 10 && digits.length <= 15\n }\n\n if (digits.length < 10) return false\n\n let normalized: string\n if (digits.startsWith('62')) {\n normalized = digits.slice(2)\n } else if (digits.startsWith('0')) {\n normalized = digits.slice(1)\n } else {\n normalized = digits\n }\n\n if (normalized.length < 10 || normalized.length > 13) return false\n if (!normalized.startsWith('8')) return false\n\n const prefix = Number.parseInt(normalized.slice(1, 3), 10)\n return isValidIndonesianPrefix(prefix)\n}\n","const LOCAL_SPECIAL = \"!#$%&'*+/=?^_`{|}~-\"\n\nfunction isQuotedLocalPart(local: string): boolean {\n if (local.length < 2) return false\n let i = 1\n while (i < local.length - 1) {\n const ch = local[i]!\n if (ch === '\\\\') {\n i++\n if (i >= local.length - 1) return false\n } else if (ch === '\"') {\n return false\n }\n i++\n }\n return true\n}\n\nfunction isUnquotedLocalPart(local: string): boolean {\n if (local.length === 0 || local.startsWith('.') || local.endsWith('.')) return false\n\n for (let i = 0; i < local.length; i++) {\n const ch = local[i]!\n if (\n (ch >= 'a' && ch <= 'z') ||\n (ch >= 'A' && ch <= 'Z') ||\n (ch >= '0' && ch <= '9') ||\n ch === '.' ||\n LOCAL_SPECIAL.includes(ch)\n ) {\n continue\n }\n return false\n }\n\n for (let i = 1; i < local.length; i++) {\n if (local[i] === '.' && local[i - 1] === '.') return false\n }\n\n return true\n}\n\nfunction isValidDomain(domain: string): boolean {\n if (domain.length === 0 || domain.startsWith('.') || domain.endsWith('.')) return false\n\n const labels = domain.split('.')\n if (labels.length < 2) return false\n\n for (const label of labels) {\n if (label.length === 0 || label.length > 63) return false\n if (label.startsWith('-') || label.endsWith('-')) return false\n\n for (let i = 0; i < label.length; i++) {\n const ch = label[i]!\n if (\n !(\n (ch >= 'a' && ch <= 'z') ||\n (ch >= 'A' && ch <= 'Z') ||\n (ch >= '0' && ch <= '9') ||\n ch === '-'\n )\n ) {\n return false\n }\n }\n }\n\n return true\n}\n\n/**\n * RFC‑compliant email address validation.\n *\n * Validation rules:\n * - Total length ≤ 254 characters\n * - Local part ≤ 64 characters; supports quoted strings (including escaped\n * characters), unquoted letters / digits / `!#$%&'*+/=?^_`{|}~-`, and dots\n * (no leading, trailing, or consecutive dots)\n * - Domain part ≤ 255 characters; valid DNS labels separated by dots, each\n * label ≤ 63 characters, no leading/trailing hyphens, at least two labels\n *\n * @param value - The email address string\n * @returns `true` if the value is a syntactically valid email address\n *\n * @example isEmail('user@example.com') // => true\n * @example isEmail('user.name+tag@example.co.id') // => true\n * @example isEmail('\"quoted@local\"@example.com') // => true\n * @example isEmail('not-an-email') // => false\n */\nexport function isEmail(value: string): boolean {\n if (value.length > 254) return false\n\n const atIndex = value.lastIndexOf('@')\n if (atIndex < 1 || atIndex === value.length - 1) return false\n\n const localPart = value.slice(0, atIndex)\n const domainPart = value.slice(atIndex + 1)\n\n if (localPart.length > 64) return false\n if (domainPart.length > 255) return false\n\n if (localPart.startsWith('\"') && localPart.endsWith('\"')) {\n if (!isQuotedLocalPart(localPart)) return false\n } else {\n if (!isUnquotedLocalPart(localPart)) return false\n }\n\n return isValidDomain(domainPart)\n}\n","const IPV4_OCTET = /^(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/\n\nfunction isValidIPv4(hostname: string): boolean {\n const octets = hostname.split('.')\n if (octets.length !== 4) return false\n return octets.every(octet => IPV4_OCTET.test(octet))\n}\n\nfunction isValidDNSHostname(hostname: string): boolean {\n if (hostname.startsWith('.') || hostname.endsWith('.')) return false\n\n const labels = hostname.split('.')\n if (labels.length < 2) return false\n\n for (const label of labels) {\n if (label.length === 0 || label.length > 63) return false\n if (label.startsWith('-') || label.endsWith('-')) return false\n\n for (let i = 0; i < label.length; i++) {\n const ch = label[i]!\n if (\n !(\n (ch >= 'a' && ch <= 'z') ||\n (ch >= 'A' && ch <= 'Z') ||\n (ch >= '0' && ch <= '9') ||\n ch === '-'\n )\n ) {\n return false\n }\n }\n }\n\n return true\n}\n\nfunction isValidHostname(hostname: string): boolean {\n if (hostname.length === 0) return false\n\n // IPv6 literal\n if (hostname.startsWith('[') && hostname.endsWith(']')) {\n return hostname.length > 2\n }\n\n // IPv4\n if (/^\\d/.test(hostname) || /\\d$/.test(hostname)) {\n if (isValidIPv4(hostname)) return true\n }\n\n // localhost\n if (hostname === 'localhost') return true\n\n // DNS hostname\n return isValidDNSHostname(hostname)\n}\n\n/**\n * Validates a URL.\n *\n * A valid URL:\n * - Must use the `http` or `https` protocol\n * - Must have a valid hostname (DNS name, IPv4, IPv6 literal, or `localhost`)\n * - May include an optional port, path, query string, and fragment\n *\n * @param value - The URL string\n * @returns `true` if the value is a valid http/https URL\n *\n * @example isURL('https://example.com') // => true\n * @example isURL('http://example.com:8080/path?q=1#f') // => true\n * @example isURL('ftp://example.com') // => false\n * @example isURL('not-a-url') // => false\n */\nexport function isURL(value: string): boolean {\n try {\n const url = new URL(value)\n\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n return false\n }\n\n return isValidHostname(url.hostname)\n } catch {\n return false\n }\n}\n","/**\n * Parse data dari NIK (Nomor Induk Kependudukan).\n *\n * @example parseNIK('3201010203940001')\n * // { nik: '3201010203940001', valid: true, gender: 'LAKI-LAKI', birthDate: Date(1994-03-02), province: 'JAWA BARAT', city: 'BOGOR', district: 'CIAWI' }\n *\n * @example parseNIK('3201015203940001')\n * // { nik: '3201015203940001', valid: true, gender: 'PEREMPUAN', birthDate: Date(1994-03-12), province: 'JAWA BARAT', ... }\n */\nexport function parseNIK(value: string): NIKInfo {\n const digits = value.replace(/\\D/g, '')\n const info: NIKInfo = {\n nik: value,\n valid: false,\n gender: null,\n birthDate: null,\n province: null,\n provinceCode: null,\n city: null,\n cityCode: null,\n district: null,\n districtCode: null,\n uniqueCode: null,\n }\n\n if (digits.length !== 16) return info\n\n const provinceCode = digits.slice(0, 2)\n const cityCode = digits.slice(2, 4)\n const districtCode = digits.slice(4, 6)\n const rawDay = Number.parseInt(digits.slice(6, 8), 10)\n const month = Number.parseInt(digits.slice(8, 10), 10)\n const year = Number.parseInt(digits.slice(10, 12), 10)\n const uniqueCode = digits.slice(12, 16)\n\n if (rawDay < 1 || rawDay > 71 || month < 1 || month > 12) return info\n\n const gender: 'LAKI-LAKI' | 'PEREMPUAN' = rawDay >= 41 ? 'PEREMPUAN' : 'LAKI-LAKI'\n let day = rawDay\n if (day >= 41) day -= 40\n\n const fullYear = year < 70 ? 2000 + year : 1900 + year\n const birthDate = new Date(fullYear, month - 1, day)\n\n if (\n birthDate.getFullYear() !== fullYear ||\n birthDate.getMonth() !== month - 1 ||\n birthDate.getDate() !== day\n ) {\n return info\n }\n\n return {\n nik: value,\n valid: true,\n gender,\n birthDate,\n province: PROVINCE_CODES[provinceCode] ?? null,\n provinceCode,\n city: null,\n cityCode,\n district: null,\n districtCode,\n uniqueCode,\n }\n}\n\nexport interface NIKInfo {\n nik: string\n valid: boolean\n gender: 'LAKI-LAKI' | 'PEREMPUAN' | null\n birthDate: Date | null\n province: string | null\n provinceCode: string | null\n city: string | null\n cityCode: string | null\n district: string | null\n districtCode: string | null\n uniqueCode: string | null\n}\n\nconst PROVINCE_CODES: Record<string, string> = {\n '11': 'ACEH',\n '12': 'SUMATERA UTARA',\n '13': 'SUMATERA BARAT',\n '14': 'RIAU',\n '15': 'JAMBI',\n '16': 'SUMATERA SELATAN',\n '17': 'BENGKULU',\n '18': 'LAMPUNG',\n '19': 'KEPULAUAN BANGKA BELITUNG',\n '21': 'KEPULAUAN RIAU',\n '31': 'DKI JAKARTA',\n '32': 'JAWA BARAT',\n '33': 'JAWA TENGAH',\n '34': 'DI YOGYAKARTA',\n '35': 'JAWA TIMUR',\n '36': 'BANTEN',\n '51': 'BALI',\n '52': 'NUSA TENGGARA BARAT',\n '53': 'NUSA TENGGARA TIMUR',\n '61': 'KALIMANTAN BARAT',\n '62': 'KALIMANTAN TENGAH',\n '63': 'KALIMANTAN SELATAN',\n '64': 'KALIMANTAN TIMUR',\n '65': 'KALIMANTAN UTARA',\n '71': 'SULAWESI UTARA',\n '72': 'SULAWESI TENGAH',\n '73': 'SULAWESI SELATAN',\n '74': 'SULAWESI TENGGARA',\n '75': 'GORONTALO',\n '76': 'SULAWESI BARAT',\n '81': 'MALUKU',\n '82': 'MALUKU UTARA',\n '91': 'PAPUA',\n '92': 'PAPUA BARAT',\n '93': 'PAPUA SELATAN',\n '94': 'PAPUA TENGAH',\n '95': 'PAPUA PEGUNUNGAN',\n}\n","/**\n * Validasi Plat Nomor Kendaraan Bermotor Indonesia.\n *\n * Format: [KODE_DEPAN] [ANGKA] [KODE_BELAKANG]\n * - Kode depan: 1-2 huruf (kode daerah)\n * - Angka: 1-4 digit\n * - Kode belakang: 1-3 huruf (opsional)\n *\n * @example isPlatNomor('B 1234 CD') // true (Jakarta)\n * @example isPlatNomor('AB 5678 XYZ') // true\n * @example isPlatNomor('B 1 A') // true\n * @example isPlatNomor('INVALID') // false\n */\nexport function isPlatNomor(value: string): boolean {\n const trimmed = value.trim().toUpperCase()\n const regex = /^([A-Z]{1,2})\\s*(\\d{1,4})\\s*([A-Z]{0,3})$/\n const match = trimmed.match(regex)\n if (!match) return false\n\n const kodeDepan = match[1]!\n const angka = parseInt(match[2]!, 10)\n const kodeBelakang = match[3] || ''\n\n if (!KODE_DAERAH.includes(kodeDepan)) return false\n if (angka < 1 || angka > 9999) return false\n if (kodeBelakang.length > 3) return false\n return true\n}\n\nconst KODE_DAERAH = [\n 'A', 'AA', 'AB', 'AD', 'AE', 'AG', 'B', 'BA', 'BB', 'BD', 'BE', 'BG',\n 'BH', 'BK', 'BL', 'BM', 'BN', 'BP', 'BR', 'BT', 'BU', 'BV', 'BW', 'D',\n 'DA', 'DB', 'DC', 'DD', 'DE', 'DF', 'DG', 'DH', 'DK', 'DL', 'DM', 'DN',\n 'DP', 'DR', 'DT', 'DU', 'DW', 'E', 'EA', 'EB', 'ED', 'EE', 'F', 'G',\n 'H', 'K', 'KB', 'KH', 'KI', 'KU', 'KT', 'L', 'M', 'N', 'NB', 'NG',\n 'NK', 'NM', 'P', 'PA', 'PB', 'R', 'S', 'ST', 'T', 'W', 'Z',\n]\n","/**\n * Validasi kode pos Indonesia.\n * Kode pos Indonesia terdiri dari 5 digit angka.\n *\n * @example isKodepos('16110') // true (Bogor)\n * @example isKodepos('12345') // true\n * @example isKodepos('1234') // false (kurang)\n * @example isKodepos('ABCDE') // false\n */\nexport function isKodepos(value: string): boolean {\n if (value.length !== 5) return false\n return /^\\d{5}$/.test(value)\n}\n","/**\n * Validasi nomor rekening bank Indonesia.\n * Format: 8-16 digit angka (tergantung bank).\n *\n * @example isNoRekening('1234567890') // true (10 digit)\n * @example isNoRekening('12345678') // true (8 digit - minimum)\n * @example isNoRekening('1234567890123456') // true (16 digit - maksimum)\n * @example isNoRekening('12345') // false (kurang dari 8 digit)\n */\nexport function isNoRekening(value: string): boolean {\n const digits = value.replace(/\\D/g, '')\n if (digits.length < 8 || digits.length > 16) return false\n return true\n}\n","/**\n * Validasi Nomor SIM Indonesia.\n * Format: 12 digit angka (2 digit golongan + 6 digit tanggal lahir + 4 digit nomor seri).\n *\n * @example isNoSIM('123456789012') // true (12 digit)\n * @example isNoSIM('12345') // false\n */\nexport function isNoSIM(value: string): boolean {\n const digits = value.replace(/\\D/g, '')\n return digits.length === 12\n}\n","/**\n * Validasi nomor paspor Indonesia.\n * Format: 2 huruf + 7 digit angka (total 9 karakter).\n *\n * @example isPassport('AB1234567') // true\n * @example isPassport('123456789') // false (harus ada huruf)\n */\nexport function isPassport(value: string): boolean {\n return /^[A-Za-z]{2}\\d{7}$/.test(value.trim())\n}\n","/**\n * Validasi nomor BPJS Kesehatan Indonesia.\n * Format: 13 digit angka.\n *\n * @example isNoBPJS('1234567890123') // true\n * @example isNoBPJS('12345') // false\n */\nexport function isNoBPJS(value: string): boolean {\n const digits = value.replace(/\\D/g, '')\n return digits.length === 13\n}\n","/**\n * Validasi Nomor Kartu Keluarga (KK) Indonesia.\n * Format: 16 digit angka.\n *\n * @example isNoKK('1234567890123456') // true\n * @example isNoKK('12345') // false\n */\nexport function isNoKK(value: string): boolean {\n const digits = value.replace(/\\D/g, '')\n return digits.length === 16\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "superjs-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "JavaScript toolkit all-in-one buat developer Indonesia: validasi NIK/NPWP/Phone, terbilang, formatRupiah, timeAgo (WIB/WITA/WIT), deepClone, logger, dep scanner. 100+ fungsi, zero dep runtime.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -105,7 +105,8 @@
|
|
|
105
105
|
},
|
|
106
106
|
"sideEffects": false,
|
|
107
107
|
"files": [
|
|
108
|
-
"dist"
|
|
108
|
+
"dist",
|
|
109
|
+
"*.md"
|
|
109
110
|
],
|
|
110
111
|
"scripts": {
|
|
111
112
|
"build": "tsup",
|