@indodev/toolkit 0.5.0 → 0.6.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/index.cjs +46 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +46 -14
- package/dist/index.js.map +1 -1
- package/dist/nik/index.cjs +156 -12
- 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 +153 -13
- package/dist/nik/index.js.map +1 -1
- package/dist/utils-DT8-jt63.d.cts +495 -0
- package/dist/utils-DT8-jt63.d.ts +495 -0
- package/package.json +1 -1
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-DT8-jt63.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-DT8-jt63.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
|
@@ -215,30 +215,170 @@ function maskNIK(nik, options = {}) {
|
|
|
215
215
|
return startPart + char.repeat(maskLength) + endPart;
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
+
// src/nik/clean.ts
|
|
219
|
+
function cleanNIK(nik) {
|
|
220
|
+
if (typeof nik !== "string") {
|
|
221
|
+
return "";
|
|
222
|
+
}
|
|
223
|
+
const cleaned = nik.replace(/\D/g, "");
|
|
224
|
+
if (cleaned.length !== 16) {
|
|
225
|
+
return "";
|
|
226
|
+
}
|
|
227
|
+
return cleaned;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// src/nik/validate-detailed.ts
|
|
231
|
+
function createError(code, message) {
|
|
232
|
+
return { code, message };
|
|
233
|
+
}
|
|
234
|
+
function validateNIKDetailed(nik) {
|
|
235
|
+
const cleaned = cleanNIK(nik);
|
|
236
|
+
if (cleaned === "") {
|
|
237
|
+
return {
|
|
238
|
+
isValid: false,
|
|
239
|
+
errors: [createError("INVALID_FORMAT", "NIK must be exactly 16 digits")],
|
|
240
|
+
nik: null
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
const provinceCode = cleaned.substring(0, 2);
|
|
244
|
+
if (!PROVINCES[provinceCode]) {
|
|
245
|
+
return {
|
|
246
|
+
isValid: false,
|
|
247
|
+
errors: [
|
|
248
|
+
createError(
|
|
249
|
+
"INVALID_PROVINCE",
|
|
250
|
+
`Province code ${provinceCode} not found`
|
|
251
|
+
)
|
|
252
|
+
],
|
|
253
|
+
nik: null
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
const info = parseNIK(cleaned);
|
|
257
|
+
if (!info) {
|
|
258
|
+
return {
|
|
259
|
+
isValid: false,
|
|
260
|
+
errors: [createError("INVALID_DATE", "Invalid date components")],
|
|
261
|
+
nik: null
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
const birthDate = info.birthDate;
|
|
265
|
+
if (!birthDate) {
|
|
266
|
+
return {
|
|
267
|
+
isValid: false,
|
|
268
|
+
errors: [createError("INVALID_DATE", "Invalid birth date")],
|
|
269
|
+
nik: null
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
const now = /* @__PURE__ */ new Date();
|
|
273
|
+
if (birthDate > now) {
|
|
274
|
+
return {
|
|
275
|
+
isValid: false,
|
|
276
|
+
errors: [
|
|
277
|
+
createError("FUTURE_DATE", "Birth date cannot be in the future")
|
|
278
|
+
],
|
|
279
|
+
nik: null
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
return {
|
|
283
|
+
isValid: true,
|
|
284
|
+
errors: [],
|
|
285
|
+
nik: cleaned
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
|
|
218
289
|
// src/nik/utils.ts
|
|
219
|
-
function getAge(nik,
|
|
290
|
+
function getAge(nik, options = {}) {
|
|
291
|
+
const { referenceDate = /* @__PURE__ */ new Date(), asString = false } = options;
|
|
220
292
|
const info = parseNIK(nik);
|
|
221
293
|
if (!info || !info.birthDate) {
|
|
222
294
|
return null;
|
|
223
295
|
}
|
|
224
296
|
const birthDate = info.birthDate;
|
|
225
|
-
let
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
297
|
+
let years = referenceDate.getFullYear() - birthDate.getFullYear();
|
|
298
|
+
let months = referenceDate.getMonth() - birthDate.getMonth();
|
|
299
|
+
let days = referenceDate.getDate() - birthDate.getDate();
|
|
300
|
+
if (days < 0) {
|
|
301
|
+
months--;
|
|
302
|
+
const prevMonth = new Date(
|
|
303
|
+
referenceDate.getFullYear(),
|
|
304
|
+
referenceDate.getMonth(),
|
|
305
|
+
0
|
|
306
|
+
);
|
|
307
|
+
days += prevMonth.getDate();
|
|
308
|
+
}
|
|
309
|
+
if (months < 0) {
|
|
310
|
+
years--;
|
|
311
|
+
months += 12;
|
|
312
|
+
}
|
|
313
|
+
if (asString) {
|
|
314
|
+
const parts = [];
|
|
315
|
+
if (years > 0) parts.push(`${years} Tahun`);
|
|
316
|
+
if (months > 0) parts.push(`${months} Bulan`);
|
|
317
|
+
if (days > 0 || parts.length === 0) parts.push(`${days} Hari`);
|
|
318
|
+
return parts.join(" ");
|
|
319
|
+
}
|
|
320
|
+
return { years, months, days };
|
|
321
|
+
}
|
|
322
|
+
function compareNIK(nik1, nik2) {
|
|
323
|
+
const cleaned1 = cleanNIK(nik1);
|
|
324
|
+
const cleaned2 = cleanNIK(nik2);
|
|
325
|
+
if (cleaned1 === "" || cleaned2 === "" || cleaned1.length !== 16 || cleaned2.length !== 16) {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
if (cleaned1 === cleaned2) {
|
|
329
|
+
return true;
|
|
330
|
+
}
|
|
331
|
+
const pos1_6_1 = cleaned1.substring(0, 6);
|
|
332
|
+
const pos1_6_2 = cleaned2.substring(0, 6);
|
|
333
|
+
if (pos1_6_1 !== pos1_6_2) {
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
const birthDate1 = cleaned1.substring(6, 12);
|
|
337
|
+
const birthDate2 = cleaned2.substring(6, 12);
|
|
338
|
+
if (birthDate1 !== birthDate2) {
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
const serial1 = cleaned1.substring(12, 16);
|
|
342
|
+
const serial2 = cleaned2.substring(12, 16);
|
|
343
|
+
return serial1 === serial2;
|
|
344
|
+
}
|
|
345
|
+
function isAdult(nik, minAge = 17) {
|
|
346
|
+
const age = getAge(nik);
|
|
347
|
+
if (age === null) {
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
if (typeof age === "string") {
|
|
351
|
+
const yearsMatch = age.match(/^(\d+)/);
|
|
352
|
+
if (yearsMatch) {
|
|
353
|
+
return parseInt(yearsMatch[1], 10) >= minAge;
|
|
354
|
+
}
|
|
355
|
+
return false;
|
|
229
356
|
}
|
|
230
|
-
return age;
|
|
357
|
+
return age.years >= minAge;
|
|
231
358
|
}
|
|
232
|
-
function formatBirthDate(nik
|
|
233
|
-
day: "numeric",
|
|
234
|
-
month: "long",
|
|
235
|
-
year: "numeric"
|
|
236
|
-
}, locale = "id-ID") {
|
|
359
|
+
function formatBirthDate(nik) {
|
|
237
360
|
const info = parseNIK(nik);
|
|
238
361
|
if (!info || !info.birthDate) {
|
|
239
362
|
return null;
|
|
240
363
|
}
|
|
241
|
-
|
|
364
|
+
const day = info.birthDate.getDate();
|
|
365
|
+
const month = info.birthDate.getMonth();
|
|
366
|
+
const year = info.birthDate.getFullYear();
|
|
367
|
+
const monthNames = [
|
|
368
|
+
"Januari",
|
|
369
|
+
"Februari",
|
|
370
|
+
"Maret",
|
|
371
|
+
"April",
|
|
372
|
+
"Mei",
|
|
373
|
+
"Juni",
|
|
374
|
+
"Juli",
|
|
375
|
+
"Agustus",
|
|
376
|
+
"September",
|
|
377
|
+
"Oktober",
|
|
378
|
+
"November",
|
|
379
|
+
"Desember"
|
|
380
|
+
];
|
|
381
|
+
return `${day} ${monthNames[month]} ${year}`;
|
|
242
382
|
}
|
|
243
383
|
function isValidForGender(nik, gender) {
|
|
244
384
|
const info = parseNIK(nik);
|
|
@@ -265,6 +405,6 @@ var InvalidNIKError = class extends Error {
|
|
|
265
405
|
}
|
|
266
406
|
};
|
|
267
407
|
|
|
268
|
-
export { InvalidNIKError, formatBirthDate, formatNIK, getAge, isValidForBirthDate, isValidForGender, maskNIK, parseNIK, validateNIK };
|
|
408
|
+
export { InvalidNIKError, cleanNIK, compareNIK, formatBirthDate, formatNIK, getAge, isAdult, isValidForBirthDate, isValidForGender, maskNIK, parseNIK, validateNIK, validateNIKDetailed };
|
|
269
409
|
//# sourceMappingURL=index.js.map
|
|
270
410
|
//# sourceMappingURL=index.js.map
|