@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.
Files changed (99) hide show
  1. package/FEAR.js +459 -0
  2. package/FEARServer.js +280 -0
  3. package/controllers/agent.js +438 -0
  4. package/controllers/auth/index.js +345 -0
  5. package/controllers/auth/token.js +50 -0
  6. package/controllers/blog.js +105 -0
  7. package/controllers/brand.js +10 -0
  8. package/controllers/cart.js +425 -0
  9. package/controllers/category.js +9 -0
  10. package/controllers/coupon.js +63 -0
  11. package/controllers/crud/crud.js +508 -0
  12. package/controllers/crud/index.js +36 -0
  13. package/controllers/email.js +34 -0
  14. package/controllers/enquiry.js +65 -0
  15. package/controllers/events.js +9 -0
  16. package/controllers/order.js +125 -0
  17. package/controllers/payment.js +31 -0
  18. package/controllers/product.js +147 -0
  19. package/controllers/review.js +247 -0
  20. package/controllers/tag.js +10 -0
  21. package/controllers/task.js +10 -0
  22. package/controllers/upload.js +41 -0
  23. package/controllers/user.js +401 -0
  24. package/index.js +7 -0
  25. package/libs/agent/index.js +561 -0
  26. package/libs/agent/modules/ai/ai.js +285 -0
  27. package/libs/agent/modules/ai/chat.js +518 -0
  28. package/libs/agent/modules/ai/config.js +688 -0
  29. package/libs/agent/modules/ai/operations.js +787 -0
  30. package/libs/agent/modules/analyze/api.js +546 -0
  31. package/libs/agent/modules/analyze/dorks.js +395 -0
  32. package/libs/agent/modules/ccard/README.md +454 -0
  33. package/libs/agent/modules/ccard/audit.js +479 -0
  34. package/libs/agent/modules/ccard/checker.js +674 -0
  35. package/libs/agent/modules/ccard/payment-processors.json +16 -0
  36. package/libs/agent/modules/ccard/validator.js +629 -0
  37. package/libs/agent/modules/code/analyzer.js +303 -0
  38. package/libs/agent/modules/code/jquery.js +1093 -0
  39. package/libs/agent/modules/code/react.js +1536 -0
  40. package/libs/agent/modules/code/refactor.js +499 -0
  41. package/libs/agent/modules/crypto/exchange.js +564 -0
  42. package/libs/agent/modules/net/proxy.js +409 -0
  43. package/libs/agent/modules/security/cve.js +442 -0
  44. package/libs/agent/modules/security/monitor.js +360 -0
  45. package/libs/agent/modules/security/scanner.js +300 -0
  46. package/libs/agent/modules/security/vulnerability.js +506 -0
  47. package/libs/agent/modules/security/web.js +465 -0
  48. package/libs/agent/modules/utils/browser.js +492 -0
  49. package/libs/agent/modules/utils/colorizer.js +285 -0
  50. package/libs/agent/modules/utils/manager.js +478 -0
  51. package/libs/cloud/index.js +228 -0
  52. package/libs/config/db.js +21 -0
  53. package/libs/config/validator.js +82 -0
  54. package/libs/db/index.js +318 -0
  55. package/libs/emailer/imap.js +126 -0
  56. package/libs/emailer/info.js +41 -0
  57. package/libs/emailer/smtp.js +77 -0
  58. package/libs/handler/async.js +3 -0
  59. package/libs/handler/error.js +66 -0
  60. package/libs/handler/index.js +161 -0
  61. package/libs/logger/index.js +49 -0
  62. package/libs/logger/morgan.js +24 -0
  63. package/libs/passport/passport.js +109 -0
  64. package/libs/search/api.js +384 -0
  65. package/libs/search/features.js +219 -0
  66. package/libs/search/service.js +64 -0
  67. package/libs/swagger/config.js +18 -0
  68. package/libs/swagger/index.js +35 -0
  69. package/libs/validator/index.js +254 -0
  70. package/models/blog.js +31 -0
  71. package/models/brand.js +12 -0
  72. package/models/cart.js +14 -0
  73. package/models/category.js +11 -0
  74. package/models/coupon.js +9 -0
  75. package/models/customer.js +0 -0
  76. package/models/enquiry.js +29 -0
  77. package/models/events.js +13 -0
  78. package/models/order.js +94 -0
  79. package/models/product.js +32 -0
  80. package/models/review.js +14 -0
  81. package/models/tag.js +10 -0
  82. package/models/task.js +11 -0
  83. package/models/user.js +68 -0
  84. package/package.json +12 -0
  85. package/routes/agent.js +615 -0
  86. package/routes/auth.js +13 -0
  87. package/routes/blog.js +19 -0
  88. package/routes/brand.js +15 -0
  89. package/routes/cart.js +105 -0
  90. package/routes/category.js +16 -0
  91. package/routes/coupon.js +15 -0
  92. package/routes/enquiry.js +14 -0
  93. package/routes/events.js +16 -0
  94. package/routes/mail.js +170 -0
  95. package/routes/order.js +19 -0
  96. package/routes/product.js +22 -0
  97. package/routes/review.js +11 -0
  98. package/routes/task.js +12 -0
  99. package/routes/user.js +17 -0
