npm package: @sachin-chourasiya/mongoose-aggregation-builder
Description: A secure, chainable MongoDB aggregation builder for Mongoose with input validation and safe defaults.
Author: Sachin Chourasiya
Latest version: 1.0.0

# @sachin-chourasiya/mongoose-aggregation-builder

A simple, secure, and chainable **MongoDB aggregation pipeline builder** for Mongoose.  
It makes complex aggregation queries easier to write, **readable**, and **safe from injection risks**.

---

## 🚀 Why Use This?

Writing raw MongoDB aggregation pipelines can be verbose and hard to maintain:

```js
User.aggregate([
  { $match: { status: 'active' } },
  {
    $lookup: {
      from: 'orders',
      localField: '_id',
      foreignField: 'userId',
      as: 'orders',
    },
  },
  { $unwind: { path: '$orders', preserveNullAndEmptyArrays: true } },
  { $group: { _id: '$_id', totalOrders: { $sum: 1 } } },
  { $sort: { totalOrders: -1 } },
  { $limit: 10 },
]);
```

With **@sachin-chourasiya/mongoose-aggregation-builder**:

```js
const pipeline = Agg()
  .filter({ status: 'active' })
  .join('orders', '_id', 'userId', 'orders')
  .unwind('orders', true)
  .countOrders()
  .sortBy('totalOrders', 'desc')
  .limit(10)
  .build();

User.aggregate(pipeline);
```

---

## 📦 Installation

```bash
npm install @sachin-chourasiya/mongoose-aggregation-builder
```

---

## ✨ Features

- **Chainable API** → Build pipelines step-by-step
- **Secure** → Sanitizes field names and prevents malicious stages
- **Readable** → No more deeply nested arrays of objects
- **Reusable** → Save and reuse pipelines easily
- **TypeScript Friendly** → Works with `.d.ts` type definitions (coming soon)

---

## 📚 Usage Examples

### Example 1 — Basic Filtering & Projection

```js
const Agg = require('@sachin-chourasiya/mongoose-aggregation-builder');

const pipeline = Agg()
  .filter({ isActive: true })
  .project({ name: 1, email: 1 })
  .build();

User.aggregate(pipeline);
```

**Generated Pipeline:**

```js
[{ $match: { isActive: true } }, { $project: { name: 1, email: 1 } }];
```

---

### Example 2 — Join with Another Collection

```js
const pipeline = Agg()
  .filter({ status: 'active' })
  .join('orders', '_id', 'userId', 'orders')
  .unwind('orders')
  .build();

User.aggregate(pipeline);
```

**Generated Pipeline:**

```js
[
  { $match: { status: 'active' } },
  {
    $lookup: {
      from: 'orders',
      localField: '_id',
      foreignField: 'userId',
      as: 'orders',
    },
  },
  { $unwind: '$orders' },
];
```

---

### Example 3 — Counting & Sorting

```js
const pipeline = Agg()
  .filter({ status: 'active' })
  .groupBy('_id', { totalOrders: { $sum: 1 } })
  .sortBy('totalOrders', 'desc')
  .limit(5)
  .build();

User.aggregate(pipeline);
```

---

## 🛡 Security

- **Field Name Sanitization** — prevents `$` operator injection in keys
- **Safe Stage Restriction** — only allows MongoDB stages you enable
- **No Eval or Function Execution** — pure JSON pipelines
- **Input Validation** — ensures correct data types for filters, sorting, etc.

---

## 📖 API Reference

### `.filter(query)`

Adds a `$match` stage to filter documents.

### `.project(fields)`

Adds a `$project` stage.

### `.join(collection, localField, foreignField, as)`

Adds a `$lookup` stage to join another collection.

### `.unwind(path, preserveNull = false)`

Adds a `$unwind` stage.

### `.groupBy(id, accumulators)`

Adds a `$group` stage.

### `.countOrders()`

Custom helper → counts number of joined documents.

### `.sortBy(field, order = "asc")`

Adds a `$sort` stage.

### `.limit(n)`

Adds a `$limit` stage.

### `.build()`

Returns the final aggregation pipeline array.

---

## 📄 License

MIT License © 2025