@slashlab/numerik-js 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/LICENSE +21 -0
- package/README.md +100 -0
- package/dist/VatEu-BNRumLqo.d.cts +142 -0
- package/dist/VatEu-BNRumLqo.d.ts +142 -0
- package/dist/chunk-3DAGKUXS.js +1210 -0
- package/dist/chunk-3DAGKUXS.js.map +1 -0
- package/dist/index.cjs +1263 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +189 -0
- package/dist/index.d.ts +189 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/zod/index.cjs +1247 -0
- package/dist/zod/index.cjs.map +1 -0
- package/dist/zod/index.d.cts +23 -0
- package/dist/zod/index.d.ts +23 -0
- package/dist/zod/index.js +56 -0
- package/dist/zod/index.js.map +1 -0
- package/package.json +104 -0
|
@@ -0,0 +1,1247 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/zod/index.ts
|
|
21
|
+
var zod_exports = {};
|
|
22
|
+
__export(zod_exports, {
|
|
23
|
+
ibanParseSchema: () => ibanParseSchema,
|
|
24
|
+
ibanSchema: () => ibanSchema,
|
|
25
|
+
idCardParseSchema: () => idCardParseSchema,
|
|
26
|
+
idCardSchema: () => idCardSchema,
|
|
27
|
+
krsParseSchema: () => krsParseSchema,
|
|
28
|
+
krsSchema: () => krsSchema,
|
|
29
|
+
nipParseSchema: () => nipParseSchema,
|
|
30
|
+
nipSchema: () => nipSchema,
|
|
31
|
+
nrbParseSchema: () => nrbParseSchema,
|
|
32
|
+
nrbSchema: () => nrbSchema,
|
|
33
|
+
passportParseSchema: () => passportParseSchema,
|
|
34
|
+
passportSchema: () => passportSchema,
|
|
35
|
+
peselParseSchema: () => peselParseSchema,
|
|
36
|
+
peselSchema: () => peselSchema,
|
|
37
|
+
regonParseSchema: () => regonParseSchema,
|
|
38
|
+
regonSchema: () => regonSchema,
|
|
39
|
+
vatEuParseSchema: () => vatEuParseSchema,
|
|
40
|
+
vatEuSchema: () => vatEuSchema
|
|
41
|
+
});
|
|
42
|
+
module.exports = __toCommonJS(zod_exports);
|
|
43
|
+
var import_zod = require("zod");
|
|
44
|
+
|
|
45
|
+
// src/exceptions/ValidationException.ts
|
|
46
|
+
var ValidationException = class extends Error {
|
|
47
|
+
constructor(result) {
|
|
48
|
+
super(result.getFirstFailure()?.message ?? "Validation failed");
|
|
49
|
+
this.result = result;
|
|
50
|
+
this.name = "ValidationException";
|
|
51
|
+
}
|
|
52
|
+
result;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// src/exceptions/InvalidChecksumException.ts
|
|
56
|
+
var InvalidChecksumException = class extends ValidationException {
|
|
57
|
+
constructor(result) {
|
|
58
|
+
super(result);
|
|
59
|
+
this.name = "InvalidChecksumException";
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// src/exceptions/InvalidDateException.ts
|
|
64
|
+
var InvalidDateException = class extends ValidationException {
|
|
65
|
+
constructor(result) {
|
|
66
|
+
super(result);
|
|
67
|
+
this.name = "InvalidDateException";
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// src/exceptions/InvalidFormatException.ts
|
|
72
|
+
var InvalidFormatException = class extends ValidationException {
|
|
73
|
+
constructor(result) {
|
|
74
|
+
super(result);
|
|
75
|
+
this.name = "InvalidFormatException";
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// src/result/ValidationFailure.ts
|
|
80
|
+
var ValidationFailure = class {
|
|
81
|
+
constructor(reason, message) {
|
|
82
|
+
this.reason = reason;
|
|
83
|
+
this.message = message;
|
|
84
|
+
}
|
|
85
|
+
reason;
|
|
86
|
+
message;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// src/result/ValidationResult.ts
|
|
90
|
+
var ValidationResult = class _ValidationResult {
|
|
91
|
+
isValid;
|
|
92
|
+
failures;
|
|
93
|
+
constructor(isValid, failures = []) {
|
|
94
|
+
this.isValid = isValid;
|
|
95
|
+
this.failures = [...failures];
|
|
96
|
+
}
|
|
97
|
+
static pass() {
|
|
98
|
+
return new _ValidationResult(true);
|
|
99
|
+
}
|
|
100
|
+
static fail(failures) {
|
|
101
|
+
return new _ValidationResult(false, failures);
|
|
102
|
+
}
|
|
103
|
+
static failWithReason(reason, message) {
|
|
104
|
+
return new _ValidationResult(false, [new ValidationFailure(reason, message)]);
|
|
105
|
+
}
|
|
106
|
+
isFailed() {
|
|
107
|
+
return !this.isValid;
|
|
108
|
+
}
|
|
109
|
+
getFailures() {
|
|
110
|
+
return this.failures;
|
|
111
|
+
}
|
|
112
|
+
getFirstFailure() {
|
|
113
|
+
return this.failures[0] ?? null;
|
|
114
|
+
}
|
|
115
|
+
hasFailureReason(reason) {
|
|
116
|
+
return this.failures.some((f) => f.reason === reason);
|
|
117
|
+
}
|
|
118
|
+
toException() {
|
|
119
|
+
switch (this.getFirstFailure()?.reason) {
|
|
120
|
+
case "invalid_checksum" /* InvalidChecksum */:
|
|
121
|
+
return new InvalidChecksumException(this);
|
|
122
|
+
case "invalid_date" /* InvalidDate */:
|
|
123
|
+
case "future_date" /* FutureDate */:
|
|
124
|
+
case "invalid_month" /* InvalidMonth */:
|
|
125
|
+
return new InvalidDateException(this);
|
|
126
|
+
default:
|
|
127
|
+
return new InvalidFormatException(this);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// src/value-objects/Iban.ts
|
|
133
|
+
var Iban = class {
|
|
134
|
+
constructor(raw, normalized) {
|
|
135
|
+
this.raw = raw;
|
|
136
|
+
this.normalized = normalized;
|
|
137
|
+
}
|
|
138
|
+
raw;
|
|
139
|
+
normalized;
|
|
140
|
+
getRaw() {
|
|
141
|
+
return this.raw;
|
|
142
|
+
}
|
|
143
|
+
getNormalized() {
|
|
144
|
+
return this.normalized;
|
|
145
|
+
}
|
|
146
|
+
toString() {
|
|
147
|
+
return this.normalized;
|
|
148
|
+
}
|
|
149
|
+
getFormatted() {
|
|
150
|
+
return this.normalized.match(/.{1,4}/g)?.join(" ") ?? this.normalized;
|
|
151
|
+
}
|
|
152
|
+
getCountryCode() {
|
|
153
|
+
return "PL";
|
|
154
|
+
}
|
|
155
|
+
getNrb() {
|
|
156
|
+
return this.normalized.slice(2);
|
|
157
|
+
}
|
|
158
|
+
getCheckDigits() {
|
|
159
|
+
return this.normalized.slice(2, 4);
|
|
160
|
+
}
|
|
161
|
+
getSortCode() {
|
|
162
|
+
return this.normalized.slice(4, 12);
|
|
163
|
+
}
|
|
164
|
+
getBankCode() {
|
|
165
|
+
return this.normalized.slice(4, 7);
|
|
166
|
+
}
|
|
167
|
+
getAccountNumber() {
|
|
168
|
+
return this.normalized.slice(12, 28);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// src/value-objects/Nrb.ts
|
|
173
|
+
var Nrb = class {
|
|
174
|
+
constructor(raw, normalized) {
|
|
175
|
+
this.raw = raw;
|
|
176
|
+
this.normalized = normalized;
|
|
177
|
+
}
|
|
178
|
+
raw;
|
|
179
|
+
normalized;
|
|
180
|
+
getRaw() {
|
|
181
|
+
return this.raw;
|
|
182
|
+
}
|
|
183
|
+
getNormalized() {
|
|
184
|
+
return this.normalized;
|
|
185
|
+
}
|
|
186
|
+
toString() {
|
|
187
|
+
return this.normalized;
|
|
188
|
+
}
|
|
189
|
+
getFormatted() {
|
|
190
|
+
const rest = this.normalized.slice(2);
|
|
191
|
+
const grouped = rest.match(/.{1,4}/g)?.join(" ") ?? rest;
|
|
192
|
+
return `${this.normalized.slice(0, 2)} ${grouped}`;
|
|
193
|
+
}
|
|
194
|
+
getIban() {
|
|
195
|
+
return `PL${this.normalized}`;
|
|
196
|
+
}
|
|
197
|
+
getFormattedIban() {
|
|
198
|
+
const full = `PL${this.normalized}`;
|
|
199
|
+
return full.match(/.{1,4}/g)?.join(" ") ?? full;
|
|
200
|
+
}
|
|
201
|
+
getCheckDigits() {
|
|
202
|
+
return this.normalized.slice(0, 2);
|
|
203
|
+
}
|
|
204
|
+
getSortCode() {
|
|
205
|
+
return this.normalized.slice(2, 10);
|
|
206
|
+
}
|
|
207
|
+
getBankCode() {
|
|
208
|
+
return this.normalized.slice(2, 5);
|
|
209
|
+
}
|
|
210
|
+
getAccountNumber() {
|
|
211
|
+
return this.normalized.slice(10, 26);
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// src/identifiers/NrbIdentifier.ts
|
|
216
|
+
var DIGITS = 26;
|
|
217
|
+
var MAX_LENGTH = 40;
|
|
218
|
+
var NrbIdentifier = class {
|
|
219
|
+
constructor(strict = true) {
|
|
220
|
+
this.strict = strict;
|
|
221
|
+
}
|
|
222
|
+
strict;
|
|
223
|
+
isStrict() {
|
|
224
|
+
return this.strict;
|
|
225
|
+
}
|
|
226
|
+
validate(input) {
|
|
227
|
+
if (input.length > MAX_LENGTH) {
|
|
228
|
+
return ValidationResult.failWithReason(
|
|
229
|
+
"invalid_length" /* InvalidLength */,
|
|
230
|
+
"Input exceeds maximum length of 40 characters."
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
const normalized = this.normalize(input);
|
|
234
|
+
if (normalized.length !== DIGITS) {
|
|
235
|
+
return ValidationResult.failWithReason(
|
|
236
|
+
"invalid_length" /* InvalidLength */,
|
|
237
|
+
"NRB must be exactly 26 digits."
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
if (!/^\d+$/.test(normalized)) {
|
|
241
|
+
return ValidationResult.failWithReason(
|
|
242
|
+
"invalid_characters" /* InvalidCharacters */,
|
|
243
|
+
"NRB must contain only digits."
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
if (!this.isValidChecksum(normalized)) {
|
|
247
|
+
return ValidationResult.failWithReason(
|
|
248
|
+
"invalid_checksum" /* InvalidChecksum */,
|
|
249
|
+
"NRB checksum (MOD-97) does not match."
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
return ValidationResult.pass();
|
|
253
|
+
}
|
|
254
|
+
isValid(input) {
|
|
255
|
+
return this.validate(input).isValid;
|
|
256
|
+
}
|
|
257
|
+
parse(input) {
|
|
258
|
+
const result = this.validate(input);
|
|
259
|
+
if (result.isFailed()) {
|
|
260
|
+
throw result.toException();
|
|
261
|
+
}
|
|
262
|
+
return new Nrb(input, this.normalize(input));
|
|
263
|
+
}
|
|
264
|
+
tryParse(input) {
|
|
265
|
+
try {
|
|
266
|
+
return this.parse(input);
|
|
267
|
+
} catch (err) {
|
|
268
|
+
if (err instanceof ValidationException) return null;
|
|
269
|
+
throw err;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
normalize(input) {
|
|
273
|
+
const stripped = input.replace(/[ -]/g, "");
|
|
274
|
+
return stripped.toUpperCase().startsWith("PL") ? stripped.slice(2) : stripped;
|
|
275
|
+
}
|
|
276
|
+
isValidChecksum(normalized) {
|
|
277
|
+
const rearranged = `${normalized.slice(2)}2521${normalized.slice(0, 2)}`;
|
|
278
|
+
let remainder = 0;
|
|
279
|
+
for (const ch of rearranged) {
|
|
280
|
+
remainder = (remainder * 10 + Number(ch)) % 97;
|
|
281
|
+
}
|
|
282
|
+
return remainder === 1;
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
// src/identifiers/IbanIdentifier.ts
|
|
287
|
+
var MAX_LENGTH2 = 40;
|
|
288
|
+
var NRB_DIGITS = 26;
|
|
289
|
+
var IbanIdentifier = class {
|
|
290
|
+
constructor(strict = true) {
|
|
291
|
+
this.strict = strict;
|
|
292
|
+
this.nrb = new NrbIdentifier(strict);
|
|
293
|
+
}
|
|
294
|
+
strict;
|
|
295
|
+
nrb;
|
|
296
|
+
isStrict() {
|
|
297
|
+
return this.strict;
|
|
298
|
+
}
|
|
299
|
+
validate(input) {
|
|
300
|
+
if (input.length > MAX_LENGTH2) {
|
|
301
|
+
return ValidationResult.failWithReason(
|
|
302
|
+
"invalid_length" /* InvalidLength */,
|
|
303
|
+
"Input exceeds maximum length of 40 characters."
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
const stripped = this.stripSeparators(input);
|
|
307
|
+
if (stripped.length < 2 || stripped.slice(0, 2).toUpperCase() !== "PL") {
|
|
308
|
+
return ValidationResult.failWithReason(
|
|
309
|
+
"invalid_format" /* InvalidFormat */,
|
|
310
|
+
"IBAN must start with the PL country prefix."
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
const nrbPart = stripped.slice(2);
|
|
314
|
+
if (nrbPart.length !== NRB_DIGITS) {
|
|
315
|
+
return ValidationResult.failWithReason(
|
|
316
|
+
"invalid_length" /* InvalidLength */,
|
|
317
|
+
"IBAN must contain exactly 26 digits after the PL prefix."
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
return this.nrb.validate(nrbPart);
|
|
321
|
+
}
|
|
322
|
+
isValid(input) {
|
|
323
|
+
return this.validate(input).isValid;
|
|
324
|
+
}
|
|
325
|
+
parse(input) {
|
|
326
|
+
const result = this.validate(input);
|
|
327
|
+
if (result.isFailed()) {
|
|
328
|
+
throw result.toException();
|
|
329
|
+
}
|
|
330
|
+
return new Iban(input, this.normalize(input));
|
|
331
|
+
}
|
|
332
|
+
tryParse(input) {
|
|
333
|
+
try {
|
|
334
|
+
return this.parse(input);
|
|
335
|
+
} catch (err) {
|
|
336
|
+
if (err instanceof ValidationException) return null;
|
|
337
|
+
throw err;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
stripSeparators(input) {
|
|
341
|
+
return input.replace(/[ -]/g, "");
|
|
342
|
+
}
|
|
343
|
+
normalize(input) {
|
|
344
|
+
const stripped = this.stripSeparators(input);
|
|
345
|
+
return `PL${stripped.slice(2)}`;
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
// src/value-objects/IdCard.ts
|
|
350
|
+
var IdCard = class {
|
|
351
|
+
constructor(raw, normalized) {
|
|
352
|
+
this.raw = raw;
|
|
353
|
+
this.normalized = normalized;
|
|
354
|
+
}
|
|
355
|
+
raw;
|
|
356
|
+
normalized;
|
|
357
|
+
getRaw() {
|
|
358
|
+
return this.raw;
|
|
359
|
+
}
|
|
360
|
+
getNormalized() {
|
|
361
|
+
return this.normalized;
|
|
362
|
+
}
|
|
363
|
+
toString() {
|
|
364
|
+
return this.normalized;
|
|
365
|
+
}
|
|
366
|
+
getSeries() {
|
|
367
|
+
return this.normalized.slice(0, 3);
|
|
368
|
+
}
|
|
369
|
+
getSequentialNumber() {
|
|
370
|
+
return this.normalized.slice(3, 8);
|
|
371
|
+
}
|
|
372
|
+
getCheckDigit() {
|
|
373
|
+
return this.normalized.slice(8, 9);
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
// src/identifiers/IdCardIdentifier.ts
|
|
378
|
+
var WEIGHTS = [7, 3, 1, 7, 3, 1, 7, 3];
|
|
379
|
+
var MAX_LENGTH3 = 32;
|
|
380
|
+
var LENGTH = 9;
|
|
381
|
+
var IdCardIdentifier = class {
|
|
382
|
+
constructor(strict = true) {
|
|
383
|
+
this.strict = strict;
|
|
384
|
+
}
|
|
385
|
+
strict;
|
|
386
|
+
isStrict() {
|
|
387
|
+
return this.strict;
|
|
388
|
+
}
|
|
389
|
+
validate(input) {
|
|
390
|
+
if (input.length > MAX_LENGTH3) {
|
|
391
|
+
return ValidationResult.failWithReason(
|
|
392
|
+
"invalid_length" /* InvalidLength */,
|
|
393
|
+
"Input exceeds maximum length of 32 characters."
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
const normalized = this.normalize(input);
|
|
397
|
+
if (normalized.length !== LENGTH) {
|
|
398
|
+
return ValidationResult.failWithReason(
|
|
399
|
+
"invalid_length" /* InvalidLength */,
|
|
400
|
+
"Identity card number must be exactly 9 characters."
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
const series = normalized.slice(0, 3);
|
|
404
|
+
if (!/^[A-Za-z]{3}$/.test(series)) {
|
|
405
|
+
return ValidationResult.failWithReason(
|
|
406
|
+
"invalid_characters" /* InvalidCharacters */,
|
|
407
|
+
"Identity card series (first 3 characters) must contain only letters."
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
if (series.includes("O") || series.includes("Q")) {
|
|
411
|
+
return ValidationResult.failWithReason(
|
|
412
|
+
"invalid_format" /* InvalidFormat */,
|
|
413
|
+
"Identity card series cannot contain the letters O or Q."
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
if (!/^\d{6}$/.test(normalized.slice(3))) {
|
|
417
|
+
return ValidationResult.failWithReason(
|
|
418
|
+
"invalid_characters" /* InvalidCharacters */,
|
|
419
|
+
"Identity card number portion (characters 4\u20139) must contain only digits."
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
if (!this.isValidChecksum(normalized)) {
|
|
423
|
+
return ValidationResult.failWithReason(
|
|
424
|
+
"invalid_checksum" /* InvalidChecksum */,
|
|
425
|
+
"Identity card checksum digit does not match."
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
return ValidationResult.pass();
|
|
429
|
+
}
|
|
430
|
+
isValid(input) {
|
|
431
|
+
return this.validate(input).isValid;
|
|
432
|
+
}
|
|
433
|
+
parse(input) {
|
|
434
|
+
const result = this.validate(input);
|
|
435
|
+
if (result.isFailed()) {
|
|
436
|
+
throw result.toException();
|
|
437
|
+
}
|
|
438
|
+
return new IdCard(input, this.normalize(input));
|
|
439
|
+
}
|
|
440
|
+
tryParse(input) {
|
|
441
|
+
try {
|
|
442
|
+
return this.parse(input);
|
|
443
|
+
} catch (err) {
|
|
444
|
+
if (err instanceof ValidationException) return null;
|
|
445
|
+
throw err;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
normalize(input) {
|
|
449
|
+
return input.replace(/[-\s]/g, "").toUpperCase();
|
|
450
|
+
}
|
|
451
|
+
icaoCharValue(char) {
|
|
452
|
+
const code = char.charCodeAt(0);
|
|
453
|
+
return code >= 48 && code <= 57 ? code - 48 : code - 55;
|
|
454
|
+
}
|
|
455
|
+
isValidChecksum(normalized) {
|
|
456
|
+
let sum = 0;
|
|
457
|
+
for (let i = 0; i < 8; i++) {
|
|
458
|
+
sum += this.icaoCharValue(normalized[i] ?? "") * (WEIGHTS[i] ?? 0);
|
|
459
|
+
}
|
|
460
|
+
return sum % 10 === Number(normalized[8]);
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
// src/value-objects/Krs.ts
|
|
465
|
+
var Krs = class {
|
|
466
|
+
constructor(raw, normalized) {
|
|
467
|
+
this.raw = raw;
|
|
468
|
+
this.normalized = normalized;
|
|
469
|
+
}
|
|
470
|
+
raw;
|
|
471
|
+
normalized;
|
|
472
|
+
getRaw() {
|
|
473
|
+
return this.raw;
|
|
474
|
+
}
|
|
475
|
+
getNormalized() {
|
|
476
|
+
return this.normalized;
|
|
477
|
+
}
|
|
478
|
+
toString() {
|
|
479
|
+
return this.normalized;
|
|
480
|
+
}
|
|
481
|
+
getFormatted() {
|
|
482
|
+
return this.normalized.padStart(10, "0");
|
|
483
|
+
}
|
|
484
|
+
getNumericValue() {
|
|
485
|
+
return Number(this.normalized);
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
// src/identifiers/KrsIdentifier.ts
|
|
490
|
+
var MAX_LENGTH4 = 32;
|
|
491
|
+
var MAX_DIGITS = 10;
|
|
492
|
+
var KrsIdentifier = class {
|
|
493
|
+
constructor(strict = true) {
|
|
494
|
+
this.strict = strict;
|
|
495
|
+
}
|
|
496
|
+
strict;
|
|
497
|
+
isStrict() {
|
|
498
|
+
return this.strict;
|
|
499
|
+
}
|
|
500
|
+
validate(input) {
|
|
501
|
+
if (input.length > MAX_LENGTH4) {
|
|
502
|
+
return ValidationResult.failWithReason(
|
|
503
|
+
"invalid_length" /* InvalidLength */,
|
|
504
|
+
"Input exceeds maximum length of 32 characters."
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
const normalized = this.normalize(input);
|
|
508
|
+
if (normalized.length === 0 || normalized.length > MAX_DIGITS) {
|
|
509
|
+
return ValidationResult.failWithReason(
|
|
510
|
+
"invalid_length" /* InvalidLength */,
|
|
511
|
+
"KRS must have between 1 and 10 digits."
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
if (!/^\d+$/.test(normalized)) {
|
|
515
|
+
return ValidationResult.failWithReason(
|
|
516
|
+
"invalid_characters" /* InvalidCharacters */,
|
|
517
|
+
"KRS must contain only digits and spaces."
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
if (Number(normalized) === 0) {
|
|
521
|
+
return ValidationResult.failWithReason(
|
|
522
|
+
"all_zeros" /* AllZeros */,
|
|
523
|
+
"KRS cannot be all zeros."
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
const padded = normalized.padStart(MAX_DIGITS, "0");
|
|
527
|
+
if (this.strict && new Set(padded).size === 1) {
|
|
528
|
+
return ValidationResult.failWithReason(
|
|
529
|
+
"all_same_digit" /* AllSameDigit */,
|
|
530
|
+
"KRS consists of a single repeated digit."
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
return ValidationResult.pass();
|
|
534
|
+
}
|
|
535
|
+
isValid(input) {
|
|
536
|
+
return this.validate(input).isValid;
|
|
537
|
+
}
|
|
538
|
+
parse(input) {
|
|
539
|
+
const result = this.validate(input);
|
|
540
|
+
if (result.isFailed()) {
|
|
541
|
+
throw result.toException();
|
|
542
|
+
}
|
|
543
|
+
return new Krs(input, this.normalize(input));
|
|
544
|
+
}
|
|
545
|
+
tryParse(input) {
|
|
546
|
+
try {
|
|
547
|
+
return this.parse(input);
|
|
548
|
+
} catch (err) {
|
|
549
|
+
if (err instanceof ValidationException) return null;
|
|
550
|
+
throw err;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
normalize(input) {
|
|
554
|
+
return input.replace(/ /g, "");
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
|
|
558
|
+
// src/value-objects/Nip.ts
|
|
559
|
+
var Nip = class {
|
|
560
|
+
constructor(raw, normalized) {
|
|
561
|
+
this.raw = raw;
|
|
562
|
+
this.normalized = normalized;
|
|
563
|
+
}
|
|
564
|
+
raw;
|
|
565
|
+
normalized;
|
|
566
|
+
getRaw() {
|
|
567
|
+
return this.raw;
|
|
568
|
+
}
|
|
569
|
+
getNormalized() {
|
|
570
|
+
return this.normalized;
|
|
571
|
+
}
|
|
572
|
+
toString() {
|
|
573
|
+
return this.normalized;
|
|
574
|
+
}
|
|
575
|
+
getFormatted() {
|
|
576
|
+
const n = this.normalized;
|
|
577
|
+
return `${n.slice(0, 3)}-${n.slice(3, 6)}-${n.slice(6, 8)}-${n.slice(8, 10)}`;
|
|
578
|
+
}
|
|
579
|
+
getFormattedAlternative() {
|
|
580
|
+
const n = this.normalized;
|
|
581
|
+
return `${n.slice(0, 3)}-${n.slice(3, 5)}-${n.slice(5, 7)}-${n.slice(7, 10)}`;
|
|
582
|
+
}
|
|
583
|
+
getTaxOfficeCode() {
|
|
584
|
+
return this.normalized.slice(0, 3);
|
|
585
|
+
}
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
// src/identifiers/NipIdentifier.ts
|
|
589
|
+
var WEIGHTS2 = [6, 5, 7, 2, 3, 4, 5, 6, 7];
|
|
590
|
+
var MAX_LENGTH5 = 32;
|
|
591
|
+
var DIGITS2 = 10;
|
|
592
|
+
var NipIdentifier = class {
|
|
593
|
+
constructor(strict = true) {
|
|
594
|
+
this.strict = strict;
|
|
595
|
+
}
|
|
596
|
+
strict;
|
|
597
|
+
isStrict() {
|
|
598
|
+
return this.strict;
|
|
599
|
+
}
|
|
600
|
+
validate(input) {
|
|
601
|
+
if (input.length > MAX_LENGTH5) {
|
|
602
|
+
return ValidationResult.failWithReason(
|
|
603
|
+
"invalid_length" /* InvalidLength */,
|
|
604
|
+
"Input exceeds maximum length of 32 characters."
|
|
605
|
+
);
|
|
606
|
+
}
|
|
607
|
+
const normalized = this.normalize(input);
|
|
608
|
+
if (normalized.length !== DIGITS2) {
|
|
609
|
+
return ValidationResult.failWithReason(
|
|
610
|
+
"invalid_length" /* InvalidLength */,
|
|
611
|
+
"NIP must be exactly 10 digits."
|
|
612
|
+
);
|
|
613
|
+
}
|
|
614
|
+
if (!/^\d+$/.test(normalized)) {
|
|
615
|
+
return ValidationResult.failWithReason(
|
|
616
|
+
"invalid_characters" /* InvalidCharacters */,
|
|
617
|
+
"NIP must contain only digits, hyphens, and spaces."
|
|
618
|
+
);
|
|
619
|
+
}
|
|
620
|
+
if (normalized.startsWith("000")) {
|
|
621
|
+
return ValidationResult.failWithReason(
|
|
622
|
+
"invalid_format" /* InvalidFormat */,
|
|
623
|
+
"NIP tax office code cannot be 000."
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
const digits = Array.from(normalized).map(Number);
|
|
627
|
+
const sum = digits.slice(0, 9).reduce((acc, d, i) => acc + d * (WEIGHTS2[i] ?? 0), 0);
|
|
628
|
+
if (sum % 11 !== (digits[9] ?? -1)) {
|
|
629
|
+
return ValidationResult.failWithReason(
|
|
630
|
+
"invalid_checksum" /* InvalidChecksum */,
|
|
631
|
+
"NIP checksum digit does not match."
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
if (this.strict && new Set(digits).size === 1) {
|
|
635
|
+
return ValidationResult.failWithReason(
|
|
636
|
+
"all_same_digit" /* AllSameDigit */,
|
|
637
|
+
"NIP consists of a single repeated digit."
|
|
638
|
+
);
|
|
639
|
+
}
|
|
640
|
+
return ValidationResult.pass();
|
|
641
|
+
}
|
|
642
|
+
isValid(input) {
|
|
643
|
+
return this.validate(input).isValid;
|
|
644
|
+
}
|
|
645
|
+
parse(input) {
|
|
646
|
+
const result = this.validate(input);
|
|
647
|
+
if (result.isFailed()) {
|
|
648
|
+
throw result.toException();
|
|
649
|
+
}
|
|
650
|
+
return new Nip(input, this.normalize(input));
|
|
651
|
+
}
|
|
652
|
+
tryParse(input) {
|
|
653
|
+
try {
|
|
654
|
+
return this.parse(input);
|
|
655
|
+
} catch (err) {
|
|
656
|
+
if (err instanceof ValidationException) return null;
|
|
657
|
+
throw err;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
normalize(input) {
|
|
661
|
+
return input.replace(/[-\s]/g, "");
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
|
|
665
|
+
// src/value-objects/Passport.ts
|
|
666
|
+
var Passport = class {
|
|
667
|
+
constructor(raw, normalized) {
|
|
668
|
+
this.raw = raw;
|
|
669
|
+
this.normalized = normalized;
|
|
670
|
+
}
|
|
671
|
+
raw;
|
|
672
|
+
normalized;
|
|
673
|
+
getRaw() {
|
|
674
|
+
return this.raw;
|
|
675
|
+
}
|
|
676
|
+
getNormalized() {
|
|
677
|
+
return this.normalized;
|
|
678
|
+
}
|
|
679
|
+
toString() {
|
|
680
|
+
return this.normalized;
|
|
681
|
+
}
|
|
682
|
+
getSeries() {
|
|
683
|
+
return this.normalized.slice(0, 2);
|
|
684
|
+
}
|
|
685
|
+
getSequentialNumber() {
|
|
686
|
+
return this.normalized.slice(2, 8);
|
|
687
|
+
}
|
|
688
|
+
getCheckDigit() {
|
|
689
|
+
return this.normalized.slice(8, 9);
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
|
|
693
|
+
// src/identifiers/PassportIdentifier.ts
|
|
694
|
+
var WEIGHTS3 = [7, 3, 1, 7, 3, 1, 7, 3];
|
|
695
|
+
var MAX_LENGTH6 = 32;
|
|
696
|
+
var LENGTH2 = 9;
|
|
697
|
+
var PassportIdentifier = class {
|
|
698
|
+
constructor(strict = true) {
|
|
699
|
+
this.strict = strict;
|
|
700
|
+
}
|
|
701
|
+
strict;
|
|
702
|
+
isStrict() {
|
|
703
|
+
return this.strict;
|
|
704
|
+
}
|
|
705
|
+
validate(input) {
|
|
706
|
+
if (input.length > MAX_LENGTH6) {
|
|
707
|
+
return ValidationResult.failWithReason(
|
|
708
|
+
"invalid_length" /* InvalidLength */,
|
|
709
|
+
"Input exceeds maximum length of 32 characters."
|
|
710
|
+
);
|
|
711
|
+
}
|
|
712
|
+
const normalized = this.normalize(input);
|
|
713
|
+
if (normalized.length !== LENGTH2) {
|
|
714
|
+
return ValidationResult.failWithReason(
|
|
715
|
+
"invalid_length" /* InvalidLength */,
|
|
716
|
+
"Passport number must be exactly 9 characters."
|
|
717
|
+
);
|
|
718
|
+
}
|
|
719
|
+
if (!/^[A-Za-z]{2}/.test(normalized)) {
|
|
720
|
+
return ValidationResult.failWithReason(
|
|
721
|
+
"invalid_characters" /* InvalidCharacters */,
|
|
722
|
+
"Passport series (first 2 characters) must contain only letters."
|
|
723
|
+
);
|
|
724
|
+
}
|
|
725
|
+
if (!/^\d{7}$/.test(normalized.slice(2))) {
|
|
726
|
+
return ValidationResult.failWithReason(
|
|
727
|
+
"invalid_characters" /* InvalidCharacters */,
|
|
728
|
+
"Passport number portion (characters 3\u20139) must contain only digits."
|
|
729
|
+
);
|
|
730
|
+
}
|
|
731
|
+
if (!this.isValidChecksum(normalized)) {
|
|
732
|
+
return ValidationResult.failWithReason(
|
|
733
|
+
"invalid_checksum" /* InvalidChecksum */,
|
|
734
|
+
"Passport checksum digit does not match."
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
return ValidationResult.pass();
|
|
738
|
+
}
|
|
739
|
+
isValid(input) {
|
|
740
|
+
return this.validate(input).isValid;
|
|
741
|
+
}
|
|
742
|
+
parse(input) {
|
|
743
|
+
const result = this.validate(input);
|
|
744
|
+
if (result.isFailed()) {
|
|
745
|
+
throw result.toException();
|
|
746
|
+
}
|
|
747
|
+
return new Passport(input, this.normalize(input));
|
|
748
|
+
}
|
|
749
|
+
tryParse(input) {
|
|
750
|
+
try {
|
|
751
|
+
return this.parse(input);
|
|
752
|
+
} catch (err) {
|
|
753
|
+
if (err instanceof ValidationException) return null;
|
|
754
|
+
throw err;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
normalize(input) {
|
|
758
|
+
return input.replace(/[-\s]/g, "").toUpperCase();
|
|
759
|
+
}
|
|
760
|
+
icaoCharValue(char) {
|
|
761
|
+
const code = char.charCodeAt(0);
|
|
762
|
+
return code >= 48 && code <= 57 ? code - 48 : code - 55;
|
|
763
|
+
}
|
|
764
|
+
isValidChecksum(normalized) {
|
|
765
|
+
let sum = 0;
|
|
766
|
+
for (let i = 0; i < 8; i++) {
|
|
767
|
+
sum += this.icaoCharValue(normalized[i] ?? "") * (WEIGHTS3[i] ?? 0);
|
|
768
|
+
}
|
|
769
|
+
return sum % 10 === Number(normalized[8]);
|
|
770
|
+
}
|
|
771
|
+
};
|
|
772
|
+
|
|
773
|
+
// src/value-objects/Pesel.ts
|
|
774
|
+
var Pesel = class {
|
|
775
|
+
constructor(raw, normalized, birthDate, gender, ordinalNumber) {
|
|
776
|
+
this.raw = raw;
|
|
777
|
+
this.normalized = normalized;
|
|
778
|
+
this.gender = gender;
|
|
779
|
+
this.ordinalNumber = ordinalNumber;
|
|
780
|
+
this.birthDate = new Date(birthDate.getTime());
|
|
781
|
+
}
|
|
782
|
+
raw;
|
|
783
|
+
normalized;
|
|
784
|
+
gender;
|
|
785
|
+
ordinalNumber;
|
|
786
|
+
birthDate;
|
|
787
|
+
getRaw() {
|
|
788
|
+
return this.raw;
|
|
789
|
+
}
|
|
790
|
+
getNormalized() {
|
|
791
|
+
return this.normalized;
|
|
792
|
+
}
|
|
793
|
+
toString() {
|
|
794
|
+
return this.normalized;
|
|
795
|
+
}
|
|
796
|
+
getBirthDate() {
|
|
797
|
+
return new Date(this.birthDate);
|
|
798
|
+
}
|
|
799
|
+
getGender() {
|
|
800
|
+
return this.gender;
|
|
801
|
+
}
|
|
802
|
+
getOrdinalNumber() {
|
|
803
|
+
return this.ordinalNumber;
|
|
804
|
+
}
|
|
805
|
+
isMale() {
|
|
806
|
+
return this.gender === "male" /* Male */;
|
|
807
|
+
}
|
|
808
|
+
isFemale() {
|
|
809
|
+
return this.gender === "female" /* Female */;
|
|
810
|
+
}
|
|
811
|
+
getAge() {
|
|
812
|
+
const today = /* @__PURE__ */ new Date();
|
|
813
|
+
const birth = this.birthDate;
|
|
814
|
+
let age = today.getFullYear() - birth.getFullYear();
|
|
815
|
+
const m = today.getMonth() - birth.getMonth();
|
|
816
|
+
if (m < 0 || m === 0 && today.getDate() < birth.getDate()) {
|
|
817
|
+
age--;
|
|
818
|
+
}
|
|
819
|
+
return age;
|
|
820
|
+
}
|
|
821
|
+
isAdult() {
|
|
822
|
+
return this.getAge() >= 18;
|
|
823
|
+
}
|
|
824
|
+
getCentury() {
|
|
825
|
+
const year = this.birthDate.getFullYear();
|
|
826
|
+
return year - year % 100;
|
|
827
|
+
}
|
|
828
|
+
};
|
|
829
|
+
|
|
830
|
+
// src/identifiers/PeselIdentifier.ts
|
|
831
|
+
var WEIGHTS4 = [1, 3, 7, 9, 1, 3, 7, 9, 1, 3];
|
|
832
|
+
var MAX_LENGTH7 = 32;
|
|
833
|
+
var DIGITS3 = 11;
|
|
834
|
+
var PeselIdentifier = class {
|
|
835
|
+
constructor(strict = true) {
|
|
836
|
+
this.strict = strict;
|
|
837
|
+
}
|
|
838
|
+
strict;
|
|
839
|
+
isStrict() {
|
|
840
|
+
return this.strict;
|
|
841
|
+
}
|
|
842
|
+
validate(input) {
|
|
843
|
+
if (input.length > MAX_LENGTH7) {
|
|
844
|
+
return ValidationResult.failWithReason(
|
|
845
|
+
"invalid_length" /* InvalidLength */,
|
|
846
|
+
"Input exceeds maximum length of 32 characters."
|
|
847
|
+
);
|
|
848
|
+
}
|
|
849
|
+
const normalized = this.normalize(input);
|
|
850
|
+
if (normalized.length !== DIGITS3) {
|
|
851
|
+
return ValidationResult.failWithReason(
|
|
852
|
+
"invalid_length" /* InvalidLength */,
|
|
853
|
+
"PESEL must be exactly 11 digits."
|
|
854
|
+
);
|
|
855
|
+
}
|
|
856
|
+
if (!/^\d+$/.test(normalized)) {
|
|
857
|
+
return ValidationResult.failWithReason(
|
|
858
|
+
"invalid_characters" /* InvalidCharacters */,
|
|
859
|
+
"PESEL must contain only digits."
|
|
860
|
+
);
|
|
861
|
+
}
|
|
862
|
+
const digits = Array.from(normalized).map(Number);
|
|
863
|
+
const encodedMonth = (digits[2] ?? 0) * 10 + (digits[3] ?? 0);
|
|
864
|
+
const month = this.decodeMonth(encodedMonth);
|
|
865
|
+
if (month === null) {
|
|
866
|
+
return ValidationResult.failWithReason(
|
|
867
|
+
"invalid_month" /* InvalidMonth */,
|
|
868
|
+
"PESEL contains an invalid month encoding."
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
const year = this.decodeYear(
|
|
872
|
+
(digits[0] ?? 0) * 10 + (digits[1] ?? 0),
|
|
873
|
+
encodedMonth
|
|
874
|
+
);
|
|
875
|
+
const day = (digits[4] ?? 0) * 10 + (digits[5] ?? 0);
|
|
876
|
+
if (!this.isValidDate(year, month, day)) {
|
|
877
|
+
return ValidationResult.failWithReason(
|
|
878
|
+
"invalid_date" /* InvalidDate */,
|
|
879
|
+
"PESEL contains an invalid date."
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
const sum = digits.slice(0, 10).reduce((acc, d, i) => acc + d * (WEIGHTS4[i] ?? 0), 0);
|
|
883
|
+
if ((10 - sum % 10) % 10 !== (digits[10] ?? -1)) {
|
|
884
|
+
return ValidationResult.failWithReason(
|
|
885
|
+
"invalid_checksum" /* InvalidChecksum */,
|
|
886
|
+
"PESEL checksum digit does not match."
|
|
887
|
+
);
|
|
888
|
+
}
|
|
889
|
+
if (this.strict) {
|
|
890
|
+
const birthDate = new Date(year, month - 1, day);
|
|
891
|
+
const today = /* @__PURE__ */ new Date();
|
|
892
|
+
today.setHours(0, 0, 0, 0);
|
|
893
|
+
if (birthDate > today) {
|
|
894
|
+
return ValidationResult.failWithReason(
|
|
895
|
+
"future_date" /* FutureDate */,
|
|
896
|
+
"PESEL birth date is in the future."
|
|
897
|
+
);
|
|
898
|
+
}
|
|
899
|
+
if (new Set(digits).size === 1) {
|
|
900
|
+
return ValidationResult.failWithReason(
|
|
901
|
+
"all_same_digit" /* AllSameDigit */,
|
|
902
|
+
"PESEL consists of a single repeated digit."
|
|
903
|
+
);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
return ValidationResult.pass();
|
|
907
|
+
}
|
|
908
|
+
isValid(input) {
|
|
909
|
+
return this.validate(input).isValid;
|
|
910
|
+
}
|
|
911
|
+
parse(input) {
|
|
912
|
+
const result = this.validate(input);
|
|
913
|
+
if (result.isFailed()) {
|
|
914
|
+
throw result.toException();
|
|
915
|
+
}
|
|
916
|
+
const normalized = this.normalize(input);
|
|
917
|
+
const digits = Array.from(normalized).map(Number);
|
|
918
|
+
const encodedMonth = (digits[2] ?? 0) * 10 + (digits[3] ?? 0);
|
|
919
|
+
const month = this.decodeMonth(encodedMonth) ?? 1;
|
|
920
|
+
const year = this.decodeYear(
|
|
921
|
+
(digits[0] ?? 0) * 10 + (digits[1] ?? 0),
|
|
922
|
+
encodedMonth
|
|
923
|
+
);
|
|
924
|
+
const day = (digits[4] ?? 0) * 10 + (digits[5] ?? 0);
|
|
925
|
+
const birthDate = new Date(year, month - 1, day);
|
|
926
|
+
const gender = (digits[9] ?? 0) % 2 === 1 ? "male" /* Male */ : "female" /* Female */;
|
|
927
|
+
const ordinalNumber = (digits[6] ?? 0) * 1e3 + (digits[7] ?? 0) * 100 + (digits[8] ?? 0) * 10 + (digits[9] ?? 0);
|
|
928
|
+
return new Pesel(input, normalized, birthDate, gender, ordinalNumber);
|
|
929
|
+
}
|
|
930
|
+
tryParse(input) {
|
|
931
|
+
try {
|
|
932
|
+
return this.parse(input);
|
|
933
|
+
} catch (err) {
|
|
934
|
+
if (err instanceof ValidationException) return null;
|
|
935
|
+
throw err;
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
normalize(input) {
|
|
939
|
+
return input.replace(/ /g, "");
|
|
940
|
+
}
|
|
941
|
+
decodeMonth(encodedMonth) {
|
|
942
|
+
if (encodedMonth >= 1 && encodedMonth <= 12) return encodedMonth;
|
|
943
|
+
if (encodedMonth >= 21 && encodedMonth <= 32) return encodedMonth - 20;
|
|
944
|
+
if (encodedMonth >= 41 && encodedMonth <= 52) return encodedMonth - 40;
|
|
945
|
+
if (encodedMonth >= 61 && encodedMonth <= 72) return encodedMonth - 60;
|
|
946
|
+
if (encodedMonth >= 81 && encodedMonth <= 92) return encodedMonth - 80;
|
|
947
|
+
return null;
|
|
948
|
+
}
|
|
949
|
+
decodeYear(yy, encodedMonth) {
|
|
950
|
+
if (encodedMonth >= 81 && encodedMonth <= 92) return 1800 + yy;
|
|
951
|
+
if (encodedMonth >= 1 && encodedMonth <= 12) return 1900 + yy;
|
|
952
|
+
if (encodedMonth >= 21 && encodedMonth <= 32) return 2e3 + yy;
|
|
953
|
+
if (encodedMonth >= 41 && encodedMonth <= 52) return 2100 + yy;
|
|
954
|
+
return 2200 + yy;
|
|
955
|
+
}
|
|
956
|
+
isValidDate(year, month, day) {
|
|
957
|
+
const d = new Date(year, month - 1, day);
|
|
958
|
+
return d.getFullYear() === year && d.getMonth() === month - 1 && d.getDate() === day;
|
|
959
|
+
}
|
|
960
|
+
};
|
|
961
|
+
|
|
962
|
+
// src/value-objects/Regon.ts
|
|
963
|
+
var Regon = class {
|
|
964
|
+
constructor(raw, normalized, type) {
|
|
965
|
+
this.raw = raw;
|
|
966
|
+
this.normalized = normalized;
|
|
967
|
+
this.type = type;
|
|
968
|
+
}
|
|
969
|
+
raw;
|
|
970
|
+
normalized;
|
|
971
|
+
type;
|
|
972
|
+
getRaw() {
|
|
973
|
+
return this.raw;
|
|
974
|
+
}
|
|
975
|
+
getNormalized() {
|
|
976
|
+
return this.normalized;
|
|
977
|
+
}
|
|
978
|
+
toString() {
|
|
979
|
+
return this.normalized;
|
|
980
|
+
}
|
|
981
|
+
getType() {
|
|
982
|
+
return this.type;
|
|
983
|
+
}
|
|
984
|
+
getBaseRegon() {
|
|
985
|
+
return this.normalized.slice(0, 9);
|
|
986
|
+
}
|
|
987
|
+
getLocalUnitSuffix() {
|
|
988
|
+
if (this.type === "individual" /* Individual */) return null;
|
|
989
|
+
return this.normalized.slice(9, 14);
|
|
990
|
+
}
|
|
991
|
+
isLocalUnit() {
|
|
992
|
+
return this.type === "legal_entity" /* LegalEntity */;
|
|
993
|
+
}
|
|
994
|
+
};
|
|
995
|
+
|
|
996
|
+
// src/identifiers/RegonIdentifier.ts
|
|
997
|
+
var WEIGHTS_9 = [8, 9, 2, 3, 4, 5, 6, 7];
|
|
998
|
+
var WEIGHTS_14 = [2, 4, 8, 5, 0, 9, 7, 3, 6, 1, 2, 4, 8];
|
|
999
|
+
var MAX_LENGTH8 = 32;
|
|
1000
|
+
var DIGITS_9 = 9;
|
|
1001
|
+
var DIGITS_14 = 14;
|
|
1002
|
+
var RegonIdentifier = class {
|
|
1003
|
+
constructor(strict = true) {
|
|
1004
|
+
this.strict = strict;
|
|
1005
|
+
}
|
|
1006
|
+
strict;
|
|
1007
|
+
isStrict() {
|
|
1008
|
+
return this.strict;
|
|
1009
|
+
}
|
|
1010
|
+
validate(input) {
|
|
1011
|
+
if (input.length > MAX_LENGTH8) {
|
|
1012
|
+
return ValidationResult.failWithReason(
|
|
1013
|
+
"invalid_length" /* InvalidLength */,
|
|
1014
|
+
"Input exceeds maximum length of 32 characters."
|
|
1015
|
+
);
|
|
1016
|
+
}
|
|
1017
|
+
const normalized = this.normalize(input);
|
|
1018
|
+
const length = normalized.length;
|
|
1019
|
+
if (length !== DIGITS_9 && length !== DIGITS_14) {
|
|
1020
|
+
return ValidationResult.failWithReason(
|
|
1021
|
+
"invalid_length" /* InvalidLength */,
|
|
1022
|
+
"REGON must be exactly 9 or 14 digits."
|
|
1023
|
+
);
|
|
1024
|
+
}
|
|
1025
|
+
if (!/^\d+$/.test(normalized)) {
|
|
1026
|
+
return ValidationResult.failWithReason(
|
|
1027
|
+
"invalid_characters" /* InvalidCharacters */,
|
|
1028
|
+
"REGON must contain only digits and spaces."
|
|
1029
|
+
);
|
|
1030
|
+
}
|
|
1031
|
+
const digits = Array.from(normalized).map(Number);
|
|
1032
|
+
if (!this.isValid9DigitChecksum(digits)) {
|
|
1033
|
+
return ValidationResult.failWithReason(
|
|
1034
|
+
"invalid_checksum" /* InvalidChecksum */,
|
|
1035
|
+
"REGON checksum digit does not match."
|
|
1036
|
+
);
|
|
1037
|
+
}
|
|
1038
|
+
if (length === DIGITS_14 && !this.isValid14DigitChecksum(digits)) {
|
|
1039
|
+
return ValidationResult.failWithReason(
|
|
1040
|
+
"invalid_checksum" /* InvalidChecksum */,
|
|
1041
|
+
"REGON local unit checksum digit does not match."
|
|
1042
|
+
);
|
|
1043
|
+
}
|
|
1044
|
+
return ValidationResult.pass();
|
|
1045
|
+
}
|
|
1046
|
+
isValid(input) {
|
|
1047
|
+
return this.validate(input).isValid;
|
|
1048
|
+
}
|
|
1049
|
+
parse(input) {
|
|
1050
|
+
const result = this.validate(input);
|
|
1051
|
+
if (result.isFailed()) {
|
|
1052
|
+
throw result.toException();
|
|
1053
|
+
}
|
|
1054
|
+
const normalized = this.normalize(input);
|
|
1055
|
+
const type = normalized.length === DIGITS_9 ? "individual" /* Individual */ : "legal_entity" /* LegalEntity */;
|
|
1056
|
+
return new Regon(input, normalized, type);
|
|
1057
|
+
}
|
|
1058
|
+
tryParse(input) {
|
|
1059
|
+
try {
|
|
1060
|
+
return this.parse(input);
|
|
1061
|
+
} catch (err) {
|
|
1062
|
+
if (err instanceof ValidationException) return null;
|
|
1063
|
+
throw err;
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
normalize(input) {
|
|
1067
|
+
return input.replace(/ /g, "");
|
|
1068
|
+
}
|
|
1069
|
+
isValid9DigitChecksum(digits) {
|
|
1070
|
+
let sum = 0;
|
|
1071
|
+
for (let i = 0; i < 8; i++) {
|
|
1072
|
+
sum += (digits[i] ?? 0) * (WEIGHTS_9[i] ?? 0);
|
|
1073
|
+
}
|
|
1074
|
+
const checksum = sum % 11;
|
|
1075
|
+
return (checksum === 10 ? 0 : checksum) === (digits[8] ?? -1);
|
|
1076
|
+
}
|
|
1077
|
+
isValid14DigitChecksum(digits) {
|
|
1078
|
+
let sum = 0;
|
|
1079
|
+
for (let i = 0; i < 13; i++) {
|
|
1080
|
+
sum += (digits[i] ?? 0) * (WEIGHTS_14[i] ?? 0);
|
|
1081
|
+
}
|
|
1082
|
+
const checksum = sum % 11;
|
|
1083
|
+
return (checksum === 10 ? 0 : checksum) === (digits[13] ?? -1);
|
|
1084
|
+
}
|
|
1085
|
+
};
|
|
1086
|
+
|
|
1087
|
+
// src/value-objects/VatEu.ts
|
|
1088
|
+
var VatEu = class {
|
|
1089
|
+
constructor(raw, normalized) {
|
|
1090
|
+
this.raw = raw;
|
|
1091
|
+
this.normalized = normalized;
|
|
1092
|
+
}
|
|
1093
|
+
raw;
|
|
1094
|
+
normalized;
|
|
1095
|
+
getRaw() {
|
|
1096
|
+
return this.raw;
|
|
1097
|
+
}
|
|
1098
|
+
getNormalized() {
|
|
1099
|
+
return this.normalized;
|
|
1100
|
+
}
|
|
1101
|
+
toString() {
|
|
1102
|
+
return this.normalized;
|
|
1103
|
+
}
|
|
1104
|
+
getCountryCode() {
|
|
1105
|
+
return "PL";
|
|
1106
|
+
}
|
|
1107
|
+
getNip() {
|
|
1108
|
+
return this.normalized.slice(2);
|
|
1109
|
+
}
|
|
1110
|
+
getFormatted() {
|
|
1111
|
+
const n = this.getNip();
|
|
1112
|
+
return `PL${n.slice(0, 3)}-${n.slice(3, 6)}-${n.slice(6, 8)}-${n.slice(8, 10)}`;
|
|
1113
|
+
}
|
|
1114
|
+
};
|
|
1115
|
+
|
|
1116
|
+
// src/identifiers/VatEuIdentifier.ts
|
|
1117
|
+
var MAX_LENGTH9 = 32;
|
|
1118
|
+
var NIP_DIGITS = 10;
|
|
1119
|
+
var PREFIX = "PL";
|
|
1120
|
+
var VatEuIdentifier = class {
|
|
1121
|
+
constructor(strict = true) {
|
|
1122
|
+
this.strict = strict;
|
|
1123
|
+
this.nip = new NipIdentifier(strict);
|
|
1124
|
+
}
|
|
1125
|
+
strict;
|
|
1126
|
+
nip;
|
|
1127
|
+
isStrict() {
|
|
1128
|
+
return this.strict;
|
|
1129
|
+
}
|
|
1130
|
+
validate(input) {
|
|
1131
|
+
if (input.length > MAX_LENGTH9) {
|
|
1132
|
+
return ValidationResult.failWithReason(
|
|
1133
|
+
"invalid_length" /* InvalidLength */,
|
|
1134
|
+
"Input exceeds maximum length of 32 characters."
|
|
1135
|
+
);
|
|
1136
|
+
}
|
|
1137
|
+
const stripped = this.stripSeparators(input);
|
|
1138
|
+
if (stripped.length < 2 || stripped.slice(0, 2).toUpperCase() !== PREFIX) {
|
|
1139
|
+
return ValidationResult.failWithReason(
|
|
1140
|
+
"invalid_format" /* InvalidFormat */,
|
|
1141
|
+
"VAT-EU number must start with the PL country prefix."
|
|
1142
|
+
);
|
|
1143
|
+
}
|
|
1144
|
+
const nipPart = stripped.slice(2);
|
|
1145
|
+
if (nipPart.length !== NIP_DIGITS) {
|
|
1146
|
+
return ValidationResult.failWithReason(
|
|
1147
|
+
"invalid_length" /* InvalidLength */,
|
|
1148
|
+
"VAT-EU must contain exactly 10 digits after the PL prefix."
|
|
1149
|
+
);
|
|
1150
|
+
}
|
|
1151
|
+
return this.nip.validate(nipPart);
|
|
1152
|
+
}
|
|
1153
|
+
isValid(input) {
|
|
1154
|
+
return this.validate(input).isValid;
|
|
1155
|
+
}
|
|
1156
|
+
parse(input) {
|
|
1157
|
+
const result = this.validate(input);
|
|
1158
|
+
if (result.isFailed()) {
|
|
1159
|
+
throw result.toException();
|
|
1160
|
+
}
|
|
1161
|
+
return new VatEu(input, this.normalize(input));
|
|
1162
|
+
}
|
|
1163
|
+
tryParse(input) {
|
|
1164
|
+
try {
|
|
1165
|
+
return this.parse(input);
|
|
1166
|
+
} catch (err) {
|
|
1167
|
+
if (err instanceof ValidationException) return null;
|
|
1168
|
+
throw err;
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
stripSeparators(input) {
|
|
1172
|
+
return input.replace(/[-\s]/g, "");
|
|
1173
|
+
}
|
|
1174
|
+
normalize(input) {
|
|
1175
|
+
const stripped = this.stripSeparators(input);
|
|
1176
|
+
return PREFIX + stripped.slice(2);
|
|
1177
|
+
}
|
|
1178
|
+
};
|
|
1179
|
+
|
|
1180
|
+
// src/Numerik.ts
|
|
1181
|
+
var Numerik = {
|
|
1182
|
+
// Personal
|
|
1183
|
+
pesel: (strict = true) => new PeselIdentifier(strict),
|
|
1184
|
+
idCard: (strict = true) => new IdCardIdentifier(strict),
|
|
1185
|
+
passport: (strict = true) => new PassportIdentifier(strict),
|
|
1186
|
+
// Tax & Business
|
|
1187
|
+
nip: (strict = true) => new NipIdentifier(strict),
|
|
1188
|
+
vatEu: (strict = true) => new VatEuIdentifier(strict),
|
|
1189
|
+
regon: (strict = true) => new RegonIdentifier(strict),
|
|
1190
|
+
krs: (strict = true) => new KrsIdentifier(strict),
|
|
1191
|
+
// Banking
|
|
1192
|
+
nrb: (strict = true) => new NrbIdentifier(strict),
|
|
1193
|
+
iban: (strict = true) => new IbanIdentifier(strict)
|
|
1194
|
+
};
|
|
1195
|
+
|
|
1196
|
+
// src/zod/index.ts
|
|
1197
|
+
function refine(identifier) {
|
|
1198
|
+
return (val, ctx) => {
|
|
1199
|
+
const result = identifier.validate(val);
|
|
1200
|
+
for (const failure of result.failures) {
|
|
1201
|
+
ctx.addIssue({ code: import_zod.z.ZodIssueCode.custom, message: failure.message });
|
|
1202
|
+
}
|
|
1203
|
+
};
|
|
1204
|
+
}
|
|
1205
|
+
function makeIdSchemas(factory) {
|
|
1206
|
+
return {
|
|
1207
|
+
schema: (strict = true) => {
|
|
1208
|
+
const id = factory(strict);
|
|
1209
|
+
return import_zod.z.string().superRefine(refine(id));
|
|
1210
|
+
},
|
|
1211
|
+
parseSchema: (strict = true) => {
|
|
1212
|
+
const id = factory(strict);
|
|
1213
|
+
return import_zod.z.string().superRefine(refine(id)).transform((val) => id.parse(val));
|
|
1214
|
+
}
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
var { schema: peselSchema, parseSchema: peselParseSchema } = makeIdSchemas((strict) => Numerik.pesel(strict));
|
|
1218
|
+
var { schema: idCardSchema, parseSchema: idCardParseSchema } = makeIdSchemas((strict) => Numerik.idCard(strict));
|
|
1219
|
+
var { schema: passportSchema, parseSchema: passportParseSchema } = makeIdSchemas((strict) => Numerik.passport(strict));
|
|
1220
|
+
var { schema: nipSchema, parseSchema: nipParseSchema } = makeIdSchemas((strict) => Numerik.nip(strict));
|
|
1221
|
+
var { schema: vatEuSchema, parseSchema: vatEuParseSchema } = makeIdSchemas((strict) => Numerik.vatEu(strict));
|
|
1222
|
+
var { schema: regonSchema, parseSchema: regonParseSchema } = makeIdSchemas((strict) => Numerik.regon(strict));
|
|
1223
|
+
var { schema: krsSchema, parseSchema: krsParseSchema } = makeIdSchemas((strict) => Numerik.krs(strict));
|
|
1224
|
+
var { schema: nrbSchema, parseSchema: nrbParseSchema } = makeIdSchemas((strict) => Numerik.nrb(strict));
|
|
1225
|
+
var { schema: ibanSchema, parseSchema: ibanParseSchema } = makeIdSchemas((strict) => Numerik.iban(strict));
|
|
1226
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1227
|
+
0 && (module.exports = {
|
|
1228
|
+
ibanParseSchema,
|
|
1229
|
+
ibanSchema,
|
|
1230
|
+
idCardParseSchema,
|
|
1231
|
+
idCardSchema,
|
|
1232
|
+
krsParseSchema,
|
|
1233
|
+
krsSchema,
|
|
1234
|
+
nipParseSchema,
|
|
1235
|
+
nipSchema,
|
|
1236
|
+
nrbParseSchema,
|
|
1237
|
+
nrbSchema,
|
|
1238
|
+
passportParseSchema,
|
|
1239
|
+
passportSchema,
|
|
1240
|
+
peselParseSchema,
|
|
1241
|
+
peselSchema,
|
|
1242
|
+
regonParseSchema,
|
|
1243
|
+
regonSchema,
|
|
1244
|
+
vatEuParseSchema,
|
|
1245
|
+
vatEuSchema
|
|
1246
|
+
});
|
|
1247
|
+
//# sourceMappingURL=index.cjs.map
|