@@ -0,0 +1,35 @@
1
+ const swaggerJsdoc = require('swagger-jsdoc');
2
+ const swaggerUi = require('swagger-ui-express');
3
+
4
+ const options = {
5
+ definition: {
6
+ openapi: '3.0.0',
7
+ info: {
8
+ title: 'FEAR API',
9
+ description: "API endpoints for FEAR services documented on swagger",
10
+ contact: {
11
+ name: "Garrett Haptonstall <FearDread>",
12
+ email: "ghaptonstall@gmail.com",
13
+ url: "https://github.com/FearDread"
14
+ },
15
+ },
16
+ servers: [
17
+ {
18
+ url: "http://localhost:4000/",
19
+ description: "Local server"
20
+ },
21
+ {
22
+ url: "http://fear.master.com:4000",
23
+ description: "Live server"
24
+ },
25
+ ],
26
+ },
27
+ apis: ['./routes/*.js'], // Path to your API routes
28
+ };
29
+
30
+ const specs = swaggerJsdoc(options);
31
+
32
+ module.exports = {
33
+ specs,
34
+ swaggerUi,
35
+ };
@@ -0,0 +1,254 @@
1
+
2
+ const handler = require('../handler');
3
+ const { body, param, query } = require('express-validator');
4
+ const { validationResult } = require('express-validator');
5
+
6
+
7
+ /**
8
+ * Input validation utilities
9
+ */
10
+ exports.input = {
11
+
12
+ /**
13
+ * Validate email format
14
+ * @param {string} email - Email to validate
15
+ * @returns {boolean} Is email valid
16
+ */
17
+ email: (email) => {
18
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
19
+ return emailRegex.test(email);
20
+ },
21
+
22
+ /**
23
+ * Validate password strength
24
+ * @param {string} password - Password to validate
25
+ * @returns {object} Validation result
26
+ */
27
+ password: (password) => {
28
+ if (!password) {
29
+ return { isValid: false, message: "Password is required" };
30
+ }
31
+ if (password.length < 6) {
32
+ return { isValid: false, message: "Password must be at least 6 characters long" };
33
+ }
34
+ return { isValid: true };
35
+ },
36
+
37
+ /**
38
+ * Validate login input
39
+ * @param {object} data - Login data
40
+ * @returns {object} Validation result
41
+ */
42
+ login: ({ email, password }) => {
43
+ if (!email || !password) return { isValid: false, message: "Email and password are required" };
44
+ if (!exports.input.email(email)) return { isValid: false, message: "Please provide a valid email address" };
45
+
46
+ return { isValid: true };
47
+ },
48
+
49
+ /**
50
+ * Validate registration input
51
+ * @param {object} data - Registration data
52
+ * @returns {object} Validation result
53
+ */
54
+ register: (data) => {
55
+ const { email, password, firstname, lastname, name } = data;
56
+
57
+ if (!email) return { isValid: false, message: "Email is required" };
58
+ if (!exports.input.email(email)) return { isValid: false, message: "Please provide a valid email address" };
59
+
60
+ const passwordValidation = exports.input.password(password);
61
+ if (!passwordValidation.isValid) return passwordValidation;
62
+
63
+ const fullName = firstname && lastname ? `${firstname} ${lastname}` : name;
64
+ if (!fullName) return { isValid: false, message: "Name is required" };
65
+
66
+ return { isValid: true, name: fullName };
67
+ }
68
+ }
69
+
70
+
71
+ /**
72
+ * Basic validation middleware for express-validator
73
+ * Checks validation results and throws handler..error if validation fails
74
+ */
75
+ exports.request = (req, res, next) => {
76
+ const errors = validationResult(req);
77
+
78
+ if (!errors.isEmpty()) {
79
+ const formattedErrors = errors.array().reduce((acc, error) => {
80
+ const field = error.path || error.param;
81
+ if (!acc[field]) {
82
+ acc[field] = [];
83
+ }
84
+ acc[field].push(error.msg);
85
+ return acc;
86
+ }, {});
87
+
88
+ const errorResponse = {
89
+ success: false,
90
+ message: 'Validation failed',
91
+ errors: formattedErrors,
92
+ errorCount: errors.array().length
93
+ };
94
+
95
+ return res.status(400).json(errorResponse);
96
+ }
97
+
98
+ next();
99
+ }
100
+
101
+ /**
102
+ * Custom validation schemas for common use cases
103
+ */
104
+ exports.schemas = {
105
+ // MongoDB ObjectId validation
106
+ mongoId: (field = 'id') => ({
107
+ [field]: {
108
+ in: ['params', 'body', 'query'],
109
+ isMongoId: {
110
+ errorMessage: `Valid ${field} is required`
111
+ }
112
+ }
113
+ }),
114
+
115
+ // Email validation
116
+ email: (field = 'email', required = true) => ({
117
+ [field]: {
118
+ in: ['body'],
119
+ ...(required && { notEmpty: { errorMessage: `${field} is required` } }),
120
+ isEmail: {
121
+ errorMessage: 'Valid email address is required'
122
+ },
123
+ normalizeEmail: true
124
+ }
125
+ }),
126
+
127
+ // Password validation
128
+ password: (field = 'password', minLength = 8) => ({
129
+ [field]: {
130
+ in: ['body'],
131
+ isLength: {
132
+ options: { min: minLength },
133
+ errorMessage: `Password must be at least ${minLength} characters long`
134
+ },
135
+ matches: {
136
+ options: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/,
137
+ errorMessage: 'Password must contain at least one uppercase letter, one lowercase letter, and one number'
138
+ }
139
+ }
140
+ }),
141
+
142
+ // Pagination validation
143
+ pagination: () => ({
144
+ page: {
145
+ in: ['query'],
146
+ optional: true,
147
+ isInt: {
148
+ options: { min: 1 },
149
+ errorMessage: 'Page must be a positive integer'
150
+ },
151
+ toInt: true
152
+ },
153
+ limit: {
154
+ in: ['query'],
155
+ optional: true,
156
+ isInt: {
157
+ options: { min: 1, max: 100 },
158
+ errorMessage: 'Limit must be between 1 and 100'
159
+ },
160
+ toInt: true
161
+ }
162
+ })
163
+ };
164
+
165
+ /**
166
+ * Dynamic validation builder
167
+ */
168
+ exports.buildValidation = (schema) => {
169
+ const { checkSchema } = require('express-validator');
170
+ return checkSchema(schema);
171
+ };
172
+
173
+ /**
174
+ * Sanitization helpers
175
+ */
176
+ exports.sanitizers = {
177
+ trimAndEscape: (field) =>
178
+ body(field).trim().escape(),
179
+
180
+ normalizeEmail: (field = 'email') =>
181
+ body(field).normalizeEmail(),
182
+
183
+ toLowerCase: (field) =>
184
+ body(field).toLowerCase(),
185
+
186
+ toBoolean: (field) =>
187
+ body(field).toBoolean()
188
+ };
189
+
190
+ /**
191
+ * Validation middleware factory
192
+ * Creates validation middleware with custom error handling
193
+ */
194
+ exports.factory = (options = {}) => {
195
+ const {
196
+ detailed = true,
197
+ firstOnly = false,
198
+ location = true
199
+ } = options;
200
+
201
+ return (req, res, next) => {
202
+ const errors = validationResult(req);
203
+
204
+ if (!errors.isEmpty()) {
205
+ if (firstOnly) {
206
+ const firstError = errors.array()[0];
207
+ const message = location
208
+ ? `${firstError.path}: ${firstError.msg}`
209
+ : firstError.msg;
210
+
211
+ throw new handler.error(message, 400);
212
+ }
213
+
214
+ if (detailed) {
215
+ const formattedErrors = errors.array().reduce((acc, error) => {
216
+ const field = error.path || error.param;
217
+ if (!acc[field]) {
218
+ acc[field] = [];
219
+ }
220
+ acc[field].push({
221
+ message: error.msg,
222
+ value: error.value,
223
+ location: error.location
224
+ });
225
+ return acc;
226
+ }, {});
227
+
228
+ return res.status(400).json({
229
+ success: false,
230
+ message: 'Validation failed',
231
+ errors: formattedErrors
232
+ });
233
+ }
234
+
235
+ // Default: simple error list
236
+ const errorMessages = errors.array().map(error =>
237
+ includeLocation ? `${error.path}: ${error.msg}` : error.msg
238
+ );
239
+
240
+ throw new handler.error(errorMessages.join(', '), 400);
241
+ }
242
+
243
+ next();
244
+ };
245
+ };
246
+
247
+ module.exports = {
248
+ input: exports.input,
249
+ request: exports.request,
250
+ schemas: exports.schemas,
251
+ builder: exports.buildValidation,
252
+ factory: exports.factory,
253
+ sanitizers: exports.sanitizers,
254
+ }
package/models/blog.js ADDED
@@ -0,0 +1,31 @@
1
+ const mongoose = require("mongoose");
2
+
3
+ const blogSchema = new mongoose.Schema({
4
+ title: { type: String, required: true },
5
+ slug: { type: String, required: false },
6
+ description: { type: String, required: true },
7
+ section: { type:String, required: false, default: "Marketing" },
8
+ category: { type: mongoose.Schema.Types.String, ref: "Category" },
9
+ numViews: { type: Number, default: 0 },
10
+ isLiked: { type: Boolean, default: false },
11
+ isDisliked: { type: Boolean, default: false },
12
+ likes: [{
13
+ type: mongoose.Schema.Types.ObjectId,
14
+ ref: "User",
15
+ }],
16
+ dislikes: [{
17
+ type: mongoose.Schema.Types.ObjectId,
18
+ ref: "User",
19
+ }],
20
+ author: { type: String, default: "Admin" },
21
+ images: [],
22
+ },
23
+ {
24
+ toJSON: { virtuals: true },
25
+ toObject: { virtuals: true },
26
+ timestamps: true,
27
+ }
28
+ );
29
+
30
+ //Export the model
31
+ module.exports = mongoose.model("Blog", blogSchema);
@@ -0,0 +1,12 @@
1
+ const mongoose = require("mongoose");
2
+
3
+ const brandSchema = new mongoose.Schema({
4
+ title: { type: String, required: true, unique: true, index: true },
5
+ logo: { type: Object, required: false, default:
6
+ { public_id: '', secure_url: ''}},
7
+ isActive: { type: Boolean, default: true }
8
+ },
9
+ { timestamps: true }
10
+ );
11
+
12
+ module.exports = mongoose.model("Brand", brandSchema);
package/models/cart.js ADDED
@@ -0,0 +1,14 @@
1
+ const mongoose = require("mongoose");
2
+
3
+ const cartSchema = new mongoose.Schema({
4
+ userId: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
5
+ productId: { type: mongoose.Schema.Types.ObjectId, ref: "Product" },
6
+ quantity: { type: Number, required: true },
7
+ price: { type: Number, required: true },
8
+ },
9
+ {
10
+ timestamps: true,
11
+ }
12
+ );
13
+
14
+ module.exports = mongoose.model("Cart", cartSchema);
@@ -0,0 +1,11 @@
1
+ const mongoose = require("mongoose"); // Erase if already required
2
+
3
+ // Declare the Schema of the Mongo model
4
+ const categorySchema = new mongoose.Schema({
5
+ title: { type: String, required: true, unique: true, index: true },
6
+ },
7
+ { timestamps: true }
8
+ );
9
+
10
+ //Export the model
11
+ module.exports = mongoose.model("Category", categorySchema);
@@ -0,0 +1,9 @@
1
+ const mongoose = require("mongoose");
2
+
3
+ const couponSchema = new mongoose.Schema({
4
+ name: { type: String, required: true, unique: true, uppercase: true },
5
+ expiry: { type: Date, required: true },
6
+ discount: { type: Number, required: true },
7
+ });
8
+
9
+ module.exports = mongoose.model("Coupon", couponSchema);
File without changes
@@ -0,0 +1,29 @@
1
+ const mongoose = require("mongoose"); // Erase if already required
2
+
3
+ // Declare the Schema of the Mongo model
4
+ var enqSchema = new mongoose.Schema({
5
+ name: {
6
+ type: String,
7
+ required: true,
8
+ },
9
+ email: {
10
+ type: String,
11
+ required: true,
12
+ },
13
+ mobile: {
14
+ type: String,
15
+ required: true,
16
+ },
17
+ comment: {
18
+ type: String,
19
+ required: true,
20
+ },
21
+ status: {
22
+ type: String,
23
+ default: "Submitted",
24
+ enum: ["Submitted", "Contacted", "In Progress", "Resolved"],
25
+ },
26
+ });
27
+
28
+ //Export the model
29
+ module.exports = mongoose.model("Enquiry", enqSchema);
@@ -0,0 +1,13 @@
1
+ const mongoose = require("mongoose");
2
+
3
+ const eventSchema = new mongoose.Schema({
4
+ title: { type: String, required: true, unique: true, index: true },
5
+ start: { type: Date, required: true, default: mongoose.now() },
6
+ end: { type: Date, required: false, default: mongoose.now() },
7
+ allDay: { type: Boolean, default: false },
8
+ color: { type: String, required: false, default: 'azure' }
9
+ },
10
+ { timestamps: true }
11
+ );
12
+
13
+ module.exports = mongoose.model("Events", eventSchema);
@@ -0,0 +1,94 @@
1
+ const mongoose = require("mongoose"); // Erase if already required
2
+
3
+ // Declare the Schema of the Mongo model
4
+ var orderSchema = new mongoose.Schema(
5
+ {
6
+ user: {
7
+ type: mongoose.Schema.Types.ObjectId,
8
+ ref: "User",
9
+ required: true,
10
+ },
11
+ shippingInfo: {
12
+ firstname: {
13
+ type: String,
14
+ required: true,
15
+ },
16
+ lastname: {
17
+ type: String,
18
+ required: true,
19
+ },
20
+ address: {
21
+ type: String,
22
+ required: true,
23
+ },
24
+ city: {
25
+ type: String,
26
+ required: true,
27
+ },
28
+ state: {
29
+ type: String,
30
+ required: true,
31
+ },
32
+ other: {
33
+ type: String,
34
+ },
35
+ pincode: {
36
+ type: Number,
37
+ required: true,
38
+ },
39
+ },
40
+ paymentInfo: {
41
+ razorpayOrderId: {
42
+ type: String,
43
+ required: true,
44
+ },
45
+ razorpayPaymentId: {
46
+ type: String,
47
+ required: true,
48
+ },
49
+ },
50
+ orderItems: [
51
+ {
52
+ product: {
53
+ type: mongoose.Schema.Types.ObjectId,
54
+ ref: "Product",
55
+ required: true,
56
+ },
57
+ quantity: {
58
+ type: Number,
59
+ required: true,
60
+ },
61
+ price: {
62
+ type: Number,
63
+ required: true,
64
+ },
65
+ },
66
+ ],
67
+ paidAt: {
68
+ type: Date,
69
+ default: Date.now(),
70
+ },
71
+ month: {
72
+ type: Number,
73
+ default: new Date().getMonth(),
74
+ },
75
+ totalPrice: {
76
+ type: Number,
77
+ required: true,
78
+ },
79
+ totalPriceAfterDiscount: {
80
+ type: Number,
81
+ required: true,
82
+ },
83
+ orderStatus: {
84
+ type: String,
85
+ default: "Ordered",
86
+ },
87
+ },
88
+ {
89
+ timestamps: true,
90
+ }
91
+ );
92
+
93
+ //Export the model
94
+ module.exports = mongoose.model("Order", orderSchema);
@@ -0,0 +1,32 @@
1
+ const mongoose = require("mongoose"); // Erase if already required
2
+ const Review = require("./review");
3
+
4
+ // Declare the Schema of the Mongo model
5
+ const productSchema = new mongoose.Schema({
6
+ title: { type: String, required: true, trim: true },
7
+ slug: { type: String, required: false, unique: true, lowercase: true },
8
+ description: { type: String, required: true },
9
+ price: { type: Number, required: true },
10
+ category: { type: mongoose.Schema.Types.String, ref: "Category" },
11
+ brand: { type: mongoose.Schema.Types.String, ref: "Brand" , required: false },
12
+ quantity: { type: Number, required: true },
13
+ sold: { type: Number, default: 0 },
14
+ reviews: [Review.schema],
15
+ images: [{
16
+ public_id: String,
17
+ url: String
18
+ },
19
+ ],
20
+ tags: String,
21
+ ratings: [{
22
+ star: Number,
23
+ comment: String,
24
+ postedby: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
25
+ },
26
+ ],
27
+ totalrating: { type: Number, default: 0 },
28
+ }, { timestamps: true }
29
+ );
30
+
31
+ //Export the model
32
+ module.exports = mongoose.model("Product", productSchema);
@@ -0,0 +1,14 @@
1
+ const mongoose = require("mongoose");
2
+
3
+ const reviewSchema = new mongoose.Schema({
4
+ user: { type: mongoose.Schema.Types.ObjectId, ref:"User", required:true },
5
+ product: { type: mongoose.Schema.Types.ObjectId, ref:"Product", required:true },
6
+ rating: { type:Number, required:true, min:1, max:5 },
7
+ comment: { type:String, required:true },
8
+ createdAt: { type:Date, default:Date.now }
9
+ },
10
+ { timestamps: true, versionKey:false}
11
+ );
12
+
13
+
14
+ module.exports = mongoose.model("Review", reviewSchema);
package/models/tag.js ADDED
@@ -0,0 +1,10 @@
1
+ const mongoose = require("mongoose");
2
+
3
+ const tagSchema = new mongoose.Schema({
4
+ tag: { type: String, required: true, unique: true, index: true }
5
+
6
+ },
7
+ { timestamps: true }
8
+ );
9
+
10
+ module.exports = mongoose.model("Brand", brandSchema);
package/models/task.js ADDED
@@ -0,0 +1,11 @@
1
+ const mongoose = require("mongoose");
2
+
3
+ const taskSchema = new mongoose.Schema({
4
+ task: { type: String, required: true, index: true },
5
+ createdBy: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
6
+ createdAt: { type:Date, default:Date.now },
7
+ isComplete: { type: Boolean, default: false},
8
+ }, {timestamps: true}
9
+ )
10
+
11
+ module.exports = mongoose.model("Task", taskSchema);
package/models/user.js ADDED
@@ -0,0 +1,68 @@
1
+ const mongoose = require("mongoose");
2
+ const bcrypt = require("bcrypt");
3
+ const crypto = require("crypto");
4
+
5
+ const userSchema = new mongoose.Schema({
6
+ name: { type: String, required: true },
7
+ lastname: { type: String, required: false },
8
+ email: { type: String, required: true, unique: true },
9
+ username: { type: String, required: false, unique: false },
10
+ mobile: { type: String, required: false, unique: true },
11
+ password: { type: String, required: true },
12
+ avatar: { type: Object, required: false, default: {
13
+ public_id: '',
14
+ secure_url: ''
15
+ }},
16
+ role: { type: String, default: "customer" },
17
+ isBlocked: { type: Boolean, default: false },
18
+ address: { type: String },
19
+ shipping: { type: String },
20
+ wishlist: [{ type: mongoose.Schema.Types.ObjectId, ref: "Product" }],
21
+ refreshToken: { type: String },
22
+ passwordChangedAt: Date,
23
+ passwordResetToken: String,
24
+ passwordResetExpires: Date
25
+ },
26
+ { timestamps: true }
27
+ );
28
+
29
+ // Hooks
30
+ userSchema.pre("save", async function (next) {
31
+ if (!this.isModified("password")) {
32
+ next();
33
+ }
34
+ const salt = await bcrypt.genSaltSync(10);
35
+ this.password = await bcrypt.hash(this.password, salt);
36
+ next();
37
+ });
38
+
39
+ // Methods
40
+ userSchema.methods.compare = async function (entered) {
41
+ return await bcrypt.compare(entered, this.password);
42
+ };
43
+
44
+ userSchema.methods.token = async function () {
45
+ const resettoken = crypto.randomBytes(32).toString("hex");
46
+
47
+ this.passwordResetToken = crypto.createHash("sha256").update(resettoken).digest("hex");
48
+ this.passwordResetExpires = Date.now() + 30 * 60 * 1000;
49
+
50
+ return resettoken;
51
+ };
52
+
53
+ //Statics
54
+ userSchema.statics.countUsers = function () {
55
+ return this.countDocuments({});
56
+ };
57
+
58
+ userSchema.statics.findByEmail = async function (email) {
59
+ return await this.findOne({ email });
60
+ };
61
+
62
+ // Query
63
+ userSchema.query.paginate = function ({ page, limit }) {
64
+ const skip = limit * (page - 1);
65
+ return this.skip(skip).limit(limit);
66
+ };
67
+
68
+ module.exports = mongoose.model("User", userSchema);
package/package.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "@feardread/fear",
3
+ "version": "1.0.1",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "keywords": [],
10
+ "author": "Garrett Haptonstall",
11
+ "license": "MIT"
12
+ }