sl-nic-validator-and-information-extractor 1.0.7 → 1.0.8
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/README.md +323 -79
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,79 +1,323 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
1
|
+
# sl-nic-validator-and-information-extractor
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/sl-nic-validator-and-information-extractor)
|
|
4
|
+
[](https://www.npmjs.com/package/sl-nic-validator-and-information-extractor)
|
|
5
|
+
[](https://bundlephobia.com/package/sl-nic-validator-and-information-extractor)
|
|
6
|
+
[](https://www.npmjs.com/package/sl-nic-validator-and-information-extractor)
|
|
7
|
+
[](./LICENSE)
|
|
8
|
+
|
|
9
|
+
Validate Sri Lankan **National Identity Card (NIC)** numbers and extract the date of birth, age, and gender encoded inside them. Supports both the **old format** (9 digits + a `V`/`X` suffix) and the **new format** (12 digits).
|
|
10
|
+
|
|
11
|
+
- **Zero runtime dependencies**
|
|
12
|
+
- **TypeScript-first** — ships full type declarations
|
|
13
|
+
- **Dual module output** — works with both ESM (`import`) and CommonJS (`require`)
|
|
14
|
+
- Tiny and dependency-free, so it drops into any JavaScript runtime or framework
|
|
15
|
+
|
|
16
|
+
> **Ecosystem note:** This is an npm package, so it runs anywhere JavaScript runs — Node.js, browsers, and JS/TS frameworks. It cannot be imported directly into non-JavaScript languages (Python, Java, C#, Go, etc.). If you need it there, expose it behind a small HTTP endpoint (see the [Express](#expressnodejs-backend) example) and call that from any language.
|
|
17
|
+
|
|
18
|
+
## Table of Contents
|
|
19
|
+
|
|
20
|
+
- [Installation](#installation)
|
|
21
|
+
- [Quick Start](#quick-start)
|
|
22
|
+
- [API Reference](#api-reference)
|
|
23
|
+
- [Usage by Environment](#usage-by-environment)
|
|
24
|
+
- [TypeScript / ESM](#typescript--esm)
|
|
25
|
+
- [Node.js (CommonJS)](#nodejs-commonjs)
|
|
26
|
+
- [React](#react)
|
|
27
|
+
- [Next.js](#nextjs-api-route)
|
|
28
|
+
- [Vue 3](#vue-3)
|
|
29
|
+
- [Angular](#angular)
|
|
30
|
+
- [Express (Node.js backend)](#expressnodejs-backend)
|
|
31
|
+
- [Browser (no build step)](#browser-no-build-step)
|
|
32
|
+
- [How the NIC Format Works](#how-the-nic-format-works)
|
|
33
|
+
- [Behavior & Edge Cases](#behavior--edge-cases)
|
|
34
|
+
- [License](#license)
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install sl-nic-validator-and-information-extractor
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
yarn add sl-nic-validator-and-information-extractor
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pnpm add sl-nic-validator-and-information-extractor
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
bun add sl-nic-validator-and-information-extractor
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Quick Start
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import {
|
|
58
|
+
isValidSlNic,
|
|
59
|
+
extractDetailsFromSlNic,
|
|
60
|
+
} from "sl-nic-validator-and-information-extractor";
|
|
61
|
+
|
|
62
|
+
isValidSlNic("972002662V"); // true
|
|
63
|
+
isValidSlNic("199720002662"); // true (new 12-digit format)
|
|
64
|
+
isValidSlNic("hello"); // false
|
|
65
|
+
|
|
66
|
+
extractDetailsFromSlNic("972002662V");
|
|
67
|
+
// {
|
|
68
|
+
// dateOfBirth: "1997-07-18",
|
|
69
|
+
// age: 28, // computed relative to today's date
|
|
70
|
+
// gender: "Male"
|
|
71
|
+
// }
|
|
72
|
+
|
|
73
|
+
extractDetailsFromSlNic("invalid"); // undefined
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## API Reference
|
|
77
|
+
|
|
78
|
+
### `isValidSlNic(nic: string): boolean`
|
|
79
|
+
|
|
80
|
+
Returns `true` if the string is a structurally valid old- or new-format Sri Lankan NIC, `false` otherwise. Input is trimmed and case-normalized before checking, so `" 972002662v "` is accepted.
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
isValidSlNic("972002662V"); // true — old format
|
|
84
|
+
isValidSlNic("199720002662"); // true — new format
|
|
85
|
+
isValidSlNic("970002662V"); // false — invalid day-of-year (000)
|
|
86
|
+
isValidSlNic("12345"); // false — wrong length
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### `extractDetailsFromSlNic(nic: string): INicDetails | undefined`
|
|
90
|
+
|
|
91
|
+
Parses a valid NIC and returns the decoded details. Returns `undefined` if the NIC is invalid, so it doubles as a validity check.
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
interface INicDetails {
|
|
95
|
+
dateOfBirth: string; // ISO date, "YYYY-MM-DD"
|
|
96
|
+
age: number; // whole years, relative to today's date
|
|
97
|
+
gender: string; // "Male" | "Female"
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
const details = extractDetailsFromSlNic("977002662V");
|
|
103
|
+
// { dateOfBirth: "1997-07-18", age: 28, gender: "Female" }
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Usage by Environment
|
|
107
|
+
|
|
108
|
+
### TypeScript / ESM
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import {
|
|
112
|
+
isValidSlNic,
|
|
113
|
+
extractDetailsFromSlNic,
|
|
114
|
+
type INicDetails,
|
|
115
|
+
} from "sl-nic-validator-and-information-extractor";
|
|
116
|
+
|
|
117
|
+
const nic = "199720002662";
|
|
118
|
+
|
|
119
|
+
if (isValidSlNic(nic)) {
|
|
120
|
+
const details: INicDetails | undefined = extractDetailsFromSlNic(nic);
|
|
121
|
+
console.log(details);
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Node.js (CommonJS)
|
|
126
|
+
|
|
127
|
+
```js
|
|
128
|
+
const {
|
|
129
|
+
isValidSlNic,
|
|
130
|
+
extractDetailsFromSlNic,
|
|
131
|
+
} = require("sl-nic-validator-and-information-extractor");
|
|
132
|
+
|
|
133
|
+
console.log(isValidSlNic("972002662V")); // true
|
|
134
|
+
console.log(extractDetailsFromSlNic("972002662V"));
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### React
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
import { useState } from "react";
|
|
141
|
+
import {
|
|
142
|
+
isValidSlNic,
|
|
143
|
+
extractDetailsFromSlNic,
|
|
144
|
+
} from "sl-nic-validator-and-information-extractor";
|
|
145
|
+
|
|
146
|
+
export function NicInput() {
|
|
147
|
+
const [nic, setNic] = useState("");
|
|
148
|
+
|
|
149
|
+
const touched = nic.length > 0;
|
|
150
|
+
const valid = isValidSlNic(nic);
|
|
151
|
+
const details = valid ? extractDetailsFromSlNic(nic) : undefined;
|
|
152
|
+
|
|
153
|
+
return (
|
|
154
|
+
<div>
|
|
155
|
+
<input
|
|
156
|
+
value={nic}
|
|
157
|
+
onChange={(e) => setNic(e.target.value)}
|
|
158
|
+
placeholder="Enter NIC number"
|
|
159
|
+
/>
|
|
160
|
+
|
|
161
|
+
{touched && !valid && <p style={{ color: "red" }}>Invalid NIC number</p>}
|
|
162
|
+
|
|
163
|
+
{details && (
|
|
164
|
+
<ul>
|
|
165
|
+
<li>Date of birth: {details.dateOfBirth}</li>
|
|
166
|
+
<li>Age: {details.age}</li>
|
|
167
|
+
<li>Gender: {details.gender}</li>
|
|
168
|
+
</ul>
|
|
169
|
+
)}
|
|
170
|
+
</div>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Next.js (API Route)
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
// app/api/nic/route.ts (App Router)
|
|
179
|
+
import { NextResponse } from "next/server";
|
|
180
|
+
import {
|
|
181
|
+
isValidSlNic,
|
|
182
|
+
extractDetailsFromSlNic,
|
|
183
|
+
} from "sl-nic-validator-and-information-extractor";
|
|
184
|
+
|
|
185
|
+
export async function POST(request: Request) {
|
|
186
|
+
const { nic } = await request.json();
|
|
187
|
+
|
|
188
|
+
if (!isValidSlNic(nic)) {
|
|
189
|
+
return NextResponse.json({ error: "Invalid NIC" }, { status: 400 });
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return NextResponse.json(extractDetailsFromSlNic(nic));
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Vue 3
|
|
197
|
+
|
|
198
|
+
```vue
|
|
199
|
+
<script setup lang="ts">
|
|
200
|
+
import { ref, computed } from "vue";
|
|
201
|
+
import {
|
|
202
|
+
isValidSlNic,
|
|
203
|
+
extractDetailsFromSlNic,
|
|
204
|
+
} from "sl-nic-validator-and-information-extractor";
|
|
205
|
+
|
|
206
|
+
const nic = ref("");
|
|
207
|
+
const valid = computed(() => isValidSlNic(nic.value));
|
|
208
|
+
const details = computed(() =>
|
|
209
|
+
valid.value ? extractDetailsFromSlNic(nic.value) : undefined
|
|
210
|
+
);
|
|
211
|
+
</script>
|
|
212
|
+
|
|
213
|
+
<template>
|
|
214
|
+
<input v-model="nic" placeholder="Enter NIC number" />
|
|
215
|
+
<p v-if="nic && !valid">Invalid NIC number</p>
|
|
216
|
+
<ul v-if="details">
|
|
217
|
+
<li>Date of birth: {{ details.dateOfBirth }}</li>
|
|
218
|
+
<li>Age: {{ details.age }}</li>
|
|
219
|
+
<li>Gender: {{ details.gender }}</li>
|
|
220
|
+
</ul>
|
|
221
|
+
</template>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Angular
|
|
225
|
+
|
|
226
|
+
A reusable Reactive Forms validator:
|
|
227
|
+
|
|
228
|
+
```ts
|
|
229
|
+
import { AbstractControl, ValidationErrors, ValidatorFn } from "@angular/forms";
|
|
230
|
+
import { isValidSlNic } from "sl-nic-validator-and-information-extractor";
|
|
231
|
+
|
|
232
|
+
export const slNicValidator: ValidatorFn = (
|
|
233
|
+
control: AbstractControl
|
|
234
|
+
): ValidationErrors | null => {
|
|
235
|
+
if (!control.value) return null; // let `required` handle empties
|
|
236
|
+
return isValidSlNic(control.value) ? null : { invalidNic: true };
|
|
237
|
+
};
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
```ts
|
|
241
|
+
// In a component
|
|
242
|
+
import { FormControl } from "@angular/forms";
|
|
243
|
+
import { slNicValidator } from "./sl-nic.validator";
|
|
244
|
+
|
|
245
|
+
nicControl = new FormControl("", [slNicValidator]);
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Express (Node.js backend)
|
|
249
|
+
|
|
250
|
+
This is also the pattern to follow if you need NIC validation from a non-JavaScript language — call this endpoint over HTTP.
|
|
251
|
+
|
|
252
|
+
```js
|
|
253
|
+
import express from "express";
|
|
254
|
+
import {
|
|
255
|
+
isValidSlNic,
|
|
256
|
+
extractDetailsFromSlNic,
|
|
257
|
+
} from "sl-nic-validator-and-information-extractor";
|
|
258
|
+
|
|
259
|
+
const app = express();
|
|
260
|
+
app.use(express.json());
|
|
261
|
+
|
|
262
|
+
app.post("/nic", (req, res) => {
|
|
263
|
+
const { nic } = req.body;
|
|
264
|
+
|
|
265
|
+
if (!isValidSlNic(nic)) {
|
|
266
|
+
return res.status(400).json({ error: "Invalid NIC" });
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
res.json(extractDetailsFromSlNic(nic));
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
app.listen(3000);
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Browser (no build step)
|
|
276
|
+
|
|
277
|
+
The package ships ESM, so it loads directly from an ESM CDN such as [esm.sh](https://esm.sh) — no bundler required:
|
|
278
|
+
|
|
279
|
+
```html
|
|
280
|
+
<script type="module">
|
|
281
|
+
import {
|
|
282
|
+
isValidSlNic,
|
|
283
|
+
extractDetailsFromSlNic,
|
|
284
|
+
} from "https://esm.sh/sl-nic-validator-and-information-extractor";
|
|
285
|
+
|
|
286
|
+
console.log(isValidSlNic("972002662V")); // true
|
|
287
|
+
console.log(extractDetailsFromSlNic("972002662V"));
|
|
288
|
+
</script>
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## How the NIC Format Works
|
|
292
|
+
|
|
293
|
+
Every Sri Lankan NIC encodes the holder's birth year, day of birth, and gender.
|
|
294
|
+
|
|
295
|
+
**Old format** — 9 digits followed by a letter, e.g. `972002662V`:
|
|
296
|
+
|
|
297
|
+
| Part | Example | Meaning |
|
|
298
|
+
| ----------- | ------- | -------------------------------------------------------------- |
|
|
299
|
+
| Year | `97` | Last two digits of the birth year (interpreted as `19xx`) |
|
|
300
|
+
| Day of year | `200` | Day of the year (1–366); **+500 for females** |
|
|
301
|
+
| Serial | `2662` | Sequential / uniqueness digits |
|
|
302
|
+
| Suffix | `V` | `V` or `X` |
|
|
303
|
+
|
|
304
|
+
**New format** — 12 digits, e.g. `199720002662`:
|
|
305
|
+
|
|
306
|
+
| Part | Example | Meaning |
|
|
307
|
+
| ----------- | ------- | -------------------------------------- |
|
|
308
|
+
| Year | `1997` | Full four-digit birth year |
|
|
309
|
+
| Day of year | `200` | Day of the year (1–366); +500 females |
|
|
310
|
+
| Serial | `02662` | Sequential / uniqueness digits |
|
|
311
|
+
|
|
312
|
+
The day-of-year uses a fixed 366-day calendar (it always reserves a slot for Feb 29). Females have **500 added** to the day, so the valid ranges are **001–366** for males and **501–866** for females.
|
|
313
|
+
|
|
314
|
+
## Behavior & Edge Cases
|
|
315
|
+
|
|
316
|
+
- **Whitespace and case** — input is trimmed and uppercased, so `" 972002662v "` validates the same as `"972002662V"`.
|
|
317
|
+
- **Old-format century** — old NICs are interpreted as `19xx` birth years.
|
|
318
|
+
- **Age is dynamic** — `age` is computed against the current date at call time, so the same NIC returns a different age over time.
|
|
319
|
+
- **February 29** — because the format reserves day 60 for Feb 29 in every year, a non-leap birth year can decode to a calendar date that didn't technically occur (e.g. `"1997-02-29"`). This is faithful to what the card encodes. If you'd rather reject such impossible dates, that guard is a one-line change in the source.
|
|
320
|
+
|
|
321
|
+
## License
|
|
322
|
+
|
|
323
|
+
[MIT](./LICENSE) © rohan_jayaraj
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sl-nic-validator-and-information-extractor",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "A function to validate new and old NIC of Sri Lanka and a function to extract information from the NIC",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|