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.
@@ -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 };
@@ -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
+ }