@aakashwije/lanka-nic 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/dist/index.cjs ADDED
@@ -0,0 +1,300 @@
1
+ 'use strict';
2
+
3
+ // src/errors.ts
4
+ var NICError = class extends Error {
5
+ code;
6
+ input;
7
+ constructor(code, message, input) {
8
+ super(message);
9
+ this.name = "NICError";
10
+ this.code = code;
11
+ this.input = input;
12
+ }
13
+ };
14
+
15
+ // src/utils/constants.ts
16
+ var OLD_NIC_PATTERN = /^\d{9}[VvXx]$/;
17
+ var NEW_NIC_PATTERN = /^\d{12}$/;
18
+ var DAY_CODE_MIN = 1;
19
+ var DAY_CODE_MAX_MALE = 366;
20
+ var DAY_CODE_FEMALE_OFFSET = 500;
21
+ var DAY_CODE_MAX_FEMALE = 866;
22
+
23
+ // src/normalize.ts
24
+ var normalizeNIC = (nic) => {
25
+ if (typeof nic !== "string") {
26
+ return "";
27
+ }
28
+ const compact = nic.trim().replace(/\s+/g, "");
29
+ if (OLD_NIC_PATTERN.test(compact)) {
30
+ return compact.slice(0, 9) + compact.slice(9).toUpperCase();
31
+ }
32
+ return compact;
33
+ };
34
+
35
+ // src/utils/date.ts
36
+ var isLeapYear = (year) => {
37
+ return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
38
+ };
39
+ var dayOfYearToUTCDate = (year, dayOfYear) => {
40
+ const maxDays = isLeapYear(year) ? 366 : 365;
41
+ if (dayOfYear < 1 || dayOfYear > maxDays) {
42
+ return null;
43
+ }
44
+ return new Date(Date.UTC(year, 0, dayOfYear));
45
+ };
46
+ var formatUTCDate = (date) => {
47
+ return date.toISOString().slice(0, 10);
48
+ };
49
+ var parseUTCBirthDate = (iso) => {
50
+ const year = Number(iso.slice(0, 4));
51
+ const month = Number(iso.slice(5, 7));
52
+ const day = Number(iso.slice(8, 10));
53
+ return new Date(Date.UTC(year, month - 1, day));
54
+ };
55
+
56
+ // src/parse.ts
57
+ var getUTCFullYearNow = () => (/* @__PURE__ */ new Date()).getUTCFullYear();
58
+ var fail = (code, message, input) => ({
59
+ success: false,
60
+ error: new NICError(code, message, input)
61
+ });
62
+ var resolveGenderAndDay = (dayCode) => {
63
+ if (dayCode >= DAY_CODE_MIN && dayCode <= DAY_CODE_MAX_MALE) {
64
+ return { gender: "male", dayOfYear: dayCode };
65
+ }
66
+ if (dayCode >= DAY_CODE_FEMALE_OFFSET + DAY_CODE_MIN && dayCode <= DAY_CODE_MAX_FEMALE) {
67
+ return { gender: "female", dayOfYear: dayCode - DAY_CODE_FEMALE_OFFSET };
68
+ }
69
+ return null;
70
+ };
71
+ var getNICType = (nic) => {
72
+ if (typeof nic !== "string") {
73
+ return "invalid";
74
+ }
75
+ const normalized = normalizeNIC(nic);
76
+ if (OLD_NIC_PATTERN.test(normalized)) {
77
+ return "old";
78
+ }
79
+ if (NEW_NIC_PATTERN.test(normalized)) {
80
+ return "new";
81
+ }
82
+ return "invalid";
83
+ };
84
+ var safeParse = (nic) => {
85
+ if (typeof nic !== "string") {
86
+ return fail("NON_STRING", "NIC must be a string", nic);
87
+ }
88
+ const normalized = normalizeNIC(nic);
89
+ if (!normalized) {
90
+ return fail("EMPTY", "NIC is empty", nic);
91
+ }
92
+ const type = getNICType(normalized);
93
+ if (type === "invalid") {
94
+ return fail(
95
+ "INVALID_FORMAT",
96
+ "NIC does not match old or new format",
97
+ nic
98
+ );
99
+ }
100
+ const birthYear = type === "old" ? 1900 + Number.parseInt(normalized.slice(0, 2), 10) : Number.parseInt(normalized.slice(0, 4), 10);
101
+ if (birthYear > getUTCFullYearNow()) {
102
+ return fail("FUTURE_YEAR", `birth year ${birthYear} is in the future`, nic);
103
+ }
104
+ const dayCode = type === "old" ? Number.parseInt(normalized.slice(2, 5), 10) : Number.parseInt(normalized.slice(4, 7), 10);
105
+ const genderAndDay = resolveGenderAndDay(dayCode);
106
+ if (!genderAndDay) {
107
+ return fail(
108
+ "INVALID_DAY_CODE",
109
+ `day code ${dayCode} is out of range`,
110
+ nic
111
+ );
112
+ }
113
+ const date = dayOfYearToUTCDate(birthYear, genderAndDay.dayOfYear);
114
+ if (!date) {
115
+ return fail(
116
+ "INVALID_DAY_FOR_YEAR",
117
+ `day ${genderAndDay.dayOfYear} does not exist in year ${birthYear}`,
118
+ nic
119
+ );
120
+ }
121
+ return {
122
+ success: true,
123
+ data: {
124
+ input: nic,
125
+ normalized,
126
+ type,
127
+ valid: true,
128
+ birthYear,
129
+ dayOfYear: genderAndDay.dayOfYear,
130
+ birthDate: formatUTCDate(date),
131
+ gender: genderAndDay.gender
132
+ }
133
+ };
134
+ };
135
+ var parseNIC = (nic) => {
136
+ const result = safeParse(nic);
137
+ return result.success ? result.data : null;
138
+ };
139
+ var parseNICOrThrow = (nic) => {
140
+ const result = safeParse(nic);
141
+ if (result.success) {
142
+ return result.data;
143
+ }
144
+ throw result.error;
145
+ };
146
+ var getBirthDate = (nic) => {
147
+ return parseNIC(nic)?.birthDate ?? null;
148
+ };
149
+ var getGender = (nic) => {
150
+ return parseNIC(nic)?.gender ?? null;
151
+ };
152
+
153
+ // src/validate.ts
154
+ var validateNIC = (nic) => {
155
+ return parseNIC(nic) !== null;
156
+ };
157
+
158
+ // src/mask.ts
159
+ var maskNIC = (nic) => {
160
+ if (typeof nic !== "string") {
161
+ return "";
162
+ }
163
+ const normalized = normalizeNIC(nic);
164
+ const type = getNICType(normalized);
165
+ if (type === "old") {
166
+ return `${normalized.slice(0, 5)}****${normalized.slice(9)}`;
167
+ }
168
+ if (type === "new") {
169
+ return `${normalized.slice(0, 7)}*****`;
170
+ }
171
+ return normalized;
172
+ };
173
+
174
+ // src/convert.ts
175
+ var convertOldToNew = (nic) => {
176
+ if (typeof nic !== "string") {
177
+ return null;
178
+ }
179
+ const normalized = normalizeNIC(nic);
180
+ if (getNICType(normalized) !== "old") {
181
+ return null;
182
+ }
183
+ const year = `19${normalized.slice(0, 2)}`;
184
+ const dayCode = normalized.slice(2, 5);
185
+ const serial = normalized.slice(5, 9);
186
+ return `${year}${dayCode}${serial}`;
187
+ };
188
+
189
+ // src/guards.ts
190
+ var isValidNIC = (value) => {
191
+ return typeof value === "string" && validateNIC(value);
192
+ };
193
+ var isOldNIC = (value) => {
194
+ return typeof value === "string" && getNICType(value) === "old" && validateNIC(value);
195
+ };
196
+ var isNewNIC = (value) => {
197
+ return typeof value === "string" && getNICType(value) === "new" && validateNIC(value);
198
+ };
199
+
200
+ // src/age.ts
201
+ var toUTCDay = (date) => {
202
+ return new Date(
203
+ Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate())
204
+ );
205
+ };
206
+ var todayUTC = () => toUTCDay(/* @__PURE__ */ new Date());
207
+ var getAgeOn = (nic, date) => {
208
+ const parsed = parseNIC(nic);
209
+ if (!parsed) {
210
+ return null;
211
+ }
212
+ const birth = parseUTCBirthDate(parsed.birthDate);
213
+ const ref = toUTCDay(date);
214
+ if (ref.getTime() < birth.getTime()) {
215
+ return null;
216
+ }
217
+ let age = ref.getUTCFullYear() - birth.getUTCFullYear();
218
+ const monthDiff = ref.getUTCMonth() - birth.getUTCMonth();
219
+ if (monthDiff < 0 || monthDiff === 0 && ref.getUTCDate() < birth.getUTCDate()) {
220
+ age -= 1;
221
+ }
222
+ return age;
223
+ };
224
+ var getAge = (nic, opts) => {
225
+ const ref = opts?.now ?? todayUTC();
226
+ return getAgeOn(nic, ref);
227
+ };
228
+
229
+ // src/equals.ts
230
+ var serialOf = (parsed) => {
231
+ if (parsed.type === "old") {
232
+ return parsed.normalized.slice(5, 9);
233
+ }
234
+ return parsed.normalized.slice(7, 11);
235
+ };
236
+ var equalsNIC = (a, b) => {
237
+ const pa = parseNIC(a);
238
+ const pb = parseNIC(b);
239
+ if (!pa || !pb) {
240
+ return false;
241
+ }
242
+ return pa.birthYear === pb.birthYear && pa.dayOfYear === pb.dayOfYear && pa.gender === pb.gender && serialOf(pa) === serialOf(pb);
243
+ };
244
+
245
+ // src/batch.ts
246
+ var validateBatch = (nics) => nics.map(validateNIC);
247
+ var parseBatch = (nics) => nics.map(parseNIC);
248
+
249
+ // src/generate.ts
250
+ var padLeft = (value, length) => String(value).padStart(length, "0").slice(-length);
251
+ var generateNIC = (opts) => {
252
+ const { year, dayOfYear, gender, format } = opts;
253
+ const serial = opts.serial ?? 1234;
254
+ if (year < 1900) {
255
+ throw new Error("year must be >= 1900");
256
+ }
257
+ if (format === "old" && year > 1999) {
258
+ throw new Error("old format only supports years 1900-1999");
259
+ }
260
+ if (!dayOfYearToUTCDate(year, dayOfYear)) {
261
+ throw new Error(`invalid day ${dayOfYear} for year ${year}`);
262
+ }
263
+ if (serial < 0) {
264
+ throw new Error("serial must be >= 0");
265
+ }
266
+ const dayCode = gender === "male" ? dayOfYear : dayOfYear + DAY_CODE_FEMALE_OFFSET;
267
+ if (format === "old") {
268
+ const yy = padLeft(year - 1900, 2);
269
+ const ddd2 = padLeft(dayCode, 3);
270
+ const ssss = padLeft(serial, 4);
271
+ return `${yy}${ddd2}${ssss}V`;
272
+ }
273
+ const yyyy = padLeft(year, 4);
274
+ const ddd = padLeft(dayCode, 3);
275
+ const sssss = padLeft(serial, 5);
276
+ return `${yyyy}${ddd}${sssss}`;
277
+ };
278
+
279
+ exports.NICError = NICError;
280
+ exports.convertOldToNew = convertOldToNew;
281
+ exports.equalsNIC = equalsNIC;
282
+ exports.generateNIC = generateNIC;
283
+ exports.getAge = getAge;
284
+ exports.getAgeOn = getAgeOn;
285
+ exports.getBirthDate = getBirthDate;
286
+ exports.getGender = getGender;
287
+ exports.getNICType = getNICType;
288
+ exports.isNewNIC = isNewNIC;
289
+ exports.isOldNIC = isOldNIC;
290
+ exports.isValidNIC = isValidNIC;
291
+ exports.maskNIC = maskNIC;
292
+ exports.normalizeNIC = normalizeNIC;
293
+ exports.parseBatch = parseBatch;
294
+ exports.parseNIC = parseNIC;
295
+ exports.parseNICOrThrow = parseNICOrThrow;
296
+ exports.safeParse = safeParse;
297
+ exports.validateBatch = validateBatch;
298
+ exports.validateNIC = validateNIC;
299
+ //# sourceMappingURL=index.cjs.map
300
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/utils/constants.ts","../src/normalize.ts","../src/utils/date.ts","../src/parse.ts","../src/validate.ts","../src/mask.ts","../src/convert.ts","../src/guards.ts","../src/age.ts","../src/equals.ts","../src/batch.ts","../src/generate.ts"],"names":["ddd"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { NICErrorCode } from './types';\n\nexport class NICError extends Error {\n readonly code: NICErrorCode;\n readonly input: unknown;\n\n constructor(code: NICErrorCode, message: string, input: unknown) {\n super(message);\n this.name = 'NICError';\n this.code = code;\n this.input = input;\n }\n}\n","export const OLD_NIC_PATTERN = /^\\d{9}[VvXx]$/;\nexport const NEW_NIC_PATTERN = /^\\d{12}$/;\n\nexport const DAY_CODE_MIN = 1;\nexport const DAY_CODE_MAX_MALE = 366;\nexport const DAY_CODE_FEMALE_OFFSET = 500;\nexport const DAY_CODE_MAX_FEMALE = 866;\n","import { OLD_NIC_PATTERN } from './utils/constants';\n\nexport const normalizeNIC = (nic: string): string => {\n if (typeof nic !== 'string') {\n return '';\n }\n\n const compact = nic.trim().replace(/\\s+/g, '');\n if (OLD_NIC_PATTERN.test(compact)) {\n return compact.slice(0, 9) + compact.slice(9).toUpperCase();\n }\n\n return compact;\n};\n","export const isLeapYear = (year: number): boolean => {\n return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;\n};\n\nexport const dayOfYearToUTCDate = (year: number, dayOfYear: number): Date | null => {\n const maxDays = isLeapYear(year) ? 366 : 365;\n if (dayOfYear < 1 || dayOfYear > maxDays) {\n return null;\n }\n\n return new Date(Date.UTC(year, 0, dayOfYear));\n};\n\nexport const formatUTCDate = (date: Date): string => {\n return date.toISOString().slice(0, 10);\n};\n\nexport const parseUTCBirthDate = (iso: string): Date => {\n const year = Number(iso.slice(0, 4));\n const month = Number(iso.slice(5, 7));\n const day = Number(iso.slice(8, 10));\n return new Date(Date.UTC(year, month - 1, day));\n};\n","import { NICError } from './errors';\nimport { normalizeNIC } from './normalize';\nimport type {\n NICErrorCode,\n NICGender,\n NICType,\n ParsedNIC,\n SafeParseResult\n} from './types';\nimport {\n DAY_CODE_FEMALE_OFFSET,\n DAY_CODE_MAX_FEMALE,\n DAY_CODE_MAX_MALE,\n DAY_CODE_MIN,\n NEW_NIC_PATTERN,\n OLD_NIC_PATTERN\n} from './utils/constants';\nimport { dayOfYearToUTCDate, formatUTCDate } from './utils/date';\n\nconst getUTCFullYearNow = (): number => new Date().getUTCFullYear();\n\nconst fail = (\n code: NICErrorCode,\n message: string,\n input: unknown\n): SafeParseResult<ParsedNIC> => ({\n success: false,\n error: new NICError(code, message, input)\n});\n\nconst resolveGenderAndDay = (\n dayCode: number\n): { gender: NICGender; dayOfYear: number } | null => {\n if (dayCode >= DAY_CODE_MIN && dayCode <= DAY_CODE_MAX_MALE) {\n return { gender: 'male', dayOfYear: dayCode };\n }\n\n if (\n dayCode >= DAY_CODE_FEMALE_OFFSET + DAY_CODE_MIN &&\n dayCode <= DAY_CODE_MAX_FEMALE\n ) {\n return { gender: 'female', dayOfYear: dayCode - DAY_CODE_FEMALE_OFFSET };\n }\n\n return null;\n};\n\nexport const getNICType = (nic: string): NICType => {\n if (typeof nic !== 'string') {\n return 'invalid';\n }\n\n const normalized = normalizeNIC(nic);\n\n if (OLD_NIC_PATTERN.test(normalized)) {\n return 'old';\n }\n\n if (NEW_NIC_PATTERN.test(normalized)) {\n return 'new';\n }\n\n return 'invalid';\n};\n\nexport const safeParse = (nic: unknown): SafeParseResult<ParsedNIC> => {\n if (typeof nic !== 'string') {\n return fail('NON_STRING', 'NIC must be a string', nic);\n }\n\n const normalized = normalizeNIC(nic);\n if (!normalized) {\n return fail('EMPTY', 'NIC is empty', nic);\n }\n\n const type = getNICType(normalized);\n if (type === 'invalid') {\n return fail(\n 'INVALID_FORMAT',\n 'NIC does not match old or new format',\n nic\n );\n }\n\n const birthYear =\n type === 'old'\n ? 1900 + Number.parseInt(normalized.slice(0, 2), 10)\n : Number.parseInt(normalized.slice(0, 4), 10);\n\n if (birthYear > getUTCFullYearNow()) {\n return fail('FUTURE_YEAR', `birth year ${birthYear} is in the future`, nic);\n }\n\n const dayCode =\n type === 'old'\n ? Number.parseInt(normalized.slice(2, 5), 10)\n : Number.parseInt(normalized.slice(4, 7), 10);\n\n const genderAndDay = resolveGenderAndDay(dayCode);\n if (!genderAndDay) {\n return fail(\n 'INVALID_DAY_CODE',\n `day code ${dayCode} is out of range`,\n nic\n );\n }\n\n const date = dayOfYearToUTCDate(birthYear, genderAndDay.dayOfYear);\n if (!date) {\n return fail(\n 'INVALID_DAY_FOR_YEAR',\n `day ${genderAndDay.dayOfYear} does not exist in year ${birthYear}`,\n nic\n );\n }\n\n return {\n success: true,\n data: {\n input: nic,\n normalized,\n type,\n valid: true,\n birthYear,\n dayOfYear: genderAndDay.dayOfYear,\n birthDate: formatUTCDate(date),\n gender: genderAndDay.gender\n }\n };\n};\n\nexport const parseNIC = (nic: string): ParsedNIC | null => {\n const result = safeParse(nic);\n return result.success ? result.data : null;\n};\n\nexport const parseNICOrThrow = (nic: string): ParsedNIC => {\n const result = safeParse(nic);\n if (result.success) {\n return result.data;\n }\n throw result.error;\n};\n\nexport const getBirthDate = (nic: string): string | null => {\n return parseNIC(nic)?.birthDate ?? null;\n};\n\nexport const getGender = (nic: string): NICGender | null => {\n return parseNIC(nic)?.gender ?? null;\n};\n","import { parseNIC } from './parse';\n\nexport const validateNIC = (nic: string): boolean => {\n return parseNIC(nic) !== null;\n};\n","import { normalizeNIC } from './normalize';\nimport { getNICType } from './parse';\n\nexport const maskNIC = (nic: string): string => {\n if (typeof nic !== 'string') {\n return '';\n }\n\n const normalized = normalizeNIC(nic);\n const type = getNICType(normalized);\n\n if (type === 'old') {\n return `${normalized.slice(0, 5)}****${normalized.slice(9)}`;\n }\n\n if (type === 'new') {\n return `${normalized.slice(0, 7)}*****`;\n }\n\n return normalized;\n};\n","import { getNICType } from './parse';\nimport { normalizeNIC } from './normalize';\n\nexport const convertOldToNew = (nic: string): string | null => {\n if (typeof nic !== 'string') {\n return null;\n }\n\n const normalized = normalizeNIC(nic);\n if (getNICType(normalized) !== 'old') {\n return null;\n }\n\n const year = `19${normalized.slice(0, 2)}`;\n const dayCode = normalized.slice(2, 5);\n const serial = normalized.slice(5, 9);\n\n // This produces a best-effort 11-digit form documented by this package.\n return `${year}${dayCode}${serial}`;\n};\n","import { getNICType } from './parse';\nimport { validateNIC } from './validate';\n\nexport const isValidNIC = (value: unknown): value is string => {\n return typeof value === 'string' && validateNIC(value);\n};\n\nexport const isOldNIC = (value: unknown): value is string => {\n return (\n typeof value === 'string' &&\n getNICType(value) === 'old' &&\n validateNIC(value)\n );\n};\n\nexport const isNewNIC = (value: unknown): value is string => {\n return (\n typeof value === 'string' &&\n getNICType(value) === 'new' &&\n validateNIC(value)\n );\n};\n","import { parseNIC } from './parse';\nimport { parseUTCBirthDate } from './utils/date';\n\nconst toUTCDay = (date: Date): Date => {\n return new Date(\n Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate())\n );\n};\n\nconst todayUTC = (): Date => toUTCDay(new Date());\n\nexport const getAgeOn = (nic: string, date: Date): number | null => {\n const parsed = parseNIC(nic);\n if (!parsed) {\n return null;\n }\n\n const birth = parseUTCBirthDate(parsed.birthDate);\n const ref = toUTCDay(date);\n\n if (ref.getTime() < birth.getTime()) {\n return null;\n }\n\n let age = ref.getUTCFullYear() - birth.getUTCFullYear();\n const monthDiff = ref.getUTCMonth() - birth.getUTCMonth();\n if (\n monthDiff < 0 ||\n (monthDiff === 0 && ref.getUTCDate() < birth.getUTCDate())\n ) {\n age -= 1;\n }\n\n return age;\n};\n\nexport const getAge = (\n nic: string,\n opts?: { now?: Date }\n): number | null => {\n const ref = opts?.now ?? todayUTC();\n return getAgeOn(nic, ref);\n};\n","import { parseNIC } from './parse';\nimport type { ParsedNIC } from './types';\n\nconst serialOf = (parsed: ParsedNIC): string => {\n if (parsed.type === 'old') {\n return parsed.normalized.slice(5, 9);\n }\n return parsed.normalized.slice(7, 11);\n};\n\nexport const equalsNIC = (a: string, b: string): boolean => {\n const pa = parseNIC(a);\n const pb = parseNIC(b);\n\n if (!pa || !pb) {\n return false;\n }\n\n return (\n pa.birthYear === pb.birthYear &&\n pa.dayOfYear === pb.dayOfYear &&\n pa.gender === pb.gender &&\n serialOf(pa) === serialOf(pb)\n );\n};\n","import { parseNIC } from './parse';\nimport type { ParsedNIC } from './types';\nimport { validateNIC } from './validate';\n\nexport const validateBatch = (nics: string[]): boolean[] => nics.map(validateNIC);\n\nexport const parseBatch = (nics: string[]): (ParsedNIC | null)[] =>\n nics.map(parseNIC);\n","import { DAY_CODE_FEMALE_OFFSET } from './utils/constants';\nimport { dayOfYearToUTCDate } from './utils/date';\n\nexport type NICGenerateOptions = {\n year: number;\n dayOfYear: number;\n gender: 'male' | 'female';\n format: 'old' | 'new';\n serial?: number;\n};\n\nconst padLeft = (value: number, length: number): string =>\n String(value).padStart(length, '0').slice(-length);\n\nexport const generateNIC = (opts: NICGenerateOptions): string => {\n const { year, dayOfYear, gender, format } = opts;\n const serial = opts.serial ?? 1234;\n\n if (year < 1900) {\n throw new Error('year must be >= 1900');\n }\n\n if (format === 'old' && year > 1999) {\n throw new Error('old format only supports years 1900-1999');\n }\n\n if (!dayOfYearToUTCDate(year, dayOfYear)) {\n throw new Error(`invalid day ${dayOfYear} for year ${year}`);\n }\n\n if (serial < 0) {\n throw new Error('serial must be >= 0');\n }\n\n const dayCode =\n gender === 'male' ? dayOfYear : dayOfYear + DAY_CODE_FEMALE_OFFSET;\n\n if (format === 'old') {\n const yy = padLeft(year - 1900, 2);\n const ddd = padLeft(dayCode, 3);\n const ssss = padLeft(serial, 4);\n return `${yy}${ddd}${ssss}V`;\n }\n\n const yyyy = padLeft(year, 4);\n const ddd = padLeft(dayCode, 3);\n const sssss = padLeft(serial, 5);\n return `${yyyy}${ddd}${sssss}`;\n};\n"]}
@@ -0,0 +1,72 @@
1
+ declare class NICError extends Error {
2
+ readonly code: NICErrorCode;
3
+ readonly input: unknown;
4
+ constructor(code: NICErrorCode, message: string, input: unknown);
5
+ }
6
+
7
+ type NICType = 'old' | 'new' | 'invalid';
8
+ type NICGender = 'male' | 'female';
9
+ declare const NormalizedNICBrand: unique symbol;
10
+ type NormalizedNIC = string & {
11
+ readonly [NormalizedNICBrand]: true;
12
+ };
13
+ type NICErrorCode = 'EMPTY' | 'NON_STRING' | 'INVALID_FORMAT' | 'INVALID_DAY_CODE' | 'INVALID_DAY_FOR_YEAR' | 'FUTURE_YEAR';
14
+ type ParsedNIC = {
15
+ input: string;
16
+ normalized: string;
17
+ type: 'old' | 'new';
18
+ valid: boolean;
19
+ birthYear: number;
20
+ dayOfYear: number;
21
+ birthDate: string;
22
+ gender: NICGender;
23
+ };
24
+ type SafeParseSuccess<T> = {
25
+ success: true;
26
+ data: T;
27
+ };
28
+ type SafeParseFailure = {
29
+ success: false;
30
+ error: NICError;
31
+ };
32
+ type SafeParseResult<T> = SafeParseSuccess<T> | SafeParseFailure;
33
+
34
+ declare const normalizeNIC: (nic: string) => string;
35
+
36
+ declare const getNICType: (nic: string) => NICType;
37
+ declare const safeParse: (nic: unknown) => SafeParseResult<ParsedNIC>;
38
+ declare const parseNIC: (nic: string) => ParsedNIC | null;
39
+ declare const parseNICOrThrow: (nic: string) => ParsedNIC;
40
+ declare const getBirthDate: (nic: string) => string | null;
41
+ declare const getGender: (nic: string) => NICGender | null;
42
+
43
+ declare const validateNIC: (nic: string) => boolean;
44
+
45
+ declare const maskNIC: (nic: string) => string;
46
+
47
+ declare const convertOldToNew: (nic: string) => string | null;
48
+
49
+ declare const isValidNIC: (value: unknown) => value is string;
50
+ declare const isOldNIC: (value: unknown) => value is string;
51
+ declare const isNewNIC: (value: unknown) => value is string;
52
+
53
+ declare const getAgeOn: (nic: string, date: Date) => number | null;
54
+ declare const getAge: (nic: string, opts?: {
55
+ now?: Date;
56
+ }) => number | null;
57
+
58
+ declare const equalsNIC: (a: string, b: string) => boolean;
59
+
60
+ declare const validateBatch: (nics: string[]) => boolean[];
61
+ declare const parseBatch: (nics: string[]) => (ParsedNIC | null)[];
62
+
63
+ type NICGenerateOptions = {
64
+ year: number;
65
+ dayOfYear: number;
66
+ gender: 'male' | 'female';
67
+ format: 'old' | 'new';
68
+ serial?: number;
69
+ };
70
+ declare const generateNIC: (opts: NICGenerateOptions) => string;
71
+
72
+ export { NICError, type NICErrorCode, type NICGender, type NICGenerateOptions, type NICType, type NormalizedNIC, type ParsedNIC, type SafeParseFailure, type SafeParseResult, type SafeParseSuccess, convertOldToNew, equalsNIC, generateNIC, getAge, getAgeOn, getBirthDate, getGender, getNICType, isNewNIC, isOldNIC, isValidNIC, maskNIC, normalizeNIC, parseBatch, parseNIC, parseNICOrThrow, safeParse, validateBatch, validateNIC };
@@ -0,0 +1,72 @@
1
+ declare class NICError extends Error {
2
+ readonly code: NICErrorCode;
3
+ readonly input: unknown;
4
+ constructor(code: NICErrorCode, message: string, input: unknown);
5
+ }
6
+
7
+ type NICType = 'old' | 'new' | 'invalid';
8
+ type NICGender = 'male' | 'female';
9
+ declare const NormalizedNICBrand: unique symbol;
10
+ type NormalizedNIC = string & {
11
+ readonly [NormalizedNICBrand]: true;
12
+ };
13
+ type NICErrorCode = 'EMPTY' | 'NON_STRING' | 'INVALID_FORMAT' | 'INVALID_DAY_CODE' | 'INVALID_DAY_FOR_YEAR' | 'FUTURE_YEAR';
14
+ type ParsedNIC = {
15
+ input: string;
16
+ normalized: string;
17
+ type: 'old' | 'new';
18
+ valid: boolean;
19
+ birthYear: number;
20
+ dayOfYear: number;
21
+ birthDate: string;
22
+ gender: NICGender;
23
+ };
24
+ type SafeParseSuccess<T> = {
25
+ success: true;
26
+ data: T;
27
+ };
28
+ type SafeParseFailure = {
29
+ success: false;
30
+ error: NICError;
31
+ };
32
+ type SafeParseResult<T> = SafeParseSuccess<T> | SafeParseFailure;
33
+
34
+ declare const normalizeNIC: (nic: string) => string;
35
+
36
+ declare const getNICType: (nic: string) => NICType;
37
+ declare const safeParse: (nic: unknown) => SafeParseResult<ParsedNIC>;
38
+ declare const parseNIC: (nic: string) => ParsedNIC | null;
39
+ declare const parseNICOrThrow: (nic: string) => ParsedNIC;
40
+ declare const getBirthDate: (nic: string) => string | null;
41
+ declare const getGender: (nic: string) => NICGender | null;
42
+
43
+ declare const validateNIC: (nic: string) => boolean;
44
+
45
+ declare const maskNIC: (nic: string) => string;
46
+
47
+ declare const convertOldToNew: (nic: string) => string | null;
48
+
49
+ declare const isValidNIC: (value: unknown) => value is string;
50
+ declare const isOldNIC: (value: unknown) => value is string;
51
+ declare const isNewNIC: (value: unknown) => value is string;
52
+
53
+ declare const getAgeOn: (nic: string, date: Date) => number | null;
54
+ declare const getAge: (nic: string, opts?: {
55
+ now?: Date;
56
+ }) => number | null;
57
+
58
+ declare const equalsNIC: (a: string, b: string) => boolean;
59
+
60
+ declare const validateBatch: (nics: string[]) => boolean[];
61
+ declare const parseBatch: (nics: string[]) => (ParsedNIC | null)[];
62
+
63
+ type NICGenerateOptions = {
64
+ year: number;
65
+ dayOfYear: number;
66
+ gender: 'male' | 'female';
67
+ format: 'old' | 'new';
68
+ serial?: number;
69
+ };
70
+ declare const generateNIC: (opts: NICGenerateOptions) => string;
71
+
72
+ export { NICError, type NICErrorCode, type NICGender, type NICGenerateOptions, type NICType, type NormalizedNIC, type ParsedNIC, type SafeParseFailure, type SafeParseResult, type SafeParseSuccess, convertOldToNew, equalsNIC, generateNIC, getAge, getAgeOn, getBirthDate, getGender, getNICType, isNewNIC, isOldNIC, isValidNIC, maskNIC, normalizeNIC, parseBatch, parseNIC, parseNICOrThrow, safeParse, validateBatch, validateNIC };