Skip to main content

ModelRoute

Every CRUD operation RapidREST offers, however you end up exposing it, comes down to the same handful of building blocks: find matching records, create one, update one, delete one, and so on. ModelRoute<T> is where that logic actually lives. It handles input validation, ACL permission checks, optimistic locking, and conflict detection for a single entity type, all the parts that are genuinely hard to get right, without ever deciding how, or whether, any of it gets exposed over HTTP. That decision is left entirely to you.

This matters more than it sounds like it should. A model that should never accept a public DELETE, an admin-only resource where only a couple of operations should ever be reachable, a URL scheme that doesn't follow the usual /:id convention, all of these want the same business logic ModelRoute already provides, just wired up selectively instead of automatically. That's exactly what extending ModelRoute directly buys you:

import { ModelRoute, RouteDecorators } from '@rapidrest/service-core';
const { Get, Head, Model, Route } = RouteDecorators;

@Model(Pet)
@Route('/pets')
export class PetRoute extends ModelRoute<Pet> {
@Head()
count(@Param() params: any, @Query() query: any, @User user?: JWTUser) {
return super.doCount({ params, query, user });
}

@Get()
find(@Param() params: any, @Query() query: any, @User user?: JWTUser) {
return super.doFind({ params, query, user });
}

@Get('/:id')
findById(@Param('id') id: string, @Query() query: any, @User user?: JWTUser) {
return super.doFindById(id, { query, user });
}
}

PetRoute here only exposes count, find, and findById, there's no way to create, update, or delete a Pet over HTTP at all, even though ModelRoute itself is perfectly capable of it. Nothing about that had to be disabled or locked down, it simply was never wired up in the first place.

The functions

FunctionWhat it does
doCountCounts matching documents. The count comes back as Content-Length, there's no response body.
doCreateCreates one document, or several from an array.
doFindReturns documents matching the query, see Filtering, Pagination & Sorting.
doFindByIdReturns the single document with the given id.
doUpdateUpdates the document with the given id.
doBulkUpdateUpdates several documents at once.
doUpdatePropertyUpdates the value of one property on one document.
doDeleteDeletes (or soft-deletes) one document. Accepts version and purge options, see CRUDRoute for what each one does when exposed over HTTP.
doTruncateDeletes every document matching the query.
doExistsChecks whether a document with the given id exists, Content-Length is 1 or 0, no body.

Each one takes an options object, the same { params, query, user }-style shape shown above, that's how permission checks and validation know who's asking and what they're asking for. Skip user and the call behaves as if it came from an anonymous caller, which usually means it gets rejected the moment ACLs are enabled.

If none of this selective wiring sounds necessary for a given model, it probably isn't, CRUDRoute already extends ModelRoute and exposes every one of these functions automatically. Reach for ModelRoute directly specifically when you don't want that.