vanta-api 1.0.3 → 1.0.5

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/README.md CHANGED
@@ -258,25 +258,73 @@ These configurations are applied automatically in methods such as `filter()`, `p
258
258
 
259
259
  ## Error Handling Middleware
260
260
 
261
- A dedicated error-handling middleware is available to centralize error responses:
261
+ Vanta-API provides a centralized error handling system featuring three components:
262
+
263
+ ### 1. handleError
264
+
265
+ **Purpose:**
266
+ A custom error class that extends the native JavaScript `Error`.
267
+ It adds:
268
+ - **`statusCode`:** HTTP status code.
269
+ - **`status`:** Determines if the error is a `"fail"` (client error) or `"error"` (server error).
270
+ - **`isOperational`:** Flags if the error is an expected operational error.
271
+ - **Stack Trace:** Captures the call stack for easier debugging.
272
+
273
+ **Usage Example in an Async Function:**
274
+
275
+ Inside an asynchronous function wrapped by **catchAsync**, you can use:
276
+
277
+ ```javascript
278
+ // Inside your async route handler
279
+ if (someConditionFails) {
280
+ return next(new handleError("Custom error message", 400));
281
+ }
282
+ ```
283
+
284
+ ### 2. catchAsync
285
+
286
+ **Purpose:**
287
+ A helper function that wraps asynchronous route handlers.
288
+ It automatically catches any thrown errors and forwards them via `next()`, avoiding repetitive try/catch blocks.
289
+
290
+ **Usage Example:**
262
291
 
263
292
  ```javascript
264
- import catchError from "./errorHandler.js";
293
+ app.get("/example", catchAsync(async (req, res, next) => {
294
+ // Your async logic here
295
+ // If an error occurs, use handleError as shown above
296
+ res.status(200).json({ data: "Success" });
297
+ }));
298
+ ```
299
+
300
+ ### 3. catchError
301
+
302
+ **Purpose:**
303
+ An Express middleware that catches any error passed along (either from synchronous or asynchronous routes).
304
+ It sets the appropriate HTTP status and returns a JSON response containing the error’s status and message.
305
+
306
+ **Usage Example:**
265
307
 
266
- // In your Express app:
267
- // app.use(catchError);
308
+ ```javascript
309
+ // At the end of your middleware stack:
310
+ app.use(catchError);
268
311
  ```
269
312
 
270
- This middleware sets the appropriate HTTP status code and JSON error message when an error occurs.
313
+ ---
314
+
271
315
 
272
316
  ---
273
317
 
274
318
  ## Full Examples
275
319
 
276
320
  ### Example 1: Basic Query
321
+ To import the package along with the error handling components, use:
322
+
323
+ ```javascript
324
+ import ApiFeatures, { handleError, catchAsync, catchError } from "vanta-api";
325
+ ```
277
326
 
278
327
  ```javascript
279
- import ApiFeatures from "./api-features.js";
280
328
  import Product from "./models/product.js";
281
329
 
282
330
  // URL: /api/products?status=active&price[gte]=100&sort=-price,createdAt&fields=name,price,category&page=1&limit=10&populate=category,brand
@@ -362,9 +410,30 @@ console.log(result);
362
410
  Integrated advanced logging using winston and centralized error handling with a custom error class and middleware.
363
411
  - **Performance Optimizations:**
364
412
  Supports aggregation cursor for large datasets and optimizes aggregation pipelines for efficient resource usage.
413
+
414
+ - **ApiFeatures:**
415
+ Provides advanced query capabilities such as filtering, sorting, pagination, and document population for your MongoDB data.
416
+
417
+ - **Error Handling Components:**
418
+ - **handleError:**
419
+ Throw consistent, structured errors with custom messages and status codes.
420
+ - **catchAsync:**
421
+ Wrap asynchronous route handlers to automatically propagate errors.
422
+ - **catchError:**
423
+ Centralized middleware to catch and respond to errors uniformly.
424
+
425
+ - **Importing:**
426
+ Use the following statement to access all features:
427
+
428
+ ```javascript
429
+ import ApiFeatures, { handleError, catchAsync, catchError } from "vanta-api";
430
+ ```
431
+
432
+ By following these guidelines, you can integrate and use Vanta-API for advanced, secure query handling and robust error management in your Node.js/Express projects.
365
433
 
