@easyflow/javascript-sdk 2.1.8 → 2.1.10
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/README.md +87 -7
- package/dist/index.d.ts +421 -0
- package/package.json +19 -6
- package/.babelrc +0 -5
- package/.github/workflows/deploy-sdk-cf.yml +0 -49
- package/.github/workflows/release-sdk-cdn.yml +0 -144
- package/.github/workflows/release-sdk.yml +0 -112
- package/.prettierrc +0 -6
- package/CDN-DEPLOYMENT.md +0 -175
- package/DEMO.md +0 -258
- package/DEPLOYMENT.md +0 -224
- package/INTEGRATION-GUIDE.md +0 -521
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/easyflow-javascript-sdk/index.html +0 -116
- package/coverage/easyflow-javascript-sdk/libs/constants.mjs.html +0 -268
- package/coverage/easyflow-javascript-sdk/libs/errors.mjs.html +0 -271
- package/coverage/easyflow-javascript-sdk/libs/exception-handler.mjs.html +0 -148
- package/coverage/easyflow-javascript-sdk/libs/fingerprint.mjs.html +0 -895
- package/coverage/easyflow-javascript-sdk/libs/http.mjs.html +0 -502
- package/coverage/easyflow-javascript-sdk/libs/index.html +0 -266
- package/coverage/easyflow-javascript-sdk/libs/logger.mjs.html +0 -568
- package/coverage/easyflow-javascript-sdk/libs/sanitizer.mjs.html +0 -1099
- package/coverage/easyflow-javascript-sdk/libs/security.mjs.html +0 -733
- package/coverage/easyflow-javascript-sdk/libs/types.mjs.html +0 -508
- package/coverage/easyflow-javascript-sdk/libs/utils.mjs.html +0 -379
- package/coverage/easyflow-javascript-sdk/libs/validator.mjs.html +0 -2623
- package/coverage/easyflow-javascript-sdk/sdk.mjs.html +0 -2434
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -131
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/easyflow-javascript-sdk/index.html +0 -116
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/constants.mjs.html +0 -268
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/errors.mjs.html +0 -271
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/exception-handler.mjs.html +0 -148
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/fingerprint.mjs.html +0 -895
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/http.mjs.html +0 -502
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/index.html +0 -266
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/logger.mjs.html +0 -568
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/sanitizer.mjs.html +0 -1099
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/security.mjs.html +0 -733
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/types.mjs.html +0 -508
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/utils.mjs.html +0 -379
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/validator.mjs.html +0 -2623
- package/coverage/lcov-report/easyflow-javascript-sdk/sdk.mjs.html +0 -2434
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -131
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov.info +0 -1429
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -196
- package/dist/435.easyflow-sdk.min.js +0 -1
- package/dist/easyflow-sdk.min.js +0 -1
- package/dist/easyflow-sdk.min.js.LICENSE.txt +0 -1
- package/dist/index.html +0 -756
- package/docs/index.html +0 -775
- package/examples/lovable-integration.html +0 -410
- package/index.html +0 -981
- package/jest.config.js +0 -37
- package/jsdoc.json +0 -42
- package/libs/auto-integration.mjs +0 -333
- package/libs/constants.mjs +0 -61
- package/libs/constants.spec.js +0 -198
- package/libs/errors.mjs +0 -62
- package/libs/errors.spec.js +0 -178
- package/libs/exception-handler.mjs +0 -21
- package/libs/exception-handler.spec.js +0 -237
- package/libs/fingerprint.mjs +0 -270
- package/libs/http.mjs +0 -163
- package/libs/http.spec.js +0 -427
- package/libs/integration-wrapper.mjs +0 -285
- package/libs/logger.mjs +0 -161
- package/libs/logger.spec.js +0 -389
- package/libs/sanitizer.mjs +0 -340
- package/libs/sanitizer.spec.js +0 -583
- package/libs/security.mjs +0 -217
- package/libs/types.mjs +0 -141
- package/libs/utils.mjs +0 -368
- package/libs/utils.spec.js +0 -231
- package/libs/validator.mjs +0 -952
- package/libs/validator.spec.js +0 -615
- package/mocks/offer.mock.js +0 -77
- package/scripts/publish-npm.sh +0 -82
- package/sdk.mjs +0 -945
- package/sdk.spec.js +0 -796
- package/test-setup.cjs +0 -211
- package/test.html +0 -154
- package/webpack.config.cjs +0 -41
package/libs/validator.mjs
DELETED
|
@@ -1,952 +0,0 @@
|
|
|
1
|
-
import { EasyflowError, ERROR_CODES, ValidationError } from './errors.mjs'
|
|
2
|
-
import { PAYMENT_METHODS } from './constants.mjs'
|
|
3
|
-
import { throwsError } from './exception-handler.mjs'
|
|
4
|
-
import { SECURITY_CONFIG } from './security.mjs'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Validation utilities for Easyflow SDK
|
|
8
|
-
*/
|
|
9
|
-
export class Validator {
|
|
10
|
-
/**
|
|
11
|
-
* Validates if a value is a non-empty string
|
|
12
|
-
* @param {*} value - Value to validate
|
|
13
|
-
* @param {string} fieldName - Field name for error message
|
|
14
|
-
* @returns {boolean} True if valid
|
|
15
|
-
* @throws {EasyflowError} If validation fails
|
|
16
|
-
*/
|
|
17
|
-
static isString(value, fieldName) {
|
|
18
|
-
if (!value || typeof value !== 'string') {
|
|
19
|
-
throwsError(
|
|
20
|
-
new EasyflowError(
|
|
21
|
-
`${fieldName} must be a non-empty string`,
|
|
22
|
-
400,
|
|
23
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
24
|
-
)
|
|
25
|
-
)
|
|
26
|
-
}
|
|
27
|
-
return true
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Validates if a value is a valid object
|
|
32
|
-
* @param {*} value - Value to validate
|
|
33
|
-
* @param {string} fieldName - Field name for error message
|
|
34
|
-
* @returns {boolean} True if valid
|
|
35
|
-
* @throws {EasyflowError} If validation fails
|
|
36
|
-
*/
|
|
37
|
-
static isObject(value, fieldName) {
|
|
38
|
-
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
39
|
-
throwsError(
|
|
40
|
-
new EasyflowError(
|
|
41
|
-
`${fieldName} must be a valid object`,
|
|
42
|
-
400,
|
|
43
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
44
|
-
)
|
|
45
|
-
)
|
|
46
|
-
}
|
|
47
|
-
return true
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Validates if a value is a non-empty array
|
|
52
|
-
* @param {*} value - Value to validate
|
|
53
|
-
* @param {string} fieldName - Field name for error message
|
|
54
|
-
* @returns {boolean} True if valid
|
|
55
|
-
* @throws {EasyflowError} If validation fails
|
|
56
|
-
*/
|
|
57
|
-
static isArray(value, fieldName) {
|
|
58
|
-
if (!Array.isArray(value) || value.length === 0) {
|
|
59
|
-
throwsError(
|
|
60
|
-
new EasyflowError(
|
|
61
|
-
`${fieldName} must be a non-empty array`,
|
|
62
|
-
400,
|
|
63
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
64
|
-
)
|
|
65
|
-
)
|
|
66
|
-
}
|
|
67
|
-
return true
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Validates a payment method object
|
|
72
|
-
* @param {Object} payment - Payment method to validate
|
|
73
|
-
* @throws {EasyflowError} If validation fails
|
|
74
|
-
*/
|
|
75
|
-
static validatePaymentMethod(payment) {
|
|
76
|
-
Validator.isObject(payment, 'payment')
|
|
77
|
-
Validator.isString(payment.method, 'payment.method')
|
|
78
|
-
if (!Object.values(PAYMENT_METHODS).includes(payment.method)) {
|
|
79
|
-
throwsError(
|
|
80
|
-
new EasyflowError(
|
|
81
|
-
`Invalid payment method: ${payment.method}`,
|
|
82
|
-
400,
|
|
83
|
-
ERROR_CODES.INVALID_PAYMENT_METHOD
|
|
84
|
-
)
|
|
85
|
-
)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
switch (payment.method) {
|
|
89
|
-
case PAYMENT_METHODS.CREDIT_CARD:
|
|
90
|
-
if (!payment.creditCard) {
|
|
91
|
-
throwsError(
|
|
92
|
-
new EasyflowError(
|
|
93
|
-
'Credit card data is required for credit-card payment method',
|
|
94
|
-
400,
|
|
95
|
-
ERROR_CODES.MISSING_CREDIT_CARD_DATA
|
|
96
|
-
)
|
|
97
|
-
)
|
|
98
|
-
Validator.validateCreditCardData(payment.creditCard)
|
|
99
|
-
}
|
|
100
|
-
break
|
|
101
|
-
case PAYMENT_METHODS.PIX:
|
|
102
|
-
break
|
|
103
|
-
case PAYMENT_METHODS.BANK_BILLET:
|
|
104
|
-
break
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Validates credit card data
|
|
110
|
-
* @param {Object} creditCard - Credit card data to validate
|
|
111
|
-
* @throws {EasyflowError} If validation fails
|
|
112
|
-
*/
|
|
113
|
-
static validateCreditCardData(creditCard) {
|
|
114
|
-
Validator.isObject(creditCard, 'creditCard')
|
|
115
|
-
const requiredFields = [
|
|
116
|
-
'cardNumber',
|
|
117
|
-
'holderName',
|
|
118
|
-
'month',
|
|
119
|
-
'year',
|
|
120
|
-
'cvv',
|
|
121
|
-
]
|
|
122
|
-
requiredFields.forEach((field) => {
|
|
123
|
-
Validator.isString(creditCard[field], `creditCard.${field}`)
|
|
124
|
-
})
|
|
125
|
-
if (!/^\d{13,19}$/.test(creditCard.cardNumber))
|
|
126
|
-
throw new ValidationError('Invalid card number')
|
|
127
|
-
|
|
128
|
-
if (!/^\d{3,4}$/.test(creditCard.cvv))
|
|
129
|
-
throw new ValidationError('Invalid CVV')
|
|
130
|
-
if (
|
|
131
|
-
!/^\d{1,2}$/.test(creditCard.month) ||
|
|
132
|
-
parseInt(creditCard.month) < 1 ||
|
|
133
|
-
parseInt(creditCard.month) > 12
|
|
134
|
-
)
|
|
135
|
-
throw new ValidationError('Invalid expiration month')
|
|
136
|
-
if (!/^\d{4}$/.test(creditCard.year))
|
|
137
|
-
throw new ValidationError('Invalid expiration year')
|
|
138
|
-
if (!creditCard.holderName || creditCard.holderName.length < 2)
|
|
139
|
-
throw new ValidationError('Invalid holder name')
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Validates order data
|
|
144
|
-
* @param {Object} data - Order data to validate
|
|
145
|
-
* @throws {EasyflowError} If validation fails
|
|
146
|
-
*/
|
|
147
|
-
static validateOrderData(data) {
|
|
148
|
-
Validator.isObject(data, 'data')
|
|
149
|
-
Validator.isArray(data.payments, 'data.payments')
|
|
150
|
-
data.payments.forEach((payment, index) => {
|
|
151
|
-
try {
|
|
152
|
-
Validator.validatePaymentMethod(payment)
|
|
153
|
-
Validator.isBiggerThanZero(
|
|
154
|
-
payment.numberInstallments,
|
|
155
|
-
'numberInstallments'
|
|
156
|
-
)
|
|
157
|
-
} catch (error) {
|
|
158
|
-
throwsError(
|
|
159
|
-
new EasyflowError(
|
|
160
|
-
`Invalid payment at index ${index}: ${error.message}`,
|
|
161
|
-
error.status,
|
|
162
|
-
error.code
|
|
163
|
-
)
|
|
164
|
-
)
|
|
165
|
-
}
|
|
166
|
-
})
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Validates if value is a valid number
|
|
171
|
-
* @param {Number} value - Number value to validate
|
|
172
|
-
* @param {String} fieldName - Field name for error message
|
|
173
|
-
* @throws {EasyflowError} If validation fails
|
|
174
|
-
*/
|
|
175
|
-
static isNumber(value, fieldName) {
|
|
176
|
-
if (typeof value !== 'number' || isNaN(value)) {
|
|
177
|
-
throwsError(
|
|
178
|
-
new EasyflowError(
|
|
179
|
-
`${fieldName} must be a valid number`,
|
|
180
|
-
400,
|
|
181
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
182
|
-
)
|
|
183
|
-
)
|
|
184
|
-
}
|
|
185
|
-
return true
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Validates if a number is greater than zero
|
|
190
|
-
* @param {Number} value - Number value to validate
|
|
191
|
-
* @param {String} fieldName - Field name for error message
|
|
192
|
-
* @throws {EasyflowError} If validation fails
|
|
193
|
-
*/
|
|
194
|
-
static isBiggerThanZero(value, fieldName) {
|
|
195
|
-
if (!Validator.isNumber(value, fieldName) || value <= 0) {
|
|
196
|
-
throwsError(
|
|
197
|
-
new EasyflowError(
|
|
198
|
-
`${fieldName} must be a number greater than zero`,
|
|
199
|
-
400,
|
|
200
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
201
|
-
)
|
|
202
|
-
)
|
|
203
|
-
}
|
|
204
|
-
return true
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Validates a URL
|
|
209
|
-
* @param url - URL to validate
|
|
210
|
-
* @returns {string} Validated URL
|
|
211
|
-
* @throws {ValidationError} If validation fails
|
|
212
|
-
*/
|
|
213
|
-
static validateUrl(url) {
|
|
214
|
-
try {
|
|
215
|
-
const parsed = new URL(url)
|
|
216
|
-
if (!SECURITY_CONFIG.ALLOWED_DOMAINS.includes(parsed.hostname))
|
|
217
|
-
throwsError(new ValidationError('Invalid domain'))
|
|
218
|
-
if (parsed.protocol !== 'https:')
|
|
219
|
-
throwsError(new ValidationError('HTTPS required'))
|
|
220
|
-
return parsed.toString()
|
|
221
|
-
} catch (error) {
|
|
222
|
-
throwsError(new ValidationError('Invalid URL'))
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Validates charge items data
|
|
228
|
-
* @param {Object} items - Charge Items Data to validate
|
|
229
|
-
* @throws {EasyflowError} If validation fails
|
|
230
|
-
*/
|
|
231
|
-
static validateChargeItemsData(items) {
|
|
232
|
-
Validator.isArray(items, 'items')
|
|
233
|
-
items.forEach((record, index) => {
|
|
234
|
-
try {
|
|
235
|
-
Validator.isObject(record, `items[${index}]`)
|
|
236
|
-
if (record.name) Validator.isString(record.name, 'name')
|
|
237
|
-
if (record.description)
|
|
238
|
-
Validator.isString(record.description, 'description')
|
|
239
|
-
if (record.quantity)
|
|
240
|
-
Validator.isBiggerThanZero(record.quantity, 'quantity')
|
|
241
|
-
if (record.priceInCents)
|
|
242
|
-
Validator.isNumber(record.priceInCents, 'priceInCents')
|
|
243
|
-
} catch (error) {
|
|
244
|
-
throwsError(
|
|
245
|
-
new EasyflowError(
|
|
246
|
-
`Invalid items at index ${index}: ${error.message}`,
|
|
247
|
-
error.status,
|
|
248
|
-
error.code
|
|
249
|
-
)
|
|
250
|
-
)
|
|
251
|
-
}
|
|
252
|
-
})
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Validates email format
|
|
257
|
-
* @param {string} email - Email to validate
|
|
258
|
-
* @param {string} fieldName - Field name for error message
|
|
259
|
-
* @returns {boolean} True if valid
|
|
260
|
-
* @throws {EasyflowError} If validation fails
|
|
261
|
-
*/
|
|
262
|
-
static validateEmail(email, fieldName = 'email') {
|
|
263
|
-
Validator.isString(email, fieldName)
|
|
264
|
-
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
|
265
|
-
if (!emailRegex.test(email)) {
|
|
266
|
-
throwsError(
|
|
267
|
-
new EasyflowError(
|
|
268
|
-
`${fieldName} must be a valid email address`,
|
|
269
|
-
400,
|
|
270
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
271
|
-
)
|
|
272
|
-
)
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
if (email.length > 254) {
|
|
276
|
-
throwsError(
|
|
277
|
-
new EasyflowError(
|
|
278
|
-
`${fieldName} is too long (max 254 characters)`,
|
|
279
|
-
400,
|
|
280
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
281
|
-
)
|
|
282
|
-
)
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
if (
|
|
286
|
-
email.includes('..') ||
|
|
287
|
-
email.startsWith('.') ||
|
|
288
|
-
email.endsWith('.')
|
|
289
|
-
) {
|
|
290
|
-
throwsError(
|
|
291
|
-
new EasyflowError(
|
|
292
|
-
`${fieldName} contains invalid characters`,
|
|
293
|
-
400,
|
|
294
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
295
|
-
)
|
|
296
|
-
)
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
return true
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* Validates CPF (Brazilian individual taxpayer number)
|
|
304
|
-
* @param {string} cpf - CPF to validate
|
|
305
|
-
* @param {string} fieldName - Field name for error message
|
|
306
|
-
* @returns {boolean} True if valid
|
|
307
|
-
* @throws {EasyflowError} If validation fails
|
|
308
|
-
*/
|
|
309
|
-
static validateCPF(cpf, fieldName = 'CPF') {
|
|
310
|
-
Validator.isString(cpf, fieldName)
|
|
311
|
-
|
|
312
|
-
const cleanCpf = cpf.replace(/\D/g, '')
|
|
313
|
-
|
|
314
|
-
if (cleanCpf.length !== 11) {
|
|
315
|
-
throwsError(
|
|
316
|
-
new EasyflowError(
|
|
317
|
-
`${fieldName} must have exactly 11 digits`,
|
|
318
|
-
400,
|
|
319
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
320
|
-
)
|
|
321
|
-
)
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
if (/^(\d)\1{10}$/.test(cleanCpf)) {
|
|
325
|
-
throwsError(
|
|
326
|
-
new EasyflowError(
|
|
327
|
-
`${fieldName} is invalid (all digits are the same)`,
|
|
328
|
-
400,
|
|
329
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
330
|
-
)
|
|
331
|
-
)
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
let sum = 0
|
|
335
|
-
for (let i = 0; i < 9; i++) {
|
|
336
|
-
sum += parseInt(cleanCpf.charAt(i)) * (10 - i)
|
|
337
|
-
}
|
|
338
|
-
let remainder = (sum * 10) % 11
|
|
339
|
-
if (remainder === 10 || remainder === 11) remainder = 0
|
|
340
|
-
if (remainder !== parseInt(cleanCpf.charAt(9))) {
|
|
341
|
-
throwsError(
|
|
342
|
-
new EasyflowError(
|
|
343
|
-
`${fieldName} is invalid`,
|
|
344
|
-
400,
|
|
345
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
346
|
-
)
|
|
347
|
-
)
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
sum = 0
|
|
351
|
-
for (let i = 0; i < 10; i++) {
|
|
352
|
-
sum += parseInt(cleanCpf.charAt(i)) * (11 - i)
|
|
353
|
-
}
|
|
354
|
-
remainder = (sum * 10) % 11
|
|
355
|
-
if (remainder === 10 || remainder === 11) remainder = 0
|
|
356
|
-
if (remainder !== parseInt(cleanCpf.charAt(10))) {
|
|
357
|
-
throwsError(
|
|
358
|
-
new EasyflowError(
|
|
359
|
-
`${fieldName} is invalid`,
|
|
360
|
-
400,
|
|
361
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
362
|
-
)
|
|
363
|
-
)
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
return true
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
/**
|
|
370
|
-
* Validates CNPJ (Brazilian company taxpayer number)
|
|
371
|
-
* @param {string} cnpj - CNPJ to validate
|
|
372
|
-
* @param {string} fieldName - Field name for error message
|
|
373
|
-
* @returns {boolean} True if valid
|
|
374
|
-
* @throws {EasyflowError} If validation fails
|
|
375
|
-
*/
|
|
376
|
-
static validateCNPJ(cnpj, fieldName = 'CNPJ') {
|
|
377
|
-
Validator.isString(cnpj, fieldName)
|
|
378
|
-
|
|
379
|
-
const cleanCnpj = cnpj.replace(/\D/g, '')
|
|
380
|
-
|
|
381
|
-
if (cleanCnpj.length !== 14) {
|
|
382
|
-
throwsError(
|
|
383
|
-
new EasyflowError(
|
|
384
|
-
`${fieldName} must have exactly 14 digits`,
|
|
385
|
-
400,
|
|
386
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
387
|
-
)
|
|
388
|
-
)
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
if (/^(\d)\1{13}$/.test(cleanCnpj)) {
|
|
392
|
-
throwsError(
|
|
393
|
-
new EasyflowError(
|
|
394
|
-
`${fieldName} is invalid (all digits are the same)`,
|
|
395
|
-
400,
|
|
396
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
397
|
-
)
|
|
398
|
-
)
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
const weights1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
|
|
402
|
-
const weights2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
|
|
403
|
-
|
|
404
|
-
let sum = 0
|
|
405
|
-
for (let i = 0; i < 12; i++) {
|
|
406
|
-
sum += parseInt(cleanCnpj.charAt(i)) * weights1[i]
|
|
407
|
-
}
|
|
408
|
-
let remainder = sum % 11
|
|
409
|
-
let digit1 = remainder < 2 ? 0 : 11 - remainder
|
|
410
|
-
|
|
411
|
-
if (digit1 !== parseInt(cleanCnpj.charAt(12))) {
|
|
412
|
-
throwsError(
|
|
413
|
-
new EasyflowError(
|
|
414
|
-
`${fieldName} is invalid`,
|
|
415
|
-
400,
|
|
416
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
417
|
-
)
|
|
418
|
-
)
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
sum = 0
|
|
422
|
-
for (let i = 0; i < 13; i++) {
|
|
423
|
-
sum += parseInt(cleanCnpj.charAt(i)) * weights2[i]
|
|
424
|
-
}
|
|
425
|
-
remainder = sum % 11
|
|
426
|
-
let digit2 = remainder < 2 ? 0 : 11 - remainder
|
|
427
|
-
|
|
428
|
-
if (digit2 !== parseInt(cleanCnpj.charAt(13))) {
|
|
429
|
-
throwsError(
|
|
430
|
-
new EasyflowError(
|
|
431
|
-
`${fieldName} is invalid`,
|
|
432
|
-
400,
|
|
433
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
434
|
-
)
|
|
435
|
-
)
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
return true
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
/**
|
|
442
|
-
* Validates legal document (CPF or CNPJ)
|
|
443
|
-
* @param {Object} document - Document object to validate
|
|
444
|
-
* @param {string} fieldName - Field name for error message
|
|
445
|
-
* @returns {boolean} True if valid
|
|
446
|
-
* @throws {EasyflowError} If validation fails
|
|
447
|
-
*/
|
|
448
|
-
static validateLegalDocument(document, fieldName = 'document') {
|
|
449
|
-
Validator.isObject(document, fieldName)
|
|
450
|
-
Validator.isString(document.type, `${fieldName}.type`)
|
|
451
|
-
Validator.isString(document.number, `${fieldName}.number`)
|
|
452
|
-
|
|
453
|
-
if (!['CPF', 'CNPJ'].includes(document.type)) {
|
|
454
|
-
throwsError(
|
|
455
|
-
new EasyflowError(
|
|
456
|
-
`${fieldName}.type must be either 'CPF' or 'CNPJ'`,
|
|
457
|
-
400,
|
|
458
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
459
|
-
)
|
|
460
|
-
)
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
if (!/^\d+$/.test(document.number)) {
|
|
464
|
-
throwsError(
|
|
465
|
-
new EasyflowError(
|
|
466
|
-
`${fieldName}.number must contain only digits`,
|
|
467
|
-
400,
|
|
468
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
469
|
-
)
|
|
470
|
-
)
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
if (document.type === 'CPF') {
|
|
474
|
-
Validator.validateCPF(document.number, `${fieldName}.number`)
|
|
475
|
-
} else {
|
|
476
|
-
Validator.validateCNPJ(document.number, `${fieldName}.number`)
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
return true
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
/**
|
|
483
|
-
* Validates phone number
|
|
484
|
-
* @param {Object} phone - Phone object to validate
|
|
485
|
-
* @param {string} fieldName - Field name for error message
|
|
486
|
-
* @returns {boolean} True if valid
|
|
487
|
-
* @throws {EasyflowError} If validation fails
|
|
488
|
-
*/
|
|
489
|
-
static validatePhone(phone, fieldName = 'phone') {
|
|
490
|
-
Validator.isObject(phone, fieldName)
|
|
491
|
-
Validator.isString(phone.areaCode, `${fieldName}.areaCode`)
|
|
492
|
-
Validator.isString(phone.ddd, `${fieldName}.ddd`)
|
|
493
|
-
Validator.isString(phone.number, `${fieldName}.number`)
|
|
494
|
-
|
|
495
|
-
if (!/^\+\d{1,4}$/.test(phone.areaCode)) {
|
|
496
|
-
throwsError(
|
|
497
|
-
new EasyflowError(
|
|
498
|
-
`${fieldName}.areaCode must be in format +XX or +XXX`,
|
|
499
|
-
400,
|
|
500
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
501
|
-
)
|
|
502
|
-
)
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
if (!/^\d{2}$/.test(phone.ddd)) {
|
|
506
|
-
throwsError(
|
|
507
|
-
new EasyflowError(
|
|
508
|
-
`${fieldName}.ddd must be exactly 2 digits`,
|
|
509
|
-
400,
|
|
510
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
511
|
-
)
|
|
512
|
-
)
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
if (!/^\d{8,9}$/.test(phone.number)) {
|
|
516
|
-
throwsError(
|
|
517
|
-
new EasyflowError(
|
|
518
|
-
`${fieldName}.number must be 8 or 9 digits`,
|
|
519
|
-
400,
|
|
520
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
521
|
-
)
|
|
522
|
-
)
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
if (typeof phone.isMobile !== 'boolean') {
|
|
526
|
-
throwsError(
|
|
527
|
-
new EasyflowError(
|
|
528
|
-
`${fieldName}.isMobile must be a boolean`,
|
|
529
|
-
400,
|
|
530
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
531
|
-
)
|
|
532
|
-
)
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
return true
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
/**
|
|
539
|
-
* Validates address
|
|
540
|
-
* @param {Object} address - Address object to validate
|
|
541
|
-
* @param {string} fieldName - Field name for error message
|
|
542
|
-
* @returns {boolean} True if valid
|
|
543
|
-
* @throws {EasyflowError} If validation fails
|
|
544
|
-
*/
|
|
545
|
-
static validateAddress(address, fieldName = 'address') {
|
|
546
|
-
Validator.isObject(address, fieldName)
|
|
547
|
-
|
|
548
|
-
const requiredFields = [
|
|
549
|
-
'zipCode',
|
|
550
|
-
'street',
|
|
551
|
-
'neighborhood',
|
|
552
|
-
'city',
|
|
553
|
-
'state',
|
|
554
|
-
'number',
|
|
555
|
-
]
|
|
556
|
-
requiredFields.forEach((field) => {
|
|
557
|
-
Validator.isString(address[field], `${fieldName}.${field}`)
|
|
558
|
-
})
|
|
559
|
-
|
|
560
|
-
if (address.complement) {
|
|
561
|
-
Validator.isString(address.complement, `${fieldName}.complement`)
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
if (!/^\d{8}$/.test(address.zipCode)) {
|
|
565
|
-
throwsError(
|
|
566
|
-
new EasyflowError(
|
|
567
|
-
`${fieldName}.zipCode must be exactly 8 digits`,
|
|
568
|
-
400,
|
|
569
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
570
|
-
)
|
|
571
|
-
)
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
if (address.street.length < 3 || address.street.length > 100) {
|
|
575
|
-
throwsError(
|
|
576
|
-
new EasyflowError(
|
|
577
|
-
`${fieldName}.street must be between 3 and 100 characters`,
|
|
578
|
-
400,
|
|
579
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
580
|
-
)
|
|
581
|
-
)
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
if (
|
|
585
|
-
address.neighborhood.length < 2 ||
|
|
586
|
-
address.neighborhood.length > 50
|
|
587
|
-
) {
|
|
588
|
-
throwsError(
|
|
589
|
-
new EasyflowError(
|
|
590
|
-
`${fieldName}.neighborhood must be between 2 and 50 characters`,
|
|
591
|
-
400,
|
|
592
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
593
|
-
)
|
|
594
|
-
)
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
if (address.city.length < 2 || address.city.length > 50) {
|
|
598
|
-
throwsError(
|
|
599
|
-
new EasyflowError(
|
|
600
|
-
`${fieldName}.city must be between 2 and 50 characters`,
|
|
601
|
-
400,
|
|
602
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
603
|
-
)
|
|
604
|
-
)
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
const validStates = [
|
|
608
|
-
'AC',
|
|
609
|
-
'AL',
|
|
610
|
-
'AP',
|
|
611
|
-
'AM',
|
|
612
|
-
'BA',
|
|
613
|
-
'CE',
|
|
614
|
-
'DF',
|
|
615
|
-
'ES',
|
|
616
|
-
'GO',
|
|
617
|
-
'MA',
|
|
618
|
-
'MT',
|
|
619
|
-
'MS',
|
|
620
|
-
'MG',
|
|
621
|
-
'PA',
|
|
622
|
-
'PB',
|
|
623
|
-
'PR',
|
|
624
|
-
'PE',
|
|
625
|
-
'PI',
|
|
626
|
-
'RJ',
|
|
627
|
-
'RN',
|
|
628
|
-
'RS',
|
|
629
|
-
'RO',
|
|
630
|
-
'RR',
|
|
631
|
-
'SC',
|
|
632
|
-
'SP',
|
|
633
|
-
'SE',
|
|
634
|
-
'TO',
|
|
635
|
-
]
|
|
636
|
-
if (!validStates.includes(address.state.toUpperCase())) {
|
|
637
|
-
throwsError(
|
|
638
|
-
new EasyflowError(
|
|
639
|
-
`${fieldName}.state must be a valid Brazilian state abbreviation`,
|
|
640
|
-
400,
|
|
641
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
642
|
-
)
|
|
643
|
-
)
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
if (!/^\d+[A-Za-z]?$/.test(address.number)) {
|
|
647
|
-
throwsError(
|
|
648
|
-
new EasyflowError(
|
|
649
|
-
`${fieldName}.number must be a valid street number`,
|
|
650
|
-
400,
|
|
651
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
652
|
-
)
|
|
653
|
-
)
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
return true
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
/**
|
|
660
|
-
* Validates customer data
|
|
661
|
-
* @param {Object} customer - Customer object to validate
|
|
662
|
-
* @param {string} fieldName - Field name for error message
|
|
663
|
-
* @returns {boolean} True if valid
|
|
664
|
-
* @throws {EasyflowError} If validation fails
|
|
665
|
-
*/
|
|
666
|
-
static validateCustomer(customer, fieldName = 'customer') {
|
|
667
|
-
Validator.isObject(customer, fieldName)
|
|
668
|
-
Validator.isString(customer.name, `${fieldName}.name`)
|
|
669
|
-
Validator.validateEmail(customer.email, `${fieldName}.email`)
|
|
670
|
-
Validator.validateLegalDocument(
|
|
671
|
-
customer.document,
|
|
672
|
-
`${fieldName}.document`
|
|
673
|
-
)
|
|
674
|
-
Validator.validatePhone(customer.phone, `${fieldName}.phone`)
|
|
675
|
-
|
|
676
|
-
if (customer.name.length < 2 || customer.name.length > 100) {
|
|
677
|
-
throwsError(
|
|
678
|
-
new EasyflowError(
|
|
679
|
-
`${fieldName}.name must be between 2 and 100 characters`,
|
|
680
|
-
400,
|
|
681
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
682
|
-
)
|
|
683
|
-
)
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
if (customer.address) {
|
|
687
|
-
Validator.validateAddress(customer.address, `${fieldName}.address`)
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
if (customer.deliveryAddress) {
|
|
691
|
-
Validator.validateAddress(
|
|
692
|
-
customer.deliveryAddress,
|
|
693
|
-
`${fieldName}.deliveryAddress`
|
|
694
|
-
)
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
return true
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
/**
|
|
701
|
-
* Validates pagination parameters
|
|
702
|
-
* @param {number} page - Page number
|
|
703
|
-
* @param {number} limit - Items per page
|
|
704
|
-
* @param {string} fieldName - Field name for error message
|
|
705
|
-
* @returns {boolean} True if valid
|
|
706
|
-
* @throws {EasyflowError} If validation fails
|
|
707
|
-
*/
|
|
708
|
-
static validatePagination(page, limit, fieldName = 'pagination') {
|
|
709
|
-
Validator.isNumber(page, `${fieldName}.page`)
|
|
710
|
-
Validator.isNumber(limit, `${fieldName}.limit`)
|
|
711
|
-
|
|
712
|
-
if (page < 1) {
|
|
713
|
-
throwsError(
|
|
714
|
-
new EasyflowError(
|
|
715
|
-
`${fieldName}.page must be greater than 0`,
|
|
716
|
-
400,
|
|
717
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
718
|
-
)
|
|
719
|
-
)
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
if (limit < 1 || limit > 100) {
|
|
723
|
-
throwsError(
|
|
724
|
-
new EasyflowError(
|
|
725
|
-
`${fieldName}.limit must be between 1 and 100`,
|
|
726
|
-
400,
|
|
727
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
728
|
-
)
|
|
729
|
-
)
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
return true
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
/**
|
|
736
|
-
* Validates business ID format
|
|
737
|
-
* @param {string} businessId - Business ID to validate
|
|
738
|
-
* @param {string} fieldName - Field name for error message
|
|
739
|
-
* @returns {boolean} True if valid
|
|
740
|
-
* @throws {EasyflowError} If validation fails
|
|
741
|
-
*/
|
|
742
|
-
static validateBusinessId(businessId, fieldName = 'businessId') {
|
|
743
|
-
Validator.isString(businessId, fieldName)
|
|
744
|
-
|
|
745
|
-
if (!/^[a-zA-Z0-9-]{3,50}$/.test(businessId)) {
|
|
746
|
-
throwsError(
|
|
747
|
-
new EasyflowError(
|
|
748
|
-
`${fieldName} must be 3-50 characters long and contain only letters, numbers, and hyphens`,
|
|
749
|
-
400,
|
|
750
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
751
|
-
)
|
|
752
|
-
)
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
if (businessId.startsWith('-') || businessId.endsWith('-')) {
|
|
756
|
-
throwsError(
|
|
757
|
-
new EasyflowError(
|
|
758
|
-
`${fieldName} cannot start or end with a hyphen`,
|
|
759
|
-
400,
|
|
760
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
761
|
-
)
|
|
762
|
-
)
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
if (businessId.includes('--')) {
|
|
766
|
-
throwsError(
|
|
767
|
-
new EasyflowError(
|
|
768
|
-
`${fieldName} cannot contain consecutive hyphens`,
|
|
769
|
-
400,
|
|
770
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
771
|
-
)
|
|
772
|
-
)
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
return true
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
/**
|
|
779
|
-
* Validates credit card token
|
|
780
|
-
* @param {string} token - Credit card token to validate
|
|
781
|
-
* @param {string} fieldName - Field name for error message
|
|
782
|
-
* @returns {boolean} True if valid
|
|
783
|
-
* @throws {EasyflowError} If validation fails
|
|
784
|
-
*/
|
|
785
|
-
static validateCreditCardToken(token, fieldName = 'creditCardToken') {
|
|
786
|
-
Validator.isString(token, fieldName)
|
|
787
|
-
|
|
788
|
-
if (!/^[a-zA-Z0-9_-]{32,128}$/.test(token)) {
|
|
789
|
-
throwsError(
|
|
790
|
-
new EasyflowError(
|
|
791
|
-
`${fieldName} must be a valid secure token (32-128 characters, alphanumeric, underscore, hyphen)`,
|
|
792
|
-
400,
|
|
793
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
794
|
-
)
|
|
795
|
-
)
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
return true
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
/**
|
|
802
|
-
* Validates order ID format (UUID v4, UUID v7, or MongoDB ObjectId)
|
|
803
|
-
* @param {string} orderId - Order ID to validate
|
|
804
|
-
* @param {string} fieldName - Field name for error message
|
|
805
|
-
* @returns {boolean} True if valid
|
|
806
|
-
* @throws {EasyflowError} If validation fails
|
|
807
|
-
*/
|
|
808
|
-
static validateOrderId(orderId, fieldName = 'orderId') {
|
|
809
|
-
Validator.isString(orderId, fieldName)
|
|
810
|
-
|
|
811
|
-
// UUID v4: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx (y = 8,9,A,B)
|
|
812
|
-
const uuidV4Pattern =
|
|
813
|
-
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
|
814
|
-
|
|
815
|
-
// UUID v7: xxxxxxxx-xxxx-7xxx-yxxx-xxxxxxxxxxxx (y = 8,9,A,B)
|
|
816
|
-
const uuidV7Pattern =
|
|
817
|
-
/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
|
818
|
-
|
|
819
|
-
// MongoDB ObjectId: 24 hex characters
|
|
820
|
-
const mongoIdPattern = /^[0-9a-f]{24}$/i
|
|
821
|
-
|
|
822
|
-
if (
|
|
823
|
-
uuidV4Pattern.test(orderId) ||
|
|
824
|
-
uuidV7Pattern.test(orderId) ||
|
|
825
|
-
mongoIdPattern.test(orderId)
|
|
826
|
-
) {
|
|
827
|
-
return true
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
throwsError(
|
|
831
|
-
new EasyflowError(
|
|
832
|
-
`${fieldName} must be a valid UUID v4, UUID v7, or MongoDB ObjectId`,
|
|
833
|
-
400,
|
|
834
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
835
|
-
)
|
|
836
|
-
)
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
/**
|
|
840
|
-
* Validates offer ID format (UUID v4, UUID v7, or MongoDB ObjectId)
|
|
841
|
-
* @param {string} offerId - Offer ID to validate
|
|
842
|
-
* @param {string} fieldName - Field name for error message
|
|
843
|
-
* @returns {boolean} True if valid
|
|
844
|
-
* @throws {EasyflowError} If validation fails
|
|
845
|
-
*/
|
|
846
|
-
static validateOfferId(offerId, fieldName = 'offerId') {
|
|
847
|
-
Validator.isString(offerId, fieldName)
|
|
848
|
-
|
|
849
|
-
// UUID v4: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx (y = 8,9,A,B)
|
|
850
|
-
const uuidV4Pattern =
|
|
851
|
-
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
|
852
|
-
|
|
853
|
-
// UUID v7: xxxxxxxx-xxxx-7xxx-yxxx-xxxxxxxxxxxx (y = 8,9,A,B)
|
|
854
|
-
const uuidV7Pattern =
|
|
855
|
-
/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
|
856
|
-
|
|
857
|
-
// MongoDB ObjectId: 24 hex characters
|
|
858
|
-
const mongoIdPattern = /^[0-9a-f]{24}$/i
|
|
859
|
-
|
|
860
|
-
if (
|
|
861
|
-
uuidV4Pattern.test(offerId) ||
|
|
862
|
-
uuidV7Pattern.test(offerId) ||
|
|
863
|
-
mongoIdPattern.test(offerId)
|
|
864
|
-
) {
|
|
865
|
-
return true
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
throwsError(
|
|
869
|
-
new EasyflowError(
|
|
870
|
-
`${fieldName} must be a valid UUID v4, UUID v7, or MongoDB ObjectId`,
|
|
871
|
-
400,
|
|
872
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
873
|
-
)
|
|
874
|
-
)
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
/**
|
|
878
|
-
* Validates customer ID format (UUID v4, UUID v7, or MongoDB ObjectId)
|
|
879
|
-
* @param {string} customerId - Customer ID to validate
|
|
880
|
-
* @param {string} fieldName - Field name for error message
|
|
881
|
-
* @returns {boolean} True if valid
|
|
882
|
-
* @throws {EasyflowError} If validation fails
|
|
883
|
-
*/
|
|
884
|
-
static validateCustomerId(customerId, fieldName = 'customerId') {
|
|
885
|
-
Validator.isString(customerId, fieldName)
|
|
886
|
-
|
|
887
|
-
// UUID v4: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx (y = 8,9,A,B)
|
|
888
|
-
const uuidV4Pattern =
|
|
889
|
-
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
|
890
|
-
|
|
891
|
-
// UUID v7: xxxxxxxx-xxxx-7xxx-yxxx-xxxxxxxxxxxx (y = 8,9,A,B)
|
|
892
|
-
const uuidV7Pattern =
|
|
893
|
-
/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
|
894
|
-
|
|
895
|
-
// MongoDB ObjectId: 24 hex characters
|
|
896
|
-
const mongoIdPattern = /^[0-9a-f]{24}$/i
|
|
897
|
-
|
|
898
|
-
if (
|
|
899
|
-
uuidV4Pattern.test(customerId) ||
|
|
900
|
-
uuidV7Pattern.test(customerId) ||
|
|
901
|
-
mongoIdPattern.test(customerId)
|
|
902
|
-
) {
|
|
903
|
-
return true
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
throwsError(
|
|
907
|
-
new EasyflowError(
|
|
908
|
-
`${fieldName} must be a valid UUID v4, UUID v7, or MongoDB ObjectId`,
|
|
909
|
-
400,
|
|
910
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
911
|
-
)
|
|
912
|
-
)
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
/**
|
|
916
|
-
* Validates credit card ID format (UUID v4, UUID v7, or MongoDB ObjectId)
|
|
917
|
-
* @param {string} creditCardId - Credit card ID to validate
|
|
918
|
-
* @param {string} fieldName - Field name for error message
|
|
919
|
-
* @returns {boolean} True if valid
|
|
920
|
-
* @throws {EasyflowError} If validation fails
|
|
921
|
-
*/
|
|
922
|
-
static validateCreditCardId(creditCardId, fieldName = 'creditCardId') {
|
|
923
|
-
Validator.isString(creditCardId, fieldName)
|
|
924
|
-
|
|
925
|
-
// UUID v4: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx (y = 8,9,A,B)
|
|
926
|
-
const uuidV4Pattern =
|
|
927
|
-
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
|
928
|
-
|
|
929
|
-
// UUID v7: xxxxxxxx-xxxx-7xxx-yxxx-xxxxxxxxxxxx (y = 8,9,A,B)
|
|
930
|
-
const uuidV7Pattern =
|
|
931
|
-
/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
|
932
|
-
|
|
933
|
-
// MongoDB ObjectId: 24 hex characters
|
|
934
|
-
const mongoIdPattern = /^[0-9a-f]{24}$/i
|
|
935
|
-
|
|
936
|
-
if (
|
|
937
|
-
uuidV4Pattern.test(creditCardId) ||
|
|
938
|
-
uuidV7Pattern.test(creditCardId) ||
|
|
939
|
-
mongoIdPattern.test(creditCardId)
|
|
940
|
-
) {
|
|
941
|
-
return true
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
throwsError(
|
|
945
|
-
new EasyflowError(
|
|
946
|
-
`${fieldName} must be a valid UUID v4, UUID v7, or MongoDB ObjectId`,
|
|
947
|
-
400,
|
|
948
|
-
ERROR_CODES.VALIDATION_ERROR
|
|
949
|
-
)
|
|
950
|
-
)
|
|
951
|
-
}
|
|
952
|
-
}
|