@feardread/fear 1.0.1
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/FEAR.js +459 -0
- package/FEARServer.js +280 -0
- package/controllers/agent.js +438 -0
- package/controllers/auth/index.js +345 -0
- package/controllers/auth/token.js +50 -0
- package/controllers/blog.js +105 -0
- package/controllers/brand.js +10 -0
- package/controllers/cart.js +425 -0
- package/controllers/category.js +9 -0
- package/controllers/coupon.js +63 -0
- package/controllers/crud/crud.js +508 -0
- package/controllers/crud/index.js +36 -0
- package/controllers/email.js +34 -0
- package/controllers/enquiry.js +65 -0
- package/controllers/events.js +9 -0
- package/controllers/order.js +125 -0
- package/controllers/payment.js +31 -0
- package/controllers/product.js +147 -0
- package/controllers/review.js +247 -0
- package/controllers/tag.js +10 -0
- package/controllers/task.js +10 -0
- package/controllers/upload.js +41 -0
- package/controllers/user.js +401 -0
- package/index.js +7 -0
- package/libs/agent/index.js +561 -0
- package/libs/agent/modules/ai/ai.js +285 -0
- package/libs/agent/modules/ai/chat.js +518 -0
- package/libs/agent/modules/ai/config.js +688 -0
- package/libs/agent/modules/ai/operations.js +787 -0
- package/libs/agent/modules/analyze/api.js +546 -0
- package/libs/agent/modules/analyze/dorks.js +395 -0
- package/libs/agent/modules/ccard/README.md +454 -0
- package/libs/agent/modules/ccard/audit.js +479 -0
- package/libs/agent/modules/ccard/checker.js +674 -0
- package/libs/agent/modules/ccard/payment-processors.json +16 -0
- package/libs/agent/modules/ccard/validator.js +629 -0
- package/libs/agent/modules/code/analyzer.js +303 -0
- package/libs/agent/modules/code/jquery.js +1093 -0
- package/libs/agent/modules/code/react.js +1536 -0
- package/libs/agent/modules/code/refactor.js +499 -0
- package/libs/agent/modules/crypto/exchange.js +564 -0
- package/libs/agent/modules/net/proxy.js +409 -0
- package/libs/agent/modules/security/cve.js +442 -0
- package/libs/agent/modules/security/monitor.js +360 -0
- package/libs/agent/modules/security/scanner.js +300 -0
- package/libs/agent/modules/security/vulnerability.js +506 -0
- package/libs/agent/modules/security/web.js +465 -0
- package/libs/agent/modules/utils/browser.js +492 -0
- package/libs/agent/modules/utils/colorizer.js +285 -0
- package/libs/agent/modules/utils/manager.js +478 -0
- package/libs/cloud/index.js +228 -0
- package/libs/config/db.js +21 -0
- package/libs/config/validator.js +82 -0
- package/libs/db/index.js +318 -0
- package/libs/emailer/imap.js +126 -0
- package/libs/emailer/info.js +41 -0
- package/libs/emailer/smtp.js +77 -0
- package/libs/handler/async.js +3 -0
- package/libs/handler/error.js +66 -0
- package/libs/handler/index.js +161 -0
- package/libs/logger/index.js +49 -0
- package/libs/logger/morgan.js +24 -0
- package/libs/passport/passport.js +109 -0
- package/libs/search/api.js +384 -0
- package/libs/search/features.js +219 -0
- package/libs/search/service.js +64 -0
- package/libs/swagger/config.js +18 -0
- package/libs/swagger/index.js +35 -0
- package/libs/validator/index.js +254 -0
- package/models/blog.js +31 -0
- package/models/brand.js +12 -0
- package/models/cart.js +14 -0
- package/models/category.js +11 -0
- package/models/coupon.js +9 -0
- package/models/customer.js +0 -0
- package/models/enquiry.js +29 -0
- package/models/events.js +13 -0
- package/models/order.js +94 -0
- package/models/product.js +32 -0
- package/models/review.js +14 -0
- package/models/tag.js +10 -0
- package/models/task.js +11 -0
- package/models/user.js +68 -0
- package/package.json +12 -0
- package/routes/agent.js +615 -0
- package/routes/auth.js +13 -0
- package/routes/blog.js +19 -0
- package/routes/brand.js +15 -0
- package/routes/cart.js +105 -0
- package/routes/category.js +16 -0
- package/routes/coupon.js +15 -0
- package/routes/enquiry.js +14 -0
- package/routes/events.js +16 -0
- package/routes/mail.js +170 -0
- package/routes/order.js +19 -0
- package/routes/product.js +22 -0
- package/routes/review.js +11 -0
- package/routes/task.js +12 -0
- package/routes/user.js +17 -0
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
const { tryCatch } = require("../../libs/handler/error");
|
|
2
|
+
const cloud = require("../../libs/cloud");
|
|
3
|
+
const SearchApi = require("../../libs/search/api");
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Generic CRUD operations for any Mongoose Model
|
|
7
|
+
* All methods use then/catch pattern for consistency
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Get all documents for requested Model
|
|
11
|
+
* @param {mongoose.Model} Model - Mongoose model
|
|
12
|
+
* @param {Object} req - Express request object
|
|
13
|
+
* @param {Object} res - Express response object
|
|
14
|
+
* @returns {boolean} Success
|
|
15
|
+
* @returns {string} Message
|
|
16
|
+
* @returns {Array} Result: Array of found Documents
|
|
17
|
+
*/
|
|
18
|
+
exports.all = tryCatch(async (Model, req, res) => {
|
|
19
|
+
const { sort = 'category', order = 'asc', populate = true } = req.query;
|
|
20
|
+
let query = Model.find();
|
|
21
|
+
// Apply sorting
|
|
22
|
+
const sortOrder = order === 'desc' ? 'desc' : 'asc';
|
|
23
|
+
query = query.sort({ [sort]: sortOrder });
|
|
24
|
+
// Apply population if requested
|
|
25
|
+
if (populate && populate !== 'false') {
|
|
26
|
+
query = query.populate();
|
|
27
|
+
}
|
|
28
|
+
return query
|
|
29
|
+
.then((result) => {
|
|
30
|
+
if (!result || result.length === 0) {
|
|
31
|
+
return res.status(200).json({ result: [], success: true, message: "No documents found", count: 0 });
|
|
32
|
+
}
|
|
33
|
+
return res.status(200).json({
|
|
34
|
+
result, success: true, message: `Found ${result.length} documents`, count: result.length
|
|
35
|
+
});
|
|
36
|
+
})
|
|
37
|
+
.catch((error) => {
|
|
38
|
+
console.error('Error in all method:', error);
|
|
39
|
+
return res.status(500).json({ result: null, success: false, message: "Error retrieving documents", error: error.message });
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Retrieves a single document by id
|
|
45
|
+
* @param {mongoose.Model} Model - Mongoose model
|
|
46
|
+
* @param {Object} req - Express request object
|
|
47
|
+
* @param {Object} res - Express response object
|
|
48
|
+
* @param {string} req.params.id - Document ID
|
|
49
|
+
* @returns {Document} Single Document
|
|
50
|
+
*/
|
|
51
|
+
exports.read = tryCatch(async (Model, req, res) => {
|
|
52
|
+
console.log('crud read id = ', req.params);
|
|
53
|
+
/*
|
|
54
|
+
if (!req.params || !req.params.id) {
|
|
55
|
+
return res.status(400).json({
|
|
56
|
+
result: null,
|
|
57
|
+
success: false,
|
|
58
|
+
message: "Document ID is required"
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
*/
|
|
62
|
+
const { id } = req.query;
|
|
63
|
+
const { populate = true } = req.query;
|
|
64
|
+
|
|
65
|
+
/*
|
|
66
|
+
// Validate ObjectId format
|
|
67
|
+
if (!id.match(/^[0-9a-fA-F]{24}$/)) {
|
|
68
|
+
return res.status(400).json({
|
|
69
|
+
result: null,
|
|
70
|
+
success: false,
|
|
71
|
+
message: "Invalid document ID format"
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
*/
|
|
75
|
+
let query = Model.findById(id);
|
|
76
|
+
|
|
77
|
+
// Apply population if requested
|
|
78
|
+
if (populate && populate !== 'false') {
|
|
79
|
+
query = query.populate();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return query
|
|
83
|
+
.then((result) => {
|
|
84
|
+
if (!result) {
|
|
85
|
+
return res.status(404).json({
|
|
86
|
+
result: null,
|
|
87
|
+
success: false,
|
|
88
|
+
message: `Document with ID ${id} not found`
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return res.status(200).json({
|
|
93
|
+
result,
|
|
94
|
+
success: true,
|
|
95
|
+
message: "Document found successfully"
|
|
96
|
+
});
|
|
97
|
+
})
|
|
98
|
+
.catch((error) => {
|
|
99
|
+
console.error('Error in read method:', error);
|
|
100
|
+
return res.status(500).json({
|
|
101
|
+
result: null,
|
|
102
|
+
success: false,
|
|
103
|
+
message: "Error retrieving document",
|
|
104
|
+
error: error.message
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Creates a single document with all necessary req.body fields
|
|
111
|
+
* @param {mongoose.Model} Model - Mongoose model
|
|
112
|
+
* @param {Object} req - Express request object
|
|
113
|
+
* @param {Object} res - Express response object
|
|
114
|
+
* @param {Object} req.body - Document data
|
|
115
|
+
* @returns {string} Message
|
|
116
|
+
*/
|
|
117
|
+
exports.create = tryCatch(async (Model, req, res) => {
|
|
118
|
+
const documentData = { ...req.body };
|
|
119
|
+
|
|
120
|
+
// Handle image uploads if present
|
|
121
|
+
if (documentData.images) {
|
|
122
|
+
documentData.images.split(',').map(item => item.trim());
|
|
123
|
+
|
|
124
|
+
const imageLinks = await cloud.uploadImages(documentData.images);
|
|
125
|
+
if ( imageLinks ) documentData.images = imageLinks;
|
|
126
|
+
console.log('Added Images:', imageLinks);
|
|
127
|
+
}
|
|
128
|
+
console.log('Creating modified document:', documentData);
|
|
129
|
+
await new Model(documentData).save()
|
|
130
|
+
.then((result) => {
|
|
131
|
+
if (!result) {
|
|
132
|
+
throw new Error("Failed to save document");
|
|
133
|
+
}
|
|
134
|
+
return res.status(201).json({
|
|
135
|
+
result, success: true, message: `Document created successfully in ${Model.modelName} collection`
|
|
136
|
+
});
|
|
137
|
+
})
|
|
138
|
+
.catch((error) => {
|
|
139
|
+
console.error('Error in create method with images:', error);
|
|
140
|
+
|
|
141
|
+
if (error.name === "ValidationError") {
|
|
142
|
+
return res.status(400).json({
|
|
143
|
+
result: null,
|
|
144
|
+
success: false,
|
|
145
|
+
message: "Validation failed: Required fields are missing or invalid",
|
|
146
|
+
errors: error.errors
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return res.status(500).json({
|
|
151
|
+
result: null,
|
|
152
|
+
success: false,
|
|
153
|
+
message: "Internal server error during document creation",
|
|
154
|
+
error: error.message
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Updates a single document
|
|
162
|
+
* @param {mongoose.Model} Model - Mongoose model
|
|
163
|
+
* @param {Object} req - Express request object
|
|
164
|
+
* @param {Object} res - Express response object
|
|
165
|
+
* @param {Object} req.body - Updated document data
|
|
166
|
+
* @param {string} req.params.id - Document ID
|
|
167
|
+
* @returns {Document} Returns updated document
|
|
168
|
+
*/
|
|
169
|
+
exports.update = tryCatch(async (Model, req, res) => {
|
|
170
|
+
if (!req.params || !req.params.id) {
|
|
171
|
+
return res.status(400).json({
|
|
172
|
+
result: null,
|
|
173
|
+
success: false,
|
|
174
|
+
message: "Document ID is required"
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const { id } = req.params;
|
|
179
|
+
const updateData = { ...req.body };
|
|
180
|
+
|
|
181
|
+
// Remove undefined values
|
|
182
|
+
Object.keys(updateData).forEach(key => {
|
|
183
|
+
if (updateData[key] === undefined) {
|
|
184
|
+
delete updateData[key];
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Validate ObjectId format
|
|
189
|
+
if (!id.match(/^[0-9a-fA-F]{24}$/)) {
|
|
190
|
+
return res.status(400).json({
|
|
191
|
+
result: null,
|
|
192
|
+
success: false,
|
|
193
|
+
message: "Invalid document ID format"
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Handle image uploads if present
|
|
198
|
+
if (updateData.images && Array.isArray(updateData.images)) {
|
|
199
|
+
return cloud.uploadImages(updateData.images)
|
|
200
|
+
.then((uploadedImages) => {
|
|
201
|
+
updateData.images = uploadedImages;
|
|
202
|
+
|
|
203
|
+
// Update document with uploaded images
|
|
204
|
+
return Model.findOneAndUpdate(
|
|
205
|
+
{ _id: id },
|
|
206
|
+
updateData,
|
|
207
|
+
{ new: true, runValidators: true }
|
|
208
|
+
).exec();
|
|
209
|
+
})
|
|
210
|
+
.then((result) => {
|
|
211
|
+
if (!result) {
|
|
212
|
+
return res.status(404).json({
|
|
213
|
+
result: null,
|
|
214
|
+
success: false,
|
|
215
|
+
message: `Document with ID ${id} not found`
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return res.status(200).json({
|
|
220
|
+
result,
|
|
221
|
+
success: true,
|
|
222
|
+
message: `Document updated successfully with ID: ${id}`
|
|
223
|
+
});
|
|
224
|
+
})
|
|
225
|
+
.catch((error) => {
|
|
226
|
+
console.error('Error in update method with images:', error);
|
|
227
|
+
|
|
228
|
+
if (error.name === "ValidationError") {
|
|
229
|
+
return res.status(400).json({
|
|
230
|
+
result: null,
|
|
231
|
+
success: false,
|
|
232
|
+
message: "Validation failed: Invalid field values provided",
|
|
233
|
+
errors: error.errors
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return res.status(500).json({
|
|
238
|
+
result: null,
|
|
239
|
+
success: false,
|
|
240
|
+
message: "Internal server error during document update",
|
|
241
|
+
error: error.message
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Update document without image uploads
|
|
247
|
+
return Model.findOneAndUpdate(
|
|
248
|
+
{ _id: id },
|
|
249
|
+
updateData,
|
|
250
|
+
{ new: true, runValidators: true }
|
|
251
|
+
)
|
|
252
|
+
.exec()
|
|
253
|
+
.then((result) => {
|
|
254
|
+
if (!result) {
|
|
255
|
+
return res.status(404).json({
|
|
256
|
+
result: null,
|
|
257
|
+
success: false,
|
|
258
|
+
message: `Document with ID ${id} not found`
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return res.status(200).json({
|
|
263
|
+
result,
|
|
264
|
+
success: true,
|
|
265
|
+
message: `Document updated successfully with ID: ${id}`
|
|
266
|
+
});
|
|
267
|
+
})
|
|
268
|
+
.catch((error) => {
|
|
269
|
+
console.error('Error in update method:', error);
|
|
270
|
+
|
|
271
|
+
if (error.name === "ValidationError") {
|
|
272
|
+
return res.status(400).json({
|
|
273
|
+
result: null,
|
|
274
|
+
success: false,
|
|
275
|
+
message: "Validation failed: Invalid field values provided",
|
|
276
|
+
errors: error.errors
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (error.code === 11000) {
|
|
281
|
+
return res.status(409).json({
|
|
282
|
+
result: null,
|
|
283
|
+
success: false,
|
|
284
|
+
message: "Update failed: Duplicate value for unique field",
|
|
285
|
+
error: error.message
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return res.status(500).json({
|
|
290
|
+
result: null,
|
|
291
|
+
success: false,
|
|
292
|
+
message: "Internal server error during document update",
|
|
293
|
+
error: error.message
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Delete a single document
|
|
300
|
+
* @param {mongoose.Model} Model - Mongoose model
|
|
301
|
+
* @param {Object} req - Express request object
|
|
302
|
+
* @param {Object} res - Express response object
|
|
303
|
+
* @param {string} req.params.id - Document ID
|
|
304
|
+
* @returns {string} Message response
|
|
305
|
+
*/
|
|
306
|
+
exports.delete = tryCatch(async (Model, req, res) => {
|
|
307
|
+
if (!req.params || !req.params.id) {
|
|
308
|
+
return res.status(400).json({
|
|
309
|
+
result: null,
|
|
310
|
+
success: false,
|
|
311
|
+
message: "Document ID is required"
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const { id } = req.params;
|
|
316
|
+
|
|
317
|
+
// Validate ObjectId format
|
|
318
|
+
if (!id.match(/^[0-9a-fA-F]{24}$/)) {
|
|
319
|
+
return res.status(400).json({
|
|
320
|
+
result: null,
|
|
321
|
+
success: false,
|
|
322
|
+
message: "Invalid document ID format"
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return Model.findOneAndDelete({ _id: id })
|
|
327
|
+
.exec()
|
|
328
|
+
.then((result) => {
|
|
329
|
+
if (!result) {
|
|
330
|
+
return res.status(404).json({
|
|
331
|
+
result: null,
|
|
332
|
+
success: false,
|
|
333
|
+
message: `Document with ID ${id} not found`
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// TODO: Clean up associated images if they exist
|
|
338
|
+
if (result.images && Array.isArray(result.images)) {
|
|
339
|
+
// Could add cloud.deleteImages(result.images) here
|
|
340
|
+
console.log('Document had images that should be cleaned up:', result.images);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return res.status(200).json({
|
|
344
|
+
result,
|
|
345
|
+
success: true,
|
|
346
|
+
message: `Document deleted successfully with ID: ${id}`
|
|
347
|
+
});
|
|
348
|
+
})
|
|
349
|
+
.catch((error) => {
|
|
350
|
+
console.error('Error in delete method:', error);
|
|
351
|
+
return res.status(500).json({
|
|
352
|
+
result: null,
|
|
353
|
+
success: false,
|
|
354
|
+
message: "Error deleting document",
|
|
355
|
+
error: error.message
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Get paginated list of documents
|
|
362
|
+
* @param {mongoose.Model} Model - Mongoose model
|
|
363
|
+
* @param {Object} req - Express request object
|
|
364
|
+
* @param {Object} res - Express response object
|
|
365
|
+
* @param {Object} req.query - Query parameters
|
|
366
|
+
* @returns {Object} Results with pagination
|
|
367
|
+
*/
|
|
368
|
+
exports.list = tryCatch(async (Model, req, res) => {
|
|
369
|
+
const page = parseInt(req.query.page) || 1;
|
|
370
|
+
const limit = parseInt(req.query.items) || 10;
|
|
371
|
+
const skip = (page - 1) * limit;
|
|
372
|
+
const { sort = 'createdAt', order = 'desc', populate = true } = req.query;
|
|
373
|
+
|
|
374
|
+
// Limit maximum items per page
|
|
375
|
+
const maxLimit = Math.min(limit, 100);
|
|
376
|
+
const sortOrder = order === 'asc' ? 1 : -1;
|
|
377
|
+
|
|
378
|
+
// Create count and results promises
|
|
379
|
+
const countPromise = Model.countDocuments();
|
|
380
|
+
|
|
381
|
+
let resultsQuery = Model.find()
|
|
382
|
+
.skip(skip)
|
|
383
|
+
.limit(maxLimit)
|
|
384
|
+
.sort({ [sort]: sortOrder });
|
|
385
|
+
|
|
386
|
+
// Apply population if requested
|
|
387
|
+
if (populate && populate !== 'false') {
|
|
388
|
+
resultsQuery = resultsQuery.populate();
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const resultsPromise = resultsQuery.exec();
|
|
392
|
+
|
|
393
|
+
return Promise.all([resultsPromise, countPromise])
|
|
394
|
+
.then(([result, count]) => {
|
|
395
|
+
const totalPages = Math.ceil(count / maxLimit);
|
|
396
|
+
const pagination = {
|
|
397
|
+
currentPage: page,
|
|
398
|
+
totalPages,
|
|
399
|
+
totalItems: count,
|
|
400
|
+
itemsPerPage: maxLimit,
|
|
401
|
+
hasNextPage: page < totalPages,
|
|
402
|
+
hasPrevPage: page > 1
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
if (count > 0) {
|
|
406
|
+
return res.status(200).json({
|
|
407
|
+
result,
|
|
408
|
+
success: true,
|
|
409
|
+
pagination,
|
|
410
|
+
message: `Found ${result.length} of ${count} documents`
|
|
411
|
+
});
|
|
412
|
+
} else {
|
|
413
|
+
return res.status(200).json({
|
|
414
|
+
result: [],
|
|
415
|
+
success: true,
|
|
416
|
+
pagination,
|
|
417
|
+
message: "Collection is empty"
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
})
|
|
421
|
+
.catch((error) => {
|
|
422
|
+
console.error('Error in list method:', error);
|
|
423
|
+
return res.status(500).json({
|
|
424
|
+
result: null,
|
|
425
|
+
success: false,
|
|
426
|
+
message: "Error retrieving document list",
|
|
427
|
+
error: error.message
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Search documents with specific properties
|
|
434
|
+
* @param {mongoose.Model} Model - Mongoose model
|
|
435
|
+
* @param {Object} req - Express request object
|
|
436
|
+
* @param {Object} res - Express response object
|
|
437
|
+
* @param {Object} req.query - Query parameters
|
|
438
|
+
* @returns {Array} List of Documents
|
|
439
|
+
*/
|
|
440
|
+
exports.search = tryCatch(async (Model, req, res) => {
|
|
441
|
+
console.log('crud serach req:: ', req.query);
|
|
442
|
+
const {
|
|
443
|
+
keyword,
|
|
444
|
+
category,
|
|
445
|
+
brand,
|
|
446
|
+
minPrice,
|
|
447
|
+
maxPrice,
|
|
448
|
+
rating,
|
|
449
|
+
sortBy = 'popularity',
|
|
450
|
+
page = 1,
|
|
451
|
+
limit = 24
|
|
452
|
+
} = req.query;
|
|
453
|
+
|
|
454
|
+
// Build query object
|
|
455
|
+
const queryObj = { page, limit };
|
|
456
|
+
if (keyword) queryObj.keyword = keyword;
|
|
457
|
+
if (category) queryObj.category = category;
|
|
458
|
+
if (brand) queryObj.brand = { in: brand }; // Support multiple brands
|
|
459
|
+
if (minPrice || maxPrice) {
|
|
460
|
+
queryObj.price = {};
|
|
461
|
+
if (minPrice) queryObj.price.gte = minPrice;
|
|
462
|
+
if (maxPrice) queryObj.price.lte = maxPrice;
|
|
463
|
+
}
|
|
464
|
+
if (rating) queryObj.rating = { gte: rating };
|
|
465
|
+
|
|
466
|
+
const sortOptions = {
|
|
467
|
+
popularity: { popularity: -1 },
|
|
468
|
+
newest: { createdAt: -1 },
|
|
469
|
+
'price-low': { price: 1 },
|
|
470
|
+
'price-high': { price: -1 },
|
|
471
|
+
rating: { rating: -1 }
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
const Search = new SearchApi(Model, queryObj, {
|
|
475
|
+
searchFields: ['_id', 'id', 'price', 'name', 'description', 'tags'],
|
|
476
|
+
defaultSort: sortOptions[sortBy] || sortOptions.popularity
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
return await Search
|
|
480
|
+
.search(['_id', 'id', 'price', 'name', 'description', 'brand', 'tags'])
|
|
481
|
+
.filter()
|
|
482
|
+
.sort()
|
|
483
|
+
.selectFields('-__v,-updatedAt')
|
|
484
|
+
.populate('reviews')
|
|
485
|
+
.paginate(limit, 50) // Max 50 items per page
|
|
486
|
+
.execute()
|
|
487
|
+
.then((result) => { return res.status(200).json({ success: true, ...result }); })
|
|
488
|
+
.catch((error) => { return res.status(500).json({ success: false, message: error.message }); })
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Create a controller object with all CRUD methods bound to a specific Model
|
|
494
|
+
* @param {mongoose.Model} Model - Mongoose model
|
|
495
|
+
* @returns {Object} Controller object with all CRUD methods
|
|
496
|
+
*/
|
|
497
|
+
module.exports = ( Model ) => {
|
|
498
|
+
|
|
499
|
+
return {
|
|
500
|
+
all: (req, res) => exports.all(Model, req, res),
|
|
501
|
+
read: (req, res) => exports.read(Model, req, res),
|
|
502
|
+
create: (req, res) => exports.create(Model, req, res),
|
|
503
|
+
update: (req, res) => exports.update(Model, req, res),
|
|
504
|
+
delete: (req, res) => exports.delete(Model, req, res),
|
|
505
|
+
list: (req, res) => exports.list(Model, req, res),
|
|
506
|
+
search: (req, res) => exports.search(Model, req, res),
|
|
507
|
+
};
|
|
508
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const crud = require("./crud");
|
|
2
|
+
|
|
3
|
+
exports.crudController = ( Model ) => {
|
|
4
|
+
let methods = {};
|
|
5
|
+
const controller = crud(Model);
|
|
6
|
+
|
|
7
|
+
methods.all = async (req, res) => {
|
|
8
|
+
controller.all(req, res);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
methods.create = async (req, res) => {
|
|
12
|
+
controller.create(req, res);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
methods.read = async (req, res) => {
|
|
16
|
+
controller.read(req, res);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
methods.update = async (req, res) => {
|
|
20
|
+
controller.update(req, res);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
methods.delete = async (req, res) => {
|
|
24
|
+
controller.delete(req, res);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
methods.list = async (req, res) => {
|
|
28
|
+
controller.list(req, res);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
methods.search = async (req, res) => {
|
|
32
|
+
controller.search(req, res);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
return methods;
|
|
36
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const nodemailer = require("nodemailer");
|
|
2
|
+
|
|
3
|
+
const asyncHandler = require("express-async-handler");
|
|
4
|
+
|
|
5
|
+
const sendEmail = asyncHandler(async (data, req, res) => {
|
|
6
|
+
// create reusable transporter object using the default SMTP transport
|
|
7
|
+
let transporter = nodemailer.createTransport({
|
|
8
|
+
host: "smtp.gmail.com",
|
|
9
|
+
port: 587,
|
|
10
|
+
secure: false, // true for 465, false for other ports
|
|
11
|
+
auth: {
|
|
12
|
+
user: process.env.MAIL_ID, // generated ethereal user
|
|
13
|
+
pass: process.env.MP, // generated ethereal password
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// send mail with defined transport object
|
|
18
|
+
let info = await transporter.sendMail({
|
|
19
|
+
from: '"Hey 👻" <abc@gmail.com>', // sender address
|
|
20
|
+
to: data.to, // list of receivers
|
|
21
|
+
subject: data.subject, // Subject line
|
|
22
|
+
text: data.text, // plain text body
|
|
23
|
+
html: data.htm, // html body
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
console.log("Message sent: %s", info.messageId);
|
|
27
|
+
// Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com>
|
|
28
|
+
|
|
29
|
+
// Preview only available when sending through an Ethereal account
|
|
30
|
+
console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));
|
|
31
|
+
// Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
module.exports = sendEmail;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const Enquiry = require("../models/enquiry");
|
|
2
|
+
const asyncHandler = require("../libs/handler/async");
|
|
3
|
+
//const validateMongoDbId = require("../utils/validateMongodbId");
|
|
4
|
+
|
|
5
|
+
const methods = require("./crud");
|
|
6
|
+
|
|
7
|
+
module.exports = methods.crudController( Enquiry );
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
const createEnquiry = asyncHandler(async (req, res) => {
|
|
11
|
+
try {
|
|
12
|
+
const newEnquiry = await Enquiry.create(req.body);
|
|
13
|
+
res.json(newEnquiry);
|
|
14
|
+
} catch (error) {
|
|
15
|
+
throw new Error(error);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
const updateEnquiry = asyncHandler(async (req, res) => {
|
|
19
|
+
const { id } = req.params;
|
|
20
|
+
validateMongoDbId(id);
|
|
21
|
+
try {
|
|
22
|
+
const updatedEnquiry = await Enquiry.findByIdAndUpdate(id, req.body, {
|
|
23
|
+
new: true,
|
|
24
|
+
});
|
|
25
|
+
res.json(updatedEnquiry);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
throw new Error(error);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
const deleteEnquiry = asyncHandler(async (req, res) => {
|
|
31
|
+
const { id } = req.params;
|
|
32
|
+
validateMongoDbId(id);
|
|
33
|
+
try {
|
|
34
|
+
const deletedEnquiry = await Enquiry.findByIdAndDelete(id);
|
|
35
|
+
res.json(deletedEnquiry);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
throw new Error(error);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
const getEnquiry = asyncHandler(async (req, res) => {
|
|
41
|
+
const { id } = req.params;
|
|
42
|
+
validateMongoDbId(id);
|
|
43
|
+
try {
|
|
44
|
+
const getaEnquiry = await Enquiry.findById(id);
|
|
45
|
+
res.json(getaEnquiry);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
throw new Error(error);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
const getallEnquiry = asyncHandler(async (req, res) => {
|
|
51
|
+
try {
|
|
52
|
+
const getallEnquiry = await Enquiry.find();
|
|
53
|
+
res.json(getallEnquiry);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
throw new Error(error);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
module.exports = {
|
|
59
|
+
createEnquiry,
|
|
60
|
+
updateEnquiry,
|
|
61
|
+
deleteEnquiry,
|
|
62
|
+
getEnquiry,
|
|
63
|
+
getallEnquiry,
|
|
64
|
+
};
|
|
65
|
+
*/
|