vanta-api 1.2.5 → 1.2.6

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 +1 -1
  2. package/src/api-features.js +57 -57
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vanta-api",
3
- "version": "1.2.5",
3
+ "version": "1.2.6",
4
4
  "description": "Advanced API features and security configuration for Node.js/MongoDB.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -91,71 +91,71 @@ export class ApiFeatures {
91
91
  return this;
92
92
  }
93
93
 
94
- populate(input = "") {
95
- // Build list from input and query.populate
96
- let list = [];
97
- const raw = Array.isArray(input) ? input : [input];
98
- if (this.query.populate) raw.push(...this.query.populate.split(","));
99
-
100
- raw.forEach((item) => {
101
- if (typeof item === "string" && item.trim()) list.push(item.trim());
102
- else if (item?.path) list.push(item);
103
- });
104
-
105
- // Deduplicate
106
- const map = new Map();
107
- list.forEach((opt) => {
108
- const key = typeof opt === "string" ? opt : opt.path;
109
- map.set(key, opt);
110
- });
94
+ populate(input = "") {
95
+ let list = [];
96
+ const raw = Array.isArray(input) ? input : [input];
97
+ if (this.query.populate) raw.push(...this.query.populate.split(","));
98
+
99
+ raw.forEach((item) => {
100
+ if (typeof item === "string" && item.trim()) list.push(item.trim());
101
+ else if (item?.path) list.push(item);
102
+ });
103
+
104
+ const map = new Map();
105
+ list.forEach((opt) => {
106
+ const key = typeof opt === "string" ? opt : opt.path;
107
+ map.set(key, opt);
108
+ });
109
+
110
+ const allowed =
111
+ securityConfig.accessLevels[this.userRole]?.allowedPopulate || [];
112
+ const final = [];
113
+ map.forEach((opt, key) => {
114
+ if (allowed.includes("*") || allowed.includes(key)) final.push(opt);
115
+ });
116
+
117
+ for (const opt of final) {
118
+ const field = typeof opt === "string" ? opt : opt.path;
119
+ const proj =
120
+ typeof opt === "object" && opt.select
121
+ ? opt.select.split(" ").reduce((a, f) => {
122
+ a[f] = 1;
123
+ return a;
124
+ }, {})
125
+ : {};
126
+
127
+ const { collection, isArray } = this._getCollectionInfo(field);
128
+
129
+ const lookup =
130
+ proj && Object.keys(proj).length
131
+ ? {
132
+ from: collection,
133
+ let: { id: `$${field}` },
134
+ pipeline: [
135
+ { $match: { $expr: { $eq: ["$_id", "$$id"] } } },
136
+ { $project: proj },
137
+ ],
138
+ as: field,
139
+ }
140
+ : {
141
+ from: collection,
142
+ localField: field,
143
+ foreignField: "_id",
144
+ as: field,
145
+ };
111
146
 
112
- // Enforce role-based populate
113
- const allowed =
114
- securityConfig.accessLevels[this.userRole]?.allowedPopulate || [];
115
- const final = [];
116
- map.forEach((opt, key) => {
117
- if (allowed.includes("*") || allowed.includes(key)) final.push(opt);
118
- });
147
+ this.pipeline.push({ $lookup: lookup });
119
148
 
120
- // Apply lookups
121
- for (const opt of final) {
122
- const field = typeof opt === "string" ? opt : opt.path;
123
- const proj =
124
- typeof opt === "object" && opt.select
125
- ? opt.select.split(" ").reduce((a, f) => {
126
- a[f] = 1;
127
- return a;
128
- }, {})
129
- : {};
130
-
131
- const { collection } = this._getCollectionInfo(field);
132
- const lookup =
133
- proj && Object.keys(proj).length
134
- ? {
135
- from: collection,
136
- let: { id: `$${field}` },
137
- pipeline: [
138
- { $match: { $expr: { $eq: ["$_id", "$$id"] } } },
139
- { $project: proj },
140
- ],
141
- as: field,
142
- }
143
- : {
144
- from: collection,
145
- localField: field,
146
- foreignField: "_id",
147
- as: field,
148
- };
149
-
150
- this.pipeline.push({ $lookup: lookup });
149
+ if (!isArray) {
151
150
  this.pipeline.push({
152
151
  $unwind: { path: `$${field}`, preserveNullAndEmptyArrays: true },
153
152
  });
154
153
  }
155
-
156
- return this;
157
154
  }
158
155
 
156
+ return this;
157
+ }
158
+
159
159
  addManualFilters(filters) {
160
160
  if (filters) this.manualFilters = { ...this.manualFilters, ...filters };
161
161
  return this;