# weare-api

> A module to help build Mongoose-based REST APIs.

Latest version **0.1.5** (published 2018-11-05) · 0 weekly downloads

## Install

```sh
npm install weare-api
pnpm add weare-api
yarn add weare-api
bun add weare-api
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.1.5 |
| Published | 2018-11-05 |
| First published | 2018-11-05 |
| Weekly downloads | 0 |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 3 |
| Unpacked size | 120.9 KB |
| Known vulnerabilities | 0 (+6 in 1 direct dependencies) |
| Install scripts | no |
| Author | Mickael Burguet |
| Maintainers | smcyr |

## Links

- npm: https://www.npmjs.com/package/weare-api
- Repository: https://bitbucket.org/weare/weare-npm-api
- npm.io page: https://npm.io/package/weare-api

## Dependencies (3)

- [async](https://npm.io/package/async.md) ^1.4.0
- [lodash](https://npm.io/package/lodash.md) ^3.10.1
- [weare-ajax-response](https://npm.io/package/weare-ajax-response.md) ^2.1.2

## Recent versions

- 0.1.5 (latest) — 2018-11-05

## README

[TOC]

WE_ARE API
===================
A module to help build mongoose-based REST APIs.
Sends responses using the [weare-ajax-response](https://bitbucket.org/weare/weare-npm-ajax-response) module.
Tests cover ~90% of the code.

## Installation
```bash
$ npm install weare-api
```

## Running the tests

To run the unit tests, you must install the dev dependencies: `npm install --only-dev`. Then, you only have to execute `npm test`.

## Usage
```js
var api = require('weare-api')(router);
```
The return value is an instance of `WeareApi` with the following properties :

### router
The same object that you passed as an argument when you initialized the module.

### parseParams
An object with the following functions:

`parseGet(req, paramsDefinition)` Parses GET parameters (`req.query`) and puts them into `req.parsedQuery`

`parsePost(req, paramsDefinition)` Parses POST parameters (`req.body`) and puts them into `req.parsedBody`

`parse(req, paramsDefinition, values, parsedObjectName)` The function used by parseGet and parsePost

The `paramsDefinition` arguments is an object defining the parameters to parse - here's an example :
```js
{
	paramName1: {
		type: 'integer|float|date'
		required: boolean
		default: 'optional value'
	},
	...
}
```
| Types   | Validators |
|---|---|
| string  | required, regExp, enum, minlength |
| integer  | required, min, max |
| float  | required, min, max |
| boolean | required |
| date | required |

### restify(options)

Creates api endpoints (*getAll*, *getOne*, *create*, *update*, *order*, *delete*) for a model. Example:

```js
var News = require('../../models/News');

api.restify({
	route: 'news',
	model: News,
	modelName: 'news',

	select: '-__v',
	populate: '_image _category',
	sort: { 'date' : 'desc' },
	pagination: {defaults: { number: 20 } },

	populateOne: '_image _category',

	disabled: [
		'create',
		'update',
		'delete'
	],


	hooks: {
		getAll: {
			// filter by category
			buildQuery: function(query, req, res, options, callback) {
				var parseErrors = api.parseParams.parseGet(req, {
					category: {
						type: 'string',
						default: null
					},
				});

				if (parseErrors !== null) {
					ajaxResponse(res).badRequest(parseErrors);
					return callback('error');
				}

				if(req.parsedQuery.category) {
					query.where('_category', req.parsedQuery.category);
				}

				callback(null, query);
			},
		},
	}
});
```

[View all the possible options by clicking here.](restify-options.md)

#### Hooks
Hooks are functions that can either modify a query before its execution or modify the data before sending it back to the client.
**You can send your own error responses back to the client, else the module will automatically send an "internalServerError" response**.
Available hooks are listed below.

#### Route types

##### **getOne** - `GET /:route/:id`
Gets a document by id.

###### **buildQuery(query, req, res, options, callback) hook**
Called before executing the `findOne` query.
The *callback* function should be called with 1 or 2 arguments: `callback(err, modifiedQuery)`.

###### **modifyResult(item, req, res, options, callback) hook**
Called before returning the *json-ified* item back to the client.
The *callback* function should be called with 1 or 2 arguments: `callback(err, modifiedItem)`.

##### **getAll** - `GET /:route`
Gets a list of documents.

###### **buildQuery(query, req, res, options, callback)  hook**
Called before executing the `find` query.
The *callback* function should be called with 1 or 2 arguments: `callback(err, modifiedQuery)`.

###### **modifyResults(responseData, req, res, options, callback) hook**
Called before returning the data back to the client. **Warning: The responseData format will be different whether you have enabled the pagination or not.**
The *callback* function should be called with 1 or 2 arguments: `callback(err, modifiedResponseData)`.


##### **create** - `POST /:route`
Creates a new document.

###### **beforeSave(document, req, res, options, callback) hook**
Called right before saving the item to the database.
The *callback* function should be called with 1 or 2 arguments: `callback(err, modifiedDocument)`.

###### **afterSave(document, req, res, options, callback) hook**
Called right after the item has been saved into the database.
The *callback* function should be called with 1 argument: `callback(err)`.

##### **update** - `PUT /:route/:id`
Updates a document by id.

###### **buildQuery(query, req, res, options, callback)  hook**
Called before executing the `findOne` query.
The *callback* function should be called with 1 or 2 arguments: `callback(err, modifiedQuery)`.

###### **beforeSave(document, req, res, options, callback) hook**
Called right before saving the item to the database.
The *callback* function should be called with 1 or 2 arguments: `callback(err, modifiedDocument)`.

###### **afterSave(document, req, res, options, callback) hook**
Called right after the item has been saved into the database.
The *callback* function should be called with 1 argument: `callback(err)`.

##### **order** - `PUT /:route/:id/order`
Updates a document order. The new order is passed in the request body: `{ "order" : Number }`
Adjusts the other documents' orders in the collection, depending on the options that where passed to `api.restify`.

##### **delete** - `DELETE /:route/:id`
Deletes a document by id.
Also calls the model's static method `deleteAssets` if it is defined.

###### **beforeDelete(document, req, res, options, callback) hook**
Called right before deleting the item from the database.
The *callback* function should be called with 1 argument: `callback(err)`.

###### **afterDelete(document, req, res, options, callback) hook**
Called right after the item has been deleted from the database.
The *callback* function should be called with 1 argument: `callback(err)`.

### routeTo(route, routeType, req, res)
Programmatically call a route.

Example: `api.routeTo('news', 'getOne', req, res);` will forward the current request to the news getOne api route.

## Groups

You can create grouped middlewares and hooks configs, that will be applied to all the REST APIs belonging to that group.
Example:

```js
api.addGroup('cms', {
	middlewares: {
		'*': [ CMSAuthMiddleware ],
		'getAll': [ CMSPermissionsMiddleware.read ],
		'getOne': [ CMSPermissionsMiddleware.read ],
		'update': [ CMSPermissionsMiddleware.edit ],
		'order':  [ CMSPermissionsMiddleware.edit ],
		'create': [ CMSPermissionsMiddleware.edit ],
		'delete': [ CMSPermissionsMiddleware.delete ],
	}
});
```

Then, we create a REST API that will be in that group:

```js
api.restify({
		route: 'retailers',
		model: Retailers,
		groups: ['cms'],
});
```

## Changelog

### 0.1.2
- added option to use "toJSON()" instead of "toObject()" for result output

### 0.1.1
- improved code readability
- added "groups" support

### 0.1.0
- initial version

---
_Source: https://npm.io/package/weare-api · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
