WFM api framework - HTTP RESTfull api for WFM (ex-webapi) #75
WFM api framework - HTTP RESTfull api for WFM (ex-webapi) #75
Conversation
|
||
public list() { | ||
return this.db.collection(this.collectionName).find({}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this class, or an interface definition of it should be async, not all storage libs can fit a synchronous api.
@@ -14,6 +14,7 @@ module.exports = function (grunt) { | |||
}, | |||
exec: { | |||
'run': 'ts-node src/index.ts', | |||
'runDebug': 'ts-node --inspect src/index.ts', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@austincunningham We can debug now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need grunt over this same line in an npm script?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I guess it's for reloading the app? There's nodemon
for that too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm.. actually it's for life reload that was supported in previous application..
I couldn't really get that running so life reload will not work now :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:)
cloud/wfm-rest-api/example/index.ts
Outdated
api.setDb(db); | ||
} else { | ||
console.info('MongoDb not connected', err); | ||
process.exit(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should add some non-zero value to make sure the process exits with an error: process.exit(1)
.
Alternatively this could be done before starting the http server at all:
promisify(MongoClient.connect)(...).then(db => api.setDb(db)).then(() => app.listen(...));
cloud/wfm-rest-api/src/ApiConfig.ts
Outdated
/** | ||
* Default module configuration | ||
*/ | ||
export const defaultConfiguration = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could implement ApiConfig
, just to inherit jsdoc info
cloud/wfm-rest-api/src/ApiConfig.ts
Outdated
resultApiName?: string; | ||
workorderCollectionName?: string; | ||
workflowCollectionName?: string; | ||
resultCollectionName?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need jsdocs for these keys
cloud/wfm-rest-api/src/WfmRestApi.ts
Outdated
const router: express.Router = express.Router(); | ||
const workorderController = new ApiController(router, this.workorderService, this.config.workorderApiName); | ||
const workflowController = new ApiController(router, this.workflowService, this.config.workflowApiName); | ||
const resultController = new ApiController(router, this.resultService, this.config.resultApiName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-1 for extra class here, this is using a constructor only for side-effects (mutating router
).
Just need something like
router.use(`/${workorderApiName}`, buildRouter(this.workorderService))
so you don't need to mutate router inside another function, and reduces # of params for buildRouter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 That will be also easy to unit tests. Do you see api exposing each crud method or we should get entire CRUD operations as now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's okay to return a router with all the methods, the idea behind router.use('/mount-point', middleware)
is that that middleware can properly handle everything from that point onwards.
* Interface is being used internally to perform database operations for WFM models | ||
* It's not recomended to use it for other application business logic. | ||
*/ | ||
export interface CrudRepository { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like using the term CRUD itself, feels like too much slang and signals boilerplate code.
Could be PagingDataRepository
or something, much fancier :D
* Note: pages are counted from number 1. | ||
* Page 0 requests will return empty data. | ||
*/ | ||
export class PaginationEngine { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe MongoPaginationEngine
? Implementation is mongo-specific.
}); | ||
}); | ||
} | ||
protected errorHandler(req: express.Request, res: express.Response, error: ApiError) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need a local error handler for this router.
This would prevent the application to define it's own global error handler, and even try to handle errors from this module in a different way.
We do have a global error handler in the app by the way: https://github.com/feedhenry-raincatcher/raincatcher-core/blob/master/demo/server/src/app.ts#L66
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example, production error handlers can redirect a user to a 'oops' page, log exceptions to external storage or email, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you suggesting here. I wanted this module to be responsible for error handling as app currently tries to render html. This will throw nice json.
What will be your suggestion - throw error here ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, in order to allow the top level app to use the global error handler you add the third param and call next(err)
, the app might crash on uncaught errors.
The global error handler that I linked should return a formatted json just the same, but it's possible to override it at that global point.
See http://expressjs.com/en/guide/error-handling.html, more specifically:
PaidContent.find(function (err, doc) {
if (err) return next(err)
res.json(doc)
})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just do not wanted this module to be self sufficient and do not leak some of the elements to users top level application, but this aproach will be more aligned with express patterns.
d691630
to
8cfaf10
Compare
demo/server/config-dev.json
Outdated
@@ -1,7 +1,10 @@ | |||
{ | |||
"morganOptions": null, | |||
"logStackTraces": true, | |||
"sync":{ | |||
"security": { | |||
"apiRole": "ADMIN" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JameelB is that admin
or ADMIN
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's admin
ab13cee
to
de0fba1
Compare
Changes Unknown when pulling 16d8bb0 on wtrocki:RAINCATCH-1145 into ** on feedhenry-raincatcher:master**. |
cloud/wfm-rest-api/README.md
Outdated
|
||
Module used to expose express based api for WFM objects. | ||
|
||
### WFM speficic implementations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
specific
cloud/wfm-rest-api/README.md
Outdated
## 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
simplified
cloud/wfm-rest-api/README.md
Outdated
|
||
## Rest API definitions | ||
|
||
Definitions apply to every to object exposed by this API. Placeholder `{object}` can be replaced by `workflow`, `workorder` and `result`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove to
in every to object
cloud/wfm-rest-api/example/README.md
Outdated
|
||
Mongodb running on standard port | ||
|
||
### Runining example |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Running
@@ -0,0 +1,9 @@ | |||
|
|||
/** | |||
* Interface used to construct standarized response for api error handlers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
standardized
@@ -0,0 +1,9 @@ | |||
|
|||
/** | |||
* Interface used to construct standarized response for api error handlers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
standardized
getLogger().debug('Api delete method called', { params: req.params }); | ||
|
||
if (!req.params.id) { | ||
const error = new ApiError(errorCodes.MISSING_ID, 'Missing id parameter'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing statusCode 400
?
getLogger().debug('Api update method called', { body: req.body }); | ||
|
||
if (!req.body) { | ||
const error = new ApiError(errorCodes.CLIENT_ERROR, 'Missing request body'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing statusCode 400
?
* Interface used to construct standarized response for api error handlers. | ||
*/ | ||
export class ApiError extends Error { | ||
constructor(public code: string, public message: string, statusCode: number = 500) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code and statusCode not used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TypeScript magic. Adding public is exposing them as fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
may need to add public
to statusCode as well?
cloud/wfm-rest-api/README.md
Outdated
## 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possibly better to say
"create, read, update and delete" - think of CRUD
cloud/wfm-rest-api/README.md
Outdated
|
||
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- What does "it" refer to in "to use it" - the rest api?
- outside "the" WFM framework
cloud/wfm-rest-api/README.md
Outdated
} | ||
``` | ||
|
||
> **Note:** If you apply security middleware additional `401` and `403` statuses may be returned |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: "If you apply middleware security, additional "
cloud/wfm-rest-api/example/README.md
Outdated
|
||
curl http://localhost:3000/api/workorders | ||
|
||
Note: This example assumes that you have run demo application that populated your database. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...run "the" demo application...
16d8bb0
to
8efbf0c
Compare
Changes Unknown when pulling 8efbf0c on wtrocki:RAINCATCH-1145 into ** on feedhenry-raincatcher:master**. |
8efbf0c
to
112d2ca
Compare
Changes Unknown when pulling 112d2ca on wtrocki:RAINCATCH-1145 into ** on feedhenry-raincatcher:master**. |
cloud/wfm-rest-api/src/ApiConfig.ts
Outdated
/** Used to create workflow route */ | ||
workflowApiName?: string; | ||
/** Used to create result route */ | ||
resultApiName?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can get rid of the Used to
s here, and more detail for the client developer: Root path for the Result http endpoints.
112d2ca
to
6388fe3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
verified
Changes Unknown when pulling 6388fe3 on wtrocki:RAINCATCH-1145 into ** on feedhenry-raincatcher:master**. |
1 similar comment
Changes Unknown when pulling 6388fe3 on wtrocki:RAINCATCH-1145 into ** on feedhenry-raincatcher:master**. |
Motivation
Allow to use express based API to operate on WFM objects.
Note: this changes are WFM specific and it will require integration with WFM module = sparate PR in angular.js repository
Notes
I have done some investigation for pagination and I did not found anything that will meet all of our criteria. I wrote simple pagination mechanism for this module. We can extract this to separate module if needed somewhere else but I think it makes sense to have it here.
Progress