# @ehbraheem/api

> A microservice boilerplate.

Latest version **0.0.3** (published 2020-06-03) · ISC license · 0 weekly downloads

## Install

```sh
npm install @ehbraheem/api
pnpm add @ehbraheem/api
yarn add @ehbraheem/api
bun add @ehbraheem/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.0.3 |
| Published | 2020-06-03 |
| First published | 2020-05-30 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | none |
| Module format | CommonJS |
| Node | >=10 |
| Dependencies | 15 |
| Unpacked size | 90.8 KB |
| Known vulnerabilities | 0 (+15 in 4 direct dependencies) |
| Install scripts | no |
| Author | Bolatan Ibrahim |
| Maintainers | bolatan |

## Links

- npm: https://www.npmjs.com/package/@ehbraheem/api
- npm.io page: https://npm.io/package/@ehbraheem/api

## Dependencies (15)

- [cors](https://npm.io/package/cors.md) ^2.8.5
- [ramda](https://npm.io/package/ramda.md) 0.27.0
- [dotenv](https://npm.io/package/dotenv.md) ^8.2.0
- [helmet](https://npm.io/package/helmet.md) ^3.16.0
- [morgan](https://npm.io/package/morgan.md) ^1.9.1
- [convict](https://npm.io/package/convict.md) 5.2.0
- [express](https://npm.io/package/express.md) 4.17.1
- [mongoose](https://npm.io/package/mongoose.md) 5.9.14
- [@hapi/joi](https://npm.io/package/@hapi/joi.md) 17.1.1
- [xss-clean](https://npm.io/package/xss-clean.md) ^0.1.1
- [fast-json-stringify](https://npm.io/package/fast-json-stringify.md) 2.0.0
- [mongoose-paginate-v2](https://npm.io/package/mongoose-paginate-v2.md) 1.3.9
- [express-mongo-sanitize](https://npm.io/package/express-mongo-sanitize.md) ^1.3.2
- [mongoose-lean-virtuals](https://npm.io/package/mongoose-lean-virtuals.md) 0.6.2
- [@ehbraheem/service-utils](https://npm.io/package/@ehbraheem/service-utils.md) 0.0.4

## Recent versions

- 0.0.3 (latest) — 2020-06-03
- 0.0.3-0 — 2020-05-30
- 0.0.2-0 — 2020-05-30
- 0.0.1 — 2020-05-30

## README

# @ehbraheem/api
A CRUD microservice module.

[![CircleCI](https://circleci.com/gh/Ehbraheem/api.svg?style=svg)](https://circleci.com/gh/Ehbraheem/api)

A CRUD microservice module exposing key features of a RESTful API as injected dependencies.

## Installation

```sh
$ yarn add @ehbraheem/api
```

## bootstrapping
To create a new CRUD service API, simply bootstrap the application by injecting the dependencies as depicted in the example below.

```ts
import server, { mongooseConnect as dbConnect, Api } from '@ehbraheem/api';
import config from './config';
import { schema } from './persistence/mongoose';

import routes from './routes';
import services from './services';


const application = (): Promise<Api> =>
  server({
    routes,
    services,
    schema,
    config,
    dbConnect,
  });
```

Then start the app as shown in the example below
```ts
(async (): Promise<void> => {
  const app = await application();

  const PORT = config.get('server.port');

  app.listen(PORT, config.get('server.hostname'), (): void => {
    // eslint-disable-next-line no-console
    console.log(`Server running on port ${config.get('server.hostname')}:${PORT}`);
  });
})();
```

## setting up environment variables
[node-convict](https://github.com/mozilla/node-convict) and [dotenv](https://github.com/motdotla/dotenv) are both used to manage application configuration. It is a requirement to create a file named `.env` at root of project and setup as follows:



```bash
# Application
PORT=4015
TLS_CERT=/path/to/server.crt
TLS_KEY=/path/to/server..key

