Skip to content
This repository has been archived by the owner on Apr 17, 2023. It is now read-only.

Commit

Permalink
Merge aeb411a into 4b534ff
Browse files Browse the repository at this point in the history
  • Loading branch information
wtrocki committed Aug 13, 2017
2 parents 4b534ff + aeb411a commit 8ab0188
Show file tree
Hide file tree
Showing 40 changed files with 1,148 additions and 23 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ cache:
- cloud/logger/node_modules
- cloud/passportauth/node_modules
- cloud/datasync/node_modules
- cloud/wfm-rest-api/node_modules
- client/logger/node_modules
- client/wfm/node_modules
- client/datasync-client/node_modules
4 changes: 4 additions & 0 deletions cloud/wfm-rest-api/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# generated code
/**/*.map
/**/*.js
coverage_report/
108 changes: 108 additions & 0 deletions cloud/wfm-rest-api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# RainCatcher Api module

Module used to expose express based api for WFM objects.

### WFM speficic implementations

Following api is being exposed:

- `/workorders`
- `/workflows`
- `/results`

This api is being added to new express router and it can be applied to any existing express based application
as follows:

```typescript
// Create api
const api = new WfmRestApi();

// Mount api into path
app.use('/api', api.createWFMRouter());
```

Api requires mongodb connection that needs to be setup as separate step

```typescript
api.setDb(db);
```
See demo application integration or [example application](./example) for more details.

### Custom database integrations

Custom database integrations are possible thanks to `CrudRepository` interface.
See Api documentation for more details.

## Rest API

Module provides a way to dynamically create API for different business objects.
Created api will use simplied implementations for typical create, read, delete and update operations.
It's not recomended to use it outside WFM framework to store user related objects. Please use mongodb driver directly.

## Rest API definitions

Definitions apply to every to object exposed by this API. Placeholder `{object}` can be replaced by `workflow`, `workorder` and `result`.

### Retrieve list

> GET {object}/
##### Pagination
Supports pagination and sorting by providing additional query parameters:

- `page` page number
- `size` number of elements to return
- `sortField` sorting field
- `order` -1 for DESC and 1 for ASC

Example `/workorders?page=0&size=5&sortField=id&order=-1`

> **Note** - sorting parameters are optional. When missing default sorting values are applied (10 results)
##### Filtering

List can be filtered by providing json as `filter` query parameter or `filter` as request body.

`filter` - json object with specific field

For example `filter = { 'reviewer': 'Paolo'}`

> **Note** - Due to nature of the url filter needs to be encoded to be passed as url
### Retrieve specific object by id

> GET {object}/:objectId
Retrieve specific object by id

Example `/workorders/B1r71fOBr`

### Save object

> POST {object}/
### Update object

> PUT {object}/
### Delete object

> DELETE {object}/:objectId
### Error handling

Api returns non 200 status in case of error.

`400` - For user input error (missing required field etc.)
`500` - For internal server errors

Additionaly error metadata is being returned:

```json
{
"code":"InvalidID",
"message":"Provided id is invalid"
}
```

> **Note:** If you apply security middleware additional `401` and `403` statuses may be returned
15 changes: 15 additions & 0 deletions cloud/wfm-rest-api/example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## wfm-web-api example

### Requirements

Mongodb running on standard port

### Runining example

ts-node example/index.ts

To test example try

curl http://localhost:3000/api/workorders

Note: This example assumes that you have run demo application that populated your database.
33 changes: 33 additions & 0 deletions cloud/wfm-rest-api/example/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { getLogger } from '@raincatcher/logger';
import * as express from 'express';
import { MongoClient } from 'mongodb';
import * as path from 'path';
import { WfmRestApi } from '../src/index';

const app = express();

// Create api
const api = new WfmRestApi();

// Mount api into path
app.use('/api', api.createWFMRouter());

// Use connect method to connect to the server
const url = 'mongodb://localhost:27017/raincatcher';
MongoClient.connect(url, function(err, db) {
if (db) {
api.setDb(db);
} else {
console.info('MongoDb not connected', err);
process.exit(1);
}
});

app.use(function(err: any, req: express.Request, res: express.Response, next: any) {
getLogger().error(err);
res.status(500).send(err);
});

