finprim 0.1.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,127 @@
1
+ import { V as ValidationResult, I as IBAN, A as AccountNumber, S as SortCode, a as SupportedCurrency, M as MoneyResult, C as CurrencyCode, B as BIC, b as CardNumber } from './types-KG-eFvWt.mjs';
2
+ export { c as ValidationFailure, d as ValidationSuccess } from './types-KG-eFvWt.mjs';
3
+
4
+ /**
5
+ * Validates an IBAN string.
6
+ * Accepts IBANs with or without spaces.
7
+ * Validates: country code, expected length, characters, and mod97 checksum.
8
+ *
9
+ * @example
10
+ * validateIBAN('GB29NWBK60161331926819')
11
+ * // { valid: true, value: 'GB29NWBK60161331926819', formatted: 'GB29 NWBK 6016 1331 9268 19' }
12
+ *
13
+ * validateIBAN('GB00NWBK60161331926819')
14
+ * // { valid: false, error: 'IBAN checksum is invalid' }
15
+ */
16
+ declare function validateIBAN(input: string): ValidationResult<IBAN>;
17
+
18
+ /**
19
+ * Validates a UK sort code.
20
+ * Accepts formats: 60-16-13, 601613, 60 16 13
21
+ *
22
+ * @example
23
+ * validateUKSortCode('60-16-13')
24
+ * // { valid: true, value: '601613', formatted: '60-16-13' }
25
+ *
26
+ * validateUKSortCode('999')
27
+ * // { valid: false, error: 'Sort code must be 6 digits...' }
28
+ */
29
+ declare function validateUKSortCode(input: string): ValidationResult<SortCode>;
30
+ /**
31
+ * Validates a UK bank account number.
32
+ * Must be exactly 8 digits.
33
+ *
34
+ * @example
35
+ * validateUKAccountNumber('31926819')
36
+ * // { valid: true, value: '31926819', formatted: '3192 6819' }
37
+ *
38
+ * validateUKAccountNumber('1234')
39
+ * // { valid: false, error: 'UK account number must be exactly 8 digits' }
40
+ */
41
+ declare function validateUKAccountNumber(input: string): ValidationResult<AccountNumber>;
42
+
43
+ declare const SUPPORTED_CURRENCIES: SupportedCurrency[];
44
+ /**
45
+ * Validates a currency code against supported ISO 4217 codes.
46
+ *
47
+ * @example
48
+ * validateCurrencyCode('GBP')
49
+ * // { valid: true, value: 'GBP', formatted: 'GBP' }
50
+ *
51
+ * validateCurrencyCode('XYZ')
52
+ * // { valid: false, error: 'Unsupported currency code: XYZ' }
53
+ */
54
+ declare function validateCurrencyCode(input: string): ValidationResult<CurrencyCode>;
55
+ /**
56
+ * Formats a number as a locale-aware currency string.
57
+ * Uses the built-in Intl.NumberFormat API — zero dependencies.
58
+ *
59
+ * @example
60
+ * formatCurrency(1000.5, 'GBP') // '£1,000.50'
61
+ * formatCurrency(1000.5, 'EUR', 'de-DE') // '1.000,50 €'
62
+ * formatCurrency(1000.5, 'USD', 'en-US') // '$1,000.50'
63
+ * formatCurrency(1000, 'JPY') // '¥1,000'
64
+ */
65
+ declare function formatCurrency(amount: number, currency: SupportedCurrency, locale?: string): string;
66
+ /**
67
+ * Parses a formatted currency string back into a structured money object.
68
+ * Detects the currency from the symbol prefix.
69
+ *
70
+ * @example
71
+ * parseMoney('£1,000.50')
72
+ * // { valid: true, amount: 1000.5, currency: 'GBP', formatted: '£1,000.50' }
73
+ *
74
+ * parseMoney('not money')
75
+ * // { valid: false, error: 'Could not detect currency from input' }
76
+ */
77
+ declare function parseMoney(input: string): MoneyResult;
78
+
79
+ /**
80
+ * Validates a BIC (Bank Identifier Code) / SWIFT code.
81
+ * Accepts both 8-character and 11-character BIC codes.
82
+ *
83
+ * Format: AAAABBCCXXX
84
+ * - AAAA = Bank code (4 letters)
85
+ * - BB = Country code (2 letters, ISO 3166-1)
86
+ * - CC = Location code (2 alphanumeric)
87
+ * - XXX = Branch code (3 alphanumeric, optional — 'XXX' means head office)
88
+ *
89
+ * @example
90
+ * validateBIC('NWBKGB2L')
91
+ * // { valid: true, value: 'NWBKGB2L', formatted: 'NWBKGB2L' }
92
+ *
93
+ * validateBIC('DEUTDEDB')
94
+ * // { valid: true, value: 'DEUTDEDB', formatted: 'DEUTDEDB' }
95
+ */
96
+ declare function validateBIC(input: string): ValidationResult<BIC>;
97
+
98
+ type CardNetwork = 'Visa' | 'Mastercard' | 'Amex' | 'Discover' | 'Unknown';
99
+ type CardValidationResult = {
100
+ valid: true;
101
+ value: CardNumber;
102
+ formatted: string;
103
+ network: CardNetwork;
104
+ last4: string;
105
+ } | {
106
+ valid: false;
107
+ error: string;
108
+ };
109
+ /**
110
+ * Validates a card number using the Luhn algorithm.
111
+ * Accepts digits with or without spaces and hyphens.
112
+ *
113
+ * The Luhn algorithm:
114
+ * 1. Double every second digit from the right
115
+ * 2. If doubling produces a number > 9, subtract 9
116
+ * 3. Sum all digits — result must be divisible by 10
117
+ *
118
+ * @example
119
+ * validateCardNumber('4532015112830366')
120
+ * // { valid: true, value: '...', formatted: '4532 0151 1283 0366', network: 'Visa', last4: '0366' }
121
+ *
122
+ * validateCardNumber('1234567890123456')
123
+ * // { valid: false, error: 'Card number failed Luhn check' }
124
+ */
125
+ declare function validateCardNumber(input: string): CardValidationResult;
126
+
127
+ export { AccountNumber, BIC, type CardNetwork, CardNumber, type CardValidationResult, CurrencyCode, IBAN, MoneyResult, SUPPORTED_CURRENCIES, SortCode, SupportedCurrency, ValidationResult, formatCurrency, parseMoney, validateBIC, validateCardNumber, validateCurrencyCode, validateIBAN, validateUKAccountNumber, validateUKSortCode };
@@ -0,0 +1,127 @@
1
+ import { V as ValidationResult, I as IBAN, A as AccountNumber, S as SortCode, a as SupportedCurrency, M as MoneyResult, C as CurrencyCode, B as BIC, b as CardNumber } from './types-KG-eFvWt.js';
2
+ export { c as ValidationFailure, d as ValidationSuccess } from './types-KG-eFvWt.js';
3
+
4
+ /**
5
+ * Validates an IBAN string.
6
+ * Accepts IBANs with or without spaces.
7
+ * Validates: country code, expected length, characters, and mod97 checksum.
8
+ *
9
+ * @example
10
+ * validateIBAN('GB29NWBK60161331926819')
11
+ * // { valid: true, value: 'GB29NWBK60161331926819', formatted: 'GB29 NWBK 6016 1331 9268 19' }
12
+ *
13
+ * validateIBAN('GB00NWBK60161331926819')
14
+ * // { valid: false, error: 'IBAN checksum is invalid' }
15
+ */
16
+ declare function validateIBAN(input: string): ValidationResult<IBAN>;
17
+
18
+ /**
19
+ * Validates a UK sort code.
20
+ * Accepts formats: 60-16-13, 601613, 60 16 13
21
+ *
22
+ * @example
23
+ * validateUKSortCode('60-16-13')
24
+ * // { valid: true, value: '601613', formatted: '60-16-13' }
25
+ *
26
+ * validateUKSortCode('999')
27
+ * // { valid: false, error: 'Sort code must be 6 digits...' }
28
+ */
29
+ declare function validateUKSortCode(input: string): ValidationResult<SortCode>;
30
+ /**
31
+ * Validates a UK bank account number.
32
+ * Must be exactly 8 digits.
33
+ *
34
+ * @example
35
+ * validateUKAccountNumber('31926819')
36
+ * // { valid: true, value: '31926819', formatted: '3192 6819' }
37
+ *
38
+ * validateUKAccountNumber('1234')
39
+ * // { valid: false, error: 'UK account number must be exactly 8 digits' }
40
+ */
41
+ declare function validateUKAccountNumber(input: string): ValidationResult<AccountNumber>;
42
+
43
+ declare const SUPPORTED_CURRENCIES: SupportedCurrency[];
44
+ /**
45
+ * Validates a currency code against supported ISO 4217 codes.
46
+ *
47
+ * @example
48
+ * validateCurrencyCode('GBP')
49
+ * // { valid: true, value: 'GBP', formatted: 'GBP' }
50
+ *
51
+ * validateCurrencyCode('XYZ')
52
+ * // { valid: false, error: 'Unsupported currency code: XYZ' }
53
+ */
54
+ declare function validateCurrencyCode(input: string): ValidationResult<CurrencyCode>;
55
+ /**
56
+ * Formats a number as a locale-aware currency string.
57
+ * Uses the built-in Intl.NumberFormat API — zero dependencies.
58
+ *
59
+ * @example
60
+ * formatCurrency(1000.5, 'GBP') // '£1,000.50'
61
+ * formatCurrency(1000.5, 'EUR', 'de-DE') // '1.000,50 €'
62
+ * formatCurrency(1000.5, 'USD', 'en-US') // '$1,000.50'
63
+ * formatCurrency(1000, 'JPY') // '¥1,000'
64
+ */
65
+ declare function formatCurrency(amount: number, currency: SupportedCurrency, locale?: string): string;
66
+ /**
67
+ * Parses a formatted currency string back into a structured money object.
68
+ * Detects the currency from the symbol prefix.
69
+ *
70
+ * @example
71
+ * parseMoney('£1,000.50')
72
+ * // { valid: true, amount: 1000.5, currency: 'GBP', formatted: '£1,000.50' }
73
+ *
74
+ * parseMoney('not money')
75
+ * // { valid: false, error: 'Could not detect currency from input' }
76
+ */
77
+ declare function parseMoney(input: string): MoneyResult;
78
+
79
+ /**
80
+ * Validates a BIC (Bank Identifier Code) / SWIFT code.
81
+ * Accepts both 8-character and 11-character BIC codes.
82
+ *
83
+ * Format: AAAABBCCXXX
84
+ * - AAAA = Bank code (4 letters)
85
+ * - BB = Country code (2 letters, ISO 3166-1)
86
+ * - CC = Location code (2 alphanumeric)
87
+ * - XXX = Branch code (3 alphanumeric, optional — 'XXX' means head office)
88
+ *
89
+ * @example
90
+ * validateBIC('NWBKGB2L')
91
+ * // { valid: true, value: 'NWBKGB2L', formatted: 'NWBKGB2L' }
92
+ *
93
+ * validateBIC('DEUTDEDB')
94
+ * // { valid: true, value: 'DEUTDEDB', formatted: 'DEUTDEDB' }
95
+ */
96
+ declare function validateBIC(input: string): ValidationResult<BIC>;
97
+
98
+ type CardNetwork = 'Visa' | 'Mastercard' | 'Amex' | 'Discover' | 'Unknown';
99
+ type CardValidationResult = {
100
+ valid: true;
101
+ value: CardNumber;
102
+ formatted: string;
103
+ network: CardNetwork;
104
+ last4: string;
105
+ } | {
106
+ valid: false;
107
+ error: string;
108
+ };
109
+ /**
110
+ * Validates a card number using the Luhn algorithm.
111
+ * Accepts digits with or without spaces and hyphens.
112
+ *
113
+ * The Luhn algorithm:
114
+ * 1. Double every second digit from the right
115
+ * 2. If doubling produces a number > 9, subtract 9
116
+ * 3. Sum all digits — result must be divisible by 10
117
+ *
118
+ * @example
119
+ * validateCardNumber('4532015112830366')
120
+ * // { valid: true, value: '...', formatted: '4532 0151 1283 0366', network: 'Visa', last4: '0366' }
121
+ *
122
+ * validateCardNumber('1234567890123456')
123
+ * // { valid: false, error: 'Card number failed Luhn check' }
124
+ */
125
+ declare function validateCardNumber(input: string): CardValidationResult;
126
+
127
+ export { AccountNumber, BIC, type CardNetwork, CardNumber, type CardValidationResult, CurrencyCode, IBAN, MoneyResult, SUPPORTED_CURRENCIES, SortCode, SupportedCurrency, ValidationResult, formatCurrency, parseMoney, validateBIC, validateCardNumber, validateCurrencyCode, validateIBAN, validateUKAccountNumber, validateUKSortCode };
package/dist/index.js ADDED
@@ -0,0 +1,336 @@
1
+ 'use strict';
2
+
3
+ // src/iban.ts
4
+ var IBAN_LENGTHS = {
5
+ AL: 28,
6
+ AD: 24,
7
+ AT: 20,
8
+ AZ: 28,
9
+ BH: 22,
10
+ BE: 16,
11
+ BA: 20,
12
+ BR: 29,
13
+ BG: 22,
14
+ CR: 22,
15
+ HR: 21,
16
+ CY: 28,
17
+ CZ: 24,
18
+ DK: 18,
19
+ DO: 28,
20
+ EE: 20,
21
+ FI: 18,
22
+ FR: 27,
23
+ GE: 22,
24
+ DE: 22,
25
+ GI: 23,
26
+ GR: 27,
27
+ GT: 28,
28
+ HU: 28,
29
+ IS: 26,
30
+ IE: 22,
31
+ IL: 23,
32
+ IT: 27,
33
+ JO: 30,
34
+ KZ: 20,
35
+ KW: 30,
36
+ LV: 21,
37
+ LB: 28,
38
+ LI: 21,
39
+ LT: 20,
40
+ LU: 20,
41
+ MK: 19,
42
+ MT: 31,
43
+ MR: 27,
44
+ MU: 30,
45
+ MC: 27,
46
+ MD: 24,
47
+ ME: 22,
48
+ NL: 18,
49
+ NO: 15,
50
+ PK: 24,
51
+ PS: 29,
52
+ PL: 28,
53
+ PT: 25,
54
+ QA: 29,
55
+ RO: 24,
56
+ SM: 27,
57
+ SA: 24,
58
+ RS: 22,
59
+ SK: 24,
60
+ SI: 19,
61
+ ES: 24,
62
+ SE: 24,
63
+ CH: 21,
64
+ TN: 24,
65
+ TR: 26,
66
+ AE: 23,
67
+ GB: 22,
68
+ VG: 24
69
+ };
70
+ function mod97(value) {
71
+ let remainder = 0;
72
+ for (const char of value) {
73
+ remainder = (remainder * 10 + parseInt(char, 10)) % 97;
74
+ }
75
+ return remainder;
76
+ }
77
+ function ibanToDigits(iban) {
78
+ const rearranged = iban.slice(4) + iban.slice(0, 4);
79
+ return rearranged.split("").map((char) => {
80
+ const code = char.charCodeAt(0);
81
+ return code >= 65 && code <= 90 ? (code - 55).toString() : char;
82
+ }).join("");
83
+ }
84
+ function formatIBANString(iban) {
85
+ return iban.replace(/(.{4})/g, "$1 ").trim();
86
+ }
87
+ function validateIBAN(input) {
88
+ if (!input || typeof input !== "string") {
89
+ return { valid: false, error: "Input must be a non-empty string" };
90
+ }
91
+ const cleaned = input.replace(/\s/g, "").toUpperCase();
92
+ if (cleaned.length < 4) {
93
+ return { valid: false, error: "IBAN is too short" };
94
+ }
95
+ const countryCode = cleaned.slice(0, 2);
96
+ if (!/^[A-Z]{2}$/.test(countryCode)) {
97
+ return { valid: false, error: "IBAN must start with a 2-letter country code" };
98
+ }
99
+ const expectedLength = IBAN_LENGTHS[countryCode];
100
+ if (!expectedLength) {
101
+ return { valid: false, error: `Unsupported country code: ${countryCode}` };
102
+ }
103
+ if (cleaned.length !== expectedLength) {
104
+ return {
105
+ valid: false,
106
+ error: `Invalid length for ${countryCode} IBAN. Expected ${expectedLength} characters, got ${cleaned.length}`
107
+ };
108
+ }
109
+ if (!/^[A-Z0-9]+$/.test(cleaned)) {
110
+ return { valid: false, error: "IBAN contains invalid characters" };
111
+ }
112
+ const digits = ibanToDigits(cleaned);
113
+ if (mod97(digits) !== 1) {
114
+ return { valid: false, error: "IBAN checksum is invalid" };
115
+ }
116
+ return {
117
+ valid: true,
118
+ value: cleaned,
119
+ formatted: formatIBANString(cleaned)
120
+ };
121
+ }
122
+
123
+ // src/sortcode.ts
124
+ function validateUKSortCode(input) {
125
+ if (!input || typeof input !== "string") {
126
+ return { valid: false, error: "Input must be a non-empty string" };
127
+ }
128
+ const cleaned = input.replace(/[-\s]/g, "");
129
+ if (!/^\d{6}$/.test(cleaned)) {
130
+ return {
131
+ valid: false,
132
+ error: "Sort code must be exactly 6 digits. Accepted formats: 60-16-13, 601613, 60 16 13"
133
+ };
134
+ }
135
+ const formatted = `${cleaned.slice(0, 2)}-${cleaned.slice(2, 4)}-${cleaned.slice(4, 6)}`;
136
+ return {
137
+ valid: true,
138
+ value: cleaned,
139
+ formatted
140
+ };
141
+ }
142
+ function validateUKAccountNumber(input) {
143
+ if (!input || typeof input !== "string") {
144
+ return { valid: false, error: "Input must be a non-empty string" };
145
+ }
146
+ const cleaned = input.replace(/\s/g, "");
147
+ if (!/^\d{8}$/.test(cleaned)) {
148
+ return {
149
+ valid: false,
150
+ error: "UK account number must be exactly 8 digits"
151
+ };
152
+ }
153
+ const formatted = `${cleaned.slice(0, 4)} ${cleaned.slice(4, 8)}`;
154
+ return {
155
+ valid: true,
156
+ value: cleaned,
157
+ formatted
158
+ };
159
+ }
160
+
161
+ // src/currency.ts
162
+ var SUPPORTED_CURRENCIES = [
163
+ "GBP",
164
+ "EUR",
165
+ "USD",
166
+ "JPY",
167
+ "CHF",
168
+ "CAD",
169
+ "AUD",
170
+ "NZD"
171
+ ];
172
+ var CURRENCY_LOCALES = {
173
+ GBP: "en-GB",
174
+ EUR: "de-DE",
175
+ USD: "en-US",
176
+ JPY: "ja-JP",
177
+ CHF: "de-CH",
178
+ CAD: "en-CA",
179
+ AUD: "en-AU",
180
+ NZD: "en-NZ"
181
+ };
182
+ var SYMBOL_MAP = {
183
+ "\xA3": "GBP",
184
+ "\u20AC": "EUR",
185
+ "$": "USD",
186
+ "\xA5": "JPY",
187
+ "CHF": "CHF"
188
+ };
189
+ function validateCurrencyCode(input) {
190
+ if (!input || typeof input !== "string") {
191
+ return { valid: false, error: "Input must be a non-empty string" };
192
+ }
193
+ const upper = input.toUpperCase();
194
+ if (!SUPPORTED_CURRENCIES.includes(upper)) {
195
+ return {
196
+ valid: false,
197
+ error: `Unsupported currency code: ${input}. Supported: ${SUPPORTED_CURRENCIES.join(", ")}`
198
+ };
199
+ }
200
+ return {
201
+ valid: true,
202
+ value: upper,
203
+ formatted: upper
204
+ };
205
+ }
206
+ function formatCurrency(amount, currency, locale) {
207
+ const resolvedLocale = locale ?? CURRENCY_LOCALES[currency] ?? "en-GB";
208
+ return new Intl.NumberFormat(resolvedLocale, {
209
+ style: "currency",
210
+ currency,
211
+ minimumFractionDigits: currency === "JPY" ? 0 : 2,
212
+ maximumFractionDigits: currency === "JPY" ? 0 : 2
213
+ }).format(amount);
214
+ }
215
+ function parseMoney(input) {
216
+ if (!input || typeof input !== "string") {
217
+ return { valid: false, error: "Input must be a non-empty string" };
218
+ }
219
+ let currency;
220
+ let cleaned = input.trim();
221
+ for (const [symbol, code] of Object.entries(SYMBOL_MAP)) {
222
+ if (cleaned.startsWith(symbol) || cleaned.endsWith(symbol)) {
223
+ currency = code;
224
+ cleaned = cleaned.replace(symbol, "").trim();
225
+ break;
226
+ }
227
+ }
228
+ if (!currency) {
229
+ return { valid: false, error: "Could not detect currency from input. Expected a symbol like \xA3, \u20AC, $, \xA5" };
230
+ }
231
+ const normalised = cleaned.replace(/,/g, "");
232
+ const amount = parseFloat(normalised);
233
+ if (isNaN(amount)) {
234
+ return { valid: false, error: `Could not parse amount from: "${cleaned}"` };
235
+ }
236
+ return {
237
+ valid: true,
238
+ amount,
239
+ currency,
240
+ formatted: formatCurrency(amount, currency)
241
+ };
242
+ }
243
+
244
+ // src/bic.ts
245
+ var BIC_REGEX = /^[A-Z]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?$/;
246
+ function validateBIC(input) {
247
+ if (!input || typeof input !== "string") {
248
+ return { valid: false, error: "Input must be a non-empty string" };
249
+ }
250
+ const cleaned = input.replace(/\s/g, "").toUpperCase();
251
+ if (cleaned.length !== 8 && cleaned.length !== 11) {
252
+ return {
253
+ valid: false,
254
+ error: `BIC must be 8 or 11 characters. Got ${cleaned.length}`
255
+ };
256
+ }
257
+ if (!BIC_REGEX.test(cleaned)) {
258
+ return {
259
+ valid: false,
260
+ error: "Invalid BIC format. Expected: 4 letters + 2 letters + 2 alphanumeric + optional 3 alphanumeric"
261
+ };
262
+ }
263
+ const bankCode = cleaned.slice(0, 4);
264
+ const countryCode = cleaned.slice(4, 6);
265
+ const location = cleaned.slice(6, 8);
266
+ const branch = cleaned.length === 11 ? cleaned.slice(8, 11) : "XXX";
267
+ return {
268
+ valid: true,
269
+ value: cleaned,
270
+ formatted: `${bankCode} ${countryCode} ${location} ${branch}`
271
+ };
272
+ }
273
+
274
+ // src/card.ts
275
+ function detectNetwork(digits) {
276
+ if (/^4/.test(digits)) return "Visa";
277
+ if (/^5[1-5]/.test(digits) || /^2[2-7]/.test(digits)) return "Mastercard";
278
+ if (/^3[47]/.test(digits)) return "Amex";
279
+ if (/^6(?:011|5)/.test(digits)) return "Discover";
280
+ return "Unknown";
281
+ }
282
+ function formatCardNumber(digits, network) {
283
+ if (network === "Amex") {
284
+ return `${digits.slice(0, 4)} ${digits.slice(4, 10)} ${digits.slice(10, 15)}`;
285
+ }
286
+ return digits.replace(/(.{4})/g, "$1 ").trim();
287
+ }
288
+ function validateCardNumber(input) {
289
+ if (!input || typeof input !== "string") {
290
+ return { valid: false, error: "Input must be a non-empty string" };
291
+ }
292
+ const digits = input.replace(/[\s-]/g, "");
293
+ if (!/^\d+$/.test(digits)) {
294
+ return { valid: false, error: "Card number must contain only digits" };
295
+ }
296
+ if (digits.length < 13 || digits.length > 19) {
297
+ return {
298
+ valid: false,
299
+ error: `Card number length invalid. Expected 13-19 digits, got ${digits.length}`
300
+ };
301
+ }
302
+ let sum = 0;
303
+ let shouldDouble = false;
304
+ for (let i = digits.length - 1; i >= 0; i--) {
305
+ let digit = parseInt(digits[i], 10);
306
+ if (shouldDouble) {
307
+ digit *= 2;
308
+ if (digit > 9) digit -= 9;
309
+ }
310
+ sum += digit;
311
+ shouldDouble = !shouldDouble;
312
+ }
313
+ if (sum % 10 !== 0) {
314
+ return { valid: false, error: "Card number failed Luhn check \u2014 this is not a valid card number" };
315
+ }
316
+ const network = detectNetwork(digits);
317
+ return {
318
+ valid: true,
319
+ value: digits,
320
+ formatted: formatCardNumber(digits, network),
321
+ network,
322
+ last4: digits.slice(-4)
323
+ };
324
+ }
325
+
326
+ exports.SUPPORTED_CURRENCIES = SUPPORTED_CURRENCIES;
327
+ exports.formatCurrency = formatCurrency;
328
+ exports.parseMoney = parseMoney;
329
+ exports.validateBIC = validateBIC;
330
+ exports.validateCardNumber = validateCardNumber;
331
+ exports.validateCurrencyCode = validateCurrencyCode;
332
+ exports.validateIBAN = validateIBAN;
333
+ exports.validateUKAccountNumber = validateUKAccountNumber;
334
+ exports.validateUKSortCode = validateUKSortCode;
335
+ //# sourceMappingURL=index.js.map
336
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/iban.ts","../src/sortcode.ts","../src/currency.ts","../src/bic.ts","../src/card.ts"],"names":[],"mappings":";;;AAGA,IAAM,YAAA,GAAuC;AAAA,EAC3C,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAC5D,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAC5D,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAC5D,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAC5D,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAC5D,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,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","file":"index.js","sourcesContent":["import type { IBAN, ValidationResult } from './types'\n\n// Expected IBAN lengths per country (ISO 13616 registry)\nconst IBAN_LENGTHS: Record<string, number> = {\n AL: 28, AD: 24, AT: 20, AZ: 28, BH: 22, BE: 16, BA: 20, BR: 29,\n BG: 22, CR: 22, HR: 21, CY: 28, CZ: 24, DK: 18, DO: 28, EE: 20,\n FI: 18, FR: 27, GE: 22, DE: 22, GI: 23, GR: 27, GT: 28, HU: 28,\n IS: 26, IE: 22, IL: 23, IT: 27, JO: 30, KZ: 20, KW: 30, LV: 21,\n LB: 28, LI: 21, LT: 20, LU: 20, MK: 19, MT: 31, MR: 27, MU: 30,\n MC: 27, MD: 24, ME: 22, NL: 18, NO: 15, PK: 24, PS: 29, PL: 28,\n PT: 25, QA: 29, RO: 24, SM: 27, SA: 24, RS: 22, SK: 24, SI: 19,\n ES: 24, SE: 24, CH: 21, TN: 24, TR: 26, AE: 23, GB: 22, VG: 24,\n}\n\n// Process digit by digit to avoid JS integer overflow on large IBAN numbers\nfunction mod97(value: string): number {\n let remainder = 0\n for (const char of value) {\n remainder = (remainder * 10 + parseInt(char, 10)) % 97\n }\n return remainder\n}\n\n// Rearrange IBAN and convert letters to numbers per ISO 13616\nfunction ibanToDigits(iban: string): string {\n const rearranged = iban.slice(4) + iban.slice(0, 4)\n return rearranged\n .split('')\n .map((char) => {\n const code = char.charCodeAt(0)\n // A=10, B=11, ... Z=35\n return code >= 65 && code <= 90 ? (code - 55).toString() : char\n })\n .join('')\n}\n\nfunction formatIBANString(iban: string): string {\n return iban.replace(/(.{4})/g, '$1 ').trim()\n}\n\n/**\n * Validates an IBAN string.\n * Accepts IBANs with or without spaces.\n * Validates: country code, expected length, characters, and mod97 checksum.\n *\n * @example\n * validateIBAN('GB29NWBK60161331926819')\n * // { valid: true, value: 'GB29NWBK60161331926819', formatted: 'GB29 NWBK 6016 1331 9268 19' }\n *\n * validateIBAN('GB00NWBK60161331926819')\n * // { valid: false, error: 'IBAN checksum is invalid' }\n */\nexport function validateIBAN(input: string): ValidationResult<IBAN> {\n if (!input || typeof input !== 'string') {\n return { valid: false, error: 'Input must be a non-empty string' }\n }\n\n const cleaned = input.replace(/\\s/g, '').toUpperCase()\n\n if (cleaned.length < 4) {\n return { valid: false, error: 'IBAN is too short' }\n }\n\n const countryCode = cleaned.slice(0, 2)\n\n if (!/^[A-Z]{2}$/.test(countryCode)) {\n return { valid: false, error: 'IBAN must start with a 2-letter country code' }\n }\n\n const expectedLength = IBAN_LENGTHS[countryCode]\n\n if (!expectedLength) {\n return { valid: false, error: `Unsupported country code: ${countryCode}` }\n }\n\n if (cleaned.length !== expectedLength) {\n return {\n valid: false,\n error: `Invalid length for ${countryCode} IBAN. Expected ${expectedLength} characters, got ${cleaned.length}`,\n }\n }\n\n if (!/^[A-Z0-9]+$/.test(cleaned)) {\n return { valid: false, error: 'IBAN contains invalid characters' }\n }\n\n const digits = ibanToDigits(cleaned)\n\n if (mod97(digits) !== 1) {\n return { valid: false, error: 'IBAN checksum is invalid' }\n }\n\n return {\n valid: true,\n value: cleaned as IBAN,\n formatted: formatIBANString(cleaned),\n }\n}\n","import type { SortCode, AccountNumber, ValidationResult } from './types'\n\n/**\n * Validates a UK sort code.\n * Accepts formats: 60-16-13, 601613, 60 16 13\n *\n * @example\n * validateUKSortCode('60-16-13')\n * // { valid: true, value: '601613', formatted: '60-16-13' }\n *\n * validateUKSortCode('999')\n * // { valid: false, error: 'Sort code must be 6 digits...' }\n */\nexport function validateUKSortCode(input: string): ValidationResult<SortCode> {\n if (!input || typeof input !== 'string') {\n return { valid: false, error: 'Input must be a non-empty string' }\n }\n\n const cleaned = input.replace(/[-\\s]/g, '')\n\n if (!/^\\d{6}$/.test(cleaned)) {\n return {\n valid: false,\n error: 'Sort code must be exactly 6 digits. Accepted formats: 60-16-13, 601613, 60 16 13',\n }\n }\n\n const formatted = `${cleaned.slice(0, 2)}-${cleaned.slice(2, 4)}-${cleaned.slice(4, 6)}`\n\n return {\n valid: true,\n value: cleaned as SortCode,\n formatted,\n }\n}\n\n/**\n * Validates a UK bank account number.\n * Must be exactly 8 digits.\n *\n * @example\n * validateUKAccountNumber('31926819')\n * // { valid: true, value: '31926819', formatted: '3192 6819' }\n *\n * validateUKAccountNumber('1234')\n * // { valid: false, error: 'UK account number must be exactly 8 digits' }\n */\nexport function validateUKAccountNumber(input: string): ValidationResult<AccountNumber> {\n if (!input || typeof input !== 'string') {\n return { valid: false, error: 'Input must be a non-empty string' }\n }\n\n const cleaned = input.replace(/\\s/g, '')\n\n if (!/^\\d{8}$/.test(cleaned)) {\n return {\n valid: false,\n error: 'UK account number must be exactly 8 digits',\n }\n }\n\n const formatted = `${cleaned.slice(0, 4)} ${cleaned.slice(4, 8)}`\n\n return {\n valid: true,\n value: cleaned as AccountNumber,\n formatted,\n }\n}\n","import type { CurrencyCode, SupportedCurrency, MoneyResult, ValidationResult } from './types'\n\nexport const SUPPORTED_CURRENCIES: SupportedCurrency[] = [\n 'GBP', 'EUR', 'USD', 'JPY', 'CHF', 'CAD', 'AUD', 'NZD',\n]\n\nconst CURRENCY_LOCALES: Record<SupportedCurrency, string> = {\n GBP: 'en-GB',\n EUR: 'de-DE',\n USD: 'en-US',\n JPY: 'ja-JP',\n CHF: 'de-CH',\n CAD: 'en-CA',\n AUD: 'en-AU',\n NZD: 'en-NZ',\n}\n\nconst SYMBOL_MAP: Record<string, SupportedCurrency> = {\n '£': 'GBP',\n '€': 'EUR',\n '$': 'USD',\n '¥': 'JPY',\n 'CHF': 'CHF',\n}\n\n/**\n * Validates a currency code against supported ISO 4217 codes.\n *\n * @example\n * validateCurrencyCode('GBP')\n * // { valid: true, value: 'GBP', formatted: 'GBP' }\n *\n * validateCurrencyCode('XYZ')\n * // { valid: false, error: 'Unsupported currency code: XYZ' }\n */\nexport function validateCurrencyCode(input: string): ValidationResult<CurrencyCode> {\n if (!input || typeof input !== 'string') {\n return { valid: false, error: 'Input must be a non-empty string' }\n }\n\n const upper = input.toUpperCase() as SupportedCurrency\n\n if (!SUPPORTED_CURRENCIES.includes(upper)) {\n return {\n valid: false,\n error: `Unsupported currency code: ${input}. Supported: ${SUPPORTED_CURRENCIES.join(', ')}`,\n }\n }\n\n return {\n valid: true,\n value: upper as CurrencyCode,\n formatted: upper,\n }\n}\n\n/**\n * Formats a number as a locale-aware currency string.\n * Uses the built-in Intl.NumberFormat API — zero dependencies.\n *\n * @example\n * formatCurrency(1000.5, 'GBP') // '£1,000.50'\n * formatCurrency(1000.5, 'EUR', 'de-DE') // '1.000,50 €'\n * formatCurrency(1000.5, 'USD', 'en-US') // '$1,000.50'\n * formatCurrency(1000, 'JPY') // '¥1,000'\n */\nexport function formatCurrency(\n amount: number,\n currency: SupportedCurrency,\n locale?: string\n): string {\n const resolvedLocale = locale ?? CURRENCY_LOCALES[currency] ?? 'en-GB'\n\n return new Intl.NumberFormat(resolvedLocale, {\n style: 'currency',\n currency,\n minimumFractionDigits: currency === 'JPY' ? 0 : 2,\n maximumFractionDigits: currency === 'JPY' ? 0 : 2,\n }).format(amount)\n}\n\n/**\n * Parses a formatted currency string back into a structured money object.\n * Detects the currency from the symbol prefix.\n *\n * @example\n * parseMoney('£1,000.50')\n * // { valid: true, amount: 1000.5, currency: 'GBP', formatted: '£1,000.50' }\n *\n * parseMoney('not money')\n * // { valid: false, error: 'Could not detect currency from input' }\n */\nexport function parseMoney(input: string): MoneyResult {\n if (!input || typeof input !== 'string') {\n return { valid: false, error: 'Input must be a non-empty string' }\n }\n\n let currency: SupportedCurrency | undefined\n let cleaned = input.trim()\n\n for (const [symbol, code] of Object.entries(SYMBOL_MAP)) {\n if (cleaned.startsWith(symbol) || cleaned.endsWith(symbol)) {\n currency = code\n cleaned = cleaned.replace(symbol, '').trim()\n break\n }\n }\n\n if (!currency) {\n return { valid: false, error: 'Could not detect currency from input. Expected a symbol like £, €, $, ¥' }\n }\n\n // Remove thousands separators, normalise decimal separator\n const normalised = cleaned.replace(/,/g, '')\n const amount = parseFloat(normalised)\n\n if (isNaN(amount)) {\n return { valid: false, error: `Could not parse amount from: \"${cleaned}\"` }\n }\n\n return {\n valid: true,\n amount,\n currency,\n formatted: formatCurrency(amount, currency),\n }\n}\n","import type { BIC, ValidationResult } from './types'\n\n// BIC format: 4 letters (bank) + 2 letters (country) + 2 alphanumeric (location) + optional 3 alphanumeric (branch)\nconst BIC_REGEX = /^[A-Z]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?$/\n\n/**\n * Validates a BIC (Bank Identifier Code) / SWIFT code.\n * Accepts both 8-character and 11-character BIC codes.\n *\n * Format: AAAABBCCXXX\n * - AAAA = Bank code (4 letters)\n * - BB = Country code (2 letters, ISO 3166-1)\n * - CC = Location code (2 alphanumeric)\n * - XXX = Branch code (3 alphanumeric, optional — 'XXX' means head office)\n *\n * @example\n * validateBIC('NWBKGB2L')\n * // { valid: true, value: 'NWBKGB2L', formatted: 'NWBKGB2L' }\n *\n * validateBIC('DEUTDEDB')\n * // { valid: true, value: 'DEUTDEDB', formatted: 'DEUTDEDB' }\n */\nexport function validateBIC(input: string): ValidationResult<BIC> {\n if (!input || typeof input !== 'string') {\n return { valid: false, error: 'Input must be a non-empty string' }\n }\n\n const cleaned = input.replace(/\\s/g, '').toUpperCase()\n\n if (cleaned.length !== 8 && cleaned.length !== 11) {\n return {\n valid: false,\n error: `BIC must be 8 or 11 characters. Got ${cleaned.length}`,\n }\n }\n\n if (!BIC_REGEX.test(cleaned)) {\n return {\n valid: false,\n error: 'Invalid BIC format. Expected: 4 letters + 2 letters + 2 alphanumeric + optional 3 alphanumeric',\n }\n }\n\n const bankCode = cleaned.slice(0, 4)\n const countryCode = cleaned.slice(4, 6)\n const location = cleaned.slice(6, 8)\n const branch = cleaned.length === 11 ? cleaned.slice(8, 11) : 'XXX'\n\n return {\n valid: true,\n value: cleaned as BIC,\n formatted: `${bankCode} ${countryCode} ${location} ${branch}`,\n }\n}\n","import type { CardNumber, ValidationResult } from './types'\n\nexport type CardNetwork = 'Visa' | 'Mastercard' | 'Amex' | 'Discover' | 'Unknown'\n\nexport type CardValidationResult =\n | { valid: true; value: CardNumber; formatted: string; network: CardNetwork; last4: string }\n | { valid: false; error: string }\n\n/**\n * Detects the card network from the card number prefix.\n */\nfunction detectNetwork(digits: string): CardNetwork {\n if (/^4/.test(digits)) return 'Visa'\n if (/^5[1-5]/.test(digits) || /^2[2-7]/.test(digits)) return 'Mastercard'\n if (/^3[47]/.test(digits)) return 'Amex'\n if (/^6(?:011|5)/.test(digits)) return 'Discover'\n return 'Unknown'\n}\n\n/**\n * Formats a card number into groups based on the network.\n * Amex: 4-6-5, all others: 4-4-4-4\n */\nfunction formatCardNumber(digits: string, network: CardNetwork): string {\n if (network === 'Amex') {\n return `${digits.slice(0, 4)} ${digits.slice(4, 10)} ${digits.slice(10, 15)}`\n }\n return digits.replace(/(.{4})/g, '$1 ').trim()\n}\n\n/**\n * Validates a card number using the Luhn algorithm.\n * Accepts digits with or without spaces and hyphens.\n *\n * The Luhn algorithm:\n * 1. Double every second digit from the right\n * 2. If doubling produces a number > 9, subtract 9\n * 3. Sum all digits — result must be divisible by 10\n *\n * @example\n * validateCardNumber('4532015112830366')\n * // { valid: true, value: '...', formatted: '4532 0151 1283 0366', network: 'Visa', last4: '0366' }\n *\n * validateCardNumber('1234567890123456')\n * // { valid: false, error: 'Card number failed Luhn check' }\n */\nexport function validateCardNumber(input: string): CardValidationResult {\n if (!input || typeof input !== 'string') {\n return { valid: false, error: 'Input must be a non-empty string' }\n }\n\n const digits = input.replace(/[\\s-]/g, '')\n\n if (!/^\\d+$/.test(digits)) {\n return { valid: false, error: 'Card number must contain only digits' }\n }\n\n if (digits.length < 13 || digits.length > 19) {\n return {\n valid: false,\n error: `Card number length invalid. Expected 13-19 digits, got ${digits.length}`,\n }\n }\n\n // Luhn algorithm\n let sum = 0\n let shouldDouble = false\n\n for (let i = digits.length - 1; i >= 0; i--) {\n let digit = parseInt(digits[i]!, 10)\n\n if (shouldDouble) {\n digit *= 2\n if (digit > 9) digit -= 9\n }\n\n sum += digit\n shouldDouble = !shouldDouble\n }\n\n if (sum % 10 !== 0) {\n return { valid: false, error: 'Card number failed Luhn check — this is not a valid card number' }\n }\n\n const network = detectNetwork(digits)\n\n return {\n valid: true,\n value: digits as CardNumber,\n formatted: formatCardNumber(digits, network),\n network,\n last4: digits.slice(-4),\n }\n}\n"]}