# OR... Mongo Database
MONGO_DB=mydb
```

You can console log `process.env` to find out available environment variables. You can also inspect the imported `config` object from `@ehbraheem/api`.


## APIs

Details of each of the exposed APIs will now be explained.

### database connectors

```ts
import { mongooseConnect, server } from '@ehbraheem/api';

server({
  ...
  dbConnect: mongooseConnect,   // DB connection helper
  ...
});
```

Simply import `mongooseConnect` (uses [mongoose](https://github.com/Automattic/mongoose)) to connect to mongo database.

### schema

A schema will need to be implemented to query and manipulate the database.

```ts
import schema from 'path/to/my/models';

server({
  ...
  schema,
  ...
});
```

The exported models are each expected to receive the `db` connector (client) as an argument, for example...

```ts
import { Dict, DbClient } from '@ehbraheem/api';
import users from './User/queries';
import books from './Book/queries';

export default (client: DbClient): Dict => ({
  users: users(client),
  books: books(client),
});
```


### routes

[Express](https://expressjs.com/en/guide/routing.html) is the core building block of this module. All routing and handling of client requests are managed by handlers defined.

```ts
import routes from 'path/to/my/routes';

server({
  ...
  routes,
  ...
});
```

Firstly, export all handlers of client requests, for example...

```ts
import createUser, { destroyUser } from './users/routes';
import createBook from './books/routes';

import { Router } from 'express';

import usersRoutes, { MOUNT_POINT as users } from './users/routes';
import booksRoutes, { MOUNT_POINT as books } from './users/routes';
import { ApiRouter, RouterArgs } from '@ehbraheem/api';

export default ({ services, validator, json, config }: RouterArgs): ApiRouter => ({
  [users]: usersRoutes({ router: Router(), services, config, validator, json }),
  [books]: booksRoutes({ router: Router(), services, config, validator, json }),
});
```

Each route handler is an higher order function that will receive in its arguments...
This is an example routes file.

```ts
import { createUser, ROUTE_NAME } from './controllers';
import { Router } from 'express';
import { RouteArgs } from '@ehbraheem/api';

export const MOUNT_POINT = `/${ROUTE_NAME}`;

export default ({ 
  router, 
  services,  // Service response formatter
  validator, // joi validator
  config,    // Application configuration 
  json,      // used by services to create JSON string format 
}: RouteArgs): Router => {
  router
    .route('/')
    .post(createUser({ services, json, validator }));

  return router;
};
```
Each route should have an equivalent controller function like the below.

```ts
import { Request, Response, NextFunction } from 'express';

export const createUser = ({
  services,
  json,
  validator,
}): ((req: Request, res: Response, next: NextFunction) => Promise<void>) => async (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  ...
};
```

Find out more about the passed in features:
- Application configuration using [convict](https://github.com/mozilla/node-convict)
- Object schema validation with [joi](https://github.com/hapijs/joi)
- A JSON string formatted resource object creator using [fast-json-stringify](https://github.com/fastify/fast-json-stringify)


### plugins

Prior to routes, Express [middlewares](https://expressjs.com/en/guide/writing-middleware.html) can be loaded. In the following example the [cookie-session](https://github.com/expressjs/cookie-session) plugin module is configured as follows:

```ts
import cookieSession from 'cookie-session';

server({
  ...
  middlewares: [cookieSession],
  ...
});
```

### services

`services` is the layer between the `router` and the `schema` layers. It's main responsibility is to pass on the `payload` from the `router` to the `schema`. It also creates the JSON string formatted resource response payload coming from the `schema` layer.

Firstly define the services; For example...

```ts
import { Dict } from '@ehbraheem/api';
import users from './users/services';
import books from './books/services';

export default (db: Dict): Dict => ({
  users: users(db),
  books: books(db),
 ...
});
```

Each `service` handler will receive in its arguments (passed down from `router`)...

```ts
export const create = async ({
  db,         // db connector
  payload,    // request payload
  config,     // app config
  payload
}) => {
  ...
};
```

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