vanta-api 1.3.0 → 1.3.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.
Files changed (2) hide show
  1. package/package.json +2 -2
  2. package/src/api-features.js +41 -40
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vanta-api",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Advanced API features and security configuration for Node.js/MongoDB.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -19,7 +19,7 @@
19
19
  "author": "Alireza Aghaee",
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "bson": "^6.10.3",
22
+ "bson": "^7.0.0",
23
23
  "mongoose": "^7.0.0",
24
24
  "pluralize": "^8.0.0",
25
25
  "winston": "^3.0.0"
@@ -18,8 +18,11 @@ export class ApiFeatures {
18
18
  constructor(model, query = {}, userRole = "") {
19
19
  this.model = model;
20
20
  this.query = { ...query };
21
- if (!userRole || ! Object.keys(securityConfig.accessLevels).includes(userRole)) {
22
- this.userRole = 'guest';
21
+ if (
22
+ !userRole ||
23
+ !Object.keys(securityConfig.accessLevels).includes(userRole)
24
+ ) {
25
+ this.userRole = "guest";
23
26
  } else {
24
27
  this.userRole = userRole;
25
28
  }
@@ -66,46 +69,43 @@ export class ApiFeatures {
66
69
  return this;
67
70
  }
68
71
 
69
- limitFields(input = "") {
70
- const rawFields = [input, this.query.fields].filter(Boolean).join(",");
71
- if (!rawFields) return this;
72
+ limitFields(input = "") {
73
+ const rawFields = [input, this.query.fields].filter(Boolean).join(",");
74
+ if (!rawFields) return this;
72
75
 
73
- const validFields = Object.keys(this.model.schema.paths).filter(
74
- (f) => !securityConfig.forbiddenFields.includes(f)
75
- );
76
-
77
- const fieldsArray = rawFields
78
- .split(",")
79
- .map((f) => f.trim())
80
- .filter(Boolean);
81
-
82
- const includeFields = new Set();
83
- const excludeFields = new Set();
76
+ const validFields = Object.keys(this.model.schema.paths).filter(
77
+ (f) => !securityConfig.forbiddenFields.includes(f)
78
+ );
84
79
 
85
- fieldsArray.forEach((f) => {
86
- if (f.startsWith("-")) excludeFields.add(f.slice(1));
87
- else includeFields.add(f);
88
- });
80
+ const fieldsArray = rawFields
81
+ .split(",")
82
+ .map((f) => f.trim())
83
+ .filter(Boolean);
89
84
 
90
- const project = {};
85
+ const includeFields = new Set();
86
+ const excludeFields = new Set();
91
87
 
92
- if (includeFields.size > 0) {
93
- includeFields.forEach((f) => {
94
- if (validFields.includes(f)) project[f] = 1;
95
- });
96
- } else if (excludeFields.size > 0) {
97
- validFields.forEach((f) => {
98
- if (!excludeFields.has(f)) project[f] = 1;
88
+ fieldsArray.forEach((f) => {
89
+ if (f.startsWith("-")) excludeFields.add(f.slice(1));
90
+ else includeFields.add(f);
99
91
  });
100
- }
101
-
102
- if (Object.keys(project).length) {
103
- this.pipeline.push({ $project: project });
104
- }
92
+ const project = {};
93
+ if (includeFields.size > 0) {
94
+ includeFields.forEach((f) => {
95
+ if (validFields.includes(f)) project[f] = 1;
96
+ });
97
+ } else if (excludeFields.size > 0) {
98
+ validFields.forEach((f) => {
99
+ if (!excludeFields.has(f)) project[f] = 1;
100
+ });
101
+ }
105
102
 
106
- return this;
107
- }
103
+ if (Object.keys(project).length) {
104
+ this.pipeline.push({ $project: project });
105
+ }
108
106
 
107
+ return this;
108
+ }
109
109
  paginate() {
110
110
  const { maxLimit } = securityConfig.accessLevels[this.userRole] || {
111
111
  maxLimit: 100,
@@ -252,7 +252,6 @@ export class ApiFeatures {
252
252
 
253
253
  _parseQueryFilters() {
254
254
  const obj = { ...this.query };
255
- // پاک کردن پارامترهای سیستماتیک
256
255
  ["page", "limit", "sort", "fields", "populate"].forEach(
257
256
  (k) => delete obj[k]
258
257
  );
@@ -320,9 +319,14 @@ export class ApiFeatures {
320
319
  }
321
320
 
322
321
  if (typeof val === "string" && /^[0-9]+$/.test(val)) {
323
- resultObj[keyObj] = parseInt(val, 10);
322
+ if (val.length > 1 && val.startsWith("0")) {
323
+ resultObj[keyObj] = val; // keep leading zero
324
+ } else {
325
+ resultObj[keyObj] = parseInt(val, 10);
326
+ }
324
327
  return;
325
328
  }
329
+
326
330
  if (typeof val === "string" && this.#isStrictObjectId(val)) {
327
331
  resultObj[keyObj] = new ObjectId(val);
328
332
  return;
@@ -343,9 +347,6 @@ export class ApiFeatures {
343
347
  _applySecurityFilters(filters) {
344
348
  let res = { ...filters };
345
349
  securityConfig.forbiddenFields.forEach((f) => delete res[f]);
346
- if (this.userRole !== "admin" && this.model.schema.path("isActive")) {
347
- res.isActive = true;
348
- }
349
350
  return res;
350
351
  }
351
352