Skip to content

Commit 8c429fb

Browse files
committed
add orgnumbervalidator
1 parent af27e24 commit 8c429fb

File tree

12 files changed

+292
-130
lines changed

12 files changed

+292
-130
lines changed

packages/validation/src/no.ts

Lines changed: 0 additions & 26 deletions
This file was deleted.

packages/validation/src/se.ts

Lines changed: 0 additions & 25 deletions
This file was deleted.

packages/validation/src/validation.test.ts

Lines changed: 0 additions & 75 deletions
This file was deleted.

packages/validation/README.md renamed to packages/validator/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![NPM Version](https://img.shields.io/npm/v/%40obosbbl%2Fvalidation)](https://www.npmjs.com/package/@obosbbl/validation)
44

55

6-
A collection of validation utilities for both 🇳🇴 and 🇸🇪 with zero dependencies.
6+
A collection of validation utilities for both 🇳🇴 and 🇸🇪 with zero dependencies. Integrates neatly with [Zod](https://github.com/colinhacks/zod).
77

88
## Install
99

@@ -36,3 +36,5 @@ postalCodeValidator('000 000') // => false
3636
## Methods
3737

3838
* validatePostalCode
39+
* validatePhoneNumber
40+
* validateOrganizationNumber

packages/validation/package.json renamed to packages/validator/package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "@obosbbl/validation",
2+
"name": "@obosbbl/validator",
33
"version": "0.0.0",
44
"description": "A collection of validation methods for OBOS",
55
"repository": {
@@ -24,5 +24,7 @@
2424
"scripts": {
2525
"build": "bunchee"
2626
},
27-
"dependencies": {}
27+
"devDependencies": {
28+
"zod": "^3.24.1"
29+
}
2830
}

packages/validator/src/no.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { mod11, stripFormatting } from './utils';
2+
3+
type PostalCodeOptions = {
4+
/**
5+
* Disallow formatting characters
6+
* @default false
7+
*/
8+
strict?: boolean;
9+
};
10+
11+
/**
12+
* Validates the input value as a valid Norwegian postal (zip) code.
13+
* Valid format is `0000`.
14+
*/
15+
export function validatePostalCode(
16+
value: string,
17+
options: PostalCodeOptions = {},
18+
): boolean {
19+
if (!options.strict) {
20+
value = stripFormatting(value);
21+
}
22+
23+
return /^\d{4}$/.test(value);
24+
}
25+
26+
type PhoneNumberOptions = {
27+
/**
28+
* Whether it should be a mobile number
29+
* @default false
30+
*/
31+
mobileOnly?: boolean;
32+
/**
33+
* Disallow formatting characters
34+
* @default false
35+
*/
36+
strict?: boolean;
37+
};
38+
39+
export function validatePhoneNumber(
40+
value: string,
41+
options: PhoneNumberOptions = {},
42+
): boolean {
43+
if (!options.strict) {
44+
value = stripFormatting(value);
45+
}
46+
47+
const isPhoneNumber = /^\d{8}$/.test(value);
48+
49+
if (options.mobileOnly) {
50+
// Norwegian mobile phone numbers start with 4 or 9
51+
// See https://nkom.no/telefoni-og-telefonnummer/telefonnummer-og-den-norske-nummerplan/alle-nummerserier-for-norske-telefonnumre
52+
return isPhoneNumber && ['4', '9'].includes(value.charAt(0));
53+
}
54+
55+
return isPhoneNumber;
56+
}
57+
58+
/**
59+
* Validates the input value as a valid {@link https://www.brreg.no/om-oss/registrene-vare/om-enhetsregisteret/organisasjonsnummeret/ Norwegian organization number}.
60+
* Valid format is 9 digits, spaces allowed, eg `000000000` or `000 000 000`.
61+
*/
62+
export function validateOrganizationNumber(value: string): boolean {
63+
/** References:
64+
* https://www.brreg.no/om-oss/registrene-vare/om-enhetsregisteret/organisasjonsnummeret/
65+
* https://no.wikipedia.org/wiki/Organisasjonsnummer
66+
*/
67+
return mod11(value, [3, 2, 7, 6, 5, 4, 3, 2]);
68+
}

packages/validator/src/se.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { stripFormatting } from './utils';
2+
3+
type PostalCodeOptions = {
4+
/**
5+
* Disallow formatting characters
6+
* @default false
7+
*/
8+
strict?: boolean;
9+
};
10+
11+
/**
12+
* Validates the input value as a valid Swedish postal (zip) code.
13+
* Valid format is either `00 000` or `00000`.
14+
*/
15+
export function validatePostalCode(
16+
value: string,
17+
options: PostalCodeOptions = {},
18+
): boolean {
19+
if (!options.strict) {
20+
value = stripFormatting(value);
21+
}
22+
23+
return /^\d{3} ?\d{2}$/.test(value);
24+
}
25+
26+
type PhoneNumberOptions = {
27+
mobileOnly?: boolean;
28+
strict?: boolean;
29+
};
30+
31+
export function validatePhoneNumber(
32+
value: string,
33+
options: PhoneNumberOptions = {},
34+
): boolean {
35+
if (!options.strict) {
36+
value = stripFormatting(value);
37+
}
38+
39+
if (options.mobileOnly) {
40+
const isMobileNumber = /^07\d{8}$/.test(value);
41+
return isMobileNumber;
42+
}
43+
44+
const isPhoneNumber = /^0\d{7,9}$/.test(value);
45+
46+
return isPhoneNumber;
47+
}
48+
49+
export function validateOrganizationNumber(
50+
value: string,
51+
options: PhoneNumberOptions = {},
52+
): boolean {
53+
if (!options.strict) {
54+
value = stripFormatting(value);
55+
}
56+
57+
return /^\d{10}$/.test(value);
58+
}

packages/validator/src/utils.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/** Strip all formatting, leaving only numbers and letters */
2+
export function stripFormatting(value: string): string {
3+
return value.replace(/[^a-zA-Z0-9]/g, '');
4+
}
5+
6+
/**
7+
* Used to validate Norwegian bank account numbers, organization numbers and national identity numbers.
8+
* See https://no.wikipedia.org/wiki/MOD11
9+
*/
10+
export function mod11(value: string, weights: number[]): boolean {
11+
// Since the control digit is a single value, the lengths should be equal
12+
if (weights.length + 1 !== value.length) {
13+
return false;
14+
}
15+
16+
let sum = 0;
17+
weights.forEach((weight, index) => {
18+
sum += weight * Number(value[index]);
19+
});
20+
21+
let controlNumber = 11 - (sum % 11);
22+
23+
if (controlNumber === 11) {
24+
controlNumber = 0;
25+
}
26+
27+
return controlNumber === Number(value[value.length - 1]);
28+
}

0 commit comments

Comments
 (0)