ModelRouterOptions
This is the main configuration.
Type Parameters
T
T
the base document type. This should not include Mongoose models, just the types of the object.
Properties
access?
optionalaccess?:ModelRouterAccessOptions
RBAC access configuration for this router. Requires accessControl on the same options object
or injected by TerrenoApp at build time.
accessControl?
optionalaccessControl?:AnyTerrenoAccess
TerrenoAccess instance used to evaluate access permissions.
admin?
optionaladmin?:AdminConfig
Optional admin panel metadata for this model. Consumed by AdminApp when aggregating
/admin/config and for server-side field scrubbing / realtime change events.
allowAnonymous?
optionalallowAnonymous?:boolean
Allow anonymous users to access the resource. Defaults to false.
collectionActions?
optionalcollectionActions?:Record<string,CollectionActionConfig<unknown,unknown,unknown>>
Named collection-scoped operations at /:actionName (GET or POST).
defaultLimit?
optionaldefaultLimit?:number
Default limit applied to list queries if not specified by the user. Defaults to 100.
defaultQueryParams?
optionaldefaultQueryParams?:Record<string,unknown>
Default queries to provide to Mongo before any user queries or transforms happen when making list queries. Accepts any Mongoose-style queries, and runs for all user types. defaultQueryParams: {hidden: false} // By default, don't show objects with hidden=true These can be overridden by the user if not disallowed by queryFilter.
endpoints?
optionalendpoints?: (router,options?) =>void
Custom route setup function. Receives the router and optionally the full options (including openApi).
Parameters
router
Router
options?
Partial<ModelRouterOptions<T>>
Returns
void
instanceActions?
optionalinstanceActions?:Record<string,InstanceActionConfig<T,unknown,unknown,unknown>>
Named instance-scoped operations at /:id/:actionName (GET or POST).
maxLimit?
optionalmaxLimit?:number
Maximum query limit the user can request. Defaults to 500, and is the lowest of the limit query, max limit, or 500.
mcp?
optionalmcp?:MCPConfig
MCP (Model Context Protocol) configuration. When provided, registers this model's CRUD operations as MCP tools that can be called by LLMs.
Tools are auto-generated based on the methods specified (default: ['list', 'read']). Auth, permissions, population, and filtering all work the same as REST.
Example
modelRouter("/todos", Todo, {
mcp: {
methods: ['list', 'read', 'create'],
excludeFields: ['internalNote'],
maxLimit: 25,
},
});
openApi?
optionalopenApi?:OpenApiMiddleware
The OpenAPI generator for this server. This is used to generate the OpenAPI documentation.
openApiExtraModelProperties?
optionalopenApiExtraModelProperties?:Record<string,unknown>
Overwrite parts of the model properties for the OpenAPI generator. This will be merged with the generated configuration. This is useful if you add custom properties to the model during serialize, for example, that you want to be documented and typed in the SDK.
openApiOverwrite?
optionalopenApiOverwrite?:object
Overwrite parts of the configuration for the OpenAPI generator. This will be merged with the generated configuration.
create?
optionalcreate?:Record<string,unknown>
delete?
optionaldelete?:Record<string,unknown>
get?
optionalget?:Record<string,unknown>
list?
optionallist?:Record<string,unknown>
update?
optionalupdate?:Record<string,unknown>
permissions
permissions:
RESTPermissions<T>
A group of method-level (create/read/update/delete/list) permissions. Determine if the user can perform the operation at all, and for read/update/delete methods, whether the user can perform the operation on the object referenced.
Deprecated
Use access with accessControl instead. Still required as a type-level
fallback; resolveModelRouterAccess replaces these methods when access is set.
populatePaths?
optionalpopulatePaths?:PopulatePath[]
Manages Mongoose populations before returning from all methods (list, read, create, etc). For each population: path: Accepts Mongoose-style populate strings for path. e.g. "user" or "users.userId" (for an array of subschemas with userId) fields: An array of strings to filter on the populated objects, following Mongoose's select rules. If each field starts a preceding "-", will act as a block list and only remove those fields. If each field does not start with a "-", will act as an allow list and only return those fields. Mixing allow and blocking is not supported. e.g. "-created updated" is an error. openApiComponent: If you have a component already registered, use that instead of autogenerating the types for the populated fields.
postCreate?
optionalpostCreate?: (value,request) =>void|Promise<void>
Hook that runs after the object is created but before the responseHandler serializes and returned. This is a good spot to perform dependent changes to other models or performing async tasks/side effects, such as sending a push notification. Throw an APIError to return a 400 with an error message.
Parameters
value
T
request
Request
Returns
void | Promise<void>
postDelete?
optionalpostDelete?: (request,value) =>void|Promise<void>
Hook that runs after the object is deleted. This is a good spot to perform dependent changes to other models or performing async tasks/side effects, such as cascading object deletions. Throw an APIError to return a 400 with an error message.
Parameters
request
Request
The Express request object.
value
T
The document that was deleted, after the soft update of deleted: true (type: T).
Returns
void | Promise<void>
postGet?
optionalpostGet?: (value,request) =>Promise<T> |undefined
Hook that runs after the object is fetched but before it is serialized. Returns a promise so that asynchronous actions can be included in the function. Throw an APIError to return a 400 with an error message. @deprecated: Use responseHandler instead.
Parameters
value
T
request
Request
Returns
Promise<T> | undefined
postList?
optionalpostList?: (value,request) =>Promise<Document<unknown,unknown,unknown,Record<string,any>, { }> &T[]>
Hook that runs after the list of objects is fetched but before they are serialized. Returns a promise so that asynchronous actions can be included in the function. Throw an APIError to return a 400 with an error message. @deprecated: Use responseHandler instead.
Parameters
value
Document<unknown, unknown, unknown, Record<string, any>, { }> & T[]
request
Request
Returns
Promise<Document<unknown, unknown, unknown, Record<string, any>, { }> & T[]>
postUpdate?
optionalpostUpdate?: (value,cleanedBody,request,prevValue) =>void|Promise<void>
Hook that runs after the object is updated but before the responseHandler serializes and returned. This is a good spot to perform dependent changes to other models or perform async tasks/side effects, such as sending a push notification. Throw an APIError to return a 400 with an error message.
Parameters
value
T
The document after it has been updated (type: T).
cleanedBody
Partial<T>
The request body relative to the model update (type: Partial
request
Request
The Express request object.
prevValue
T
The entire document before it was updated (type: T).
Returns
void | Promise<void>
preCreate?
optionalpreCreate?: (value,request) =>T|Promise<T> |null
Hook that runs after transformer.transform but before the object is created.
Can update the body fields based on the request or the user.
Return null to return a generic 403 error. Throw an APIError to return a 400 with specific
error information.
Parameters
value
Partial<T> | (Partial<T> | undefined)[] | null | undefined
request
Request
Returns
T | Promise<T> | null
preDelete?
optionalpreDelete?: (value,request) =>T|Promise<T> |null
Hook that runs after transformer.transform but before the object is deleted.
Return null to return a generic 403 error.
Throw an APIError to return a 400 with specific error information.
Parameters
value
T
The document to be deleted, before the soft update of deleted: true (type: T).
request
Request
The Express request object.
Returns
T | Promise<T> | null
preUpdate?
optionalpreUpdate?: (value,request) =>T|Promise<T> |null
Hook that runs after transformer.transform but before changes are made for update operations.
Can update the body fields based on the request or the user.
Also applies to all array operations. Return null to return a generic 403 error.
Throw an APIError to return a 400 with specific error information.
Parameters
value
Partial<T>
The request body relative to the model update (type: Partial
request
Request
The Express request object.
Returns
T | Promise<T> | null
queryFields?
optionalqueryFields?:string[]
A list of fields on the model that can be queried using standard comparisons for booleans,
strings, dates
(as ISOStrings), and numbers.
For example:
?foo=true // boolean query
?foo=bar // string query
?foo=1 // number query
?foo=2022-07-23T02:34:07.118Z // date query (should first be encoded for query params, not shown here)
Note: limit and page are automatically supported and are reserved.
queryFilter?
optionalqueryFilter?: (user?,query?) =>Record<string,unknown> |Promise<Record<string,unknown> |null> |null
queryFilter is a function to parse the query params and see if the query should be allowed.
This can be used for permissioning to make sure less privileged users are not making
privileged queries. If a query should not be allowed,
return null from the function and an empty query result will be returned to the client
without an error. You can also throw an APIError to be explicit about the issues.
You can transform the given query params by returning different values.
If the query is acceptable as-is, return query as-is.
Parameters
user?
query?
Record<string, unknown>
Returns
Record<string, unknown> | Promise<Record<string, unknown> | null> | null
realtime?
optionalrealtime?:RealtimeConfig
Enable real-time sync for this model via WebSocket events. When configured, CRUD operations will emit events to connected clients through the RealtimeApp plugin's change stream watcher.
Requires the RealtimeApp plugin to be registered with TerrenoApp.
responseHandler?
optionalresponseHandler?: (value,method,request,options) =>Promise<JSONValue>
Serialize an object or list of objects before returning to the client. This is a good spot to remove sensitive information from the object, such as passwords or API keys. Throw an APIError to return a 400 with an error message.
Parameters
value
Document<unknown, unknown, unknown, Record<string, any>, { }> & T | Document<unknown, unknown, unknown, Record<string, any>, { }> & T[]
method
"read" | "delete" | "list" | "create" | "update"
request
Request
options
ModelRouterOptions<T>
Returns
Promise<JSONValue>
sort?
optionalsort?:string| {[key:string]:"ascending"|"descending"; }
Default sort for list operations. Can be a single field, a space-seperated list of fields, or an object. ?sort=foo // single field: foo ascending ?sort=-foo // single field: foo descending ?sort=-foo bar // multi field: foo descending, bar ascending ?sort={foo: 'ascending', bar: 'descending'} // object: foo ascending, bar descending
Note: you should have an index field on these fields or Mongo may slow down considerably.
sync?
optionalsync?:SyncConfig
Enable local-first sync (@terreno/syncdb) for this model. Documents are scoped into streams (owner/tenant/broadcast/custom) with monotonic per-stream cursors.
Requires the schema to use isDeletedPlugin (soft delete tombstones) and
syncPlugin (per-stream _syncSeq stamping) — validated at registration.
Only works with the three-argument form: modelRouter('/path', Model, options).
transformer?
optionaltransformer?:TerrenoTransformer<T>
Transformers allow data to be transformed before actions are executed, and serialized before being returned to the user.
Transformers can be used to throw out fields that the user should not be able to write to, such as the admin flag.
Serializers can be used to hide data from the client or change how it is presented. Serializers run after the data
has been changed or queried but before returning to the client.
Deprecated
Use preCreate/preUpdate/preDelete hooks instead of transformer.transform. Use serialize instead of transformer.serialize.
validation?
optionalvalidation?:boolean|ModelRouterValidationOptions
Enable runtime validation of request bodies against the OpenAPI schema. When enabled, requests that don't match the documented schema will return 400 errors.
Can be set to:
true: Enable validation for create and update operationsfalse: Disable validation (default)- Object with
validateCreateandvalidateUpdatebooleans for fine-grained control
Note: Global validation can be enabled via configureOpenApiValidator().
This option overrides the global setting for this specific router.