[data-reveal]{opacity:1!important;transform:none!important}
Addressing and Structure
Interface reference

Addressing and Structure

Overview

Every builder operation identifies its target with a string ref. This page covers PageRef for a page, BlockPath for a block inside it, and CategoryRef for a menu category. Resources and Queries define their own refs.

Alongside the refs, this page describes the read shapes the builder hands back: the page metadata it can read and patch, the block tree it resolves from source, and the lightweight summaries the listing operations return. The operations that produce and consume these shapes live in Page Operations.

import type {
  BlockPath,
  CategoryRef,
  PageRef,
} from "@antelopejs/interface-dms-builder";

const page: PageRef = "/dashboard";
const block: BlockPath = "/dashboard#kpis/row/revenue";
const category: CategoryRef = "pages.reports";

Address a Page

PageRef is a page's route string, built from its category's slug and the page's own name — a page named revenue under the root pages category is /revenue. CreatePage returns the ref it assigned, and every page operation takes it as its first argument.

import {
  CreatePage,
  GetPageStructure,
} from "@antelopejs/interface-dms-builder";

const created = await CreatePage({
  name: "revenue",
  displayName: "Revenue",
  category: "pages",
});
if (created.ok) {
  const structure = await GetPageStructure(created.data.ref); // "/revenue"
}

Address a Block

BlockPath addresses one block inside a page: <pageRef>#<name> for a top-level block, then /<childId> for each nesting level below it.

PathWhat it addresses
/dashboard#kpisThe top-level block named kpis on /dashboard
/dashboard#kpis/rowThe .child("row", …) of that block
/dashboard#kpis/row/revenueThe .child("revenue", …) of row

The first segment after # is the static class member the block is declared as; every further segment is the id passed to .child(). AddBlock returns the path of the block it added, so you rarely build one by hand.

Address a Category

CategoryRef is a category's stable id. The three roots are pages, modules and settings; a category created under a parent is addressed by joining them with a dot, so a reports category under pages is pages.reports.

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

const category = await CreateCategory({
  name: "reports",
  displayName: "Reports",
  parent: "pages",
});
// category.data.ref === "pages.reports"

Read a Page's Metadata

PageMeta is what the builder knows about a page. It comes back inside PageStructure, which GetPageStructure returns.

FieldTypeDescription
refPageRefThe page's route string.
idstringThe page id, the first argument of its PageController.
displayNamestringThe label shown in the menu.
iconstringIcon name, when the page declares one.
categoryCategoryRefThe category the page belongs to.
ordernumberSort order within the category.
descriptionstringThe page's description.
hiddenbooleanWhether the page is hidden from the menu.
permissionPagePermissionThe permission guarding the page.
livePageLiveThe page's Direct / Pause options, when it is live.
filepathstringThe file the page is declared in, resolved by the builder's source index rather than by the runtime registry.

hidden, permission and live read back like any other field, as long as the page declares them literally. A permission built from a call or a reference — an Action, say — reads back as undefined: the builder reports only what it can also rewrite.

PagePermission mirrors the DMS MenuOptions.permission: a partial permission spec, whose fields are id, title, icon, description, dependencies and defaultGranted. A bare action id is not accepted — the DMS types the option as Partial<Permission> | Action, so a string would be written and then refused by the typecheck gate.

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

const permission: PagePermission = {
  id: "reports.export",
  title: "Export reports",
};

The DMS also accepts an Action there. That is a live object rather than data, so it has no encoding in the builder: a page declaring one reads its permission back as undefined.

PageLive mirrors the DMS MenuOptions.live: maxRate, slowRateAfter, rememberKey. Present, even empty ({}), the page is live — its blocks refetch through a Direct / Pause valve its LiveToggle switches; absent, they refetch on every event. Sent as null in a patch, it is taken off.

Patch a Page's Metadata

EditablePageMeta is the subset of PageMeta that ConfigurePage accepts as a patch: displayName, icon, category, order, description, hidden, permission and live. ref, id and filepath are not patchable — they follow from where the page lives.

Patching category moves the page, which changes its ref: the result carries the new one, and a route_changed warning says what the old route was. See Page Operations.

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

const patch: Partial<EditablePageMeta> = {
  displayName: "Monthly revenue",
  order: 10,
};

Read the Block Tree

BlockNode is one block in a page's tree. The builder resolves each static member and each .child() call it can parse; anything it cannot parse still appears as a node, marked not editable.

FieldTypeDescription
pathBlockPathThe block's address.
namestringStatic key for a top-level block, .child() id for a nested one.
typestring | nullThe factory name, or null when it does not resolve.
editablebooleanfalse marks an opaque, non-canonical block.
opaqueReasonstringWhy the block is opaque. Set when editable === false.
slotstringThe slot the block sits in, when its parent declares slots.
metaRecord<string, unknown>Child metadata beyond slot, such as { colSpan: 2 }. Keep it when constructing a draft from the tree.
configRecord<string, unknown>The block's options object. Present only when the block is editable.
controllerResourceRefFor a controller-leading block such as TableView, the resource its leading argument resolves to, when it is a known generated resource.
childrenBlockNode[]Container blocks only, in .child() order.

An opaque block is one the builder can see but not rewrite — a block behind an unresolved reference, or one produced by a computed expression rather than a direct factory call. Reading it is fine; ConfigureBlock, AddBlock under it and MoveBlock onto it fail with opaque_target, described in Results and Errors.

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

const result = await GetPageStructure("/dashboard");
if (result.ok) {
  for (const block of result.data.blocks) {
    if (!block.editable) {
      console.log(`${block.path} is opaque: ${block.opaqueReason}`);
    }
  }
}

Read a Page's Structure

PageStructure is the whole page as the builder sees it.

FieldTypeDescription
pagePageMetaThe page's metadata.
blocksBlockNode[]The top-level blocks, each carrying its own children.
queriesQueryStructure[]The query routes declared on the page, found by shape. See Queries.
versionstringA content hash of the page file.

version is what makes a write conditional: pass it back as expectedVersion on the next mutation and the operation fails with stale if the file changed in between. See Results and Errors.

Read the Listings

ListPages and ListCategories return summaries rather than full structures, so you can survey a project without parsing every page.

PageSummary:

FieldTypeDescription
refPageRefThe page's route string.
idstringThe page id.
displayNamestringThe label shown in the menu.
categoryCategoryRefThe category the page belongs to.
moduleIdstringThe module the page comes from, for pages declared inside a module.
filepathstringThe file the page is declared in.
iconstringThe icon the menu shows beside the page, when it declares one.
ordernumberSorts the page among the others of its category, when it declares one.
hiddenbooleanWhether the menu leaves the page out; its route still answers.

CategorySummary:

FieldTypeDescription
refCategoryRefThe category's id.
displayNamestringThe label shown in the menu.
parentCategoryRefThe parent category, absent for a root.
import {
  ListCategories,
  ListPages,
} from "@antelopejs/interface-dms-builder";

const [pages, categories] = await Promise.all([
  ListPages(),
  ListCategories(),
]);
const rootPages = pages.filter((page) => page.category === "pages");

Patch a Category's Metadata

EditableCategoryMeta is what ConfigureCategory accepts: displayName, parent, icon and order. Re-parenting a category is refused — every page beneath it would change route at once; see Page Operations.

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

const patch: Partial<EditableCategoryMeta> = { displayName: "Reports", order: 2 };

Next Steps

  • Catalog - Discover the block types and DataTypes you can emit