@carecard/validate 3.1.16 → 3.1.18
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/.github/workflows/auto-draft-pr.yml +114 -0
- package/.github/workflows/ci.yml +15 -15
- package/.github/workflows/publish.yml +24 -24
- package/.prettierrc.js +11 -10
- package/eslint.config.mjs +8 -8
- package/index.d.ts +76 -30
- package/index.js +6 -4
- package/lib/validate.js +131 -131
- package/lib/validateProperties.js +218 -218
- package/lib/validateWhitelistProperties.js +285 -0
- package/package.json +41 -38
package/lib/validate.js
CHANGED
|
@@ -1,231 +1,231 @@
|
|
|
1
1
|
const isImageUrl = imageUrl => {
|
|
2
|
-
|
|
2
|
+
if (imageUrl === undefined || typeof imageUrl !== 'string' || imageUrl.length === 0 || imageUrl.length > 2048) return false;
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
const imageUrlRegex = /^[a-zA-Z0-9-_./]+$/;
|
|
5
|
+
return imageUrlRegex.test(imageUrl);
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
const isInteger = number => {
|
|
9
|
-
|
|
9
|
+
return Number.isInteger(number);
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
const isValidJsonString = str => {
|
|
13
|
-
|
|
13
|
+
if (str === undefined || typeof str !== 'string' || str.length === 0 || str.length > 10000) return false;
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
try {
|
|
16
|
+
const json = JSON.parse(str);
|
|
17
|
+
return typeof json === 'object' && json !== null;
|
|
18
|
+
} catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
const isValidIntegerString = str => {
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
if (str === undefined || typeof str !== 'string' || str.length === 0 || str.length > 20) return false;
|
|
25
|
+
return /^\d+$/.test(str);
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
const isValidUuidString = str => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
if (str === undefined || typeof str !== 'string' || str.length === 0) return false;
|
|
30
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
31
|
+
return uuidRegex.test(str);
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
const isCharactersString = str => {
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
if (str === undefined || typeof str !== 'string' || str.length === 0 || str.length > 1000) return false;
|
|
36
|
+
return /^[\da-zA-Z _-]+$/.test(str);
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
const isNameString = str => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
if (typeof str !== 'string' || str.length === 0 || str.length > 1000) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return /^[A-Za-z][0-9a-zA-Z-_.,'() ]+$/.test(str.trim());
|
|
44
44
|
};
|
|
45
45
|
|
|
46
46
|
const isSafeSearchString = str => {
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
if (typeof str !== 'string' || str.length === 0) return false;
|
|
48
|
+
return /^[A-Za-z][0-9a-zA-Z\-_.,'()@ ]{1,100}$/.test(str.trim());
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
const isEmailString = email => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
if (typeof email !== 'string' || email.length === 0 || email.length > 320) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
// Simplified safe email regex
|
|
56
|
+
const regExpEmail =
|
|
57
|
+
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-zA-Z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/;
|
|
58
|
+
return regExpEmail.test(email);
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
const isJwtString = jwt => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
if (typeof jwt !== 'string' || jwt.length === 0 || jwt.length > 8192 || jwt.trim() === '') return false;
|
|
63
|
+
const jwtRegex = /^eyJ[a-zA-Z0-9-_.]+$/;
|
|
64
|
+
return jwtRegex.test(jwt);
|
|
65
65
|
};
|
|
66
66
|
|
|
67
67
|
const isPasswordString = password => {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
if (typeof password !== 'string' || password.length === 0 || password.length > 128) return false;
|
|
69
|
+
const regExPassword = /^(?=.*[a-zA-Z0-9])(?=.*[!@#$%^&*_-])[a-zA-Z0-9!@#$%^&*_-]{6,32}$/;
|
|
70
|
+
return regExPassword.test(String(password));
|
|
71
71
|
};
|
|
72
72
|
|
|
73
73
|
const isSimplePasswordString = password => {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
if (typeof password !== 'string' || password.length === 0 || password.length > 128) return false;
|
|
75
|
+
const regExPassword = /^[a-zA-Z0-9!@#$%^&*_-]{6,32}$/;
|
|
76
|
+
return regExPassword.test(String(password));
|
|
77
77
|
};
|
|
78
78
|
|
|
79
79
|
const isPasswordStringFailureMessage = password => {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
80
|
+
if (!isPasswordString(password)) {
|
|
81
|
+
return 'Total 6 to 32 characters, numbers and one of !@#$%^&*_-';
|
|
82
|
+
} else {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
85
|
};
|
|
86
86
|
|
|
87
87
|
const isSimplePasswordStringFailureMessage = password => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
if (!isSimplePasswordString(password)) {
|
|
89
|
+
return 'Total 6 to 32 characters, numbers or !@#$%^&*_-';
|
|
90
|
+
} else {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
93
|
};
|
|
94
94
|
|
|
95
95
|
const isUsernameString = str => {
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
if (typeof str !== 'string' || str.length === 0 || str.length > 200) return false;
|
|
97
|
+
return /^[0-9a-zA-Z]+$/.test(str);
|
|
98
98
|
};
|
|
99
99
|
|
|
100
100
|
function isPhoneNumber(str) {
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
if (typeof str !== 'string' || str.length === 0 || str.length > 20) return false;
|
|
102
|
+
return /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/.test(str);
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
const isUrlSafeString = inputString => {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
if (typeof inputString !== 'string' || inputString.length === 0 || inputString.length > 2048 || inputString.trim() === '') return false;
|
|
107
|
+
const urlSafeRegex = /^[a-zA-Z0-9-_.]+$/;
|
|
108
|
+
return urlSafeRegex.test(inputString);
|
|
109
109
|
};
|
|
110
110
|
|
|
111
111
|
const isString6To24CharacterLong = password => {
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
if (typeof password !== 'string' || password.length === 0) return false;
|
|
113
|
+
return 6 <= password.length && password.length <= 24;
|
|
114
114
|
};
|
|
115
115
|
|
|
116
116
|
const isString6To16CharacterLong = password => {
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
if (typeof password !== 'string' || password.length === 0) return false;
|
|
118
|
+
return 6 <= password.length && password.length <= 16;
|
|
119
119
|
};
|
|
120
120
|
|
|
121
121
|
const isProvinceString = inputString => {
|
|
122
|
-
|
|
122
|
+
const provinces = ['on', 'qc'];
|
|
123
123
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
124
|
+
if (isNameString(inputString)) {
|
|
125
|
+
return provinces.includes(inputString.toLowerCase().trim());
|
|
126
|
+
}
|
|
127
127
|
|
|
128
|
-
|
|
128
|
+
return false;
|
|
129
129
|
};
|
|
130
130
|
|
|
131
131
|
const isBoolValue = inputValue => {
|
|
132
|
-
|
|
132
|
+
return typeof inputValue === 'boolean' || inputValue === 'true' || inputValue === 'false';
|
|
133
133
|
};
|
|
134
134
|
|
|
135
135
|
const isPostalCodeString = inputString => {
|
|
136
|
-
|
|
136
|
+
const postalCodeRegex = /^(?!.*[DFIOQU])[A-VXY][0-9][A-Z] ?[0-9][A-Z][0-9]$/i;
|
|
137
137
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
if (isNameString(inputString)) {
|
|
139
|
+
return postalCodeRegex.test(inputString.trim());
|
|
140
|
+
}
|
|
141
141
|
|
|
142
|
-
|
|
142
|
+
return false;
|
|
143
143
|
};
|
|
144
144
|
|
|
145
145
|
const isSafeString = str => {
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
if (typeof str !== 'string' || str.length === 0 || str.length > 10000) return false;
|
|
147
|
+
return /^[\da-zA-Z-_.,#*'()[\]: ]+$/.test(str);
|
|
148
148
|
};
|
|
149
149
|
|
|
150
150
|
const isInStringArray = (StringArray, inputString) => {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
if (isNameString(inputString)) {
|
|
152
|
+
return StringArray.includes(inputString.toLowerCase().trim());
|
|
153
|
+
}
|
|
154
154
|
|
|
155
|
-
|
|
155
|
+
return false;
|
|
156
156
|
};
|
|
157
157
|
|
|
158
158
|
const isCountryCodeString = str => {
|
|
159
|
-
|
|
159
|
+
if (typeof str !== 'string' || str.length === 0 || str.length > 4) return false;
|
|
160
160
|
|
|
161
|
-
|
|
161
|
+
const countryCodeRegex = /^\+[1-9][0-9]{0,2}$/;
|
|
162
162
|
|
|
163
|
-
|
|
163
|
+
return countryCodeRegex.test(str);
|
|
164
164
|
};
|
|
165
165
|
|
|
166
166
|
const isValidDomainName = domain => {
|
|
167
|
-
|
|
167
|
+
if (typeof domain !== 'string' || domain.length === 0 || domain.length > 253) return false;
|
|
168
168
|
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
const domainRegex = /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$/i;
|
|
170
|
+
return domainRegex.test(domain);
|
|
171
171
|
};
|
|
172
172
|
|
|
173
173
|
const isValidTimestampzString = str => {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
174
|
+
if (typeof str !== 'string' || str.length === 0 || str.length > 64) return false;
|
|
175
|
+
// ISO 8601 for UTC or with Offset: 2023-10-27T10:00:00Z or 2023-10-27T10:00:00+02:00
|
|
176
|
+
const timestampzRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;
|
|
177
|
+
return timestampzRegex.test(str) && !isNaN(Date.parse(str));
|
|
178
178
|
};
|
|
179
179
|
|
|
180
180
|
const isValidTimestampString = str => {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
181
|
+
if (typeof str !== 'string' || str.length === 0 || str.length > 64) return false;
|
|
182
|
+
// ISO 8601 without time zone: 2023-10-27T10:00:00 or 2023-10-27T10:00:00.123
|
|
183
|
+
const timestampRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?$/;
|
|
184
|
+
return timestampRegex.test(str) && !isNaN(Date.parse(str));
|
|
185
185
|
};
|
|
186
186
|
|
|
187
187
|
const isValidUrl = url => {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
188
|
+
if (typeof url !== 'string' || url.length === 0 || url.length > 2048) return false;
|
|
189
|
+
try {
|
|
190
|
+
const parsedUrl = new URL(url);
|
|
191
|
+
return parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:';
|
|
192
|
+
} catch {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
195
|
};
|
|
196
196
|
const isValidArrayOfStrings = arr => {
|
|
197
|
-
|
|
198
|
-
|
|
197
|
+
if (!Array.isArray(arr)) return false;
|
|
198
|
+
return arr.every(isSafeString);
|
|
199
199
|
};
|
|
200
200
|
module.exports = {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
201
|
+
isImageUrl,
|
|
202
|
+
isInteger,
|
|
203
|
+
isValidJsonString,
|
|
204
|
+
isValidIntegerString,
|
|
205
|
+
isValidUuidString,
|
|
206
|
+
isCharactersString,
|
|
207
|
+
isNameString,
|
|
208
|
+
isSafeSearchString,
|
|
209
|
+
isEmailString,
|
|
210
|
+
isJwtString,
|
|
211
|
+
isPasswordString,
|
|
212
|
+
isSimplePasswordString,
|
|
213
|
+
isPasswordStringFailureMessage,
|
|
214
|
+
isSimplePasswordStringFailureMessage,
|
|
215
|
+
isUsernameString,
|
|
216
|
+
isPhoneNumber,
|
|
217
|
+
isUrlSafeString,
|
|
218
|
+
isString6To24CharacterLong,
|
|
219
|
+
isString6To16CharacterLong,
|
|
220
|
+
isProvinceString,
|
|
221
|
+
isBoolValue,
|
|
222
|
+
isPostalCodeString,
|
|
223
|
+
isSafeString,
|
|
224
|
+
isInStringArray,
|
|
225
|
+
isCountryCodeString,
|
|
226
|
+
isValidDomainName,
|
|
227
|
+
isValidTimestampzString,
|
|
228
|
+
isValidTimestampString,
|
|
229
|
+
isValidUrl,
|
|
230
|
+
isValidArrayOfStrings,
|
|
231
231
|
};
|