asma-helpers 0.37.10 → 0.37.11
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/lib/helpers/validateNorwegianPersonalNumber.d.ts +0 -6
- package/lib/helpers/validateNorwegianPersonalNumber.d.ts.map +1 -1
- package/lib/helpers/validateNorwegianPersonalNumber.js +37 -27
- package/lib/helpers/validateNorwegianPersonalNumber.js.map +1 -1
- package/package.json +1 -1
- package/src/helpers/validateNorwegianPersonalNumber.ts +55 -38
|
@@ -15,12 +15,6 @@ export declare const validateNorwegianPersonalNumber: (number: string) => NORWEG
|
|
|
15
15
|
* @returns Formatted date string (DD.MM.YYYY) if the ID is valid, or null if the ID is invalid.
|
|
16
16
|
*/
|
|
17
17
|
export declare const getBirthDateFromNorwegianPersonalNumber: (number: string) => string | null;
|
|
18
|
-
/**
|
|
19
|
-
*
|
|
20
|
-
* Is considered valid synthetic month if syntheticMonth is one of these: 41-52, 53-64, 65, 66-77, 81-92
|
|
21
|
-
*/
|
|
22
|
-
export declare function getAddedNumberForSyntheticMonth(syntheticMonth: number): number | 'INVALID';
|
|
23
|
-
export declare function convertStringToNumberArray(str: string): [number, number, number, number, number, number, number, number, number, number, number];
|
|
24
18
|
export declare function generateUniqueToken(user: {
|
|
25
19
|
fnr: string;
|
|
26
20
|
salt: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateNorwegianPersonalNumber.d.ts","sourceRoot":"","sources":["../../src/helpers/validateNorwegianPersonalNumber.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,yBAAyB,wDAAyD,CAAA;AAE/F,MAAM,MAAM,+BAA+B,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;AACpG,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAElE;AACD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE1D;AACD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAElE;AACD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE7D;AACD,wBAAgB,8CAA8C,CAAC,MAAM,EAAE,MAAM,GAAG;IAC5E,KAAK,EAAE,+BAA+B,CAAA;IACtC,SAAS,CAAC,EAAE,MAAM,CAAA;CACrB,
|
|
1
|
+
{"version":3,"file":"validateNorwegianPersonalNumber.d.ts","sourceRoot":"","sources":["../../src/helpers/validateNorwegianPersonalNumber.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,yBAAyB,wDAAyD,CAAA;AAE/F,MAAM,MAAM,+BAA+B,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;AACpG,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAElE;AACD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE1D;AACD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAElE;AACD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE7D;AACD,wBAAgB,8CAA8C,CAAC,MAAM,EAAE,MAAM,GAAG;IAC5E,KAAK,EAAE,+BAA+B,CAAA;IACtC,SAAS,CAAC,EAAE,MAAM,CAAA;CACrB,CA4FA;AAED,eAAO,MAAM,+BAA+B,WAAY,MAAM,oCACE,CAAA;AAEhE;;;;GAIG;AACH,eAAO,MAAM,uCAAuC,WAAY,MAAM,kBACM,CAAA;AAmC5E,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAQrH"}
|
|
@@ -16,34 +16,44 @@ export function validateNorwegianPersonalNumberAndGetBirthDate(number) {
|
|
|
16
16
|
// Check if the number has the correct format (11 digits)
|
|
17
17
|
if (!/^\d{11}$/.test(number))
|
|
18
18
|
return { class: 'INVALID' };
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Convert the string to an array of digits
|
|
21
|
+
* Since the input is guaranteed to be 11 digits, digits will always be a number
|
|
22
|
+
*/
|
|
23
|
+
const digits = number.split('').map(Number);
|
|
23
24
|
// D-number: First digit between 4 and 7
|
|
24
25
|
const isDNumber = digits[0] >= 4 && digits[0] <= 7;
|
|
25
26
|
// Synthetic number: First digit of the birth date +40
|
|
26
27
|
const isSynthetic = digits[2] >= 4;
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
// Temporary number: Last five digits are `11111` or `22222`
|
|
29
|
+
const isTemporary = ['11111', '22222'].includes(number.slice(6));
|
|
30
|
+
let day = digits[0] * 10 + digits[1];
|
|
31
|
+
let month = digits[2] * 10 + digits[3];
|
|
32
|
+
const year = digits[4] * 10 + digits[5];
|
|
33
|
+
const currentYear = new Date().getFullYear();
|
|
34
|
+
const fullYear = year + (year <= currentYear % 100 ? 2000 : 1900); // Adjust year based on the current century
|
|
35
|
+
// Format day and month with leading zero
|
|
36
|
+
const formatWithLeadingZero = (value) => value.toString().padStart(2, '0');
|
|
37
|
+
const formattedDay = formatWithLeadingZero(day);
|
|
38
|
+
const formattedMonth = formatWithLeadingZero(month);
|
|
39
|
+
const birthDate = `${formattedDay}.${formattedMonth}.${fullYear}`;
|
|
32
40
|
if (isSynthetic) {
|
|
33
41
|
const syntheticMonth = digits[2] * 10 + digits[3];
|
|
34
42
|
const addedNumber = getAddedNumberForSyntheticMonth(syntheticMonth);
|
|
35
|
-
if
|
|
36
|
-
|
|
37
|
-
|
|
43
|
+
// Invalid synthetic number if no valid month
|
|
44
|
+
if (addedNumber === 'INVALID') {
|
|
45
|
+
return { class: 'INVALID' };
|
|
46
|
+
}
|
|
47
|
+
// Subtract the added number to get the original month and update the birth date to reflect adjusted moth
|
|
48
|
+
month -= addedNumber;
|
|
49
|
+
return { class: 'SYNTHETIC', birthDate: `${formattedDay}.${formatWithLeadingZero(month)}.${fullYear}` };
|
|
38
50
|
}
|
|
39
51
|
else {
|
|
40
52
|
month = digits[2] * 10 + digits[3];
|
|
41
53
|
}
|
|
42
|
-
if (
|
|
43
|
-
return { class: '
|
|
44
|
-
|
|
45
|
-
if (lastFiveDigits === '11111' || lastFiveDigits === '22222')
|
|
46
|
-
return { class: 'TEMPORARY', birthDate: `${day}.${month}.${year}` };
|
|
54
|
+
if (isTemporary) {
|
|
55
|
+
return { class: 'TEMPORARY', birthDate };
|
|
56
|
+
}
|
|
47
57
|
// Validate control digits (modulus 11)
|
|
48
58
|
const k1Weights = [3, 7, 6, 1, 8, 9, 4, 5, 2];
|
|
49
59
|
const k2Weights = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2];
|
|
@@ -57,11 +67,15 @@ export function validateNorwegianPersonalNumberAndGetBirthDate(number) {
|
|
|
57
67
|
if (k1 !== digits[9] || k2 !== digits[10])
|
|
58
68
|
return { class: 'INVALID' };
|
|
59
69
|
// Identify type based on pattern
|
|
60
|
-
if (isDNumber)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return { class: '
|
|
64
|
-
|
|
70
|
+
if (isDNumber) {
|
|
71
|
+
day = digits[0] - 4 + digits[1] * 10;
|
|
72
|
+
// Update birth date to reflect adjusted day
|
|
73
|
+
return { class: 'DNUMBER', birthDate: `${formatWithLeadingZero(day)}.${formattedMonth}.${fullYear}` };
|
|
74
|
+
}
|
|
75
|
+
if (!isValidDate(year, month, day)) {
|
|
76
|
+
return { class: 'INVALID' };
|
|
77
|
+
}
|
|
78
|
+
return { class: 'REAL', birthDate };
|
|
65
79
|
}
|
|
66
80
|
export const validateNorwegianPersonalNumber = (number) => validateNorwegianPersonalNumberAndGetBirthDate(number).class;
|
|
67
81
|
/**
|
|
@@ -82,10 +96,9 @@ function isLeapYear(year) {
|
|
|
82
96
|
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
|
83
97
|
}
|
|
84
98
|
/**
|
|
85
|
-
*
|
|
86
99
|
* Is considered valid synthetic month if syntheticMonth is one of these: 41-52, 53-64, 65, 66-77, 81-92
|
|
87
100
|
*/
|
|
88
|
-
|
|
101
|
+
function getAddedNumberForSyntheticMonth(syntheticMonth) {
|
|
89
102
|
if (syntheticMonth === 65)
|
|
90
103
|
return 60; // Special case for 65
|
|
91
104
|
/**
|
|
@@ -100,9 +113,6 @@ export function getAddedNumberForSyntheticMonth(syntheticMonth) {
|
|
|
100
113
|
}
|
|
101
114
|
return 'INVALID'; // Return INVALID if no valid result found
|
|
102
115
|
}
|
|
103
|
-
export function convertStringToNumberArray(str) {
|
|
104
|
-
return str.split('').map(Number);
|
|
105
|
-
}
|
|
106
116
|
export function generateUniqueToken(user) {
|
|
107
117
|
const { fnr, salt, actno, customer_id } = user;
|
|
108
118
|
if (customer_id && actno && validateNorwegianPersonalNumber(fnr) === 'TEMPORARY') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateNorwegianPersonalNumber.js","sourceRoot":"","sources":["../../src/helpers/validateNorwegianPersonalNumber.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,CAAU,CAAA;AAG/F,MAAM,UAAU,0BAA0B,CAAC,MAAc;IACrD,OAAO,+BAA+B,CAAC,MAAM,CAAC,KAAK,WAAW,CAAA;AAClE,CAAC;AACD,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC7C,OAAO,+BAA+B,CAAC,MAAM,CAAC,KAAK,SAAS,CAAA;AAChE,CAAC;AACD,MAAM,UAAU,0BAA0B,CAAC,MAAc;IACrD,OAAO,+BAA+B,CAAC,MAAM,CAAC,KAAK,WAAW,CAAA;AAClE,CAAC;AACD,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAChD,OAAO,+BAA+B,CAAC,MAAM,CAAC,KAAK,MAAM,CAAA;AAC7D,CAAC;AACD,MAAM,UAAU,8CAA8C,CAAC,MAAc;IAIzE,yDAAyD;IACzD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;IAEzD
|
|
1
|
+
{"version":3,"file":"validateNorwegianPersonalNumber.js","sourceRoot":"","sources":["../../src/helpers/validateNorwegianPersonalNumber.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -22,11 +22,23 @@ export function validateNorwegianPersonalNumberAndGetBirthDate(number: string):
|
|
|
22
22
|
// Check if the number has the correct format (11 digits)
|
|
23
23
|
if (!/^\d{11}$/.test(number)) return { class: 'INVALID' }
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Convert the string to an array of digits
|
|
27
|
+
* Since the input is guaranteed to be 11 digits, digits will always be a number
|
|
28
|
+
*/
|
|
29
|
+
const digits = number.split('').map(Number) as [
|
|
30
|
+
number,
|
|
31
|
+
number,
|
|
32
|
+
number,
|
|
33
|
+
number,
|
|
34
|
+
number,
|
|
35
|
+
number,
|
|
36
|
+
number,
|
|
37
|
+
number,
|
|
38
|
+
number,
|
|
39
|
+
number,
|
|
40
|
+
number,
|
|
41
|
+
]
|
|
30
42
|
|
|
31
43
|
// D-number: First digit between 4 and 7
|
|
32
44
|
const isDNumber = digits[0] >= 4 && digits[0] <= 7
|
|
@@ -34,30 +46,42 @@ export function validateNorwegianPersonalNumberAndGetBirthDate(number: string):
|
|
|
34
46
|
// Synthetic number: First digit of the birth date +40
|
|
35
47
|
const isSynthetic = digits[2] >= 4
|
|
36
48
|
|
|
37
|
-
//
|
|
49
|
+
// Temporary number: Last five digits are `11111` or `22222`
|
|
50
|
+
const isTemporary = ['11111', '22222'].includes(number.slice(6))
|
|
38
51
|
|
|
39
|
-
|
|
40
|
-
|
|
52
|
+
let day = digits[0] * 10 + digits[1]
|
|
53
|
+
let month = digits[2] * 10 + digits[3]
|
|
54
|
+
const year = digits[4] * 10 + digits[5]
|
|
41
55
|
|
|
42
|
-
const
|
|
56
|
+
const currentYear = new Date().getFullYear()
|
|
57
|
+
const fullYear = year + (year <= currentYear % 100 ? 2000 : 1900) // Adjust year based on the current century
|
|
43
58
|
|
|
44
|
-
|
|
59
|
+
// Format day and month with leading zero
|
|
60
|
+
const formatWithLeadingZero = (value: number) => value.toString().padStart(2, '0')
|
|
61
|
+
const formattedDay = formatWithLeadingZero(day)
|
|
62
|
+
const formattedMonth = formatWithLeadingZero(month)
|
|
63
|
+
|
|
64
|
+
const birthDate = `${formattedDay}.${formattedMonth}.${fullYear}`
|
|
45
65
|
|
|
46
66
|
if (isSynthetic) {
|
|
47
67
|
const syntheticMonth = digits[2] * 10 + digits[3]
|
|
48
68
|
const addedNumber = getAddedNumberForSyntheticMonth(syntheticMonth)
|
|
49
69
|
|
|
50
|
-
|
|
51
|
-
|
|
70
|
+
// Invalid synthetic number if no valid month
|
|
71
|
+
if (addedNumber === 'INVALID') {
|
|
72
|
+
return { class: 'INVALID' }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Subtract the added number to get the original month and update the birth date to reflect adjusted moth
|
|
76
|
+
month -= addedNumber
|
|
77
|
+
return { class: 'SYNTHETIC', birthDate: `${formattedDay}.${formatWithLeadingZero(month)}.${fullYear}` }
|
|
52
78
|
} else {
|
|
53
79
|
month = digits[2] * 10 + digits[3]
|
|
54
80
|
}
|
|
55
|
-
if (!isValidDate(year, month, day)) return { class: 'INVALID' }
|
|
56
81
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return { class: 'TEMPORARY', birthDate: `${day}.${month}.${year}` }
|
|
82
|
+
if (isTemporary) {
|
|
83
|
+
return { class: 'TEMPORARY', birthDate }
|
|
84
|
+
}
|
|
61
85
|
|
|
62
86
|
// Validate control digits (modulus 11)
|
|
63
87
|
const k1Weights = [3, 7, 6, 1, 8, 9, 4, 5, 2]
|
|
@@ -75,10 +99,19 @@ export function validateNorwegianPersonalNumberAndGetBirthDate(number: string):
|
|
|
75
99
|
if (k1 !== digits[9] || k2 !== digits[10]) return { class: 'INVALID' }
|
|
76
100
|
|
|
77
101
|
// Identify type based on pattern
|
|
78
|
-
if (isDNumber)
|
|
79
|
-
|
|
80
|
-
|
|
102
|
+
if (isDNumber) {
|
|
103
|
+
day = digits[0] - 4 + digits[1] * 10
|
|
104
|
+
// Update birth date to reflect adjusted day
|
|
105
|
+
return { class: 'DNUMBER', birthDate: `${formatWithLeadingZero(day)}.${formattedMonth}.${fullYear}` }
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (!isValidDate(year, month, day)) {
|
|
109
|
+
return { class: 'INVALID' }
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return { class: 'REAL', birthDate }
|
|
81
113
|
}
|
|
114
|
+
|
|
82
115
|
export const validateNorwegianPersonalNumber = (number: string) =>
|
|
83
116
|
validateNorwegianPersonalNumberAndGetBirthDate(number).class
|
|
84
117
|
|
|
@@ -102,11 +135,11 @@ function isValidDate(year: number, month: number, day: number): boolean {
|
|
|
102
135
|
function isLeapYear(year: number): boolean {
|
|
103
136
|
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0
|
|
104
137
|
}
|
|
138
|
+
|
|
105
139
|
/**
|
|
106
|
-
*
|
|
107
140
|
* Is considered valid synthetic month if syntheticMonth is one of these: 41-52, 53-64, 65, 66-77, 81-92
|
|
108
141
|
*/
|
|
109
|
-
|
|
142
|
+
function getAddedNumberForSyntheticMonth(syntheticMonth: number): number | 'INVALID' {
|
|
110
143
|
if (syntheticMonth === 65) return 60 // Special case for 65
|
|
111
144
|
/**
|
|
112
145
|
* dead numbers 78,79,80
|
|
@@ -123,22 +156,6 @@ export function getAddedNumberForSyntheticMonth(syntheticMonth: number): number
|
|
|
123
156
|
return 'INVALID' // Return INVALID if no valid result found
|
|
124
157
|
}
|
|
125
158
|
|
|
126
|
-
export function convertStringToNumberArray(str: string) {
|
|
127
|
-
return str.split('').map(Number) as [
|
|
128
|
-
number,
|
|
129
|
-
number,
|
|
130
|
-
number,
|
|
131
|
-
number,
|
|
132
|
-
number,
|
|
133
|
-
number,
|
|
134
|
-
number,
|
|
135
|
-
number,
|
|
136
|
-
number,
|
|
137
|
-
number,
|
|
138
|
-
number,
|
|
139
|
-
]
|
|
140
|
-
}
|
|
141
|
-
|
|
142
159
|
export function generateUniqueToken(user: { fnr: string; salt: string; customer_id?: string; actno?: string }): string {
|
|
143
160
|
const { fnr, salt, actno, customer_id } = user
|
|
144
161
|
|