Field Decorators
FieldDecorator lets you hook into a document's read/write path per field — wrap
what's written before it reaches storage, unwrap it after it comes back. Use it for per-field
encryption, compression, checksums, or logging.
Attaching decorators
Decorators can be configured at the collection level, the document level, or both:
val notes = Documents.collection("notes") {
decorators = listOf(LoggingDecorator())
}
val note = notes.document<Note>("note-1") {
decorators = listOf(ChecksumDecorator())
}
// note's effective decorator list, in order: [LoggingDecorator(), ChecksumDecorator()]
Collection-level decorators apply to every document opened in that collection; document-level decorators are appended after them for that one document.
Order matters
Writes fold through the decorator list left-to-right; reads fold right-to-left. Whichever decorator ran last on write runs first on read, so each wrap is undone in the reverse order it was applied:
// decorators = listOf(Compress, Encrypt)
// write: bytes -> Compress.wrap -> Encrypt.wrap -> stored
// read: stored -> Encrypt.unwrap -> Compress.unwrap -> bytes
This is why compress-then-encrypt — not the reverse — is the order that actually works: encrypted bytes are high-entropy and don't meaningfully compress. See Decorations for why the library folds the list this way.
Where else this applies
Decorators also apply under field delegates — see
Field Delegates — and sit immediately next to where CBOR
encode/decode happens, see Serialization (CBOR)
and Field Decomposition. A decorator's
unwrap failing surfaces as DocumentDecodingException, the same as any
other decode failure — see Error Handling.