data-validation-proximity 1.1.0 → 1.1.2
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 +330 -0
- package/index.js +3 -2
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
# Data Validation Proximity
|
|
2
|
+
|
|
3
|
+
A comprehensive library of Joi-based validation middlewares for Express.js applications, specifically designed for e-commerce platforms with complex data structures.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install data-validation-proximity
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Dependencies
|
|
12
|
+
|
|
13
|
+
This package requires Joi for validation:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install joi@^17.x
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
### Basic Setup
|
|
22
|
+
|
|
23
|
+
```javascript
|
|
24
|
+
const express = require('express');
|
|
25
|
+
const {
|
|
26
|
+
validateUser,
|
|
27
|
+
validateProduct,
|
|
28
|
+
validateStore
|
|
29
|
+
} = require('data-validation-proximity');
|
|
30
|
+
|
|
31
|
+
const app = express();
|
|
32
|
+
app.use(express.json());
|
|
33
|
+
|
|
34
|
+
// Apply validation middleware to routes
|
|
35
|
+
app.post('/api/users', validateUser, (req, res) => {
|
|
36
|
+
// req.body is validated
|
|
37
|
+
res.json({ message: 'User created' });
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
app.post('/api/products', validateProduct, (req, res) => {
|
|
41
|
+
// req.body is validated and preprocessed
|
|
42
|
+
res.json({ message: 'Product created' });
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
app.post('/api/stores', validateStore, (req, res) => {
|
|
46
|
+
// req.body is validated
|
|
47
|
+
res.json({ message: 'Store created' });
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Available Validation Middlewares
|
|
52
|
+
|
|
53
|
+
### User & Authentication
|
|
54
|
+
|
|
55
|
+
- **`validateUser`** - Validates user registration/creation
|
|
56
|
+
- **`validateUserUpdate`** - Validates user profile updates
|
|
57
|
+
- **`validateLogin`** - Validates login credentials
|
|
58
|
+
- **`validateResetPassword`** - Validates password reset requests
|
|
59
|
+
|
|
60
|
+
### Store Management
|
|
61
|
+
|
|
62
|
+
- **`validateStore`** - Validates store creation with full details
|
|
63
|
+
- **`validateStoreUpdate`** - Validates store information updates
|
|
64
|
+
- **`validateStoreCategory`** - Validates store category data
|
|
65
|
+
- **`validateStoreRate`** - Validates store rating submissions
|
|
66
|
+
|
|
67
|
+
### Product Management
|
|
68
|
+
|
|
69
|
+
- **`validateProduct`** - Validates product creation with images and variants
|
|
70
|
+
- **`validateProductUpdate`** - Validates product updates
|
|
71
|
+
- **`validateCategory`** - Validates product category data
|
|
72
|
+
|
|
73
|
+
### Orders & Transactions
|
|
74
|
+
|
|
75
|
+
- **`validateOrder`** - Validates order placement
|
|
76
|
+
- **`validateCart`** - Validates shopping cart data
|
|
77
|
+
- **`validateBill`** - Validates billing information
|
|
78
|
+
- **`validatePayment`** - Validates payment transactions
|
|
79
|
+
- **`validatePaymentType`** - Validates payment method types
|
|
80
|
+
|
|
81
|
+
### Promotions & Offers
|
|
82
|
+
|
|
83
|
+
- **`validateOffer`** - Validates special offers/promotions
|
|
84
|
+
- **`validateFlashDeal`** - Validates flash sale deals
|
|
85
|
+
- **`validateReductionOffer`** - Validates discount offers
|
|
86
|
+
|
|
87
|
+
### Subscriptions
|
|
88
|
+
|
|
89
|
+
- **`validatePlan`** - Validates subscription plans
|
|
90
|
+
- **`validateSubscription`** - Validates subscription data
|
|
91
|
+
- **`validateSubscriptionOffer`** - Validates subscription offer details
|
|
92
|
+
|
|
93
|
+
### Other
|
|
94
|
+
|
|
95
|
+
- **`validateNotification`** - Validates notification data
|
|
96
|
+
- **`validateSale`** - Validates sales records
|
|
97
|
+
- **`validateView`** - Validates view tracking data
|
|
98
|
+
- **`validateUserAction`** - Validates user activity tracking
|
|
99
|
+
|
|
100
|
+
## Features
|
|
101
|
+
|
|
102
|
+
### Automatic Data Preprocessing
|
|
103
|
+
|
|
104
|
+
The library includes intelligent preprocessing for complex data:
|
|
105
|
+
|
|
106
|
+
#### JSON Field Parsing
|
|
107
|
+
|
|
108
|
+
Automatically parses stringified JSON fields:
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
// Before validation, string fields are parsed to objects
|
|
112
|
+
app.post('/api/products', validateProduct, (req, res) => {
|
|
113
|
+
// req.body.variants: "[{...}]" → [{...}]
|
|
114
|
+
// req.body.policy: "{...}" → {...}
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### File Array Normalization
|
|
119
|
+
|
|
120
|
+
Normalizes file uploads for consistent handling:
|
|
121
|
+
|
|
122
|
+
```javascript
|
|
123
|
+
// Single file uploads are converted to arrays
|
|
124
|
+
app.post('/api/products', validateProduct, (req, res) => {
|
|
125
|
+
// req.files.images: single file → [file]
|
|
126
|
+
// req.files.varientsImages: single file → [file]
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Complex Schema Support
|
|
131
|
+
|
|
132
|
+
#### Address Schema
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
{
|
|
136
|
+
latitude: Number,
|
|
137
|
+
longitude: Number,
|
|
138
|
+
countryCode: String (min 2 chars),
|
|
139
|
+
country: String (min 3 chars),
|
|
140
|
+
city: String (min 3 chars),
|
|
141
|
+
streetName: String (min 3 chars),
|
|
142
|
+
postalCode: String (min 3 chars),
|
|
143
|
+
fullAdress: String,
|
|
144
|
+
region: String,
|
|
145
|
+
apartmentNumber: String
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### Working Time Schema
|
|
150
|
+
|
|
151
|
+
```javascript
|
|
152
|
+
{
|
|
153
|
+
option: String (required),
|
|
154
|
+
fixedHours: [{
|
|
155
|
+
openTime: String,
|
|
156
|
+
closeTime: String
|
|
157
|
+
}],
|
|
158
|
+
customizedHours: {
|
|
159
|
+
[dayName]: [{
|
|
160
|
+
openTime: String,
|
|
161
|
+
closeTime: String
|
|
162
|
+
}]
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### Policy Schema
|
|
168
|
+
|
|
169
|
+
Comprehensive policy validation for:
|
|
170
|
+
- Working hours
|
|
171
|
+
- Pickup policies
|
|
172
|
+
- Delivery options
|
|
173
|
+
- Reservation rules (duration, payment, cancellation)
|
|
174
|
+
- Return policies (duration, conditions, refunds)
|
|
175
|
+
- Order management (validation, notifications)
|
|
176
|
+
|
|
177
|
+
### Role Validation
|
|
178
|
+
|
|
179
|
+
Built-in support for role-based validation:
|
|
180
|
+
|
|
181
|
+
```javascript
|
|
182
|
+
// Valid roles: 'user', 'admin', 'seller', 'paymentManager', 'manager', 'SuperManager'
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Examples
|
|
186
|
+
|
|
187
|
+
### User Registration
|
|
188
|
+
|
|
189
|
+
```javascript
|
|
190
|
+
const { validateUser } = require('data-validation-proximity');
|
|
191
|
+
|
|
192
|
+
app.post('/api/register', validateUser, async (req, res) => {
|
|
193
|
+
// req.body contains validated data:
|
|
194
|
+
// - username, email, password, phone
|
|
195
|
+
// - optional: address, profileImage, etc.
|
|
196
|
+
const user = await User.create(req.body);
|
|
197
|
+
res.status(201).json(user);
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Product Creation
|
|
202
|
+
|
|
203
|
+
```javascript
|
|
204
|
+
const { validateProduct } = require('data-validation-proximity');
|
|
205
|
+
|
|
206
|
+
app.post('/api/products', validateProduct, async (req, res) => {
|
|
207
|
+
// Automatically preprocessed:
|
|
208
|
+
// - JSON strings parsed to objects
|
|
209
|
+
// - File arrays normalized
|
|
210
|
+
// - Validated: name, price, category, variants, policy
|
|
211
|
+
const product = await Product.create(req.body);
|
|
212
|
+
res.status(201).json(product);
|
|
213
|
+
});
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Store Setup
|
|
217
|
+
|
|
218
|
+
```javascript
|
|
219
|
+
const { validateStore } = require('data-validation-proximity');
|
|
220
|
+
|
|
221
|
+
app.post('/api/stores', validateStore, async (req, res) => {
|
|
222
|
+
// Validated data includes:
|
|
223
|
+
// - store details (name, description, category)
|
|
224
|
+
// - address with coordinates
|
|
225
|
+
// - working hours
|
|
226
|
+
// - policies
|
|
227
|
+
// - payment methods
|
|
228
|
+
const store = await Store.create(req.body);
|
|
229
|
+
res.status(201).json(store);
|
|
230
|
+
});
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Order Placement
|
|
234
|
+
|
|
235
|
+
```javascript
|
|
236
|
+
const { validateOrder } = require('data-validation-proximity');
|
|
237
|
+
|
|
238
|
+
app.post('/api/orders', validateOrder, async (req, res) => {
|
|
239
|
+
// Validated: products, amounts, addresses, payment info
|
|
240
|
+
const order = await Order.create(req.body);
|
|
241
|
+
res.status(201).json(order);
|
|
242
|
+
});
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Error Handling
|
|
246
|
+
|
|
247
|
+
Validation errors return a 400 status with detailed error messages:
|
|
248
|
+
|
|
249
|
+
```javascript
|
|
250
|
+
// Invalid request
|
|
251
|
+
{
|
|
252
|
+
"error": "\"email\" must be a valid email"
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Multiple validation errors
|
|
256
|
+
{
|
|
257
|
+
"error": "\"price\" must be a positive number"
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Integration with Custom Error Library
|
|
262
|
+
|
|
263
|
+
Works seamlessly with `custom-error-library`:
|
|
264
|
+
|
|
265
|
+
```javascript
|
|
266
|
+
const { errorMiddleware } = require('custom-error-library');
|
|
267
|
+
const { validateProduct } = require('data-validation-proximity');
|
|
268
|
+
|
|
269
|
+
app.post('/api/products', validateProduct, createProduct);
|
|
270
|
+
|
|
271
|
+
// Error middleware handles validation errors
|
|
272
|
+
app.use(errorMiddleware);
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Advanced Usage
|
|
276
|
+
|
|
277
|
+
### Custom Validation Middleware
|
|
278
|
+
|
|
279
|
+
You can create custom validation middlewares using the exported helper:
|
|
280
|
+
|
|
281
|
+
```javascript
|
|
282
|
+
const { createValidationMiddleware } = require('data-validation-proximity');
|
|
283
|
+
const Joi = require('joi');
|
|
284
|
+
|
|
285
|
+
const customSchema = Joi.object({
|
|
286
|
+
customField: Joi.string().required()
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
const validateCustom = createValidationMiddleware(customSchema);
|
|
290
|
+
|
|
291
|
+
app.post('/api/custom', validateCustom, handler);
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Preprocessing Hooks
|
|
295
|
+
|
|
296
|
+
For complex data transformations, validation middlewares include preprocessing:
|
|
297
|
+
|
|
298
|
+
```javascript
|
|
299
|
+
// Example: Product validation with preprocessing
|
|
300
|
+
// 1. Parses JSON strings (variants, policy, etc.)
|
|
301
|
+
// 2. Normalizes file arrays
|
|
302
|
+
// 3. Validates against schema
|
|
303
|
+
// 4. Passes to route handler
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Best Practices
|
|
307
|
+
|
|
308
|
+
1. **Apply validation early** - Use validation middleware before business logic
|
|
309
|
+
2. **Combine with error handling** - Use with `custom-error-library` for consistent errors
|
|
310
|
+
3. **Use appropriate validators** - Choose specific validators (validateUser vs validateUserUpdate)
|
|
311
|
+
4. **Handle file uploads** - Validation automatically normalizes file arrays
|
|
312
|
+
5. **Trust preprocessed data** - Data is cleaned and parsed before validation
|
|
313
|
+
|
|
314
|
+
## Schema Reference
|
|
315
|
+
|
|
316
|
+
### Common Field Types
|
|
317
|
+
|
|
318
|
+
| Field Type | Validation Rules | Example |
|
|
319
|
+
|------------|-----------------|---------|
|
|
320
|
+
| Email | Valid email format | `user@example.com` |
|
|
321
|
+
| Phone | String, min 8 chars | `+1234567890` |
|
|
322
|
+
| Password | String, min 6 chars | `securePass123` |
|
|
323
|
+
| Price | Positive number | `29.99` |
|
|
324
|
+
| Coordinates | Number (lat/lng) | `34.0522, -118.2437` |
|
|
325
|
+
| URL | Valid URL format | `https://example.com` |
|
|
326
|
+
| Role | Enum of valid roles | `seller`, `admin` |
|
|
327
|
+
|
|
328
|
+
## License
|
|
329
|
+
|
|
330
|
+
MIT
|
package/index.js
CHANGED
|
@@ -165,7 +165,7 @@ const addressSchema = joi.object({
|
|
|
165
165
|
city: joi.string().min(3),
|
|
166
166
|
streetName: joi.string().min(3),
|
|
167
167
|
postalCode: joi.string().min(3),
|
|
168
|
-
|
|
168
|
+
fullAddress: joi.string(),
|
|
169
169
|
region: joi.string(),
|
|
170
170
|
apartmentNumber: joi.string(),
|
|
171
171
|
});
|
|
@@ -207,6 +207,7 @@ const userSchema = joi.object({
|
|
|
207
207
|
role: joi.string().valid(...validRoles).required(),
|
|
208
208
|
cart: joi.string().allow(null).allow(''),
|
|
209
209
|
google: joi.boolean(),
|
|
210
|
+
profileImage: joi.string(),
|
|
210
211
|
});
|
|
211
212
|
|
|
212
213
|
exports.userSchemaValidation = createValidationMiddleware(userSchema);
|
|
@@ -268,7 +269,7 @@ const updateSchema = joi.object({
|
|
|
268
269
|
city: joi.string().min(3),
|
|
269
270
|
streetName: joi.string().min(3),
|
|
270
271
|
postalCode: joi.string().min(3),
|
|
271
|
-
|
|
272
|
+
fullAddress: joi.string(),
|
|
272
273
|
region: joi.string(),
|
|
273
274
|
apartmentNumber: joi.string(),
|
|
274
275
|
}),
|