366
434
  ---
367
435
 
368
436
  VantaApi provides a complete solution for integrating powerful, secure, and customizable query capabilities into any Node.js/MongoDB project.
369
437
 
370
- ---
438
+ ---
439
+
package/index.js ADDED
@@ -0,0 +1,6 @@
1
+ import ApiFeatures from "./src/api-features.js";
2
+ import catchError from "./src/errorHandler.js";
3
+ import HandleERROR from "./src/handleError.js";
4
+ import catchAsync from "./src/catchAsync.js";
5
+ export {catchError,HandleERROR,catchAsync}
6
+ export default ApiFeatures
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "vanta-api",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Advanced API features and security configuration for Node.js/MongoDB.",
5
- "main": "src/api-features.js",
5
+ "main": "index.js",
6
6
  "scripts": {
7
7
  "postinstall": "node bin/create-security-config.js",
8
8
  "test": "jest",
9
- "start": "node src/api-features.js"
9
+ "start": "node index.js"
10
10
  },
11
11
  "keywords": [
12
12
  "api",
@@ -1,4 +1,3 @@
1
- // api-features.js
2
1
  import mongoose from "mongoose";
3
2
  import winston from "winston";
4
3
  import { securityConfig } from "./config.js";
@@ -170,8 +169,6 @@ export class ApiFeatures {
170
169
  });
171
170
  });
172
171
 
173
- // پشتیبانی از nested populate: در صورت نیاز، منطق تو در تو را می‌توانید اینجا اضافه کنید.
174
-
175
172
  return this;
176
173
  }
177
174
 
@@ -184,11 +181,9 @@ export class ApiFeatures {
184
181
 
185
182
  async execute(options = {}) {
186
183
  try {
187
- // انتخاب حالت cursor در مواقع پردازش داده‌های حجیم
188
184
  if (options.useCursor === true) {
189
185
  this.useCursor = true;
190
186
  }
191
- // اجرای موازی pipeline‌های شمارش و داده
192
187
  const [countResult, dataResult] = await Promise.all([
193
188
  this.Model.aggregate([...this.countPipeline, { $count: "total" }]),
194
189
  (this.useCursor
@@ -258,7 +253,22 @@ export class ApiFeatures {
258
253
 
259
254
  #sanitizeNestedObjects(obj) {
260
255
  return Object.entries(obj).reduce((acc, [key, value]) => {
261
- if (typeof value === "object" && !Array.isArray(value)) {
256
+ // Handle ObjectId fields with nested operators
257
+ if (key.endsWith("Id") && typeof value === "object" && !Array.isArray(value)) {
258
+ const sanitizedObj = {};
259
+ for (const [op, val] of Object.entries(value)) {
260
+ if (["$eq", "$ne", "$gt", "$gte", "$lt", "$lte"].includes(op) && mongoose.isValidObjectId(val)) {
261
+ sanitizedObj[op] = new mongoose.Types.ObjectId(val);
262
+ } else if (["$in", "$nin"].includes(op) && Array.isArray(val)) {
263
+ sanitizedObj[op] = val
264
+ .filter(v => mongoose.isValidObjectId(v))
265
+ .map(v => new mongoose.Types.ObjectId(v));
266
+ } else {
267
+ sanitizedObj[op] = val;
268
+ }
269
+ }
270
+ acc[key] = sanitizedObj;
271
+ } else if (typeof value === "object" && !Array.isArray(value)) {
262
272
  acc[key] = this.#sanitizeNestedObjects(value);
263
273
  } else {
264
274
  acc[key] = this.#sanitizeValue(key, value);
@@ -274,7 +284,7 @@ export class ApiFeatures {
274
284
  if (typeof value === "string") {
275
285
  if (value === "true") return true;
276
286
  if (value === "false") return false;
277
- if (/^\d+$/.test(value)) return parseInt(value);
287
+ if (/^\d+$/.test(value)) return parseInt(value, 10);
278
288
  }
279
289
  return value;
280
290
  }
@@ -0,0 +1,6 @@
1
+ export const catchAsync=fn=>{
2
+ return (req,res,next)=>{
3
+ fn(req,res,next).catch(next)
4
+ }
5
+ }
6
+ export default catchAsync