@dforge-core/dforge-mcp 0.1.7 → 0.1.8

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 CHANGED
@@ -4,6 +4,28 @@ All notable changes to `@dforge-core/dforge-mcp`. This project uses semver-ish
4
4
  `0.1.0-rc.N` pre-release tags; the published version is set at publish time via
5
5
  the release workflow, so committed `package.json` versions are placeholders.
6
6
 
7
+ ## 0.1.8
8
+
9
+ ### Added
10
+ - **`dforge_module_validate` now flags a grid-style data view over an entity
11
+ with no visible column.** Errors when a column-rendering view (grid, list,
12
+ kanban, calendar, gallery, tree-grid, master-detail, or the default) draws an
13
+ own-module entity that has no *visible scalar column* — a field whose `flags`
14
+ include `V` and whose `columnType` isn't a set (`S`). Without one the view
15
+ renders the runtime empty state *"No visible columns configured for this
16
+ entity."* This mirrors the server's install-time `DataViewVisibleColumnValidator`,
17
+ so authors catch it pre-flight instead of at pack/install. Column-agnostic view
18
+ types (`diagram`, `matrix`, `library`) are exempt; cross-module entities are
19
+ skipped; the check runs after trait expansion so a trait-contributed `V` field
20
+ counts.
21
+
22
+ ### Skill
23
+ - `dforge-mcp-author`: documented the **visible-column requirement** for
24
+ column-rendering data views. `references/data-views.md` gains a "the entity
25
+ needs a visible column" rule (visibility is entity-driven via the `V` flag, not
26
+ the view's `columns` array) plus common-mistake bullets, and
27
+ `references/validation-checklist.md` gains matching checklist/red-flag entries.
28
+
7
29
  ## 0.1.7
8
30
 
9
31
  ### Changed
package/dist/server.js CHANGED
@@ -33902,6 +33902,15 @@ var SYSTEM_ENTITY_PK = {
33902
33902
  menu_item: "menu_item_id",
33903
33903
  resource: "resource_id"
33904
33904
  };
