@indodev/toolkit 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/email-validator/index.cjs +10 -0
- package/dist/email-validator/index.cjs.map +1 -1
- package/dist/email-validator/index.d.cts +1 -1
- package/dist/email-validator/index.d.ts +1 -1
- package/dist/email-validator/index.js +10 -1
- package/dist/email-validator/index.js.map +1 -1
- package/dist/{parse-BmmsNlJt.d.cts → errors--47zprcf.d.cts} +41 -7
- package/dist/{parse-BmmsNlJt.d.ts → errors--47zprcf.d.ts} +41 -7
- package/dist/{email-validator-R9L5unIw.d.cts → errors-DdutHLae.d.cts} +23 -1
- package/dist/{email-validator-R9L5unIw.d.ts → errors-DdutHLae.d.ts} +23 -1
- package/dist/index.cjs +317 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +310 -39
- package/dist/index.js.map +1 -1
- package/dist/{compare-Ku_8OhuU.d.cts → mask-CToJqmrd.d.cts} +79 -1
- package/dist/{compare-Ku_8OhuU.d.ts → mask-CToJqmrd.d.ts} +79 -1
- package/dist/nik/index.cjs +177 -24
- package/dist/nik/index.cjs.map +1 -1
- package/dist/nik/index.d.cts +24 -330
- package/dist/nik/index.d.ts +24 -330
- package/dist/nik/index.js +174 -25
- package/dist/nik/index.js.map +1 -1
- package/dist/npwp/index.cjs +10 -0
- package/dist/npwp/index.cjs.map +1 -1
- package/dist/npwp/index.d.cts +23 -1
- package/dist/npwp/index.d.ts +23 -1
- package/dist/npwp/index.js +10 -1
- package/dist/npwp/index.js.map +1 -1
- package/dist/parse-B3UzEHq3.d.cts +155 -0
- package/dist/parse-B3UzEHq3.d.ts +155 -0
- package/dist/parse-DlrgrRfY.d.cts +155 -0
- package/dist/parse-DlrgrRfY.d.ts +155 -0
- package/dist/phone/index.cjs +36 -12
- package/dist/phone/index.cjs.map +1 -1
- package/dist/phone/index.d.cts +1 -1
- package/dist/phone/index.d.ts +1 -1
- package/dist/phone/index.js +36 -13
- package/dist/phone/index.js.map +1 -1
- package/dist/plate/index.cjs +57 -0
- package/dist/plate/index.cjs.map +1 -1
- package/dist/plate/index.d.cts +1 -1
- package/dist/plate/index.d.ts +1 -1
- package/dist/plate/index.js +56 -1
- package/dist/plate/index.js.map +1 -1
- package/dist/text/index.cjs +31 -8
- package/dist/text/index.cjs.map +1 -1
- package/dist/text/index.d.cts +2 -63
- package/dist/text/index.d.ts +2 -63
- package/dist/text/index.js +31 -8
- package/dist/text/index.js.map +1 -1
- package/dist/utils-D4A4ro8M.d.cts +507 -0
- package/dist/utils-D4A4ro8M.d.ts +507 -0
- package/dist/vin/index.cjs +64 -0
- package/dist/vin/index.cjs.map +1 -1
- package/dist/vin/index.d.cts +1 -1
- package/dist/vin/index.d.ts +1 -1
- package/dist/vin/index.js +63 -1
- package/dist/vin/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/types-i5e6R0AS.d.cts +0 -39
- package/dist/types-i5e6R0AS.d.ts +0 -39
- package/dist/utils-DDVlOusI.d.cts +0 -30
- package/dist/utils-DDVlOusI.d.ts +0 -30
package/dist/nik/index.d.ts
CHANGED
|
@@ -1,353 +1,47 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* A valid NIK must:
|
|
5
|
-
* - Be exactly 16 digits
|
|
6
|
-
* - Have a valid province code (positions 1-2)
|
|
7
|
-
* - Have a valid date (positions 7-12)
|
|
8
|
-
* - Not be in the future
|
|
9
|
-
* - Not be before 1900
|
|
10
|
-
*
|
|
11
|
-
* For female NIKs, the day is encoded as (actual day + 40).
|
|
12
|
-
* For example, a female born on the 15th would have day = 55.
|
|
13
|
-
*
|
|
14
|
-
* @param nik - The 16-digit NIK string to validate
|
|
15
|
-
* @returns `true` if the NIK is valid, `false` otherwise
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```typescript
|
|
19
|
-
* validateNIK('3201234567890123'); // true - valid NIK
|
|
20
|
-
* validateNIK('1234'); // false - wrong length
|
|
21
|
-
* validateNIK('9912345678901234'); // false - invalid province
|
|
22
|
-
* ```
|
|
23
|
-
*
|
|
24
|
-
* @public
|
|
25
|
-
*/
|
|
26
|
-
declare function validateNIK(nik: string): boolean;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Information extracted from a valid NIK.
|
|
30
|
-
*
|
|
31
|
-
* Contains parsed data including location codes, birth date, gender,
|
|
32
|
-
* and serial number from a 16-digit NIK string.
|
|
33
|
-
*
|
|
34
|
-
* @public
|
|
35
|
-
*/
|
|
36
|
-
interface NIKInfo {
|
|
37
|
-
/**
|
|
38
|
-
* Province information extracted from positions 1-2 of the NIK.
|
|
39
|
-
*
|
|
40
|
-
* @example
|
|
41
|
-
* ```typescript
|
|
42
|
-
* { code: '32', name: 'Jawa Barat' }
|
|
43
|
-
* ```
|
|
44
|
-
*/
|
|
45
|
-
province: {
|
|
46
|
-
/** Two-digit province code (e.g., '32') */
|
|
47
|
-
code: string;
|
|
48
|
-
/** Full province name (e.g., 'Jawa Barat') */
|
|
49
|
-
name: string;
|
|
50
|
-
};
|
|
51
|
-
/**
|
|
52
|
-
* Regency (Kabupaten/Kota) information extracted from positions 3-4 of the NIK.
|
|
53
|
-
*
|
|
54
|
-
* @example
|
|
55
|
-
* ```typescript
|
|
56
|
-
* { code: '01', name: 'Kab. Bogor' }
|
|
57
|
-
* ```
|
|
58
|
-
*/
|
|
59
|
-
regency: {
|
|
60
|
-
/** Two-digit regency code (e.g., '01') */
|
|
61
|
-
code: string;
|
|
62
|
-
/** Full regency name (e.g., 'Kab. Bogor') */
|
|
63
|
-
name: string;
|
|
64
|
-
};
|
|
65
|
-
/**
|
|
66
|
-
* District (Kecamatan) information extracted from positions 5-6 of the NIK.
|
|
67
|
-
* May be `null` if district data is not available.
|
|
68
|
-
*
|
|
69
|
-
* @example
|
|
70
|
-
* ```typescript
|
|
71
|
-
* { code: '23', name: 'Ciawi' }
|
|
72
|
-
* ```
|
|
73
|
-
*/
|
|
74
|
-
district: {
|
|
75
|
-
/** Two-digit district code (e.g., '23') */
|
|
76
|
-
code: string;
|
|
77
|
-
/** Full district name, or `null` if data unavailable */
|
|
78
|
-
name: string | null;
|
|
79
|
-
};
|
|
80
|
-
/**
|
|
81
|
-
* Birth date extracted from positions 7-12 of the NIK.
|
|
82
|
-
* For females, the day is encoded as (actual day + 40).
|
|
83
|
-
* Returns `null` if the date is invalid.
|
|
84
|
-
*
|
|
85
|
-
* @example
|
|
86
|
-
* ```typescript
|
|
87
|
-
* new Date(1989, 0, 31) // January 31, 1989
|
|
88
|
-
* ```
|
|
89
|
-
*/
|
|
90
|
-
birthDate: Date | null;
|
|
91
|
-
/**
|
|
92
|
-
* Gender derived from the day encoding in the NIK.
|
|
93
|
-
* - 'male': day is 1-31
|
|
94
|
-
* - 'female': day is 41-71 (actual day + 40)
|
|
95
|
-
* - `null`: if unable to determine
|
|
96
|
-
*/
|
|
97
|
-
gender: 'male' | 'female' | null;
|
|
98
|
-
/**
|
|
99
|
-
* Serial number from positions 13-16 of the NIK.
|
|
100
|
-
* Uniquely identifies individuals with the same location and birth date.
|
|
101
|
-
* Returns `null` if unable to extract.
|
|
102
|
-
*
|
|
103
|
-
* @example
|
|
104
|
-
* ```typescript
|
|
105
|
-
* '0123'
|
|
106
|
-
* ```
|
|
107
|
-
*/
|
|
108
|
-
serialNumber: string | null;
|
|
109
|
-
/**
|
|
110
|
-
* Whether the NIK passed validation checks.
|
|
111
|
-
* If `false`, other fields may be `null` or contain partial data.
|
|
112
|
-
*/
|
|
113
|
-
isValid: boolean;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Options for masking a NIK to protect privacy.
|
|
117
|
-
*
|
|
118
|
-
* Controls how many characters to show at the start and end,
|
|
119
|
-
* what character to use for masking, and optional separators.
|
|
120
|
-
*
|
|
121
|
-
* @example
|
|
122
|
-
* ```typescript
|
|
123
|
-
* // Default: shows first 4 and last 4 digits
|
|
124
|
-
* { start: 4, end: 4, char: '*' }
|
|
125
|
-
* // Result: '3201********0123'
|
|
126
|
-
*
|
|
127
|
-
* // With separator
|
|
128
|
-
* { start: 4, end: 4, char: '*', separator: '-' }
|
|
129
|
-
* // Result: '3201-****-****-0123'
|
|
130
|
-
* ```
|
|
131
|
-
*
|
|
132
|
-
* @public
|
|
133
|
-
*/
|
|
134
|
-
interface MaskOptions {
|
|
135
|
-
/**
|
|
136
|
-
* Number of characters to show at the start.
|
|
137
|
-
*
|
|
138
|
-
* @defaultValue 4
|
|
139
|
-
*/
|
|
140
|
-
start?: number;
|
|
141
|
-
/**
|
|
142
|
-
* Number of characters to show at the end.
|
|
143
|
-
*
|
|
144
|
-
* @defaultValue 4
|
|
145
|
-
*/
|
|
146
|
-
end?: number;
|
|
147
|
-
/**
|
|
148
|
-
* Character to use for masking hidden digits.
|
|
149
|
-
*
|
|
150
|
-
* @defaultValue '*'
|
|
151
|
-
*/
|
|
152
|
-
char?: string;
|
|
153
|
-
/**
|
|
154
|
-
* Optional separator to add between groups of digits.
|
|
155
|
-
* If provided, the NIK will be formatted with separators.
|
|
156
|
-
*
|
|
157
|
-
* @defaultValue undefined (no separator)
|
|
158
|
-
*
|
|
159
|
-
* @example
|
|
160
|
-
* ```typescript
|
|
161
|
-
* '-' // Results in format: '3201-****-****-0123'
|
|
162
|
-
* ' ' // Results in format: '3201 **** **** 0123'
|
|
163
|
-
* ```
|
|
164
|
-
*/
|
|
165
|
-
separator?: string;
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Error thrown when an invalid NIK is provided to a function.
|
|
169
|
-
* Extends native Error with a `code` property for programmatic error handling.
|
|
170
|
-
*
|
|
171
|
-
* @example
|
|
172
|
-
* ```typescript
|
|
173
|
-
* try {
|
|
174
|
-
* requireNIK('invalid');
|
|
175
|
-
* } catch (error) {
|
|
176
|
-
* if (error instanceof InvalidNIKError) {
|
|
177
|
-
* console.log(error.code); // 'INVALID_NIK'
|
|
178
|
-
* }
|
|
179
|
-
* }
|
|
180
|
-
* ```
|
|
181
|
-
*
|
|
182
|
-
* @public
|
|
183
|
-
*/
|
|
184
|
-
declare class InvalidNIKError extends Error {
|
|
185
|
-
/** Error code for programmatic identification */
|
|
186
|
-
readonly code: "INVALID_NIK";
|
|
187
|
-
constructor(message?: string);
|
|
188
|
-
}
|
|
1
|
+
import { c as NIKValidationResult } from '../utils-D4A4ro8M.js';
|
|
2
|
+
export { A as Age, G as GetAgeOptions, I as InvalidNIKError, M as MaskOptions, j as NIKErrorCode, N as NIKInfo, h as NIKValidationError, d as compareNIK, a as formatBirthDate, f as formatNIK, g as getAge, e as isAdult, b as isValidForBirthDate, i as isValidForGender, m as maskNIK, p as parseNIK, v as validateNIK } from '../utils-D4A4ro8M.js';
|
|
189
3
|
|
|
190
4
|
/**
|
|
191
|
-
*
|
|
5
|
+
* Cleans a NIK by removing all non-digit characters.
|
|
192
6
|
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
7
|
+
* Accepts NIK in any format (with separators like `.`, `-`, ` `) and
|
|
8
|
+
* returns a clean 16-digit string. Returns empty string for invalid inputs.
|
|
195
9
|
*
|
|
196
|
-
* @param nik -
|
|
197
|
-
* @returns
|
|
10
|
+
* @param nik - NIK in any format
|
|
11
|
+
* @returns Clean 16-digit NIK or empty string if invalid
|
|
198
12
|
*
|
|
199
13
|
* @example
|
|
200
|
-
* Parse a valid male NIK:
|
|
201
14
|
* ```typescript
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
* //
|
|
205
|
-
* // province: { code: '32', name: 'Jawa Barat' },
|
|
206
|
-
* // regency: { code: '01', name: 'Kab. Bogor' },
|
|
207
|
-
* // district: { code: '01', name: null },
|
|
208
|
-
* // birthDate: Date(1989, 0, 31), // Jan 31, 1989
|
|
209
|
-
* // gender: 'male',
|
|
210
|
-
* // serialNumber: '0123',
|
|
211
|
-
* // isValid: true
|
|
212
|
-
* // }
|
|
213
|
-
* ```
|
|
214
|
-
*
|
|
215
|
-
* @example
|
|
216
|
-
* Parse a female NIK (day + 40):
|
|
217
|
-
* ```typescript
|
|
218
|
-
* const info = parseNIK('3201019508550123');
|
|
219
|
-
* console.log(info.gender); // 'female'
|
|
220
|
-
* console.log(info.birthDate); // Date(1995, 7, 15) - Aug 15, 1995
|
|
221
|
-
* ```
|
|
222
|
-
*
|
|
223
|
-
* @example
|
|
224
|
-
* Invalid NIK returns null:
|
|
225
|
-
* ```typescript
|
|
226
|
-
* const info = parseNIK('invalid');
|
|
227
|
-
* console.log(info); // null
|
|
15
|
+
* cleanNIK('32-01-01-89-01-31-0123'); // '3201018901310123'
|
|
16
|
+
* cleanNIK('3201.8901.3101.23'); // '32018901310123' (only 14 digits - invalid)
|
|
17
|
+
* cleanNIK('invalid'); // ''
|
|
228
18
|
* ```
|
|
229
19
|
*
|
|
230
20
|
* @public
|
|
231
21
|
*/
|
|
232
|
-
declare function
|
|
22
|
+
declare function cleanNIK(nik: string): string;
|
|
233
23
|
|
|
234
24
|
/**
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
* Groups the NIK into logical segments: province, regency, district,
|
|
238
|
-
* year, month, day, and serial number.
|
|
239
|
-
*
|
|
240
|
-
* @param nik - The 16-digit NIK string to format
|
|
241
|
-
* @param separator - Character to use as separator
|
|
242
|
-
* @returns Formatted NIK string, or original string if invalid format
|
|
243
|
-
*
|
|
244
|
-
* @example
|
|
245
|
-
* Default separator (dash):
|
|
246
|
-
* ```typescript
|
|
247
|
-
* formatNIK('3201234567890123');
|
|
248
|
-
* // '32-01-23-45-67-89-0123'
|
|
249
|
-
* ```
|
|
250
|
-
*
|
|
251
|
-
* @example
|
|
252
|
-
* Custom separator:
|
|
253
|
-
* ```typescript
|
|
254
|
-
* formatNIK('3201234567890123', ' ');
|
|
255
|
-
* // '32 01 23 45 67 89 0123'
|
|
256
|
-
* ```
|
|
257
|
-
*
|
|
258
|
-
* @example
|
|
259
|
-
* Invalid NIK returns as-is:
|
|
260
|
-
* ```typescript
|
|
261
|
-
* formatNIK('1234');
|
|
262
|
-
* // '1234'
|
|
263
|
-
* ```
|
|
264
|
-
*
|
|
265
|
-
* @public
|
|
266
|
-
*/
|
|
267
|
-
declare function formatNIK(nik: string, separator?: string): string;
|
|
268
|
-
/**
|
|
269
|
-
* Masks a NIK to protect privacy while keeping partial visibility.
|
|
270
|
-
*
|
|
271
|
-
* By default, shows the first 4 and last 4 digits, masking the middle 8.
|
|
272
|
-
* Optionally formats the masked NIK with separators.
|
|
273
|
-
*
|
|
274
|
-
* @param nik - The 16-digit NIK string to mask
|
|
275
|
-
* @param options - Masking configuration options
|
|
276
|
-
* @returns Masked NIK string, or original string if invalid format
|
|
277
|
-
*
|
|
278
|
-
* @example
|
|
279
|
-
* Default masking (first 4, last 4):
|
|
280
|
-
* ```typescript
|
|
281
|
-
* maskNIK('3201234567890123');
|
|
282
|
-
* // '3201********0123'
|
|
283
|
-
* ```
|
|
25
|
+
* Validates a NIK and returns detailed error information.
|
|
284
26
|
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
* ```typescript
|
|
288
|
-
* maskNIK('3201234567890123', { char: 'X' });
|
|
289
|
-
* // '3201XXXXXXXX0123'
|
|
290
|
-
* ```
|
|
27
|
+
* Unlike `validateNIK` which returns a boolean, this function provides
|
|
28
|
+
* structured error reporting for form validation use cases.
|
|
291
29
|
*
|
|
292
|
-
* @
|
|
293
|
-
*
|
|
294
|
-
* ```typescript
|
|
295
|
-
* maskNIK('3201234567890123', { separator: '-' });
|
|
296
|
-
* // '32-01-**-**-**-**-0123'
|
|
297
|
-
* ```
|
|
30
|
+
* @param nik - The NIK string to validate (accepts any format with separators)
|
|
31
|
+
* @returns Detailed validation result with errors array
|
|
298
32
|
*
|
|
299
33
|
* @example
|
|
300
|
-
* Custom start and end:
|
|
301
34
|
* ```typescript
|
|
302
|
-
*
|
|
303
|
-
*
|
|
35
|
+
* const result = validateNIKDetailed('3201018901310123');
|
|
36
|
+
* if (!result.isValid) {
|
|
37
|
+
* result.errors.forEach(err => {
|
|
38
|
+
* console.log(`${err.code}: ${err.message}`);
|
|
39
|
+
* });
|
|
40
|
+
* }
|
|
304
41
|
* ```
|
|
305
42
|
*
|
|
306
43
|
* @public
|
|
307
44
|
*/
|
|
308
|
-
declare function
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* Calculates the age of a person based on their NIK.
|
|
312
|
-
*
|
|
313
|
-
* @param nik - The 16-digit NIK string
|
|
314
|
-
* @param referenceDate - The date to calculate age from (default: current date)
|
|
315
|
-
* @returns The age in years, or null if the NIK is invalid or birth date cannot be parsed
|
|
316
|
-
*
|
|
317
|
-
* @example
|
|
318
|
-
* ```typescript
|
|
319
|
-
* getAge('3201018901310123'); // 35 (as of 2024)
|
|
320
|
-
* ```
|
|
321
|
-
*/
|
|
322
|
-
declare function getAge(nik: string, referenceDate?: Date): number | null;
|
|
323
|
-
/**
|
|
324
|
-
* Formats the birth date from a NIK into a human-readable string.
|
|
325
|
-
*
|
|
326
|
-
* @param nik - The 16-digit NIK string
|
|
327
|
-
* @param locale - The locale to use for formatting (default: 'id-ID')
|
|
328
|
-
* @returns Formatted birth date string, or null if invalid
|
|
329
|
-
*
|
|
330
|
-
* @example
|
|
331
|
-
* ```typescript
|
|
332
|
-
* formatBirthDate('3201018901310123'); // '31 Januari 1989'
|
|
333
|
-
* ```
|
|
334
|
-
*/
|
|
335
|
-
declare function formatBirthDate(nik: string, options?: Intl.DateTimeFormatOptions, locale?: string): string | null;
|
|
336
|
-
/**
|
|
337
|
-
* Checks if a NIK matches a specific gender.
|
|
338
|
-
*
|
|
339
|
-
* @param nik - The 16-digit NIK string
|
|
340
|
-
* @param gender - The gender to check ('male' | 'female')
|
|
341
|
-
* @returns True if the NIK matches the gender, false otherwise
|
|
342
|
-
*/
|
|
343
|
-
declare function isValidForGender(nik: string, gender: 'male' | 'female'): boolean;
|
|
344
|
-
/**
|
|
345
|
-
* Checks if a NIK matches a specific birth date.
|
|
346
|
-
*
|
|
347
|
-
* @param nik - The 16-digit NIK string
|
|
348
|
-
* @param birthDate - The birth date to check
|
|
349
|
-
* @returns True if the NIK matches the birth date, false otherwise
|
|
350
|
-
*/
|
|
351
|
-
declare function isValidForBirthDate(nik: string, birthDate: Date): boolean;
|
|
45
|
+
declare function validateNIKDetailed(nik: string): NIKValidationResult;
|
|
352
46
|
|
|
353
|
-
export {
|
|
47
|
+
export { NIKValidationResult, cleanNIK, validateNIKDetailed };
|
package/dist/nik/index.js
CHANGED
|
@@ -179,8 +179,17 @@ function maskNIK(nik, options = {}) {
|
|
|
179
179
|
if (!/^\d{16}$/.test(nik)) {
|
|
180
180
|
return nik;
|
|
181
181
|
}
|
|
182
|
-
const {
|
|
183
|
-
|
|
182
|
+
const { visibleStart, visibleEnd, maskChar, separator, start, end, char } = options;
|
|
183
|
+
const hasLegacyOptions = start !== void 0 || end !== void 0 || char !== void 0;
|
|
184
|
+
if (hasLegacyOptions) {
|
|
185
|
+
console.warn(
|
|
186
|
+
"[DEPRECATED] Mask options start/end/char are deprecated. Use visibleStart/visibleEnd/maskChar instead. These old names will be removed in v1.0.0."
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
const effectiveStart = visibleStart !== void 0 ? visibleStart : start !== void 0 ? start : 4;
|
|
190
|
+
const effectiveEnd = visibleEnd !== void 0 ? visibleEnd : end !== void 0 ? end : 4;
|
|
191
|
+
const effectiveChar = maskChar !== void 0 ? maskChar : char !== void 0 ? char : "*";
|
|
192
|
+
if (effectiveStart + effectiveEnd >= 16) {
|
|
184
193
|
return nik;
|
|
185
194
|
}
|
|
186
195
|
if (separator) {
|
|
@@ -191,54 +200,194 @@ function maskNIK(nik, options = {}) {
|
|
|
191
200
|
const partStart = charCount;
|
|
192
201
|
const partEnd = charCount + part.length;
|
|
193
202
|
charCount += part.length;
|
|
194
|
-
if (partEnd <=
|
|
203
|
+
if (partEnd <= effectiveStart) {
|
|
195
204
|
return part;
|
|
196
|
-
} else if (partStart >= 16 -
|
|
205
|
+
} else if (partStart >= 16 - effectiveEnd) {
|
|
197
206
|
return part;
|
|
198
|
-
} else if (partStart >=
|
|
199
|
-
return
|
|
207
|
+
} else if (partStart >= effectiveStart && partEnd <= 16 - effectiveEnd) {
|
|
208
|
+
return effectiveChar.repeat(part.length);
|
|
200
209
|
} else {
|
|
201
210
|
return part.split("").map((ch, idx) => {
|
|
202
211
|
const pos = partStart + idx;
|
|
203
|
-
if (pos <
|
|
212
|
+
if (pos < effectiveStart || pos >= 16 - effectiveEnd) {
|
|
204
213
|
return ch;
|
|
205
214
|
}
|
|
206
|
-
return
|
|
215
|
+
return effectiveChar;
|
|
207
216
|
}).join("");
|
|
208
217
|
}
|
|
209
218
|
});
|
|
210
219
|
return maskedParts.join(separator);
|
|
211
220
|
}
|
|
212
|
-
const startPart = nik.substring(0,
|
|
213
|
-
const endPart = nik.substring(16 -
|
|
214
|
-
const maskLength = 16 -
|
|
215
|
-
return startPart +
|
|
221
|
+
const startPart = nik.substring(0, effectiveStart);
|
|
222
|
+
const endPart = nik.substring(16 - effectiveEnd);
|
|
223
|
+
const maskLength = 16 - effectiveStart - effectiveEnd;
|
|
224
|
+
return startPart + effectiveChar.repeat(maskLength) + endPart;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// src/nik/clean.ts
|
|
228
|
+
function cleanNIK(nik) {
|
|
229
|
+
if (typeof nik !== "string") {
|
|
230
|
+
return "";
|
|
231
|
+
}
|
|
232
|
+
const cleaned = nik.replace(/\D/g, "");
|
|
233
|
+
if (cleaned.length !== 16) {
|
|
234
|
+
return "";
|
|
235
|
+
}
|
|
236
|
+
return cleaned;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// src/nik/validate-detailed.ts
|
|
240
|
+
function createError(code, message) {
|
|
241
|
+
return { code, message };
|
|
242
|
+
}
|
|
243
|
+
function validateNIKDetailed(nik) {
|
|
244
|
+
const cleaned = cleanNIK(nik);
|
|
245
|
+
if (cleaned === "") {
|
|
246
|
+
return {
|
|
247
|
+
isValid: false,
|
|
248
|
+
errors: [createError("INVALID_FORMAT", "NIK must be exactly 16 digits")],
|
|
249
|
+
nik: null
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
const provinceCode = cleaned.substring(0, 2);
|
|
253
|
+
if (!PROVINCES[provinceCode]) {
|
|
254
|
+
return {
|
|
255
|
+
isValid: false,
|
|
256
|
+
errors: [
|
|
257
|
+
createError(
|
|
258
|
+
"INVALID_PROVINCE",
|
|
259
|
+
`Province code ${provinceCode} not found`
|
|
260
|
+
)
|
|
261
|
+
],
|
|
262
|
+
nik: null
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
const info = parseNIK(cleaned);
|
|
266
|
+
if (!info) {
|
|
267
|
+
return {
|
|
268
|
+
isValid: false,
|
|
269
|
+
errors: [createError("INVALID_DATE", "Invalid date components")],
|
|
270
|
+
nik: null
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
const birthDate = info.birthDate;
|
|
274
|
+
if (!birthDate) {
|
|
275
|
+
return {
|
|
276
|
+
isValid: false,
|
|
277
|
+
errors: [createError("INVALID_DATE", "Invalid birth date")],
|
|
278
|
+
nik: null
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
const now = /* @__PURE__ */ new Date();
|
|
282
|
+
if (birthDate > now) {
|
|
283
|
+
return {
|
|
284
|
+
isValid: false,
|
|
285
|
+
errors: [
|
|
286
|
+
createError("FUTURE_DATE", "Birth date cannot be in the future")
|
|
287
|
+
],
|
|
288
|
+
nik: null
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
return {
|
|
292
|
+
isValid: true,
|
|
293
|
+
errors: [],
|
|
294
|
+
nik: cleaned
|
|
295
|
+
};
|
|
216
296
|
}
|
|
217
297
|
|
|
218
298
|
// src/nik/utils.ts
|
|
219
|
-
function getAge(nik,
|
|
299
|
+
function getAge(nik, options = {}) {
|
|
300
|
+
const { referenceDate = /* @__PURE__ */ new Date(), asString = false } = options;
|
|
220
301
|
const info = parseNIK(nik);
|
|
221
302
|
if (!info || !info.birthDate) {
|
|
222
303
|
return null;
|
|
223
304
|
}
|
|
224
305
|
const birthDate = info.birthDate;
|
|
225
|
-
let
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
306
|
+
let years = referenceDate.getFullYear() - birthDate.getFullYear();
|
|
307
|
+
let months = referenceDate.getMonth() - birthDate.getMonth();
|
|
308
|
+
let days = referenceDate.getDate() - birthDate.getDate();
|
|
309
|
+
if (days < 0) {
|
|
310
|
+
months--;
|
|
311
|
+
const prevMonth = new Date(
|
|
312
|
+
referenceDate.getFullYear(),
|
|
313
|
+
referenceDate.getMonth(),
|
|
314
|
+
0
|
|
315
|
+
);
|
|
316
|
+
days += prevMonth.getDate();
|
|
317
|
+
}
|
|
318
|
+
if (months < 0) {
|
|
319
|
+
years--;
|
|
320
|
+
months += 12;
|
|
321
|
+
}
|
|
322
|
+
if (asString) {
|
|
323
|
+
const parts = [];
|
|
324
|
+
if (years > 0) parts.push(`${years} Tahun`);
|
|
325
|
+
if (months > 0) parts.push(`${months} Bulan`);
|
|
326
|
+
if (days > 0 || parts.length === 0) parts.push(`${days} Hari`);
|
|
327
|
+
return parts.join(" ");
|
|
328
|
+
}
|
|
329
|
+
return { years, months, days };
|
|
330
|
+
}
|
|
331
|
+
function compareNIK(nik1, nik2) {
|
|
332
|
+
const cleaned1 = cleanNIK(nik1);
|
|
333
|
+
const cleaned2 = cleanNIK(nik2);
|
|
334
|
+
if (cleaned1 === "" || cleaned2 === "" || cleaned1.length !== 16 || cleaned2.length !== 16) {
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
if (cleaned1 === cleaned2) {
|
|
338
|
+
return true;
|
|
339
|
+
}
|
|
340
|
+
const pos1_6_1 = cleaned1.substring(0, 6);
|
|
341
|
+
const pos1_6_2 = cleaned2.substring(0, 6);
|
|
342
|
+
if (pos1_6_1 !== pos1_6_2) {
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
const birthDate1 = cleaned1.substring(6, 12);
|
|
346
|
+
const birthDate2 = cleaned2.substring(6, 12);
|
|
347
|
+
if (birthDate1 !== birthDate2) {
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
const serial1 = cleaned1.substring(12, 16);
|
|
351
|
+
const serial2 = cleaned2.substring(12, 16);
|
|
352
|
+
return serial1 === serial2;
|
|
353
|
+
}
|
|
354
|
+
function isAdult(nik, minAge = 17) {
|
|
355
|
+
const age = getAge(nik);
|
|
356
|
+
if (age === null) {
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
if (typeof age === "string") {
|
|
360
|
+
const yearsMatch = age.match(/^(\d+)/);
|
|
361
|
+
if (yearsMatch) {
|
|
362
|
+
return parseInt(yearsMatch[1], 10) >= minAge;
|
|
363
|
+
}
|
|
364
|
+
return false;
|
|
229
365
|
}
|
|
230
|
-
return age;
|
|
366
|
+
return age.years >= minAge;
|
|
231
367
|
}
|
|
232
|
-
function formatBirthDate(nik
|
|
233
|
-
day: "numeric",
|
|
234
|
-
month: "long",
|
|
235
|
-
year: "numeric"
|
|
236
|
-
}, locale = "id-ID") {
|
|
368
|
+
function formatBirthDate(nik) {
|
|
237
369
|
const info = parseNIK(nik);
|
|
238
370
|
if (!info || !info.birthDate) {
|
|
239
371
|
return null;
|
|
240
372
|
}
|
|
241
|
-
|
|
373
|
+
const day = info.birthDate.getDate();
|
|
374
|
+
const month = info.birthDate.getMonth();
|
|
375
|
+
const year = info.birthDate.getFullYear();
|
|
376
|
+
const monthNames = [
|
|
377
|
+
"Januari",
|
|
378
|
+
"Februari",
|
|
379
|
+
"Maret",
|
|
380
|
+
"April",
|
|
381
|
+
"Mei",
|
|
382
|
+
"Juni",
|
|
383
|
+
"Juli",
|
|
384
|
+
"Agustus",
|
|
385
|
+
"September",
|
|
386
|
+
"Oktober",
|
|
387
|
+
"November",
|
|
388
|
+
"Desember"
|
|
389
|
+
];
|
|
390
|
+
return `${day} ${monthNames[month]} ${year}`;
|
|
242
391
|
}
|
|
243
392
|
function isValidForGender(nik, gender) {
|
|
244
393
|
const info = parseNIK(nik);
|
|
@@ -265,6 +414,6 @@ var InvalidNIKError = class extends Error {
|
|
|
265
414
|
}
|
|
266
415
|
};
|
|
267
416
|
|
|
268
|
-
export { InvalidNIKError, formatBirthDate, formatNIK, getAge, isValidForBirthDate, isValidForGender, maskNIK, parseNIK, validateNIK };
|
|
417
|
+
export { InvalidNIKError, cleanNIK, compareNIK, formatBirthDate, formatNIK, getAge, isAdult, isValidForBirthDate, isValidForGender, maskNIK, parseNIK, validateNIK, validateNIKDetailed };
|
|
269
418
|
//# sourceMappingURL=index.js.map
|
|
270
419
|
//# sourceMappingURL=index.js.map
|