README
Fayona (The Node version of . Net Core)
Note: The below details is high abstract of what the library provide
Motivation
At some point, we needed Node.js for a particular thing and my colleagues have been using Net Core for always, so I thought it would be nice to make the functions and classes look familiar to reduce the learning.
Getting Started
- Create
Application
class and extendFayona
class - Invoke
UseControllers
instance method to register the controllers UseControllers
accept callback with registry instance- Invoke
UseEndpoints
to configure routes/endpoints options - you can use
UseErrorHandler
to catch any unhandled application error
export class Application extends Fayona {
constructor() {
this.UseControllers((registry) => {
registry.addController(UserController);
registry.addController(ActivityController);
});
this.UseEndpoints((endpointOptions) => {
endpointOptions.prefix = '/api';
})
this.UseErrorHandler(globalErrorHandler);
}
}
Define Controllers
@Route('users')
export class UserController {
service = locate(UserService);
@HttpGet('', identity.Authorize(Role.ADMIN))
async getAllUsers(@FromQuery(Pagination) pagination: Pagination) {
const users = await this.service.getAll(pagination);
return users;
}
@HttpGet('search', identity.Authorize())
public searchForUser(@FromQuery(SearchForUsersQuery) dto: SearchForUsersQuery) {
return this.service.searchForUsers(dto);
}
@HttpGet(':id', identity.Authorize(Role.ADMIN))
public get(@FromParams('id') id: string) {
return this.service.getById(id);
}
@HttpPost('')
async createUser(@FromBody(CreateUserDto) dto: CreateUserDto) {
// you don't need to handle any error in service.create method, you catch all up in UseErrorHandler, typically create entity method will be called a lot and in most cases you'll return the same exception or doing same null checking therefore you can handle it all once by just letting them.
await this.service.create(dto);
return new SuccessResponse('Created');
}
}
Application
class contains express instance, so you can fallback to it in any case.
Still there's a lot to be written, this is just for demonstration sake.
Modules
Module | Description |
---|---|
translation |
Translation library that helps you to switch from language to another |
routing |
Set of decorators to facilitate declaring HTTP actions |
locator |
Simple service locator implementation |
identity |
Simple service locator implementation (Under Development) |
Routing Decorators/Attributes
Attribute | Description |
---|---|
Route |
explicty mark the handler to specific endpoint |
FromBody |
retrive the body from the incoming requst and implictly validate it if possible |
FromQuery |
retrive query params/param from Uri |
FromParams |
retrive specific param from Uri |
FromHeaders |
retrive header name from the request |
ContextResponse |
Get current http context Response |
ContextRequest |
Get current http context Request |
HttpPost |
Mark the handler as HTTP POST request handler |
HttpGet |
Mark the handler as HTTP GET request handler |
HttpPut |
Mark the handler as HTTP PUT request handler |
HttpDelete |
Mark the handler as HTTP DELETE request handler |
HttpPatch |
Mark the handler as HTTP PATCH request handler |
Identity Decorators/Attributes
Attribute | Description |
---|---|
AllowAnonymous |
Mark the route to be authentication free |
identity.Authorize(...Roles?) |
Prevent access to a route or route action if the user is not authenticated or have the desired role |
identity.Authenticated() |
Prevent access to a route or route action if the user is not authenticated |
Api
@Route(endpoint: string, options?: IRouterDecorationOption)
is the escence of this library, it will route all the requests to the givin path and will execute the handler that match the final endpoint
@Route('examples')
class ExampleController {
}
Classes
export interface IRouterDecorationOption extends RouterOptions {
/**
* Register child route under the parent prefix
*
* e.g:
*
* @Route('restaurants', {
* children: [MealController]
* })
* class RestaurantController {}
*
*
* @Route('meals')
* class MealController {}
*
* so in order to hit the meals, you will call `restaurants/meals`
*
* Note: you mustn't explicty register ChildController via AddController method in startup configuration
*/
children?: any[];
/**
* Set of middleware will be executed before calling the final end point
*
* e.g: identity.Authorize()
*/
middleware?: RequestHandler[] | RequestHandlerParams[];
}
Developer
License
Licensed under MIT