Transformers
Transformers change the entities and files arocapi returns, for example to add fields.
| Option | Required | Type | Default | Purpose |
|---|---|---|---|---|
entityTransformers |
no | EntityTransformer[] |
[] |
Transform each entity from /entities, /entity/:id and /search. |
fileTransformers |
no | FileTransformer[] |
[] |
Transform each file from /files. |
Pipeline
Section titled “Pipeline”Every entity and file response flows through the same steps:
- Base transformer. arocapi turns the database row into an
AuthorisedEntityorAuthorisedFileshape, resolvingmemberOfandrootCollectionto{ id, name }. - Access. arocapi attaches the access function’s result as
access. - Your transformers, in order. Each receives the previous one’s output and can read
access.
Transformers don’t run for /entity/:id/metadata or /file/:id, which return bytes from your
storage backend. Search results get searchExtra (score and highlights) after your transformers.
The request lifecycle shows where these steps sit.
entityTransformers
Section titled “entityTransformers”Each transformer receives an AuthorisedEntity (or the previous transformer’s output) and the request context, and may
be async.
| Field | Type |
|---|---|
id |
string |
entityType |
string |
name |
string |
description |
string |
memberOf |
{ id, name } | null |
rootCollection |
{ id, name } | null |
metadataLicenseId |
string |
contentLicenseId |
string |
access |
AccessInfo |
import type { EntityTransformer, Options } from 'arocapi';
const addShortId: EntityTransformer = (entity) => ({ ...entity, shortId: entity.id.split('/').pop() });
export const entityTransformers: Options['entityTransformers'] = [addShortId];The returned object is sent as is. The Record is never redacted by arocapi, so a transformer that removes fields is the only thing that can.
fileTransformers
Section titled “fileTransformers”Each transformer receives an AuthorisedFile and the request context:
| Field | Type |
|---|---|
id |
string |
filename |
string |
mediaType |
string |
size |
number |
access |
{ content: boolean; contentAuthorizationUrl?: string } |
A file’s access is its file entity’s Content access.
import type { FileTransformer } from 'arocapi';
export const addSizeInKb: FileTransformer = (file) => ({ ...file, sizeInKb: Math.round(file.size / 1024) });Request context
Section titled “Request context”Visibility filters, the access function, isAuthenticated, transformers and storage backends all receive a RequestContext:
| Field | Type | Purpose |
|---|---|---|
request |
FastifyRequest |
The current request: headers, query and whatever your authentication sets on it. |
fastify |
FastifyInstance |
The Fastify instance, for reading your own decorations. arocapi adds none. |
import type { EntityTransformer } from 'arocapi';
export const addRequestedLanguage: EntityTransformer = (entity, { request }) => ({ ...entity, requestedLanguage: request.headers['accept-language'] ?? null,});