nik-id 1.0.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/LICENSE +21 -0
- package/README.md +492 -0
- package/dist/generate.cjs +95 -0
- package/dist/generate.d.cts +83 -0
- package/dist/generate.d.ts +83 -0
- package/dist/generate.js +70 -0
- package/dist/index.cjs +183 -0
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +154 -0
- package/dist/parse.cjs +111 -0
- package/dist/parse.d.cts +81 -0
- package/dist/parse.d.ts +81 -0
- package/dist/parse.js +84 -0
- package/dist/types.cjs +18 -0
- package/dist/types.d.cts +183 -0
- package/dist/types.d.ts +183 -0
- package/dist/types.js +0 -0
- package/dist/validate.cjs +81 -0
- package/dist/validate.d.cts +81 -0
- package/dist/validate.d.ts +81 -0
- package/dist/validate.js +54 -0
- package/package.json +106 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { ValidationResult } from './types.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Modul validasi NIK (Nomor Induk Kependudukan).
|
|
5
|
+
*
|
|
6
|
+
* Menyediakan fungsi {@link validateNIK} untuk mengecek apakah sebuah string
|
|
7
|
+
* merupakan NIK yang valid secara format. Validasi dilakukan secara bertahap:
|
|
8
|
+
* tipe data → panjang → isi digit → kode provinsi → tanggal lahir → nomor urut.
|
|
9
|
+
*
|
|
10
|
+
* Modul ini **tidak** memvalidasi apakah kode wilayah benar-benar terdaftar
|
|
11
|
+
* di database Kemendagri — hanya format dan range yang dicek. Untuk resolve
|
|
12
|
+
* nama wilayah dari kode, gunakan package `kode-wilayah-id`.
|
|
13
|
+
*
|
|
14
|
+
* @module validate
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { validateNIK } from 'nik-id/validate';
|
|
19
|
+
*
|
|
20
|
+
* const result = validateNIK("3204076508850001");
|
|
21
|
+
* if (result.valid) {
|
|
22
|
+
* console.log("NIK valid!");
|
|
23
|
+
* } else {
|
|
24
|
+
* console.log(result.error);
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Validasi format NIK (Nomor Induk Kependudukan).
|
|
31
|
+
*
|
|
32
|
+
* Melakukan pengecekan bertahap terhadap string NIK:
|
|
33
|
+
*
|
|
34
|
+
* 1. **Tipe data** — input harus berupa `string`
|
|
35
|
+
* 2. **Panjang** — harus tepat 16 karakter
|
|
36
|
+
* 3. **Format** — harus semua digit angka (0-9)
|
|
37
|
+
* 4. **Kode provinsi** — 2 digit pertama harus dalam range 11-97
|
|
38
|
+
* 5. **Tanggal lahir** — digit 7-12 harus membentuk tanggal yang valid
|
|
39
|
+
* (DD 01-31 untuk laki-laki, 41-71 untuk perempuan; MM 01-12; YY 00-99)
|
|
40
|
+
* 6. **Nomor urut** — digit 13-16 tidak boleh `0000`
|
|
41
|
+
*
|
|
42
|
+
* Validasi berhenti di error pertama yang ditemukan (fail-fast).
|
|
43
|
+
*
|
|
44
|
+
* @param nik - String yang akan divalidasi sebagai NIK
|
|
45
|
+
* @returns {@link ValidationResult} — `{ valid: true }` kalau valid,
|
|
46
|
+
* `{ valid: false, error: "..." }` kalau tidak
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* // NIK valid
|
|
51
|
+
* validateNIK("3204076508850001");
|
|
52
|
+
* // { valid: true }
|
|
53
|
+
*
|
|
54
|
+
* // Input bukan string
|
|
55
|
+
* validateNIK(12345 as any);
|
|
56
|
+
* // { valid: false, error: "NIK harus berupa string" }
|
|
57
|
+
*
|
|
58
|
+
* // Panjang salah
|
|
59
|
+
* validateNIK("123");
|
|
60
|
+
* // { valid: false, error: "NIK harus 16 digit" }
|
|
61
|
+
*
|
|
62
|
+
* // Mengandung huruf
|
|
63
|
+
* validateNIK("320407650885000A");
|
|
64
|
+
* // { valid: false, error: "NIK hanya boleh berisi angka" }
|
|
65
|
+
*
|
|
66
|
+
* // Kode provinsi di luar range
|
|
67
|
+
* validateNIK("0004076508850001");
|
|
68
|
+
* // { valid: false, error: "Kode provinsi tidak valid" }
|
|
69
|
+
*
|
|
70
|
+
* // Tanggal tidak ada di kalender
|
|
71
|
+
* validateNIK("3204073102850001"); // 31 Februari
|
|
72
|
+
* // { valid: false, error: "Tanggal lahir tidak valid" }
|
|
73
|
+
*
|
|
74
|
+
* // Nomor urut 0000
|
|
75
|
+
* validateNIK("3204076508850000");
|
|
76
|
+
* // { valid: false, error: "Nomor urut tidak valid" }
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
declare function validateNIK(nik: string): ValidationResult;
|
|
80
|
+
|
|
81
|
+
export { validateNIK };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { ValidationResult } from './types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Modul validasi NIK (Nomor Induk Kependudukan).
|
|
5
|
+
*
|
|
6
|
+
* Menyediakan fungsi {@link validateNIK} untuk mengecek apakah sebuah string
|
|
7
|
+
* merupakan NIK yang valid secara format. Validasi dilakukan secara bertahap:
|
|
8
|
+
* tipe data → panjang → isi digit → kode provinsi → tanggal lahir → nomor urut.
|
|
9
|
+
*
|
|
10
|
+
* Modul ini **tidak** memvalidasi apakah kode wilayah benar-benar terdaftar
|
|
11
|
+
* di database Kemendagri — hanya format dan range yang dicek. Untuk resolve
|
|
12
|
+
* nama wilayah dari kode, gunakan package `kode-wilayah-id`.
|
|
13
|
+
*
|
|
14
|
+
* @module validate
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { validateNIK } from 'nik-id/validate';
|
|
19
|
+
*
|
|
20
|
+
* const result = validateNIK("3204076508850001");
|
|
21
|
+
* if (result.valid) {
|
|
22
|
+
* console.log("NIK valid!");
|
|
23
|
+
* } else {
|
|
24
|
+
* console.log(result.error);
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Validasi format NIK (Nomor Induk Kependudukan).
|
|
31
|
+
*
|
|
32
|
+
* Melakukan pengecekan bertahap terhadap string NIK:
|
|
33
|
+
*
|
|
34
|
+
* 1. **Tipe data** — input harus berupa `string`
|
|
35
|
+
* 2. **Panjang** — harus tepat 16 karakter
|
|
36
|
+
* 3. **Format** — harus semua digit angka (0-9)
|
|
37
|
+
* 4. **Kode provinsi** — 2 digit pertama harus dalam range 11-97
|
|
38
|
+
* 5. **Tanggal lahir** — digit 7-12 harus membentuk tanggal yang valid
|
|
39
|
+
* (DD 01-31 untuk laki-laki, 41-71 untuk perempuan; MM 01-12; YY 00-99)
|
|
40
|
+
* 6. **Nomor urut** — digit 13-16 tidak boleh `0000`
|
|
41
|
+
*
|
|
42
|
+
* Validasi berhenti di error pertama yang ditemukan (fail-fast).
|
|
43
|
+
*
|
|
44
|
+
* @param nik - String yang akan divalidasi sebagai NIK
|
|
45
|
+
* @returns {@link ValidationResult} — `{ valid: true }` kalau valid,
|
|
46
|
+
* `{ valid: false, error: "..." }` kalau tidak
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* // NIK valid
|
|
51
|
+
* validateNIK("3204076508850001");
|
|
52
|
+
* // { valid: true }
|
|
53
|
+
*
|
|
54
|
+
* // Input bukan string
|
|
55
|
+
* validateNIK(12345 as any);
|
|
56
|
+
* // { valid: false, error: "NIK harus berupa string" }
|
|
57
|
+
*
|
|
58
|
+
* // Panjang salah
|
|
59
|
+
* validateNIK("123");
|
|
60
|
+
* // { valid: false, error: "NIK harus 16 digit" }
|
|
61
|
+
*
|
|
62
|
+
* // Mengandung huruf
|
|
63
|
+
* validateNIK("320407650885000A");
|
|
64
|
+
* // { valid: false, error: "NIK hanya boleh berisi angka" }
|
|
65
|
+
*
|
|
66
|
+
* // Kode provinsi di luar range
|
|
67
|
+
* validateNIK("0004076508850001");
|
|
68
|
+
* // { valid: false, error: "Kode provinsi tidak valid" }
|
|
69
|
+
*
|
|
70
|
+
* // Tanggal tidak ada di kalender
|
|
71
|
+
* validateNIK("3204073102850001"); // 31 Februari
|
|
72
|
+
* // { valid: false, error: "Tanggal lahir tidak valid" }
|
|
73
|
+
*
|
|
74
|
+
* // Nomor urut 0000
|
|
75
|
+
* validateNIK("3204076508850000");
|
|
76
|
+
* // { valid: false, error: "Nomor urut tidak valid" }
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
declare function validateNIK(nik: string): ValidationResult;
|
|
80
|
+
|
|
81
|
+
export { validateNIK };
|
package/dist/validate.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// src/utils.ts
|
|
2
|
+
function disambiguateYear(yy) {
|
|
3
|
+
const currentYY = (/* @__PURE__ */ new Date()).getFullYear() % 100;
|
|
4
|
+
return yy > currentYY ? 1900 + yy : 2e3 + yy;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// src/validate.ts
|
|
8
|
+
var MIN_PROVINCE_CODE = 11;
|
|
9
|
+
var MAX_PROVINCE_CODE = 97;
|
|
10
|
+
var NIK_LENGTH = 16;
|
|
11
|
+
var DIGITS_ONLY_PATTERN = /^\d{16}$/;
|
|
12
|
+
function isValidCalendarDate(year, month, day) {
|
|
13
|
+
const date = new Date(year, month - 1, day);
|
|
14
|
+
return date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day;
|
|
15
|
+
}
|
|
16
|
+
function validateNIK(nik) {
|
|
17
|
+
if (typeof nik !== "string") {
|
|
18
|
+
return { valid: false, error: "NIK harus berupa string" };
|
|
19
|
+
}
|
|
20
|
+
if (nik.length !== NIK_LENGTH) {
|
|
21
|
+
return { valid: false, error: "NIK harus 16 digit" };
|
|
22
|
+
}
|
|
23
|
+
if (!DIGITS_ONLY_PATTERN.test(nik)) {
|
|
24
|
+
return { valid: false, error: "NIK hanya boleh berisi angka" };
|
|
25
|
+
}
|
|
26
|
+
const provinceCode = Number.parseInt(nik.substring(0, 2), 10);
|
|
27
|
+
if (provinceCode < MIN_PROVINCE_CODE || provinceCode > MAX_PROVINCE_CODE) {
|
|
28
|
+
return { valid: false, error: "Kode provinsi tidak valid" };
|
|
29
|
+
}
|
|
30
|
+
const dd = Number.parseInt(nik.substring(6, 8), 10);
|
|
31
|
+
const mm = Number.parseInt(nik.substring(8, 10), 10);
|
|
32
|
+
const yy = Number.parseInt(nik.substring(10, 12), 10);
|
|
33
|
+
const isValidMaleDD = dd >= 1 && dd <= 31;
|
|
34
|
+
const isValidFemaleDD = dd >= 41 && dd <= 71;
|
|
35
|
+
if (!isValidMaleDD && !isValidFemaleDD) {
|
|
36
|
+
return { valid: false, error: "Tanggal lahir tidak valid" };
|
|
37
|
+
}
|
|
38
|
+
if (mm < 1 || mm > 12) {
|
|
39
|
+
return { valid: false, error: "Tanggal lahir tidak valid" };
|
|
40
|
+
}
|
|
41
|
+
const actualDay = isValidFemaleDD ? dd - 40 : dd;
|
|
42
|
+
const fullYear = disambiguateYear(yy);
|
|
43
|
+
if (!isValidCalendarDate(fullYear, mm, actualDay)) {
|
|
44
|
+
return { valid: false, error: "Tanggal lahir tidak valid" };
|
|
45
|
+
}
|
|
46
|
+
const seq = nik.substring(12, 16);
|
|
47
|
+
if (seq === "0000") {
|
|
48
|
+
return { valid: false, error: "Nomor urut tidak valid" };
|
|
49
|
+
}
|
|
50
|
+
return { valid: true };
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
validateNIK
|
|
54
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nik-id",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Parser, validator, dan generator NIK (Nomor Induk Kependudukan) Indonesia — TypeScript, zero dependencies",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"sideEffects": false,
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./dist/index.d.cts",
|
|
18
|
+
"default": "./dist/index.cjs"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"./validate": {
|
|
22
|
+
"import": {
|
|
23
|
+
"types": "./dist/validate.d.ts",
|
|
24
|
+
"default": "./dist/validate.js"
|
|
25
|
+
},
|
|
26
|
+
"require": {
|
|
27
|
+
"types": "./dist/validate.d.cts",
|
|
28
|
+
"default": "./dist/validate.cjs"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"./parse": {
|
|
32
|
+
"import": {
|
|
33
|
+
"types": "./dist/parse.d.ts",
|
|
34
|
+
"default": "./dist/parse.js"
|
|
35
|
+
},
|
|
36
|
+
"require": {
|
|
37
|
+
"types": "./dist/parse.d.cts",
|
|
38
|
+
"default": "./dist/parse.cjs"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"./generate": {
|
|
42
|
+
"import": {
|
|
43
|
+
"types": "./dist/generate.d.ts",
|
|
44
|
+
"default": "./dist/generate.js"
|
|
45
|
+
},
|
|
46
|
+
"require": {
|
|
47
|
+
"types": "./dist/generate.d.cts",
|
|
48
|
+
"default": "./dist/generate.cjs"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"./types": {
|
|
52
|
+
"import": {
|
|
53
|
+
"types": "./dist/types.d.ts"
|
|
54
|
+
},
|
|
55
|
+
"require": {
|
|
56
|
+
"types": "./dist/types.d.cts"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"files": [
|
|
61
|
+
"dist"
|
|
62
|
+
],
|
|
63
|
+
"scripts": {
|
|
64
|
+
"build": "tsup",
|
|
65
|
+
"test": "vitest run",
|
|
66
|
+
"test:coverage": "vitest run --coverage",
|
|
67
|
+
"lint": "biome check src/ tests/",
|
|
68
|
+
"lint:fix": "biome check --write src/ tests/",
|
|
69
|
+
"format": "biome format --write src/ tests/",
|
|
70
|
+
"format:check": "biome format src/ tests/",
|
|
71
|
+
"typecheck": "tsc --noEmit",
|
|
72
|
+
"audit": "npm audit --audit-level=moderate",
|
|
73
|
+
"prepublishOnly": "npm run typecheck && npm run lint && npm run test:coverage && npm run build"
|
|
74
|
+
},
|
|
75
|
+
"keywords": [
|
|
76
|
+
"nik",
|
|
77
|
+
"ktp",
|
|
78
|
+
"indonesia",
|
|
79
|
+
"validator",
|
|
80
|
+
"parser",
|
|
81
|
+
"kependudukan",
|
|
82
|
+
"identitas",
|
|
83
|
+
"kemendagri",
|
|
84
|
+
"dukcapil"
|
|
85
|
+
],
|
|
86
|
+
"author": "Sumitro Aji Prabowo",
|
|
87
|
+
"license": "MIT",
|
|
88
|
+
"repository": {
|
|
89
|
+
"type": "git",
|
|
90
|
+
"url": "git+https://github.com/sumitroajiprabowo/nik-id.git"
|
|
91
|
+
},
|
|
92
|
+
"homepage": "https://github.com/sumitroajiprabowo/nik-id#readme",
|
|
93
|
+
"bugs": {
|
|
94
|
+
"url": "https://github.com/sumitroajiprabowo/nik-id/issues"
|
|
95
|
+
},
|
|
96
|
+
"engines": {
|
|
97
|
+
"node": ">=20"
|
|
98
|
+
},
|
|
99
|
+
"devDependencies": {
|
|
100
|
+
"@biomejs/biome": "^2.4.15",
|
|
101
|
+
"@vitest/coverage-v8": "^4.1.6",
|
|
102
|
+
"tsup": "^8.5.1",
|
|
103
|
+
"typescript": "^6.0.3",
|
|
104
|
+
"vitest": "^4.1.6"
|
|
105
|
+
}
|
|
106
|
+
}
|