[data-reveal]{opacity:1!important;transform:none!important}
Value Encodings
Interface reference

Value Encodings

Overview

Configuration values are plain JSON by default. AddBlockInput.config, a ConfigureBlock patch, a page's permission — all of it is written to source exactly as you pass it, as a literal.

Some options need TypeScript values rather than JSON literals. A form field needs a DataType instance, a relation needs a controller class, and a chart card needs a nested chart. The structured encodings below let the builder write those values and their imports. Use a raw $expr only as an escape hatch; drafts and query parameters reject it.

import type {
  BlockValue,
  DataTypeValue,
  ExprValue,
  RefValue,
} from "@antelopejs/interface-dms-builder";

Choose an Encoding

You are writingEncoding
A string, number, boolean, array or objectThe value itself, as JSON.
A value the catalog marks x-dataTypeDataTypeValue
A reference to a builder-generated resource classRefValue
A nested component in an option marked x-componentBlockValue
Anything else that must reach the source as codeExprValue

The catalog is what tells you which option needs which: an option marked x-dataType in a block's ConfigSchema takes a DataTypeValue, and nothing else. See Catalog.

Write a DataType

DataTypeValue emits new <DataType>(<config>) and adds the import for you.

FieldTypeDescription
$dataTypestringA DataTypeDescriptor.id from the catalog, e.g. "string" or "select".
configRecord<string, unknown>The DataType's options. Omit for a no-arg new <DataType>().
import { AddBlock } from "@antelopejs/interface-dms-builder";

await AddBlock({
  page: "/customers",
  name: "editor",
  type: "Form",
  config: {
    fields: [
      {
        id: "name",
        label: "Name",
        type: { $dataType: "string", config: { placeholder: "Name" } },
      },
    ],
  },
});
// emits:  type: new DefaultDataTypes.StringType({ placeholder: "Name" })

The same encoding is what a resource field's dataType takes, described in Resources.

A $dataType id the catalog does not list fails with invalid_config, and the message points you at GetCatalog for the valid ids.

Reference a Generated Class

RefValue emits the bare class identifier of a builder-generated resource, with its import added. It is the structured, validated alternative to ExprValue for a class reference — a RelationType's dataApiController, for instance.

FieldTypeDescription
$ref.resourcestringA ResourceRef — the resource's name, e.g. "product".
$ref.as"dataApi" | "table" | "model"Which of the resource's classes to reference. Defaults to "dataApi".
import { AddField } from "@antelopejs/interface-dms-builder";

await AddField("order-line", {
  name: "productId",
  label: "Product",
  dataType: {
    $dataType: "relation",
    config: { dataApiController: { $ref: { resource: "product" } } },
  },
});
// emits:  dataApiController: productDataAPI   (imported from the resource's data-api.ts)

as selects among the three classes a resource generates: "dataApi" for the DataController, "table" for the Table, "model" for the BasicDataModel. An unknown resource fails with invalid_config, and the message points you at ListResources.

AddBlockInput.controller is the same reference in a dedicated field: a controller-leading block type takes a ResourceRef there rather than a RefValue in its config. See Page Operations.

Write a Raw Expression

ExprValue is emitted verbatim. Reach for it only when the builder cannot model the value structurally.

FieldTypeDescription
$exprstringTypeScript source, spliced into the emitted file as written.
import { ConfigureBlock } from "@antelopejs/interface-dms-builder";

await ConfigureBlock("/revenue#total", {
  valueFormat: { $expr: "REVENUE_FORMAT" },
});

Two constraints come with it:

  • The referenced symbol must already be in scope in the target file. $expr adds no import.
  • $expr is refused inside a query's parameters — a query's values are data, and a raw expression would put uncheckable code inside a model body. See Queries.

Consumers that run the builder in a restricted mode may refuse $expr outright, since arbitrary code defeats the structured guarantees the rest of the surface provides. RefValue is allowed in that mode precisely because it is validated; prefer it whenever the value you need is a generated class.

Nest a Block in a Config Value

A few options hold a component rather than data — a ChartCard's chart, marked x-component in the catalog. BlockValue is how you write one: the builder emits the nested factory call and adds its import.

import type { BlockValue } from "@antelopejs/interface-dms-builder";

const chart: BlockValue = {
  $block: { type: "ChartArea", config: { xaxisType: "datetime" } },
};
// → chart: ChartArea({ xaxisType: "datetime" })

type is a catalog key, like AddBlockInput.type; an unknown one is rejected with invalid_config. Read-back is symmetrical: a nested factory call whose callee is a known block type comes back as a $block sentinel rather than as $expr, so the value stays editable.

Most nesting does not go through config — it goes through .child, which you express with AddBlockInput.parent or with BlockDraft.children. Reach for $block only where the catalog marks an option x-component.

Next Steps