app.listen(3000, function() {
getLogger().info('Example auth app listening on port 3000');
});
61 changes: 61 additions & 0 deletions cloud/wfm-rest-api/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"name": "@raincatcher/wfm-rest-api",
"version": "1.0.0",
"description": "Module used for building RESTFULL api on top of the WFM solution",
"types": "src/index.ts",
"author": "feedhenry-raincatcher@redhat.com",
"license": "Apache-2.0",
"main": "src/",
"scripts": {
"clean": "del coverage_report src/**/*.js src/**/*.map test/**/*.js test/**/*.map",
"build": "tsc",
"start": "ts-node src/index.ts",
"test": "npm run clean && nyc mocha"
},
"nyc": {
"include": [
"src/**/*.ts"
],
"extension": [
".ts"
],
"require": [
"ts-node/register"
],
"reporter": [
"lcov",
"text"
],
"report-dir": "coverage_report",
"check-coverage": true,
"lines": 75,
"functions": 80,
"branches": 70
},
"dependencies": {
"@raincatcher/logger": "1.0.0",
"bluebird": "^3.5.0",
"express": "^4.15.3",
"lodash": "^4.17.4",
"mongodb": "^2.2.31"
},
"devDependencies": {
"@types/bluebird": "^3.5.5",
"@types/express": "^4.0.35",
"@types/lodash": "^4.14.72",
"@types/mocha": "^2.2.41",
"@types/mongodb": "^2.2.9",
"@types/proxyquire": "^1.3.27",
"@types/sinon": "^2.3.3",
"@types/sinon-express-mock": "^1.3.2",
"del-cli": "^1.0.0",
"mocha": "^3.4.2",
"nyc": "^11.0.1",
"proxyquire": "^1.8.0",
"sinon": "^3.2.0",
"sinon-express-mock": "^1.3.1",
"source-map-support": "^0.4.15",
"ts-node": "^3.0.4",
"typescript": "^2.3.4"
}
}
31 changes: 31 additions & 0 deletions cloud/wfm-rest-api/src/ApiConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

/**
* Module configuration interface
* Holds all values that can be changed to modify module behavior
*/
export interface ApiConfig {
/** Used to create workorder route */
workorderApiName?: string;
/** Used to create workflow route */
workflowApiName?: string;
/** Used to create result route */
resultApiName?: string;
/** Used as collection name to make database query for workorder */
workorderCollectionName?: string;
/** Used as collection name to make database query for workflow */
workflowCollectionName?: string;
/** Used as collection name to make database query for result */
resultCollectionName?: string;
}

/**
* Default module configuration
*/
export const defaultConfiguration: ApiConfig = {
workorderApiName: 'workorders',
workflowApiName: 'workflows',
resultApiName: 'results',
workorderCollectionName: 'workorders',
workflowCollectionName: 'workflows',
resultCollectionName: 'result'
};
54 changes: 54 additions & 0 deletions cloud/wfm-rest-api/src/WfmRestApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@

import * as Promise from 'bluebird';
import * as express from 'express';
import * as _ from 'lodash';
import { Db } from 'mongodb';
import { ApiConfig, defaultConfiguration } from './ApiConfig';
import { ApiController } from './impl/ApiController';
import { MongoDbRepository } from './impl/MongoDbRepository';

/**
* RESTfull api handlers for Workorders, Workflows and Results (WFM objects)
*/
export class WfmRestApi {
private config;
private workorderService: MongoDbRepository;
private workflowService: MongoDbRepository;
private resultService: MongoDbRepository;

constructor(userConfig?: ApiConfig) {
this.config = _.defaults(defaultConfiguration, userConfig);
this.createWFMServices();
}

/**
* Create new router for hosting WFM http api.
*/
public createWFMRouter() {
const router: express.Router = express.Router();
const workorderController = new ApiController(router, this.workorderService, this.config.workorderApiName);
workorderController.applyAllRoutes();
const workflowController = new ApiController(router, this.workflowService, this.config.workflowApiName);
workflowController.applyAllRoutes();
const resultController = new ApiController(router, this.resultService, this.config.resultApiName);
resultController.applyAllRoutes();
return router;
}

/**
* Inject database connection to services
*
* @param db - mongodb driver
*/
public setDb(db: Db) {
this.workorderService.setDb(db);
this.workflowService.setDb(db);
this.resultService.setDb(db);
}

protected createWFMServices() {
this.workorderService = new MongoDbRepository(this.config.workorderCollectionName);
this.workflowService = new MongoDbRepository(this.config.workflowCollectionName);
this.resultService = new MongoDbRepository(this.config.resultCollectionName);
}
}
8 changes: 8 additions & 0 deletions cloud/wfm-rest-api/src/data-api/ApiError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

/**
* Interface used to construct standarized response for api error handlers.
*/
export interface ApiError {
code: string;
message: string;
}

0 comments on commit 8ab0188

Please sign in to comment.