joopjs 2.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/CHANGELOG.md +678 -0
- package/README.md +583 -0
- package/dist/a11y.service-C-DQQfgO.d.mts +143 -0
- package/dist/a11y.service-CauEJrJe.d.ts +143 -0
- package/dist/adapters-B6slG6hQ.d.mts +84 -0
- package/dist/adapters-B6slG6hQ.d.ts +84 -0
- package/dist/aes.service-CkoupAww.d.mts +95 -0
- package/dist/aes.service-CkoupAww.d.ts +95 -0
- package/dist/ai/index.d.mts +99 -0
- package/dist/ai/index.d.ts +99 -0
- package/dist/ai/index.js +307 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/index.mjs +304 -0
- package/dist/ai/index.mjs.map +1 -0
- package/dist/analytics/index.d.mts +42 -0
- package/dist/analytics/index.d.ts +42 -0
- package/dist/analytics/index.js +139 -0
- package/dist/analytics/index.js.map +1 -0
- package/dist/analytics/index.mjs +136 -0
- package/dist/analytics/index.mjs.map +1 -0
- package/dist/angular/index.d.mts +148 -0
- package/dist/angular/index.d.ts +148 -0
- package/dist/angular/index.js +122 -0
- package/dist/angular/index.js.map +1 -0
- package/dist/angular/index.mjs +101 -0
- package/dist/angular/index.mjs.map +1 -0
- package/dist/api/index.d.mts +128 -0
- package/dist/api/index.d.ts +128 -0
- package/dist/api/index.js +1358 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/index.mjs +1332 -0
- package/dist/api/index.mjs.map +1 -0
- package/dist/auth/index.d.mts +105 -0
- package/dist/auth/index.d.ts +105 -0
- package/dist/auth/index.js +989 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/index.mjs +979 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/auth.service-DNVB-L4U.d.mts +16 -0
- package/dist/auth.service-PjUUSUIt.d.ts +16 -0
- package/dist/banking/index.d.mts +1530 -0
- package/dist/banking/index.d.ts +1530 -0
- package/dist/banking/index.js +4739 -0
- package/dist/banking/index.js.map +1 -0
- package/dist/banking/index.mjs +4661 -0
- package/dist/banking/index.mjs.map +1 -0
- package/dist/cache/index.d.mts +40 -0
- package/dist/cache/index.d.ts +40 -0
- package/dist/cache/index.js +174 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/index.mjs +172 -0
- package/dist/cache/index.mjs.map +1 -0
- package/dist/client-profile.service-BuPeXVp5.d.mts +28 -0
- package/dist/client-profile.service-D5bRRYQp.d.ts +28 -0
- package/dist/config.models-Cqg04fAQ.d.mts +84 -0
- package/dist/config.models-Cqg04fAQ.d.ts +84 -0
- package/dist/config.service-CrCvI-JS.d.ts +31 -0
- package/dist/config.service-Cz4QQLlf.d.mts +31 -0
- package/dist/core/index.d.mts +4 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.js +631 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/index.mjs +619 -0
- package/dist/core/index.mjs.map +1 -0
- package/dist/crypto-utils-DriNhLdx.d.mts +30 -0
- package/dist/crypto-utils-DriNhLdx.d.ts +30 -0
- package/dist/data-storage.service-DT6xaTxE.d.ts +51 -0
- package/dist/data-storage.service-LvhGRCmw.d.mts +51 -0
- package/dist/deeplink/index.d.mts +39 -0
- package/dist/deeplink/index.d.ts +39 -0
- package/dist/deeplink/index.js +268 -0
- package/dist/deeplink/index.js.map +1 -0
- package/dist/deeplink/index.mjs +265 -0
- package/dist/deeplink/index.mjs.map +1 -0
- package/dist/deeplink.service-Ctd5u243.d.mts +35 -0
- package/dist/deeplink.service-uUuTnY9_.d.ts +35 -0
- package/dist/dev/index.d.mts +20 -0
- package/dist/dev/index.d.ts +20 -0
- package/dist/dev/index.js +51 -0
- package/dist/dev/index.js.map +1 -0
- package/dist/dev/index.mjs +49 -0
- package/dist/dev/index.mjs.map +1 -0
- package/dist/device/index.d.mts +108 -0
- package/dist/device/index.d.ts +108 -0
- package/dist/device/index.js +960 -0
- package/dist/device/index.js.map +1 -0
- package/dist/device/index.mjs +951 -0
- package/dist/device/index.mjs.map +1 -0
- package/dist/differential-privacy-BcAv1G80.d.mts +210 -0
- package/dist/differential-privacy-C8mAUjZr.d.ts +210 -0
- package/dist/encryption/index.d.mts +75 -0
- package/dist/encryption/index.d.ts +75 -0
- package/dist/encryption/index.js +605 -0
- package/dist/encryption/index.js.map +1 -0
- package/dist/encryption/index.mjs +598 -0
- package/dist/encryption/index.mjs.map +1 -0
- package/dist/form-validator-3tkmzr_o.d.mts +72 -0
- package/dist/form-validator-3tkmzr_o.d.ts +72 -0
- package/dist/forms/index.d.mts +59 -0
- package/dist/forms/index.d.ts +59 -0
- package/dist/forms/index.js +446 -0
- package/dist/forms/index.js.map +1 -0
- package/dist/forms/index.mjs +442 -0
- package/dist/forms/index.mjs.map +1 -0
- package/dist/i18n/index.d.mts +37 -0
- package/dist/i18n/index.d.ts +37 -0
- package/dist/i18n/index.js +147 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/index.mjs +145 -0
- package/dist/i18n/index.mjs.map +1 -0
- package/dist/idempotency.service-_6LqhivP.d.mts +372 -0
- package/dist/idempotency.service-eOKoISRD.d.ts +372 -0
- package/dist/index-B_ksKpS1.d.mts +202 -0
- package/dist/index-CqDKWTUP.d.mts +28 -0
- package/dist/index-CqDKWTUP.d.ts +28 -0
- package/dist/index-DFqEoX_l.d.ts +202 -0
- package/dist/index-Dz0gOur2.d.mts +36 -0
- package/dist/index-Dz0gOur2.d.ts +36 -0
- package/dist/index.d.mts +1336 -0
- package/dist/index.d.ts +1336 -0
- package/dist/index.js +19464 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +19155 -0
- package/dist/index.mjs.map +1 -0
- package/dist/india/index.d.mts +75 -0
- package/dist/india/index.d.ts +75 -0
- package/dist/india/index.js +325 -0
- package/dist/india/index.js.map +1 -0
- package/dist/india/index.mjs +303 -0
- package/dist/india/index.mjs.map +1 -0
- package/dist/joop-Bx7Iwj5p.d.mts +155 -0
- package/dist/joop-CA3DMeOO.d.ts +155 -0
- package/dist/native-bridge/index.d.mts +27 -0
- package/dist/native-bridge/index.d.ts +27 -0
- package/dist/native-bridge/index.js +98 -0
- package/dist/native-bridge/index.js.map +1 -0
- package/dist/native-bridge/index.mjs +96 -0
- package/dist/native-bridge/index.mjs.map +1 -0
- package/dist/network/index.d.mts +85 -0
- package/dist/network/index.d.ts +85 -0
- package/dist/network/index.js +454 -0
- package/dist/network/index.js.map +1 -0
- package/dist/network/index.mjs +451 -0
- package/dist/network/index.mjs.map +1 -0
- package/dist/network-monitor-BIwPSXme.d.mts +179 -0
- package/dist/network-monitor-Bqp2hvZr.d.ts +179 -0
- package/dist/notification.service-Dm4fvfZf.d.mts +25 -0
- package/dist/notification.service-tEMKatWJ.d.ts +25 -0
- package/dist/observability/index.d.mts +179 -0
- package/dist/observability/index.d.ts +179 -0
- package/dist/observability/index.js +559 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/index.mjs +552 -0
- package/dist/observability/index.mjs.map +1 -0
- package/dist/oidc-client-DIJcClmB.d.mts +190 -0
- package/dist/oidc-client-DxhyE59t.d.ts +190 -0
- package/dist/platform/index.d.mts +73 -0
- package/dist/platform/index.d.ts +73 -0
- package/dist/platform/index.js +127 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/index.mjs +125 -0
- package/dist/platform/index.mjs.map +1 -0
- package/dist/pwa/index.d.mts +31 -0
- package/dist/pwa/index.d.ts +31 -0
- package/dist/pwa/index.js +247 -0
- package/dist/pwa/index.js.map +1 -0
- package/dist/pwa/index.mjs +244 -0
- package/dist/pwa/index.mjs.map +1 -0
- package/dist/react/index.d.mts +133 -0
- package/dist/react/index.d.ts +133 -0
- package/dist/react/index.js +632 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/index.mjs +630 -0
- package/dist/react/index.mjs.map +1 -0
- package/dist/router/index.d.mts +39 -0
- package/dist/router/index.d.ts +39 -0
- package/dist/router/index.js +168 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/index.mjs +166 -0
- package/dist/router/index.mjs.map +1 -0
- package/dist/security/index.d.mts +206 -0
- package/dist/security/index.d.ts +206 -0
- package/dist/security/index.js +1297 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/index.mjs +1285 -0
- package/dist/security/index.mjs.map +1 -0
- package/dist/session/index.d.mts +115 -0
- package/dist/session/index.d.ts +115 -0
- package/dist/session/index.js +297 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/index.mjs +292 -0
- package/dist/session/index.mjs.map +1 -0
- package/dist/state/index.d.mts +43 -0
- package/dist/state/index.d.ts +43 -0
- package/dist/state/index.js +156 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/index.mjs +152 -0
- package/dist/state/index.mjs.map +1 -0
- package/dist/statement-parser-BHQtXwCM.d.ts +260 -0
- package/dist/statement-parser-C2qNmb49.d.mts +260 -0
- package/dist/storage/index.d.mts +40 -0
- package/dist/storage/index.d.ts +40 -0
- package/dist/storage/index.js +256 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/index.mjs +252 -0
- package/dist/storage/index.mjs.map +1 -0
- package/dist/sync/index.d.mts +69 -0
- package/dist/sync/index.d.ts +69 -0
- package/dist/sync/index.js +330 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/index.mjs +323 -0
- package/dist/sync/index.mjs.map +1 -0
- package/dist/sync-engine-DCIMRG5s.d.ts +61 -0
- package/dist/sync-engine-DZqyKHkK.d.mts +61 -0
- package/dist/theme/index.d.mts +53 -0
- package/dist/theme/index.d.ts +53 -0
- package/dist/theme/index.js +169 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/index.mjs +167 -0
- package/dist/theme/index.mjs.map +1 -0
- package/dist/ui/index.d.mts +66 -0
- package/dist/ui/index.d.ts +66 -0
- package/dist/ui/index.js +811 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/index.mjs +803 -0
- package/dist/ui/index.mjs.map +1 -0
- package/dist/utilities/index.d.mts +199 -0
- package/dist/utilities/index.d.ts +199 -0
- package/dist/utilities/index.js +1991 -0
- package/dist/utilities/index.js.map +1 -0
- package/dist/utilities/index.mjs +1923 -0
- package/dist/utilities/index.mjs.map +1 -0
- package/dist/validation/index.d.mts +60 -0
- package/dist/validation/index.d.ts +60 -0
- package/dist/validation/index.js +460 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/index.mjs +455 -0
- package/dist/validation/index.mjs.map +1 -0
- package/dist/vue/index.d.mts +135 -0
- package/dist/vue/index.d.ts +135 -0
- package/dist/vue/index.js +621 -0
- package/dist/vue/index.js.map +1 -0
- package/dist/vue/index.mjs +619 -0
- package/dist/vue/index.mjs.map +1 -0
- package/dist/watermark.service-Detur5tq.d.ts +235 -0
- package/dist/watermark.service-QNegMeQZ.d.mts +235 -0
- package/dist/workers/index.d.mts +42 -0
- package/dist/workers/index.d.ts +42 -0
- package/dist/workers/index.js +359 -0
- package/dist/workers/index.js.map +1 -0
- package/dist/workers/index.mjs +356 -0
- package/dist/workers/index.mjs.map +1 -0
- package/dist/workflow/index.d.mts +99 -0
- package/dist/workflow/index.d.ts +99 -0
- package/dist/workflow/index.js +282 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow/index.mjs +279 -0
- package/dist/workflow/index.mjs.map +1 -0
- package/package.json +226 -0
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
// src/banking/iban.utility.ts
|
|
2
|
+
var IBAN_LENGTHS = {
|
|
3
|
+
AL: 28,
|
|
4
|
+
AD: 24,
|
|
5
|
+
AE: 23,
|
|
6
|
+
AT: 20,
|
|
7
|
+
AZ: 28,
|
|
8
|
+
BA: 20,
|
|
9
|
+
BE: 16,
|
|
10
|
+
BG: 22,
|
|
11
|
+
BH: 22,
|
|
12
|
+
BR: 29,
|
|
13
|
+
BY: 28,
|
|
14
|
+
CH: 21,
|
|
15
|
+
CR: 22,
|
|
16
|
+
CY: 28,
|
|
17
|
+
CZ: 24,
|
|
18
|
+
DE: 22,
|
|
19
|
+
DK: 18,
|
|
20
|
+
DO: 28,
|
|
21
|
+
EE: 20,
|
|
22
|
+
EG: 29,
|
|
23
|
+
ES: 24,
|
|
24
|
+
FI: 18,
|
|
25
|
+
FO: 18,
|
|
26
|
+
FR: 27,
|
|
27
|
+
GB: 22,
|
|
28
|
+
GE: 22,
|
|
29
|
+
GI: 23,
|
|
30
|
+
GL: 18,
|
|
31
|
+
GR: 27,
|
|
32
|
+
GT: 28,
|
|
33
|
+
HR: 21,
|
|
34
|
+
HU: 28,
|
|
35
|
+
IE: 22,
|
|
36
|
+
IL: 23,
|
|
37
|
+
IQ: 23,
|
|
38
|
+
IS: 26,
|
|
39
|
+
IT: 27,
|
|
40
|
+
JO: 30,
|
|
41
|
+
KW: 30,
|
|
42
|
+
KZ: 20,
|
|
43
|
+
LB: 28,
|
|
44
|
+
LC: 32,
|
|
45
|
+
LI: 21,
|
|
46
|
+
LT: 20,
|
|
47
|
+
LU: 20,
|
|
48
|
+
LV: 21,
|
|
49
|
+
LY: 25,
|
|
50
|
+
MC: 27,
|
|
51
|
+
MD: 24,
|
|
52
|
+
ME: 22,
|
|
53
|
+
MK: 19,
|
|
54
|
+
MR: 27,
|
|
55
|
+
MT: 31,
|
|
56
|
+
MU: 30,
|
|
57
|
+
NL: 18,
|
|
58
|
+
NO: 15,
|
|
59
|
+
PK: 24,
|
|
60
|
+
PL: 28,
|
|
61
|
+
PS: 29,
|
|
62
|
+
PT: 25,
|
|
63
|
+
QA: 29,
|
|
64
|
+
RO: 24,
|
|
65
|
+
RS: 22,
|
|
66
|
+
SA: 24,
|
|
67
|
+
SC: 31,
|
|
68
|
+
SD: 18,
|
|
69
|
+
SE: 24,
|
|
70
|
+
SI: 19,
|
|
71
|
+
SK: 24,
|
|
72
|
+
SM: 27,
|
|
73
|
+
ST: 25,
|
|
74
|
+
SV: 28,
|
|
75
|
+
TL: 23,
|
|
76
|
+
TN: 24,
|
|
77
|
+
TR: 26,
|
|
78
|
+
UA: 29,
|
|
79
|
+
VA: 22,
|
|
80
|
+
VG: 24,
|
|
81
|
+
XK: 20
|
|
82
|
+
};
|
|
83
|
+
function validateIban(iban) {
|
|
84
|
+
const clean = iban.replace(/\s/g, "").toUpperCase();
|
|
85
|
+
const country = clean.slice(0, 2);
|
|
86
|
+
if (!IBAN_LENGTHS[country] || clean.length !== IBAN_LENGTHS[country]) return false;
|
|
87
|
+
const numeric = (clean.slice(4) + clean.slice(0, 4)).split("").map((c) => c.charCodeAt(0) >= 65 ? (c.charCodeAt(0) - 55).toString() : c).join("");
|
|
88
|
+
let remainder = 0;
|
|
89
|
+
for (const ch of numeric) remainder = (remainder * 10 + parseInt(ch)) % 97;
|
|
90
|
+
return remainder === 1;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/banking/luhn.utility.ts
|
|
94
|
+
var CARD_PATTERNS = [
|
|
95
|
+
{ network: "amex", pattern: /^3[47]/, lengths: [15], cvvLength: 4 },
|
|
96
|
+
{ network: "diners", pattern: /^3(?:0[0-5]|[68])/, lengths: [14], cvvLength: 3 },
|
|
97
|
+
{ network: "discover", pattern: /^6(?:011|5[0-9]{2})/, lengths: [16], cvvLength: 3 },
|
|
98
|
+
{ network: "jcb", pattern: /^(?:2131|1800|35)/, lengths: [16], cvvLength: 3 },
|
|
99
|
+
{ network: "maestro", pattern: /^(?:5018|5020|5038|6304|6759|676[1-3])/, lengths: [12, 13, 14, 15, 16, 17, 18, 19], cvvLength: 3 },
|
|
100
|
+
{ network: "mastercard", pattern: /^5[1-5]|^2[2-7]/, lengths: [16], cvvLength: 3 },
|
|
101
|
+
{ network: "unionpay", pattern: /^62/, lengths: [16, 17, 18, 19], cvvLength: 3 },
|
|
102
|
+
{ network: "visa", pattern: /^4/, lengths: [13, 16, 19], cvvLength: 3 }
|
|
103
|
+
];
|
|
104
|
+
function validateLuhn(cardNumber) {
|
|
105
|
+
const digits = cardNumber.replace(/\D/g, "");
|
|
106
|
+
if (digits.length < 8) return false;
|
|
107
|
+
let sum = 0;
|
|
108
|
+
let double = false;
|
|
109
|
+
for (let i = digits.length - 1; i >= 0; i--) {
|
|
110
|
+
let d = parseInt(digits[i], 10);
|
|
111
|
+
if (double) {
|
|
112
|
+
d *= 2;
|
|
113
|
+
if (d > 9) d -= 9;
|
|
114
|
+
}
|
|
115
|
+
sum += d;
|
|
116
|
+
double = !double;
|
|
117
|
+
}
|
|
118
|
+
return sum % 10 === 0;
|
|
119
|
+
}
|
|
120
|
+
function getCardNetwork(cardNumber) {
|
|
121
|
+
const digits = cardNumber.replace(/\D/g, "");
|
|
122
|
+
for (const card of CARD_PATTERNS) {
|
|
123
|
+
if (card.pattern.test(digits)) return card.network;
|
|
124
|
+
}
|
|
125
|
+
return "unknown";
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// src/banking/amount.utility.ts
|
|
129
|
+
function isValidAmount(value) {
|
|
130
|
+
if (typeof value === "string") {
|
|
131
|
+
const clean = value.replace(/[,\s]/g, "");
|
|
132
|
+
return /^-?\d+(\.\d+)?$/.test(clean) && isFinite(parseFloat(clean));
|
|
133
|
+
}
|
|
134
|
+
return typeof value === "number" && isFinite(value);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// src/validation/form-validator.ts
|
|
138
|
+
var EMAIL_RE = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\.[a-zA-Z]{2,}$/;
|
|
139
|
+
var PHONE_RE = /^\+?[\d\s\-().]{7,20}$/;
|
|
140
|
+
var JoopFormValidator = class {
|
|
141
|
+
required(value) {
|
|
142
|
+
if (value == null || value === "" || Array.isArray(value) && value.length === 0) return "This field is required";
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
minLength(value, min) {
|
|
146
|
+
if (String(value ?? "").length < min) return `Minimum ${min} characters required`;
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
maxLength(value, max) {
|
|
150
|
+
if (String(value ?? "").length > max) return `Maximum ${max} characters allowed`;
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
min(value, min) {
|
|
154
|
+
if (Number(value) < min) return `Minimum value is ${min}`;
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
max(value, max) {
|
|
158
|
+
if (Number(value) > max) return `Maximum value is ${max}`;
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
email(value) {
|
|
162
|
+
if (!EMAIL_RE.test(String(value ?? ""))) return "Invalid email address";
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
phone(value) {
|
|
166
|
+
if (!PHONE_RE.test(String(value ?? ""))) return "Invalid phone number";
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
iban(value) {
|
|
170
|
+
if (!validateIban(String(value ?? ""))) return "Invalid IBAN";
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
luhn(value) {
|
|
174
|
+
const digits = String(value ?? "").replace(/\D/g, "");
|
|
175
|
+
if (!validateLuhn(digits)) return "Invalid card number";
|
|
176
|
+
const network = getCardNetwork(digits);
|
|
177
|
+
if (network === "unknown") return "Unrecognised card type";
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
amount(value, min, max) {
|
|
181
|
+
if (!isValidAmount(value)) return "Invalid amount";
|
|
182
|
+
const n = Number(value);
|
|
183
|
+
if (min !== void 0 && n < min) return `Minimum amount is ${min}`;
|
|
184
|
+
if (max !== void 0 && n > max) return `Maximum amount is ${max}`;
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
pattern(value, regex, message) {
|
|
188
|
+
if (!regex.test(String(value ?? ""))) return message ?? "Invalid format";
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
dateRange(start, end, maxDays, minDate, maxDate) {
|
|
192
|
+
if (start > end) return "Start date must be before end date";
|
|
193
|
+
if (minDate && start < minDate) return `Start date cannot be before ${minDate.toLocaleDateString()}`;
|
|
194
|
+
if (maxDate && end > maxDate) return `End date cannot be after ${maxDate.toLocaleDateString()}`;
|
|
195
|
+
if (maxDays) {
|
|
196
|
+
const days = Math.ceil((end.getTime() - start.getTime()) / 864e5);
|
|
197
|
+
if (days > maxDays) return `Date range cannot exceed ${maxDays} days`;
|
|
198
|
+
}
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
passwordStrength(password) {
|
|
202
|
+
const suggestions = [];
|
|
203
|
+
let score = 0;
|
|
204
|
+
if (password.length >= 8) score++;
|
|
205
|
+
else suggestions.push("Use at least 8 characters");
|
|
206
|
+
if (password.length >= 12) score++;
|
|
207
|
+
if (/[A-Z]/.test(password)) score++;
|
|
208
|
+
else suggestions.push("Add uppercase letters");
|
|
209
|
+
if (/[0-9]/.test(password)) score++;
|
|
210
|
+
else suggestions.push("Add numbers");
|
|
211
|
+
if (/[^A-Za-z0-9]/.test(password)) score++;
|
|
212
|
+
else suggestions.push("Add special characters");
|
|
213
|
+
if (/(.)\1{2,}/.test(password)) {
|
|
214
|
+
score--;
|
|
215
|
+
suggestions.push("Avoid repeating characters");
|
|
216
|
+
}
|
|
217
|
+
score = Math.max(0, Math.min(4, score));
|
|
218
|
+
const labels = ["very-weak", "weak", "fair", "strong", "very-strong"];
|
|
219
|
+
return { score, label: labels[score], suggestions };
|
|
220
|
+
}
|
|
221
|
+
/** Validate a single value against multiple rules */
|
|
222
|
+
validate(value, rules) {
|
|
223
|
+
const errors = [];
|
|
224
|
+
for (const rule of rules) {
|
|
225
|
+
let err = null;
|
|
226
|
+
switch (rule.type) {
|
|
227
|
+
case "required":
|
|
228
|
+
err = this.required(value);
|
|
229
|
+
break;
|
|
230
|
+
case "minLength":
|
|
231
|
+
err = this.minLength(String(value ?? ""), rule.min);
|
|
232
|
+
break;
|
|
233
|
+
case "maxLength":
|
|
234
|
+
err = this.maxLength(String(value ?? ""), rule.max);
|
|
235
|
+
break;
|
|
236
|
+
case "min":
|
|
237
|
+
err = this.min(value, rule.min);
|
|
238
|
+
break;
|
|
239
|
+
case "max":
|
|
240
|
+
err = this.max(value, rule.max);
|
|
241
|
+
break;
|
|
242
|
+
case "email":
|
|
243
|
+
err = this.email(String(value ?? ""));
|
|
244
|
+
break;
|
|
245
|
+
case "phone":
|
|
246
|
+
err = this.phone(String(value ?? ""));
|
|
247
|
+
break;
|
|
248
|
+
case "iban":
|
|
249
|
+
err = this.iban(String(value ?? ""));
|
|
250
|
+
break;
|
|
251
|
+
case "luhn":
|
|
252
|
+
err = this.luhn(String(value ?? ""));
|
|
253
|
+
break;
|
|
254
|
+
case "amount":
|
|
255
|
+
err = this.amount(value, rule.min, rule.max);
|
|
256
|
+
break;
|
|
257
|
+
case "pattern":
|
|
258
|
+
err = this.pattern(String(value ?? ""), rule.regex, rule.message);
|
|
259
|
+
break;
|
|
260
|
+
case "custom":
|
|
261
|
+
err = rule.validate(value);
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
if (err) errors.push(err);
|
|
265
|
+
}
|
|
266
|
+
return { valid: errors.length === 0, errors };
|
|
267
|
+
}
|
|
268
|
+
/** Validate an entire form object against a schema */
|
|
269
|
+
validateForm(form, schema) {
|
|
270
|
+
const errors = {};
|
|
271
|
+
for (const field of Object.keys(schema)) {
|
|
272
|
+
const result = this.validate(form[field], schema[field]);
|
|
273
|
+
if (!result.valid) errors[field] = result.errors;
|
|
274
|
+
}
|
|
275
|
+
return errors;
|
|
276
|
+
}
|
|
277
|
+
isFormValid(errors) {
|
|
278
|
+
return Object.keys(errors).length === 0;
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
// src/validation/password-rules.ts
|
|
283
|
+
var passwordRules = {
|
|
284
|
+
minLength: (n) => ({
|
|
285
|
+
id: `minLength:${n}`,
|
|
286
|
+
label: `At least ${n} characters`,
|
|
287
|
+
required: true,
|
|
288
|
+
test: (pw) => pw.length >= n
|
|
289
|
+
}),
|
|
290
|
+
maxLength: (n) => ({
|
|
291
|
+
id: `maxLength:${n}`,
|
|
292
|
+
label: `No more than ${n} characters`,
|
|
293
|
+
required: true,
|
|
294
|
+
test: (pw) => pw.length <= n
|
|
295
|
+
}),
|
|
296
|
+
uppercase: (n = 1) => ({
|
|
297
|
+
id: `uppercase:${n}`,
|
|
298
|
+
label: `At least ${n} uppercase letter${n > 1 ? "s" : ""}`,
|
|
299
|
+
required: true,
|
|
300
|
+
test: (pw) => (pw.match(/[A-Z]/g)?.length ?? 0) >= n
|
|
301
|
+
}),
|
|
302
|
+
lowercase: (n = 1) => ({
|
|
303
|
+
id: `lowercase:${n}`,
|
|
304
|
+
label: `At least ${n} lowercase letter${n > 1 ? "s" : ""}`,
|
|
305
|
+
required: true,
|
|
306
|
+
test: (pw) => (pw.match(/[a-z]/g)?.length ?? 0) >= n
|
|
307
|
+
}),
|
|
308
|
+
digit: (n = 1) => ({
|
|
309
|
+
id: `digit:${n}`,
|
|
310
|
+
label: `At least ${n} digit${n > 1 ? "s" : ""}`,
|
|
311
|
+
required: true,
|
|
312
|
+
test: (pw) => (pw.match(/[0-9]/g)?.length ?? 0) >= n
|
|
313
|
+
}),
|
|
314
|
+
special: (n = 1, chars = "!@#$%^&*()_+-=[]{}|;':\",.<>?/`~\\") => ({
|
|
315
|
+
id: `special:${n}`,
|
|
316
|
+
label: `At least ${n} special character${n > 1 ? "s" : ""}`,
|
|
317
|
+
required: true,
|
|
318
|
+
test: (pw) => pw.split("").filter((c) => chars.includes(c)).length >= n
|
|
319
|
+
}),
|
|
320
|
+
noSpaces: () => ({
|
|
321
|
+
id: "noSpaces",
|
|
322
|
+
label: "No spaces allowed",
|
|
323
|
+
required: true,
|
|
324
|
+
test: (pw) => !/\s/.test(pw)
|
|
325
|
+
}),
|
|
326
|
+
noRepeatingChars: (n = 3) => ({
|
|
327
|
+
id: `noRepeating:${n}`,
|
|
328
|
+
label: `No ${n}+ consecutive identical characters`,
|
|
329
|
+
required: false,
|
|
330
|
+
test: (pw) => !new RegExp(`(.)\\1{${n - 1},}`).test(pw)
|
|
331
|
+
}),
|
|
332
|
+
noSequential: () => ({
|
|
333
|
+
id: "noSequential",
|
|
334
|
+
label: "No sequential characters (abc, 123)",
|
|
335
|
+
required: false,
|
|
336
|
+
test: (pw) => {
|
|
337
|
+
const s = pw.toLowerCase();
|
|
338
|
+
for (let i = 0; i < s.length - 2; i++) {
|
|
339
|
+
const a = s.charCodeAt(i), b = s.charCodeAt(i + 1), c = s.charCodeAt(i + 2);
|
|
340
|
+
if (b === a + 1 && c === a + 2) return false;
|
|
341
|
+
}
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
}),
|
|
345
|
+
noCommonWords: (list) => {
|
|
346
|
+
const common = list ?? ["password", "123456", "qwerty", "letmein", "admin", "welcome", "monkey", "dragon"];
|
|
347
|
+
return {
|
|
348
|
+
id: "noCommonWords",
|
|
349
|
+
label: "Not a common password",
|
|
350
|
+
required: false,
|
|
351
|
+
test: (pw) => !common.includes(pw.toLowerCase())
|
|
352
|
+
};
|
|
353
|
+
},
|
|
354
|
+
matchesPattern: (pattern, label) => ({
|
|
355
|
+
id: `pattern:${pattern.source}`,
|
|
356
|
+
label,
|
|
357
|
+
required: true,
|
|
358
|
+
test: (pw) => pattern.test(pw)
|
|
359
|
+
})
|
|
360
|
+
};
|
|
361
|
+
var passwordRuleSets = {
|
|
362
|
+
/** Basic: 8+ chars, 1 uppercase, 1 digit */
|
|
363
|
+
basic: () => ({
|
|
364
|
+
name: "basic",
|
|
365
|
+
rules: [
|
|
366
|
+
passwordRules.minLength(8),
|
|
367
|
+
passwordRules.uppercase(),
|
|
368
|
+
passwordRules.digit()
|
|
369
|
+
]
|
|
370
|
+
}),
|
|
371
|
+
/** Standard: 10+ chars, upper, lower, digit, special */
|
|
372
|
+
standard: () => ({
|
|
373
|
+
name: "standard",
|
|
374
|
+
rules: [
|
|
375
|
+
passwordRules.minLength(10),
|
|
376
|
+
passwordRules.uppercase(),
|
|
377
|
+
passwordRules.lowercase(),
|
|
378
|
+
passwordRules.digit(),
|
|
379
|
+
passwordRules.special(),
|
|
380
|
+
passwordRules.noSpaces()
|
|
381
|
+
]
|
|
382
|
+
}),
|
|
383
|
+
/** Banking: strict 12+ chars, 2 uppercase, 2 digits, 2 special, no repeats */
|
|
384
|
+
banking: () => ({
|
|
385
|
+
name: "banking",
|
|
386
|
+
rules: [
|
|
387
|
+
passwordRules.minLength(12),
|
|
388
|
+
passwordRules.maxLength(64),
|
|
389
|
+
passwordRules.uppercase(2),
|
|
390
|
+
passwordRules.lowercase(2),
|
|
391
|
+
passwordRules.digit(2),
|
|
392
|
+
passwordRules.special(2),
|
|
393
|
+
passwordRules.noSpaces(),
|
|
394
|
+
passwordRules.noRepeatingChars(3),
|
|
395
|
+
passwordRules.noSequential(),
|
|
396
|
+
passwordRules.noCommonWords()
|
|
397
|
+
]
|
|
398
|
+
}),
|
|
399
|
+
/** PIN: exactly N digits */
|
|
400
|
+
pin: (length = 6) => ({
|
|
401
|
+
name: "pin",
|
|
402
|
+
rules: [
|
|
403
|
+
passwordRules.matchesPattern(new RegExp(`^\\d{${length}}$`), `Exactly ${length} digits`),
|
|
404
|
+
passwordRules.noRepeatingChars(length)
|
|
405
|
+
]
|
|
406
|
+
})
|
|
407
|
+
};
|
|
408
|
+
var JoopPasswordRulesValidator = class {
|
|
409
|
+
_ruleSet;
|
|
410
|
+
constructor(ruleSet) {
|
|
411
|
+
this._ruleSet = ruleSet;
|
|
412
|
+
}
|
|
413
|
+
validate(password) {
|
|
414
|
+
const passed = [];
|
|
415
|
+
const failed = [];
|
|
416
|
+
const failedLabels = [];
|
|
417
|
+
for (const rule of this._ruleSet.rules) {
|
|
418
|
+
if (rule.test(password)) {
|
|
419
|
+
passed.push(rule.id);
|
|
420
|
+
} else {
|
|
421
|
+
failed.push(rule.id);
|
|
422
|
+
failedLabels.push(rule.label);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
const requiredFailed = this._ruleSet.rules.filter((r) => r.required !== false && !passed.includes(r.id));
|
|
426
|
+
const valid = requiredFailed.length === 0;
|
|
427
|
+
const total = this._ruleSet.rules.length;
|
|
428
|
+
const score = total > 0 ? Math.round(passed.length / total * 100) : 0;
|
|
429
|
+
return {
|
|
430
|
+
valid,
|
|
431
|
+
score,
|
|
432
|
+
strength: score < 40 ? "weak" : score < 65 ? "fair" : score < 85 ? "strong" : "very-strong",
|
|
433
|
+
passed,
|
|
434
|
+
failed,
|
|
435
|
+
failedLabels
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
/** Check a single rule by ID */
|
|
439
|
+
checkRule(password, ruleId) {
|
|
440
|
+
const rule = this._ruleSet.rules.find((r) => r.id === ruleId);
|
|
441
|
+
return rule ? rule.test(password) : false;
|
|
442
|
+
}
|
|
443
|
+
/** Get all rules with their current pass/fail state */
|
|
444
|
+
getRuleStates(password) {
|
|
445
|
+
return this._ruleSet.rules.map((rule) => ({ rule, passed: rule.test(password) }));
|
|
446
|
+
}
|
|
447
|
+
/** Swap the rule set at runtime */
|
|
448
|
+
setRuleSet(ruleSet) {
|
|
449
|
+
this._ruleSet = ruleSet;
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
export { JoopFormValidator, JoopPasswordRulesValidator, passwordRuleSets, passwordRules };
|
|
454
|
+
//# sourceMappingURL=index.mjs.map
|
|
455
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/banking/iban.utility.ts","../../src/banking/luhn.utility.ts","../../src/banking/amount.utility.ts","../../src/validation/form-validator.ts","../../src/validation/password-rules.ts"],"names":[],"mappings":";AAAA,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,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,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,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,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,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,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,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,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,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EA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","file":"index.mjs","sourcesContent":["const IBAN_LENGTHS: Record<string, number> = {\n AL: 28, AD: 24, AE: 23, AT: 20, AZ: 28, BA: 20, BE: 16, BG: 22, BH: 22,\n BR: 29, BY: 28, CH: 21, CR: 22, CY: 28, CZ: 24, DE: 22, DK: 18, DO: 28,\n EE: 20, EG: 29, ES: 24, FI: 18, FO: 18, FR: 27, GB: 22, GE: 22, GI: 23,\n GL: 18, GR: 27, GT: 28, HR: 21, HU: 28, IE: 22, IL: 23, IQ: 23, IS: 26,\n IT: 27, JO: 30, KW: 30, KZ: 20, LB: 28, LC: 32, LI: 21, LT: 20, LU: 20,\n LV: 21, LY: 25, MC: 27, MD: 24, ME: 22, MK: 19, MR: 27, MT: 31, MU: 30,\n NL: 18, NO: 15, PK: 24, PL: 28, PS: 29, PT: 25, QA: 29, RO: 24, RS: 22,\n SA: 24, SC: 31, SD: 18, SE: 24, SI: 19, SK: 24, SM: 27, ST: 25, SV: 28,\n TL: 23, TN: 24, TR: 26, UA: 29, VA: 22, VG: 24, XK: 20,\n};\n\nexport function validateIban(iban: string): boolean {\n const clean = iban.replace(/\\s/g, '').toUpperCase();\n const country = clean.slice(0, 2);\n if (!IBAN_LENGTHS[country] || clean.length !== IBAN_LENGTHS[country]) return false;\n\n const numeric = (clean.slice(4) + clean.slice(0, 4))\n .split('')\n .map(c => c.charCodeAt(0) >= 65 ? (c.charCodeAt(0) - 55).toString() : c)\n .join('');\n\n let remainder = 0;\n for (const ch of numeric) remainder = (remainder * 10 + parseInt(ch)) % 97;\n return remainder === 1;\n}\n\nexport function formatIban(iban: string): string {\n return iban.replace(/\\s/g, '').toUpperCase().replace(/(.{4})/g, '$1 ').trim();\n}\n\nexport function getIbanCountry(iban: string): string {\n return iban.replace(/\\s/g, '').toUpperCase().slice(0, 2);\n}\n\nexport function parseIban(iban: string): { country: string; checkDigits: string; bban: string } | null {\n const clean = iban.replace(/\\s/g, '').toUpperCase();\n if (!validateIban(clean)) return null;\n return { country: clean.slice(0, 2), checkDigits: clean.slice(2, 4), bban: clean.slice(4) };\n}\n\nexport function getSupportedIbanCountries(): string[] {\n return Object.keys(IBAN_LENGTHS).sort();\n}\n","// ── Luhn algorithm & card type detection ──────────────────────────────────\n\nexport type JoopCardNetwork = 'visa' | 'mastercard' | 'amex' | 'discover' | 'unionpay' | 'jcb' | 'diners' | 'maestro' | 'unknown';\n\nexport interface JoopCardInfo {\n network: JoopCardNetwork;\n valid: boolean;\n lengths: number[];\n cvvLength: number;\n formatted: string;\n}\n\nconst CARD_PATTERNS: Array<{ network: JoopCardNetwork; pattern: RegExp; lengths: number[]; cvvLength: number }> = [\n { network: 'amex', pattern: /^3[47]/, lengths: [15], cvvLength: 4 },\n { network: 'diners', pattern: /^3(?:0[0-5]|[68])/, lengths: [14], cvvLength: 3 },\n { network: 'discover', pattern: /^6(?:011|5[0-9]{2})/, lengths: [16], cvvLength: 3 },\n { network: 'jcb', pattern: /^(?:2131|1800|35)/, lengths: [16], cvvLength: 3 },\n { network: 'maestro', pattern: /^(?:5018|5020|5038|6304|6759|676[1-3])/, lengths: [12,13,14,15,16,17,18,19], cvvLength: 3 },\n { network: 'mastercard', pattern: /^5[1-5]|^2[2-7]/, lengths: [16], cvvLength: 3 },\n { network: 'unionpay', pattern: /^62/, lengths: [16,17,18,19], cvvLength: 3 },\n { network: 'visa', pattern: /^4/, lengths: [13,16,19], cvvLength: 3 },\n];\n\n/** Validate a card number using the Luhn algorithm */\nexport function validateLuhn(cardNumber: string): boolean {\n const digits = cardNumber.replace(/\\D/g, '');\n if (digits.length < 8) return false;\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = parseInt(digits[i], 10);\n if (double) { d *= 2; if (d > 9) d -= 9; }\n sum += d;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\n/** Compute the Luhn check digit for a partial card number */\nexport function luhnCheckDigit(partial: string): number {\n const digits = partial.replace(/\\D/g, '');\n let sum = 0;\n let double = true;\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = parseInt(digits[i], 10);\n if (double) { d *= 2; if (d > 9) d -= 9; }\n sum += d;\n double = !double;\n }\n return (10 - (sum % 10)) % 10;\n}\n\n/** Detect the card network from the card number prefix */\nexport function getCardNetwork(cardNumber: string): JoopCardNetwork {\n const digits = cardNumber.replace(/\\D/g, '');\n for (const card of CARD_PATTERNS) {\n if (card.pattern.test(digits)) return card.network;\n }\n return 'unknown';\n}\n\n/** Get full card validation info */\nexport function getCardInfo(cardNumber: string): JoopCardInfo {\n const digits = cardNumber.replace(/\\D/g, '');\n const match = CARD_PATTERNS.find(c => c.pattern.test(digits));\n const network = match?.network ?? 'unknown';\n const lengths = match?.lengths ?? [13, 14, 15, 16, 19];\n const cvvLength = match?.cvvLength ?? 3;\n const valid = lengths.includes(digits.length) && validateLuhn(digits);\n const formatted = formatCardNumber(digits);\n return { network, valid, lengths, cvvLength, formatted };\n}\n\n/** Format card number with spaces (e.g. 4111 1111 1111 1111 or 3714 496353 98431 for Amex) */\nexport function formatCardNumber(cardNumber: string): string {\n const digits = cardNumber.replace(/\\D/g, '');\n const network = getCardNetwork(digits);\n if (network === 'amex') {\n return digits.replace(/^(\\d{4})(\\d{6})(\\d{5})$/, '$1 $2 $3');\n }\n if (network === 'diners') {\n return digits.replace(/^(\\d{4})(\\d{6})(\\d{4})$/, '$1 $2 $3');\n }\n return digits.replace(/(\\d{4})(?=\\d)/g, '$1 ');\n}\n\n/** Validate card expiry (MM/YY or MM/YYYY) */\nexport function isCardExpired(month: number | string, year: number | string): boolean {\n const m = parseInt(String(month), 10);\n let y = parseInt(String(year), 10);\n if (y < 100) y += 2000;\n const now = new Date();\n const expiry = new Date(y, m - 1, 1);\n expiry.setMonth(expiry.getMonth() + 1); // expire at end of month\n return expiry <= now;\n}\n\n/** Validate a CVV/CVC value */\nexport function validateCvv(cvv: string, network: JoopCardNetwork = 'unknown'): boolean {\n const digits = cvv.replace(/\\D/g, '');\n const expectedLength = network === 'amex' ? 4 : 3;\n return digits.length === expectedLength;\n}\n","export function safeAdd(a: number, b: number, decimals = 2): number {\n const f = Math.pow(10, decimals);\n return (Math.round(a * f) + Math.round(b * f)) / f;\n}\n\nexport function safeSubtract(a: number, b: number, decimals = 2): number {\n const f = Math.pow(10, decimals);\n return (Math.round(a * f) - Math.round(b * f)) / f;\n}\n\nexport function safeMultiply(a: number, b: number, decimals = 2): number {\n return parseFloat((a * b).toFixed(decimals));\n}\n\nexport function safeDivide(a: number, b: number, decimals = 2): number {\n if (b === 0) throw new Error('Division by zero');\n return parseFloat((a / b).toFixed(decimals));\n}\n\nexport function roundAmount(amount: number, decimals = 2): number {\n const f = Math.pow(10, decimals);\n return Math.round(amount * f) / f;\n}\n\nexport function isValidAmount(value: unknown): boolean {\n if (typeof value === 'string') {\n const clean = value.replace(/[,\\s]/g, '');\n return /^-?\\d+(\\.\\d+)?$/.test(clean) && isFinite(parseFloat(clean));\n }\n return typeof value === 'number' && isFinite(value);\n}\n\nexport function clampAmount(amount: number, min: number, max: number): number {\n return Math.min(Math.max(amount, min), max);\n}\n\nexport function toMinorUnits(amount: number, decimalPlaces = 2): number {\n return Math.round(amount * Math.pow(10, decimalPlaces));\n}\n\nexport function fromMinorUnits(amount: number, decimalPlaces = 2): number {\n return amount / Math.pow(10, decimalPlaces);\n}\n\nexport function sumAmounts(...amounts: number[]): number {\n const f = 100;\n return amounts.reduce((acc, a) => acc + Math.round(a * f), 0) / f;\n}\n","import { validateIban } from '../banking/iban.utility';\nimport { validateLuhn, getCardNetwork } from '../banking/luhn.utility';\nimport { isValidAmount } from '../banking/amount.utility';\n\nexport type JoopValidationRule =\n | { type: 'required' }\n | { type: 'minLength'; min: number }\n | { type: 'maxLength'; max: number }\n | { type: 'min'; min: number }\n | { type: 'max'; max: number }\n | { type: 'pattern'; regex: RegExp; message?: string }\n | { type: 'email' }\n | { type: 'phone' }\n | { type: 'iban' }\n | { type: 'luhn' }\n | { type: 'amount'; min?: number; max?: number }\n | { type: 'dateRange'; maxDays?: number; minDate?: Date; maxDate?: Date }\n | { type: 'custom'; validate: (v: unknown) => string | null };\n\nexport interface JoopValidationResult { valid: boolean; errors: string[]; }\nexport type JoopFormErrors = Record<string, string[]>;\nexport type JoopFormSchema = Record<string, JoopValidationRule[]>;\n\nexport interface JoopPasswordStrength {\n score: number; // 0–4\n label: 'very-weak' | 'weak' | 'fair' | 'strong' | 'very-strong';\n suggestions: string[];\n}\n\nconst EMAIL_RE = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\\.[a-zA-Z]{2,}$/;\nconst PHONE_RE = /^\\+?[\\d\\s\\-().]{7,20}$/;\n\nexport class JoopFormValidator {\n\n required(value: unknown): string | null {\n if (value == null || value === '' || (Array.isArray(value) && value.length === 0)) return 'This field is required';\n return null;\n }\n\n minLength(value: string, min: number): string | null {\n if (String(value ?? '').length < min) return `Minimum ${min} characters required`;\n return null;\n }\n\n maxLength(value: string, max: number): string | null {\n if (String(value ?? '').length > max) return `Maximum ${max} characters allowed`;\n return null;\n }\n\n min(value: number | string, min: number): string | null {\n if (Number(value) < min) return `Minimum value is ${min}`;\n return null;\n }\n\n max(value: number | string, max: number): string | null {\n if (Number(value) > max) return `Maximum value is ${max}`;\n return null;\n }\n\n email(value: string): string | null {\n if (!EMAIL_RE.test(String(value ?? ''))) return 'Invalid email address';\n return null;\n }\n\n phone(value: string): string | null {\n if (!PHONE_RE.test(String(value ?? ''))) return 'Invalid phone number';\n return null;\n }\n\n iban(value: string): string | null {\n if (!validateIban(String(value ?? ''))) return 'Invalid IBAN';\n return null;\n }\n\n luhn(value: string): string | null {\n const digits = String(value ?? '').replace(/\\D/g, '');\n if (!validateLuhn(digits)) return 'Invalid card number';\n const network = getCardNetwork(digits);\n if (network === 'unknown') return 'Unrecognised card type';\n return null;\n }\n\n amount(value: string | number, min?: number, max?: number): string | null {\n if (!isValidAmount(value)) return 'Invalid amount';\n const n = Number(value);\n if (min !== undefined && n < min) return `Minimum amount is ${min}`;\n if (max !== undefined && n > max) return `Maximum amount is ${max}`;\n return null;\n }\n\n pattern(value: string, regex: RegExp, message?: string): string | null {\n if (!regex.test(String(value ?? ''))) return message ?? 'Invalid format';\n return null;\n }\n\n dateRange(start: Date, end: Date, maxDays?: number, minDate?: Date, maxDate?: Date): string | null {\n if (start > end) return 'Start date must be before end date';\n if (minDate && start < minDate) return `Start date cannot be before ${minDate.toLocaleDateString()}`;\n if (maxDate && end > maxDate) return `End date cannot be after ${maxDate.toLocaleDateString()}`;\n if (maxDays) {\n const days = Math.ceil((end.getTime() - start.getTime()) / 86_400_000);\n if (days > maxDays) return `Date range cannot exceed ${maxDays} days`;\n }\n return null;\n }\n\n passwordStrength(password: string): JoopPasswordStrength {\n const suggestions: string[] = [];\n let score = 0;\n if (password.length >= 8) score++; else suggestions.push('Use at least 8 characters');\n if (password.length >= 12) score++;\n if (/[A-Z]/.test(password)) score++; else suggestions.push('Add uppercase letters');\n if (/[0-9]/.test(password)) score++; else suggestions.push('Add numbers');\n if (/[^A-Za-z0-9]/.test(password)) score++; else suggestions.push('Add special characters');\n if (/(.)\\1{2,}/.test(password)) { score--; suggestions.push('Avoid repeating characters'); }\n score = Math.max(0, Math.min(4, score));\n const labels: JoopPasswordStrength['label'][] = ['very-weak', 'weak', 'fair', 'strong', 'very-strong'];\n return { score, label: labels[score], suggestions };\n }\n\n /** Validate a single value against multiple rules */\n validate(value: unknown, rules: JoopValidationRule[]): JoopValidationResult {\n const errors: string[] = [];\n for (const rule of rules) {\n let err: string | null = null;\n switch (rule.type) {\n case 'required': err = this.required(value); break;\n case 'minLength': err = this.minLength(String(value ?? ''), rule.min); break;\n case 'maxLength': err = this.maxLength(String(value ?? ''), rule.max); break;\n case 'min': err = this.min(value as number, rule.min); break;\n case 'max': err = this.max(value as number, rule.max); break;\n case 'email': err = this.email(String(value ?? '')); break;\n case 'phone': err = this.phone(String(value ?? '')); break;\n case 'iban': err = this.iban(String(value ?? '')); break;\n case 'luhn': err = this.luhn(String(value ?? '')); break;\n case 'amount': err = this.amount(value as string, rule.min, rule.max); break;\n case 'pattern': err = this.pattern(String(value ?? ''), rule.regex, rule.message); break;\n case 'custom': err = rule.validate(value); break;\n }\n if (err) errors.push(err);\n }\n return { valid: errors.length === 0, errors };\n }\n\n /** Validate an entire form object against a schema */\n validateForm(form: Record<string, unknown>, schema: JoopFormSchema): JoopFormErrors {\n const errors: JoopFormErrors = {};\n for (const field of Object.keys(schema)) {\n const result = this.validate(form[field], schema[field]);\n if (!result.valid) errors[field] = result.errors;\n }\n return errors;\n }\n\n isFormValid(errors: JoopFormErrors): boolean {\n return Object.keys(errors).length === 0;\n }\n}\n","// Configurable password rule engine with named rule sets\n\nexport interface JoopPasswordRule {\n id: string;\n label: string;\n test: (password: string) => boolean;\n required?: boolean;\n}\n\nexport interface JoopPasswordRuleSet {\n name: string;\n rules: JoopPasswordRule[];\n minScore?: number; // minimum rules that must pass (default: all required rules)\n}\n\nexport interface JoopPasswordValidationResult {\n valid: boolean;\n score: number; // 0–100\n strength: 'weak' | 'fair' | 'strong' | 'very-strong';\n passed: string[]; // rule IDs that passed\n failed: string[]; // rule IDs that failed\n failedLabels: string[]; // human-readable failure messages\n}\n\n// ── Built-in rules ────────────────────────────────────────────────────────────\n\nexport const passwordRules = {\n minLength: (n: number): JoopPasswordRule => ({\n id: `minLength:${n}`, label: `At least ${n} characters`, required: true,\n test: pw => pw.length >= n,\n }),\n maxLength: (n: number): JoopPasswordRule => ({\n id: `maxLength:${n}`, label: `No more than ${n} characters`, required: true,\n test: pw => pw.length <= n,\n }),\n uppercase: (n = 1): JoopPasswordRule => ({\n id: `uppercase:${n}`, label: `At least ${n} uppercase letter${n>1?'s':''}`, required: true,\n test: pw => (pw.match(/[A-Z]/g)?.length ?? 0) >= n,\n }),\n lowercase: (n = 1): JoopPasswordRule => ({\n id: `lowercase:${n}`, label: `At least ${n} lowercase letter${n>1?'s':''}`, required: true,\n test: pw => (pw.match(/[a-z]/g)?.length ?? 0) >= n,\n }),\n digit: (n = 1): JoopPasswordRule => ({\n id: `digit:${n}`, label: `At least ${n} digit${n>1?'s':''}`, required: true,\n test: pw => (pw.match(/[0-9]/g)?.length ?? 0) >= n,\n }),\n special: (n = 1, chars = '!@#$%^&*()_+-=[]{}|;\\':\",.<>?/`~\\\\'): JoopPasswordRule => ({\n id: `special:${n}`, label: `At least ${n} special character${n>1?'s':''}`, required: true,\n test: pw => pw.split('').filter(c => chars.includes(c)).length >= n,\n }),\n noSpaces: (): JoopPasswordRule => ({\n id: 'noSpaces', label: 'No spaces allowed', required: true,\n test: pw => !/\\s/.test(pw),\n }),\n noRepeatingChars: (n = 3): JoopPasswordRule => ({\n id: `noRepeating:${n}`, label: `No ${n}+ consecutive identical characters`, required: false,\n test: pw => !new RegExp(`(.)\\\\1{${n-1},}`).test(pw),\n }),\n noSequential: (): JoopPasswordRule => ({\n id: 'noSequential', label: 'No sequential characters (abc, 123)', required: false,\n test: pw => {\n const s = pw.toLowerCase();\n for (let i = 0; i < s.length - 2; i++) {\n const a = s.charCodeAt(i), b = s.charCodeAt(i+1), c = s.charCodeAt(i+2);\n if (b === a+1 && c === a+2) return false;\n }\n return true;\n },\n }),\n noCommonWords: (list?: string[]): JoopPasswordRule => {\n const common = list ?? ['password','123456','qwerty','letmein','admin','welcome','monkey','dragon'];\n return {\n id: 'noCommonWords', label: 'Not a common password', required: false,\n test: pw => !common.includes(pw.toLowerCase()),\n };\n },\n matchesPattern: (pattern: RegExp, label: string): JoopPasswordRule => ({\n id: `pattern:${pattern.source}`, label, required: true,\n test: pw => pattern.test(pw),\n }),\n};\n\n// ── Pre-defined rule sets ─────────────────────────────────────────────────────\n\nexport const passwordRuleSets = {\n /** Basic: 8+ chars, 1 uppercase, 1 digit */\n basic: (): JoopPasswordRuleSet => ({\n name: 'basic',\n rules: [\n passwordRules.minLength(8),\n passwordRules.uppercase(),\n passwordRules.digit(),\n ],\n }),\n\n /** Standard: 10+ chars, upper, lower, digit, special */\n standard: (): JoopPasswordRuleSet => ({\n name: 'standard',\n rules: [\n passwordRules.minLength(10),\n passwordRules.uppercase(),\n passwordRules.lowercase(),\n passwordRules.digit(),\n passwordRules.special(),\n passwordRules.noSpaces(),\n ],\n }),\n\n /** Banking: strict 12+ chars, 2 uppercase, 2 digits, 2 special, no repeats */\n banking: (): JoopPasswordRuleSet => ({\n name: 'banking',\n rules: [\n passwordRules.minLength(12),\n passwordRules.maxLength(64),\n passwordRules.uppercase(2),\n passwordRules.lowercase(2),\n passwordRules.digit(2),\n passwordRules.special(2),\n passwordRules.noSpaces(),\n passwordRules.noRepeatingChars(3),\n passwordRules.noSequential(),\n passwordRules.noCommonWords(),\n ],\n }),\n\n /** PIN: exactly N digits */\n pin: (length = 6): JoopPasswordRuleSet => ({\n name: 'pin',\n rules: [\n passwordRules.matchesPattern(new RegExp(`^\\\\d{${length}}$`), `Exactly ${length} digits`),\n passwordRules.noRepeatingChars(length),\n ],\n }),\n};\n\n// ── Validator ─────────────────────────────────────────────────────────────────\n\nexport class JoopPasswordRulesValidator {\n private _ruleSet: JoopPasswordRuleSet;\n\n constructor(ruleSet: JoopPasswordRuleSet) {\n this._ruleSet = ruleSet;\n }\n\n validate(password: string): JoopPasswordValidationResult {\n const passed: string[] = [];\n const failed: string[] = [];\n const failedLabels: string[] = [];\n\n for (const rule of this._ruleSet.rules) {\n if (rule.test(password)) {\n passed.push(rule.id);\n } else {\n failed.push(rule.id);\n failedLabels.push(rule.label);\n }\n }\n\n const requiredFailed = this._ruleSet.rules\n .filter(r => r.required !== false && !passed.includes(r.id));\n\n const valid = requiredFailed.length === 0;\n const total = this._ruleSet.rules.length;\n const score = total > 0 ? Math.round((passed.length / total) * 100) : 0;\n\n return {\n valid,\n score,\n strength: score < 40 ? 'weak' : score < 65 ? 'fair' : score < 85 ? 'strong' : 'very-strong',\n passed,\n failed,\n failedLabels,\n };\n }\n\n /** Check a single rule by ID */\n checkRule(password: string, ruleId: string): boolean {\n const rule = this._ruleSet.rules.find(r => r.id === ruleId);\n return rule ? rule.test(password) : false;\n }\n\n /** Get all rules with their current pass/fail state */\n getRuleStates(password: string): Array<{ rule: JoopPasswordRule; passed: boolean }> {\n return this._ruleSet.rules.map(rule => ({ rule, passed: rule.test(password) }));\n }\n\n /** Swap the rule set at runtime */\n setRuleSet(ruleSet: JoopPasswordRuleSet): void {\n this._ruleSet = ruleSet;\n }\n}\n"]}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { J as JoopInstance } from '../joop-Bx7Iwj5p.mjs';
|
|
2
|
+
import { J as JoopNetworkMonitor, a as JoopKeyVault } from '../network-monitor-BIwPSXme.mjs';
|
|
3
|
+
import { J as JoopAppState, b as JoopNetworkType, c as JoopEffectiveType } from '../adapters-B6slG6hQ.mjs';
|
|
4
|
+
import { JoopThemeInfo } from '../theme/index.mjs';
|
|
5
|
+
import '../config.service-Cz4QQLlf.mjs';
|
|
6
|
+
import '../config.models-Cqg04fAQ.mjs';
|
|
7
|
+
import '../index-B_ksKpS1.mjs';
|
|
8
|
+
import '../index-Dz0gOur2.mjs';
|
|
9
|
+
import '../data-storage.service-LvhGRCmw.mjs';
|
|
10
|
+
import '../index-CqDKWTUP.mjs';
|
|
11
|
+
import '../auth.service-DNVB-L4U.mjs';
|
|
12
|
+
import '../oidc-client-DIJcClmB.mjs';
|
|
13
|
+
import '../client-profile.service-BuPeXVp5.mjs';
|
|
14
|
+
import '../idempotency.service-_6LqhivP.mjs';
|
|
15
|
+
import '../aes.service-CkoupAww.mjs';
|
|
16
|
+
import '../encryption/index.mjs';
|
|
17
|
+
import '../crypto-utils-DriNhLdx.mjs';
|
|
18
|
+
import '../session/index.mjs';
|
|
19
|
+
import '../observability/index.mjs';
|
|
20
|
+
import '../dev/index.mjs';
|
|
21
|
+
import '../statement-parser-C2qNmb49.mjs';
|
|
22
|
+
import '../i18n/index.mjs';
|
|
23
|
+
import '../a11y.service-C-DQQfgO.mjs';
|
|
24
|
+
import '../native-bridge/index.mjs';
|
|
25
|
+
import '../deeplink.service-Ctd5u243.mjs';
|
|
26
|
+
import '../cache/index.mjs';
|
|
27
|
+
import '../network/index.mjs';
|
|
28
|
+
import '../analytics/index.mjs';
|
|
29
|
+
import '../form-validator-3tkmzr_o.mjs';
|
|
30
|
+
import '../watermark.service-QNegMeQZ.mjs';
|
|
31
|
+
import '../storage/index.mjs';
|
|
32
|
+
import '../forms/index.mjs';
|
|
33
|
+
import '../notification.service-Dm4fvfZf.mjs';
|
|
34
|
+
import '../router/index.mjs';
|
|
35
|
+
import '../pwa/index.mjs';
|
|
36
|
+
import '../ai/index.mjs';
|
|
37
|
+
import '../differential-privacy-BcAv1G80.mjs';
|
|
38
|
+
import '../workers/index.mjs';
|
|
39
|
+
import '../state/index.mjs';
|
|
40
|
+
import '../sync-engine-DZqyKHkK.mjs';
|
|
41
|
+
import '../workflow/index.mjs';
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* joopjs/vue — Vue 3 composables integration
|
|
45
|
+
*
|
|
46
|
+
* Vue 3.x is a required peer dependency. Call createJoopVue(Vue) once and
|
|
47
|
+
* destructure the composables you need:
|
|
48
|
+
*
|
|
49
|
+
* import * as Vue from 'vue';
|
|
50
|
+
* import { createJoopVue } from 'joopjs/vue';
|
|
51
|
+
* export const {
|
|
52
|
+
* provideJoop, useJoop, useJoopNetwork, useJoopAuth,
|
|
53
|
+
* } = createJoopVue(Vue);
|
|
54
|
+
*
|
|
55
|
+
* Root component setup():
|
|
56
|
+
* provideJoop(await createJoop(config));
|
|
57
|
+
*
|
|
58
|
+
* Any child component setup():
|
|
59
|
+
* const { isLoggedIn } = useJoopAuth();
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
type _Ref<T> = {
|
|
63
|
+
value: T;
|
|
64
|
+
};
|
|
65
|
+
type _ComputedRef<T> = {
|
|
66
|
+
readonly value: T;
|
|
67
|
+
};
|
|
68
|
+
interface VueLike {
|
|
69
|
+
ref<T>(value: T): _Ref<T>;
|
|
70
|
+
computed<T>(getter: () => T): _ComputedRef<T>;
|
|
71
|
+
onUnmounted(fn: () => void): void;
|
|
72
|
+
provide<T>(key: symbol, value: T): void;
|
|
73
|
+
inject<T>(key: symbol, defaultValue: T | null): T | null;
|
|
74
|
+
}
|
|
75
|
+
interface JoopNetworkComposable {
|
|
76
|
+
online: _ComputedRef<boolean>;
|
|
77
|
+
type: _ComputedRef<JoopNetworkType>;
|
|
78
|
+
effectiveType: _ComputedRef<JoopEffectiveType | undefined>;
|
|
79
|
+
isMetered: _ComputedRef<boolean>;
|
|
80
|
+
monitor: JoopNetworkMonitor;
|
|
81
|
+
}
|
|
82
|
+
interface JoopLifecycleComposable {
|
|
83
|
+
state: _ComputedRef<JoopAppState>;
|
|
84
|
+
isActive: _ComputedRef<boolean>;
|
|
85
|
+
}
|
|
86
|
+
interface JoopKeyVaultComposable {
|
|
87
|
+
value: _Ref<string | null>;
|
|
88
|
+
loading: _Ref<boolean>;
|
|
89
|
+
set(v: string): Promise<void>;
|
|
90
|
+
remove(): Promise<void>;
|
|
91
|
+
refresh(): Promise<void>;
|
|
92
|
+
}
|
|
93
|
+
interface JoopAuthComposable {
|
|
94
|
+
isLoggedIn: _Ref<boolean>;
|
|
95
|
+
login(): void;
|
|
96
|
+
logout(): void;
|
|
97
|
+
}
|
|
98
|
+
interface JoopThemeComposable {
|
|
99
|
+
active: _Ref<string>;
|
|
100
|
+
themes: _ComputedRef<JoopThemeInfo[]>;
|
|
101
|
+
setTheme(nameOrId: string): void;
|
|
102
|
+
}
|
|
103
|
+
interface JoopI18nComposable {
|
|
104
|
+
language: _Ref<string>;
|
|
105
|
+
direction: _Ref<'ltr' | 'rtl'>;
|
|
106
|
+
t(key: string, params?: Record<string, string>): string;
|
|
107
|
+
setLanguage(lang: string): void;
|
|
108
|
+
}
|
|
109
|
+
interface JoopLoaderComposable {
|
|
110
|
+
isLoading: _Ref<boolean>;
|
|
111
|
+
show(): void;
|
|
112
|
+
hide(): void;
|
|
113
|
+
}
|
|
114
|
+
interface JoopFeatureFlagComposable {
|
|
115
|
+
enabled: _ComputedRef<boolean>;
|
|
116
|
+
variant: _ComputedRef<string | null>;
|
|
117
|
+
}
|
|
118
|
+
declare function createJoopVue<V extends VueLike>(vue: V): {
|
|
119
|
+
JoopKey: symbol;
|
|
120
|
+
provideJoop: (instance: JoopInstance) => void;
|
|
121
|
+
useJoop: () => JoopInstance;
|
|
122
|
+
useJoopNetworkMonitor: () => JoopNetworkComposable;
|
|
123
|
+
useJoopAppLifecycle: () => JoopLifecycleComposable;
|
|
124
|
+
useJoopKeyVault: (key: string, vaultConfig?: ConstructorParameters<typeof JoopKeyVault>[0]) => JoopKeyVaultComposable;
|
|
125
|
+
useJoopAuth: () => JoopAuthComposable;
|
|
126
|
+
useJoopTheme: () => JoopThemeComposable;
|
|
127
|
+
useJoopI18n: () => JoopI18nComposable;
|
|
128
|
+
useJoopLoader: () => JoopLoaderComposable;
|
|
129
|
+
useJoopConfig: <T>(key: string) => _ComputedRef<T | undefined>;
|
|
130
|
+
useJoopFeatureFlag: (flagKey: string, context?: Record<string, unknown>) => JoopFeatureFlagComposable;
|
|
131
|
+
useJoopStore: <S extends Record<string, unknown>, T>(selector: (state: S) => T) => _Ref<T>;
|
|
132
|
+
};
|
|
133
|
+
type JoopVueComposables = ReturnType<typeof createJoopVue>;
|
|
134
|
+
|
|
135
|
+
export { type JoopAuthComposable, type JoopFeatureFlagComposable, type JoopI18nComposable, type JoopKeyVaultComposable, type JoopLifecycleComposable, type JoopLoaderComposable, type JoopNetworkComposable, type JoopThemeComposable, type JoopVueComposables, type VueLike, createJoopVue };
|