nodejs-backpack 0.0.1-security → 2.0.28

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.

Potentially problematic release.


This version of nodejs-backpack might be problematic. Click here for more details.

@@ -0,0 +1,174 @@
1
+ const {
2
+ successResponse,
3
+ checkValidationResult,
4
+ errorResponse,
5
+ } = require("rest-api-response-npm");
6
+ const ${schemaName} = require("../models/${schemaName}");
7
+ const {
8
+ generatePaginationLinks,
9
+ searchableFields,
10
+ mergerFilesAndBody,
11
+ filterMissingFields,
12
+ } = require("../helpers/helper.js");
13
+
14
+ const ${fileName}Controller = {
15
+ list: async (req, res) => {
16
+ var currentPage = parseInt(req?.query?.page_no) || 1;
17
+ var perPage = parseInt(req?.query?.page_limit) || 10;
18
+ var searchInput = req?.query?.search || "";
19
+
20
+ const rgx = (pattern) => new RegExp(`.*${pattern}.*`);
21
+ const searchRgx = rgx(searchInput);
22
+
23
+ var SearchFieldArray = ${___SearchFieldArray___};
24
+
25
+ const count = await ${schemaName}.countDocuments({
26
+ $or: SearchFieldArray,
27
+ });
28
+
29
+ const totalPages = Math.ceil(count / perPage);
30
+
31
+ await ${schemaName}.find({
32
+ $or: SearchFieldArray,
33
+ })
34
+ .skip((currentPage - 1) * perPage)
35
+ .limit(perPage)
36
+ .sort({ createdAt: -1 })
37
+ .then((results) => {
38
+ const response = {
39
+ totalRecords: count,
40
+ totalPages: totalPages,
41
+ currentPage: currentPage,
42
+ perPage: perPage,
43
+ results: results,
44
+ };
45
+
46
+ generatePaginationLinks(
47
+ req,
48
+ response,
49
+ currentPage,
50
+ perPage,
51
+ totalPages,
52
+ searchInput
53
+ );
54
+ return successResponse(
55
+ res,
56
+ response,
57
+ "${fileName} list fetched successfully!"
58
+ );
59
+ })
60
+ .catch((err) => {
61
+ return errorResponse(res, err, "Opps something went wrong!", 500);
62
+ });
63
+ },
64
+ getDetail: async (req, res) => {
65
+ const response = checkValidationResult(res, req);
66
+ if (response["status_code"] === 422) {
67
+ return errorResponse(
68
+ res,
69
+ response["data"],
70
+ response["message"],
71
+ response["status_code"]
72
+ );
73
+ }
74
+ await ${schemaName}.findById(req.params.id)
75
+ .then((result) => {
76
+ if (result) {
77
+ return successResponse(res, result, "${fileName} detail fetched successfully!");
78
+ } else {
79
+ data = {
80
+ id: ["Record doesn't exist!"],
81
+ };
82
+ return validationResponse(res, data, "Record doesn't exist!");
83
+ }
84
+ })
85
+ .catch((err) =>
86
+ {
87
+ return errorResponse(res, err, "Opps something went wrong!", 500)
88
+ }
89
+ );
90
+ },
91
+ store: async (req, res) => {
92
+ const response = checkValidationResult(res, req);
93
+ if (response["status_code"] === 422) {
94
+ return errorResponse(
95
+ res,
96
+ response["data"],
97
+ response["message"],
98
+ response["status_code"]
99
+ );
100
+ }
101
+ /*File values into body*/
102
+ mergerFilesAndBody(req);
103
+ var storeData = ${___StoreFieldArray___};
104
+ var ${schemaName}Store = new ${schemaName}(storeData);
105
+ await ${schemaName}Store.save()
106
+ .then((result) => {
107
+ return successResponse(res, result, "${fileName} created successfully!");
108
+ })
109
+ .catch((err) => {
110
+ return errorResponse(res, err, "Opps something went wrong!", 500);
111
+ });
112
+ },
113
+ update: async (req, res) => {
114
+ const response = checkValidationResult(res, req);
115
+ if (response["status_code"] === 422) {
116
+ return errorResponse(
117
+ res,
118
+ response["data"],
119
+ response["message"],
120
+ response["status_code"]
121
+ );
122
+ }
123
+ /*File values into body*/
124
+ mergerFilesAndBody(req);
125
+
126
+ var updateData = ${___StoreFieldArray___};
127
+
128
+ updateData = filterMissingFields(updateData); // Removes fields with null values
129
+
130
+ await ${schemaName}.findByIdAndUpdate(req.params.id, updateData, { new: true })
131
+ .then((result) => {
132
+ if (result) {
133
+ successResponse(res, result, "${fileName} updated successfully!");
134
+ } else {
135
+ data = {
136
+ id: ["Record doesn't exist!"],
137
+ };
138
+ validationResponse(res, data, "Record doesn't exist!");
139
+ }
140
+ })
141
+ .catch((err) =>
142
+ errorResponse(res, err, "Opps something went wrong!", 500)
143
+ );
144
+ },
145
+ destroy: async (req, res) => {
146
+ const response = checkValidationResult(res, req);
147
+ if (response["status_code"] === 422) {
148
+ return errorResponse(
149
+ res,
150
+ response["data"],
151
+ response["message"],
152
+ response["status_code"]
153
+ );
154
+ }
155
+ await ${schemaName}.findByIdAndDelete(req.params.id)
156
+ .then((result) => {
157
+ if (result) {
158
+ return successResponse(res, result, "Deleted successfully!");
159
+ } else {
160
+ data = {
161
+ id: ["Record doesn't exist!"],
162
+ };
163
+ return validationResponse(res, data, "Record doesn't exist!");
164
+ }
165
+ })
166
+ .catch((err) =>
167
+ {
168
+ return errorResponse(res, err, "Opps something went wrong!", 500)
169
+ }
170
+ );
171
+ }
172
+ };
173
+
174
+ module.exports = ${fileName}Controller;
package/sample-env ADDED
@@ -0,0 +1,4 @@
1
+ PORT=3000
2
+ DB="mongodb+srv://USERNAME:PASSWORD@mongo.9bdgpey.mongodb.net/node_backpack"
3
+ JWT_SIGNATURE=node_backpack
4
+ HOST=http://localhost:3000
@@ -0,0 +1,27 @@
1
+ const multer = require("multer");
2
+ const fs = require("fs");
3
+ const path = require("path");
4
+
5
+ // Create a Multer instance with destination for uploaded files
6
+ const storage = (routeName) =>
7
+ multer.diskStorage({
8
+ destination: function (req, file, cb) {
9
+ const folder = `./public/${routeName}`;
10
+
11
+ // Check if the folder exists, create it if it doesn't
12
+ if (!fs.existsSync(folder)) {
13
+ fs.mkdirSync(folder, { recursive: true });
14
+ }
15
+
16
+ cb(null, folder);
17
+ },
18
+ filename: function (req, file, cb) {
19
+ let fileExt = path.extname(file.originalname);
20
+ cb(null, `${routeName}-${Date.now()}${fileExt}`);
21
+ },
22
+ });
23
+
24
+ // Enable file upload middleware using Multer
25
+ const upload = (routeName) => multer({ storage: storage(routeName) });
26
+
27
+ module.exports = upload;
@@ -0,0 +1,5 @@
1
+ const multer = require("multer");
2
+
3
+ let formParser = multer().none();
4
+
5
+ module.exports = formParser;
@@ -0,0 +1,138 @@
1
+ function extractRouteName(req) {
2
+ const path = req.originalUrl.split("?")[0]; // Remove query parameters
3
+ const parts = path.split("/").filter(Boolean); // Remove empty parts
4
+ return parts[parts.length - 1];
5
+ }
6
+
7
+ function generatePaginationLinks(
8
+ req,
9
+ response,
10
+ currentPage,
11
+ perPage,
12
+ totalPages,
13
+ searchInput
14
+ ) {
15
+ const routeName = extractRouteName(req);
16
+
17
+ // add first page link
18
+ const firstLink = `${req.protocol}://${req.get("host")}${
19
+ req.baseUrl
20
+ }/${routeName}?page_no=1&page_limit=${perPage}&search=${searchInput}`;
21
+ response.firstLink = firstLink;
22
+
23
+ // add previous page link if exist
24
+ if (currentPage > 1) {
25
+ const previousPage = currentPage - 1;
26
+ const previousLink = `${req.protocol}://${req.get("host")}${
27
+ req.baseUrl
28
+ }/${routeName}?page_no=${previousPage}&page_limit=${perPage}&search=${searchInput}`;
29
+ response.previousLink = previousLink;
30
+ } else {
31
+ response.previousLink = null;
32
+ }
33
+
34
+ // add current page link if exist
35
+ if (currentPage >= 1 || currentPage <= totalPages) {
36
+ const currentLink = `${req.protocol}://${req.get("host")}${
37
+ req.baseUrl
38
+ }/${routeName}?page_no=${currentPage}&page_limit=${perPage}&search=${searchInput}`;
39
+ response.currentLink = currentLink;
40
+ } else {
41
+ response.currentLink = null;
42
+ }
43
+
44
+ // add next page link if exist
45
+ if (currentPage < totalPages) {
46
+ const nextPage = currentPage + 1;
47
+ const nextLink = `${req.protocol}://${req.get("host")}${
48
+ req.baseUrl
49
+ }/${routeName}?page_no=${nextPage}&page_limit=${perPage}&search=${searchInput}`;
50
+ response.nextLink = nextLink;
51
+ } else {
52
+ response.nextLink = null;
53
+ }
54
+
55
+ // add last page link
56
+ const lastPage = totalPages ? totalPages : 1;
57
+ const lastLink = `${req.protocol}://${req.get("host")}${
58
+ req.baseUrl
59
+ }/${routeName}?page_no=${lastPage}&page_limit=${perPage}&search=${searchInput}`;
60
+ response.lastLink = lastLink;
61
+
62
+ return response;
63
+ }
64
+
65
+ function modelsParams(Schema) {
66
+ // Obtain the schema parameters object
67
+ const paths = Schema?.schema?.paths;
68
+ let parameters = [];
69
+ let all = [];
70
+ let required = [];
71
+ let optional = [];
72
+ // Loop over the paths and log each field's name and type
73
+ for (const path in paths) {
74
+ let isRequired = paths[path]?.options?.required ? true : false;
75
+ parameters.push({
76
+ field: path,
77
+ is_required: isRequired,
78
+ });
79
+ if (isRequired) {
80
+ required.push(path);
81
+ } else {
82
+ optional.push(path);
83
+ }
84
+ all.push(path);
85
+ }
86
+ const unwantedProps = ["_id", "createdAt", "updatedAt", "__v"];
87
+ const filteredFormData = all.filter((prop) => !unwantedProps.includes(prop));
88
+ return {
89
+ parameters: parameters,
90
+ allFields: all,
91
+ requiredFields: required,
92
+ optionalFields: optional,
93
+ filteredFormFields: filteredFormData,
94
+ };
95
+ }
96
+
97
+ function searchableFields(Model) {
98
+ var formFields = modelsParams(Model);
99
+ var uploadFieldArray = [];
100
+ var searchFields = [];
101
+ if (
102
+ formFields &&
103
+ formFields?.filteredFormFields &&
104
+ formFields?.filteredFormFields.length
105
+ ) {
106
+ searchFields = formFields?.filteredFormFields;
107
+ return searchFields;
108
+ }
109
+ }
110
+ function mergerFilesAndBody(req) {
111
+ if (req.files && Object.keys(req.files).length > 0) {
112
+ Object.keys(req.files).forEach(function (key) {
113
+ if (req.files[key] && req.files[key] !== undefined) {
114
+ var file = req.files[key];
115
+ if (file && file?.path && file?.fieldname)
116
+ req.body[file?.fieldname] = file?.path.replace(/\public\\/g, "");
117
+ }
118
+ });
119
+ req.files = [];
120
+ return req;
121
+ }
122
+ }
123
+ function filterMissingFields(data) {
124
+ for (var key in data) {
125
+ if (data[key] === null) {
126
+ delete data[key];
127
+ }
128
+ }
129
+ return data;
130
+ }
131
+
132
+ module.exports = {
133
+ generatePaginationLinks,
134
+ modelsParams,
135
+ searchableFields,
136
+ mergerFilesAndBody,
137
+ filterMissingFields,
138
+ };
@@ -0,0 +1,7 @@
1
+ const express = require("express");
2
+ const router = express.Router();
3
+ // individual-route-module-imported
4
+
5
+ // defining-api-routes
6
+
7
+ module.exports = router;
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "my-node-project",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1",
8
+ "dev": "nodemon app.js"
9
+ },
10
+ "author": "",
11
+ "license": "ISC",
12
+ "dependencies": {
13
+ "bcryptjs": "^2.4.3",
14
+ "body-parser": "^1.20.2",
15
+ "dotenv": "^16.3.1",
16
+ "express": "^4.18.2",
17
+ "express-validator": "^7.0.1",
18
+ "jsonwebtoken": "^9.0.1",
19
+ "mongoose": "^7.3.1",
20
+ "mongoose-backpack": "^0.2.7",
21
+ "multer": "^1.4.5-lts.1",
22
+ "node-backpack": "^0.0.427",
23
+ "nodemailer": "^6.9.3",
24
+ "rest-api-response-npm": "^0.1.4"
25
+ },
26
+ "devDependencies": {
27
+ "nodemon": "^3.0.1"
28
+ }
29
+ }
@@ -0,0 +1,20 @@
1
+ const express = require('express');
2
+ const router = express.Router();
3
+ const ${fileName}Controller = require('../controllers/${fileName}Controller');
4
+ const ListValidationRequest = require('./validationRequest/${fileName}/ListValidationRequest');
5
+ const GetDetailValidationRequest = require('./validationRequest/${fileName}/GetDetailValidationRequest');
6
+ const StoreValidationRequest = require('./validationRequest/${fileName}/StoreValidationRequest');
7
+ const UpdateValidationRequest = require('./validationRequest/${fileName}/UpdateValidationRequest');
8
+ const DestroyValidationRequest = require('./validationRequest/${fileName}/DestroyValidationRequest');
9
+ const upload = require('../helpers/fileUploader');
10
+ const formParser = require('../helpers/formParser');
11
+
12
+ const prefix = '${apiUrl}';
13
+
14
+ router.get(`/${prefix}/`,formParser,ListValidationRequest, ${fileName}Controller.list);
15
+ router.get(`/${prefix}/:id`,formParser,GetDetailValidationRequest, ${fileName}Controller.getDetail);
16
+ router.post(`/${prefix}/`,upload(prefix).any(),StoreValidationRequest, ${fileName}Controller.store);
17
+ router.put(`/${prefix}/:id`,upload(prefix).any(),UpdateValidationRequest, ${fileName}Controller.update);
18
+ router.delete(`/${prefix}/:id`,formParser,DestroyValidationRequest, ${fileName}Controller.destroy);
19
+
20
+ module.exports = router;
@@ -0,0 +1,26 @@
1
+ const mongoose = require("mongoose");
2
+ const Schema = mongoose.Schema;
3
+ const { appendParams } = require("mongoose-backpack");
4
+
5
+ const ResetToken = new Schema(
6
+ {
7
+ email: {
8
+ type: String,
9
+ required: true,
10
+ },
11
+ reset_token: {
12
+ type: String,
13
+ required: false,
14
+ },
15
+ },
16
+ { timestamps: true }
17
+ );
18
+
19
+ appendData = {
20
+ id: function () {
21
+ return this._id;
22
+ },
23
+ };
24
+ appendParams(ResetToken, appendData);
25
+
26
+ module.exports = mongoose.model("ResetToken", ResetToken);
@@ -0,0 +1,51 @@
1
+ const mongoose = require("mongoose");
2
+ const Schema = mongoose.Schema;
3
+ const { appendParams } = require("mongoose-backpack");
4
+
5
+ const User = new Schema(
6
+ {
7
+ first_name: {
8
+ type: String,
9
+ required: true,
10
+ },
11
+ last_name: {
12
+ type: String,
13
+ required: true,
14
+ },
15
+ email: {
16
+ type: String,
17
+ required: true,
18
+ },
19
+ phone_no: {
20
+ type: String,
21
+ required: false,
22
+ },
23
+ password: {
24
+ type: String,
25
+ required: true,
26
+ },
27
+ image: {
28
+ type: String,
29
+ required: false,
30
+ },
31
+ token: {
32
+ type: String,
33
+ required: false,
34
+ },
35
+ },
36
+ { timestamps: true }
37
+ );
38
+
39
+ appendData = {
40
+ id: function () {
41
+ return this._id;
42
+ },
43
+ full_name: function () {
44
+ const firstName = this?.first_name ? this.first_name + " " : "";
45
+ const lastName = this?.last_name ? this.last_name : "";
46
+ return `${firstName}${lastName}`;
47
+ },
48
+ };
49
+ appendParams(User, appendData);
50
+
51
+ module.exports = mongoose.model("User", User);
@@ -0,0 +1,49 @@
1
+ const mongoose = require("mongoose");
2
+ const Schema = mongoose.Schema;
3
+ const { appendParams } = require("mongoose-backpack");
4
+
5
+ const ${fileContent} = new Schema(
6
+ {
7
+ name: {
8
+ type: String,
9
+ required: true,
10
+ },
11
+ },
12
+ { timestamps: true }
13
+ );
14
+
15
+ const appendData = {
16
+ id: function () {
17
+ return this._id;
18
+ },
19
+ };
20
+ appendParams(${fileContent}, appendData);
21
+
22
+ const ${fileContent}Model = mongoose.model("${fileContent}", ${fileContent});
23
+
24
+ // Created a change stream. The 'change' event gets emitted when there's a change in the database
25
+ /*
26
+ ${fileContent}Model.watch().on("change", (data) => {
27
+ const timestamp = new Date();
28
+ const operationType = data.operationType;
29
+
30
+ switch (operationType) {
31
+ case "insert":
32
+ // TODO Logic Code...
33
+ console.log(timestamp, "Document created:", data.fullDocument);
34
+ break;
35
+ case "update":
36
+ // TODO Logic Code...
37
+ console.log(timestamp, "Document updated:", data.updateDescription);
38
+ break;
39
+ case "delete":
40
+ // TODO Logic Code...
41
+ console.log(timestamp, "Document deleted:", data.documentKey);
42
+ break;
43
+ default:
44
+ console.log(timestamp, "Unknown operation type:", operationType);
45
+ }
46
+ });
47
+ */
48
+
49
+ module.exports = ${fileContent}Model;
@@ -0,0 +1,4 @@
1
+ const { body, param, check } = require("express-validator");
2
+ const ${schemaName} = require("../../../models/${schemaName}");
3
+
4
+ module.exports = defaultExport = [__validation__dynamic__code__];
package/typing.gif ADDED
Binary file
package/README.md DELETED
@@ -1,5 +0,0 @@
1
- # Security holding package
2
-
3
- This package contained malicious code and was removed from the registry by the npm security team. A placeholder was published to ensure users are not affected in the future.
4
-
5
- Please refer to www.npmjs.com/advisories?search=nodejs-backpack for more information.