RapidREST ships with two abstract base classes that you can extend to provide automatic CRUD functionality for data models. These base classes
are: ModelRoute and CRUDRoute.
ModelRoute
The ModelRoute base class provides a set of functions that implement all of the business logic for the most common CRUD operations seen in a
typical REST API. The business logic implemented in these functions includes input validation, authorization and permissions verification
(using ACLs), conflict and missing data identification, optimistic locking (via the version property) and more.
The following table lists the available functions and the overall behavior that function implements.
| Function | What it does |
|---|---|
doCount | Counts all documents (supports query filtering). Sets Content-Length with the count. |
doCreate | Creates a new document of the given type. |
doDelete | Delete a single document (supports ?version= and ?purge=true). |
doExists | Checks if a document with the given id exists. Content-Length is 1 or 0. |
doFind | Returns all documents matching the given query filter. |
doFindById | Returns the single document with the given id. |
doTruncate | Deletes all documents (supports query filtering). |
doUpdate | Modifies a single document with the given id. |
doBulkUpdate | Modifies multiple documents. |
doUpdateProperty | Update the value of a single object's property |
Since this base class does not explicitly declare any REST API endpoints it is ideal for implementing classes that wish to control or expose only a limited subset of the implemented functionality.
For example, to utilize ModelRoute and implement only count, find and findById functionality, create a new class that extends ModelRoute
that implements only the desired functions as shown in the example below.
import { ModelRoute, RouteDecorators } from "@rapidrest/service-core";
const { Head, Get, Route } = RouteDecorators;
@Route("/my-model")
export class MyModelRoute extends ModelRoute<MyModel> {
@Head()
public count(
@Param() params: any,
@Query() query: any,
@Response res: HttpResponse,
@User user?: JWTUser,
): Promise<any> {
return super.doCount({ params, query, res, user });
}
@Get()
public find(@Param() params: any, @Query() query: any, @User user?: JWTUser): Promise<Array<MyModel>> {
return super.doFind({ params, query, user });
}
@Get("/:id")
public findById(@Param("id") id: string, @Query() query: any, @User user?: JWTUser): Promise<MyModel | null> {
return super.doFindById(id, { query, user });
}
}
CRUDRoute
The CRUDRoute abstract base class is an extension of ModelRoute that wires up each of the pre-defined behavior functions to real REST API endpoints. For most data-driven REST APIs, this is the preferred base class to extend.
To utilize CRUDRoute for your own data model simply create a new class and extend it like in the example below.
import { CRUDRoute, RouteDecorators } from "@rapidrest/service-core";
const { Route } = RouteDecorators;
@Route("/my-model")
export class MyModelRoute extends CRUDRoute<MyModel> {}
The table below details which REST API endpoints this class exposes, the path it's bound to, the underlying ModelRoute function it calls, and what
additional decorators it implements.
| HTTP Verb+Path | Calls Function | Addtl. Decorators |
|---|---|---|
HEAD /<path> | doCount | none |
POST /<path> | doCreate | @Validate("validateCreate") |
DELETE /<path/:id | doDelete | none |
HEAD /<path>/:id | doExists | none |
GET /<path> | doFind | none |
GET /<path>/:id | doFindById | none |
DELETE /<path> | doTruncate | none |
PUT /<path> | doBulkUpdate | @Validate("validateUpdateBulk") |
PUT /<path>/:id | doUpdate | @Validate("validateUpdate") |
PUT /<path>/:id/:property | doUpdateProperty | none |
Note that while none of the above endpoints implements authorization explicitly, the user's action will be verified against the class and/or document
ACL when it is decorated with the @Protect decorator.
You may optionally override any of endpoint functions defined in CRUDRoute to apply additional decorators. It is not necessary to duplicate all of
the decorators in the base class. For example, if you want to apply the @Auth decorator to require authentication to the create endpoint, all
that is needed is the following in your implementing class.
@Route("/my-model")
export class MyModelRoute extends CRUDRoute<MyModel> {
@Auth(["jwt"])
public create(obj: MyModel | MyModel[], @Request req: HttpRequest, @User user?: JWTUser): Promise<MyModel | Array<MyModel>> {
return super.doCreate(obj, { req, user });
}
}