33905
+ var COLUMN_AGNOSTIC_VIEW_TYPES = /* @__PURE__ */ new Set(["diagram", "matrix", "library"]);
33906
+ function hasVisibleScalarColumn(fields) {
33907
+ for (const f of Object.values(fields)) {
33908
+ if (!f || typeof f !== "object") continue;
33909
+ const flags = typeof f.flags === "string" ? f.flags : "";
33910
+ if (flags.includes("V") && f.columnType !== "S") return true;
33911
+ }
33912
+ return false;
33913
+ }
33905
33914
  function resolveTranslationFile(translationsDir, locale) {
33906
33915
  const exact = path10.join(translationsDir, `${locale}.json`);
33907
33916
  if (fs8.existsSync(exact)) return exact;
@@ -33933,6 +33942,7 @@ function moduleValidate(args) {
33933
33942
  const entityMap = manifest.entities ?? {};
33934
33943
  const entities = {};
33935
33944
  const columnsOf = {};
33945
+ const fieldDefsOf = {};
33936
33946
  for (const [name, relPath] of Object.entries(entityMap)) {
33937
33947
  if (name.includes(".")) continue;
33938
33948
  const abs = path10.join(paths.root, relPath.replace(/^\.\//, ""));
@@ -33950,12 +33960,15 @@ function moduleValidate(args) {
33950
33960
  entities[name] = e;
33951
33961
  const fields = e.fields ?? {};
33952
33962
  const cols = new Set(Object.keys(fields));
33963
+ let traitFields = {};
33953
33964
  const traits2 = e.traits ?? [];
33954
33965
  try {
33955
- for (const c of Object.keys(expandTraits(traits2, name))) cols.add(c);
33966
+ traitFields = expandTraits(traits2, name);
33967
+ for (const c of Object.keys(traitFields)) cols.add(c);
33956
33968
  } catch {
33957
33969
  }
33958
33970
  columnsOf[name] = cols;
33971
+ fieldDefsOf[name] = { ...traitFields, ...fields };
33959
33972
  }
33960
33973
  const deps = new Set(Object.keys(manifest.dependencies ?? {}));
33961
33974
  const isKnownEntity = (code2) => {
@@ -34024,6 +34037,27 @@ function moduleValidate(args) {
34024
34037
  }
34025
34038
  }
34026
34039
  }
34040
+ const vcSeen = /* @__PURE__ */ new Set();
34041
+ for (const [vcode, v] of Object.entries(views)) {
34042
+ const sources = v.dataSources ?? [];
34043
+ if (sources.length === 0) continue;
34044
+ const viewType = v.viewType ?? "grid";
34045
+ if (COLUMN_AGNOSTIC_VIEW_TYPES.has(viewType)) continue;
34046
+ for (const s of sources) {
34047
+ const ent = s.entityCode;
34048
+ if (!ent) continue;
34049
+ const defs = fieldDefsOf[ent];
34050
+ if (!defs) continue;
34051
+ if (hasVisibleScalarColumn(defs)) continue;
34052
+ const key = `${vcode}\0${ent}`;
34053
+ if (vcSeen.has(key)) continue;
34054
+ vcSeen.add(key);
34055
+ err(
34056
+ `data_views \u2192 ${vcode}`,
34057
+ `view (${viewType}) renders entity '${ent}', which has no visible column \u2014 mark at least one of its fields visible with the 'V' flag (set columns / columnType 'S' don't count for a grid)`
34058
+ );
34059
+ }
34060
+ }
34027
34061
  const menus = readJsonOrDefault(paths.menus, {});
34028
34062
  const walk = (node, where) => {
34029
34063
  if (!node || typeof node !== "object") return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dforge-core/dforge-mcp",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "MCP server for dForge module authoring. Exposes scaffold/pack/install tools and schema resources so AI agents (Claude Code, Cursor, Zed) can create and ship dForge modules.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/iash44/dForge-core",
@@ -58,6 +58,28 @@ Lives in: `ui/data_views.json`
58
58
  }
59
59
  ```
60
60
 
61
+ ## Critical rule — the entity needs a visible column
62
+
63
+ A grid-style view can only render an entity that has at least one **visible scalar column** — a field whose `flags` include `V` and whose `columnType` is **not** a set (`S`). Column visibility is entity-driven (the field's flags), **not** view-driven: the `columns` array inside `dataSources[]` is layout-only (reorder/pin/width among already-visible fields) — it can't make a non-`V` field appear.
64
+
65
+ If none of an entity's fields are visible (or only its set/child-collection columns are), the view renders the runtime empty state *"No visible columns configured for this entity."* — a broken screen the user only hits when they open the menu item. `dforge_module_validate` and `dforge_module_pack` now **reject** this before install.
66
+
67
+ ```jsonc
68
+ // WRONG — grid over an entity whose fields are all hidden (no "V")
69
+ "fields": {
70
+ "code": { "fieldTypeCd": "text", "flags": "EM" }, // E=editable, M=… but no V
71
+ "lines": { "columnType": "S", "flags": "VEM" } // visible, but a SET — doesn't count for a grid
72
+ }
73
+ // RIGHT — at least one visible scalar field
74
+ "fields": {
75
+ "code": { "fieldTypeCd": "text", "flags": "VEM" } // V present, not a set → satisfies the grid
76
+ }
77
+ ```
78
+
79
+ This applies to every column-rendering view type (grid, list, kanban, calendar, gallery, tree-grid, master-detail, and the default). The column-agnostic types — `diagram`, `matrix`, `library` — draw from `viewConfig`/relationships instead, so they're **exempt** from this rule.
80
+
81
+ See [flags.md](flags.md) for the flag string, [column-types.md](column-types.md) for `columnType` (`R`/`S`/`F`).
82
+
61
83
  ## View types
62
84
 
63
85
  | `viewType` | Description | `viewConfig` | When to use |
@@ -243,3 +265,4 @@ Most views only have one source. Order is view-level and applies to the primary
243
265
  - Object-array order like `[{ column_cd: "...", direction: "asc" }]` — **wrong shape for data views**. Use `string[]` with leading `-` for descending.
244
266
  - `viewType` is **optional** — omitted or unknown values fall back to `grid` at runtime. Set it explicitly for any non-grid view (`kanban`, `calendar`, `matrix`, …); a `matrix` view also **requires** a `viewConfig` with `rowAxis`/`colAxis`/`cell`.
245
267
  - Inventing view types like `"spreadsheet"` or `"table"` — **wrong**. Use `grid`.
268
+ - A grid-style view over an entity with **no visible scalar column** (no field flagged `V`, or only set columns) — **rejected** at validate/pack. Mark at least one non-set field visible. See the [critical rule above](#critical-rule--the-entity-needs-a-visible-column). `diagram`/`matrix`/`library` are exempt.
@@ -72,6 +72,7 @@ For each entity:
72
72
  - [ ] Each source has `entityCode` and `columns`
73
73
  - [ ] `entityCode` points to an entity that exists
74
74
  - [ ] Column codes in `columns` all exist on the entity
75
+ - [ ] The rendered entity has **at least one visible scalar column** (a field with `V` in `flags`, `columnType` not `S`) — a grid/list/kanban/etc. view over an entity whose fields are all hidden (or only sets) is **rejected** at validate/pack and would render "No visible columns configured for this entity." `diagram`/`matrix`/`library` are exempt
75
76
  - [ ] If set, `viewType` is from the supported list (`grid`, `list`, `kanban`, `calendar`, `gallery`, `tree-grid`, `diagram`, `master-detail`, `library`, `matrix`)
76
77
  - [ ] A `matrix` view has a `viewConfig` with `rowAxis`, `colAxis`, and `cell` (cell `entity` matches the primary `dataSources` entity; `rowKey`/`colKey` are real cell columns)
77
78
  - [ ] Sort uses the view-def-root `order` key — a `string[]` like `["-created_date", "name"]` (leading `-` = descending), NOT `sort` / `[{column_cd, direction}]` (that object shape belongs to queries & reports, not data views)
@@ -172,6 +173,7 @@ If you see any of these, stop and investigate:
172
173
  - Menus with `children: [...]` (array, not dict)
173
174
  - Roles with `entityRights` (wrong key)
174
175
  - Data views with root-level `entityCode` (should be inside `dataSources`)
176
+ - A grid/list/kanban/etc. view over an entity with no field flagged `V` (or only set columns visible) — rejected at validate/pack
175
177
  - Formula columns without `baseDatatypeCd`
176
178
  - DSL actions with JavaScript/Python syntax
177
179
  - Seed data files without numbered prefixes