@dforge-core/dforge-mcp 0.1.0-rc.11 → 0.1.0-rc.13
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.
- package/CHANGELOG.md +132 -0
- package/README.md +75 -21
- package/dist/server.js +2405 -272
- package/docs/creating-modules.md +7 -3
- package/package.json +11 -6
- package/resources/docs/conventions.md +20 -14
- package/resources/schemas/entity.schema.json +8 -1
- package/resources/schemas/reports.schema.json +4 -0
- package/skills/dforge-mcp-author/SKILL.md +227 -95
- package/skills/dforge-mcp-author/examples/simple-todo/README.md +38 -0
- package/skills/dforge-mcp-author/examples/simple-todo/entities/todo_item.json +83 -0
- package/skills/dforge-mcp-author/examples/simple-todo/entities/todo_list.json +43 -0
- package/skills/dforge-mcp-author/examples/simple-todo/logic/actions/mark_done.dsl +6 -0
- package/skills/dforge-mcp-author/examples/simple-todo/manifest.json +32 -0
- package/skills/dforge-mcp-author/examples/simple-todo/security/roles.json +10 -0
- package/skills/dforge-mcp-author/examples/simple-todo/seed-data/01-lists.json +17 -0
- package/skills/dforge-mcp-author/examples/simple-todo/ui/actions.json +11 -0
- package/skills/dforge-mcp-author/examples/simple-todo/ui/data_views.json +35 -0
- package/skills/dforge-mcp-author/examples/simple-todo/ui/menus.json +28 -0
- package/skills/dforge-mcp-author/references/action-dsl.md +397 -0
- package/skills/dforge-mcp-author/references/column-types.md +168 -0
- package/skills/dforge-mcp-author/references/conventions.md +177 -0
- package/skills/dforge-mcp-author/references/data-migration.md +270 -0
- package/skills/dforge-mcp-author/references/data-views.md +192 -0
- package/skills/dforge-mcp-author/references/excel-import.md +61 -0
- package/skills/dforge-mcp-author/references/field-types.md +144 -0
- package/skills/dforge-mcp-author/references/filters.md +326 -0
- package/skills/dforge-mcp-author/references/flags.md +73 -0
- package/skills/dforge-mcp-author/references/formulas.md +206 -0
- package/skills/dforge-mcp-author/references/jobs.md +149 -0
- package/skills/dforge-mcp-author/references/manifest.md +123 -0
- package/skills/dforge-mcp-author/references/menus.md +164 -0
- package/skills/dforge-mcp-author/references/number-sequences.md +117 -0
- package/skills/dforge-mcp-author/references/print-templates.md +159 -0
- package/skills/dforge-mcp-author/references/queries.md +312 -0
- package/skills/dforge-mcp-author/references/reports.md +398 -0
- package/skills/dforge-mcp-author/references/schema-import.md +331 -0
- package/skills/dforge-mcp-author/references/security.md +244 -0
- package/skills/dforge-mcp-author/references/settings.md +120 -0
- package/skills/dforge-mcp-author/references/traits.md +153 -0
- package/skills/dforge-mcp-author/references/translations.md +158 -0
- package/skills/dforge-mcp-author/references/validation-checklist.md +182 -0
- package/skills/dforge-mcp-author/scripts/xlsx_to_model.py +198 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Data Views Reference
|
|
2
|
+
|
|
3
|
+
Data views define how users see and interact with entity data. One entity can have many data views (grid, kanban, gallery, tree-grid, list, card).
|
|
4
|
+
|
|
5
|
+
Lives in: `ui/data_views.json`
|
|
6
|
+
|
|
7
|
+
## Structure
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"contact_list": {
|
|
12
|
+
"label": "All Contacts",
|
|
13
|
+
"description": "Primary list of contacts",
|
|
14
|
+
"viewType": "grid",
|
|
15
|
+
"icon": "bi-people",
|
|
16
|
+
"dataSources": [{
|
|
17
|
+
"entityCode": "contact",
|
|
18
|
+
"label": "Contacts",
|
|
19
|
+
"columns": [
|
|
20
|
+
{ "column_cd": "first_name", "width": 150 },
|
|
21
|
+
{ "column_cd": "last_name", "width": 150 },
|
|
22
|
+
{ "column_cd": "email", "width": 220 },
|
|
23
|
+
{ "column_cd": "phone", "width": 130 },
|
|
24
|
+
{ "column_cd": "account", "width": 200 }
|
|
25
|
+
],
|
|
26
|
+
"filter": null
|
|
27
|
+
}],
|
|
28
|
+
"order": ["last_name"]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Critical rule — `dataSources` array
|
|
34
|
+
|
|
35
|
+
**Always** put `entityCode`, `columns`, and per-source `filter` inside a `dataSources` array. Never at the root. The view-level `order` and `filter` sit at the view-def root, alongside `viewType`.
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
// WRONG — will fail validation
|
|
39
|
+
{
|
|
40
|
+
"contact_list": {
|
|
41
|
+
"label": "Contacts",
|
|
42
|
+
"viewType": "grid",
|
|
43
|
+
"entityCode": "contact", // WRONG — should be inside dataSources
|
|
44
|
+
"columns": [ /* ... */ ] // WRONG — should be inside dataSources
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// RIGHT
|
|
49
|
+
{
|
|
50
|
+
"contact_list": {
|
|
51
|
+
"label": "Contacts",
|
|
52
|
+
"viewType": "grid",
|
|
53
|
+
"dataSources": [{
|
|
54
|
+
"entityCode": "contact",
|
|
55
|
+
"columns": [ /* ... */ ]
|
|
56
|
+
}]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## View types
|
|
62
|
+
|
|
63
|
+
| `viewType` | Description | `viewConfig` | When to use |
|
|
64
|
+
|---|---|---|---|
|
|
65
|
+
| `grid` | Spreadsheet-style table with sortable columns | — | Default for most entities; bulk data |
|
|
66
|
+
| `list` | Compact list view | — | Mobile-friendly, card-sized items |
|
|
67
|
+
| `kanban` | Columns grouped by a status field | `groupByField` | Workflow entities with stages (deals, tickets) |
|
|
68
|
+
| `gallery` | Image-forward card grid | — | Image-heavy entities (products, real estate) |
|
|
69
|
+
| `tree-grid` | Hierarchical grid with expand/collapse | — | Tree structures (folders, categories, org charts) |
|
|
70
|
+
| `calendar` | Calendar display of date-based records | `dateField`, `titleField` | Schedules, due dates, events |
|
|
71
|
+
| `card` | Single-record detail view | — | Record detail pages (implicit — every entity has one) |
|
|
72
|
+
|
|
73
|
+
## View config (`viewConfig`)
|
|
74
|
+
|
|
75
|
+
Some view types need additional configuration via the `viewConfig` property:
|
|
76
|
+
|
|
77
|
+
### Kanban
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"opportunities_kanban": {
|
|
82
|
+
"viewType": "kanban",
|
|
83
|
+
"label": "Sales Pipeline",
|
|
84
|
+
"dataSources": [{
|
|
85
|
+
"entityCode": "opportunity",
|
|
86
|
+
"columns": ["opportunity_name", "account", "total_amount", "owner_id"]
|
|
87
|
+
}],
|
|
88
|
+
"viewConfig": {
|
|
89
|
+
"groupByField": "stage"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`groupByField` — the dropdown/status column to group cards by. Each distinct value becomes a kanban column.
|
|
96
|
+
|
|
97
|
+
### Calendar
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"invoices_calendar": {
|
|
102
|
+
"viewType": "calendar",
|
|
103
|
+
"label": "Invoice Calendar",
|
|
104
|
+
"dataSources": [{
|
|
105
|
+
"entityCode": "invoice",
|
|
106
|
+
"columns": ["invoice_number", "customer", "total_amount", "due_date"]
|
|
107
|
+
}],
|
|
108
|
+
"viewConfig": {
|
|
109
|
+
"dateField": "due_date",
|
|
110
|
+
"titleField": "invoice_number"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
- `dateField` — the date column that determines where records appear on the calendar
|
|
117
|
+
- `titleField` — the column whose value is shown as the calendar event title
|
|
118
|
+
|
|
119
|
+
## Columns
|
|
120
|
+
|
|
121
|
+
Each column is either a simple string or an object:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
"columns": [
|
|
125
|
+
"first_name", // just column code, default width
|
|
126
|
+
{ "column_cd": "email", "width": 220 }, // with width override
|
|
127
|
+
{ "column_cd": "account", "width": 200, "visible": true }
|
|
128
|
+
]
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Filters
|
|
132
|
+
|
|
133
|
+
Filters use dForge's canonical JSON filter format — see [filters.md](filters.md) for the full grammar. Keys are `c` (column), `o` (operator), `v` (value) for conditions, and `g` (group operator), `i` (items) for groups.
|
|
134
|
+
|
|
135
|
+
Single condition:
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
"filter": { "c": "status", "o": "=", "v": "active" }
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Group:
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
"filter": {
|
|
145
|
+
"g": "and",
|
|
146
|
+
"i": [
|
|
147
|
+
{ "c": "status", "o": "=", "v": "active" },
|
|
148
|
+
{ "c": "created_date", "o": ">", "v": "2026-01-01" }
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Do **not** use `op`/`args`/`column`/`value` — that format is rejected.
|
|
154
|
+
|
|
155
|
+
## Sort (`order`)
|
|
156
|
+
|
|
157
|
+
Sort lives at the **view-def root** (not inside `dataSources[]`) under the key **`order`** — a `string[]` of column codes. Direction is encoded in the string itself:
|
|
158
|
+
|
|
159
|
+
- Bare column code → **ascending** (the default; no prefix needed)
|
|
160
|
+
- Leading `-` → **descending**
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
"order": ["last_name", "first_name"] // both ascending
|
|
164
|
+
"order": ["-created_date"] // descending (audit trait provides created_date)
|
|
165
|
+
"order": ["-created_date", "last_name"] // primary desc, then asc tiebreak
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The array order is the sort precedence: the first entry is the primary sort key, subsequent entries are tiebreakers.
|
|
169
|
+
|
|
170
|
+
This matches the shape the runtime persists and `data.get` accepts. **Do not** use `"sort"`, `[{ column_cd, direction }]`, or `[{ c, d }]` here — those shapes belong to `query.run` and `report.run` (see [queries.md](queries.md)), not `data_views.json`.
|
|
171
|
+
|
|
172
|
+
## Multi-source views
|
|
173
|
+
|
|
174
|
+
A view can show data from multiple entities (e.g. a dashboard-style view mixing contacts and activities). Each entry in `dataSources` is independent with its own columns/filter.
|
|
175
|
+
|
|
176
|
+
```json
|
|
177
|
+
"dataSources": [
|
|
178
|
+
{ "entityCode": "contact", "columns": [ /* ... */ ] },
|
|
179
|
+
{ "entityCode": "activity", "columns": [ /* ... */ ] }
|
|
180
|
+
]
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Most views only have one source. Order is view-level and applies to the primary (level 0) source.
|
|
184
|
+
|
|
185
|
+
## Common mistakes
|
|
186
|
+
|
|
187
|
+
- Putting `entityCode` or `columns` at the root — **wrong**. They go inside `dataSources[]`.
|
|
188
|
+
- Using `viewCode` or `view_cd` — **wrong**. The code is the dictionary key.
|
|
189
|
+
- Using `"sort"` for data view ordering — **wrong**. The field is `"order"` and it lives at view-def root (not inside `dataSources[]`).
|
|
190
|
+
- Object-array order like `[{ column_cd: "...", direction: "asc" }]` — **wrong shape for data views**. Use `string[]` with leading `-` for descending.
|
|
191
|
+
- Forgetting `viewType` — **required**, defaults don't apply.
|
|
192
|
+
- Inventing view types like `"spreadsheet"` or `"table"` — **wrong**. Use `grid`.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Importing a data model from a spreadsheet (.xlsx / .csv)
|
|
2
|
+
|
|
3
|
+
When the user gives you a spreadsheet to turn into a module, you can't read a
|
|
4
|
+
binary `.xlsx` directly — decode it first, then reason over the result.
|
|
5
|
+
|
|
6
|
+
## Flow
|
|
7
|
+
|
|
8
|
+
1. **Extract the sheets to a JSON model.** Load the bundled extractor resource
|
|
9
|
+
`dforge://script/xlsx-to-model`, write it to a temp file, and run it:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
python3 /tmp/xlsx_to_model.py "<path/to/file.xlsx>"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
It needs only Python 3 (pure standard library — no `pip install`). It prints
|
|
16
|
+
`{"sheets":[{"name":..,"headers":[..],"rows":[[..],..]}]}`. If it prints
|
|
17
|
+
`{"error":..}` (e.g. Python missing), fall back: ask the user to export each
|
|
18
|
+
sheet as **CSV** (CSV is plain text — read it directly).
|
|
19
|
+
|
|
20
|
+
2. **Turn the model into a table-spec.** For each sheet:
|
|
21
|
+
- `name` = the sheet name, snake_cased (`"Order Lines"` → `order_lines`).
|
|
22
|
+
- One **column** per header: `name` = header snake_cased; `sampleValues` =
|
|
23
|
+
that column's values from `rows` (a few are enough). Don't set `fieldTypeCd`
|
|
24
|
+
unless you're sure — let the import infer it. Add a `sqlType` hint only when
|
|
25
|
+
the values make the type obvious (all integers → `int`, decimals → `numeric`,
|
|
26
|
+
`YYYY-MM-DD` strings → `date`; remember xlsx **dates arrive as numbers**, so
|
|
27
|
+
lean on the header name, e.g. `*_date`, to spot them).
|
|
28
|
+
- **References (FKs):** when a column looks like a foreign key — header
|
|
29
|
+
`<thing>_id` (or `<thing> id`) where `<thing>` matches another sheet — put it
|
|
30
|
+
in `references: [{ column, toTable }]` instead of as a plain column.
|
|
31
|
+
- Skip an `id` / primary-key column — the `identity` trait provides `{entity}_id`.
|
|
32
|
+
|
|
33
|
+
3. **Show the proposed entity inventory for sign-off** (same gate as any Phase 1
|
|
34
|
+
scaffold), then call **`dforge_module_import`**:
|
|
35
|
+
- existing module → `{ moduleDir, tables }`
|
|
36
|
+
- new module → add `module: { code, displayName }` (greenfield).
|
|
37
|
+
|
|
38
|
+
4. **Run `dforge_module_validate`** and refine the generated default grids to
|
|
39
|
+
surface the imported columns.
|
|
40
|
+
|
|
41
|
+
## With data or empty — both work
|
|
42
|
+
|
|
43
|
+
A sheet may be **populated** (headers + rows) or **structure-only** (headers, no
|
|
44
|
+
data rows). Both produce a valid entity:
|
|
45
|
+
|
|
46
|
+
- **Populated** → use the `sampleValues` for type inference (numbers, dates,
|
|
47
|
+
dropdowns). Best results.
|
|
48
|
+
- **Empty (headers only)** → the extractor returns `"rows": []`. You still get
|
|
49
|
+
one column per header, but with no samples the import defaults most columns to
|
|
50
|
+
`text` — so lean on the **header name** (`email`, `phone`, `*_date`, `*_id` →
|
|
51
|
+
FK) and add `sqlType` hints where the user can tell you the type. Consider
|
|
52
|
+
confirming the inferred types with the user before importing.
|
|
53
|
+
|
|
54
|
+
## Notes
|
|
55
|
+
|
|
56
|
+
- One worksheet (or one Excel table object) = one entity. Ignore obviously
|
|
57
|
+
non-tabular sheets (dashboards, notes).
|
|
58
|
+
- The extractor returns the first non-empty row as `headers`; if a sheet has
|
|
59
|
+
title rows above the real header, tell the user or adjust the spec by hand.
|
|
60
|
+
- Type inference + the FK+Reference pattern are handled by `dforge_module_import`
|
|
61
|
+
against the `@dforge-core/metadata` registry — you only produce the table-spec.
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Field Types Reference
|
|
2
|
+
|
|
3
|
+
The canonical list of field types supported by dForge. **Do not invent new values — the set is fixed** and validated by the platform on module install.
|
|
4
|
+
|
|
5
|
+
Source of truth: `server/database/system-modules/metadata/seed-data/field_types.json` in the dForge repo.
|
|
6
|
+
|
|
7
|
+
> **You usually don't set `dbDatatype`.** For a plain data column, omit it — the field tools derive it from `fieldTypeCd` (the "Common `dbDatatype`" column below): `currency` → `numeric(18,2)`, `text` → `varchar`, `checkbox` → `bool`, etc. An explicit value is never overridden, so only set `dbDatatype` when you need to:
|
|
8
|
+
> - **a hidden FK column** — it has no `fieldTypeCd`, so derivation can't fire; set `dbDatatype: "cuid"` to match the target entity's `identity` PK (see `column-types.md`);
|
|
9
|
+
> - **override the size/precision** — e.g. `varchar(100)` via `maxLen`, or a specific numeric scale.
|
|
10
|
+
>
|
|
11
|
+
> Reference (`columnType: "R"`) and formula (`columnType: "F"`) columns never get a `dbDatatype` at all.
|
|
12
|
+
|
|
13
|
+
## String-backed
|
|
14
|
+
|
|
15
|
+
| `fieldTypeCd` | `baseDatatypeCd` | Description | Common `dbDatatype` | Params |
|
|
16
|
+
|---|---|---|---|---|
|
|
17
|
+
| `text` | `string` | Single-line text | `varchar` (with `maxLen`) | `maxLen` |
|
|
18
|
+
| `email` | `string` | Email address. Client-side format validation. | `varchar` 250 | — |
|
|
19
|
+
| `phone` | `string` | Phone/telephone. | `varchar` 50 | — |
|
|
20
|
+
| `url` | `string` | Web URL. | `varchar` 500 | — |
|
|
21
|
+
| `textarea` | `string` | Multi-line plain text. | `text` | `defaultLines`, `maxLines` |
|
|
22
|
+
| `richtext` | `string` | Rich text editor (HTML). | `text` | — |
|
|
23
|
+
| `code` | `string` | Code editor with syntax highlighting. | `text` | `language` |
|
|
24
|
+
| `dropdown` | `string` | Fixed list of options. | `varchar` | `options: ["a","b",…]` or `[{value,label,icon,color}]` |
|
|
25
|
+
| `flags` | `string` | Multiple checkboxes with letter flags. | `varchar` | `optionSets`, `style: "buttons"` |
|
|
26
|
+
| `tags` | `string` | Free-form tag list. | `varchar` or `text` | — |
|
|
27
|
+
| `color` | `string` | Color picker. | `varchar(20)` | — |
|
|
28
|
+
| `hidden` | `string` | Internal, never shown in UI. | `varchar` | — |
|
|
29
|
+
|
|
30
|
+
## Number-backed
|
|
31
|
+
|
|
32
|
+
| `fieldTypeCd` | `baseDatatypeCd` | Description | Common `dbDatatype` | Params |
|
|
33
|
+
|---|---|---|---|---|
|
|
34
|
+
| `number` | `number` | Numeric value. | `int`, `bigint`, `numeric` | `min`, `max`, `scale` |
|
|
35
|
+
| `currency` | `number` | Monetary value. Precision 2. | `numeric(18,2)` | `currency: "USD"`, `min`, `max` |
|
|
36
|
+
| `percent` | `number` | Percentage 0–100. Precision 2. | `numeric(5,2)` | `min`, `max` (default 0–100) |
|
|
37
|
+
|
|
38
|
+
## Boolean-backed
|
|
39
|
+
|
|
40
|
+
| `fieldTypeCd` | `baseDatatypeCd` | Description | Common `dbDatatype` | Params |
|
|
41
|
+
|---|---|---|---|---|
|
|
42
|
+
| `checkbox` | `bool` | Boolean checkbox. | `bool` | — |
|
|
43
|
+
|
|
44
|
+
> **`checkbox` is the only valid `fieldTypeCd` for boolean fields.** Do not use `bool`, `boolean`, or `toggle` as `fieldTypeCd` — those are not valid field type codes. (`bool` IS the correct `dbDatatype` for this field, but `checkbox` is the only correct `fieldTypeCd`.)
|
|
45
|
+
|
|
46
|
+
## Date/time-backed
|
|
47
|
+
|
|
48
|
+
| `fieldTypeCd` | `baseDatatypeCd` | Description | Common `dbDatatype` | Params |
|
|
49
|
+
|---|---|---|---|---|
|
|
50
|
+
| `date` | `date` | Calendar date only. | `date` | `min`, `max` (ISO strings or `TODAY()`) |
|
|
51
|
+
| `datetime` | `timestamp` | Date + time with timezone. | `timestamptz` | `min`, `max` |
|
|
52
|
+
| `time` | `time` | Time of day. | `time` | — |
|
|
53
|
+
|
|
54
|
+
## Binary / file
|
|
55
|
+
|
|
56
|
+
| `fieldTypeCd` | `baseDatatypeCd` | Description | Params |
|
|
57
|
+
|---|---|---|---|
|
|
58
|
+
| `file` | `binary` | Arbitrary file upload. | `accept`, `maxSize` |
|
|
59
|
+
| `image` | `binary` | Image upload with preview. | `maxSize`, `dimensions` |
|
|
60
|
+
|
|
61
|
+
## Reference / lookup / set
|
|
62
|
+
|
|
63
|
+
| `fieldTypeCd` | `baseDatatypeCd` | `columnType` | Description |
|
|
64
|
+
|---|---|---|---|
|
|
65
|
+
| `lookup` | `guid` | `R` | Reference to another entity (always paired with a hidden FK column — see SKILL.md "FK+Reference pattern") |
|
|
66
|
+
| `user` | `cuid` | `D` | User picker. Writes a user ID directly, no paired FK needed. |
|
|
67
|
+
| `grid` | `set` | `S` | Detail grid of related records (1:N backwards reference). Used with `link` declaring the relation. |
|
|
68
|
+
| `entitylink` | `json` | `D` | Polymorphic link to any entity (stores `{entity, id}` pair). |
|
|
69
|
+
|
|
70
|
+
## JSON
|
|
71
|
+
|
|
72
|
+
| `fieldTypeCd` | `baseDatatypeCd` | Description |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| `json` | `json` | JSON editor. Stored in `jsonb`. |
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Default values
|
|
79
|
+
|
|
80
|
+
There is **no** `defaultValue` (or `default`) key on an entity data column — it fails schema
|
|
81
|
+
validation (`entity.schema.json` is `additionalProperties: false`). To give a column a default:
|
|
82
|
+
|
|
83
|
+
| Need | Do this |
|
|
84
|
+
|---|---|
|
|
85
|
+
| Literal / computed default (`'draft'`, `TODAY()`) | Carry a `formula` on the column (formula context — uppercase `TODAY()`/`NOW()`), e.g. `"formula": "'draft'"` or `"formula": "TODAY()"`. |
|
|
86
|
+
| Document number (PO-2026-0001) | Declare a `numberSequence` on the entity — auto-fills on insert. |
|
|
87
|
+
| Anything set at create time | Set it in an action/trigger DSL (`execute:` uses lowercase `now()`). |
|
|
88
|
+
|
|
89
|
+
> `defaultValue` **is** valid on **module settings** (`settings.json`) — that's the only place it
|
|
90
|
+
> belongs. Don't carry the settings habit over to entity fields.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Common mistakes
|
|
95
|
+
|
|
96
|
+
> **Wrong key name:** `fieldType` is a C# navigation property on the server model — it is not a valid JSON key in entity definitions. Always use `fieldTypeCd` (the string code). Using `fieldType: { ... }` or `fieldType: "date"` causes the platform to silently ignore the field type, producing null constraint errors on save.
|
|
97
|
+
|
|
98
|
+
> **No `defaultValue` on entity fields:** `defaultValue` is a *settings* key, not a column key — on a field it fails schema validation. Set a column default with a `formula`, a `numberSequence`, or DSL logic (see "Default values" above).
|
|
99
|
+
|
|
100
|
+
### Wrong `dbDatatype` values
|
|
101
|
+
|
|
102
|
+
These are SQL type names LLMs tend to use for `dbDatatype`. **They are all wrong.** The right values come from the tables above.
|
|
103
|
+
|
|
104
|
+
| Wrong `dbDatatype` | Right `dbDatatype` | Used with `fieldTypeCd` |
|
|
105
|
+
|---|---|---|
|
|
106
|
+
| `datetime` | `timestamptz` | `datetime` |
|
|
107
|
+
| `timestamp` | `timestamptz` | `datetime` |
|
|
108
|
+
| `boolean` | `bool` | `checkbox` |
|
|
109
|
+
| `string` | `varchar` (with `maxLen`) or `text` | `text`, `textarea`, `dropdown`, … |
|
|
110
|
+
| `integer` | `int` or `bigint` | `number` |
|
|
111
|
+
| `float`, `double`, `decimal` | `numeric` | `number`, `currency`, `percent` |
|
|
112
|
+
| `number` | `int`, `bigint`, or `numeric` | `number`, `currency`, `percent` |
|
|
113
|
+
|
|
114
|
+
### Wrong `fieldTypeCd` values
|
|
115
|
+
|
|
116
|
+
These are the field type names LLMs tend to invent. **They are all wrong.**
|
|
117
|
+
|
|
118
|
+
| Wrong | Right |
|
|
119
|
+
|---|---|
|
|
120
|
+
| key `fieldType: { fieldTypeCd: "date", ... }` | key `fieldTypeCd: "date"` (plain string) |
|
|
121
|
+
| key `fieldType: "date"` | key `fieldTypeCd: "date"` |
|
|
122
|
+
| `bool`, `boolean` | `checkbox` |
|
|
123
|
+
| `integer` | `number` |
|
|
124
|
+
| `float` | `number` |
|
|
125
|
+
| `decimal` | `number` with `scale` param |
|
|
126
|
+
| `datePicker` | `date` |
|
|
127
|
+
| `timestamp` | `datetime` |
|
|
128
|
+
| `money` | `currency` |
|
|
129
|
+
| `select`, `enum` | `dropdown` |
|
|
130
|
+
| `multiselect` | `flags` or `tags` |
|
|
131
|
+
| `autocomplete` | `lookup` |
|
|
132
|
+
| `reference` | `lookup` |
|
|
133
|
+
| `relation` | `lookup` or `grid` |
|
|
134
|
+
| `link` | `url` |
|
|
135
|
+
| `picture`, `photo` | `image` |
|
|
136
|
+
| `attachment` | `file` |
|
|
137
|
+
| `multiline` | `textarea` |
|
|
138
|
+
| `richText`, `markdown` | `richtext` |
|
|
139
|
+
| `userPicker` | `user` |
|
|
140
|
+
| `phoneNumber` | `phone` |
|
|
141
|
+
|
|
142
|
+
## When in doubt
|
|
143
|
+
|
|
144
|
+
If the user describes a field type that isn't in this list (e.g. "rating stars", "geo location", "signature pad"), those field types **do not currently exist**. Do not fabricate a `fieldTypeCd` value. Tell the user what's available and ask how they'd like to model it with existing types (e.g. rating as `number` with `min: 1, max: 5`, geo location as two `number` columns or a `json` column).
|