Skip to content

Latest commit

 

History

History
139 lines (103 loc) · 4.63 KB

9.modifiers.md

File metadata and controls

139 lines (103 loc) · 4.63 KB
title Modifiers
description Use database modifiers such as @Hashed, @Encrypted, and @Localized with a data controller, and pass a per-request modifier key with @ModifierKey.
mode reference

Overview

Modifiers from @antelopejs/interface-database-decorators work with the Data API without extra configuration in the data controller. Modifiers such as @Hashed or @Encrypted transform data on every read and write.

Some modifiers need a value at runtime, such as the locale key of the localization modifier. The @ModifierKey decorator maps a controller field to the runtime key of one modifier.

The @ModifierKey decorator

Use @ModifierKey when a modifier needs a value that changes per request. The decorator links a controller field to a modifier class. At request time, the Data API passes the value of the field to the modifier when it locks and unlocks data.

import { ModifierKey } from "@antelopejs/interface-data-api/metadata";

Signature

@ModifierKey(modifierClass: typeof ContainerModifier<any>)
Parameter Description
modifierClass The modifier class that needs a runtime key, for example LocalizationModifier

Example: localized content

The LocalizationModifier needs a locale identifier to choose which translation to store or read. In this example, @ModifierKey takes that value from an HTTP header.

import { Controller, Parameter } from "@antelopejs/interface-api";
import {
  DataController,
  DefaultRoutes,
  RegisterDataController,
} from "@antelopejs/interface-data-api";
import {
  Access,
  AccessMode,
  Listable,
  ModelReference,
  ModifierKey,
} from "@antelopejs/interface-data-api/metadata";
import {
  BasicDataModel,
  Field,
  Localized,
  LocalizationModifier,
  Model,
  RegisterTable,
  Table,
} from "@antelopejs/interface-database-decorators";

@RegisterTable("content", "myapp")
class Content extends Table.with(LocalizationModifier) {
  @Field("string")
  declare _id: string;

  @Localized()
  @Field("string")
  declare title: string;

  @Localized()
  @Field("string")
  declare description: string;
}

class ContentModel extends BasicDataModel(Content, "content") {}

@RegisterDataController()
class ContentAPI extends DataController(
  Content,
  DefaultRoutes.All,
  Controller("/content"),
) {
  @ModelReference()
  @Model(ContentModel, "my-database")
  declare contentModel: ContentModel;

  @Parameter("x-content-language", "header")
  @ModifierKey(LocalizationModifier)
  declare language: string;

  @Listable()
  @Access(AccessMode.ReadWrite)
  declare title: string;

  @Listable()
  @Access(AccessMode.ReadWrite)
  declare description: string;
}

How it works

  1. The HTTP request includes the header x-content-language: fr.
  2. The language property receives the value "fr".
  3. On a write, the modifier stores the localized value under the key "fr".
  4. On a read, the modifier reads the localized value stored under "fr".

This request writes French values:

POST /content/new
x-content-language: fr
Content-Type: application/json

{
  "title": "Titre en francais",
  "description": "Description en francais"
}

The record stores the data under the "fr" locale key. A later request with x-content-language: en reads and writes other localized values of the same record.

Most modifiers, such as @Hashed and @Encrypted, do not need @ModifierKey. Only a modifier that needs a runtime value per request needs this decorator.

Integration with other features

Foreign keys

Modifiers work with foreign key relationships. When the Data API resolves foreign records, it unlocks the modifier fields of those records. See Foreign keys for details.

Filters

A custom filter receives a query expression that the modifier's unlockrequest() method builds, not a decrypted JavaScript value. Localization supports access at query time. The built-in encryption modifier leaves its stored value unchanged in query expressions, so do not filter on the plain text of an encrypted field. See Modifier integration in the filters page for details.

Learn more

For the full list of modifiers and how to write your own, see the @antelopejs/interface-database-decorators repository.

Next steps

To flatten a field of another table onto each row for sorting and filtering in the database, see Joined fields.