@carecard/validate 3.25.0 → 3.26.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.
|
@@ -110,6 +110,13 @@ depend on those folders being present.
|
|
|
110
110
|
|
|
111
111
|
- General low-level validators should be deterministic predicate functions that
|
|
112
112
|
return `true` or `false`.
|
|
113
|
+
- `isEmailString` is the sole CareCard email-format decision. It accepts an
|
|
114
|
+
unmodified ASCII address no longer than 254 characters, with one practical
|
|
115
|
+
dot-atom local part no longer than 64 characters and a valid multi-label
|
|
116
|
+
DNS/punycode domain. It rejects quoted local parts, domain literals, Unicode
|
|
117
|
+
EAI, whitespace, invalid or empty DNS labels, numeric final labels, and
|
|
118
|
+
single-label domains. Callers may map its boolean to domain errors but must
|
|
119
|
+
not apply another email-syntax predicate.
|
|
113
120
|
- `validatePassword` is the sole password-policy function and sole direct
|
|
114
121
|
password export. It returns the NFC-normalized accepted value or a stable
|
|
115
122
|
failure reason; do not add password predicates, aliases, failure-message
|
package/lib/validate.js
CHANGED
|
@@ -82,14 +82,35 @@ const isSafeSearchString = str => {
|
|
|
82
82
|
return /^[A-Za-z][0-9a-zA-Z\-_.,'()@ ]{1,100}$/.test(str.trim());
|
|
83
83
|
};
|
|
84
84
|
|
|
85
|
+
const EMAIL_LOCAL_PART_PATTERN =
|
|
86
|
+
/^[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*$/;
|
|
87
|
+
const EMAIL_DOMAIN_LABEL_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?$/;
|
|
88
|
+
|
|
89
|
+
const isEmailDomain = domain => {
|
|
90
|
+
if (domain.length === 0 || domain.length > 253) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
const labels = domain.split('.');
|
|
94
|
+
return (
|
|
95
|
+
labels.length >= 2 &&
|
|
96
|
+
labels.every(label => EMAIL_DOMAIN_LABEL_PATTERN.test(label)) &&
|
|
97
|
+
!/^\d+$/.test(labels.at(-1))
|
|
98
|
+
);
|
|
99
|
+
};
|
|
100
|
+
|
|
85
101
|
const isEmailString = email => {
|
|
86
|
-
if (typeof email !== 'string' || email.length === 0 || email.length >
|
|
102
|
+
if (typeof email !== 'string' || email.length === 0 || email.length > 254) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
const separatorIndex = email.indexOf('@');
|
|
106
|
+
if (separatorIndex <= 0 || separatorIndex !== email.lastIndexOf('@')) {
|
|
87
107
|
return false;
|
|
88
108
|
}
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
109
|
+
const localPart = email.slice(0, separatorIndex);
|
|
110
|
+
const domain = email.slice(separatorIndex + 1);
|
|
111
|
+
return (
|
|
112
|
+
localPart.length <= 64 && EMAIL_LOCAL_PART_PATTERN.test(localPart) && isEmailDomain(domain)
|
|
113
|
+
);
|
|
93
114
|
};
|
|
94
115
|
|
|
95
116
|
const isJwtString = jwt => {
|
|
@@ -116,6 +116,10 @@ function validateProperties(obj = {}) {
|
|
|
116
116
|
}
|
|
117
117
|
break;
|
|
118
118
|
case 'email':
|
|
119
|
+
case 'requested_by_email':
|
|
120
|
+
case 'requestedByEmail':
|
|
121
|
+
case 'approved_by_email':
|
|
122
|
+
case 'approvedByEmail':
|
|
119
123
|
if (isEmailString(value)) {
|
|
120
124
|
returnObj[key] = value;
|
|
121
125
|
}
|
|
@@ -207,14 +211,10 @@ function validateProperties(obj = {}) {
|
|
|
207
211
|
case 'documentDescription':
|
|
208
212
|
case 'nick_name':
|
|
209
213
|
case 'nickName':
|
|
210
|
-
case 'requested_by_email':
|
|
211
|
-
case 'requestedByEmail':
|
|
212
214
|
case 'requested_by_phone':
|
|
213
215
|
case 'requestedByPhone':
|
|
214
216
|
case 'approved_by_name':
|
|
215
217
|
case 'approvedByName':
|
|
216
|
-
case 'approved_by_email':
|
|
217
|
-
case 'approvedByEmail':
|
|
218
218
|
case 'approved_by_phone':
|
|
219
219
|
case 'approvedByPhone':
|
|
220
220
|
if (isTextString(value)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carecard/validate",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.26.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/CareCard-ca/pkg-validate.git"
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"typescript": "6.0.3"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@carecard/common-util": "3.
|
|
50
|
+
"@carecard/common-util": "3.26.0"
|
|
51
51
|
},
|
|
52
52
|
"nyc": {
|
|
53
53
|
"all": true,
|
package/readme.md
CHANGED
|
@@ -74,7 +74,7 @@ General direct validators return `true` or `false`.
|
|
|
74
74
|
| `isStreetString(value)` | Non-empty street-like string up to 1000 chars using letters, numbers, spaces, `,`, `.`, `/`, `#`, or `-`, and not starting with `,`, `_`, or `-`. |
|
|
75
75
|
| `isNameString(value)` | 1 to 1000 char string that starts with a letter and uses letters, numbers, spaces, `_`, `-`, `.`, `,`, `'`, `(`, or `)`. Leading/trailing spaces are trimmed before pattern validation. |
|
|
76
76
|
| `isSafeSearchString(value)` | Trimmed string that starts with a letter and then uses letters, numbers, spaces, `_`, `-`, `.`, `,`, `'`, `(`, `)`, or `@`. |
|
|
77
|
-
| `isEmailString(value)` |
|
|
77
|
+
| `isEmailString(value)` | Unmodified ASCII email up to 254 chars with one dot-atom local part (max 64 chars) and a multi-label DNS/punycode domain. Quoted local parts, domain literals, Unicode EAI, whitespace, empty labels, invalid DNS labels, numeric final labels, and single-label domains are rejected. |
|
|
78
78
|
| `isJwtString(value)` | Non-blank JWT-like string up to 8192 chars that starts with `eyJ` and contains only letters, numbers, `-`, `_`, and `.`. |
|
|
79
79
|
| `validatePassword(value)` | A well-formed Unicode password from 15 to 128 code points after NFC normalization that is not an exact case-sensitive blocklist match. Returns a discriminated result with the normalized value or a stable failure reason. All Unicode characters, including spaces and emoji, are permitted without composition rules. |
|
|
80
80
|
| `isUsernameString(value)` | 1 to 200 alphanumeric chars. |
|
|
@@ -128,7 +128,7 @@ where the package supports both.
|
|
|
128
128
|
| `isBoolValue` | `is_primary`, `isPrimary`, `active`, `document_optional`, `documentOptional` |
|
|
129
129
|
| `isSafeSearchString` | `search_string`, `searchString` |
|
|
130
130
|
| `validatePassword` | `password`, `new_password`, `newPassword` |
|
|
131
|
-
| `isEmailString` | `email`
|
|
131
|
+
| `isEmailString` | `email`, `requested_by_email`, `requestedByEmail`, `approved_by_email`, `approvedByEmail` |
|
|
132
132
|
| `isPhoneNumber` | `phone_number`, `phoneNumber` |
|
|
133
133
|
| `isCountryCodeString` | `country_code`, `countryCode` |
|
|
134
134
|
| `isUrlSafeString` | `token`, `email_verification_token`, `emailVerificationToken`, `verification_token`, `verificationToken` |
|
|
@@ -137,7 +137,7 @@ where the package supports both.
|
|
|
137
137
|
| `isValidIntegerString` | `offset_number`, `offsetNumber`, `number_of_orders`, `numberOfOrders`, `price`, `from`, `number`, `limit`, `offset` |
|
|
138
138
|
| `isValidJsonString` on the raw value | `about` |
|
|
139
139
|
| `isValidJsonString(JSON.stringify(value))` | `weight`, `dimensions`, `permission`, `scope_data`, `scopeData`, `meta_data`, `metaData`, `metadata` |
|
|
140
|
-
| `isTextString` | `document_description`, `documentDescription`, `nick_name`, `nickName`, `requested_by_name`, `requestedByName`, `
|
|
140
|
+
| `isTextString` | `document_description`, `documentDescription`, `nick_name`, `nickName`, `requested_by_name`, `requestedByName`, `requested_by_phone`, `requestedByPhone`, `approved_by_name`, `approvedByName`, `approved_by_phone`, `approvedByPhone` |
|
|
141
141
|
| `isValidArrayOfStrings` | `aliases` |
|
|
142
142
|
| `isImageUrl` or `isValidUrl` | `image_url`, `imageUrl`, `website`, `file_url`, `fileUrl` |
|
|
143
143
|
| `isValidDomainName` | `domain_name`, `domainName`, `domain`, `email_domain`, `emailDomain`, `email_domain_name`, `emailDomainName` |
|