@antelopejs/interface-dms-builder 0.3.1 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,14 @@
1
- # Addressing and Structure
1
+ ---
2
+ title: "Addressing and structure"
3
+ description: "The refs that name a page, a block and a category, and the page, block and listing shapes the builder reads back."
4
+ mode: reference
5
+ ---
2
6
 
3
7
  ## Overview
4
8
 
5
9
  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](./5.resources.md) and [Queries](./6.queries.md) define their own refs.
6
10
 
7
- 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](./4.page-operations.md).
11
+ This page also describes the shapes the builder reads back. Those are the page metadata it can read and patch, the block tree it resolves from source, and the summaries the listing operations return. [Page operations](./4.page-operations.md) documents the operations that produce and take these shapes.
8
12
 
9
13
  ```typescript
10
14
  import type {
@@ -18,9 +22,9 @@ const block: BlockPath = "/dashboard#kpis/row/revenue";
18
22
  const category: CategoryRef = "pages.reports";
19
23
  ```
20
24
 
21
- ## Address a Page
25
+ ## Address a page
22
26
 
23
- `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.
27
+ `PageRef` is the route string of a page. The builder joins the slug of the category with the page's own `urlSlug`, which defaults to its 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.
24
28
 
25
29
  ```typescript
26
30
  import {
@@ -38,9 +42,9 @@ if (created.ok) {
38
42
  }
39
43
  ```
40
44
 
41
- ## Address a Block
45
+ ## Address a block
42
46
 
43
- `BlockPath` addresses one block inside a page: `<pageRef>#<name>` for a top-level block, then `/<childId>` for each nesting level below it.
47
+ `BlockPath` addresses one block inside a page. A top-level block is `<pageRef>#<name>`, and each nesting level below it adds `/<childId>`.
44
48
 
45
49
  | Path | What it addresses |
46
50
  | --- | --- |
@@ -48,11 +52,11 @@ if (created.ok) {
48
52
  | `/dashboard#kpis/row` | The `.child("row", …)` of that block |
49
53
  | `/dashboard#kpis/row/revenue` | The `.child("revenue", …)` of `row` |
50
54
 
51
- 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.
55
+ The first segment after `#` is the static class member that declares the block. Every further segment is the id passed to `.child()`. `AddBlock` returns the path of the block it added.
52
56
 
53
- ## Address a Category
57
+ ## Address a category
54
58
 
55
- `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`.
59
+ `CategoryRef` is the stable id of a category. The three roots are `pages`, `modules` and `settings`. The ref of a category under a parent joins the parent ref and the category id with a dot, so a `reports` category under `pages` is `pages.reports`. The root category of a module is `modules.<moduleId>`.
56
60
 
57
61
  ```typescript
58
62
  import { CreateCategory } from "@antelopejs/interface-dms-builder";
@@ -65,27 +69,27 @@ const category = await CreateCategory({
65
69
  // category.data.ref === "pages.reports"
66
70
  ```
67
71
 
68
- ## Read a Page's Metadata
72
+ ## Read a page's metadata
69
73
 
70
- `PageMeta` is what the builder knows about a page. It comes back inside `PageStructure`, which `GetPageStructure` returns.
74
+ `PageMeta` holds what the builder knows about a page. It comes back inside the `PageStructure` that `GetPageStructure` returns.
71
75
 
72
76
  | Field | Type | Description |
73
77
  | --- | --- | --- |
74
78
  | `ref` | `PageRef` | The page's route string. |
75
79
  | `id` | `string` | The page id, the first argument of its `PageController`. |
76
80
  | `displayName` | `string` | The label shown in the menu. |
77
- | `icon` | `string` | Icon name, when the page declares one. |
81
+ | `icon` | `string` | The icon name, when the page declares one. |
78
82
  | `category` | `CategoryRef` | The category the page belongs to. |
79
83
  | `order` | `number` | Sort order within the category. |
80
84
  | `description` | `string` | The page's description. |
81
85
  | `hidden` | `boolean` | Whether the page is hidden from the menu. |
82
86
  | `permission` | `PagePermission` | The permission guarding the page. |
83
- | `live` | `PageLive` | The page's Direct / Pause options, when it is live. |
84
- | `filepath` | `string` | The file the page is declared in, resolved by the builder's source index rather than by the runtime registry. |
87
+ | `live` | `PageLive` | The Direct and Pause options of the page, when it is live. |
88
+ | `filepath` | `string` | The file that declares the page. The builder's source index resolves it, not the runtime registry. |
85
89
 
86
- `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.
90
+ `hidden`, `permission` and `live` read back like any other field when the page declares them as literals. A `permission` built from a call or a reference, such as an `Action`, reads back as `undefined`. The builder reports only what it can also rewrite.
87
91
 
88
- `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.
92
+ `PagePermission` mirrors the DMS `MenuOptions.permission`. It is a partial permission spec with the fields `id`, `title`, `icon`, `description`, `dependencies` and `defaultGranted`. Its type is `ConfigObject`, an object of plain data, so the compiler refuses a function or a class instance. A bare action id is not accepted. The DMS types the option as `Partial<Permission> | Action`, so the builder would write a string and the typecheck gate would then refuse it.
89
93
 
90
94
  ```typescript
91
95
  import type { PagePermission } from "@antelopejs/interface-dms-builder";
@@ -96,15 +100,15 @@ const permission: PagePermission = {
96
100
  };
97
101
  ```
98
102
 
99
- 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`.
103
+ The DMS also accepts an `Action` there. An `Action` is a live object and not data, so the builder has no encoding for it. A page that declares one reads its permission back as `undefined`.
100
104
 
101
- `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.
105
+ `PageLive` mirrors the DMS `MenuOptions.live`, with the fields `maxRate`, `slowRateAfter` and `rememberKey`. It is a `ConfigObject` as well. When `live` is present, even as `{}`, the page is live. Its blocks then refetch through a Direct and Pause valve that its `LiveToggle` switches. When `live` is absent, the blocks refetch on every event. A patch that sends `live` as `null` removes it.
102
106
 
103
- ## Patch a Page's Metadata
107
+ ## Patch a page's metadata
104
108
 
105
- `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.
109
+ `EditablePageMeta` is the subset of `PageMeta` that `ConfigurePage` accepts as a patch. Its fields are `displayName`, `icon`, `category`, `order`, `description`, `hidden`, `permission` and `live`. `ref`, `id` and `filepath` are not patchable, because they follow from where the page lives.
106
110
 
107
- 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](./4.page-operations.md).
111
+ A patch of `category` moves the page and changes its `ref`. The result carries the new ref, and a `route_changed` warning names the old route. [Move a page between categories](./4.page-operations.md#move-a-page-between-categories) describes the move.
108
112
 
109
113
  ```typescript
110
114
  import type { EditablePageMeta } from "@antelopejs/interface-dms-builder";
@@ -115,24 +119,25 @@ const patch: Partial<EditablePageMeta> = {
115
119
  };
116
120
  ```
117
121
 
118
- ## Read the Block Tree
122
+ ## Read the block tree
119
123
 
120
- `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.
124
+ `BlockNode` is one block in the tree of a page. The builder resolves each static member and each `.child()` call it can parse. A block it cannot parse still appears as a node, marked not editable.
121
125
 
122
126
  | Field | Type | Description |
123
127
  | --- | --- | --- |
124
128
  | `path` | `BlockPath` | The block's address. |
125
129
  | `name` | `string` | Static key for a top-level block, `.child()` id for a nested one. |
126
130
  | `type` | `string \| null` | The factory name, or `null` when it does not resolve. |
127
- | `editable` | `boolean` | `false` marks an opaque, non-canonical block. |
131
+ | `editable` | `boolean` | Whether the builder can edit the options it understands. `false` marks an opaque block. |
128
132
  | `opaqueReason` | `string` | Why the block is opaque. Set when `editable === false`. |
129
133
  | `slot` | `string` | The slot the block sits in, when its parent declares slots. |
130
- | `meta` | `Record<string, unknown>` | Child metadata beyond `slot`, such as `{ colSpan: 2 }`. Keep it when constructing a draft from the tree. |
131
- | `config` | `Record<string, unknown>` | The block's options object. Present only when the block is editable. |
132
- | `controller` | `ResourceRef` | For a controller-leading block such as `TableView`, the resource its leading argument resolves to, when it is a known generated resource. |
134
+ | `meta` | `ConfigObject` | Child metadata beyond `slot`, as declared in the third argument of `.child()`, such as `{ colSpan: 2 }`. Nested blocks only. Keep it when you build a draft from the tree. |
135
+ | `config` | `ConfigObject` | The options of the block that are literals. Present only when the block is editable. |
136
+ | `lockedOptions` | `Record<string, string>` | The top-level options defined by an expression in code, each with the reason it is locked. A save keeps them unchanged. |
137
+ | `controller` | `ResourceRef` | For a block whose factory takes a controller first, such as `TableView`, the resource that the leading argument resolves to, when it is a known generated resource. |
133
138
  | `children` | `BlockNode[]` | Container blocks only, in `.child()` order. |
134
139
 
135
- 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](./8.results-and-errors.md).
140
+ The builder can read an opaque block but cannot rewrite it. A block behind an unresolved reference is opaque, and so is a block that a computed expression produces instead of a direct factory call. `ConfigureBlock` on it, `AddBlock` under it and `MoveBlock` onto it fail with `opaque_target`, which [Results and errors](./8.results-and-errors.md) describes.
136
141
 
137
142
  ```typescript
138
143
  import { GetPageStructure } from "@antelopejs/interface-dms-builder";
@@ -147,22 +152,22 @@ if (result.ok) {
147
152
  }
148
153
  ```
149
154
 
150
- ## Read a Page's Structure
155
+ ## Read a page's structure
151
156
 
152
157
  `PageStructure` is the whole page as the builder sees it.
153
158
 
154
159
  | Field | Type | Description |
155
160
  | --- | --- | --- |
156
- | `page` | `PageMeta` | The page's metadata. |
161
+ | `page` | `PageMeta` | The metadata of the page. |
157
162
  | `blocks` | `BlockNode[]` | The top-level blocks, each carrying its own children. |
158
- | `queries` | `QueryStructure[]` | The query routes declared on the page, found by shape. See [Queries](./6.queries.md). |
163
+ | `queries` | `QueryStructure[]` | The query routes declared on the page, found by shape. [Queries](./6.queries.md) describes them. |
159
164
  | `version` | `string` | A content hash of the page file. |
160
165
 
161
- `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](./8.results-and-errors.md).
166
+ `version` 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. [Results and errors](./8.results-and-errors.md) describes `stale`.
162
167
 
163
- ## Read the Listings
168
+ ## Read the listings
164
169
 
165
- `ListPages` and `ListCategories` return summaries rather than full structures, so you can survey a project without parsing every page.
170
+ `ListPages` and `ListCategories` return summaries instead of full structures, so a caller can survey a project without the structure of every page.
166
171
 
167
172
  `PageSummary`:
168
173
 
@@ -172,11 +177,12 @@ if (result.ok) {
172
177
  | `id` | `string` | The page id. |
173
178
  | `displayName` | `string` | The label shown in the menu. |
174
179
  | `category` | `CategoryRef` | The category the page belongs to. |
175
- | `moduleId` | `string` | The module the page comes from, for pages declared inside a module. |
180
+ | `moduleId` | `string` | The `module` option of the page, for a page that declares one. |
176
181
  | `filepath` | `string` | The file the page is declared in. |
177
182
  | `icon` | `string` | The icon the menu shows beside the page, when it declares one. |
178
183
  | `order` | `number` | Sorts the page among the others of its category, when it declares one. |
179
- | `hidden` | `boolean` | Whether the menu leaves the page out; its route still answers. |
184
+ | `hidden` | `boolean` | Whether the menu leaves the page out. Its route still answers. |
185
+ | `sourceModule` | `string` | The project module the page lives in, when it is not the project's own module. |
180
186
 
181
187
  `CategorySummary`:
182
188
 
@@ -185,6 +191,8 @@ if (result.ok) {
185
191
  | `ref` | `CategoryRef` | The category's id. |
186
192
  | `displayName` | `string` | The label shown in the menu. |
187
193
  | `parent` | `CategoryRef` | The parent category, absent for a root. |
194
+ | `icon` | `string` | The icon name, when the category declares one. |
195
+ | `order` | `number` | Its place among its siblings in the menu, lowest first, when the category declares one. |
188
196
 
189
197
  ```typescript
190
198
  import {
@@ -199,9 +207,9 @@ const [pages, categories] = await Promise.all([
199
207
  const rootPages = pages.filter((page) => page.category === "pages");
200
208
  ```
201
209
 
202
- ## Patch a Category's Metadata
210
+ ## Patch a category's metadata
203
211
 
204
- `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](./4.page-operations.md).
212
+ `EditableCategoryMeta` is what `ConfigureCategory` accepts. Its fields are `displayName`, `parent`, `icon` and `order`. `ConfigureCategory` refuses a new `parent` with `unsupported`, because every page beneath the category would change route at once. [Configure a category](./4.page-operations.md#configure-a-category) lists the refusals.
205
213
 
206
214
  ```typescript
207
215
  import type { EditableCategoryMeta } from "@antelopejs/interface-dms-builder";
@@ -209,6 +217,6 @@ import type { EditableCategoryMeta } from "@antelopejs/interface-dms-builder";
209
217
  const patch: Partial<EditableCategoryMeta> = { displayName: "Reports", order: 2 };
210
218
  ```
211
219
 
212
- ## Next Steps
220
+ ## Next steps
213
221
 
214
- - [Catalog](./3.catalog.md) - Discover the block types and DataTypes you can emit
222
+ - [Catalog](./3.catalog.md) lists the block types and DataTypes the builder can write.
package/docs/3.catalog.md CHANGED
@@ -1,12 +1,16 @@
1
- # Catalog
1
+ ---
2
+ title: "Catalog"
3
+ description: "The block types, DataTypes, reserved field names and declared data sources the builder reports, with the schema of each option."
4
+ mode: reference
5
+ ---
2
6
 
3
7
  ## Overview
4
8
 
5
- The catalog is the builder's answer to "what can I put on a page?". `GetCatalog` returns a `BlockCatalog`: every block factory the builder knows how to emit, every DataType a form field can use, and the field names a resource may not take. Each entry carries the import the emitter will add and a schema for the options the factory accepts, so you can validate a configuration before you write it.
9
+ The catalog lists what the builder can put on a page. `GetCatalog` returns a `BlockCatalog` with every block factory the builder can write, every DataType a form field can use, and the field names a resource may not take. Each entry carries the import the emitter adds and a schema for the options the factory accepts, so a caller can validate a configuration before it writes one.
6
10
 
7
- Read the catalog before `AddBlock`: the `type` you pass is a catalog key, and `AddBlock` rejects a type that is not in it.
11
+ The `type` passed to `AddBlock` is a catalog key. `AddBlock` fails with `unsupported` for a type the catalog does not list.
8
12
 
9
- ## Read the Catalog
13
+ ## Read the catalog
10
14
 
11
15
  ```typescript
12
16
  import { GetCatalog } from "@antelopejs/interface-dms-builder";
@@ -17,57 +21,76 @@ const containers = catalog.blocks.filter((block) => block.container);
17
21
  const dataTypeIds = catalog.dataTypes.map((dataType) => dataType.id);
18
22
  ```
19
23
 
20
- `GetCatalog` is a read: it returns a `BlockCatalog` directly, not an `OpResult`.
24
+ `GetCatalog` is a read. It returns a `BlockCatalog` directly, not an `OpResult`.
21
25
 
22
26
  | Field | Type | Description |
23
27
  | --- | --- | --- |
24
- | `blocks` | `BlockTypeDescriptor[]` | Every block factory the builder can emit and configure. |
28
+ | `blocks` | `BlockTypeDescriptor[]` | Every block factory the builder can write and configure. |
25
29
  | `dataTypes` | `DataTypeDescriptor[]` | Every DataType usable as a form field's `type`. |
26
30
  | `reservedFieldNames` | `string[]` | Names a resource field may not take. |
27
- | `generatedAt` | `string` | Cache key, invalidated when the module source changes. |
31
+ | `generatedAt` | `string` | The ISO time at which the builder built the cached catalog. It is also the cache key. |
28
32
 
29
- The catalog is cached. `RefreshSourceIndex` with no scope drops that cache; see [Page Operations](./4.page-operations.md).
33
+ The builder caches the catalog. `RefreshSourceIndex` without a `page` in its scope drops that cache, as [Refresh the source index](./4.page-operations.md#refresh-the-source-index) describes.
30
34
 
31
- ## Describe a Block Type
35
+ ## Describe a block type
32
36
 
33
- `BlockTypeDescriptor` is keyed on `type`, the factory's export name.
37
+ `BlockTypeDescriptor` is keyed on `type`, the export name of the factory.
34
38
 
35
39
  | Field | Type | Description |
36
40
  | --- | --- | --- |
37
- | `type` | `string` | The factory export name, e.g. `KpiCard`. This is the catalog key and the value of `AddBlockInput.type`. |
41
+ | `type` | `string` | The export name of the factory, such as `KpiCard`. It is the catalog key and the value of `AddBlockInput.type`. |
38
42
  | `import` | `ImportRef` | The import the emitter adds for the factory. |
43
+ | `componentName` | `string` | The frontend component the factory emits, such as `dms-kpi-card`. |
44
+ | `label` | `string` | The label for the palette. A consumer falls back to `type` when it is absent. |
45
+ | `icon` | `string` | The icon name for the palette. |
46
+ | `group` | `BlockGroup` | The palette section: `layout`, `content`, `data`, `visualization`, or another name a DMS declares. |
39
47
  | `container` | `boolean` | Whether the block accepts `.child(...)`. |
40
- | `slots` | `SlotDescriptor[]` | The named regions the block exposes, when it has any. |
41
- | `config` | `ConfigSchema` | A description of the factory's options object. |
42
- | `shapeSource` | `ShapeSource` | How the emit shape was determined. |
48
+ | `allowedChildren` | `string[]` | The block types accepted as children. Any type is accepted when it is absent. |
49
+ | `slots` | `SlotDescriptor[]` | The fixed named regions the block exposes, when it has any. |
50
+ | `dynamicSlots` | `DynamicSlots` | Where the block's own options name its regions, for a container such as `Tab`. |
51
+ | `config` | `ConfigSchema` | A description of the options object of the factory. |
52
+ | `defaults` | `ConfigObject` | The option values the factory applies when the caller omits them. |
53
+ | `childMeta` | `ConfigSchema` | The schema of the metadata a child carries, such as `{ colSpan }`. |
54
+ | `fixedOptions` | `ConfigObject` | The options the factory sets itself whatever the caller passes, such as the `type` of a chart. |
55
+ | `configOrigin` | `ConfigOrigin` | How the builder determined the shape of `config`. |
43
56
  | `description` | `string` | A human-readable description of the block. |
44
- | `controllerArg` | `boolean` | `true` when the factory takes a leading controller-class argument before its options object. |
45
- | `initialChildren` | `BlockInitialChild[]` | The children a new block of this type starts with, as the DMS's own helper places them in code (a `PageToolbar`'s `LiveToggle` and `PeriodSelector`, with the options of `pageToolbar()`). Each has an `id` (the child id roles name it by), a `type` (a catalog key) and its `options`. Absent for most types. |
57
+ | `controllerArg` | `boolean` | `true` when the factory takes a controller class as its first argument, before its options object. |
58
+ | `initialChildren` | `BlockInitialChild[]` | The children a new block of this type starts with, as the DMS's own helper places them in code. A `PageToolbar` starts with a `LiveToggle` and a `PeriodSelector`, with the options of `pageToolbar()`. Each child has an `id` (the child id that roles name it by), a `type` (a catalog key) and its `options`. Absent for most types. |
46
59
 
47
- Only a `container` block can hold children, so it is the check to make before passing a block's path as `AddBlockInput.parent`.
60
+ Only a `container` block can hold children. Check `container` before you pass the path of a block as `AddBlockInput.parent`.
48
61
 
49
- ## Place a Block in a Slot
62
+ ## Place a block in a slot
50
63
 
51
- A container block may declare named regions. `SlotDescriptor` describes one:
64
+ A container block can declare named regions. `SlotDescriptor` describes one fixed region.
52
65
 
53
66
  | Field | Type | Description |
54
67
  | --- | --- | --- |
55
68
  | `id` | `string` | The slot id, passed as `AddBlockInput.slot`. |
69
+ | `label` | `string` | The name of the slot for a person. |
56
70
  | `description` | `string` | What the slot is for. |
57
71
 
58
72
  ```typescript
59
73
  import { GetCatalog } from "@antelopejs/interface-dms-builder";
60
74
 
61
75
  const catalog = await GetCatalog();
62
- const descriptor = catalog.blocks.find((block) => block.type === "Tab");
76
+ const descriptor = catalog.blocks.find((block) => block.type === "Card");
63
77
  const slotIds = descriptor?.slots?.map((slot) => slot.id) ?? [];
78
+ // ["actions", "footer"]
64
79
  ```
65
80
 
66
- ## Handle a Controller-Leading Block
81
+ Some containers take their regions from their own options instead. `Tab` names one region per entry of its `items` option. Its descriptor has no `slots` and carries `dynamicSlots` instead.
67
82
 
68
- Some factories take a controller class before their options — `TableView(controller, options)` is the common case. Those descriptors carry `controllerArg: true`, and their `config` describes the *second* argument, the options object.
83
+ | Field | Type | Description |
84
+ | --- | --- | --- |
85
+ | `optionPath` | `string` | The option of the block config that lists the regions, such as `items`. |
86
+ | `idKey` | `string` | The key of each entry that holds the slot id, such as `slot`. |
87
+ | `labelKey` | `string` | The key of each entry that holds its label, such as `label`. |
88
+
89
+ ## Handle a block that takes a controller
90
+
91
+ Some factories take a controller class before their options, as in `TableView(controller, options)`. Those descriptors carry `controllerArg: true`, and their `config` describes the second argument, the options object.
69
92
 
70
- A block type with `controllerArg: true` requires `AddBlockInput.controller`, naming the resource whose DataAPI class becomes the leading argument; passing `controller` for any other block type is rejected with `invalid_config`. Both rules are covered in [Page Operations](./4.page-operations.md).
93
+ A block type with `controllerArg: true` requires `AddBlockInput.controller`, which names the resource whose DataAPI class becomes the first argument. `AddBlock` fails with `invalid_config` when that `controller` is missing, and when a `controller` is passed for any other block type. [Add a block](./4.page-operations.md#add-a-block) covers both rules.
71
94
 
72
95
  ```typescript
73
96
  import { GetCatalog } from "@antelopejs/interface-dms-builder";
@@ -79,17 +102,26 @@ if (tableView?.controllerArg) {
79
102
  }
80
103
  ```
81
104
 
82
- ## Read a Config Schema
105
+ ## Read a config schema
83
106
 
84
- `ConfigSchema` is a `Record<string, unknown>` holding a JSON-Schema-shaped description of a block's or DataType's options, generated from its TypeScript type. Keys are option names; each value describes that option — `type`, `enum` for a literal union, `properties` for a nested object, `items` for an array, `oneOf` for a union of object shapes.
107
+ `ConfigSchema` is a `Record<string, OptionSchema>`. It describes the options of a block or a DataType in a shape close to JSON Schema. The keys are option names. Each `OptionSchema` describes one option with these fields:
85
108
 
86
- On top of the standard keys, the schema carries DMS extensions in the `x-` namespace. The one you act on is `x-dataType`:
109
+ - `type` is one of `string`, `number`, `boolean`, `object`, `array`, `record`, `union` or `unknown`.
110
+ - `optional`, `nullable`, `description` and `default` describe the value.
111
+ - `enum` lists the values of a literal union.
112
+ - `properties` describes a nested object, `items` the element of an array, and `values` and `keys` a record.
113
+ - `oneOf` lists the branches of a union, and `discriminator` names the property that tags each branch.
114
+ - `prefixItems` lists the element shapes of a tuple, and `allOf` the shapes of an intersection.
115
+ - `truncated` is `true` when the value has more structure than the catalog describes.
116
+ - `ui` tells a builder UI how to present the option, with fields such as `label`, `widget`, `group` and `advanced`.
117
+
118
+ On top of these keys, the schema carries DMS extensions in the `x-` namespace.
87
119
 
88
120
  | Key | Meaning |
89
121
  | --- | --- |
90
- | `x-dataType: true` | The value is a DataType instance (`new <DataType>(...)`), such as a Form field's `type`. Pass a `DataTypeValue`, described in [Value Encodings](./7.values.md). |
91
-
92
- An option whose value holds a nested block is marked the same way, with its own `x-` key. That is rare: most nesting goes through `.child`, which you express with `AddBlockInput.parent` rather than through config.
122
+ | `x-dataType: true` | The value is a DataType instance (`new <DataType>(...)`), such as the `type` of a Form field. Pass a `DataTypeValue`, described in [Value encodings](./7.values.md). |
123
+ | `x-component: true` | The value holds a nested block. Most nesting goes through `.child()`, which `AddBlockInput.parent` expresses instead of config. |
124
+ | `x-controller: true` | The option receives the DataAPI class of a table, such as the `dataApiController` of a relation. Its value is a `$ref` to a resource. |
93
125
 
94
126
  ```typescript
95
127
  import { GetCatalog } from "@antelopejs/interface-dms-builder";
@@ -99,39 +131,39 @@ const form = catalog.blocks.find((block) => block.type === "Form");
99
131
  const fieldsOption = form?.config.fields; // schema for the `fields` option
100
132
  ```
101
133
 
102
- ## Resolve an Import
134
+ ## Resolve an import
103
135
 
104
- `ImportRef` is the import the emitter adds when it writes a factory call, a DataType instantiation or a class reference.
136
+ `ImportRef` is the import the emitter adds when it writes a factory call, a DataType instance or a class reference.
105
137
 
106
138
  | Field | Type | Description |
107
139
  | --- | --- | --- |
108
- | `name` | `string` | The imported symbol, e.g. `KpiCard` or `DefaultDataTypes.StringType`. |
140
+ | `name` | `string` | The imported symbol, such as `KpiCard` or `DefaultDataTypes.StringType`. |
109
141
  | `module` | `string` | A package specifier, fixed and independent of the emitting file. |
110
- | `targetFile` | `string` | An absolute path, resolved to a specifier relative to the file being written — used for a reference to a local class such as a generated resource. |
142
+ | `targetFile` | `string` | An absolute path that the emitter turns into a specifier relative to the file it writes. The emitter uses it for a reference to a local class, such as a generated resource. |
111
143
 
112
- A descriptor carries one or the other: `module` for a symbol that comes from a package, `targetFile` for one that lives in the project's own source.
144
+ An `ImportRef` carries one of the two. `module` names a symbol from a package, and `targetFile` points at a symbol in the project's own source.
113
145
 
114
- ## Know Where a Shape Came From
146
+ ## Know where a shape came from
115
147
 
116
- `ShapeSource` is `"inferred" | "annotated"`, and a `BlockTypeDescriptor` reports which applies to its `config`:
148
+ `ConfigOrigin` is `"inferred" | "annotated"`. A `BlockTypeDescriptor` reports which one applies to its `config`.
117
149
 
118
- - **`inferred`** — the shape was read off the factory's TypeScript signature. It is as good as the types are: a well-typed options interface yields a precise schema, while a wide or generic option yields a loose one.
119
- - **`annotated`** — the shape was declared for the builder rather than derived from the signature.
150
+ - `annotated` means that the DMS declared the block type for the builder. Its schema carries labels, defaults and widgets. A declared block type replaces the inferred one of the same name.
151
+ - `inferred` means that the builder read the shape off the TypeScript signature of the factory, for a factory the DMS has not declared. A precise options interface gives a precise schema, and a wide or generic option gives a loose one.
120
152
 
121
- Use `shapeSource` when deciding how much to trust `config`. An empty or shallow `config` on an `inferred` descriptor means the type could not be described further, not that the factory takes no options.
153
+ An empty or shallow `config` on an `inferred` descriptor means that the builder could not describe the type further. It does not mean that the factory takes no options.
122
154
 
123
- ## Choose a DataType
155
+ ## Choose a data type
124
156
 
125
- `DataTypeDescriptor` describes a DataType a form field's `type` (or a table column's `type`) can use.
157
+ `DataTypeDescriptor` describes a DataType that the `type` of a form field or of a table column can use.
126
158
 
127
159
  | Field | Type | Description |
128
160
  | --- | --- | --- |
129
- | `id` | `string` | The registered id, e.g. `string`, `number`, `select`. |
161
+ | `id` | `string` | The registered id, such as `string`, `number` or `select`. |
130
162
  | `import` | `ImportRef` | The import the emitter adds for the DataType class. |
131
- | `config` | `ConfigSchema` | A description of the DataType's options. |
163
+ | `config` | `ConfigSchema` | A description of the options of the DataType. |
132
164
  | `description` | `string` | A human-readable description. |
133
165
 
134
- The `id` is what you pass as `$dataType` when writing a value; see [Value Encodings](./7.values.md). A `$dataType` the catalog does not list is rejected with `invalid_config`.
166
+ Pass the `id` as `$dataType` to write a DataType value, as [Value encodings](./7.values.md) describes. A `$dataType` that the catalog does not list fails with `invalid_config`.
135
167
 
136
168
  ```typescript
137
169
  import {
@@ -158,9 +190,9 @@ await AddBlock({
158
190
  });
159
191
  ```
160
192
 
161
- ## Avoid a Reserved Field Name
193
+ ## Avoid a reserved field name
162
194
 
163
- `reservedFieldNames` lists the names a resource field may not take: they collide with a generated DataController route or a Model member, and `CreateResource` or `AddField` rejects them with `invalid_config`. Reading them from the catalog saves you carrying your own copy of the list.
195
+ `reservedFieldNames` lists the names a resource field may not take. They collide with a route of the generated DataController or a member of the model, and `CreateResource` and `AddField` fail with `invalid_config` on them. The list is `_id`, `model`, `get`, `list`, `select`, `count`, `new`, `edit`, `delete`, `archive`, `restore`, `exportStart`, `exportStatus` and `exportDownload`. Read it from the catalog instead of keeping a copy.
164
196
 
165
197
  ```typescript
166
198
  import { GetCatalog } from "@antelopejs/interface-dms-builder";
@@ -170,8 +202,32 @@ const reserved = new Set(catalog.reservedFieldNames);
170
202
  const fieldName = reserved.has("status") ? "state" : "status";
171
203
  ```
172
204
 
173
- Resource fields are covered in [Resources](./5.resources.md).
205
+ [Resources](./5.resources.md) covers resource fields.
206
+
207
+ ## List the declared data sources
208
+
209
+ `ListDataSources(response?)` returns the routes that developers declared beside their own code as something a block may read. It is separate from the catalog, because these sources come and go as modules load. With `response`, it returns only the sources whose `responseKind` equals it. It returns a `DataSourceDescriptor[]` directly, not an `OpResult`.
210
+
211
+ ```typescript
212
+ import { ListDataSources } from "@antelopejs/interface-dms-builder";
213
+
214
+ const sources = await ListDataSources();
215
+ const paths = sources.map((source) => source.path);
216
+ ```
217
+
218
+ | Field | Type | Description |
219
+ | --- | --- | --- |
220
+ | `id` | `string` | The id of the source. |
221
+ | `title` | `string` | The title of the source. |
222
+ | `description` | `string` | A description of the source. |
223
+ | `responseKind` | `string` | The shape the source answers with, matched against what a block can read. |
224
+ | `path` | `string` | The path a block fetches, as declared. |
225
+ | `method` | `string` | The HTTP method, when the source declares one. |
226
+ | `params` | `ConfigSchema` | The parameters the source takes, described like block options. |
227
+ | `period` | `{ from: string; to: string }` | The query parameters that carry a period, when the source takes one. |
228
+
229
+ The builder never reads or rewrites the code behind a declared source. It knows only what the declaration says.
174
230
 
175
- ## Next Steps
231
+ ## Next steps
176
232
 
177
- - [Page Operations](./4.page-operations.md) - Create pages and categories, and edit a page's block tree
233
+ - [Page operations](./4.page-operations.md) creates pages and categories, and edits the block tree of a page.